Carp/docs/LanguageGuide.md

160 lines
5.0 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-10-17 23:48:02 +03:00
To learn more about the details of memory management, check out [Memory.md](https://github.com/carp-lang/Carp/blob/master/docs/Memory.md)
2017-10-17 23:47:21 +03:00
2017-06-26 17:09:12 +03:00
### Comments
```
2017-06-26 17:14:10 +03:00
;; Comments begin with a semicolon and continue until the end of the line.
2017-06-26 17:09:12 +03:00
```
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
```
2017-06-26 17:13:24 +03:00
t ;; Type variables begin with a lowercase letter
2017-06-26 17:12:41 +03:00
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 17:17:25 +03:00
The following forms can be used in Carp source code and will be compiled to C after type checking
and other static analysis. Please note that they can not be executed at the REPL.
2017-06-26 16:50:51 +03:00
```
2017-06-26 17:09:12 +03:00
(def variable-name value) ;; Define a global variable
2017-06-26 17:15:59 +03:00
(defn function-name [<arg1> <arg2> ...] <body>) ;; Define a function
2017-06-26 17:09:12 +03:00
(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-10-18 09:50:00 +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 17:15:59 +03:00
(defmacro <name> [<arg1> <arg2> ...] <macro-body>) ;; Its argument will not be evaluated when called
(dynamic <name> [<arg1> <arg2> ...] <function-body>) ;; A function that can only be used at the REPL
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```.
2017-09-06 15:43:41 +03:00
*Using* a module makes it possible to access its members without qualifying them:
2017-06-26 14:45:51 +03:00
2017-06-26 16:50:51 +03:00
```
2017-09-06 15:43:41 +03:00
(use Float)
2017-06-26 14:45:51 +03:00
(defn f []
(cos 3.2f))
```
2017-09-06 15:43:41 +03:00
If there are several used modules that contain symbols with the same name, the type inferer will try to figure
2017-06-26 14:45:51 +03:00
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-09-06 15:43:41 +03:00
(use String)
(use Array)
2017-06-26 14:45:51 +03:00
(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-09-06 15:43:41 +03:00
(use String)
(use Array)
2017-06-26 14:45:51 +03:00
(defn f [x]
(count x))
```
Specifying the type solves this error:
2017-06-26 16:50:51 +03:00
```
2017-09-06 15:43:41 +03:00
(use String)
(use Array)
2017-06-26 14:45:51 +03:00
(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
```