J'essaie d'apprendre Scheme et j'ai du mal à comprendre la différence entre map
et apply
.
Si je comprends bien, map
applique la fonction à chaque élément de la liste, et apply
applique quelque chose aux arguments d'une procédure.
Peuvent-ils être utilisés de manière interchangeable?
Ils ne sont pas les mêmes! Leurs noms peuvent en fait aider à se rappeler qui fait quoi.
map
prendra comme argument une procédure et une ou plusieurs listes. La procédure sera appelée une fois pour chaque position des listes, en utilisant comme arguments la liste des éléments à cette position:
(map - '(2 3 4))
; => (-2 -3 -4)
map
appelé (- 2)
, (- 3)
, (- 4)
pour construire la liste.
(map + '( 1 2 3)
'(10 20 30))
; => (11 22 33)
map
appelé (+ 1 10)
(+ 2 20)
(+ 3 30)
pour construire la liste.
(map * '(2 2 -1)
'(0 3 4)
'(5 4 2))
; => (0 24 -8)
map
appelé (* 2 0 5)
(* 2 3 4)
(* -1 4 2)
pour construire la liste.
map
porte ce nom car il implémente une "map" (fonction) sur un ensemble de valeurs (dans les listes):
(map - '(2 3 4))
arguments mapping "-" result
2 === (- 2) ===> -2
3 === (- 3) ===> -3
4 === (- 4) ===> -4
(map + '( 1 2 3)
'(10 20 30))
arguments mapping "+" result
1 10 === (+ 1 10) ===> 11
2 20 === (+ 2 20) ===> 22
3 30 === (+ 3 30) ===> 33
apply
prendra au moins deux arguments, le premier étant une procédure et le dernier une liste. Il appellera la procédure avec les arguments suivants, y compris ceux de la liste:
(apply + '(2 3 4))
; => 9
C'est la même chose que (+ 2 3 4)
(apply display '("Hello, world!"))
; does not return a value, but prints "Hello, world!"
C'est la même chose que (display "Hello, world!")
.
apply
est utile lorsque vous avez des arguments sous forme de liste,
(define arguments '(10 50 100))
(apply + arguments)
Si vous essayez de réécrire la dernière ligne sans utiliser apply
, vous vous rendrez compte que vous devez parcourir la liste en sommant chaque élément ...
apply
peut également être utilisé avec plus de ces deux arguments. Le premier argument doit être un objet appelable (une procédure ou une continuation). Le dernier doit être une liste. Les autres (entre le premier et le dernier) sont des objets de tout type. Donc, appeler
(apply PROC a b c ... y z '(one two ... twenty))
équivaut à appeler
(PROC a b c ... y z one two ... twenty)
Voici un exemple concret:
(apply + 1 -2 3 '(10 20))
; => 32
C'est la même chose que (+ 1 -2 3 10 20)
apply
porte ce nom car il vous permet "d'appliquer" une procédure à plusieurs arguments.
Non, apply
appelle son premier argument comme une procédure, avec tous les autres comme arguments, avec le dernier - liste - ouvert, c'est-à-dire son contenu "découpé en tranches":
(apply f a b (list c d e)) == (f a b c d e)
Par exemple.:
(appliquer + 1 2 (liste 3 4 5))
; Valeur: 15
Ce n'est qu'un appel; map
appelle en effet son premier argument pour chaque élément membre de son deuxième argument.
Une utilisation combinée de map
et apply
est la fameuse astuce transpose
:
(appliquer la liste des cartes '((1 2 3) (10 20 30)))
; Valeur: ((1 10) (2 20) (3 30))
Comme l'a suggéré la première réponse, map
La procédure sera appelée une fois pour chaque position des listes, en utilisant comme arguments la liste des éléments à cette position
En revanche, apply
(apply function argument-list)
passer des arguments dans argument-list
à function
à la fois. Donc function
n'est appelé qu'une seule fois.