Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functions vs function pointers

Tags:

scala

Can someone explain the following to me:

scala> def squared(x: Int) = x * x
squared: (x: Int)Int
scala> val sq : (Int) => Int = squared
sq: Int => Int = <function1>
scala>  sq.getClass
res111: Class[_ <: Int => Int] = class $anonfun$1

I understand this so far, squared is a function while sq is a function pointer.

But then I do this:

scala> squared.getClass
<console>:13: error: missing arguments for method squared;
follow this method with `_' if you want to treat it as a partially applied function
   squared.getClass
   ^

Why can't I invoke getClass on squared ? After all, aren't functions 1st class objects ? Why do I need to do this for it to work ?

scala> squared(7).getClass
res113: Class[Int] = int

And I also get the same result for

scala> sq(5).getClass
res115: Class[Int] = int

Come to think of it, why do

scala>squared(5)

and

scala> sq(5)

produce the same result, even though one is a function, and the other a function pointer without needing to use a different syntax ? Something akin to *sq(5) may have been clearer, no ?

like image 250
femibyte Avatar asked May 21 '16 23:05

femibyte


1 Answers

The concept of a pointer isn't really relevant here, or in Scala (or the JVM) more generally. The difference between squared and sq is that squared is a method, and sq is a function.

Scala is (primarily) a language designed to be compiled to JVM bytecode. The JVM doesn't have first class functions, but it does have methods, which are associated either with an instance of a class (instance methods) or simply with the class itself (static methods). Methods in this sense are a fundamentally different kind of thing than objects to the JVM—they can't be passed as arguments to other methods, etc.

Because Scala is a functional language and functional languages are built on the idea of higher-order functions and first class functions more generally, the Scala language designers needed to be able to encode functions in a way that would work on the JVM. This is done via a Function1 class, and when you write something like this:

val sq: (Int) => Int = x => x * x

You are using Scala's syntactic sugar for creating instances of the Function1 class. These things are functions encoded as JVM objects, so they can be passed around and treated as first class things in the language.

Scala doesn't abandon the idea of methods, though. For reasons related in part to Scala's functional-OOP hybridity and in part to issues of performance, most Scala programs make extensive use of def definitions, which define methods, not "functions" in the sense of Function1. Scala provides a special conversion process (called eta expansion) by which methods can be treated as functions in many situations (including the right-hand side of your sq definition here).

If this all seems confusing, believe me, it is. You get used to it after a while, though (just get the idea of pointers out of your head as quickly as possible).

like image 119
Travis Brown Avatar answered Sep 20 '22 13:09

Travis Brown