dotnetN00b
dotnetN00b

Reputation: 5131

Why is the anonymous function and function in Scala constructed like this?

In SICP 1.3.2, there is this function

(define (f x y)
  ((lambda (a b)
     (+ (* x (square a))
        (* y b)
        (* a b)))
   (+ 1 (* x y))
   (- 1 y)))

Now after 30 minutes chasing after errors, I found this page and it provided this function

  def f_lambda(x: Int, y: Int) =
    (((a: Int, b: Int) => ((x * square(a)) + (y * b) + (a * b)))
      (1 + (x * y), 1 - y)) 

I do not understand why it is surrounded (like a fort) with parentheses.

Edit: Sorry, my real issue is I don't understand why this function is constructed the way it is. In other words, why are all the parentheses needed in the first place. This looks completely "foreign" compared to the Scala code I've seen so far.

Upvotes: 1

Views: 201

Answers (2)

chrisloy
chrisloy

Reputation: 179

I don't understand either. You can strip a few off:

def f_lambda(x: Int, y: Int) =
  ((a: Int, b: Int) => (x * square(a)) + (y * b) + (a * b)) (1 + (x * y), 1 - y)

Or if you want to rely on the fact that multiplication takes precedence over addition:

def f_lambda(x: Int, y: Int) =
  ((a: Int, b: Int) => x * square(a) + y * b + a * b) (1 + x * y, 1 - y)

Personally I think the first is a bit more readable.

Edit:

Breaking this down a bit, this is declaring an anonymous function which takes two Ints as arguments, styled "a" and "b":

(a: Int, b: Int) => x*square(a) + y*b + a*b

Note this is still using x and y (being the arguments to the outer method). It is then applying this inner function using a = 1 + xy and b = 1 - y.

So substituting, I believe you end up with:

x*square(1 + x*y) + y*(1 - y) + (1 + x*y)*(1 -y)

Why not write it this way in the first place (or using an inner function as Shadowland has)? Well, it's a matter of style and context I guess, so I can't really guess the author's initial intention. The point is that Scala is flexible enough to allow lots of different styles by which you can express the same thing.

Upvotes: 2

Shadowlands
Shadowlands

Reputation: 15074

First, it is certainly possible to eliminate a few of the pairs of parentheses in the particular example you give above, although in the case of the outermost pair, this does require putting part or all of the last line on the end of the preceding line:

def f_lambda2(x: Int, y: Int) =
   ((a: Int, b: Int) => (x * square(a) + y * b + a * b))(1 + x * y, 1 - y)

That said, you may - as with any code - choose to put in extra parentheses to clarify things (eg. around multiplications to make precedence clearer).

Second, there are alternate ways to write such a function which can make what is going on clearer for any reader. This does mean less brevity of code, but I think the clarity gained can definitely be worth it:

def f_lambda3(x: Int, y: Int) = {
  def inner(a: Int, b: Int) = (x * square(a)) + (y * b) + (a * b)
  inner(1 + x * y, 1 - y)
}

Overall, just because the most efficient, compact representation of a coding concept might arguably involve bracket madness (yay, Lisp!), this doesn't mean this has to be carried over to Scala, which has many much more accessible constructs for writing exressive code.

Upvotes: 2

Related Questions