Seems canonical enough to me :slightly_smiling_face:
Turns out that this doesn’t work well. equal?
-based hash is really too expensive and becomes the bottleneck of memoization for my code formatter. So I switched the data structure to a vector of hash instead.
(match-define
(hash-table
('key-a a)
('key-b b)) #hasheq( (key-a . "foo") (key-b . "bar"))
of any use?
oh, darn, didn’t read the question right
disregard what I said
@sorawee you can make your own hash functions
@community has joined the channel
You mean using define-custom-hash-types
? Tried that. The overhead is super high (even higher than the code in https://racket.slack.com/archives/C06V96CKX/p163306063508130)
for some reason your link doesn’t work for me
too bad it’s that slow though :confused:
My link is to the very first post of this thread — the one that asks the question
I guess that’s why it doesn’t work. It’s already “opened”
@sorawee How does the following perform? (define counter 0)
(define (next-counter!) (begin0 counter (set! counter (add1 counter))))
(define ref (make-hasheq)) ;; K => Nat
(define table (make-hasheqv)) ;; Nat => V
(define (keys->nat k1 k2)
(combine (hash-ref! ref k1 next-counter!)
(hash-ref! ref k2 next-counter!)))
(define (combine x y) ;; combines two Nats by (coarsely) interleaving bits
(cond [(and (zero? x) (zero? y)) 0]
[else (+ (bitwise-bit-field x 0 8)
(arithmetic-shift (combine y (arithmetic-shift x -8)) 8))]))
(define my-ref
(case-lambda
[(k1 k2) (hash-ref table (keys->nat k1 k2))]
[(k1 k2 default) (hash-ref table (keys->nat k1 k2) default)]))
(define (my-set! k1 k2 v)
(hash-set! table (keys->nat k1 k2) v))
You can also do it with nested tables. (define table (make-hasheq))
(define ref (make-hasheq))
(define (my-ref x y)
(define a (hash-ref! ref x gensym))
(define b (hash-ref! ref y gensym))
(hash-ref! (hash-ref! table a make-hasheq)
b ...))
> I guess that’s why it doesn’t work. It’s already “opened” Thanks Slack for the example, how it can be hard to determine equality both efficiently and correctly? :stuck_out_tongue:
I think you mean “so this all changed long after the stepper was written” :wink: Thanks!
Well 15 years is all I can speak to, but my guess is that it has always worked that way
I didn’t realize that the stepper was published in 2001 and it even predates Racket’s modern module system!!
MzScheme :scream:
> 10. Flatt, M. PLT MzScheme: Language manual. Technical Report TR97–280, RiceUniversity, 1997.
So the stepper introduces continuation marks into Racket? Wow!!
> how it can be hard to determine equality both efficiently and correctly? Type theorists have been working on this problem for decades and it is still an ongoing work!
I’m afraid I watched too many episodes of Sesame Street to take this problem too seriously. https://www.youtube.com/watch?v=_Sgk-ZYxKxM
It’s worth noting that the identifier produced by (datum->syntax #f 'x)
can be referenced or bound by any other identifier named x
that has an empty set of scopes. In many cases syntax-local-introduce
can be a better choice that datum->syntax
for treating a bit of syntax as though it had been part of the input to the macro. In this case, though, the best choice would be using define-syntax-parameter
and syntax-parameterize
.