All docsTypes and shapes

Types and shapes

Venutian's eight types, value versus reference semantics, and shape, the language's one way to declare a record type.

Venutian has eight types, in full: Integer, Number, Text, Truth, Nothing, List, Function, and one type per shape you declare. There is no Dictionary, no Tuple, no Set, no file object type, and no separate boolean subtype the way some languages check bool before int under the hood: kind(yes) always reads "Truth".

Value types and reference types

Every core type is either a value type, copied rather than shared, or a reference type, shared and mutated in place:

  • Value types: Integer, Number, Text, Truth, Nothing.
  • Reference types: List, and every shape instance.
venutian
a = [1, 2, 3]
b = a           :: b is bound to the same List, not a copy
b[0] = 99
print a          :: [99, 2, 3], a changed too
print b          :: [99, 2, 3]

Reassigning a itself never mutates anything a List shares: a = [7] afterward just rebinds the name a, leaving whatever b still points at untouched. == is Venutian's only comparison operator, and for a List or a shape instance it compares structurally, field by field, not by identity.

Numbers

Integer and Number are the two numeric types. An Integer literal is plain digits (12); a Number literal is digits, a dot, and digits (3.14). There is no hex, octal or binary literal prefix, no underscore digit grouping, no exponent notation, and no .5 or 10. shorthand.

venutian
print 2 + 3 * 4      :: 14, ordinary precedence, no exponent operator
print power(2, 10)    :: 1024, exponentiation is a builtin
print 7 / 2           :: 3.5, '/' always produces a Number

shape: Venutian's record type

shape declares a record type: fields only, with no attached methods. A shape's fields are typed, and an instance is built by calling the shape name like a function:

venutian
:: 'shape' declares a record type.
shape Person
    name: Text
    age: Integer

ada = Person("Ada Lovelace", 36)
print ada.name
print ada.age
print ada
output
Ada Lovelace
36
Person(name: "Ada Lovelace", age: 36)

A shape instance is a reference type: assigning it shares the same instance, and a field assignment mutates it in place, visible through every name bound to it.

venutian
same_person = ada
ada.age = 37
print same_person.age
output
37

Two shape instances compare equal when every field does, not by identity:

venutian
print Person("Ada", 36) == Person("Ada", 36)
print kind(ada)
output
yes
Person

Inheritance

A shape can inherit another shape's fields with inherits, and a typed pattern that names the parent shape matches an instance of any shape that inherits it, the same way a typed rescue does (see errors):

venutian
shape Animal
    name: Text

shape Dog inherits Animal
    breed: Text

shape Cat inherits Animal
    indoor: Truth

make describe(value)
    choose value
        is d: Dog
            print d.name, "is a Dog (breed", d.breed + ")"
        is c: Cat
            print c.name, "is a Cat (indoor:", as_text(c.indoor) + ")"
        is a: Animal
            print a.name, "is some other kind of Animal"
        is : Text
            print "just plain Text, not an Animal at all"
        otherwise
            print "no idea what that is"

describe(Dog("Rex", "Labrador"))
describe(Cat("Whiskers", yes))
output
Rex is a Dog (breed Labrador)
Whiskers is a Cat (indoor: yes)

choose's is name: Type pattern binds the matched value under name at that type; is : Type matches without binding a name at all. Patterns are tried in order, and the first one that matches wins, so a more specific shape like Dog is listed before its parent Animal.

See errors for how the same typed matching works in a rescue clause, and modules for using a shape declared in another file.