David542
David542

Reputation: 110123

The apply function in SICP/Scheme

I've asked a few questions here about Scheme/SICP, and quite frequently the answers involve using the apply procedure, which I haven't seen in SICP, and in the book's Index, it only lists it one time, and it turns out to be a footnote.

Some examples of usage are basically every answer to this question: Going from Curry-0, 1, 2, to ...n.

I am interested in how apply works, and I wonder if some examples are available. How could the apply procedure be re-written into another function, such as rewriting map like this?

#lang sicp

(define (map func sequence)
    (if (null? sequence) nil
        (cons (func (car sequence)) (map func (cdr sequence)))))

It seems maybe it just does a function call with the first argument? Something like:

(apply list '(1 2 3 4 5)) ; --> (list 1 2 3 4 5)
(apply + '(1 2 3))        ; --> (+ 1 2 3)

So maybe something similar to this in Python?

>>> args=[1,2,3]
>>> func='max'
>>> getattr(__builtins__, func)(*args)
3

Upvotes: 3

Views: 746

Answers (2)

Will Ness
Will Ness

Reputation: 71065

You asked to see how apply could be coded, not how it can be used.

It can be coded as

#lang sicp

; (define (appl f xs)    ; #lang racket
;   (eval 
;     (cons f (map (lambda (x) (list 'quote x)) xs))))

(define (appl f xs)      ; #lang r5rs, sicp
  (eval
    (cons f (map (lambda (x) (list 'quote x)) 
                 xs))
    (null-environment 5)))

Trying it out in Racket under #lang sicp:

> (display (appl list '(1 2 3 4 5)))
(1 2 3 4 5)

> (display (     list   1 2 3 4 5 ))
(1 2 3 4 5)

> (appl + (list (+ 1 2) 3))
6

> (     +       (+ 1 2) 3 )
6

> (display (appl map (cons list '((1 2 3)  (10 20 30)))))
((1 10) (2 20) (3 30))

> (display (     map       list  '(1 2 3) '(10 20 30)  ))
((1 10) (2 20) (3 30))

Here's the link to the docs about eval.

It requires an environment as the second argument, so we supply it with (null-environment 5) which just returns an empty environment, it looks like it. We don't actually need any environment here, as the evaluation of the arguments has already been done at that point.

Upvotes: 1

Barmar
Barmar

Reputation: 780851

apply is used when you want to call a function with a dynamic number of arguments.

Your map function only allows you to call functions that take exactly one argument. You can use apply to map functions with different numbers of arguments, using a variable number of lists.

(define (map func . sequences)
  (if (null? (car sequences))
      '()
      (cons (apply func (map car sequences))
            (apply map func (map cdr sequences)))))

(map + '(1 2 3) '(4 5 6))
;; Output: (5 7 9)

Upvotes: 2

Related Questions