]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - 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
diff --git a/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.02 Language basics.md b/bundles/org.simantics.scl.tutorial/scl/Tutorial/1.02 Language basics.md
new file mode 100644 (file)
index 0000000..82e575c
--- /dev/null
@@ -0,0 +1,357 @@
+# Language basics\r
+\r
+SCL is a functional programming language that is based on [lambda calculus]. \r
+Lambda calculus is a minimal but still Turing complete language with three\r
+constructions:\r
+* *Variables*\r
+* *Function applications*\r
+* *Function definitions* (lambda terms)\r
+\r
+These are also the most central elements of SCL and most of the other constructions are only\r
+syntactic sugar on top of lambda calculus.\r
+\r
+SCL syntax is very close to the syntax of [Haskell] programming language and many tutorials\r
+on Haskell apply also to SCL. The main difference between the languages is the evaluation strategy:\r
+Haskell evaluates terms lazily, SCL strictly. Unlike Haskell, SCL allows side-effects during\r
+function application, but controls them with effect typing. In this respects, it behaves similarly\r
+to [ML] or [OCaml].\r
+\r
+SCL inherits the following philosophy from Haskell and other programming languages in functional paradigm: \r
+* Avoid stateful programming \r
+* Express mathematical problems in mathematical syntax\r
+* Expressive types prevent runtime errors\r
+\r
+[lambda calculus]: http://en.wikipedia.org/wiki/Lambda_calculus\r
+[Haskell]: https://www.haskell.org/\r
+[ML]: http://en.wikipedia.org/wiki/ML_(programming_language)\r
+[OCaml]: https://ocaml.org/\r
+\r
+This section gives a walkthrough for the most importatant constructs of SCL language.\r
+\r
+## Literals\r
+\r
+SCL supports the following types of constant expressions: \r
+\r
+**Integers**\r
+\r
+    3423\r
+    \r
+**Floating point numbers**\r
+    \r
+    1.2\r
+    2.6e-4\r
+    \r
+**String literals**\r
+\r
+SCL supports single-line strings (enclosed in quotes) \r
+\r
+    "Single line text"\r
+    "Text\nwith\nmultiple lines"\r
+\r
+and multi-line strings (enclosed in triple quotes)\r
+\r
+    """Text\r
+    with\r
+    multiple lines"""\r
+\r
+Single-line strings may contain escaped characters (`\n` line feed, `\t` tabulator, `\r` carriage return, `\uxxxx` unicode character,\r
+`\<character>` the character without the first `\`).\r
+    \r
+**Character literals**\r
+\r
+    't'\r
+    '\''\r
+    \r
+**Boolean constants** are written as `True` and `False` although they are not technically literals (but constructors).\r
+\r
+## Identifiers\r
+\r
+Variable and constant names start with lower case letter followed by letters, digits, `_` and `'`.\r
+It customary to write multi-word concepts with camel case convention, for example\r
+`printError` or `importA5Model`.\r
+\r
+The following names are reserved and cannot be used as identifiers:\r
+`as`, `by`, `class`, `data`, `deriving`, `do`, `effect`, `else`, `enforce`, `extends`, `forall`, `hiding`, `if`,\r
+`import`, `importJava`, `in`, `include`, `infix`, `infixl`, `infixr`, `instance`, `let`, `match`, `mdo`, `rule`,\r
+`select`, `then`, `transformation`, `type`, `when`, `where`, `with`.\r
+\r
+Identifiers starting with upper case letter are *constructors* and they can be defined only\r
+together with the new data types. Examples: `True`, `False` and `Nothing`.\r
+\r
+## Function applications\r
+\r
+A function is applied by writing the function and its parameters consecutively.\r
+\r
+    sin pi\r
+    max 2 5\r
+\r
+A parameter needs to be closed in parenthesis if it is not a variable, literal, or an expression starting\r
+with `if`, `let`, `do`, etc. \r
+\r
+    sqrt (x*x + y*y)\r
+    atan2 (sin a) (cos a)\r
+\r
+For example\r
+\r
+    sqrt x*x + y*y\r
+    \r
+is evaluated as\r
+\r
+    (sqrt x)*x + y*y\r
+\r
+because the function application has higher precedence than\r
+any binary operator.\r
+Parentheses are also needed around negation\r
+\r
+    sin (-1.42)\r
+\r
+because otherwise the expression is tried to compile as\r
+\r
+    sin - 1.42\r
+\r
+causing a compilation error because `sin` and `1.42` are not\r
+compatible for subtraction.\r
+\r
+## Binary operators\r
+\r
+Binary operators are normal functions that are just written between their parameters:\r
+\r
+    1 + 2\r
+\r
+Each binary operator can be converted into ordinary function by putting parentheses around it\r
+\r
+    (+) 1 2\r
+\r
+Similarly an ordinary function can be converted into binary operator by putting backticks (\`) around it.\r
+\r
+    3.4 `max` 4.5\r
+    \r
+Binary operators have precedences that determines how multiple consecutive binary operators\r
+are compiled. For example\r
+\r
+    1*2+3*4+5*6\r
+   \r
+is evaluated as\r
+\r
+    ((1*2) + (3*4)) + (5*6)\r
+\r
+## Variable definitions\r
+\r
+Variables are defined by syntax\r
+\r
+    variableName = variableValue\r
+\r
+for example\r
+\r
+    g = 9.80665\r
+\r
+Defined variable values are available in the\r
+consecutive expressions:\r
+\r
+    a = 13\r
+    b = 14\r
+    a*b\r
+\r
+## Function definitions\r
+\r
+Functions are defined by writing a function application\r
+in the left-hand side of the equation:\r
+\r
+    increaseByOne x = x+1\r
+    \r
+Defined functions are available in the consecutive expressions:\r
+\r
+    increaseByOne 13\r
+\r
+## Conditional expressions\r
+\r
+Conditional expressions are written in the form:\r
+\r
+    if <condition> then <successBranch> else <failureBranch>\r
+    \r
+The `else` branch is always mandatory.\r
+\r
+    abs x = if x > 0\r
+            then x\r
+            else -x\r
+\r
+## Recursion\r
+\r
+A function definition can refer to itself. For example, the Euclidean algorithm for\r
+computing the greatest common divisor of two integers can be written as:\r
+\r
+    gcd a b = if a > b\r
+              then gcd b a\r
+              else if a == 0\r
+              then b\r
+              else gcd (b `mod` a) a\r
+\r
+## Local definitions\r
+\r
+Variable and function definitions can be written as a part of larger\r
+expression. There are three language constructs for this purpose:\r
+\r
+    let <definitions> in <result>\r
+    \r
+    do <definitions> \r
+       <result>\r
+       \r
+    <definition> where <definitions>\r
+\r
+They are quite similar and\r
+it is usually just a stylistic choice which one to use.\r
+\r
+If you are only defining local variables that are needed in a subexpression\r
+and their computation does not have side-effects (or has only reading effects),\r
+the most natural choice is `let`-construct that allows you to define\r
+variables between `let` and `in` and used the variables in the expression following `in`:\r
+\r
+~~~\r
+distance (x1,y1) (x2,y2) = let dx = x1-x2\r
+                               dy = y1-y2\r
+                           in sqrt (dx*dx + dy*dy) \r
+~~~\r
+\r
+Let-expressions can be freely embedded in other expressions:\r
+\r
+~~~\r
+"""\r
+Finds a root of f given neg and pos with assumption that\r
+   f neg < 0\r
+and\r
+   f pos > 0 \r
+""" \r
+bisectionMethod f neg pos =\r
+  let middle = (neg+pos)*0.5 in\r
+    if abs (neg-pos) < 1e-9\r
+    then middle\r
+    else let middleVal = f middle in\r
+      if middleVal < (-1e-9)\r
+      then bisectionMethod f middle pos\r
+      else if middleVal > 1e-9\r
+      then bisectionMethod f neg middle\r
+      else middle\r
+~~~\r
+\r
+Another construction allowing local variable bindings is `do`. The value of the whole\r
+`do`-expression is determined by the last expression in the `do`-block. This construct\r
+should be used when there are side-effects involved and you want to mix variable bindings\r
+with function applications that ignore their result:\r
+\r
+~~~\r
+createModel parent name = do\r
+    model = newResource ()\r
+    claim model L0.InstanceOf SIMU.Model\r
+    claimRelatedValue model L0.HasName name\r
+    claim model L0.PartOf parent\r
+    model\r
+~~~\r
+\r
+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
+it does not define an expression but is always related to some other definition.\r
+The benefit is that the same `where` -block can be used by multiple\r
+different guarded definitions:  \r
+\r
+~~~\r
+"""\r
+Returns all solutions of the quadratic equation a*x^2 + b*x + c = 0.\r
+"""\r
+solveQuadratic :: Double -> Double -> Double -> [Double]\r
+solveQuadratic a b c\r
+    | discriminant < 0 = []\r
+    | discriminant > 0 = let sqrtDisc = sqrt discriminant\r
+                         in [ (-b-sqrtDisc)/(2*a)\r
+                            , (-b+sqrtDisc)/(2*a) ]\r
+    | otherwise        = [ -b / (2*a) ]\r
+  where\r
+    discriminant = b*b - 4*a*c\r
+~~~\r
+\r
+\r
+## Functions taking other functions as parameters\r
+\r
+In SCL, functions are ordinary values that can be stored to variables and manipulated.\r
+For example, writing only the function name to the console produces:\r
+\r
+    > sin\r
+    <value of type Double -> <a> Double> \r
+\r
+We can define for example a numerical derivative operation\r
+\r
+    epsilon = 1e-9\r
+    der f x = (f (x + epsilon) - f (x - epsilon)) / (2*epsilon)\r
+    \r
+Now,\r
+    \r
+    > der sin 0\r
+    1.0\r
+    > der exp 1\r
+    2.7182818218562943\r
+\r
+## Anonymous function definitions\r
+\r
+Functional style of programming favors lots of small functions.\r
+Giving a name for all of them becomes quickly tedious and\r
+therefore functions can be defined also anonymously. For\r
+example \r
+\r
+    \x -> x+1\r
+\r
+defines a function that increases its parameter by one.\r
+Thus\r
+\r
+    (\x -> x+1) 13\r
+    \r
+returns `14`.\r
+\r
+Assuming that the function `der` is defined as above\r
+\r
+    > der (\x -> x*x) 2\r
+    4.000000330961484 \r
+\r
+## Partial function application\r
+\r
+It is possible to give a function less parameters that\r
+it accepts:\r
+\r
+    > der sin\r
+    <value of type Double -> <a> Double>\r
+    \r
+Such a partial application creates a function that expects\r
+the missing parameters:\r
+\r
+    > myCos = der sin\r
+    > myCos 0\r
+    > myCos pi\r
+    -1.000000082740371\r
+\r
+It is possible to partially apply also binary operators giving\r
+only one of its parameters. Such an application must always\r
+be enclosed in parentheses\r
+    \r
+    lessThanOne = (< 1)\r
+    greaterThanOne = (1 <)\r
+\r
+## Pattern matching\r
+\r
+The constructors are special kind of values and functions\r
+that can be used in the left-hand side of the function and\r
+value definitions. Most common constructors are\r
+the tuple constructors `()`, `(,)`, `(,,)`, ...:  \r
+\r
+    toPolarCoordinates (x,y) = (sqrt (x*x + y*y), atan2 y x)\r
+    toRectangularCoordinates (r,angle) = (r*cos angle, r*sin angle)\r
+\r
+Other constructors are used like functions, but the name\r
+of the constructor is capitalized, for example `Just` and `Nothing`:\r
+\r
+    fromMaybe _       (Just v) = v\r
+    fromMaybe default Nothing  = default\r
+    \r
+This example demonstrates also some other features. A function \r
+can be defined with multiple equations and the first matching\r
+equation is used. Also, if some parameter value is not used,\r
+it may be replaced by `_`.\r
+\r
+## Indentation\r
+\r