Я пытаюсь выровнять метапрограммирование в Racket и понял, что не знаю, как взять данные и просто «оценить» их.

Если бы у меня был

  (for ((x '(("Five" (+ 2 3))
             ("Twelve" (* 6 2))
             ("Three" (- (/ 21 3) 4)))))
    (displayln (format "~s: ~s" (first x) (second x))))

Я получаю

: "Five": (+ 2 3)
: "Twelve": (* 6 2)
: "Three": (- (/ 21 3) 4)

Что на самом деле не то, что я хочу - я хочу оценить этот список, чтобы получить ответ.

Я уверен, что это просто (возможно, мне нужно использовать синтаксис?), Но сейчас я просто скучаю по картинке. Как я могу это сделать?

< EM> Edit: Я хочу оценить s-exp непосредственно перед отображением, а не в начальном списке. Вот почему я полагаю, что мне может понадобиться синтаксис, поскольку мне (я думаю) придется вводить текущий контекст синтаксиса.

3
George Mauer 21 Июл 2020 в 06:56

2 ответа

Лучший ответ

Eval - почти всегда неправильный выбор, но eval - это то, что вы ищете:

#lang racket

(define base-ns (make-base-namespace))
(for ((x '(("Five" (+ 2 3))
           ("Twelve" (* 6 2))
           ("Three" (- (/ 21 3) 4)))))
  (displayln (format "~s: ~s" (first x) (eval (second x) base-ns))))

Альтернатива 1: лямбда / гром

(for ((x `(("Five" ,(thunk (+ 2 3)))
           ("Twelve" ,(thunk (* 6 2)))
           ("Three" ,(thunk (- (/ 21 3) 4))))))
  ;; notice double parentheses to call the thunk
  (displayln (format "~s: ~s" (first x) ((second x)))))

Thunk - это просто синтаксический сахар для лямбды без аргументов. Я немного поиграл с процедурами, которые могут печатать их источники. Таким образом, вы можете создать свой собственный thunk с исходной структурой в виде структуры, которую я продемонстрирую на моей визуальной лямбде:

(struct proc (src obj)
  #:property prop:procedure (struct-field-index obj)
  #:transparent
  #:methods gen:custom-write
  [(define (write-proc x port mode)
     ((case mode
        [(#t) write]
        [(#f) display]
        [else pretty-print])
      (proc-src x)
      port))])

(define-syntax lambda*
  (syntax-rules ()
    ((_ . rest)
     (proc '(lambda* . rest) (lambda . rest)))))

(define test (lambda* (x y) (+ x y)))

test                  ; ==> #(struct:closure (lambda* (x y) (+ x y)) #<procedure>)
(proc-src test)       ; ==> (lambda* (x y) (+ x y))
(proc-obj test)       ; ==> #<procedure>
((proc-obj test) 1 2) ; ==> 3
(test 1 2)            ; ==> 3
(display test)        ; prints (lambda* (x y) (+ x y))
3
Sylwester 22 Июл 2020 в 02:47

Используйте backquote вместе с unquote, который

;; backquote: ` 
;; unquote: ,
;; there is also splice list: ,@

(for ((x `(("Five" ,(+ 2 3))
           ("Twelve" ,(* 6 2))
           ("Three" ,(- (/ 21 3) 4)))))
  (displayln (format "~s: ~s" (first x) (second x))))

;; "Five": 5
;; "Twelve": 12
;; "Three": 3

1
Gwang-Jin Kim 21 Июл 2020 в 07:08