-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtutorial.rix
More file actions
231 lines (164 loc) · 7.2 KB
/
tutorial.rix
File metadata and controls
231 lines (164 loc) · 7.2 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# a hello world program:
prn "Hello, World!"
# you can print numbers as well
prn 51
# and also any other datatype
prn tru
# prn automatically adds a newline, but there are alternatives that don't
# this prints "this language: hopefully not broken"
wrt "this language: " prn "hopefully not broken"
# in the previous example, you see two statements on the same line. statements only end when the function gets all its arguments
# function calls always come before their arguments, and basic math operations are functions
prn + 1 4
# you can group the + 1 4 with parens for easier readablility. this does make a real difference in some cases, but we'll discuss that later
prn (+ 1 4)
# order of operations is irrelivent
# prints 22
prn + * 5 4 - 3 1
# although such examples will benefit from parens
prn + (* 5 4) (- 3 1)
# every function returns a value. prn returns the value it just printed
# should print:
# hello
# hello
prn (prn "hello")
# lists in rix are really important. this is their syntax. they can contain any other datatypes
[1 "potato" 3]
# variables can be declared using the following syntax. notice the final semicolon
foo: 5;
# functions are defined as follows. the first argument to the function 'fn' is a list of parameters, and the second argument is a list of code that will be run
test-function: fn [x] [+ x 1];
# should print 3
prn test-function 2
# functions preserve the state of the environment that they were created in
# remember the 'foo' value from the variable declaration section? at this point in the program, it's set to 5
test-function2: fn [x] [+ x foo];
# no matter what we set foo to be, test-function2 will always save the value 5 within it
foo: 6;
# prints 9
prn test-function2 4
# you can specifically prevent functions from saving the values of certain variables with the 'cloex' function
test-function3: cloex [foo] fn [x] [+ x foo];
# prints 10
prn test-function3 4
foo: 5;
# prints 9
prn test-function3 4
# names of things are values as well, and they can be accessed with 'symbolname syntax
# prints test-function3
prn 'test-function3
# the ' prefix is called a "quote" operator. they can be put on basically anything you'd like, and they stop the evaluation of the underlying value, allowing you to access it
# what if you want to get the value of a function without evaluating it? you can use $funcname syntax
# what this actually does is get the value associated with the name "test-function3" and stop evaluating it there
# prints fn [x] [+ x foo]
prn $test-function3
# the ` prefix is called the "quasiquote" operator. Here's how it works
# prints [1 2 5]
foo: 5;
prn `[1 2 ,foo]
# that was the unquote operator, and it's used to evaluate things within quasiquoted lists
# prints [1 2 6]
prn `[1 2 ,(+ foo 1)]
# you can also use the "splice" operator to do a similar thing, but if the expression you're evaluating returns a list, it's spliced into the parent list
# prints [1 2 1 2 5]
bar: `[1 2 ,foo];
prn `[1 2 @bar]
# prints [1 2 [1 2 5]]
prn `[1 2 ,bar]
# macros are functions that don't evaluate their input parameters
test-macro: mac [x] [prn (unlock x)];
# since macros often deal with inputs that can be accidentally evaluated, the inputs to a macro are "locked" by default, meaning that they cannot be evaluated
# unless you use the builtin 'unlock' function to unlock them
# prints 5
test-macro 5
# prints (+ 1 4) (instead of 5, since macros don't evaluate their inputs)
test-macro (+ 1 4)
# prints foo
test-macro foo
# macros are also unique in that their return values are appended onto the token list
test-macro2: mac [a] [`[,(unlock a) ,(unlock a)]];
# prints 6
prn (+ test-macro2 3)
# mac is itself a macro, and if its second input isn't a list, then it will be evaluated and then returned. This means you can drop the outer set of [] before test-macro2's definition
test-macro2: mac [a] `[,(unlock a) ,(unlock a)];
# hashtables are written like this. like lists, they can have any type for their keys and values
{{key1 "value"} {"key2" [value1 value2]}}
# they can also use quasiquotes and unquotes
hashtest: `{{key1 ,foo} {key2 ,bar}};
# prints {{key1 5} {key2 [1 2 5]}}
prn hashtest
# you can access values in a hashtable like so
# prints [1 2 5]
prn (at 'key2 hashtest)
# let is a function that takes in a hashtable and a list, and runs the code in that list with key-value pairs in the hashtable stored as variables
let {{potato 1} {foo 3}}
[
# prints [1 2 5 4]
prn '[@bar ,(+ potato foo)]
]
# the main type of conditional is if. it's just a function, with no special syntax, that takes in a bool and two lists
# prints "hello"
if (> foo 4)
[
prn "hello"
]
[
prn "goodbye"
]
# prints "goodbye"
if (> foo 5)
[
prn "hello"
]
[
prn "goodbye"
]
# if is also an expression
# prints 1
prn (if (> foo 4) [1] [2])
# let's include the library macs
incl macs
# libraries are included with the macro incl
# macs defines some useful macros, as well as other things that aren't quite macros, but are similarly useful
# here's the function pass
foo-function: fn [x y z] [+ x (- y z)];
# prints 6
prn (foo-function 5 4 3)
# prints 6
x: 5;
y: 4;
z: 3;
prn (pass $foo-function)
# let's look at the definition of pass. it contains plenty of stuff we haven't seen yet
exp pass: desc "passes parameters into a function. the parameters are assumed to exist, so you can pass local variables directly into a function" typreq [typ func] fn [func]
[
tapp `[,$func @(fparams $func)]
];
# exp exports a definition, meaning that when you use 'incl' on this file, you get access to this definition
# desc adds a description to a value. you can use the builtin 'pdesc' function to print the description of a value. This is useful for when you don't know what a function does
# typreq is a function that takes in a list of the types of a function's parameters, and checks if the function is called with those types at runtime
# types are defined with 'typ <typename>'. 'typ func' is the type of a function.
# Most types are what you'd expect them to be (you can use gettyp <value> to get the actual type). The special types 'typ any' and 'typ callable' are useful. 'typ any' matches any value,
# and 'typ callable' matches anything you can call like a function
# tapp appends the following list to the token list, effectively meaning that it will be evaluated right after pass is done evaluating
# fparams gets the parameters of a function as a list of symbols.
# to summarize how 'pass' works, it appends a list of tokens to the token list. That list contains the function input, and that function's parameters, concatinated into the main list
# so, pass $foo-function generates the code foo-function x y z
# prints the description of pass
pdesc $pass
# prints 'typ func'
prn (gettyp $pass)
# in the above section, we just redefined the function pass. In order to access the original function imported from macs, we use
prn (pass@macs $foo-function)
# struct is a very useful macro found in macs
# defines a function new-person that takes in a name and age, and produces a value of type "person", which is really just a relabeled hashtable
struct person [name age]
jeff: new-person "Jeff" 32;
# prints 'typ person'
prn (gettyp jeff)
# prints 32
prn (at 'age jeff)
# to explain:
# generics
# custom evaluation
# continuations