DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Mastering Advanced Aggregations in Spark SQL
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Upgrading Spark Pipelines Code: A Comprehensive Guide

Trending

  • Implementing Explainable AI in CRM Using Stream Processing
  • How to Introduce a New API Quickly Using Micronaut
  • Useful System Table Queries in Relational Databases
  • Introducing Graph Concepts in Java With Eclipse JNoSQL, Part 2: Understanding Neo4j
  1. DZone
  2. Coding
  3. Languages
  4. 7 Uses of Underscore in Scala

7 Uses of Underscore in Scala

Underscores are overloaded in Scala: see 7 places where '_' means different things.

By 
Daniel Ciocirlan user avatar
Daniel Ciocirlan
·
Sep. 15, 20 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
8.0K Views

Join the DZone community and get the full member experience.

Join For Free

This article is for the curious Scala programmer who has seen underscores more times than they'd find comfortable. In this article I'll share almost all the places where you might see an underscore, so that you don't freak out when you see yet another one in a different context.

You can also read this article over at the Rock the JVM blog or watch the video version of it on YouTube or embedded below:


Other than that, I want to get straight to the point.

1. Ignoring

Underscores are commonly used when names or values are not important and/or unused. Here is a comprehensive list of ignored elements. First, variable names:

Scala
 




x


 
1
val _ = 5



Why you'd do that, I have no idea - the point of intentionally declaring a value or variable is to use it. But it's possible. Probably the most useless case of an underscore. However, the case when the compiler throws a value at use, but we don't use it, so we use an underscore. The most common use case is with lambdas whose arguments we don't need or use:

Scala
 




xxxxxxxxxx
1


 
1
val onlyFives = (1 to 10).map(_ => 5)



We could have said (1 to 10).map(x => 5) but we don't need x and the compiler would have issued an unused variable warning anyway, so we replace with an underscore.

Another scenario is when we use self-types as a type restriction, but you don't actually need to name the self-type:

Scala
 




xxxxxxxxxx
1


 
1
trait Singer
2
trait Actor { _: Singer =>
3
  // implementation
4
}



Finally, one of the less common places where underscores ignore stuff is generic types. For example:

Scala
 




xxxxxxxxxx
1


 
1
def processList(list: List[Option[_]]): Int =  list.length



Since we don't care what type those Options are, we type them with underscore. Underscores are also useful when we want to interoperate with Java libraries or generic types which were not explicitly typed (think pre-Java 5).

2. Wildcards

Underscores are also used to have the meaning of "everything" in certain contexts. One of them is importing everything in a package:

Scala
 




xxxxxxxxxx
1


 
1
import cats.implicits._



But by far the most frequent use case is in pattern matching, where the underscore means "match everything".

Scala
 




xxxxxxxxxx
1


 
1
meaningOfLife match {
2
  case _ => "I'm fine with anything"
3
}



3. Default Initializers

Particularly for variables, when we don't know what to initialize them with, let the JVM decide - zero for numerical values, false for Booleans, null for reference types:

Scala
 




xxxxxxxxxx
1


 
1
var myVariable: String = _



4. Lambda Sugars

You've probably seen this before. Let's say we want to multiply every element of a list by 5, we would do

Scala
 




xxxxxxxxxx
1


 
1
List(1,2,3,4).map(x => x * 5)



Except there's an even shorter version. We can wrote

Scala
 




xxxxxxxxxx
1


 
1
List(1,2,3,4).map(_ * 5)



which means the same thing: the compiler expands that to the slightly longer lambda version. The downside is that we can only use the underscore once in the function body - that's because each underscore represents a different argument of the lambda. For example, if I wrote

Scala
 




xxxxxxxxxx
1


 
1
val sumFunction: (Int, Int) => Int = _ + _



The _ + _ part is identical to (a, b) => a + b. Java programmers seeing this for the first time might find it too short, but it's really easy to get used to it.

5. Eta-expansion

Underscores are also used to turn methods into function values. We talk about the process in detail in another article (check the link above).

Scala
 




xxxxxxxxxx
1


 
1
def incrementer(x: Int) = x + 1
2
val incrementerFunction = incrementer _



The underscore is a signal to the compiler to create a new lambda with the implementation of x => incrementer(x).

6. Higher-Kinded Types

HKTs are generic types, whose type arguments are themselves generic. Libraries like Cats exploit this like crazy. Their structure is of the form

Scala
 




xxxxxxxxxx
1


 
1
class MyHigherKindedJewel[M[_]]



Where the type argument M is also generic. If I want to instantiate my HKT with a concrete generic type like List, I'll use the List type (not a List[String] or something else):

Scala
 




xxxxxxxxxx
1


 
1
val myJewel = new MyHigherKindedJewel[List]



7. Vararg methods

When we have a method taking a variable number of arguments, such as

Scala
 




xxxxxxxxxx
1


 
1
def makeSentence(words: String*) = ...



we might find ourselves we need to expand some collection of Strings as arguments to this method. We can't pass them manually at runtime, so we need to expand the collection automatically:

Scala
 




xxxxxxxxxx
1


 
1
val words = List("I", "love", "Scala")
2
val love = makeSentence(words: _*)



In this way, the elements of the list are exploded into the argument list to the method.

Conclusion

Scala overloaded the meaning of the underscore in many, many places - hopefully this article served as a good overview of where you might see it in real code.

Let me know if I've missed anything!

In the meantime, follow Rock the JVM on Twitter, LinkedIn and on the YouTube channel, and check out the Rock the JVM blog for more articles like this!

Scala (programming language)

Published at DZone with permission of Daniel Ciocirlan. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Mastering Advanced Aggregations in Spark SQL
  • Thermometer Continuation in Scala
  • Deploying a Scala Play Application to Heroku: A Step-by-Step Guide
  • Upgrading Spark Pipelines Code: A Comprehensive Guide

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!