Carp/docs/LanguageGuide.md

155 lines
4.7 KiB
Markdown
Raw Normal View History

2017-06-26 12:45:18 +03:00
## The Language
2017-06-26 16:58:23 +03:00
### Introduction
2017-06-26 16:50:51 +03:00
Carp borrows its looks from Clojure but the runtime semantics are much closer to those of ML or Rust.
Types are inferred but can be annoted for readability using the ```the``` keyword (see below).
2017-06-26 12:45:18 +03:00
2017-06-26 16:58:23 +03:00
Memory management is handled by static analysis, a value is owned by the function where it was created.
When a value is returned or passed to another function the initial function will give up ownership of it
and any subsequent use will lead to a compiler error. To temporarily lend a value to another function
(i.e. to print it) a reference must be created, using the ```ref``` special form (or the ```&``` reader macro).
2017-06-26 17:09:12 +03:00
### Comments
```
;; Comments begin with semi-colon and continue until the end of the line.
```
2017-06-26 12:45:18 +03:00
### Data Literals
2017-06-26 16:50:51 +03:00
```
2017-06-26 17:09:12 +03:00
100 ;; Int
3.14f ;; Float
10.0 ;; Double
true ;; Bool
"hello" ;; String
\e ;; Char
[1 2 3] ;; (Array Int)
2017-06-26 12:45:18 +03:00
```
2017-06-26 17:12:41 +03:00
### Type Literals
```
t ;; Type variables begin with a lowercase letter
Int
Float
Double
Bool
String
Char
(Array t)
(Fn [<arg-type1> <arg-type2> ...] <return-type>) ;; Function type
```
2017-06-26 12:45:18 +03:00
### Dynamic-only Data Literals
Right now the following data types are only available for manipulation in non-compiled code.
2017-06-26 16:50:51 +03:00
```
2017-06-26 12:45:18 +03:00
(1 2 3) ; list
foo ; symbol
```
### Special Forms
2017-06-26 16:50:51 +03:00
```
2017-06-26 17:09:12 +03:00
(def variable-name value) ;; Define a global variable
(defn function-name [<arg1> <arg2> ...] <body>) ;; Define a function (will be compiled)
(let [<var1> <expr1> <var2> <expr2> ...] <body>) ;; Define local bindings
(do <expr1> <expr2> ... <return-expression>) ;; Perform side-effecting functions, then return a value
(if <expression> <true-branch> <false-branch>) ;; Branching
(while <expression> <body>) ;; Loop until expression is false
(ref <expression>) ;; Borrow an owned value
2017-06-26 16:50:51 +03:00
(address <expression>) ;; Takes the memory address of a value, returns a C-style pointer
(set! <variable> <expression>) ;; Mutate a variable
(the Int <expression>) ;; Explicitly declare the type of an expression
2017-06-26 12:45:18 +03:00
```
2017-06-26 16:58:23 +03:00
### Reader Macros
```
2017-06-26 17:09:12 +03:00
&x ;; same as (ref x)
@x ;; same as (copy x)
2017-06-26 16:58:23 +03:00
```
### Named Holes
2017-06-26 16:50:51 +03:00
When using a statically typed language like Carp it can sometimes be hard to know what value should
be used at a specific point in your program. In such cases the concept of 'holes' can be useful. Just
add a hole in your source code and reload (":r") to let the Carp compiler figure out what type goes there.
```
2017-06-26 16:58:23 +03:00
(String.append ?w00t "!") ;; Will generate a type error telling you that the type of '?w00t' is String
2017-06-26 12:45:18 +03:00
```
### Dynamic-only Special Forms
2017-06-26 16:58:23 +03:00
These can only be used at the REPL and during macro evaluation.
2017-06-26 16:50:51 +03:00
2017-06-26 12:45:18 +03:00
```
2017-06-26 16:50:51 +03:00
(defmacro <name> [<arg1> <arg2> ...] <macro-body>)
(dynamic <name> [<arg1> <arg2> ...] <function-body>)
2017-06-26 17:09:12 +03:00
(quote <expression>) ;; Avoid further evaluation of the expression
(car <collection>) ;; Return the first element of a list or array
(cdr <collection>) ;; Return all but the first element of a list or array
(cons <expr> <list>) ;; Add the value of <expr> as the first element the <list>
(list <expr1> <expr2> ...) ;; Create a list from a series of evaluated expressions
(array <expr1> <expr2> ...) ;; Create an array from a series of evaluated expressions
2017-06-26 14:45:51 +03:00
```
2017-06-26 16:58:23 +03:00
### Modules and Name Lookup
2017-06-26 14:45:51 +03:00
Functions and variables can be stored in modules which are named and can be nested. To use a symbol inside a module
you need to qualify it with the module name, like this: ```Float.cos```.
Importing a module makes it possible to access its members without qualifying them:
2017-06-26 16:50:51 +03:00
```
2017-06-26 14:45:51 +03:00
(import Float)
(defn f []
(cos 3.2f))
```
If there are several imported modules that contain symbols with the same name, the type inferer will try to figure
out which one of the symbols you really mean (based on the types in your code). If it can't, it will display an error.
For example, both the module ```String``` and ```Array``` contain a function named 'count'. In the following code it's
possible to see that it's the array version that is needed, and that one will be called:
2017-06-26 16:50:51 +03:00
```
2017-06-26 14:45:51 +03:00
(import String)
(import Array)
(defn f []
(count [1 2 3 4 5]))
```
In the following example it's not possible to figure out which type is intended:
2017-06-26 16:50:51 +03:00
```
2017-06-26 14:45:51 +03:00
(import String)
(import Array)
(defn f [x]
(count x))
```
Specifying the type solves this error:
2017-06-26 16:50:51 +03:00
```
2017-06-26 14:45:51 +03:00
(import String)
(import Array)
(defn f [x]
(String.count x))
2017-06-26 12:45:18 +03:00
```
### Structs
2017-06-26 16:50:51 +03:00
```
(deftype Vector2 [x Int, y Int])
2017-06-26 12:45:18 +03:00
2017-06-26 16:50:51 +03:00
(let [my-pos (Vector2.init 10 20)]
2017-06-26 12:45:18 +03:00
...)
;; A 'lens' is automatically generated for each member:
2017-06-26 16:50:51 +03:00
(Vector2.x my-pos) ;; => 10
(Vector2.set-x my-pos 30) ;; => (Vector2 30 20)
(Vector2.update-x my-pos inc) ;; => (Vector2 11 20)
2017-06-26 12:45:18 +03:00
```
2017-06-26 16:58:23 +03:00
### C Interop
2017-06-26 16:50:51 +03:00
```
(register blah (Fn (Int Int) String)) ;; Will register the function 'blah' that takes two Int:s and returns a String
(register pi Double) ;; Will register the global variable 'pi' of type Double
2017-06-26 12:45:18 +03:00
```