
Say that I have a syntax class with several cases, and I want to specify that, if a certain attribute does not meet a specific condition, then the class should raise a failure condition. I can include this logic with every mention of the syntax class, but it’s really part of the class itself, and shouldn’t be repeated at use sites. Including the condition checking in every case of the pattern is also not great, since the condition relies only on an attribute that is well-defined for all cases, so is independent of any particular case’s structure.
Since there’s no tidy way to do what I’m trying, I’m wondering if maybe I’m going about things the wrong way?

@kellysmith12.21 Have you seen https://docs.racket-lang.org/syntax-parse-example/index.html#%28part._syntax-class-contract%29 ?

Maybe N/A for you. (My pre-first-cup-of-coffee brain was only able to grok, “like a contract for a syntax class”, from what you wrote. Made me think of this, which I’ve seen but not tried.)

That kind of structure within a number seems common. Something similar happens with floating-point numbers, of course, and it turns out that CS hashing does badly there, because it uses the bits of the FP representation as a fixnum.
I’ll run more tests, but so far adjusting the hash function seems like a clear, dramatic win on patterns that seem likely to occur in practice:
https://gist.github.com/mflatt/f55adb5a6d08045c0d6276b4ce64ddfb

It turns out that the bit shuffling should happen at the level of the hash-table implementation, not the hashing function. It’s the hash-table implementation that was ignoring the extra bits, after all. Adjusting at that level is also needed to repair eq?
-based tables for fixnums. Meanwhile, performance of immutable hash tables is not affected this way.

One alternative to adding common attributes or checks to every variant of a syntax class is to split it into two syntax classes. The “inner” syntax class has multiple variants, and the “outer” syntax class has a single variant that refers to the inner syntax class and also performs the common checks based on attributes defined by the inner class. The outer syntax class will have to explicitly re-export every inner attribute that you want to use elsewhere. You may find the :stxclass
pattern useful: it binds the attributes of stxclass
without a dotted prefix.

In OO terms, the solution is to replace “is-a” and implementation inheritance with “has-a” and forwarding.

@ryanc A wrapper syntax class seems the way to go, especially since the outer class serves as a refinement of the inner class. Thank-you.

@greg That’s not quite what I was looking for, but that’s a useful utility, nonetheless. Thanks :grinning:

@radicalmatt has joined the channel

Is there a nice workaround for the exception to how ~?
works in a datum
template? Always succeeding, even with a #f
value from a missing binding, is not particularly helpful, when building templates.

Thanks for looking into this and fixing the issue.
I also tried creating my own hash function, which drops the bottom 21 bits (which are the common ones for my data set) and used make-custom-hash
, while this was significantly faster, it was still about 3–4 times slower than using an immutable hash. I suspect there is some overhead with using make-custom-hash
when compared to the “native” hash implementations.
I was also surprised by the performance of immutable hashes, which I didn’t use until now.

No, because syntax-parse
does not distinguish “missing” from “has the value #f
”.

Is there any way to make this: #lang racket
(struct/contract qty ([n number?]))
(struct/contract kg qty ())
(kg "bad")
which says qty: contract violation
, say kg: contract violation
instead?

I suppose can do it by attaching the contract during provide Or rather, automate that by making a defqty macro that makes the struct as well as the provide form.