23872

Scala Syntax Help Currying

I came across some code in scala in a similar form like this:

def test1(f : Int => Int)(x : Int) = x + f(x) def test2(f : Int => Int)(x : Int) = f(x) test2(test1(x => 2*x))(2)

I'm confused, so function test1 takes a function and a Int as parameters, and returns a function, right? Then how can test1(x => 2*x) be valid and returns a function to test2? Apparently it takes 2 asthe integer parameter, but why? How does the statement test2(test1(x => 2*x))(2) expand?

Thanks in advance.

Answer1:

This:

test2(test1(x => 2*x))(2)

expands to this:

test2(y => test1(x => 2*x)(y))(2)

Scala's methods with multiple argument lists can act a lot like curried functions in other languages, but in fact are implemented as methods that requires all of their parameters, and this does show through in the syntax. For example if you put this into the REPL:

test1(x => 2*x)

It will complain about missing arguments. What this syntax does allow is "eta-expansion", where a method is converted into a function. If you write:

val func: Int => Int = test1(x => 2*x) _

You can get a function that represents test1 partially applied. Scala will do eta-expansion automatically if the context requires it, which is what happens with test2(test1(x => 2*x))(2). Note that test1 itself never returns a function, but the compiler will build a function based on it when required.

However, if you define test1 like:

def test1(f : Int => Int) = (x : Int) => x + f(x)

Then the compiler will accept test1(x => 2*x) without the _. Also, in the underlying implementation there will be only one class implementing the closure retured by test1, whereas with the original definition every partial application of test1 causes a new class to be created for it. On the other hand, it is less efficient when given both parameters, because the closure is always created.

Answer2:

function test1 takes a function and a Int as parameters, and returns a function, right?

No, it only takes a function as its argument and returns a function. The returned function then takes an int as the argument and returns an int.

Then how can test1(x => 2*x) be valid and returns a function to test2?

I hope that's clear now.

How does the statement test2(test1(x => 2*x))(2) expand?

test1 is called with x => 2*x as the argument and returns a function. Then test2 is called with that returned function as its argument and returns another function. Then that other function is called with 2 as its argument.

Recommend

  • Insane Chrome issue…Chrome renders twisties?
  • Resize of Iframe dynamically depending on the content of the Iframe of the Iframe's src URL
  • Using vba to copy the contents of a word document into another word document
  • Dynamically Impersonate a remote user - c# and asp.net
  • Conditionally encapsulate rules
  • add new field to form with rvest
  • Change Divider Color Android DatePicker Dialog
  • Google Bigquery Command Line Return Limit
  • object play not found in scala application
  • Checkpointing In ALS Spark Scala
  • Is there a way to link a linux's thread TID and a pthread_t “thread ID”
  • Scala: Function returning an unknown type
  • Regex for Specific Tag
  • Spark (Scala) Writing (and reading) to local file system from driver
  • How can we prepend rows to a react native list-view?
  • Retrieving specified columns from a list of csv files to create a data data frame in R
  • How to override value that appears in a dropdown in the rails_admin gem
  • CSS bleed-through with cfinput type=“datefield”
  • Possible to get mouse events fired when cursor is outside page?
  • Is it possible to open regedit and navigate to straight to a specific key using process.start?
  • What's the purpose of QString?
  • Jackson Parser: ignore deserializing for type mismatch
  • d3 v4 drag and drop with TypeScript
  • Why does access(2) check for real and not effective UID?
  • Repeat a vertical line on every page in Report Builder / SSRS
  • PHPUnit_Framework_TestCase class is not available. Fix… - Makegood , Eclipse
  • Illegal mix of collations for operation for date/time comparison
  • Android screen density dpi vs ppi
  • swift auto completion not working in Xcode6-Beta
  • Bug in WPF DataGrid
  • Can Jackson SerializationFeature be overridden per field or class?
  • Finding past revisions of files in StarTeam w/ .NET SDK / C#
  • R: gsub and capture
  • Cannot Parse HTML Data Using Android / JSOUP
  • Comma separated Values
  • SQL merge duplicate rows and join values that are different
  • Benchmarking RAM performance - UWP and C#
  • C# - Getting references of reference
  • java string with new operator and a literal
  • Net Present Value in Excel for Grouped Recurring CF