What is the idiomatic way to represent a data type variant that contains no useful data (i.e. is a simple tag): a symbol, or a fieldless struct?
I personally like fieldless struct more than symbol. The problem with symbols is that it’s so easy to misspell, and there’s not really a way to prevent the mistake. With fieldless struct, the macroexpander can help you catch the mistake.
But idiomatically, I think it depends on other variants. If other variants are also structs, then it fieldless structs are definitely the idiomatic way and not symbols.
On the other hand, if other variants are numbers, booleans, etc., then symbols are usually used.
Ok. Since the other variants are structs, I’ll use a fieldless struct.
You can still use https://docs.racket-lang.org/reference/symbols.html?q=gensym#%28def._%28%28quote._~23~25kernel%29._gensym%29%29\|gensym and name the symbol: (define my-special-symbol (gensym))
You don’t care about the actual name of the symbol, you only care that it’s something that cannot be eq?
to anything generated elsewhere. Then you have to use the identifier my-special-symbol
so if you misspell it you’ll be notified. (The symbol is uninterned, which means it can’t be written then read back to the same value)
The only other thing that fieldless struct give you is the corresponding predicate, but otherwise it’s also a little bit overblown compared to uninterned symbols.
If you don’t want to use gensym you can equally still use https://docs.racket-lang.org/reference/symbols.html?q=gensym#%28def._%28%28quote._~23~25kernel%29._string-~3euninterned-symbol%29%29\|string-uninterned-symbol> : (define my-sym (string->uninterned-symbol "my-sym"))
and this can be automated with a macro of course: #lang racket
(require syntax/parse/define)
(define-simple-macro (define-uninterned-symbol sym)
(define sym (string->uninterned-symbol (format "~a" 'sym))))
(define-uninterned-symbol my-awesome-symbol)
my-awesome-symbol ; 'my-awesome-symbol
(eq? my-awesome-symbol my-awesome-symbol) ; #t
(eq? my-awesome-symbol 'my-awesome-symbol) ; #f
And since you didn’t ask for it, here’s a version that also creates the predicate: #lang racket
(require (for-syntax syntax/parse
racket/syntax))
(define-syntax (define-uninterned-symbol+predicate stx)
(syntax-parse stx
[(_ name:id)
(with-syntax ([pred (format-id #'name "~a?" (syntax-e #'name) #:source #'name)])
#'(begin
(define name (string->uninterned-symbol (format "~a" 'name)))
(define (pred x) (eq? x name))))]))
;; Example:
(define-uninterned-symbol+predicate abc)
abc ; 'abc
(eq? abc abc) ; #true
(eq? abc 'abc) ; #false
(abc? abc) ; #true
(abc? 'abc) ; #false
If other variants are also structs, I still think that it’s more reasonable to use fieldless structs. As a plus, you will have a uniform pattern matching:
(match val
[(nullary-node) ...]
[(unary-node x) ...]
[(binary-node x y) ...])
That’s not to say it’s not possible to pattern match symbols, but it would be less uniform:
(match val
['nullary-node ...] ;; also easy to misspell
[(unary-node x) ...])
(define nullary-node 'nullary-node)
(match val
[(== nullary-node) ...] ;; it works I guess?
[(unary-node x) ...])
(define (nullary-node? x) (eq? 'nullary-node))
(match val
[(? nullary-node?) ...] ;; it works I guess?
[(unary-node x) ...])
I was considering the general case. If everything else are structs, I agree with you :slightly_smiling_face:
Hello, if a hash table only uses symbols as keys which of the equality predicates should I use? eqv? or eq?
for hash-ref
Both would work. eq
is fastest.
ok that’s what I thought, thanks :slightly_smiling_face:!
is it okay to build a hash table with symbols generated by gensym by the way?
yes
alrighty thanks! Was trying to understand what would be a good correspondence to the value store of the first machine describe in the Van Roy book. Thought a hash table with gensym symbols would be good!
there’s also define-singleton-type
:slightly_smiling_face: https://docs.racket-lang.org/rebellion/Singleton_Types.html\|https://docs.racket-lang.org/rebellion/Singleton_Types.html
Downloading the whole of Rebellion just for this might be a little overblown maybe :wink:
Though it’s a great way to entice exploration of the whole thing!
You also have make-generative-token
!
yup :p