2
votes

I'm having trouble understanding this example of matrix multiplication in Scheme from Rosetta Code:

(define multiplyMatrices
    (lambda (matrix1 matrix2)
        (map (lambda (row)
            (apply map (lambda column
                (apply + (map * row column)))
            matrix2))
        matrix1)))

where matrix1 and matrix2 are each a list of lists. My question is this: Why is column on the fourth line not wrapped in parentheses?

As I understand it, a lambda expression is of the form (lambda (<id1 id2 ...>) <exp>). From testing the code I know that it works and I know that wrapping column in parentheses does break the program, but I don't understand how the line is even syntactical and every explanation for lambda expressions I find online always describes them as I did above.

3

3 Answers

4
votes

The other answers are correct, but I want to point out that this isn't a special syntax, but rather a specific case of a more general syntax involving a rest parameter.

Consider the following functions:

(lambda () ...)
(lambda (first) ...)
(lambda (first second) ...)
(lambda (first second third) ...)

These functions take 0, 1, 2, and 3 arguments, respectively.

Now consider these functions:

(lambda rest ...)
(lambda (first . rest) ...)
(lambda (first second . rest) ...)
(lambda (first second third . rest) ...)

These functions take at least 0, 1, 2, and 3 arguments, respectively. Any further arguments are collected into a list and bound to rest, in these cases.

The first set of functions use proper lists as their lambda lists. The second set of functions use improper lists as their lambda lists. So what's the distinction between the two? A proper list is simply a list that has () as its final cdr, and an improper list is a list that has something else as its final cdr. It's that simple.

To give greater visual symmetry between the two sets of functions, the first set of functions could be written this way:

(lambda () ...)
(lambda (first . ()) ...)
(lambda (first second . ()) ...)
(lambda (first second third . ()) ...)

The list (first second third) is exactly the same as (first second third . ()). Once these expressions are read in, there is no way to distinguish between the two.

1
votes

This syntax puts all the parameters into a list:

(define test (lambda x x))

(test 1)
=> '(1)

(test 1 2 3)
=> '(1 2 3)

(test '(1 2 3))
=> '((1 2 3))

See also here: "If formals is a single variable (not in a list), e.g., z, it is bound to a list of the actual parameters."

0
votes

Notice the difference between the following two functions:

> (define f1 (lambda (x) x))
> (f1 "HELLO")
"HELLO"

and

> (define f2 (lambda y y))    
> (f2 "HELLO")
'("HELLO")

When a function is called in scheme, the arguments are bound to the function's parameter list. Since f1's argument list is (x) (with parenthesis around it,) the list is destructured, so x refers to the one argument in the list that was passed to it.

f2 does not include parenthesis around its argument list, y, so the argument list sent to it is not destructured, so the list is returned.