Is there any unsafe way to determine if a value is an opaque struct?
Back in the Scheme days without a portable gensym
and with no structs, it was popular to write (define none (list 'none))
to produce a unique value that printed nicely.
It depends on what you mean by “opaque struct”.
I assume you want to recognize instances of something like (struct s ())
and not, say, a number or a primitive like cons
. But various core datatypes are represented with opaque structures, including some forms of procedures and most chaperoned values. It’s not clear that drawing a line between those after-the-fact makes sense, and I’m not immediately sure what operation would make sense if you don’t draw a line.
The intended way of distinguishing layers is to set an inspector so that anything created as opaque afterward is not opaque to you, but I don’t know whether that’s an option in your case.
I’d like to recognize non-primitives, what would be record? at the chez level
(If that includes core data structures that happen to be structs that’s ok.)
I think record?
will capture everything you want, but possibly more. “Primitive” versus “not primitive” just isn’t a reliable concept.
I can provide a bit more context. I’m just doing some extremely experimental code and I’d like to be able to chaperone values that I reasonably shouldn’t be able to chaperone. Generally, I know that you can retrieve the struct type of an arbitrary opaque struct unsafely via unsafe-struct-ref
and -1
but I obviously don’t want to do that for primitives.
Ok. Since you’re going to Chez Scheme for record?
, I recommend also using record-rtd
instead of unsafe-struct-ref
with -1
.
Right, but I’m interested in doing this at the Racket level. Of course I can hack my version of Racket to expose these things, but I’d prefer not to do that :stuck_out_tongue:
But maybe that’s the only thing to do here
Or the other option I suppose is to just have a predicate that checks for every primitive and just hope that I don’t miss any.
In case it helps, it’s possible at the Rumble level to determine whether a record type was created with make-struct-type
: use inspector-ref
and check that the result is not none
.
Ah, that is useful. Thanks!
Wow. Not having gensym
is understandable, but having no structs/records sounds quite limiting for abstraction. Would people then use lists to store records? (Wait, records would be nicer, I suppose, if you have them.) Given that Scheme is Scheme, I’d expect people roll their own record
/struct
types, though. :wink: Along these lines, I saw there’s nowadays an <https://srfi.schemers.org/srfi–9/srfi–9.html|SRFI for records>.
It wasn’t unusual to see: (define foo-tag (list 'foo))
(define (make-foo a b) (vector foo-tag a b))
(define (foo? x) (and (vector? x) (eq? (vector-ref x 0) foo-tag))
(define (foo-a x) (cond [(foo? x) (vector-ref x 1)] [else (error 'foo-a "expected a foo")]))
etc
However, this was only necessary when writing portable Scheme. Most implementations had their own records/structures.
I believe portable records/structures first appeared in R6RS.