]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.tutorial/scl/Tutorial/1.02 Language basics.md
Import org.simantics.scl.tutorial from incubator SVN repo
[simantics/platform.git] / bundles / org.simantics.scl.tutorial / scl / Tutorial / 1.02 Language basics.md
1 # Language basics\r
2 \r
3 SCL is a functional programming language that is based on [lambda calculus]. \r
4 Lambda calculus is a minimal but still Turing complete language with three\r
5 constructions:\r
6 * *Variables*\r
7 * *Function applications*\r
8 * *Function definitions* (lambda terms)\r
9 \r
10 These are also the most central elements of SCL and most of the other constructions are only\r
11 syntactic sugar on top of lambda calculus.\r
12 \r
13 SCL syntax is very close to the syntax of [Haskell] programming language and many tutorials\r
14 on Haskell apply also to SCL. The main difference between the languages is the evaluation strategy:\r
15 Haskell evaluates terms lazily, SCL strictly. Unlike Haskell, SCL allows side-effects during\r
16 function application, but controls them with effect typing. In this respects, it behaves similarly\r
17 to [ML] or [OCaml].\r
18 \r
19 SCL inherits the following philosophy from Haskell and other programming languages in functional paradigm: \r
20 * Avoid stateful programming \r
21 * Express mathematical problems in mathematical syntax\r
22 * Expressive types prevent runtime errors\r
23 \r
24 [lambda calculus]: http://en.wikipedia.org/wiki/Lambda_calculus\r
25 [Haskell]: https://www.haskell.org/\r
26 [ML]: http://en.wikipedia.org/wiki/ML_(programming_language)\r
27 [OCaml]: https://ocaml.org/\r
28 \r
29 This section gives a walkthrough for the most importatant constructs of SCL language.\r
30 \r
31 ## Literals\r
32 \r
33 SCL supports the following types of constant expressions: \r
34 \r
35 **Integers**\r
36 \r
37     3423\r
38     \r
39 **Floating point numbers**\r
40     \r
41     1.2\r
42     2.6e-4\r
43     \r
44 **String literals**\r
45 \r
46 SCL supports single-line strings (enclosed in quotes) \r
47 \r
48     "Single line text"\r
49     "Text\nwith\nmultiple lines"\r
50 \r
51 and multi-line strings (enclosed in triple quotes)\r
52 \r
53     """Text\r
54     with\r
55     multiple lines"""\r
56 \r
57 Single-line strings may contain escaped characters (`\n` line feed, `\t` tabulator, `\r` carriage return, `\uxxxx` unicode character,\r
58 `\<character>` the character without the first `\`).\r
59     \r
60 **Character literals**\r
61 \r
62     't'\r
63     '\''\r
64     \r
65 **Boolean constants** are written as `True` and `False` although they are not technically literals (but constructors).\r
66 \r
67 ## Identifiers\r
68 \r
69 Variable and constant names start with lower case letter followed by letters, digits, `_` and `'`.\r
70 It customary to write multi-word concepts with camel case convention, for example\r
71 `printError` or `importA5Model`.\r
72 \r
73 The following names are reserved and cannot be used as identifiers:\r
74 `as`, `by`, `class`, `data`, `deriving`, `do`, `effect`, `else`, `enforce`, `extends`, `forall`, `hiding`, `if`,\r
75 `import`, `importJava`, `in`, `include`, `infix`, `infixl`, `infixr`, `instance`, `let`, `match`, `mdo`, `rule`,\r
76 `select`, `then`, `transformation`, `type`, `when`, `where`, `with`.\r
77 \r
78 Identifiers starting with upper case letter are *constructors* and they can be defined only\r
79 together with the new data types. Examples: `True`, `False` and `Nothing`.\r
80 \r
81 ## Function applications\r
82 \r
83 A function is applied by writing the function and its parameters consecutively.\r
84 \r
85     sin pi\r
86     max 2 5\r
87 \r
88 A parameter needs to be closed in parenthesis if it is not a variable, literal, or an expression starting\r
89 with `if`, `let`, `do`, etc. \r
90 \r
91     sqrt (x*x + y*y)\r
92     atan2 (sin a) (cos a)\r
93 \r
94 For example\r
95 \r
96     sqrt x*x + y*y\r
97     \r
98 is evaluated as\r
99 \r
100     (sqrt x)*x + y*y\r
101 \r
102 because the function application has higher precedence than\r
103 any binary operator.\r
104 Parentheses are also needed around negation\r
105 \r
106     sin (-1.42)\r
107 \r
108 because otherwise the expression is tried to compile as\r
109 \r
110     sin - 1.42\r
111 \r
112 causing a compilation error because `sin` and `1.42` are not\r
113 compatible for subtraction.\r
114 \r
115 ## Binary operators\r
116 \r
117 Binary operators are normal functions that are just written between their parameters:\r
118 \r
119     1 + 2\r
120 \r
121 Each binary operator can be converted into ordinary function by putting parentheses around it\r
122 \r
123     (+) 1 2\r
124 \r
125 Similarly an ordinary function can be converted into binary operator by putting backticks (\`) around it.\r
126 \r
127     3.4 `max` 4.5\r
128     \r
129 Binary operators have precedences that determines how multiple consecutive binary operators\r
130 are compiled. For example\r
131 \r
132     1*2+3*4+5*6\r
133    \r
134 is evaluated as\r
135 \r
136     ((1*2) + (3*4)) + (5*6)\r
137 \r
138 ## Variable definitions\r
139 \r
140 Variables are defined by syntax\r
141 \r
142     variableName = variableValue\r
143 \r
144 for example\r
145 \r
146     g = 9.80665\r
147 \r
148 Defined variable values are available in the\r
149 consecutive expressions:\r
150 \r
151     a = 13\r
152     b = 14\r
153     a*b\r
154 \r
155 ## Function definitions\r
156 \r
157 Functions are defined by writing a function application\r
158 in the left-hand side of the equation:\r
159 \r
160     increaseByOne x = x+1\r
161     \r
162 Defined functions are available in the consecutive expressions:\r
163 \r
164     increaseByOne 13\r
165 \r
166 ## Conditional expressions\r
167 \r
168 Conditional expressions are written in the form:\r
169 \r
170     if <condition> then <successBranch> else <failureBranch>\r
171     \r
172 The `else` branch is always mandatory.\r
173 \r
174     abs x = if x > 0\r
175             then x\r
176             else -x\r
177 \r
178 ## Recursion\r
179 \r
180 A function definition can refer to itself. For example, the Euclidean algorithm for\r
181 computing the greatest common divisor of two integers can be written as:\r
182 \r
183     gcd a b = if a > b\r
184               then gcd b a\r
185               else if a == 0\r
186               then b\r
187               else gcd (b `mod` a) a\r
188 \r
189 ## Local definitions\r
190 \r
191 Variable and function definitions can be written as a part of larger\r
192 expression. There are three language constructs for this purpose:\r
193 \r
194     let <definitions> in <result>\r
195     \r
196     do <definitions> \r
197        <result>\r
198        \r
199     <definition> where <definitions>\r
200 \r
201 They are quite similar and\r
202 it is usually just a stylistic choice which one to use.\r
203 \r
204 If you are only defining local variables that are needed in a subexpression\r
205 and their computation does not have side-effects (or has only reading effects),\r
206 the most natural choice is `let`-construct that allows you to define\r
207 variables between `let` and `in` and used the variables in the expression following `in`:\r
208 \r
209 ~~~\r
210 distance (x1,y1) (x2,y2) = let dx = x1-x2\r
211                                dy = y1-y2\r
212                            in sqrt (dx*dx + dy*dy) \r
213 ~~~\r
214 \r
215 Let-expressions can be freely embedded in other expressions:\r
216 \r
217 ~~~\r
218 """\r
219 Finds a root of f given neg and pos with assumption that\r
220    f neg < 0\r
221 and\r
222    f pos > 0 \r
223 """ \r
224 bisectionMethod f neg pos =\r
225   let middle = (neg+pos)*0.5 in\r
226     if abs (neg-pos) < 1e-9\r
227     then middle\r
228     else let middleVal = f middle in\r
229       if middleVal < (-1e-9)\r
230       then bisectionMethod f middle pos\r
231       else if middleVal > 1e-9\r
232       then bisectionMethod f neg middle\r
233       else middle\r
234 ~~~\r
235 \r
236 Another construction allowing local variable bindings is `do`. The value of the whole\r
237 `do`-expression is determined by the last expression in the `do`-block. This construct\r
238 should be used when there are side-effects involved and you want to mix variable bindings\r
239 with function applications that ignore their result:\r
240 \r
241 ~~~\r
242 createModel parent name = do\r
243     model = newResource ()\r
244     claim model L0.InstanceOf SIMU.Model\r
245     claimRelatedValue model L0.HasName name\r
246     claim model L0.PartOf parent\r
247     model\r
248 ~~~\r
249 \r
250 The final binding construction is `where` that locates variable definitions after the position the variables are used. It differs from `let` and `do` because\r
251 it does not define an expression but is always related to some other definition.\r
252 The benefit is that the same `where` -block can be used by multiple\r
253 different guarded definitions:  \r
254 \r
255 ~~~\r
256 """\r
257 Returns all solutions of the quadratic equation a*x^2 + b*x + c = 0.\r
258 """\r
259 solveQuadratic :: Double -> Double -> Double -> [Double]\r
260 solveQuadratic a b c\r
261     | discriminant < 0 = []\r
262     | discriminant > 0 = let sqrtDisc = sqrt discriminant\r
263                          in [ (-b-sqrtDisc)/(2*a)\r
264                             , (-b+sqrtDisc)/(2*a) ]\r
265     | otherwise        = [ -b / (2*a) ]\r
266   where\r
267     discriminant = b*b - 4*a*c\r
268 ~~~\r
269 \r
270 \r
271 ## Functions taking other functions as parameters\r
272 \r
273 In SCL, functions are ordinary values that can be stored to variables and manipulated.\r
274 For example, writing only the function name to the console produces:\r
275 \r
276     > sin\r
277     <value of type Double -> <a> Double> \r
278 \r
279 We can define for example a numerical derivative operation\r
280 \r
281     epsilon = 1e-9\r
282     der f x = (f (x + epsilon) - f (x - epsilon)) / (2*epsilon)\r
283     \r
284 Now,\r
285     \r
286     > der sin 0\r
287     1.0\r
288     > der exp 1\r
289     2.7182818218562943\r
290 \r
291 ## Anonymous function definitions\r
292 \r
293 Functional style of programming favors lots of small functions.\r
294 Giving a name for all of them becomes quickly tedious and\r
295 therefore functions can be defined also anonymously. For\r
296 example \r
297 \r
298     \x -> x+1\r
299 \r
300 defines a function that increases its parameter by one.\r
301 Thus\r
302 \r
303     (\x -> x+1) 13\r
304     \r
305 returns `14`.\r
306 \r
307 Assuming that the function `der` is defined as above\r
308 \r
309     > der (\x -> x*x) 2\r
310     4.000000330961484 \r
311 \r
312 ## Partial function application\r
313 \r
314 It is possible to give a function less parameters that\r
315 it accepts:\r
316 \r
317     > der sin\r
318     <value of type Double -> <a> Double>\r
319     \r
320 Such a partial application creates a function that expects\r
321 the missing parameters:\r
322 \r
323     > myCos = der sin\r
324     > myCos 0\r
325     > myCos pi\r
326     -1.000000082740371\r
327 \r
328 It is possible to partially apply also binary operators giving\r
329 only one of its parameters. Such an application must always\r
330 be enclosed in parentheses\r
331     \r
332     lessThanOne = (< 1)\r
333     greaterThanOne = (1 <)\r
334 \r
335 ## Pattern matching\r
336 \r
337 The constructors are special kind of values and functions\r
338 that can be used in the left-hand side of the function and\r
339 value definitions. Most common constructors are\r
340 the tuple constructors `()`, `(,)`, `(,,)`, ...:  \r
341 \r
342     toPolarCoordinates (x,y) = (sqrt (x*x + y*y), atan2 y x)\r
343     toRectangularCoordinates (r,angle) = (r*cos angle, r*sin angle)\r
344 \r
345 Other constructors are used like functions, but the name\r
346 of the constructor is capitalized, for example `Just` and `Nothing`:\r
347 \r
348     fromMaybe _       (Just v) = v\r
349     fromMaybe default Nothing  = default\r
350     \r
351 This example demonstrates also some other features. A function \r
352 can be defined with multiple equations and the first matching\r
353 equation is used. Also, if some parameter value is not used,\r
354 it may be replaced by `_`.\r
355 \r
356 ## Indentation\r
357 \r