Решение, использующее build-list
, может начаться с создания списка из m
элементов:
(build-list m add1)
Здесь (build-list 2 add1)
-> (1 2)
Далее, один мог бы map
над списком с помощью build-list
снова, чтобы создать список списков. Нам понадобится процедура для применения к списку, например (1 2)
, которая будет составлять список из каждого элемента. Обратите внимание, что каждый элемент должен преобразовываться в список n+1
элементов (в случае list-of-numbers 2 3
у нас есть n == 3
):
(lambda (x) (build-list (add1 n) some-procedure))
Когда эта процедура применяется к элементу из (1 2)
мы должны получить список типа (1 1 1 1)
или (1 2 4 8)
. С этой целью some-procedure
будет вызываться на номер в диапазоне [0, n]
. Что нужно сделать some-procedure
, это взять его номер из первого списка (x
в приведенном выше выражении lambda
) и увеличить его до степени его числа из второго списка (число в диапазоне * 1027). *). Итак, теперь можно записать some-procedure
как:
(lambda (y) (expt x y))
Здесь x
берется из первого выражения lambda
, а y
берется из диапазона [0, n]
, предоставленного build-list
. Теперь нам нужно map
это составное lambda
выражение поверх первого списка, который мы построили:
(map (lambda (x) (build-list (add1 n) (lambda (y) (expt x y))))
(build-list m add1))
Если бы мы должны были проверить результат вышеприведенного отображения с входами 2 и 3 для m
и n
, соответственно, мы получили бы:
'((1 1 1 1) (1 2 4 8))
Осталось только умножить apply
на подсписки здесь; опять же, мы можем map
a lambda
выражение, которое использует apply
в каждом из подсписков, оставляя нам список результатов:
(define (list-of-numbers m n)
(map (lambda (s) (apply * s))
(map (lambda (x) (build-list (add1 n) (lambda (y) (expt x y))))
(build-list m add1))))
Вот пример вывода:
scratch.rkt> (list-of-numbers 2 3)
'(1 64)
scratch.rkt> (list-of-numbers 3 3)
'(1 64 729)
scratch.rkt> (list-of-numbers 3 2)
'(1 8 27)
Есть ли что-нибудь, что я могу использовать вместо применения?
Вместо использования apply
, можно снова использовать map
с примененным выражением lambda
foldl
вместе с умножением на подсписки:
(define (list-of-numbers-2 m n)
(map (lambda (x) (foldl * 1 x))
(map (lambda (x) (build-list (add1 n) (lambda (y) (expt x y))))
(build-list m add1))))
Работает так же, как и раньше:
scratch.rkt> (list-of-numbers-2 2 3)
'(1 64)
scratch.rkt> (list-of-numbers-2 3 3)
'(1 64 729)
scratch.rkt> (list-of-numbers-2 3 2)
'(1 8 27)