How do I get the type of a value in Scheme?

20,110

Solution 1

In Scheme implementations with a Tiny-CLOS-like object system, you can just use class-of. Here's a sample session in Racket, using Swindle:

$ racket -I swindle
Welcome to Racket v5.2.1.
-> (class-of 42)
#<primitive-class:exact-integer>
-> (class-of #t)
#<primitive-class:boolean>
-> (class-of 'foo)
#<primitive-class:symbol>
-> (class-of "bar")
#<primitive-class:immutable-string>

And similarly with Guile using GOOPS:

scheme@(guile-user)> ,use (oop goops)
scheme@(guile-user)> (class-of 42)
$1 = #<<class> <integer> 14d6a50>
scheme@(guile-user)> (class-of #t)
$2 = #<<class> <boolean> 14c0000>
scheme@(guile-user)> (class-of 'foo)
$3 = #<<class> <symbol> 14d3a50>
scheme@(guile-user)> (class-of "bar")
$4 = #<<class> <string> 14d3b40>

Solution 2

In Racket, you can use the describe package by Doug Williams from PLaneT. It works like this:

> (require (planet williams/describe/describe))
> (variant (λ (x) x))
'procedure
> (describe #\a)
#\a is the character whose code-point number is 97(#x61) and
general category is ’ll (letter, lowercase)

Solution 3

All of the answers here are helpful, but I think that people have neglected to explain why this might be hard; the Scheme standard doesn't include a static type system, so values can't be said to have just one "type". Things get interesting in and around subtypes (e.g. number vs floating-point-number) and union types (what type do you give to a function that returns either a number or a string?).

If you describe your desired use a bit more, you might discover that there are more specific answers that will help you more.

Solution 4

To check the type of something just add a question mark after the type, for example to check if x is a number:

(define get-Type
  (lambda (x)
    (cond ((number? x) "Number")
          ((pair? x) "Pair")
          ((string? x) "String")
          ((list? x) "List")))) 

Just continue with that.

Share:
20,110

Related videos on Youtube

Matt Fenwick
Author by

Matt Fenwick

Cloud native engineer &amp; Kubernetes member. Check out some of my work on github: Cyclonus: conformance test suite for kubernetes CNIs for network policy implementations NMRPyStar: an API for accessing archived NMR data files in the NMR-Star format used by the BMRB. Miscue-js: validation of JSON files to deal with obnoxious and tricky interoperability issues such as number overflows and duplicate keys Some cool technologies that I use: Python Javascript Haskell MySQL golang kubernetes

Updated on July 20, 2020

Comments

  • Matt Fenwick
    Matt Fenwick almost 4 years

    I want a function that gets the type of a value at runtime. Example use:

    (get-type a)
    

    where a has been defined to be some arbitrary Scheme value.

    How do I do this? Or do I have to implement this myself, using a cond stack of boolean?, number? etc. ?

  • C. K. Young
    C. K. Young almost 12 years
    The OP specifically asked if there were an alternative to this approach. Also, why use nested ifs when you can use cond? *boggles*
  • newacct
    newacct almost 12 years
    He says "at runtime", so this has nothing to do with static types. It's the dynamic (runtime) types of values he's after
  • dyoo
    dyoo almost 12 years
    You're missing John's point, in the sense that the dynamic runtime types don't always have enough information to disambiguate. Concrete example: let's say that I have a program that deals with colors and names. I may choose to represent values of these types with just strings. Then if I see the word "Gray", I don't have enough information to distinguish the type because I'm using the same representation.
  • John Clements
    John Clements almost 12 years
    Ditto; you can delete the word "static" from my post, and it still makes sense. Danny's example is a good one. In fact, the C language has the same issue: there's no "what's the type of this value" operator, because many values have the same representation.
  • Sled
    Sled over 11 years
    @ewein @Chris Jester-Young is this missing any? For (get-Type (car (string->list (number->string 5)))) this doesn't return anything.
  • Sled
    Sled over 11 years
    Turns out for my case the missing bit was character?. For completeness sake there is also vector?.
  • Salil
    Salil about 11 years
    This package is indeed helpful. I wish it was part of the core Racket.
  • day
    day about 10 years
    I don't see why the two examples you give poses any problem. For the number vs floating-point-number case, return the latter since it is the least. For the procedure case, just return ′procedure.
  • John Clements
    John Clements about 10 years
    Narrowly: what about the type "numbers-greater-than-zero" and "floating-point-numbers"? Neither of these fits inside the other one. More generally: you have a particular notion of types in mind, and you could certainly write a get-type that does what you want it to. You should do that!