Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 19, 2022 11:10 am GMT

Eta Expansion in Scala

Eta Expansion

"Can you tell me about Eta Expansion?"

I froze. My pulse raised, temperature started rising, throat dried. I mumbled something about methods and functions and how Scala is OO. But that I didn't know, sorry! Please stop staring.

This was my reaction to a fairly innoccuous question in an interview for a Scala contract. The work never came off. The company apparently wanted to make an offer, alas internal politics interviened. But I can't help thinking it was my lack of a coherent answer to that question that led to my downfall!

Incidentally this is not an untypical reaction that I have in interview situations. Fortunately coding has nothing to do with the instant recall of textbook process descriptions and everything to do with solving problems, but there's not really a good way to test that in a 30 minute interview. So here we are.

This blog is my attempt to put down an actual answer to that question, and in doing so gain some extra insight into Scala and also FP in general.

So what is Eta Expansion?

One of the core tenets of FP is that functions are first-class citizens. If you can do something with a value, then you can do it with a function. Consider the definition of the method map on the List class

final def map[B](f: (A) => B): List[B]

We can see that map on a List[A] takes a function as an argument that will map elements from a type A to type B, and return a List[B]

So we can turn numbers into strings like so

List(1, 2, 3).map(n => n.toString)

So far, so functional. Our anonymous function satisfies the signature of map, which takes a function A => B (or Int => String in this case).

But what if we want to pass in a method. We know that scala is OO and so when we say

def f(n: Int): String = ...

then f is a method on the class we're working in, and not a function. We would define a function as

val f: (Int) => String = ...

And (in Scala 2.x) we can put a function in a List (first class, remember), but not a method

val fFunction: (Int) => String = ...def fMethod(n: Int): String = ...List(fFunction) // okList(fMethod)   // not ok

(This is not the case in Scala 3, which has improved Eta Expansion to allow this and also add in support of auto-expanding curried functions)

But hang on a sec, my Scala compiler will cheerfully allow

def f(n: Int): String = ....List(1, 2, 3).map(f)

And this is where Eta Expansion comes in. Phew! That's a long way to go without touching how it works.

It's worth noting that when we define a function like

val f: (Int) => String = ...

This is syntactic sugar and what's really under the hood is an object which implements the trait FunctionN, or specifically in this case

Function1[Int, String]

And it's associated apply method, which will apply the function to given argument(s).

So there we have it, Eta Expansion somewhat expanded upon. There's lots more to unpack, especially in Scala 3, so I may come back to this in the future.


Original Link: https://dev.to/stefintrim/eta-expansion-in-scala-3imp

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To