3

I am preparing a presentation on Scala and functional programming and I am not sure about two notions.

I use a function introduced earlier during the presentation:

def safe_division(x: Int, y: Int) : Option[Double] = {
  if(y != 0)
    Some(x / y.toDouble)
  else
    None
}

I created a curried version (please correct me if I am wrong!):

val curried_safe_division: (Int) => (Int) => Option[Double] = {
  (x) => 
    (y) =>     
      if(y != 0)
        Some(x / y.toDouble)
      else
        None
}

So the first part where I am unsure is "is curried_safe_division called the curry?"

Then I introduce some code to show how currying functions allows a programmer to reuse functionalities efficiently:

val divideSix = curried_safe_division(6)
divideSix(3)
// prints: Some(2.0)
divideSix(6)
// prints: Some(1.0)

Am I right saying here that divideSix is a closure? Is curried_safe_division not a closure as well? I am using this definition:

https://softwareengineering.stackexchange.com/a/40708 a function that can be stored as a variable (referred to as a "first-class function"), that has a special ability to access other variables local to the scope it was created in.

I read multiple resources online, the wikipedia pages and this stackoverflow question: What is a 'Closure'? but it is still not super clear

Community
  • 1
  • 1
Daniel
  • 1,172
  • 14
  • 31
  • "is curried_safe_division called the curry?" What do you mean by "the curry" ? – pedrofurla Apr 03 '17 at 15:44
  • Now for closures, I'd read all https://en.wikipedia.org/wiki/Closure_(computer_programming). – pedrofurla Apr 03 '17 at 15:49
  • @pedrofurla I am not sure what the "curry" is supposed to mean, but my understanding is that it is supposed to be the "Base function" from where you spawn the other partially defined functions – Daniel Apr 03 '17 at 15:59
  • 1
    So, there is no such thing as "the curry". There are functions, there are first order values. There are curried functions or uncurried functions. Currying is named after mathematician Haskell Curry (https://en.wikipedia.org/wiki/Currying) is the act of transforming a n-uple function into n partially applied functions. Uncurrying is the opposite. – pedrofurla Apr 03 '17 at 16:03
  • 1
    Btw, the closure wikipedia page is a disappointment indeed. I consider it to the enclosing of bindings, I don't think they are same as first class functions. First class functions doesn't necessarily enclose bindings (e.g. `(x:Int) => 10`) – pedrofurla Apr 03 '17 at 16:10
  • From further research my understanding now is that the curry is `curried_safe_division(6)`, so I would say now that it is the definition of a partial function from a curried function, what do you think? – Daniel Apr 03 '17 at 16:10

2 Answers2

4

Value curried_safe_division is a function. This is different than safe_division, which is a method.

Furthermore, curried_safe_division is a curried function. When you take safe_division and turn it into a function, what you would normally get is (Int, Int) => Option[Double]. By changing it into Int => Int => Option[Double], you curried the function.

Function divideSix is not a closure. It's a simple function that takes an integer and returns an integer. What is a closure however is the internal function in curried_safe_division:

val curried_safe_division: (Int) => (Int) => Option[Double] =
    (x) => 
    // function below is a closure   
      (y) =>     
        if(y != 0)
          Some(x / y.toDouble)
        else
          None
    // end of closure
  }

You can clearly see that it depends on x but doesn't take it as its own parameter; instead, it used the x from the outer scope. It "closes over x". When you say val divideSix = curried_safe_division(6), you are taking that closure, supplying it with six as the value of parameter x, and assigning that to divideSix. But divideSix itself is not a closure. It doesn't close over anything. It just takes one integer parameter and divides it by six.

I've seen that some people tend to refer to the resulting function value (divideSix in our example) as "closure" because it's a function that resulted from partially applying some function (curried_safe_division in our example) and resulted in a function (marked between comments in our example) which was an actual closure. I'm fine with that. As longs as you understand the mechanics, it's easy to find your way around terminology.

slouc
  • 9,508
  • 3
  • 16
  • 41
  • I wish I could upvote you twice, the "closes over x" makes it easy to remember – Daniel Apr 03 '17 at 16:44
  • Glad I could help. If you haven't already, check [this](http://www.artima.com/pins1ed/functions-and-closures.html#8.7) out . – slouc Apr 03 '17 at 16:46
  • From the link you gave me: "The resulting function value, which will contain a reference to the captured more variable, is called a closure, therefore, because the function value is the end product of the act of closing the open term, (x: Int) => x + more." @slouc am I not "closing the open term" by doing curried_safe_division(6) therefore curried_safe_division(6) would be the closure? – Daniel Apr 03 '17 at 16:58
  • Yes, `addMore` is a closure. It closed over "more". Same way, if your code between the parts I marked with comments were a method, and you create a function value out of it, it would be a closure. However, `divideSix` is not a closure; it's a function value that was assigned the value of the closure with 6 applied to it. What's confusing you is that in your case you have a function of 2 params, create a closure and assign it to a function of 1 param, whereas in their example they have a 1-param function so applying 10 to it results in Int. Your `divideSix` is analogous to their 11. – slouc Apr 03 '17 at 17:14
  • 1
    So your `curried_safe_division` is a function from some integer x to a *closure that takes an y, closes over x and returns an integer*. The moment you apply the x part (in your case 6) to that closure, it returns a function that takes an integer and divides it by six. It's no longer a closure at that point; remember, the closure had two things it was operating on (one from params and one from the outside). But it's now just `Int => Int`. Your `divideSix` is exactly the same as `divideSix = x => x / 6` (without the fancy "safe" part). There's no closure there. I hope I'm making sense to you :) – slouc Apr 03 '17 at 17:22
  • Yes I was unsure if the Closure was the act of "closing" or what you just described in this comment which makes a lot of sense – Daniel Apr 03 '17 at 17:29
  • 1
    It's a function that uses stuff from outer scope and retains it even when the outer context is gone (e.g. function is executed). When you invoke `curried_safe_division` with 6 as parameter x, normally that parameter would be forgotten as soon as the function is done and removed from the stack. But function y => blabla closes over parameter x and "captures it". That function is a closure. When you supply 6 to it, it returns Int => Int which is technically not a closure, but some people may refer to it as a closure because it's a function that "closed over 6" and now only takes one Int. – slouc Apr 03 '17 at 18:02
  • 1
    When you understand the principles, terminology is easy to settle and agree upon, whether in a conversation, a presentation or a SO question :) I would never call the resulting function a closure; it's a result of supplying a value to a closure. But I can see why perhaps some people would (because, as I said, parameter 6 has been fixed or "closed over" and now just one parameter remains). – slouc Apr 03 '17 at 18:04
1

Currying is actually much simpler than your example. You don't need to introduce the method/function distinction at the same time.

// a curried safe_division method
def safe_division(x: Int)(y: Int) : Option[Double] =
  if (y != 0) Some(x / y.toDouble)
  else        None

From there you can introduce eta expansion, safe_division(2)_, which creates a function of type Int => Option[Double].

Community
  • 1
  • 1
jwvh
  • 50,871
  • 7
  • 38
  • 64
  • Thank you for the heads up, I think this syntax will probably be a lot clearer indeed. The function / method distinction is not something I am tackling in this presentation and honestly I would have to learn myself before – Daniel Apr 03 '17 at 17:23