Hi! Stupid question, but how do I append two datums
Like, how do I turn 'pine
and 'apple
into 'pineapple
Is the best way to do it just (string->datum (string-append (datum->string 'pine) (datum->string 'apple)))
?
they’re “symbols”, not “datums”
but yes, you have to use symbol->string
and string->symbol
, though if you’re using them as syntax identifiers, you can use format-id
.
How can I then use that identifier from format-id
? In my case, I’m using it to generate a function name and I have the arguments as syntax-objects
I thought I could do e.g. (let ([id (format-id <args>)]) (list->syntax (id <stx1> <stx2>)))
, but it doesn’t seem like there’s such a list->syntax function
Are you using syntax/parse
?
Yes
In reality, <stx1>
is #'var
where var
is a pattern variable
You can use #:with id (format-id <args>)
as a pattern directive, then #'(id <stx1> <stx2>)
.
Oh! Thanks
Or, if you want the ordinary, non-pattern binding, #`(#,(format-id <args>) <stx1> <stx2>)
Or, if you really do want to do it manually, (datum->syntax #'here (list (format-id <args>) <stx1> <stx2>))
, but I think using syntax
or quasisyntax
is a better bet.
@hazel.r.pearson has joined the channel
So, when I make this identifier with format-id
I have to provide
it, whereas if I call it directly I don’t. Is there any way to not have to provide the identifier?
@brendan I don’t know what you mean. Can you make a MCVE? https://stackoverflow.com/help/mcve
yeah, sorry
In point-lang.rkt
#lang racket
(require syntax/parse/define (for-syntax racket/syntax))
(provide #%module-begin #%datum #%app define/point set-field)
(struct point (x y) #:mutable)
(define-syntax-parser set-field
[(_ p field val) #`(#,(format-id #'field "set-point-~a!" (syntax-e #'field)) p val)])
(define-syntax-parser define/point
[(_ p:id x:number y:number) #'(define p (point x y))])
in point-test.rkt
#lang s-exp "point-lang.rkt"
(define/point my-point 1 2)
(set-field my-point x 1)
@lexi.lambda this is pretty much what I’m trying to do
I think your first argument to format-id
is wrong, since you want the field mutator to have the lexical context of point-lang.rkt
, not point-test.rkt
. Try using #'here
instead of #'field
for the lexical context argument.
oh… that makes perfect sense
(There is nothing magical about the name “here
” in #'here
, it’s just a piece of syntax that has the lexical context of the containing module.)
@brendan Also, FWIW, you probably want to put the :id
syntax class on field
, since otherwise (set-field my-point "x" 1)
will fail with a compile-time contract violation blaming point-lang.rkt
.
Oh, I thought id
actually checked that it was a valid identifier
identifier?
is just (and/c syntax? (lambda (stx) (symbol? (syntax-e stx))))
.
Okay, that makes more sense
Thanks for the help Alexis!