Это abs возможно! Ты почти там. Вы просто столкнулись с двойными пространствами имен Common Lisp, и это может занять много времени. Надеюсь, я смогу сказать кое-что, чтобы сделать Common namespaces Common Lisp немного менее запутанным.
Ваш код почти правильный. Вы писали:
(defun foo (fn seq)
(mapcar #'fn seq))
Но что это за попытка? Хорошо, # ' является сокращением. Я расширю его для вас.
(defun foo (fn seq)
(mapcar (function fn) seq))
Так, символ # 'представляет собой сокращенную (символ функции). В Common Lisp - как вы, кажется, знаете - символы могут быть привязаны к функции и переменной; это два пространства имен, о которых так много говорит Лисперс: пространство имен функций и пространство имен переменных.
Теперь функция особой формы - это функция, привязанная к символу или, если хотите, значение, которое имеет символ в пространстве имен функций.
Теперь, на REPL, то, что вы написали, было бы очевидно, что вы хотите.
(mapcar #'car sequence)
карта Будет ли автомобиль функцию последовательности списков. И символ не имеет привязки к переменной, только привязка к функции, поэтому вам нужно использовать (функция ...) (или его стенограмма, # '), чтобы получить фактическую функцию.
Вашей Foo функция не работает, так как функция передается в качестве аргумента в настоящее время связана с символом в качестве переменной. Попробуйте следующее:
(let ((fn #'sqrt))
(mapcar #'fn '(4 9 16 25)))
Возможно, вы ожидали список квадратных квадратов этих чисел, но это не сработало. Это потому, что вы использовали let, чтобы привязать функцию квадратного корня к fn как переменную. Теперь попробуйте этот код:
(let ((fn #'sqrt))
(mapcar fn '(4 9 16 25)))
Восхитительный!Это связывает функцию квадратного корня с символом fn в качестве переменной.
Итак, давайте пересмотреть ваш Foo функции:
(defun foo (fn seq)
(mapcar fn seq))
Это будет работа, потому что п является переменной. Давайте проверим это, просто чтобы убедиться:
;; This will not work
(foo sqrt '(4 9 16 25))
;; This will work
(foo #'sqrt '(4 9 16 25))
Первый не работает, так как квадратный корень связан с SQRT в функциональном пространстве имен. Итак, во втором мы взяли функцию из символа и передали ее в foo, которая привязала ее к символу fn как переменную.
Хорошо, а что, если вы хотите связать функцию с символом в пространстве имен функций? Ну, для начала, defun делает это, надолго. Если вы хотите, чтобы он был временным, например, , позвоните, используйте flet. Flet, на мой взгляд, глупый, потому что он не работает точно так же, как пусть делает. Но я приведу пример, чтобы вы могли видеть.
(flet ((fn (x) (sqrt x)))
(mapcar fn '(4 9 16 25)))
не будет работать, потому что FLET не связывает функцию символа в переменном пространстве имен, но в функциональном пространстве имен.
(flet ((fn (x) (sqrt x)))
(mapcar #'fn '(4 9 16 25)))
Это будет делать то, что вы ожидаете, потому что FLET связаны эту функцию с символом п в функциональном пространстве имен. И, чтобы поездить на идею функции пространства имен дома:
(flet ((fn (x) (sqrt x)))
(fn 16))
Вернется 4.
+1 Ого, это довольно какой-то ответ. Очень подробно. :-) –