Reputation: 110123
In trying to 'reduce' the apply
function, is the correct a proper understanding?
For example for (apply func args)
(apply
and matching )
.func
as the first element of the args
, moving the outer quote in one level if necessary.Here would be an application:
; (add-pairs '((1 2)(3 4))) --> (3 7)
(define (add-pairs ps)
(if (null? ps) nil
(cons (+ (car (car ps)) (cadr (car ps))) (add-pairs (cdr ps)))))
(apply add-pairs '(((1 2) (3 4))))
xxxxxxx x
; Remove the "(apply " and matching ")"
add-pairs '(((1 2) (3 4)))
------------^
; Insert the function into the args, moving the quote in one level if required.
(add-pairs '((1 2) (3 4)))
Is the above an accurate way to show how the apply
gets added in, or am I missing anything?
Upvotes: 1
Views: 211
Reputation: 438
It seems like you know Python. I personally think that apply
in Scheme and star operator *
in Python are quite similar.
Imagine you want to zip several lists, which were themselves packed inside a list. Trying to call
list_of_lists = [[1, 2],[3, 4]]
zip(list_of_lists)
would not give you [(1, 3), (2, 4)]
, so you write
zip(*list_of_lists)
# here it's the same as
zip(list_of_lists[0], list_of_lists[1])
using the iterable unpacking operator *
. A (pretty full) alternative to this in Racket/Scheme is using an apply function:
(define list-of-lists '((1 2) (3 4)))
(apply zip list-of-lists)
;; here it's the same as
(zip (car list-of-lists) (cadr list-of-lists))
(If, of course, zip in Scheme was defined the same way as in Python, requiring arbitrary number of arguments)
But you can definitely see the difference here, the syntactic one. In Python version of apply
we are 'applying' this *
to arguments and then pass what was 'returned' to calling function (zip
). Scheme acts like a functional language and reverses everything inside out (at least that's how I see it): you're 'applying' apply
to a function and its arguments and then it handles everything itself.
The other significant difference is that, of course, apply
in Scheme is a normal function, so we can write e.g.
(define (apply-func-to-sum-and-args func args)
(func + args))
(apply-func-to-sum-and-args apply (list 1 2 3))
;; returns 6
Though I believe (correct me if I'm wrong) that this function cannot be written in pure Scheme and it calls some weird C function under the hood.
Upvotes: 1
Reputation: 71065
The example is unfortunate, as it only leaves one argument after "the opening of the parentheses". But yes, that's how I also think about it. The simpler the better, :) as long as it is correct.
Except that of course the values in the list are first evaluated, so it's not a simply-syntactical process. But as a basic example,
(apply + (list 1 2 3))
==
( + 1 2 3 )
i.e. the parens around the arguments is what goes away.
For a non-trivial example, see
Upvotes: 2