Skip to content

Instantly share code, notes, and snippets.

@leveled
Created February 3, 2021 13:34
Show Gist options
  • Save leveled/db7c93056872257799a93ea021e53b78 to your computer and use it in GitHub Desktop.
Save leveled/db7c93056872257799a93ea021e53b78 to your computer and use it in GitHub Desktop.
Complex variable types in nim
#Type with enum
type
Direction = enum
north, east, south, west
var x = south # `x` is of type `Direction`; its value is `south`
echo x # writes "south" to `stdout`
#Subrange
type
MySubrange = range[0..5]
#Set
type
CharSet = set[char]
var
x: CharSet
x = {'a'..'z', '0'..'9'} # This constructs a set that contains the
# letters from 'a' to 'z' and the digits
# from '0' to '9'
#Bit Fields
type
MyFlag* {.size: sizeof(cint).} = enum
A
B
C
D
MyFlags = set[MyFlag]
proc toNum(f: MyFlags): int = cast[cint](f)
proc toFlags(v: int): MyFlags = cast[MyFlags](v)
assert toNum({}) == 0
assert toNum({A}) == 1
assert toNum({D}) == 8
assert toNum({A, C}) == 5
assert toFlags(0) == {}
assert toFlags(7) == {A, B, C}
#Arrays
type
IntArray = array[0..5, int] # an array that is indexed with 0..5
var
x: IntArray
x = [1, 2, 3, 4, 5, 6]
for i in low(x)..high(x):
echo x[i]
type
Direction = enum
north, east, south, west
BlinkLights = enum
off, on, slowBlink, mediumBlink, fastBlink
LevelSetting = array[north..west, BlinkLights]
var
level: LevelSetting
level[north] = on
level[south] = slowBlink
level[east] = fastBlink
echo repr(level) # --> [on, fastBlink, slowBlink, off]
echo low(level) # --> north
echo len(level) # --> 4
echo high(level) # --> west
type
LightTower = array[1..10, LevelSetting]
var
tower: LightTower
tower[1][north] = slowBlink
tower[1][east] = mediumBlink
echo len(tower) # --> 10
echo len(tower[1]) # --> 4
echo repr(tower) # --> [[slowBlink, mediumBlink, ...more output..
# The following lines don't compile due to type mismatch errors
#tower[north][east] = on
#tower[0][1] = on
#Sequences
var
x: seq[int] # a reference to a sequence of integers
x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence allocated on the heap
#Open Arrays
var
fruits: seq[string] # reference to a sequence of strings that is initialized with '@[]'
capitals: array[3, string] # array of strings with a fixed size
capitals = ["New York", "London", "Berlin"] # array 'capitals' allows assignment of only three elements
fruits.add("Banana") # sequence 'fruits' is dynamically expandable during runtime
fruits.add("Mango")
proc openArraySize(oa: openArray[string]): int =
oa.len
assert openArraySize(fruits) == 2 # procedure accepts a sequence as parameter
assert openArraySize(capitals) == 3 # but also an array type
#Varargs
proc myWriteln(f: File, a: varargs[string]) =
for s in items(a):
write(f, s)
write(f, "\n")
myWriteln(stdout, "abc", "def", "xyz")
# is transformed by the compiler to:
myWriteln(stdout, ["abc", "def", "xyz"])
#Slices
var
a = "Nim is a programming language"
b = "Slices are useless."
echo a[7 .. 12] # --> 'a prog'
b[11 .. ^2] = "useful"
echo b # --> 'Slices are useful.'
#Objects
type
Person = object
name: string
age: int
var person1 = Person(name: "Peter", age: 30)
echo person1.name # "Peter"
echo person1.age # 30
var person2 = person1 # copy of person 1
person2.age += 14
echo person1.age # 30
echo person2.age # 44
# the order may be changed
let person3 = Person(age: 12, name: "Quentin")
# not every member needs to be specified
let person4 = Person(age: 3)
# unspecified members will be initialized with their default
# values. In this case it is the empty string.
doAssert person4.name == ""
#Exported object
type
Person* = object # the type is visible from other modules
name*: string # the field of this type is visible from other modules
age*: int
#Tuples
type
# type representing a person:
# A person consists of a name and an age.
Person = tuple
name: string
age: int
# Alternative syntax for an equivalent type.
PersonX = tuple[name: string, age: int]
# anonymous field syntax
PersonY = (string, int)
var
person: Person
personX: PersonX
personY: PersonY
person = (name: "Peter", age: 30)
# Person and PersonX are equivalent
personX = person
# Create a tuple with anonymous fields:
personY = ("Peter", 30)
# A tuple with anonymous fields is compatible with a tuple that has
# field names.
person = personY
personY = person
# Usually used for short tuple initialization syntax
person = ("Peter", 30)
echo person.name # "Peter"
echo person.age # 30
echo person[0] # "Peter"
echo person[1] # 30
# You don't need to declare tuples in a separate type section.
var building: tuple[street: string, number: int]
building = ("Rue del Percebe", 13)
echo building.street
# The following line does not compile, they are different tuples!
#person = building
# --> Error: type mismatch: got (tuple[street: string, number: int])
# but expected 'Person'
#Reference object
type
Node = ref object
le, ri: Node
data: int
var
n: Node
new(n)
n.data = 9
# no need to write n[].data; in fact n[].data is highly discouraged!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment