160 lines
3.6 KiB
Markdown
160 lines
3.6 KiB
Markdown
# Chapter 1: Getting Started
|
|
|
|
Deimos can be run both interactively via a read-eval-print loop (REPL) or by compiling and running a given source file.
|
|
|
|
## REPL
|
|
|
|
The REPL allows interactive programming similar to classic functional languages as well as Ruby. To start the REPL, run:
|
|
|
|
```
|
|
dm repl
|
|
```
|
|
|
|
### Basics
|
|
|
|
All statements and expressions in the REPL are scoped under a synthetic function; in other words, variables persist
|
|
through each input:
|
|
|
|
```
|
|
> let x = 2
|
|
> x
|
|
2
|
|
> let y = 3
|
|
> x + y
|
|
5
|
|
```
|
|
|
|
In addition to statements and expressions, functions can be defined in scope:
|
|
|
|
```
|
|
> fn double(x: Int) x * 2 end
|
|
> double(4)
|
|
8
|
|
```
|
|
|
|
Note that variables in the "top" scope are not available inside defined functions:
|
|
|
|
```
|
|
> let x = 7
|
|
> fn doubleX() x * 2 end
|
|
Error: Symbol x could not be found.
|
|
```
|
|
|
|
This requires the use of closures, which can "capture" variables in their containing scope:
|
|
|
|
```
|
|
> let x = 42
|
|
> let doubleX = { x * 2 }
|
|
> doubleX()
|
|
84
|
|
```
|
|
|
|
Note the difference in syntax between function declarations and closure declarations. As we will later see, closures are
|
|
powerful constructs.
|
|
|
|
### Introduction to Classes
|
|
|
|
Classes can also be defined in the REPL:
|
|
|
|
```
|
|
> class Dog \
|
|
pub name: String \
|
|
pub ctor(name: String) \
|
|
self.name = name \
|
|
end \
|
|
end
|
|
```
|
|
|
|
A few things are going on here. First, note the use the backslash to indicate that we are not done with our input
|
|
(normally, a newline without a preceding backslash will cause the interpreter to consume everything input so far). Next,
|
|
note our syntax for declaring a class, with hints of Rust and Ruby:
|
|
|
|
- `class` keyword: the usual meaning
|
|
- `pub` keyword: makes a property or method available outside the class (i.e., non-private)
|
|
- `: Type` annotations: indicates the type of a property, parameter, or variable.
|
|
- `ctor` keyword: marks a constructor. *Note: Classes can only have **one** constructor*.
|
|
- `self` keyword, followed by property name: like the usual construct in OOP languages.
|
|
|
|
Once we've defined our class, we can use it:
|
|
|
|
```
|
|
> let bear = Dog("Bear")
|
|
> let skye = Dog("Skye")
|
|
> bear.name
|
|
Bear
|
|
> skye.name
|
|
Skye
|
|
```
|
|
|
|
Note above how we construct instances of the class by "calling" the class, exactly like we do in Kotlin.
|
|
|
|
#### Class Declaration Short Form
|
|
|
|
The above class example is a bit verbose; Deimos offers the following equivalent, inspired by Kotlin:
|
|
|
|
```
|
|
class Dog(pub name: String) end
|
|
```
|
|
|
|
This is especially useful in the REPL, where we may just want to declare a data type for doing some data processing.
|
|
|
|
```
|
|
> class Point(pub x: Int, pub y: Int) end
|
|
> fn double(p: Point) Point(p.x * 2, p.y * 2) end
|
|
> let a = Point(3, 4)
|
|
> double(a)
|
|
Point(6, 8)
|
|
> let b = Point(5, 6)
|
|
> double(double(b))
|
|
Point(20, 24)
|
|
```
|
|
|
|
## Compiling and Running Files
|
|
|
|
To compile and run a file, do:
|
|
|
|
```
|
|
dm run <your file name here>.dm
|
|
```
|
|
|
|
Note that the `.dm` extension is required in the command name (unlike `java`).
|
|
|
|
The above command will compile and immediately run the file. In order for a Deimos file to be executable, it must
|
|
contain a `main` function like the following:
|
|
|
|
```
|
|
fn main()
|
|
println("Hello, Deimos!")
|
|
end
|
|
```
|
|
|
|
Unlike the REPL, statements and expressions are not allowed in the top-level scope; they must be contained in a function
|
|
or method:
|
|
|
|
```
|
|
let x = 10 // ERROR! Will not parse.
|
|
```
|
|
|
|
However, functions, classes, and other top-level constructs are allowed:
|
|
|
|
```
|
|
fn double(p: Point) -> Point
|
|
Point(p.x * 2, p.y * 2)
|
|
end
|
|
|
|
class Point(x: Int, y: Int) end
|
|
|
|
fn main()
|
|
let a = Point(1, 2)
|
|
let b = Point(3, 4)
|
|
println(double(a)) // Point(2, 4)
|
|
println(double(b)) // Point(6, 8)
|
|
end
|
|
```
|
|
|
|
```
|
|
let f = { a, b -> a + b } << 4
|
|
let x = f(5)
|
|
println(x) // 9
|
|
```
|