Запустите функцию, имя которой находится в списке - PullRequest
0 голосов
/ 25 марта 2019

Я все еще изучаю ракетку.

Мне нужно вызвать неизвестную функцию.Функция и ее параметры находятся в следующем списке:

(define l1 '((function-name parameter1)
(function-name parameter3)))

Чтобы запустить эту функцию, я делаю:

(first (car l1)) (second (car l1)) another-parameter

Но я получаю ошибку:

 application: not a procedure;
 expected a procedure that can be applied to arguments
  given: 'function-name
  arguments...:

Как мне запустить этот function-name?

ОБНОВЛЕНИЕ:

Я попытался ответить Оскару:

(eval (first (car l1)) (second (car l1)) another-parameter)

И я получил ошибку:

 eval: arity mismatch;
 the expected number of arguments does not match the given number
  given: 3
  arguments...:

Я также попытался:

(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(eval (first (car l1)) (second (car l1)) another-parameter ns)

И я получаю ту же ошибку:

 eval: arity mismatch;
 the expected number of arguments does not match the given number
  given: 4
  arguments...:

Затем я попробовал это:

(eval (list (first (car l1)) (second (car l1)) another-parameter))

И я получаю ошибку:

function-name: unbound identifier;
 also, no #%app syntax transformer is bound in: function-name

Наконец, у меня естьпопробовал:

(eval (list (first (car l1)) (second (car l1)) another-parameter) ns)

и я получаю внутреннюю ошибку от function-name.Но эта функция работает отлично.

function-name может быть как минимум тремя (или более) функциями, поэтому я не помещал ее здесь раньше.Все они будут иметь два списка в качестве параметров, и они будут возвращать #t или # f.

Один из затем, затем один тест, который сейчас проверяется:

(define match (lambda (list1 list2) ...))

Очевидно, list1 и list2 являются списками.

ОБНОВЛЕНИЕ 2: Я попробовал Минимальный, Полный и проверяемый пример Оскара, и он работает.Но я изменил, чтобы использовать на моем на работе, и это не работает.Посмотрите:

(define function-name
  (lambda (list1 list2)
    (append list1 list2)))

(define parameter1 '(1 2))
(define parameter3 '(3 4))
(define another-parameter '(5 6))

(define l1 '((function-name parameter1)
             (function-name parameter3)))

(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))

(define another-function
  (lambda (l1 the-parameter)
    (cond
      [(eval (list (first (car l1)) (second (car l1)) 'the-parameter) ns) l1])
  )
)

(another-function l1 another-parameter)

Я создал another-function, и он не работает с параметром 'the-parameter.Он жалуется, говоря:

the-parameter: undefined;
 cannot reference an identifier before its definition

Так что проблема в том, что я использую параметр функции в качестве параметра для функции eval.

Ответы [ 2 ]

4 голосов
/ 26 марта 2019

Пожалуйста, оцените процедуру следующим образом:

(define l1 `((,sin ,(+ 1 2))
             (,+ 1 2 3)))

(sin (+ 1 2))                 ; ==> 0.14..
((caar l1) (cadar l1))        ; ==> 0.14..
(apply (caar l1) (cdar l1))   ; ==> 0.14..

(+ 1 2 3)                     ; ==> 6
(apply (caadr l1) (cdadr l1)) ; ==> 6

Почему это работает? Что ж. Вы попытались назвать название процедуры. Оценивая имя процедуры, вы получаете фактический объект процедуры. Вы действительно можете оценить процедуру в REPL и посмотреть, что вы получите:

+  ; ==> #<procedure:+>
l1 ; ==> ((#<procedure:sin> 3) (#<procedure:+> 1 2 3))

Если бы l1 было определено как '((sin (+ 1 2)) (+ 1 2 3)), то при оценке он вернул бы ((sin (+ 1 2)) (+ 1 2 3)), поэтому есть большая разница.

И конечно. Использование квазицитаты / unquote - это просто причудливый способ написать это:

(define l1 (list (list sin (+ 1 2))
                 (list + '1 '2 '3)))
2 голосов
/ 25 марта 2019

Вы можете использовать eval и квазицитирование для этого, оно работает для вашего ввода. Сделайте обратите внимание, что именно так вы должны публиковать свои вопросы, это Минимальный, полный и проверяемый пример , который любой может скопировать и запустить, не догадываясь, о чем вы думали:

(define function-name
  (lambda (list1 list2)
    (append list1 list2)))

(define parameter1 '(1 2))
(define parameter3 '(3 4))
(define another-parameter '(5 6))

(define l1 '((function-name parameter1)
             (function-name parameter3)))

(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))

(define another-function
  (lambda (l1 the-parameter)
    (cond
      [(eval `(,(first (car l1)) ,(second (car l1)) ',the-parameter) ns)
       l1])))

(another-function l1 another-parameter)
=> '((function-name parameter1) (function-name parameter3))
...