0 | |
Expel
|
|
0 |
Ubik
|
1 | 1 |
=====
|
2 | 2 |
|
3 | 3 |
*This document is a work-in-progress, and everything in it is subject to
|
4 | 4 |
change.*
|
5 | 5 |
|
6 | |
Expel will eventually be a programming language. Expel aims to be a
|
|
6 |
Ubik will eventually be a programming language. Ubik aims to be a
|
7 | 7 |
programming language that approximates the combination of the.
|
8 | 8 |
conciseness of Haskell, the simplicity of Lisp, the productivity of
|
9 | |
Python and the deployability of Go. Expel is what I wish I could write
|
10 | |
everything in, but first I have to write Expel.
|
11 | |
|
12 | |
Expel will have strict, static typing with full type inference. Expel
|
|
9 |
Python and the deployability of Go. Ubik is what I wish I could write
|
|
10 |
everything in, but first I have to write Ubik.
|
|
11 |
|
|
12 |
Ubik will have strict, static typing with full type inference. Ubik
|
13 | 13 |
will be homoiconic, and provide language-level features that allow users
|
14 | 14 |
to control order-of-evaluation; in doing so, it will obviate the need
|
15 | |
for macros. Expel will draw heavily from Python's view of
|
16 | |
everything-as-namespace. Expel will, at first, be interpreted, but
|
17 | |
eventually will be compiled into LLVM IR (or similar). Expel will not
|
18 | |
have a null value or type. Expel will have no mutable state.
|
19 | |
|
20 | |
## Expel in examples
|
21 | |
|
22 | |
Syntactically, Expel borrows heavily from Haskell and Hoon. As in Hoon,
|
|
15 |
for macros. Ubik will draw heavily from Python's view of
|
|
16 |
everything-as-namespace. Ubik will, at first, be interpreted, but
|
|
17 |
eventually will be compiled into LLVM IR (or similar). Ubik will not
|
|
18 |
have a null value or type. Ubik will have no mutable state.
|
|
19 |
|
|
20 |
## Ubik in examples
|
|
21 |
|
|
22 |
Syntactically, Ubik borrows heavily from Haskell and Hoon. As in Hoon,
|
23 | 23 |
punctuation is used in lieu of keywords, allowing any alphabetic symbol
|
24 | 24 |
to be a valid user operator. Of course, there are also symbols provided
|
25 | 25 |
by the standard library; these, however, need not be imported.
|
|
55 | 55 |
|
56 | 56 |
The `{` (pronounced "new-block") operator introduces a new scoping
|
57 | 57 |
block. This allows for what other languages call `with` or `let`; in
|
58 | |
Expel, to create symbols of limited scope, you create a binding within a
|
|
58 |
Ubik, to create symbols of limited scope, you create a binding within a
|
59 | 59 |
scope block. Note that in this example, the type signature of `f` is
|
60 | 60 |
inferred.
|
61 | 61 |
|
|
159 | 159 |
|
160 | 160 |
### Record types
|
161 | 161 |
|
162 | |
Expel has record types, which are structured types containing multiple
|
163 | |
typed and named fields. Unlike many other functional languages, Expel
|
|
162 |
Ubik has record types, which are structured types containing multiple
|
|
163 |
typed and named fields. Unlike many other functional languages, Ubik
|
164 | 164 |
seeks to avoid polluting the record's enclosing namespace by accessing
|
165 | 165 |
child fields using the member operator instead of creating accessor
|
166 | 166 |
functions for each.
|
|
191 | 191 |
|
192 | 192 |
### Conditionals
|
193 | 193 |
|
194 | |
There is only one explicit control-flow construct in Expel: a simple
|
|
194 |
There is only one explicit control-flow construct in Ubik: a simple
|
195 | 195 |
conditional statement. You can create a conditional statement using the
|
196 | 196 |
`=>` (pronounced "implies") and `/>` (pronounced "opposes") operator,
|
197 | 197 |
like so:
|
|
216 | 216 |
As an example, examine the case of the member operator. While some
|
217 | 217 |
uses of the member operator are language built-ins, the usage of the
|
218 | 218 |
member operator to access a field in a record is implemented in native
|
219 | |
Expel as a CTPA. Record types are all instances of a `Record`
|
|
219 |
Ubik as a CTPA. Record types are all instances of a `Record`
|
220 | 220 |
typeclass:
|
221 | 221 |
|
222 | 222 |
_ Record
|
|
224 | 224 |
|
225 | 225 |
`Symbol` is a type provided by the prelude that represents a symbol in
|
226 | 226 |
the AST of the program. Note the `!` (pronounced "eager") operator after
|
227 | |
the `Symbol` type; this tells Expel that this is an unevaluated
|
|
227 |
the `Symbol` type; this tells Ubik that this is an unevaluated
|
228 | 228 |
expression tree instead of an actual value. It is a compile-time error
|
229 | 229 |
to pass this function anything but a symbol as its first argument.
|
230 | 230 |
|
|
265 | 265 |
|
266 | 266 |
## Input, output and external state
|
267 | 267 |
|
268 | |
Expel has to deal with a problem common to all side-effect-free
|
|
268 |
Ubik has to deal with a problem common to all side-effect-free
|
269 | 269 |
languages: how does such a system mutate the state of the system it runs
|
270 | 270 |
on? Modern computing systems are state modification machines; no real
|
271 | 271 |
programming language can ignore this. However, the advantages of
|
272 | 272 |
stateless computing are innumerable: repeatability, parallelization and
|
273 | 273 |
understandability shouldn't be compromised wherever possible.
|
274 | 274 |
|
275 | |
To this goal, the Expel runtime provides a view into state outside the
|
|
275 |
To this goal, the Ubik runtime provides a view into state outside the
|
276 | 276 |
system that enforces repeatability and a weak form of immutability,
|
277 | |
while falling short on the ability to parallelize in some cases. Expel
|
|
277 |
while falling short on the ability to parallelize in some cases. Ubik
|
278 | 278 |
programs declare what external state sources they need access to; this
|
279 | 279 |
could be a file, a random number generator, or an interface to a
|
280 | 280 |
physical device. The runtime provides a monadic view to these state
|
|
287 | 287 |
a randomly-chosen initial starting seed for the lifetime of the runtime.
|
288 | 288 |
|
289 | 289 |
Writing external state to a state sink is harder, especially when
|
290 | |
coupled with the desire for immutability. Expel solves this by only
|
|
290 |
coupled with the desire for immutability. Ubik solves this by only
|
291 | 291 |
allowing one handle to each state sink to be created over the lifetime
|
292 | 292 |
of the runtime. This is equivalent to saying that a file may only be
|
293 | 293 |
opened for writing once over the lifetime of the program. It is also
|
|
303 | 303 |
into, in which everything but that which interacts with the outside world is
|
304 | 304 |
fully repeatable.
|
305 | 305 |
|
306 | |
## All Expel operators
|
|
306 |
## All Ubik operators
|
307 | 307 |
|
308 | 308 |
### `:`
|
309 | 309 |
Pronounced "bind name", creates a binding with a name.
|