Alex Staveley is a software professional passionate about software engineering and technical architecture. He blogs about architectural approaches, Java topics, web solutions and various technical bits and pieces. Alex is a DZone MVB and is not an employee of DZone and has posted 48 posts at DZone. You can read more from them at their website. View Full User Profile

Scala Function Literals

01.10.2013
| 3887 views |
  • submit to reddit

Functions are an important part of the Scala language. Scala Functions can have a parameter list and can also have a return type. So the first confusing thing is what's the difference between a function and a method? Well the difference is a method is just a type of function that belongs to a class, a trait or a singleton object.

So what's cool about functions in scala? Well you can define functions inside functions (which are called local functions) and you can also have anonymous functions which can be passed to and returned from other functions. This post is about those anonymous functions which are referred to as function literals.

As stated, one of the cool things about function literals is that you can pass them to other functions. For example, consider snippet below where we pass a function to a filter function for a List.

List(1,2,3,4,5).filter((x: Int)=> x > 3)

In this case, the function literal is (x: Int)=> x > 3 This will output: resX: List[Int] = List(4, 5).

=> called "right arrow" means convert the thing on the left to the thing on the right. The function literal in this example is just one simple statement (that's what they usually are), but it is possible for function literals to have multiple statements in a traditional function body surrounded by {}. For example, we could say:

List(1,2,3,4,5).filter((x: Int)=>{
  println("x="+ x);
  x > 3;})

which gives:

x=1
x=2
x=3
x=4
x=5
resX: List[Int] = List(4, 5)

Now one of the key features of Scala is to be able to get more done with less code. So with that mindset, let's see how we can shorten our original function literal. Firstly, we can remove the parameter type.

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

This technique is called target typing. The target use of the expression in this case, what is going to filter is allowed to determine the type of the x parameter.

We can further reduce the strain on our fingers by removing the parentheses. This is because the parentheses were only there to show what was been referred to as Int in the parameter typing. But now the typing is inferred the brackets are superflous and can be removed.

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

Shorten it even more? yeah sure... We can use the placeholder underscore syntax.

List(1,2,3,4,5).filter(_ > 3)

nderscores have different meanings in Scala depending on the context they are used. In this case, if you are old enough think back to the cheesey game show blankety blank.

This gameshow consisted of of sentences with blanks in them and the contestants had to make suggestions for what went into the blank. In this example, the filter function fills in the blanks with the values in the Lists it is being invoked on. So the filter function is the blankety blank contestant and the List (1,2,3,4,5) are what the filter function uses to fill the blank in.
So now our code is really neat and short. In Java to achieve the same, it would be:
Iterator<Integer> it = 
         new ArrayList<Integer>(Arrays.asList(1,2,3,4,5)).iterator();
while( it.hasNext() ) {
    Integer myInt = it.next();
    if(myInt > 3) it.remove();
}
So, here we can see where Scala make code shorted and development time quicker. Till the next time!
Published at DZone with permission of Alex Staveley, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Russel Winder replied on Thu, 2013/01/10 - 12:37pm

Your Java example is not compilable: the ArrayList object cannot be constructed like that. You probably meant to use Arrays.asList. Of course even with Arrays.asList(1, 2, 3, 4, 5) being used the example fails because Iterator.remove is an optional method and throws java.lang.UnsupportedOperationException.

Move forward to Java 8 and you get to write something like:

    Arrays.asList(1,2,3,4,5).filter(x -> x > 3)

So then Scala has zero win over Java.

Alex Staveley replied on Thu, 2013/01/10 - 5:03pm in response to: Russel Winder

@Russel Winder  Thanks.  You are right. I updated code. And good point about Java 8 as well. I don't think Java 8 will offer as much as Scala offers in this regards and will perhaps cover that interesting subject in another post.


Silvio Bierman replied on Thu, 2013/01/10 - 7:47pm in response to: Russel Winder

Java8 does get closures but they are a lot less powerfull than Scala closures, primarily because of the "effectively final" limitation on closed over local variables and the lack of support for special curly brace syntax for parameter lists. This prehibits classes that expose control-structure like methods and can be seamlessly interweaved with predefined control structures.

All in all Java8 closes Scala's "win" gap by something like 2%. Scala is not for everyone and if you think Java is better suited for you than that is fine. But you should not make the mistake thinking that Scala only has niche features over Java that are either academic or will soon (-er or later) come to a Java near you.


Russel Winder replied on Fri, 2013/01/11 - 5:40am in response to: Alex Staveley

I wonder if you meant to update the first line to:

    Iterator<Integer> it = Arrays.asList(1,2,3,4,5).iterator();

Russel Winder replied on Fri, 2013/01/11 - 5:48am in response to: Silvio Bierman

Java 8 is closing over references not values, so yes there is a requirement of final and that irritates.

Without an example, your point about curly brace parameter lists is a bit vacuous I'm afraid.

Scala is a lot better than Java in so many ways, but it is becoming the Algol68 of the JVM. Algol68 was by far the best programming language of the 1960s, but it was too complex and so had little take up. Scala risks this position by trying to bring Type Theory mentality to programming. Certainly not wrong, but not populist. Hence Kotlin and Ceylon. The 1960s gave us C instead of Algol68, I suspect the 2010s will give us a language other than Scala. It's not about quality, it's about what the average programmer is prepared to use.

Silvio Bierman replied on Fri, 2013/01/11 - 8:15am in response to: Russel Winder

I was lucky enough to program in Algol68 for a couple of years and (at that time) liked its concepts. But it was too complex both for programmers to use it and compilers/platforms to implement it and therefore died.

I agree Scala may be becoming a bit rich on the feature side. But if you can and want to manage the complexities it allows very elegant and straightforward expression of smart algorithms and constructs while in Java these tend to become obscured by the boiler plate.

Perhaps Scala is too complex for certain programmers to feel comfortable with it which may prevent it from becoming main stream. For me it is a language that allows for a much higher productivity at a much more challenging level.

Silvio Bierman replied on Fri, 2013/01/11 - 9:42am in response to: Russel Winder

About the curly brace parameter list syntax: together with thunks this supports creating classes that work and look exactly like control structures do. In fact it would be trivial to define a while-loop in Scala had it not been in the language already.

Java closures allow something like:

someObj.foreach((Int r) -> { /* ... */ })
otherObj.apply(() -> { /* ... */ })
lastObj.apply("foo",() -> { /* ... */ })

whereas in Scala this would be:

someObj.foreach { r => /* ... */ }
otherObj { /* ... */ }
lastObj("foo") { /* ... */ }

Since locals are fully readable and writable inside closures such constructs can be seamlessly interweaved with standard control structures.

Russel Winder replied on Fri, 2013/01/11 - 10:15am in response to: Silvio Bierman

Silvio,

OK, I get your point about curly braces and parameters, and yes Scala (and Groovy) are far better than Java on this. Java isn't going to change, so the campaign has to be to get Scala and Groovy to be the languages of choice on the JVM!


Silvio Bierman replied on Sat, 2013/01/12 - 12:11pm in response to: Russel Winder

Perhaps there can be multiple languages of choice.I do not think consensus on this is realistic.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.