Valtype
Valtype is Goblin's type introspection keyword. It tells you what type a value is at runtime. vt is the shorthand version.
Sometimes you need to know what type a value actually is — when you're debugging, when you're working with data you didn't create, or when a variable could hold different types depending on what happened before. valtype answers that question.
It is available in four equivalent forms:
age.vt age.valtype vt(age) valtype(age)
age.vt age.valtype vt(age) valtype(age)
All four do the same thing. Use whichever reads most naturally in context.
vt works on any expression — not just named variables:
(1 + 2).vt /// -> "int" "hello".vt /// -> "str"
(1 + 2).vt /// -> "int" "hello".vt /// -> "str"
Basic Usage
name | "Daniel" age | 46 active | true score | 99.5 name.vt /// -> "str" age.vt /// -> "int" active.vt /// -> "bool" score.vt /// -> "float"
name | "Daniel" age | 46 active | true score | 99.5 name.vt /// -> "str" age.vt /// -> "int" active.vt /// -> "bool" score.vt /// -> "float"
Inferred vs. Type-Locked Variables
What vt reports depends on how the variable was declared.
An unlocked variable reports its current runtime type:
age | 46 age.vt /// -> "int" age |= 99.5 age.vt /// -> "float"
age | 46 age.vt /// -> "int" age |= 99.5 age.vt /// -> "float"
A type-locked variable always reports its declared lock type, regardless of the stored value:
age.i32 | 46 age.vt /// -> "i32"
age.i32 | 46 age.vt /// -> "i32"
A type-locked collection reports the lock type qualified by the collection kind:
zip_codes.int | [90210, 80924] zip_codes.vt /// -> "array(int)" scores.float | { alice: 9.8, bob: 8.5 } scores.vt /// -> "map(float)"
zip_codes.int | [90210, 80924] zip_codes.vt /// -> "array(int)" scores.float | { alice: 9.8, bob: 8.5 } scores.vt /// -> "map(float)"
Comparing Types
vt returns a string, so you can compare it directly:
age | 46 if age.vt == "int" say "it's an integer" xx
age | 46 if age.vt == "int" say "it's an integer" xx
On Objects, Classes, and Enums
vt works on variables, object instances, and class definitions themselves.
On an object instance, vt returns "object":
rome <> Kingdom | name: "Rome", gold: 1000 rome.vt /// -> "object"
rome <> Kingdom | name: "Rome", gold: 1000 rome.vt /// -> "object"
On a class definition, vt returns "class":
Kingdom.vt /// -> "class"
Kingdom.vt /// -> "class"
On an enum value, vt returns "enum":
status | Status::idle status.vt /// -> "enum"
status | Status::idle status.vt /// -> "enum"