Types
built-in types, custom user types/objects and related helpers
Functions
Predicates
The Types module provides the foundation for Arturo's type system, including type checking, custom type definitions, and object-oriented programming capabilities.
Key Concepts
- Basic type checking
- Custom type definitions
- Object creation and manipulation
- Type conversion
- Magic methods for operator overloading
- Inheritance and composition
Basic Usage
Type Checking
; basic type checks
print type 42 ; :integer
print type "hello" ; :string
print type [1 2 3] ; :block
; check specific type
print integer? 42 ; true
print string? 42 ; false
; check if value is of type
print is? :integer 42 ; true
print is? :string "hi" ; true
Custom Types
; define new type
define :person [
; constructor
init: method [name age][
this\name: name
this\age: age
]
; string representation
string: method [][
~{|this\name| (|this\age| years old)}
]
]
; create instance
john: to :person ["John" 38]!
print john
; John (38 years old)
Tip
Within methods, you can use\field
as a shortcut forthis\field
. This makes code more concise and readable. For example:string: method [][ ; these are equivalent: print this\name ; explicit print \name ; shortcut ]
Inheritance
; base type
define :animal [
init: method [species][
\species: species
]
speak: method [][
print "..."
]
]
; derived type
define :dog is :animal [
init: method [name][
; call parent constructor
super "canis"
\name: name
]
speak: method [][
print "woof!"
]
]
; usage
fido: to :dog ["Fido"]!
print fido\species ; canis
fido\speak ; woof!
Type Conversions
; basic conversions
str: to :string 42 ; "42"
num: to :integer "42" ; 42
flt: to :floating "3.14" ; 3.14
; with custom format
date: to :date .format:"yyyy-MM-dd" "2024-01-15"
Magic Methods
Magic methods allow you to customize how your types behave with various operations.
Method | Arguments | Description | Example Use |
---|---|---|---|
init | any | Constructor | Object initialization |
get | field | Field access | obj\field |
set | field, value | Field assignment | obj\field: value |
changing | - | Before change hook | Pre-modification |
changed | - | After change hook | Post-modification |
compare | that | Custom comparison | Sort ordering |
equal? | that | Equality check | obj1 = obj2 |
less? | that | Less than | obj1 < obj2 |
greater? | that | Greater than | obj1 > obj2 |
add | that | Addition | obj1 + obj2 |
sub | that | Subtraction | obj1 - obj2 |
mul | that | Multiplication | obj1 * obj2 |
div | that | Division | obj1 / obj2 |
fdiv | that | Float division | obj1 // obj2 |
mod | that | Modulo | obj1 % obj2 |
pow | that | Power | obj1 ^ obj2 |
inc | - | Increment | inc 'obj |
dec | - | Decrement | dec 'obj |
neg | - | Negation | neg obj |
key? | key | Key existence | key? obj "field" |
contains? | what | Contains check | contains? obj item |
append | value | Add item | 'obj ++ value |
remove | value | Remove item | 'obj -- value |
string | - | String conversion | to :string obj |
integer | - | Integer conversion | to :integer obj |
floating | - | Float conversion | to :floating obj |
rational | - | Rational conversion | to :rational obj |
complex | - | Complex conversion | to :complex obj |
quantity | - | Quantity conversion | to :quantity obj |
logical | - | Logical conversion | to :logical obj |
block | - | Block conversion | to :block obj |
dictionary | - | Dictionary conversion | to :dictionary obj |
Tip
Magic methods are optional - implement only those that make sense for your type's behavior. Also, remember that when implementing magic methods, they affect how your type behaves with standard operators and functions throughout Arturo.
Common Patterns
Implementing Comparable Objects
define :score [
init: method [value][
\value: value
]
; custom comparison
compare: method [that][
if \value < that\value -> return neg 1
if \value > that\value -> return 1
return 0
]
]
; usage
scores: @[
to :score [42]!
to :score [18]!
to :score [73]!
]
print sort scores
; [value:18] [value:42] [value:73]
Tip
For simple comparisons based on a single field, you can use the sortable helper instead of implementing a fullcompare
method. In the above example, for instance:;... compare: sortable 'value ;...
Custom Collections
define :stack [
init: method [][
\items: []
]
push: method [item][
'this\items ++ item
]
pop: method [][
if empty? \items -> return null
return pop 'this\items
]
; custom conversion
string: method [][
~{Stack(|size \items| items)}
]
; support iteration
contains?: method [item][
contains? \items item
]
]
; usage
s: to :stack []!
s\push 1
s\push 2
print s\pop ; 2
Property Change Notifications
define :observable [
init: method [value][
\value: value
\observers: []
]
changing: method [][
loop \observers 'obs [
obs\beforeChange \value
]
]
changed: method [][
loop observers 'obs [
obs\afterChange \value
]
]
addObserver: method [observer][
'this\observers ++ observer
]
]
; usage
value: to :observable [42]!
value\addObserver #[
beforeChange: function [val][
print ["About to change from:" val]
]
afterChange: function [val][
print ["Changed to:" val]
]
]