According to the documentation eval
and eval-syntax
behave the same with the exception that eval
enriches the input syntax.
If top-level-form is a syntax object whose datum is not a compiled form, then its lexical information is enriched before it is sent to the evaluation handler:
Like eval, except that stx must be a syntax object, and its lexical context is not enriched before it is passed to the evaluation handler.
I am having a hard time understanding what this means. I get the impression that involves namespaces somehow, but I can't come up with an example program where eval and eval-syntax behave differently. (When given a syntax object.)
So how do eval
and eval-syntax
differ, or at least can you give me a sample program that shows them behaving differently?
Here is a sample interaction that shows them behaving differently:
Welcome to Racket v6.2.900.10.
-> (define ns (make-base-namespace)) ; set up namespace ns
-> (eval '(require racket/vector) ns) ; bring in vector-map into ns
-> (module a racket/base
(define stx #'(vector-map + #(1 2) #(3 4))) ; no vector-map here
(provide stx))
-> (require 'a)
-> (eval stx ns)
'#(4 6)
-> (eval-syntax stx ns)
; vector-map: undefined;
; cannot reference undefined identifier
; [,bt for context]
This shows that namespace-syntax-introduce
is applied to the syntax object stx
in the eval
case using a namespace that has the vector bindings, which is why the vector-map
application succeeds.
In the eval-syntax
case, the syntax object does not have the lexical information for vector-map
and no namespace introduction is done, so it results in an error.
Note that you need the module to show this difference rather than a top-level definition of the syntax object because top-level bindings are special. See this bit from namespace-syntax-introduce
:
The additional context is overridden by any existing top-level bindings in the syntax object’s lexical information
You can get similar behavior inside of a module:
#lang racket/base ; racket/base does not include racket/vector
(define ns (make-base-namespace)) ; Create Namespace
(eval #'(require racket/vector) ns) ; Load racket/vector into ns
(define stx #'(vector-map + #(1 2) #(3 4)))
(eval stx ns) ; => '#(4 6)
(eval-syntax stx ns) ; => ERROR!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With