Понимание шаблона карты для n-арных операций над n списками в Scheme

Я это понимаю (map f '(a b c d)) является '(f(a) f(b) f(c) f(d)) применяя функцию f каждому элементу в списке. Но мне трудно понять следующее:

(map * '(1 2) '(1 2))

Выход должен быть '(1 4), Как так?

Может кто-нибудь объяснить, как map шаблон работает в Scheme, когда мы применяем n-ную операцию к n спискам?

3 ответа

map берет i-ые элементы предоставленных списков, передает их в n-арную операцию и сохраняет результат в i-й позиции возвращенного списка.

Так, (map f '(a b c d) '(A B C D)) будет равен ((f a A) (f b B) (f c C) (f d D)), Более двух списков обрабатываются аналогично.

Чтобы действительно понять что-то лучше всего реализовать это самим.

Карта для функций с 1 аргументом проста, это

(define (map1 f1  xs)
  (cons (f1   (car xs))
        (map1 f1
              (cdr xs))))

(добавление базового варианта оставлено в качестве упражнения). Аналогично для двоих,

(define (map2 f2  xs  ys)
  (cons (f2   (car xs)  (car ys))
        (map2 f2
              (cdr xs)  (cdr ys))))

и три,

(define (map3 f3  xs  ys  zs)
  (cons (f3   (car xs)  (car ys)  (car zs))
        (map3 f3
              (cdr xs)  (cdr ys)  (cdr zs))))

Мы можем использовать один и тот же шаблон для любой n- аргументной функции, которая должна быть отображена на любые n списков, чтобы получить n аргументов из:

 map_n:
        xs:  x1  x2  x3  x4  x5 ...
        ys:  y1  y2  y3  y4  y5 ...
        zs:  z1  z2  z3  z4  z5 ...
        ...........................
              ↓   ↓   ↓   ↓   ↓
              f   f   f   f   f
              =   =   =   =   =
    results: r1  r2  r3  r4  r5 ...

'(f (a) f (b) f (c) f (d)) есть и может быть только (f (a) f (b) f (c) f (d)) после оценки.

map для одного списка аргумент может быть определен так:

(define (map1 fn lst)
  (if (null? lst)
      '()
      (cons (fn (car lst))
            (map1 fn (cdr lst)))))

а также (map add1 '(1 2 3)) можно заменить на

(cons (add1 '1) 
      (cons (add1 '2)
            (cons (add1 '3)
                  '())))
; ==> (2 . (3 . (4 . ())))
; ==> (2 3 4)

Сейчас map принимает по крайней мере один аргумент списка и ожидает, что переданная функция принимает один или каждый. таким образом (map * '(1 2) '(1 2)) такой же как:

(cons (* '1 '1)
      (cons (* '2 '2)
            '()))
; ==> (1 . (4 . ())) 
; ==> (1 4)

Я не совсем уверен, если у вас возникли проблемы с пониманием map или как составляются списки. Если это последнее, вы должны сделать это главным приоритетом, чтобы иметь возможность видеть (1 2 (3 4)) и понимаю, что 3 это caaddr так как пары (1 . (2 . ((3 . (4 . ())) . ()))), Прочтите это справа налево, глядя на пары, и вы увидите это. Если это map тогда вам нужно их реализовать. Это лучший способ узнать это.

Другие вопросы по тегам