Как работает funcall в Лиспе?
От: Worminator X Россия #StandWithPalestine 🖤🤍💚
Дата: 02.07.24 04:04
Оценка:
В Common Lisp такой код с функцией funcall:
(print (funcall
        (lambda (x y)
                (format NIL "~d + ~d = ~d" x y (+ x y))
        )
        2
        3
       )
)

И такой без нее:
(print (
        (lambda (x y)
                (format NIL "~d + ~d = ~d" x y (+ x y))
        )
        2
        3
       )
)

Работает совершенно аналогично — вызывает лямбда-выражение с парой параметров и выводит "2 + 3 = 5".

Однако, когда я пытаюсь написать простой пример с ООП:
(setq User-counter 0)
(defun User (name)
    (let
     (
      (id (setq User-counter (+ User-counter 1)))
     )
     (lambda (method)
             (cond
                 ((eq method 'getId) (lambda () id))
                 ((eq method 'getName) (lambda () name))
                 ((eq method 'data) (lambda () (list id name)))
                 ((eq method 'format) (lambda (f) (format NIL f id name)))
             )
     )
    )
)

То вызов методов с funcall работает:
(print (funcall (funcall (User "Worminator") 'format) "id: ~d, name: ~s"))

А вот без funcall выдает ошибку:
(print (((User "Worminator") 'format) "id: ~d, name: ~s"))

EVAL: ((USER "Worminator") 'FORMAT) is not a function name; try using a symbol instead


Почему? Можно ли как-то использовать второй вариант? Что означает not a function name — вообще не понял. И что делает funcall? Зачем нужна apply — ясно, она берет аргументы для вызова из списка, а вот с этой функцией непонятно. В другом диалекте Лиспа, Scheme, кстати, не нашел funcall (или там другое имя для нее).

Как-то запутанно все... В учебнике Святослава Лаврова, по которому когда-то учил Лисп, funcall совершенно не упоминалась, там говорилось, что выражение (f a1 ... aN) просто применяет значение f (которое должно быть лямбдой) к аругментам a1-aN и выдает результат. И вообще весь Лисп описывался 10 базовыми функциями: car, cdr, cons, atom, eq, cond, lambda, defun, setq и quote.
— Нет в мире справедливости, — простонал Билл, когда цепкие пальцы Смертвича впились в его плечо.
— Конечно, нет, — согласился Смертвич. — А ты как думал?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.