Как применить первый элемент списка к остальной части списка? - PullRequest
1 голос
/ 06 мая 2020

Почему:

(apply (car (list 'xor)) '(#t #t))

заявка: не процедура; ожидается процедура, которая может быть применена к заданным аргументам: 'xor

(apply (car (list (list 'xor))) '(#t #t))

application: not a procedure; ожидается процедура, которая может быть применена к заданным аргументам: '(xor)

(apply (car '(xor #t #t)) (cdr '(xor #t #t)))

application: not a procedure; ожидается процедура, которая может быть применена к заданным аргументам: 'xor

Как применить первый элемент списка к остальной части списка?

1 Ответ

1 голос
/ 06 мая 2020

В вашей программе 'xor - это символ, а не процедура. В приведенной ниже программе xor относится к реальной процедуре, а не является символом -

(apply (car (list xor)) (list #t #t))
; #f

(apply (car (list xor)) (list #t #f))
; #t

или просто -

(apply xor (list #t #f))
; #t

Когда вы пишете '(xor #t #t), xor заключен в кавычки и превращен в символ -

(car '(xor #t #t))
; 'xor

Вы можете использовать квази-цитирование `(...), но чаще всего отменяете ,... все, что не хотите преобразовывать в символ -

(apply (car `(,xor #t #t)) (cdr `(,xor #t #t)))
; #f

(apply (car `(,xor #t #f)) (cdr `(,xor #t #f)))
; #t

Предположительно s-выражения будут построены где-нибудь еще -

(define sexpr1 (list xor #t #t))
(define sexpr2 (list xor #t #f))

(apply (car sexpr1) (cdr sexpr1)) ;#f
(apply (car sexpr2) (cdr sexpr2)) ;#t

Если s-выражения содержат данные в чисто кавычках, вы можете eval выражение, используя пространство имен .

Мы добавляем racket/base, чтобы разрешить применение процедуры. Процедура в вашей программе, xor, включена в racket/bool -

(define (run-sexpr sexpr)
  (parameterize ((current-namespace (make-base-empty-namespace)))
    (namespace-require 'racket/base)
    (namespace-require 'racket/bool)
    (eval sexpr)))

(run-sexpr '(xor #t #t)) ;#f
(run-sexpr '(xor #t #f)) ;#t

Выше мы eval все s-выражение, но это может быть нежелательно. Чтобы программа работала, нам нужно всего лишь eval, чтобы превратить символ 'xor в значимую процедуру xor. Возможно, это ближе всего к вашей первоначальной цели -

(define (run-sexpr sexpr)
  (parameterize (...)
    (...)
    (apply (eval (car sexpr)) ;only eval car
           (cdr sexpr))))     ;apply cdr verbatim

(run-sexpr '(xor #t #t)) ;#f
(run-sexpr '(xor #t #f)) ;#t
...