-
Notifications
You must be signed in to change notification settings - Fork 81
/
declare.zy
113 lines (90 loc) · 3.86 KB
/
declare.zy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// declare structs
//
// and then have the struct definition enforced during type-checking
// of assignments.
(struct Car [
(field Id: int64 e:0 gotags:`json:"id",name:"id"`)
(field Name: string e:1 gotags:`json:"name"`)
(field BadApple: string e:2 deprecated:true)
])
// structs can be redefined at the repl
(struct Car [
(field Id: int64 e:0 gotags:`json:"id",name:"id"` )
(field Name: string e:1 gotags:`json:"name"` )
(field BadApple: string e:2 deprecated:true )
(field SliceOfLife: ([]string) e:3 ) // slice of string, matching Go's syntax.
(field PointerSisters: (* int64) e:4 ) // a pointer to an int64
(field OtherCar: (* Car) e:5 ) // a pointer to a Car struct
])
(def p (Car Id: 99912))
(def r (Car OtherCar: (& p))) // & is the address-of operator, like in Go/C.
(assert (==
(* (& p)) // * is the dereference operator, the opposite of &, like in Go/C.
p // Notice how * and & cancel out, leaving us with p again.
)
)
(def p1 (& p)) // (& p) takes the address of the object that p evaluates to;
(def p2 (& p)) // since & is a normal function, the resulting pointer points to the
// (Car Id: 99912) object, not to p itself.
(assert (== p1 p2)) // hence two pointers to the same underlying object are equal.
(def car2 (Car Id: 7))
(assert (!= (& car2) p1))
(assert (!= (& car2) p2))
// declare a pointer without binding it; it will default to nil (The zero type, as in Go).
(var a (* Car))
(expectError "Error calling ':': Error calling '*': illegal to dereference nil pointer" (assert (== (:Id (* a)) 0)))
(assert (== (type? a) "*Car"))
(a = (& p)) // once assigned...
(assert (== (:Id (* a)) 99912)) // then a can be used.
// structs can be changed in type-safe ways
// First lets make a Car struct, using the already declared Car type.
{hasSlice = (Car SliceOfLife: ["hi" "there"])}
(assert (== (:SliceOfLife hasSlice) ["hi" "there"]))
(assert (== 2 (len hasSlice.SliceOfLife)))
// then lets change the struct
{hasSlice.SliceOfLife = ["zygo" "rocks" "it"]}
(assert (== 3 (len hasSlice.SliceOfLife)))
// if we try to update a non-existant field (good for catching typos), we cannot:
(expectError `Error calling 'infix': Car has no field 'NewField' [err 2]`
{hasSlice.NewField = "wacky"})
// and the declared types must be matched.
(expectError `Error calling 'infix': field Car.SliceOfLife is ([]string), cannot assign ([]int64) '[1 2 3]'`
{hasSlice.SliceOfLife = [1 2 3]})
// nil for slices and pointers should be okay
(Car SliceOfLife:nil)
(Car OtherCar:nil)
// assignment of [] (the empty slice) should also work
{hasSlice.SliceOfLife = []}
(assert (== 0 (len hasSlice.SliceOfLife)))
// we can point to ourselves if need be.
(def w (Car Name: "Willow"))
{w.OtherCar = (& w)}
(assert (== (& w) (:OtherCar w)))
// or with dot symbol notation:
(assert (== (& w) w.OtherCar))
// binding time for type should be the most recent definition in force.
(struct Dog [(field tag: int64)])
(def d (Dog))
(struct Dog [(field big: bool)])
(def e (Dog))
{d.tag = 12}
{e.big = true}
(expectError `Error calling 'infix': Dog has no field 'tag' [err 2]` {e.tag = 445})
(expectError `Error calling 'infix': Dog has no field 'big' [err 2]` {d.big = true})
// How to declare functions that are type checked, use func:
//
// we'll always use named return types; so we can
// have an implicit return; this facilitates automatic compile-down.
//
(func doSomething [a:int b:string] [n:int err:error]
(return a nil))
//
// And here is how to declare interfaces:
//
(interface Drivable [
(func driveIt [a:int b:string] [n:int err:error])
])
//
// declare methods like this:
//
(method [p: (* Car)] driveIt [a:int b:string] [n:int err:error])