1# Comments start with a '#'
2# All comments encompass a single line
3
4###########################################
5## 1. Primitive Data types and Operators
6###########################################
7
8# You have numbers
93. # 3
10
11# Numbers are all doubles in interpreted mode
12
13# Mathematical operator precedence is not respected.
14# binary 'operators' are evaluated in ltr order
151 + 1. # 2
168 - 4. # 4
1710 + 2 * 3. # 36
18
19# Division is always floating division
2035 / 2 # 17.5.
21
22# Integer division is non-trivial, you may use floor
23(35 / 2) floor # 17.
24
25# Booleans are primitives
26True.
27False.
28
29# Boolean messages
30True not. # False
31False not. # True
321 = 1. # True
331 !=: 1. # False
341 < 10. # True
35
36# Here, `not` is a unary message to the object `Boolean`
37# Messages are comparable to instance method calls
38# And they have three different forms:
39# 1. Unary messages: Length > 1, and they take no arguments:
40 False not.
41# 2. Binary Messages: Length = 1, and they take a single argument:
42 False & True.
43# 3. Keyword messages: must have at least one ':', they take as many arguments
44# as they have `:` s
45 False either: 1 or: 2. # 2
46
47# Strings
48'This is a string'.
49'There are no character types exposed to the user'.
50# "You cannot use double quotes for strings" <- Error
51
52# Strins can be summed
53'Hello, ' + 'World!'. # 'Hello, World!'
54
55# Strings allow access to their characters
56'This is a beautiful string' at: 0. # 'T'
57
58###########################################
59## intermission: Basic Assignment
60###########################################
61
62# You may assign values to the current scope:
63var name is value. # assigns `value` into `name`
64
65# You may also assign values into the current object's namespace
66my name is value. # assigns `value` into the current object's `name` property
67
68# Please note that these names are checked at compile (read parse if in interpreted mode) time
69# but you may treat them as dynamic assignments anyway
70
71###########################################
72## 2. Lists(Arrays?) and Tuples
73###########################################
74
75# Arrays are allowed to have multiple types
76Array new < 1 ; 2 ; 'string' ; Nil. # Array new < 1 ; 2 ; 'string' ; Nil
77
78# Tuples act like arrays, but are immutable.
79# Any shenanigans degrade them to arrays, however
80[1, 2, 'string']. # [1, 2, 'string']
81
82# They can interoperate with arrays
83[1, 'string'] + (Array new < 'wat'). # Array new < 1 ; 'string' ; 'wat'
84
85# Indexing into them
86[1, 2, 3] at: 1. # 2
87
88# Some array operations
89var arr is Array new < 1 ; 2 ; 3.
90
91arr head. # 1
92arr tail. # Array new < 2 ; 3.
93arr init. # Array new < 1 ; 2.
94arr last. # 3
95arr push: 4. # Array new < 1 ; 2 ; 3 ; 4.
96arr pop. # 4
97arr pop: 1. # 2, `arr` is rebound to Array new < 1 ; 3.
98
99# List comprehensions
100[x * 2 + y,, arr, arr + [4, 5],, x > 1]. # Array ← 7 ; 9 ; 10 ; 11
101# fresh variable names are bound as they are encountered,
102# so `x` is bound to the values in `arr`
103# and `y` is bound to the values in `arr + [4, 5]`
104#
105# The general format is: [expr,, bindings*,, predicates*]
106
107
108####################################
109## 3. Functions
110####################################
111
112# A simple function that takes two variables
113var add is {:a:b ^a + b.}.
114
115# this function will resolve all its names except the formal arguments
116# in the context it is called in.
117
118# Using the function
119add applyTo: 3 and: 5. # 8
120add applyAll: [3, 5]. # 8
121
122# Also a (customizable -- more on this later) pseudo-operator allows for a shorthand
123# of function calls
124# By default it is REF[args]
125
126add[3, 5]. # 8
127
128# To customize this behaviour, you may simply use a compiler pragma:
129#:callShorthand ()
130
131# And then you may use the specified operator.
132# Note that the allowed 'operator' can only be made of any of these: []{}()
133# And you may mix-and-match (why would anyone do that?)
134
135add(3, 5). # 8
136
137# You may also use functions as operators in the following way:
138
1393 `add` 5. # 8
140# This call binds as such: add[(3), 5]
141# because the default fixity is left, and the default precedence is 1
142
143# You may change the precedence/fixity of this operator with a pragma
144#:declare infixr 1 add
145
1463 `add` 5. # 8
147# now this binds as such: add[3, (5)].
148
149# There is another form of functions too
150# So far, the functions were resolved in a dynamic fashion
151# But a lexically scoped block is also possible
152var sillyAdd is {\:x:y add[x,y].}.
153
154# In these blocks, you are not allowed to declare new variables
155# Except with the use of Object::'letEqual:in:`
156# And the last expression is implicitly returned.
157
158# You may also use a shorthand for lambda expressions
159var mul is \:x:y x * y.
160
161# These capture the named bindings that are not present in their
162# formal parameters, and retain them. (by ref)
163
164###########################################
165## 5. Control Flow
166###########################################
167
168# inline conditional-expressions
169var citron is 1 = 1 either: 'awesome' or: 'awful'. # citron is 'awesome'
170
171# multiple lines is fine too
172var citron is 1 = 1
173 either: 'awesome'
174 or: 'awful'.
175
176# looping
17710 times: {:x
178 Pen writeln: x.
179}. # 10. -- side effect: 10 lines in stdout, with numbers 0 through 9 in them
180
181# Citron properly supports tail-call recursion in lexically scoped blocks
182# So use those to your heart's desire
183
184# mapping most data structures is as simple as `fmap:`
185[1, 2, 3, 4] fmap: \:x x + 1. # [2, 3, 4, 5]
186
187# You can use `foldl:accumulator:` to fold a list/tuple
188[1, 2, 3, 4] foldl: (\:acc:x acc * 2 + x) accumulator: 4. # 90
189
190# That expression is the same as
191(2 * (2 * (2 * (2 * 4 + 1) + 2) + 3) + 4)
192
193###################################
194## 6. IO
195###################################
196
197# IO is quite simple
198# With `Pen` being used for console output
199# and Program::'input' and Program::'waitForInput' being used for console input
200
201Pen writeln: 'Hello, ocean!' # prints 'Hello, ocean!\n' to the terminal
202
203Pen writeln: Program waitForInput. # reads a line and prints it back