В чем разница между картой и применением в схеме?

Я пытаюсь изучить Схему, и мне трудно понять разницу между map и apply.

Как я понимаю, map применяет функцию к каждому элементу списка, а apply применяет что-то к аргументам процедуры.

Можно ли их использовать взаимозаменяемо?

Ответ 1

Они не то же самое! Их имена могут действительно помочь вспомнить, что делает.

map будет принимать в качестве аргумента одну процедуру и один или несколько списков. Процедура будет вызываться один раз для каждой позиции списков, используя в качестве аргумента список элементов в этой позиции:

(map - '(2 3 4))
; => (-2 -3 -4)

map, который называется (- 2), (- 3), (- 4) для создания списка.

(map + '( 1  2  3)
       '(10 20 30))
; => (11 22 33)

map называется (+ 1 10) (+ 2 20) (+ 3 30) для создания списка.

(map * '(2 2 -1)
       '(0 3  4)
       '(5 4  2))
; => (0 24 -8)

map называется (* 2 0 5) (* 2 3 4) (* -1 4 2) для создания списка.

map имеет это имя, потому что оно реализует "карту" (функцию) в наборе значений (в списках):

(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 будет принимать как минимум два аргумента, первая из которых является процедурой и последним списком. Он вызывается процедурой со следующими аргументами, в том числе внутри списка:

(apply + '(2 3 4))
; => 9

Это то же самое, что и (+ 2 3 4)

(apply display '("Hello, world!"))
; does not return a value, but prints "Hello, world!"

Это то же самое, что и (display "Hello, world!").

apply полезен, когда у вас есть аргументы в виде списка,

(define arguments '(10 50 100))
(apply + arguments)

Если вы попытаетесь переписать последнюю строку без использования apply, вы поймете, что вам нужно перебрать список, суммирующий каждый элемент...

apply также может использоваться с более чем двумя аргументами. Первый аргумент должен быть вызываемым объектом (процедура или продолжение). Последний должен быть списком. Остальные (между первым и последним) являются объектами любого типа. Поэтому вызов

(apply PROC a b c ... y z '(one two ... twenty))

совпадает с вызовом

(PROC a b c ... y z  one two ... twenty)

Вот конкретный пример:

(apply + 1 -2 3 '(10 20))
; => 32

Это то же самое, что и (+ 1 -2 3 10 20)

apply имеет это имя, потому что оно позволяет вам "применить" процедуру к нескольким аргументам.

Ответ 2

Нет, apply вызывает свой первый аргумент как процедуру, а все остальные - как свои аргументы, с последним - список - открыт, т.е. его содержимое "нарезано":

(apply f a b (list c d e)) == (f a b c d e)

например:.

(применить + 1 2 (список 3 4 5))
; Значение: 15

Это всего лишь один вызов; map действительно вызывает свой первый аргумент для каждого элемента-члена его второго аргумента.

Одно совместное использование map и apply - это знаменитый трюк transpose:

(применить список карт '((1 2 3) (10 20 30)))
    , Значение: ((1 10) (2 20) (3 30))

Ответ 3

Как указано в верхнем ответе, map

Процедура будет вызываться один раз для каждой позиции списков, используя в качестве аргументов список элементов в этой позиции

Напротив, apply

(apply function argument-list)

передать аргументы в argument-list чтобы function все сразу. Так что function вызывается только один раз.