1

I have the following procedure to add three numbers:

(define add-3 (lambda (x y z) (+ x y z)))
(add-3 100 200 300)
; 600

When converting it to a curried function, it reduces to something like the following,

(apply (lambda args1
         (apply add-3 (cons 100 args1)))
       '(200 300))
; 600

My question is how does the above further reduce? For example, if I substitute in the list args1=(200 300) I get the following:

(apply (lambda args1
         (apply add-3 (cons 100 args1)))
       '(200 300))

(apply
 (apply add-3 (cons 100 '(200 300))))

But that gives me ar arity mismatch, so I must be doing something wrong in the reduction/substitution. What would be the proper way to do that?

I suppose a more direct way to ask this is how does the following simplification occur?

(apply (lambda args (apply add-3 args)) '(100 200 300))
; 600

; ... how do we get here?
(apply add-3 '(100 200 300))
; 600

For context: https://stackoverflow.com/a/68038585/651174.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
David542
  • 104,438
  • 178
  • 489
  • 842
  • The reduction is exactly like in the linked answer - from `(apply (lambda args1 (apply add-3 ...))` to `(apply add-3 (cons 100 '(200 300)))`. It looks like you went from `(apply fn ls)` to `(apply (fn ls))`, but that's incorrect. – molbdnilo Jun 21 '21 at 08:28
  • @molbdnilo thanks, does my answer here make any sense? I spent some time going through it... https://stackoverflow.com/a/68075322/651174 – David542 Jun 21 '21 at 22:11

2 Answers2

2

Starting again with this as the baseline:

(define add-3 (lambda (x y z) (+ x y z)))
(add-3 100 200 300)
; 600

And then we start with the function we want to reduce:

(apply (lambda args1
         (apply add-3 (cons 100 args1)))
       '(200 300))

How do we reduce this? The apply works as follows:

(apply + '(1 2))
(      +   1 2 )
3

That is, it takes a procedure and applies that to the arguments from the list supplied. So, to start off, we can take the 'inner lambda function' and apply that:

((lambda args1 (apply add-3 (cons 100 args1))) 200 300)

This isn't much of a simplification, but we can set args1='(200 300) to get rid of that component, which gives us:

(let ((args1 '(200 300)))
  (apply add-3 (cons 100 args1)))

We can go a few routes here, but to simplify things, let's do the (cons 100 args1) call, which simplifies to (100 200 300):

(let ((args1 '(200 300)))
  (apply add-3 '(100 200 300)))

Notice we no longer have args1 in the body, so we can remove the let:

(apply add-3 '(100 200 300))

And now we can use the apply definition of (apply func args) -> (func arg1 arg2 ...) to get:

(add-3 100 200 300)

Which is what we wanted. Notice that in our reduction we were able to take advantage of the following:

(apply (lambda args BODY) LIST)

And transform it into:

(let ((args LIST))
    BODY)

The simplest example here would be something like:

(apply (lambda args (length args)) '(1 2 3 4))
;  {
;    BODY = (length args)
;    LIST = '(1 2 3 4)
;  }
;  ==>
(let ((args '(1 2 3 4)))
    (length args))

For more information, this answer provides additional context: https://stackoverflow.com/a/68048663/651174.

Spectric
  • 30,714
  • 6
  • 20
  • 43
David542
  • 104,438
  • 178
  • 489
  • 842
  • 1
    good, yes. the only thing is, I'd rename `FUNC` to `BODY`. because it's not a function, it;s a function's body. – Will Ness Jun 22 '21 at 13:15
-1

You're asking how to deconstruct a list?

(define l1 (list 100 200 300))
(apply (lambda args (apply add-3 args)) l1)

(define l2 (cons 100 (cons 200 (cons 300 '()))))
(apply (lambda args (apply add-3 args)) l2)

https://en.wikibooks.org/wiki/Scheme_Programming/List_Operations

Doyousketch2
  • 2,060
  • 1
  • 11
  • 11