ask the type of a value

29 views
Skip to first unread message

Hendrik Boom

unread,
Aug 3, 2020, 10:19:38 AM8/3/20
to Racket Users
In plain, untyped Racket:

It is possible to ask if a value is a symbol with symbol?
It is possible to ask if a value is a string with string?
etc.

Is there a way to ask the type of a value without having to guess it first?

-- hendrik

Laurent

unread,
Aug 3, 2020, 11:07:52 AM8/3/20
to Racket Users
Maybe try `struct->vector`, which works on any value iirc (from mobile, can't test)

--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/20200803141931.t4v4nc2e5d4afx6f%40topoi.pooq.com.

Alexis King

unread,
Aug 3, 2020, 11:20:20 AM8/3/20
to Hendrik Boom, Racket Users
In general, the answer is “no,” mostly because it’s not clear in Racket what “the type of a value” means. It’s difficult to come up with a definition that would be useful enough to satisfy your criterion of not “having to guess it first.” Consider: suppose you had a hypothetical `type-of` operation that returned a value’s type:

(type-of 'hello) ; => 'symbol
(type-of "hello") ; => 'string

Now suppose you apply type-of to a value you know nothing about and get back 'widget. Well, you don’t know what a widget is, so that didn’t actually get you any further from where you started: you still don’t know what to do with the value.

Furthermore, types are not actually disjoint. You can write a struct definition with properties like prop:procedure and prop:evt, and if a struct has both, should type-of return the struct’s name, 'procedure, or 'evt? It’s not really clear. You might be able to come up with some more sophisticated system with (potentially multiple) inheritance that could capture these relationships, but I can say with confidence that no such system currently exists in Racket.

Alexis

Laurent

unread,
Aug 3, 2020, 12:07:12 PM8/3/20
to Alexis King, Hendrik Boom, Racket Users
and yet:

> (for-each
   (λ (x) (printf "~a: ~a\n" (~v x #:min-width 28) (struct->vector x)))
   `(hello "hello" 43110 #f #(h e l l o) #"hello" (h e l l o)
           ,(new frame% [label ""])))

hello                       : #(struct:symbol ...)
"hello"                     : #(struct:string ...)
43110                       : #(struct:fixnum-integer ...)
#f                          : #(struct:false ...)
#(h e l l o)                : #(struct:vector ...)
#"hello"                    : #(struct:byte-string ...)
(h e l l o)                 : #(struct:pair ...)
#(struct:object:frame% ...) : #(struct:object:frame% ...)


;)


--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.

Hendrik Boom

unread,
Aug 3, 2020, 12:48:51 PM8/3/20
to Racket Users
On Mon, Aug 03, 2020 at 05:06:51PM +0100, Laurent wrote:
> and yet:
>
> > (for-each
> (λ (x) (printf "~a: ~a\n" (~v x #:min-width 28) (struct->vector x)))
> `(hello "hello" 43110 #f #(h e l l o) #"hello" (h e l l o)
> ,(new frame% [label ""])))
>
> hello : #(struct:symbol ...)
> "hello" : #(struct:string ...)
> 43110 : #(struct:fixnum-integer ...)
> #f : #(struct:false ...)
> #(h e l l o) : #(struct:vector ...)
> #"hello" : #(struct:byte-string ...)
> (h e l l o) : #(struct:pair ...)
> #(struct:object:frame% ...) : #(struct:object:frame% ...)
>
> ;)

Thank you.

That itself is already useful.
struct->vector combined with printf handles my immediate application.
It told me #(struct:object:image-snip% ...)
As I've been warned, it doesn't tell me much, but the result is a
useful clue for further investigation.

It turns out to react positively to image?

Still, it would be nice to find out how to get this information more
directly instead of relying on functions that do much more than
what I was asking for.

-- hendrik

Ryan Culpepper

unread,
Aug 3, 2020, 1:12:50 PM8/3/20
to Laurent, Alexis King, Hendrik Boom, Racket Users
but beware, for

  > (for-each
     (lambda (x) (printf "~a: ~a\n" (~v x #:min-width 28) (struct->vector x)))
     (list "hello" (let () (struct string (n)) (string 5))))
  "hello"                     : #(struct:string ...)
  #<string>                   : #(struct:string ...)

Ryan


Alexis King

unread,
Aug 3, 2020, 3:02:27 PM8/3/20
to Hendrik Boom, Racket Users
> On Aug 3, 2020, at 11:48, Hendrik Boom <hen...@topoi.pooq.com> wrote:
>
> Still, it would be nice to find out how to get this information more
> directly instead of relying on functions that do much more than
> what I was asking for.

In general, there aren’t any. The ability of struct->vector to extract a symbolic name for any value really is specific to struct->vector (and it’s only really useful for debugging, for the reason Ryan points out).

If you only care about bona fide structs, not primitive values like strings and ports, you can do a little better using struct-info:

(define (type-name v)
(match/values (struct-info v)
[(#f _) #f]
[((app struct-type-info name _ _ _ _ _ _ _) _) name]))

(struct point (x y) #:transparent)
(type-name (point 1 2)) ; => 'point

But this doesn’t work for non-transparent structs unless you own a sufficiently powerful inspector:

(let ()
(struct point (x y))
(type-name (point 1 2))) ; => #f

(let ()
(struct point (x y)
#:inspector (make-inspector))
(type-name (point 1 2))) ; => 'point

But again, this just gets you a symbolic name, which is subject to the same issue Ryan points out. The value you get back from struct-info is truly unique to that particular type, so it’s a more useful value than the symbolic name. But again, it’s not clear to me why you’d want to do this (except for debugging/instrumentation), since you still can’t possibly do anything useful with a value of a truly unknown type.

On the other hand, if it *is* for debugging, then meddling with the inspector is a valid thing to do (and is in fact one of the main reasons inspectors exist). You can change current-inspector to a weaker inspector during the instantiation of the modules you want to debug, and then you can use struct-info to get information about any values of the struct types they create.

Alexis
Reply all
Reply to author
Forward
0 new messages