aboutsummaryrefslogtreecommitdiff
path: root/documentation/book/the_lux_programming_language
diff options
context:
space:
mode:
Diffstat (limited to 'documentation/book/the_lux_programming_language')
-rw-r--r--documentation/book/the_lux_programming_language/appendix_a.md46
-rw-r--r--documentation/book/the_lux_programming_language/appendix_c.md106
-rw-r--r--documentation/book/the_lux_programming_language/appendix_d.md69
-rw-r--r--documentation/book/the_lux_programming_language/appendix_e.md2
-rw-r--r--documentation/book/the_lux_programming_language/appendix_f.md24
-rw-r--r--documentation/book/the_lux_programming_language/appendix_g.md14
-rw-r--r--documentation/book/the_lux_programming_language/appendix_h.md26
-rw-r--r--documentation/book/the_lux_programming_language/chapter_1.md21
-rw-r--r--documentation/book/the_lux_programming_language/chapter_10.md80
-rw-r--r--documentation/book/the_lux_programming_language/chapter_11.md118
-rw-r--r--documentation/book/the_lux_programming_language/chapter_12.md2
-rw-r--r--documentation/book/the_lux_programming_language/chapter_13.md40
-rw-r--r--documentation/book/the_lux_programming_language/chapter_14.md46
-rw-r--r--documentation/book/the_lux_programming_language/chapter_16.md101
-rw-r--r--documentation/book/the_lux_programming_language/chapter_17.md60
-rw-r--r--documentation/book/the_lux_programming_language/chapter_18.md51
-rw-r--r--documentation/book/the_lux_programming_language/chapter_2.md15
-rw-r--r--documentation/book/the_lux_programming_language/chapter_3.md58
-rw-r--r--documentation/book/the_lux_programming_language/chapter_4.md10
-rw-r--r--documentation/book/the_lux_programming_language/chapter_5.md46
-rw-r--r--documentation/book/the_lux_programming_language/chapter_6.md14
-rw-r--r--documentation/book/the_lux_programming_language/chapter_7.md63
-rw-r--r--documentation/book/the_lux_programming_language/chapter_8.md189
-rw-r--r--documentation/book/the_lux_programming_language/chapter_9.md6
-rw-r--r--documentation/book/the_lux_programming_language/conclusion.md2
25 files changed, 607 insertions, 602 deletions
diff --git a/documentation/book/the_lux_programming_language/appendix_a.md b/documentation/book/the_lux_programming_language/appendix_a.md
index 605658385..d0b4fe8b1 100644
--- a/documentation/book/the_lux_programming_language/appendix_a.md
+++ b/documentation/book/the_lux_programming_language/appendix_a.md
@@ -7,8 +7,8 @@ If you recall [Chapter 1](chapter_1.md), there was this example code:
```clojure
(.require
[library
- [lux "*"
- [program {"+" program:}]
+ [lux (.except)
+ [program (.only program)]
["[0]" debug]
[control
["[0]" io]]]])
@@ -16,7 +16,7 @@ If you recall [Chapter 1](chapter_1.md), there was this example code:
Here, we're importing the `library/lux` module.
-The `"*"`/`"all"` option means _locally import every definition exported by the `library/lux` module_.
+The `(.except)` option means _locally import every definition exported by the `library/lux` module_.
This allows usage of those definitions without having to give them the `library/lux.` prefix, or even the `.` shortcut prefix.
@@ -24,11 +24,11 @@ This may cause some issues if you import 2 definitions with the same name from d
In those circumstances, the compiler will complain, saying that you can't re-define `X`; where `X` is the name of the definition.
-Then, we import `library/lux/program`, but we **only** import locally the `program:` definition.
-That is what the `"+"`/`"only"` option allows.
+Then, we import `library/lux/program`, but we **only** import locally the `program` definition.
+That is what the `.only` option allows.
- There is also a `"-"`/`"exclude"` option which means locally import everything **except** the specified definitions_.
- You could use it like this: `[your_module {"-" foo bar baz}]`
+ There is also a `.only` option which means locally import everything **except** the specified definitions_.
+ You could use it like this: `[your_module (.except foo bar baz)]`
Finally, we import both the `library/lux/debug` and `library/lux/control/io` modules.
@@ -56,8 +56,8 @@ The `.require` declaration could just as easily been written like this:
```clojure
(.require
- [library/lux "*"]
- [library/lux/program {"+" program:}]
+ [library/lux (.except)]
+ [library/lux/program (.only program)]
["debug" library/lux/debug]
["io" library/lux/control/io])
```
@@ -75,10 +75,10 @@ For example:
```clojure
(.require
[library
- [lux "*"
+ [lux (.except)
[data
[collection
- ["[0]" list ("[1]::[0]" functor monoid)]]]]])
+ ["[0]" list (.use "[1]::[0]" functor monoid)]]]]])
```
The import above would locally import:
@@ -107,10 +107,10 @@ For example:
```clojure
(.require
[library
- [lux "*"
+ [lux (.except)
[data
- ["[0]" collection "_"
- ["[1]/[0]" list ("[1]::[0]" functor monoid)]]]]])
+ ["[0]" collection (.only)
+ ["[1]/[0]" list (.use "[1]::[0]" functor monoid)]]]]])
```
Would locally import:
@@ -127,10 +127,10 @@ This means:
```clojure
(.require
[library
- [lux "*"
- ["[0]" data "_"
+ [lux (.except)
+ ["[0]" data
[collection
- ["[1]/[0]" list ("[1]::[0]" functor monoid)]]]]])
+ ["[1]/[0]" list (.use "[1]::[0]" functor monoid)]]]]])
```
Would locally import:
@@ -147,10 +147,10 @@ For example:
```clojure
(.require
[library
- [lux "*"
+ [lux (.except)
[data
[collection
- ["[0]" list {"+" repeated size} ("[1]::[0]" monad)]]]]])
+ ["[0]" list (.only repeated size) (.use "[1]::[0]" monad)]]]]])
```
---
@@ -180,7 +180,7 @@ You can import other modules in the hierarchy like this:
... In program/foo/baz
(.require
[library
- [lux "*"]]
+ [lux (.except)]]
["[0]" /quux] ... program/foo/baz/quux, aliased as /quux
["[0]" //bar] ... program/foo/bar, aliased as //bar
["[0]" ///] ... program, aliased as ///
@@ -205,7 +205,7 @@ Also, this relative path syntax can be nested, like so:
... In program/foo/baz
(.require
[library
- [lux "*"]]
+ [lux (.except)]]
[/
["[0]" quux]] ... program/foo/baz/quux, aliased as quux
[//
@@ -221,7 +221,7 @@ Or even:
... In program/foo/baz
(.require
[library
- [lux "*"]]
+ [lux (.except)]]
[/
["[0]" quux] ... program/foo/baz/quux, aliased as quux
[//
@@ -242,7 +242,7 @@ For the second way to do relative imports, you can see this example:
... In program/foo/baz
(.require
[library
- [lux "*"]]
+ [lux (.except)]]
[\\test
["[0]" /] ... test/foo/baz, aliased as /
]
diff --git a/documentation/book/the_lux_programming_language/appendix_c.md b/documentation/book/the_lux_programming_language/appendix_c.md
index a2c0953cb..5bfb731ea 100644
--- a/documentation/book/the_lux_programming_language/appendix_c.md
+++ b/documentation/book/the_lux_programming_language/appendix_c.md
@@ -1,26 +1,28 @@
# Appendix C: Pattern-matching macros
-Pattern-matching is a native Lux feature, and yet `case` is a macro.
+Pattern-matching is a native Lux feature, and yet `when` is a macro.
_Why?_, you may wonder. _What does being a macro add to the mix?_
-Well, as it turns out, by making `case` be a macro, Lux can perform some compile-time calculations which ultimately enable a set of really cool features to be implemented: custom pattern-matching.
+Well, as it turns out, by making `when` be a macro, Lux can perform some compile-time calculations which ultimately enable a set of really cool features to be implemented: custom pattern-matching.
Most languages with pattern-matching have a fixed set of rules and patterns for how everything works.
Not so with Lux.
-Lux provides a set of default mechanisms, but by using macros where patterns are located, `case` can expand those macro calls to get the myriad benefits they offer.
+Lux provides a set of default mechanisms, but by using macros where patterns are located, `when` can expand those macro calls to get the myriad benefits they offer.
But enough chit-chat.
Let's see them in action.
+ **Note**: The following examples assume you `.require` the `["^" library/lux/meta/macro/pattern]` module.
+
## Pattern-matching macros in the Standard Library
```clojure
-(case (list 1 2 3)
- (^ (list x y z))
+(when (list 1 2 3)
+ (list x y z)
{.#Some (+ x (* y z))}
_
@@ -29,15 +31,15 @@ Let's see them in action.
You may remember how annoying it was to pattern-match against lists in the [Chapter 5](chapter_5.md) example.
-Well, by using the `^` pattern-matching macro, you can use any normal macros you want inside the pattern to profit from their code-construction capacities.
+Well, `when` will expand any **normal** macros inside your patterns before proceeding to pattern-match against the input data.
```clojure
... Multi-level pattern matching.
... Useful in situations where the result of a branch depends on further refinements on the values being matched.
... For example:
-(case (split (size static) uri)
- (^multi {.#Some [chunk uri']}
- [(text::= static chunk) #1])
+(when (split (size static) uri)
+ (^.multi {.#Some [chunk uri']}
+ [(text::= static chunk) #1])
(match_uri endpoint? parts' uri')
_
@@ -45,16 +47,16 @@ Well, by using the `^` pattern-matching macro, you can use any normal macros you
... Short-cuts can be taken when using boolean tests.
... The example above can be rewritten as...
-(case (split (size static) uri)
- (^multi {.#Some [chunk uri']}
- (text::= static chunk))
+(when (split (size static) uri)
+ (^.multi {.#Some [chunk uri']}
+ (text::= static chunk))
(match_uri endpoint? parts' uri')
_
{.#Left (format "Static part " (%.text static) " doesn't match URI: " uri}))
```
-I **love** `^multi`.
+I **love** `multi`.
It's one of those features you don't need often, but when you do, it saves the day.
@@ -62,24 +64,24 @@ The possibilities are endless when it comes to the refinement you can do, and wh
```clojure
... Allows you to simultaneously bind and de-structure a value.
-(def (hash (^@ set [element_hash _]))
+(def (hash (^.let set [element_hash _]))
(list#mix (function (_ elem acc)
(n.+ (# element_hash hash elem) acc))
0
(set.list set)))
```
-`^@` is for when you want to deal with a value both as a whole and in parts.
+`let` is for when you want to deal with a value both as a whole and in parts.
```clojure
-... Same as the "open" macro, but meant to be used as a pattern-matching macro for generating local bindings.
+... Same as the "use" macro, but meant to be used as a pattern-matching macro for generating local bindings.
... Can optionally take an aliasing text for the generated local bindings.
-(def .public (range (^open "[0]") from to)
+(def .public (range (.open "[0]") from to)
(All (_ a) (-> (Enum a) a a (List a)))
(range' <= succ from to))
```
-`^open` allows you to open structures using local variables during pattern-matching.
+`.open` allows you to open structures using local variables during pattern-matching.
It's excellent when taking structures as function arguments, or when opening structures locally in `let` expressions.
@@ -97,15 +99,15 @@ It's excellent when taking structures as function arguments, or when opening str
(def (weekend? day)
(-> Day Bit)
- (case day
- (^or {#Saturday} {#Sunday})
+ (when day
+ (^.or {#Saturday} {#Sunday})
true
_
false))
```
-`^or` patterns allow you to have multiple patterns with the same branch.
+`or` patterns allow you to have multiple patterns with the same branch.
It's a real time-saver.
@@ -113,11 +115,11 @@ It's a real time-saver.
... It's similar to do-template, but meant to be used during pattern-matching.
(def (beta_reduce env type)
(-> (List Type) Type Type)
- (case type
+ (when type
{.#Primitive name params}
{.#Primitive name (list#map (beta_reduce env) params)}
- (^template [<tag>]
+ (^.with_template [<tag>]
[{<tag> left right}
{<tag> (beta_reduce env left) (beta_reduce env right)}])
([.#Sum]
@@ -125,9 +127,9 @@ It's a real time-saver.
[.#Function]
[.#Apply])
- (^template [<tag>]
+ (^.with_template [<tag>]
[{<tag> old_env def}
- (case old_env
+ (when old_env
{.#End}
{<tag> env def}
@@ -146,9 +148,9 @@ It's a real time-saver.
type))
```
-`^template` is `^or`'s big brother.
+`with_template` is `or`'s big brother.
-Whereas `^or` demands that you provide the exact patterns you want (and with a single branch body), `^template` lets you provide templates for both the patterns and bodies, and then fills the blanks with all the given parameters.
+Whereas `or` demands that you provide the exact patterns you want (and with a single branch body), `with_template` lets you provide templates for both the patterns and bodies, and then fills the blanks with all the given parameters.
You can save yourself quite a lot of typing (and debugging) by reusing a lot of pattern-matching code with this macro.
@@ -157,11 +159,11 @@ It's a great asset!
```clojure
... Allows destructuring of streams in pattern-matching expressions.
... Caveat emptor: Only use it for destructuring, and not for testing values within the streams.
-(let [(^stream& x y z _tail) (some_stream_function 1 2 3)]
+(let [(stream.pattern x y z _tail) (some_stream_function 1 2 3)]
(func x y z))
```
-`^stream&` hails from the `library/lux/data/collection/stream` module, and it's quite special, because it allows you to de-structure something you normally wouldn't be able to: functions.
+`stream.pattern` hails from the `library/lux/data/collection/stream` module, and it's quite special, because it allows you to de-structure something you normally wouldn't be able to: functions.
You see, Lux streams (as defined in `library/lux/data/collection/stream`) are implemented using functions.
@@ -169,7 +171,7 @@ The reason is that they are infinite in scope, and having an infinite data-struc
Well, no biggie!
-`^stream&` does some black magic to make sure you can de-structure your stream just like any other data-structure.
+`stream.pattern` does some black magic to make sure you can de-structure your stream just like any other data-structure.
## How to make your own
@@ -183,13 +185,13 @@ After that, you'll receive all the branches (pattern + body) following the call
You can process all your inputs as you wish, but in the end you must produce an even number of outputs (even, because the outputs must take the form of pattern+body pairs).
-These will be further macro-expanded until all macros have been dealt with and only primitive patterns remain, so `case` can just go ahead and do normal pattern-matching.
+These will be further macro-expanded until all macros have been dealt with and only primitive patterns remain, so `when` can just go ahead and do normal pattern-matching.
You may wonder: _why do I receive the body?_
The answer is simple: depending on your macro, you may be trying to provide some advance functionality that requires altering (or replicating) the code of the body.
-For example, `^or` copies the body for every alternative pattern you give it, and `^template` must both copy and customize the bodies (and patterns) according to the parameters you give it.
+For example, `^.or` copies the body for every alternative pattern you give it, and `^.with_template` must both copy and customize the bodies (and patterns) according to the parameters you give it.
But receiving the next set of branches takes the cake for the weirdest input.
@@ -197,32 +199,30 @@ _What gives?_
It's simple: some macros are so advanced that they require altering not just their bodies, but anything that comes later.
-A great example of that is the `^multi` macro.
+A great example of that is the `^.multi` macro.
-`^multi` performs some large-scale transformations on your code which require getting access to the rest of the code after a given usage of `^multi`.
+`^.multi` performs some large-scale transformations on your code which require getting access to the rest of the code after a given usage of `^.multi`.
However, most of the time, you'll just return the branches (and sometimes the body) unchanged.
-To make things easier to understand, here is the implementation of the `^` macro, from the `library/lux` module:
+To make things easier to understand, here is the implementation of the `or` macro, from the `library/lux/meta/macro/pattern` module:
```clojure
-(macro: (^ tokens)
- (case tokens
- {#Item [_ {#Form {#Item pattern {#End}}}] {#Item body branches}}
- (do meta_monad
- [pattern+ (full_expansion pattern)]
- (case pattern+
- {#Item pattern' {#End}}
- (in (list& pattern' body branches))
-
- _
- (failure "^ can only expand to 1 pattern.")))
-
- _
- (failure "Wrong syntax for ^ macro")))
+(def .public or
+ (pattern
+ (macro (_ tokens)
+ (when tokens
+ (list.partial [_ {.#Form patterns}] body branches)
+ (when patterns
+ {.#End}
+ (///.failure (..wrong_syntax_error (symbol ..or)))
+
+ _
+ (.let [pairs (.|> patterns
+ (list#each (function (_ pattern) (list pattern body)))
+ list#conjoint)]
+ (///#in (list#composite pairs branches))))
+ _
+ (///.failure (..wrong_syntax_error (symbol ..or)))))))
```
-The `^` prefix given to PM-macros was chosen simply to make them stand-out when you see them in code.
-
-There is nothing special attached to that particular character.
-
diff --git a/documentation/book/the_lux_programming_language/appendix_d.md b/documentation/book/the_lux_programming_language/appendix_d.md
index 2d8adcd8e..07b6ea5b4 100644
--- a/documentation/book/the_lux_programming_language/appendix_d.md
+++ b/documentation/book/the_lux_programming_language/appendix_d.md
@@ -12,6 +12,8 @@ I try to figure out ways to get my code to be more pipe-sensitive, to see how fa
My personal record is 14 steps.
+ **Note**: The following examples assume that you `.require` the `["|" library/lux/control/pipe]` module.
+
## Piping macros in the standard library
Anyhow, after looking at some of the innovations of Clojure in the piping department, I decided to come up with my own tricks to try to get Lux to become a piping superpower.
@@ -24,17 +26,17 @@ Take a look at these babies:
... Loops for pipes.
... Both the testing and calculating steps are pipes and must be given inside tuples.
(|> 1
- (loop> [(n.< 10)]
- [++]))
+ (|.loop [(n.< 10)]
+ [++]))
```
-`loop>` takes a test _tuple_ and a body _tuple_.
+`loop` takes a test _tuple_ and a body _tuple_.
The reason is that each of those tuples represents the steps on an implicit piping macro (_oh, yeah!_).
So `[(n.< 10)]` is like `(|> value (n.< 10))`, and `[++]` is like `(|> value ++)`.
-Which value? Whatever has been piped into `loop>` from the underlying `|>` (in this case, the value `1`).
+Which value? Whatever has been piped into `loop` from the underlying `|>` (in this case, the value `1`).
---
@@ -43,15 +45,15 @@ Which value? Whatever has been piped into `loop>` from the underlying `|>` (in t
... Both the tests and the bodies are piped-code, and must be given inside a tuple.
... If a last else-pipe isn't given, the piped-argument will be used instead.
(|> 5
- (cond> [i.even?] [(i.* 2)]
- [i.odd?] [(i.* 3)]
- ... else branch
- [(new> -1 [])]))
+ (|.cond [i.even?] [(i.* 2)]
+ [i.odd?] [(i.* 3)]
+ ... else branch
+ [(|.new -1 [])]))
```
We have looping, and now we have branching; with a `cond`-inspired piping macro (complete with _else_ branch, just in case).
-But what's that thing over there? That `new>` thing?
+But what's that thing over there? That `new` thing?
Well, it's another piping macro. Of course!
@@ -60,10 +62,10 @@ Well, it's another piping macro. Of course!
(|> 20
(i.* 3)
(i.+ 4)
- (new> 0 [++]))
+ (|.new 0 [++]))
```
-`new>` establishes a new piping sequence that ignores any previous one.
+`new` establishes a new piping sequence that ignores any previous one.
Useful in certain kinds of situations.
@@ -72,10 +74,10 @@ Useful in certain kinds of situations.
```clojure
... Gives a name to the piped-argument, within the given expression.
(|> 5
- (let> @ (+ @ @)))
+ (|.let @ (+ @ @)))
```
-`let>` binds the current value piped into it so you can refer to it multiple times within its body.
+`let` binds the current value piped into it so you can refer to it multiple times within its body.
Pretty nifty, huh?
@@ -85,17 +87,17 @@ Pretty nifty, huh?
... Pattern-matching for pipes.
... The bodies of each branch are NOT pipes; just regular values.
(|> 5
- (case> 0 "zero"
- 1 "one"
- 2 "two"
- 3 "three"
- 4 "four"
- 5 "five"
- 6 "six"
- 7 "seven"
- 8 "eight"
- 9 "nine"
- _ "???"))
+ (|.when 0 "zero"
+ 1 "one"
+ 2 "two"
+ 3 "three"
+ 4 "four"
+ 5 "five"
+ 6 "six"
+ 7 "seven"
+ 8 "eight"
+ 9 "nine"
+ _ "???"))
```
Yeah, that's right!
@@ -110,10 +112,10 @@ You'll thank me later.
... Monadic pipes.
... Each step in the monadic computation is a pipe and must be given inside a tuple.
(|> 5
- (do> identity.monad
- [(i.* 3)]
- [(i.+ 4)]
- [+]))
+ (|.do identity.monad
+ [(i.* 3)]
+ [(i.+ 4)]
+ [+]))
```
And just to show you I'm serious, I did the unthinkable.
@@ -129,11 +131,12 @@ All you need is a macro that takes anything you want as parameters, but always t
As an example, here's the definition for `let>`:
```clojure
-(syntax: .public (let> [binding <code>.any
- body <code>.any
- prev <code>.any])
- (in (list (` (let [(~ binding) (~ prev)]
- (~ body))))))
+(def .public let
+ (syntax (_ [binding <code>.any
+ body <code>.any
+ prev <code>.any])
+ (in (list (` (.let [(, binding) (, prev)]
+ (, body)))))))
```
---
diff --git a/documentation/book/the_lux_programming_language/appendix_e.md b/documentation/book/the_lux_programming_language/appendix_e.md
index b31ec03d0..64b1e6b56 100644
--- a/documentation/book/the_lux_programming_language/appendix_e.md
+++ b/documentation/book/the_lux_programming_language/appendix_e.md
@@ -95,7 +95,7 @@ Here are some examples from the `library/lux/ffi` module, where I have some type
(def privacy_modifier^
(Parser Privacy)
- (let [(^open "[0]") <>.monad]
+ (let [(open "[0]") <>.monad]
($_ <>.or
(<code>.this! (' "public"))
(<code>.this! (' "private"))
diff --git a/documentation/book/the_lux_programming_language/appendix_f.md b/documentation/book/the_lux_programming_language/appendix_f.md
index 37b0788d3..a076931f5 100644
--- a/documentation/book/the_lux_programming_language/appendix_f.md
+++ b/documentation/book/the_lux_programming_language/appendix_f.md
@@ -1,6 +1,6 @@
# Appendix F: Implicit polymorphism
-If you've used Lux's interfaces and implementations already (with the `#` macro), you've probably noticed that you need to pass around the specific implementations you need every time you want to call some interface's method.
+If you've used Lux's interfaces and implementations already (with the `at` macro), you've probably noticed that you need to pass around the specific implementations you need every time you want to call some interface's method.
That can become tiresome if you need to do it all the time, and specially if you come from languages that do method-selection for you automatically.
@@ -24,7 +24,7 @@ At any other point, it's a hindrance.
Well... there is an alternative.
-The Lux Standard Library includes a module called `library/lux/type/implicit`, which provides a macro called `##`, that serves as an easier-to-use alternative to the `#` macro.
+The Lux Standard Library includes a module called `library/lux/type/implicit`, which provides a macro called `a/an` (or, alternatively, `a` or `an`), that serves as an easier-to-use alternative to the `at` macro.
What it does is that instead of requiring the implementation you want to use, it only requires the name of the method you want to call and the arguments.
@@ -32,7 +32,7 @@ Then, at compile-time, it does some type-checking and some look-ups and selects
That implementation can come from the local-var environment, from the definitions in your own module, or even from the exported definitions of the modules you're importing.
-That way, you can use `#` whenever you need precision and power, and use `##` whenever you're doing more lightweight programming.
+That way, you can use `at` whenever you need precision and power, and use `a/an` whenever you're doing more lightweight programming.
Fantastic!
@@ -40,30 +40,30 @@ This is how you'd use it:
```clojure
... Equality for nats
-(# nat.equivalence = x y)
+(at nat.equivalence = x y)
... vs
-(## = x y)
+(an = x y)
```
```clojure
... Equality for lists of nats
-(# (list.equivalence nat.equivalence) =
- (list.indices 10)
- (list.indices 10))
+(at (list.equivalence nat.equivalence) =
+ (list.indices 10)
+ (list.indices 10))
... vs
-(## = (list.indices 10) (list.indices 10))
+(an = (list.indices 10) (list.indices 10))
```
```clojure
... Functor mapping
-(# list.functor each ++ (list.indices 10))
+(at list.functor each ++ (list.indices 10))
... vs
-(## each ++ (list.indices 10))
+(an each ++ (list.indices 10))
```
---
Thanks to implicit polymorphism, you don't have to choose between power and ease of use.
-Just do a static-import of the `library/lux/type/implicit` module, and you'll get the `##` available and ready for action.
+Just do a static-import of the `library/lux/type/implicit` module, and you'll get the `a/an` available and ready for action.
diff --git a/documentation/book/the_lux_programming_language/appendix_g.md b/documentation/book/the_lux_programming_language/appendix_g.md
index 3f8113057..e18349a69 100644
--- a/documentation/book/the_lux_programming_language/appendix_g.md
+++ b/documentation/book/the_lux_programming_language/appendix_g.md
@@ -11,15 +11,15 @@ Of course, the parser may fail, in which case the user should receive some meani
The `library/lux/control/parser/text` library provides a type, and a host of combinators, for building and working with text parsers.
```clojure
-(type: .public Offset
+(type .public Offset
Nat)
-(type: .public Parser
+(type .public Parser
(//.Parser [Offset Text]))
... And from library/lux/control/parser
-(type: .public (Parser s a)
+(type .public (Parser s a)
(-> s (Try [s a])))
```
@@ -129,11 +129,11 @@ For example:
(regex "a(.)c")
... That means, these are the types of these regular-expressions:
-(: (Parser Text)
- (regex "a{1,}"))
+(is (Parser Text)
+ (regex "a{1,}"))
-(: (Parser [Text Text])
- (regex "a(.)c"))
+(is (Parser [Text Text])
+ (regex "a(.)c"))
```
---
diff --git a/documentation/book/the_lux_programming_language/appendix_h.md b/documentation/book/the_lux_programming_language/appendix_h.md
index 2f83b846d..75d6dfc12 100644
--- a/documentation/book/the_lux_programming_language/appendix_h.md
+++ b/documentation/book/the_lux_programming_language/appendix_h.md
@@ -9,7 +9,7 @@ lux version
=>
-00.06.05
+0.07.00
```
This command tells you the version of Aedifex you're using.
@@ -45,7 +45,7 @@ lux deps
[?] Fetching com.github.luxlang:lux-jvm-0.6.5 from "~/.m2/repository"
[O] Found com.github.luxlang:lux-jvm-0.6.5 at "~/.m2/repository"
- Local successes: 0: "com.github.luxlang:lux-jvm-0.6.5"
+ Local successes: 0: "com.github.luxlang:lux-jvm-0.7.0"
Local failures:
Remote successes:
Remote failures:
@@ -162,8 +162,8 @@ Now that we have seen the available commands, it would be useful to see an annot
... The following are alternative profiles to use in various situations.
"jvm"
- [... "compiler" specifies the dependency to fetch and use as the compiler.
- "compiler" ["com.github.luxlang" "lux-jvm" "0.6.5" "jar"]
+ [... "lux" specifies the dependency to fetch and use as the compiler.
+ "lux" ["com.github.luxlang" "lux-jvm" "0.6.5" "jar"]
... "dependencies" is an optional list of dependencies to fetch.
... The dependencies have the same shape as when specifying the compiler.
... When omitting the packaging format of the dependency, "tar" will be assumed.
@@ -174,37 +174,37 @@ Now that we have seen the available commands, it would be useful to see an annot
]
"js"
- ["compiler" ["com.github.luxlang" "lux-js" "0.6.5" "js"]
+ ["lux" ["com.github.luxlang" "lux-js" "0.6.5" "js"]
... The OS command to use when running JS tests. The default is described below.
... "js" ["node" "--stack_size=8192"]
]
"python"
- ["compiler" ["com.github.luxlang" "lux-python" "0.6.5" "jar"]
+ ["lux" ["com.github.luxlang" "lux-python" "0.6.5" "jar"]
... The OS command to use when running Python tests. The default is described below.
... "python" ["python3"]
]
"lua"
- ["compiler" ["com.github.luxlang" "lux-lua" "0.6.5" "jar"]
+ ["lux" ["com.github.luxlang" "lux-lua" "0.6.5" "jar"]
... The OS command to use when running Lua tests. The default is described below.
... "lua" ["lua"]
]
"ruby"
- ["compiler" ["com.github.luxlang" "lux-ruby" "0.6.5" "jar"]
+ ["lux" ["com.github.luxlang" "lux-ruby" "0.6.5" "jar"]
... The OS command to use when running Ruby tests. The default is described below.
... "ruby" ["ruby"]
]
"bibliotheca"
["info" ["description" "Standard Library for the Lux programming language."]
- "test" "test/lux"]
+ "test" test/lux._]
"scriptum"
["info" ["description" "Documentation for the Standard Library for the Lux programming language."]
- "program" "documentation/lux"
- "test" "documentation/lux"]
+ "program" documentation/lux._
+ "test" documentation/lux._]
"aedifex"
["info" ["description" "A build system/tool made exclusively for Lux."]
@@ -212,8 +212,8 @@ Now that we have seen the available commands, it would be useful to see an annot
... Specifying them here is like automatically using Aedifex's "with" command.
"parents" ["jvm"]
... The name of the main module of the program.
- "program" "program/aedifex"
+ "program" program/aedifex._
... The name of the main module where the tests are located.
- "test" "test/aedifex"]]
+ "test" test/aedifex._]]
```
diff --git a/documentation/book/the_lux_programming_language/chapter_1.md b/documentation/book/the_lux_programming_language/chapter_1.md
index 63059fd62..dfaa0e666 100644
--- a/documentation/book/the_lux_programming_language/chapter_1.md
+++ b/documentation/book/the_lux_programming_language/chapter_1.md
@@ -23,7 +23,7 @@ Lux uses a custom-made build tool named _Aedifex_ which is configured using a de
To install Aedifex, go to https://github.com/LuxLang/lux/tree/master/shell and download either `lux.bat` or `lux.sh` depending on whether you're on Windows or Linux/Mac.
-Also [download the aedifex.jar file](https://github.com/LuxLang/lux/releases/download/0.6.5/aedifex.jar), and place it (along with either of the scripts you downloaded) somewhere in your `PATH`.
+Also [download the aedifex.jar file](https://github.com/LuxLang/lux/releases/download/0.7.0/aedifex.jar), and place it (along with either of the scripts you downloaded) somewhere in your `PATH`.
Now, you'll have access to the `lux` command, which allows you to run Aedifex to build and test Lux projects.
@@ -43,10 +43,10 @@ These are the steps:
"repositories" ["https://oss.sonatype.org/content/repositories/snapshots/"
"https://oss.sonatype.org/service/local/staging/deploy/maven2/"]
- "dependencies" [["com.github.luxlang" "stdlib" "0.6.5" "tar"]]
- "compiler" ["com.github.luxlang" "lux-jvm" "0.6.5" "jar"]
+ "dependencies" [["com.github.luxlang" "stdlib" "0.7.0" "tar"]]
+ "lux" ["com.github.luxlang" "lux-jvm" "0.7.0" "jar"]
- "program" "main"]]
+ "program" main.main]]
... By default, Aedifex uses the "source" directory for finding your source-code.
... The file containing our program will be my_project/source/main.lux.
@@ -57,14 +57,15 @@ These are the steps:
```clojure
(.require
[library
- [lux "*"
- [program {"+" program:}]
+ [lux (.except)
+ [program (.only program)]
["[0]" debug]
[control
["[0]" io]]]])
-(program: args
- (io.io (debug.log! "Hello, world!")))
+(def main
+ (program args
+ (io.io (debug.log! "Hello, world!"))))
... As you can see, this is nothing more than a very simple "Hello, world!" program to test things out.
... Everything will be explained later in the rest of the book.
@@ -98,6 +99,10 @@ You can also explore [the Lux repository on GitHub](https://github.com/LuxLang/l
The place to talk about Lux is at [the Lux forum](http://luxlang.freeforums.net/).
+You can also come and say hi at the [Gitter channel](https://gitter.im/LuxProgrammingLanguage/community).
+
+And, to communicate directly with me, just email me at: luxlisp@gmail.com
+
---
Now, we can proceed to the actual teaching of the language!
diff --git a/documentation/book/the_lux_programming_language/chapter_10.md b/documentation/book/the_lux_programming_language/chapter_10.md
index 73fe729ea..79017dd35 100644
--- a/documentation/book/the_lux_programming_language/chapter_10.md
+++ b/documentation/book/the_lux_programming_language/chapter_10.md
@@ -51,18 +51,18 @@ But macros work with the Lux _AST_, so that's the first thing you need to master
Check it out:
```clojure
-(type: .public Location
+(type .public Location
(Record
[#module Text
#line Nat
#column Nat]))
-(type: .public (Ann m v)
+(type .public (Ann m v)
(Record
[#meta m
#datum v]))
-(type: .public (Code' w)
+(type .public (Code' w)
(Variant
{#Bit Bit}
{#Nat Nat}
@@ -75,7 +75,7 @@ Check it out:
{#Variant (List (w (Code' w)))}
{#Tuple (List (w (Code' w)))}))
-(type: .public Code
+(type .public Code
(Ann Location (Code' (Ann Location))))
```
@@ -128,20 +128,20 @@ The beautiful thing is that `(' (you can use the "'" #macro [to generate {arbitr
```clojure
... Hygienic quasi-quotation as a macro.
-... Unquote (~) and unquote-splice (~+) must also be used as forms.
+... Unquote (,) and unquote-splice (,*) must also be used as forms.
... All unprefixed symbols will receive their parent module's prefix if imported; otherwise will receive the prefix of the module on which the quasi-quote is being used.
-(` (def (~ name)
- (function ((~ name) (~+ args))
- (~ body))))
+(` (def (, name)
+ (function ((, name) (,* args))
+ (, body))))
```
This is a variation on the `'` macro that allows you to do templating with the code you want to generate.
-Everything you write will be generated _as is_, except those forms which begin with `~` or `~+`.
+Everything you write will be generated _as is_, except those forms which begin with `,` or `,*`.
-`~` means: _evaluate this expression and use its `Code` value_.
+`,` means: _evaluate this expression and use its `Code` value_.
-`~+` means: _the value of this expression is a list of `Code`s, and I want to splice all of them in the surrounding `Code` node_.
+`,*` means: _the value of this expression is a list of `Code`s, and I want to splice all of them in the surrounding `Code` node_.
With these tools, you can introduce a lot of complexity and customization into your code generation, which would be a major hassle if you had to build the `Code` nodes yourself.
@@ -153,10 +153,10 @@ With these tools, you can introduce a lot of complexity and customization into y
```clojure
... Unhygienic quasi-quotation as a macro.
-... Unquote (~) and unquote-splice (~+) must also be used as forms.
-(`' (def (~ name)
- (function ((~ name) (~+ args))
- (~ body))))
+... Unquote (,) and unquote-splice (,*) must also be used as forms.
+(`' (def (, name)
+ (function ((, name) (,* args))
+ (, body))))
```
Finally, there is this variation, which removes the hygiene check.
@@ -170,7 +170,7 @@ Now that you know how to generate code like a pro, it's time to see how macros g
First, let's check the type of macros:
```clojure
-(type: .public Macro
+(type .public Macro
(primitive "#Macro"))
```
@@ -189,7 +189,7 @@ It does so by labelling macros (_type-wise_) with this funky type.
There is, however, another type which elucidates what is going on with macros.
```clojure
-(type: .public Macro'
+(type .public Macro'
(-> (List Code) (Meta (List Code))))
```
@@ -197,34 +197,36 @@ You might remember from the previous chapter that you can only access the `Lux`
Now, you can see how everything connects.
-You define macros by using the `macro:` macro (_so meta..._):
+You define macros by using the `macro` macro (_so meta..._):
```clojure
-(macro: .public (symbol tokens)
- (case tokens
- (^ (list [_ (.#Symbol [module name])]))
- (# meta.monad in (list (` [(~ (code.text module)) (~ (code.text name))])))
-
- _
- (meta.failure "Wrong syntax for 'symbol'.")))
+(def .public symbol
+ (macro (_ tokens)
+ (when tokens
+ (list [_ (.#Symbol [module name])])
+ (at meta.monad in (list (` [(, (code.text module)) (, (code.text name))])))
+
+ _
+ (meta.failure "Wrong syntax for 'symbol'."))))
```
Here's another example:
```clojure
-(macro: .public (else tokens state)
- (case tokens
- (^ (.list else maybe))
- (let [g!temp (macro.symbol "")]
- (.#Right [state (.list (` (case (~ maybe)
- {.#Some (~ g!temp)}
- (~ g!temp)
-
- {.#None}
- (~ else))))]))
-
- _
- (.#Left "Wrong syntax for else")))
+(def .public else
+ (macro (_ tokens state)
+ (when tokens
+ (list else maybe)
+ (let [g!temp (macro.symbol "")]
+ (.#Right [state (.list (` (when (, maybe)
+ {.#Some (, g!temp)}
+ (, g!temp)
+
+ {.#None}
+ (, else))))]))
+
+ _
+ (.#Left "Wrong syntax for else"))))
```
You may want to read [Appendix C](appendix_c.md) to learn about the pattern-matching macros used in these examples.
@@ -242,7 +244,7 @@ If any macros are used in the output, they will be _expanded_ further until only
You may be wondering what is the relationship between the `Macro` and `Macro'` types.
When you define a macro, you define it as a function, which is to say, a `Macro'` type.
But once it has been defined, it gets re-labelled as a `Macro`, so that way the Lux compiler can distinguish it from other functions.
- This is all done for you by the `macro:` macro, so there's no need to worry about it.
+ This is all done for you by the `macro` macro, so there's no need to worry about it.
---
diff --git a/documentation/book/the_lux_programming_language/chapter_11.md b/documentation/book/the_lux_programming_language/chapter_11.md
index a069c4c9e..4e131408e 100644
--- a/documentation/book/the_lux_programming_language/chapter_11.md
+++ b/documentation/book/the_lux_programming_language/chapter_11.md
@@ -17,14 +17,14 @@ The `library/lux/control/parser/code` module houses some powerful tools.
For starters, it's the home of the (_code_) `Parser` type:
```clojure
-(type: .public Parser
+(type .public Parser
(//.Parser (List Code)))
```
Which is based on the _generic_ `Parser` type from the `library/lux/control/parser` module:
```clojure
-(type: .public (Parser s a)
+(type .public (Parser s a)
(-> s (Try [s a])))
```
@@ -36,30 +36,31 @@ The `Parser` type works with streams of inputs instead of single elements, and i
There are many such code-parsers (and combinators) in the `library/lux/control/parser/code` module, and you should definitely take a look at what's available in the documentation.
-Then, in the `library/lux/macro/syntax` module, there is a mechanism for defining macros: the `syntax:` macro.
+Then, in the `library/lux/macro/syntax` module, there is a mechanism for defining macros: the `syntax` macro.
```clojure
-... A more advanced way to define macros than 'macro:'.
+... A more advanced way to define macros than 'macro'.
... The inputs to the macro can be parsed in complex ways through the use of syntax parsers.
... The macro body is also (implicitly) run in the Meta monad, to save some typing.
... Also, the compiler state can be accessed through the *lux* binding.
-(syntax: .public (object [.let [imports (class_imports *lux*)
- class_vars (list)]
- super (opt (super_class_decl^ imports class_vars))
- interfaces (tuple (some (super_class_decl^ imports class_vars)))
- constructor_args (constructor_args^ imports class_vars)
- methods (some (overriden_method_def^ imports))])
- (let [def_code ($_ text#composite "anon-class:"
- (spaced (list (super_class_decl$ (maybe.else object_super_class super))
- (with_brackets (spaced (list#each super_class_decl$ interfaces)))
- (with_brackets (spaced (list#each constructor_arg$ constructor_args)))
- (with_brackets (spaced (list#each (method_def$ id) methods))))))]
- (in (list (` ((~ (code.text def_code))))))))
+(def .public object
+ (syntax (_ [.let [imports (class_imports *lux*)
+ class_vars (list)]
+ super (opt (super_class_decl^ imports class_vars))
+ interfaces (tuple (some (super_class_decl^ imports class_vars)))
+ constructor_args (constructor_args^ imports class_vars)
+ methods (some (overriden_method_def^ imports))])
+ (let [def_code ($_ text#composite "anon-class:"
+ (spaced (list (super_class_decl$ (maybe.else object_super_class super))
+ (with_brackets (spaced (list#each super_class_decl$ interfaces)))
+ (with_brackets (spaced (list#each constructor_arg$ constructor_args)))
+ (with_brackets (spaced (list#each (method_def$ id) methods))))))]
+ (in (list (` ((, (code.text def_code)))))))))
```
This example is a macro for making anonymous _JVM_ classes that lives in `lux/ffi`.
-The difference between `macro:` and `syntax:` is that `syntax:` allows you to parse, in a structured manner, the inputs to your macro, thereby reducing considerably the complexity necessary for making _big_ macros.
+The difference between `macro` and `syntax` is that `syntax` allows you to parse, in a structured manner, the inputs to your macro, thereby reducing considerably the complexity necessary for making _big_ macros.
Also, because you're using code-parsers for the hard work, you can write reusable parsers that you can share throughout your macros, if you want to have common syntax.
@@ -67,7 +68,7 @@ You can even compose your parsers, or use parsers from someone else's library.
There are already some small modules under `library/lux/macro/syntax/` which house some reusable code-parsers and code-generators.
-Additionally, `syntax:` binds the `Lux` value on a variable called `*lux*`, so you can use it during your parsing.
+Additionally, `syntax` binds the `Lux` value on a variable called `*lux*`, so you can use it during your parsing.
What do those code-parsers look like?
@@ -78,25 +79,27 @@ Here is an example:
(.require
[library
- [lux "*"
+ [lux (.except)
[abstract
- [monad {"+" do}]]
+ [monad (.only do)]]
[control
- ["<>" parser ("[1]#[0]" functor)
- ["<[0]>" code {"+" Parser}]]]
+ ["<>" parser (.use "[1]#[0]" functor)]]
[data
["[0]" product]
[collection
- ["[0]" list ("[1]#[0]" mix)]]]
- [macro
- [syntax {"+" syntax:}]
- ["[0]" code]]
+ ["[0]" list (.use "[1]#[0]" mix)]]]
+ [meta
+ ["[0]" code
+ ["<[1]>" \\parser (.only Parser)]]
+ [macro
+ [syntax (.only syntax)]
+ ["[0]" code]]]
[math
[number
["n" nat]
["i" int]]]]])
-(type: Infix
+(type Infix
(Rec Infix
(Variant
{#Const Code}
@@ -141,7 +144,7 @@ And here are some examples of syntax macros:
(def (prefix infix)
(-> Infix Code)
- (case infix
+ (when infix
{#Const value}
value
@@ -149,46 +152,47 @@ And here are some examples of syntax macros:
(code.form parts)
{#Unary op subject}
- (` ((~ op) (~ (prefix subject))))
+ (` ((, op) (, (prefix subject))))
{#Binary left op right}
- (` ((~ op) (~ (prefix right)) (~ (prefix left))))))
+ (` ((, op) (, (prefix right)) (, (prefix left))))))
-(syntax: .public (infix [expr ..expression])
- (in (list (..prefix expr))))
+(def .public infix
+ (syntax (_ [expr ..expression])
+ (in (list (..prefix expr)))))
```
```clojure
-(syntax: .public (^stream& [patterns (<code>.form (<>.many <code>.any))
- body <code>.any
- branches (<>.some <code>.any)])
- (with_symbols [g!stream]
- (let [body+ (` (let [(~+ (|> patterns
- (list#each (function (_ pattern)
- (list (` [(~ pattern) (~ g!stream)])
- (` ((~! //.result) (~ g!stream))))))
- list#conjoint))]
- (~ body)))]
- (in (list& g!stream body+ branches)))))
+(def .public ^stream&
+ (syntax (_ [patterns (<code>.form (<>.many <code>.any))
+ body <code>.any
+ branches (<>.some <code>.any)])
+ (with_symbols [g!stream]
+ (let [body+ (` (let [(,* (|> patterns
+ (list#each (function (_ pattern)
+ (list (` [(, pattern) (, g!stream)])
+ (` ((,! //.result) (, g!stream))))))
+ list#conjoint))]
+ (, body)))]
+ (in (list& g!stream body+ branches))))))
```
```clojure
-(syntax: .public (cond> [_ _reversed_
- prev <code>.any
- else body^
- _ _reversed_
- branches (<>.some (<>.and body^ body^))])
- (with_symbols [g!temp]
- (in (list (` (let [(~ g!temp) (~ prev)]
- (cond (~+ (do list.monad
- [[test then] branches]
- (list (` (|> (~ g!temp) (~+ test)))
- (` (|> (~ g!temp) (~+ then))))))
- (|> (~ g!temp) (~+ else)))))))))
+(def .public cond>
+ (syntax (_ [_ _reversed_
+ prev <code>.any
+ else body^
+ _ _reversed_
+ branches (<>.some (<>.and body^ body^))])
+ (with_symbols [g!temp]
+ (in (list (` (let [(, g!temp) (, prev)]
+ (cond (,* (do list.monad
+ [[test then] branches]
+ (list (` (|> (, g!temp) (,* test)))
+ (` (|> (, g!temp) (,* then))))))
+ (|> (, g!temp) (,* else))))))))))
```
- By the way, the body of `syntax:` runs inside a `(do library/lux/meta.monad [] ...)` expression, so you have immediate access to `Monad`'s `in` method for simple macros, like the last one.
-
---
This may be a short chapter, but not because its subject is small.
diff --git a/documentation/book/the_lux_programming_language/chapter_12.md b/documentation/book/the_lux_programming_language/chapter_12.md
index fe30e5295..2d6b722c3 100644
--- a/documentation/book/the_lux_programming_language/chapter_12.md
+++ b/documentation/book/the_lux_programming_language/chapter_12.md
@@ -63,7 +63,7 @@ Well, by using types; of course!
If you head to the `library/lux/control/io` module, you will find the following type definition:
```clojure
-(abstract: .public (IO a)
+(primitive .public (IO a)
...
)
```
diff --git a/documentation/book/the_lux_programming_language/chapter_13.md b/documentation/book/the_lux_programming_language/chapter_13.md
index 8fbd4b85d..f522a2e2c 100644
--- a/documentation/book/the_lux_programming_language/chapter_13.md
+++ b/documentation/book/the_lux_programming_language/chapter_13.md
@@ -26,12 +26,12 @@ Let's explore them.
## Importing classes, methods, and fields
-It's all done with the help of the `import:` macro:
+It's all done with the help of the `import` macro:
```clojure
... Allows importing JVM classes, and using them as types.
... Their methods, fields and enum options can also be imported.
-(import: java/lang/Object
+(import java/lang/Object
["[1]::[0]"
(new [])
(equals [java/lang/Object] boolean)
@@ -42,31 +42,31 @@ It's all done with the help of the `import:` macro:
... "try" means that the computation might throw an exception, and the return value will be wrapped inside the Try type.
... "io" means the computation has side effects, and will be wrapped inside the IO type.
... These options must show up in the following order ["io" "try" "?"] (although, each option can be used independently).
-(import: java/lang/String
+(import java/lang/String
["[1]::[0]"
(new [[byte]])
("static" valueOf [char] java/lang/String)
("static" valueOf "as" int_valueOf [int] java/lang/String)])
-(import: (java/util/List e)
+(import (java/util/List e)
["[1]::[0]"
(size [] int)
(get [int] e)])
-(import: (java/util/ArrayList a)
+(import (java/util/ArrayList a)
["[1]::[0]"
([T] toArray [[T]] [T])])
... The class-type that is generated is of the fully-qualified name.
... This avoids a clash between the java.util.List type, and Lux's own List type.
... All enum options to be imported must be specified.
-(import: java/lang/Character$UnicodeScript
+(import java/lang/Character$UnicodeScript
["[1]::[0]"
("enum" ARABIC CYRILLIC LATIN)])
... It should also be noted, the types that show up in method arguments or return values may only be Java classes, arrays, primitives, void or type-vars.
... Lux types, such as Maybe cannot be used (otherwise, they'd be confused for Java classes).
-(import: (lux/concurrency/async/JvmAsync A)
+(import (lux/concurrency/async/JvmAsync A)
["[1]::[0]"
(resolve [A] boolean)
(poll [] A)
@@ -90,18 +90,18 @@ As you have noticed, it works by creating functions for all the class members yo
It also creates Lux type definitions matching the classes you import, so that you may easily refer to them when you write your own types later in regular Lux code.
- It must be noted that `import:` requires that you only import methods and fields from their original declaring classes/interfaces.
+ It must be noted that `import` requires that you only import methods and fields from their original declaring classes/interfaces.
What that means is that if class `A` declares/defines method `foo`, and class `B` extends `A`; to import `foo`, you must do it by importing it from `A`, instead of `B`.
## Writing classes
-Normally, you'd use the `class:` macro:
+Normally, you'd use the `class` macro:
```clojure
... Allows defining JVM classes in Lux code.
... For example:
-(class: "final" (TestClass A) [Runnable]
+(class "final" (TestClass A) [Runnable]
... Fields
("private" foo boolean)
("private" bar A)
@@ -109,9 +109,9 @@ Normally, you'd use the `class:` macro:
... Methods
("public" [] (new [value A]) []
(exec
- (:= ::foo #1)
- (:= ::bar value)
- (:= ::baz "")
+ (set foo #1)
+ (set bar value)
+ (set baz "")
[]))
("public" (virtual) java/lang/Object
"")
@@ -125,10 +125,10 @@ Normally, you'd use the `class:` macro:
... An optional super-class can be specified before the tuple. If not specified, java.lang.Object will be assumed.
... Fields and methods defined in the class can be used with special syntax.
... For example:
-... ::resolved, for accessing the 'resolved' field.
-... (:= ::resolved #1) for modifying it.
-... (::new! []) for calling the class's constructor.
-... (::resolve! container [value]) for calling the 'resolve' method.
+... (get resolved), for accessing the 'resolved' field.
+... (set resolved #1) for modifying it.
+... (new! []) for calling the class's constructor.
+... (resolve! container [value]) for calling the 'resolve' method.
```
And, for anonymous classes, you'd use `object`:
@@ -161,7 +161,7 @@ And, for anonymous classes, you'd use `object`:
```clojure
... Checks whether an object is an instance of a particular class.
... Caveat emptor: Can't check for polymorphism, so avoid using parameterized classes.
-(case (check java/lang/String "YOLO")
+(when (check java/lang/String "YOLO")
{.#Some value_as_string}
{.#None})
```
@@ -181,12 +181,12 @@ Calling multiple methods consecutively
```clojure
... Call a variety of methods on an object. Then, return the object.
-(do_to object
+(to object
(ClassName::method1 arg0 arg1 arg2)
(ClassName::method2 arg3 arg4 arg5))
```
- `do_to` is inspired by Clojure's own doto macro.
+ `to` is inspired by Clojure's own `doto` macro.
The difference is that, whereas Clojure's version pipes the object as the first argument to the method, Lux's pipes it at the end (which is where method functions take their object values).
The `library/lux/ffi` module offers much more, but you'll have to discover it yourself by heading over to [the documentation for the Standard Library](https://github.com/LuxLang/lux/tree/master/documentation/library/standard).
diff --git a/documentation/book/the_lux_programming_language/chapter_14.md b/documentation/book/the_lux_programming_language/chapter_14.md
index 2fd53c5bb..366f6a740 100644
--- a/documentation/book/the_lux_programming_language/chapter_14.md
+++ b/documentation/book/the_lux_programming_language/chapter_14.md
@@ -120,7 +120,7 @@ Also, interaction with actors is based on _message-passing_, and an actor may co
The relevant module is the `library/lux/control/concurrency/actor` module, and the relevant type is:
```clojure
-(abstract: .public (Actor s)
+(primitive .public (Actor s)
...
)
```
@@ -136,47 +136,27 @@ Just from this definition, it's easy to see that actors are stateful (a necessit
To create an actor, you must first specify its `Behavior`:
```clojure
-(type: .public (Behavior o s)
- (Record
- [#on_init (-> o s)
- #on_mail (-> (Mail s) s (Actor s) (Async (Try s)))]))
+(type .public (Behavior s)
+ (-> (Mail s) s (Actor s) (Async (Try s))))
```
-These functions know how to initialize an actor, and how to react to incoming mail.
+This function knows how to react to incoming mail.
You can then call the `spawn!` function with an initial state and a `Behavior`.
But writing complex actors with multiple options for its messages can be messy with these tools, so a macro was made to simplify that.
```clojure
-... Defines a named actor, with its behavior and internal state.
-... Messages for the actor must be defined after the on_mail handler.
-(actor: .public (stack a)
- (List a)
-
- ((on_mail mail state self)
- (do (try.with async.monad)
- [.let [_ (debug.log! "BEFORE")]
- output (mail state self)
- .let [_ (debug.log! "AFTER")]]
- (in output)))
-
- (message: .public (push [value a] state self)
- Nat
- (let [state' {.#Item value state}]
- (async.resolved {try.#Success [state' (list.size state')]}))))
-
-(actor: .public counter
- Nat
-
- (message: .public (count! [increment Nat] state self)
- Any
+(def counter
+ (/.Behavior Nat)
+ (function (_ message state self)
+ (message state self)))
+
+(def (count! increment)
+ (-> Nat (/.Message Nat Nat))
+ (function (_ state self)
(let [state' (n.+ increment state)]
- (async.resolved {try.#Success [state' []]})))
-
- (message: .public (read! [] state self)
- Nat
- (async.resolved {try.#Success [state state]})))
+ (async#in {try.#Success [state' state']}))))
```
For every message type you define, a function will be defined in your module with the same name, and taking the same arguments, plus the actor.
diff --git a/documentation/book/the_lux_programming_language/chapter_16.md b/documentation/book/the_lux_programming_language/chapter_16.md
index 72f9e3616..111af0854 100644
--- a/documentation/book/the_lux_programming_language/chapter_16.md
+++ b/documentation/book/the_lux_programming_language/chapter_16.md
@@ -22,7 +22,7 @@ Let's take a look at the `project.lux` file for the Lux standard library itself.
```clojure
[""
- ["identity" ["com.github.luxlang" "stdlib" "0.6.5"]
+ ["identity" ["com.github.luxlang" "stdlib" "0.7.0"]
"deploy_repositories" ["snapshots" "https://oss.sonatype.org/content/repositories/snapshots/"
"releases" "https://oss.sonatype.org/service/local/staging/deploy/maven2/"]
@@ -31,11 +31,11 @@ Let's take a look at the `project.lux` file for the Lux standard library itself.
"https://oss.sonatype.org/service/local/staging/deploy/maven2/"]]
"jvm"
- ["compiler" ["com.github.luxlang" "lux-jvm" "0.6.5" "jar"]]
+ ["lux" ["com.github.luxlang" "lux-jvm" "0.7.0" "jar"]]
"bibliotheca"
- ["info" ["description" "Standard Library for the Lux programming language."]
- "test" "test/lux"]
+ ["info" ["description" "Standard library for the Lux programming language."]
+ "test" test/lux._]
]
```
@@ -46,16 +46,22 @@ Here is a summary of the file:
```clojure
(.require
[library
- ["/" lux "*"
- [program {"+" program:}]
- ["_" test {"+" Test}]
+ ["/" lux (.except)
+ [program (.only program)]
+ [test
+ ["_" property (.only Test)]]
[control
["[0]" io]]
...
]])
-(program: args
- (io.io (_.run! (_.times 100 ..test))))
+...
+...
+...
+
+(def _
+ (program args
+ (io.io (_.run! (_.times 100 ..test)))))
```
@@ -82,17 +88,18 @@ To know how tests work, let's take a look at one of those modules.
```clojure
(.require
[library
- [lux "*"
- ["_" test {"+" Test}]
+ [lux (.except)
+ [test
+ ["_" property (.only Test)]]
[abstract
- [monad {"+" do}]
+ [monad (.only do)]
[\\specification
["$[0]" equivalence]
- ["$[0]" functor {"+" Injection}]]]
+ ["$[0]" functor (.only Injection)]]]
[control
["[0]" maybe]]
[data
- ["[0]" bit ("[1]#[0]" equivalence)]]
+ ["[0]" bit (.use "[1]#[0]" equivalence)]]
[math
["[0]" random]
[number
@@ -109,7 +116,7 @@ To know how tests work, let's take a look at one of those modules.
(<| (_.covering /._)
(_.for [/.Stack])
(do random.monad
- [size (# random.monad map (n.% 100) random.nat)
+ [size (at random.monad map (n.% 100) random.nat)
sample (random.stack size random.nat)
expected_top random.nat]
($_ _.and
@@ -118,37 +125,37 @@ To know how tests work, let's take a look at one of those modules.
(_.for [/.functor]
($functor.spec ..injection /.equivalence /.functor))
- (_.cover [/.size]
- (n.= size (/.size sample)))
- (_.cover [/.empty?]
- (bit#= (n.= 0 (/.size sample))
- (/.empty? sample)))
- (_.cover [/.empty]
- (/.empty? /.empty))
- (_.cover [/.value]
- (case (/.value sample)
- {.#None}
- (/.empty? sample)
-
- {.#Some _}
- (not (/.empty? sample))))
- (_.cover [/.next]
- (case (/.next sample)
- {.#None}
- (/.empty? sample)
-
- {.#Some [top remaining]}
- (# (/.equivalence n.equivalence) =
- sample
- (/.top top remaining))))
- (_.cover [/.top]
- (case (/.next (/.top expected_top sample))
- {.#Some [actual_top actual_sample]}
- (and (same? expected_top actual_top)
- (same? sample actual_sample))
-
- {.#None}
- false))
+ (_.coverage [/.size]
+ (n.= size (/.size sample)))
+ (_.coverage [/.empty?]
+ (bit#= (n.= 0 (/.size sample))
+ (/.empty? sample)))
+ (_.coverage [/.empty]
+ (/.empty? /.empty))
+ (_.coverage [/.value]
+ (when (/.value sample)
+ {.#None}
+ (/.empty? sample)
+
+ {.#Some _}
+ (not (/.empty? sample))))
+ (_.coverage [/.next]
+ (when (/.next sample)
+ {.#None}
+ (/.empty? sample)
+
+ {.#Some [top remaining]}
+ (at (/.equivalence n.equivalence) =
+ sample
+ (/.top top remaining))))
+ (_.coverage [/.top]
+ (when (/.next (/.top expected_top sample))
+ {.#Some [actual_top actual_sample]}
+ (and (same? expected_top actual_top)
+ (same? sample actual_sample))
+
+ {.#None}
+ false))
))))
```
@@ -159,7 +166,7 @@ First of all, by using the `covering` macro, you can tell the test suit to track
That way, if your tests miss some _exported/public_ definitions, the report you'll get after running the tests will tell you, so you can judiciously choose to either expand your coverage, or skip covering them.
-The `for` and `cover` macros then signal whenever one or more definitions are being covered by a given test.
+The `for` and `coverage` macros then signal whenever one or more definitions are being covered by a given test.
Lux also defines some _specifications_, which are basically parameterizable tests, which implement consistent testing for various interfaces in the standard library.
diff --git a/documentation/book/the_lux_programming_language/chapter_17.md b/documentation/book/the_lux_programming_language/chapter_17.md
index e13693d89..ef2195e07 100644
--- a/documentation/book/the_lux_programming_language/chapter_17.md
+++ b/documentation/book/the_lux_programming_language/chapter_17.md
@@ -31,7 +31,7 @@ Sadly, the ideal world can only exist within our dreams, but (as of v0.6) steps
Currently, it is possible to write Lux programs that compile to the following target platforms:
-* Java Virtual Machines
+* Java virtual machines
* JavaScript interpreters (such as browsers, and Node JS)
* Python interpreters
* Lua interpreters
@@ -66,16 +66,16 @@ And this also means that Lux's concurrency mechanisms work as expected on the JV
In order to compile a Lux program to any of these alternative platforms, you must use a different compiler for each.
-An Aedifex `project.lux` file allows for a `"compiler"` option to specify (as a dependency) the compiler you wish to use.
+An Aedifex `project.lux` file allows for a `"lux"` option to specify (as a dependency) the (Lux) compiler you wish to use.
-This option can be omitted, in which case it will pick, as a default value: `["com.github.luxlang" "lux-jvm" "0.6.5" "jar"]`.
+This option can be omitted, in which case it will pick, as a default value: `["com.github.luxlang" "lux-jvm" "0.7.0" "jar"]`.
Here are the compilers for the alternative platforms:
-* For JavaScript: `["com.github.luxlang" "lux-js" "0.6.5" "js"]`
-* For Python: `["com.github.luxlang" "lux-python" "0.6.5" "jar"]`
-* For Lua: `["com.github.luxlang" "lux-lua" "0.6.5" "jar"]`
-* For Ruby: `["com.github.luxlang" "lux-ruby" "0.6.5" "jar"]`
+* For JavaScript: `["com.github.luxlang" "lux-js" "0.7.0" "js"]`
+* For Python: `["com.github.luxlang" "lux-python" "0.7.0" "jar"]`
+* For Lua: `["com.github.luxlang" "lux-lua" "0.7.0" "jar"]`
+* For Ruby: `["com.github.luxlang" "lux-ruby" "0.7.0" "jar"]`
You don't need to use any special command on Aedifex in order to compile Lux to any alternative platform.
@@ -132,40 +132,40 @@ To give you an example of `for` in action, here is a definition from the `librar
(def .public (replaced pattern replacement template)
(-> Text Text Text Text)
(for [@.old
- (:as Text
- ("jvm invokevirtual:java.lang.String:replace:java.lang.CharSequence,java.lang.CharSequence"
- (:as (Primitive "java.lang.String") template)
- (:as (Primitive "java.lang.CharSequence") pattern)
- (:as (Primitive "java.lang.CharSequence") replacement)))
+ (as Text
+ ("jvm invokevirtual:java.lang.String:replace:java.lang.CharSequence,java.lang.CharSequence"
+ (as (Primitive "java.lang.String") template)
+ (as (Primitive "java.lang.CharSequence") pattern)
+ (as (Primitive "java.lang.CharSequence") replacement)))
@.jvm
- (:as Text
- ("jvm member invoke virtual" [] "java.lang.String" "replace" []
- (:as (Primitive "java.lang.String") template)
- ["Ljava/lang/CharSequence;" (:as (Primitive "java.lang.CharSequence") pattern)]
- ["Ljava/lang/CharSequence;" (:as (Primitive "java.lang.CharSequence") replacement)]))
+ (as Text
+ ("jvm member invoke virtual" [] "java.lang.String" "replace" []
+ (as (Primitive "java.lang.String") template)
+ ["Ljava/lang/CharSequence;" (as (Primitive "java.lang.CharSequence") pattern)]
+ ["Ljava/lang/CharSequence;" (as (Primitive "java.lang.CharSequence") replacement)]))
... TODO: Comment/turn-off when generating a JS compiler using a JVM-based compiler because Nashorn's implementation of "replaceAll" is incorrect.
@.js
- (:as Text
- ("js object do" "replaceAll" template [pattern replacement]))
+ (as Text
+ ("js object do" "replaceAll" template [pattern replacement]))
@.python
- (:as Text
- ("python object do" "replace" template pattern replacement))
+ (as Text
+ ("python object do" "replace" template pattern replacement))
... TODO @.lua
@.ruby
- (:as Text
- ("ruby object do" "gsub" template pattern replacement))
+ (as Text
+ ("ruby object do" "gsub" template pattern replacement))
@.php
- (:as Text
- ("php apply" (:expected ("php constant" "str_replace"))
- pattern replacement template))
+ (as Text
+ ("php apply" (expected ("php constant" "str_replace"))
+ pattern replacement template))
... TODO @.scheme
... TODO @.common_lisp
... TODO @.r
]
... Inefficient default
- (loop [left ""
- right template]
- (case (..split_by pattern right)
+ (loop (again [left ""
+ right template])
+ (when (..split_by pattern right)
{.#Some [pre post]}
(again ($_ "lux text concat" left pre replacement) post)
@@ -193,7 +193,7 @@ However, it is possible to specify that a file contains code that is only meant
* For Lua: `foo.lua.lux`
* For Ruby: `foo.rb.lux`
-If you're using, let's say, the JavaScript compiler for Lux (i.e. `["com.github.luxlang" "lux-js" "0.6.5" "js"]`), whenever you import a module as a dependency, the compiler will first look for a file with the `.js.lux` extension, and if it fails to find one, it will look for a file with the plain `.lux` extension.
+If you're using, let's say, the JavaScript compiler for Lux (i.e. `["com.github.luxlang" "lux-js" "0.7.0" "js"]`), whenever you import a module as a dependency, the compiler will first look for a file with the `.js.lux` extension, and if it fails to find one, it will look for a file with the plain `.lux` extension.
_What happens if I do not have a `.js.lux` file, but I do have files with the other special extensions?_
diff --git a/documentation/book/the_lux_programming_language/chapter_18.md b/documentation/book/the_lux_programming_language/chapter_18.md
index 83a87f1ae..bf1ad9108 100644
--- a/documentation/book/the_lux_programming_language/chapter_18.md
+++ b/documentation/book/the_lux_programming_language/chapter_18.md
@@ -87,14 +87,8 @@ The first type of extension we'll see is the `Analysis` extension:
```clojure
(.require
[library
- [lux "*"
- [extension {"+" [analysis: synthesis: generation:]}]
- ["@" target
- ["[0]" jvm]
- ["[0]" js]
- ["[0]" python]
- ["[0]" lua]
- ["[0]" ruby]]
+ [lux (.only)
+ [extension (.only analysis synthesis generation)]
[abstract
["[0]" monad {"+" [do]}]]
[control
@@ -105,19 +99,26 @@ The first type of extension we'll see is the `Analysis` extension:
[data
[collection
["[0]" sequence]]]
- [tool
- [compiler
- ["[0]" phase]
- [language
- [lux
- ["[0]" analysis]
- ["[0]" synthesis]
- ["[0]" directive]
- [phase
- [analysis
- ["[0]" type]]]]]]]]])
-
-(analysis: ("my triple" self phase archive [elementC <code>.any])
+ [meta
+ ["@" target
+ ["[0]" jvm]
+ ["[0]" js]
+ ["[0]" python]
+ ["[0]" lua]
+ ["[0]" ruby]]
+ [tool
+ [compiler
+ ["[0]" phase]
+ [language
+ [lux
+ ["[0]" analysis]
+ ["[0]" synthesis]
+ ["[0]" directive]
+ [phase
+ [analysis
+ ["[0]" type]]]]]]]]]])
+
+(analysis ("my triple" self phase archive [elementC <code>.any])
(do phase.monad
[[type elementA] (type.with_inference
(phase archive elementC))
@@ -165,14 +166,14 @@ Also, you might have noticed that, besides the input code we're parsing, our ext
---
```clojure
-(analysis: ("my quadruple" self phase archive [elementC <code>.any])
+(analysis ("my quadruple" self phase archive [elementC <code>.any])
(do phase.monad
[[type elementA] (type.with_inference
(phase archive elementC))
_ (type.infer (.Tuple type type type type))]
(in {analysis.#Extension self (list elementA)})))
-(synthesis: ("my quadruple" self phase archive [elementA <analysis>.any])
+(synthesis ("my quadruple" self phase archive [elementA <analysis>.any])
(do phase.monad
[elementS (phase archive elementA)]
(in (synthesis.tuple (list elementS elementS elementS elementS)))))
@@ -187,14 +188,14 @@ Currently, the optimization infrastructure Lux provides is not very sophisticate
---
```clojure
-(analysis: ("my quintuple" self phase archive [elementC <code>.any])
+(analysis ("my quintuple" self phase archive [elementC <code>.any])
(do phase.monad
[[type elementA] (type.with_inference
(phase archive elementC))
_ (type.infer (.Tuple type type type type type))]
(in {analysis.#Extension self (list elementA)})))
-(generation: ("my quintuple" self phase archive [elementS <synthesis>.any])
+(generation ("my quintuple" self phase archive [elementS <synthesis>.any])
(do phase.monad
[elementG (phase archive elementS)]
(in (for {@.jvm (row.row (#jvm.Embedded elementG)
diff --git a/documentation/book/the_lux_programming_language/chapter_2.md b/documentation/book/the_lux_programming_language/chapter_2.md
index ed1a5620f..166210d29 100644
--- a/documentation/book/the_lux_programming_language/chapter_2.md
+++ b/documentation/book/the_lux_programming_language/chapter_2.md
@@ -84,7 +84,7 @@ Examples of directives are `.require` declarations at the top of modules, and de
## Programs
-Lux doesn't have special "main" functions/procedures/methods that you define, but the `program:` macro accomplishes the same thing and works similarly.
+Lux doesn't have special "main" functions/procedures/methods that you define, but the `program` macro accomplishes the same thing and works similarly.
It takes a list of command-line inputs and must produce some sort of action to be performed as the program's behavior.
@@ -94,7 +94,7 @@ That action must be of type `(IO Any)`, which just means it is a synchronous pro
Lux programs can have graphical user interfaces, and in the future they may run in various environments with much different means of interfacing with users, or other programs.
-But as a bare minimum, the Lux standard library provides the means to implement command-line interfaces, through the functionality in the `library/lux/control/parser/cli` module.
+But as a bare minimum, the Lux standard library provides the means to implement command-line interfaces, through the functionality in the `parser/lux/program` module.
That module implements a variety of parsers for implementing rich command-line argument processing, and you should definitely take a look at it once you're ready to write your first serious Lux program.
@@ -114,14 +114,15 @@ In the previous chapter we compiled and ran a Lux program, but nothing has been
... This will be our program's main module.
(.require
[library
- [lux "*"
- [program {"+" program:}]
+ [lux (.except)
+ [program (.only program)]
["[0]" debug]
[control
["[0]" io]]]])
-(program: args
- (io.io (debug.log! "Hello, world!")))
+(def main
+ (program args
+ (io.io (debug.log! "Hello, world!"))))
```
The first part of this program specifies which dependencies we `require`.
@@ -136,7 +137,7 @@ Then we import the `library/lux/control/io` module. We're giving this module an
Notice how we express nested modules (up to arbitrary depths) by simply nesting in brackets.
-Finally, we import the `library/lux/program` module. Notice how the syntax is a bit different in this case. Here, we're saying that we don't want to locally import any definition within it, except `program:`. We use a similar syntax when importing the `library/lux` module, except with an asterisk instead of a plus sign. That just means we want to locally import all the public definitions, instead of just listing the ones we want.
+Finally, we import the `library/lux/program` module. Notice how the syntax is a bit different in this case. Here, we're saying that we don't want to locally import any definition within it, only `program`. We use a similar syntax when importing the `library/lux` module. That just means we want to locally import all the public definitions, except none.
Now, let's analyse the actual code!
diff --git a/documentation/book/the_lux_programming_language/chapter_3.md b/documentation/book/the_lux_programming_language/chapter_3.md
index 8565e24e3..ef2aa4433 100644
--- a/documentation/book/the_lux_programming_language/chapter_3.md
+++ b/documentation/book/the_lux_programming_language/chapter_3.md
@@ -161,62 +161,62 @@ Patience, young grasshopper. We'll talk about those in the next chapter.
For now, let's talk about **types**.
-The type-annotation macro is called `:` (I know, _real cute_). You use it like this: `(: Some_Type some_value)`.
+The type-annotation macro is called `is`. You use it like this: `(is Some_Type some_value)`.
-There is also a separate macro for type-coerciones that's called `:as`, which is used the same way. However, you should probably steer clear off that one, unless you know what you're doing, since you can trick the compiler into thinking a value belongs to any type you want by using it.
+There is also a separate macro for type-coerciones that's called `as`, which is used the same way. However, you should probably steer clear off that one, unless you know what you're doing, since you can trick the compiler into thinking a value belongs to any type you want by using it.
Now that we know about type annotations, I'll show you some types by giving you some valid Lux expressions:
```clojure
-(: Bit #1)
-(: Bit .true)
-(: Nat 123)
-(: Int -123)
-(: Rev .789)
-(: Frac +456.789)
-(: Text "YOLO")
-
-(type: Some_Enum
+(is Bit #1)
+(is Bit .true)
+(is Nat 123)
+(is Int -123)
+(is Rev .789)
+(is Frac +456.789)
+(is Text "YOLO")
+
+(type Some_Enum
(Variant
{#Primitive}
{#Variant}
{#Tuple}))
-(: [Int [Text Some_Enum] Bit]
- [10 ["nested" {#Tuple}] .false])
+(is [Int [Text Some_Enum] Bit]
+ [10 ["nested" {#Tuple}] .false])
-(type: Quux
+(type Quux
(Variant
{#Foo}
{#Bar Int Frac Text}))
-(: Quux {#Foo})
+(is Quux {#Foo})
-(: Quux {#Bar 10 +20.0 "thirty"})
+(is Quux {#Bar 10 +20.0 "thirty"})
-(type: Lang
+(type Lang
(Record
[#name Text
#paradigm Paradigm
#platforms (List Platform)]))
-(: Lang
- [#name "Lux"
- #paradigm {#Functional}
- #platforms (list {#JVM})])
+(is Lang
+ [#name "Lux"
+ #paradigm {#Functional}
+ #platforms (list {#JVM})])
-(: Lang
- ["Lux" {#Functional} (list {#JVM})])
+(is Lang
+ ["Lux" {#Functional} (list {#JVM})])
-(: [Text Paradigm (List Platform)]
- [#name "Lux"
- #paradigm {#Functional}
- #platforms (list {#JVM})])
+(is [Text Paradigm (List Platform)]
+ [#name "Lux"
+ #paradigm {#Functional}
+ #platforms (list {#JVM})])
```
- By the way, the value of a type-annotation or a type-coearcion expression is just the value being annotated/coerced. So `(: Bit #1)` simply yields `#1`.
+ By the way, the value of a type-annotation or a type-coearcion expression is just the value being annotated/coerced. So `(is Bit #1)` simply yields `#1`.
-_What is that `type:` thingie?_
+_What is that `type` thingie?_
It's just a macro for defining types. We'll learn more about it in a future chapter.
diff --git a/documentation/book/the_lux_programming_language/chapter_4.md b/documentation/book/the_lux_programming_language/chapter_4.md
index 201d0cc28..210cea258 100644
--- a/documentation/book/the_lux_programming_language/chapter_4.md
+++ b/documentation/book/the_lux_programming_language/chapter_4.md
@@ -23,8 +23,8 @@ What is its type?
Well, I'm glad you asked.
```clojure
-(: (-> Nat Nat)
- (function (plus_two x) (++ (++ x))))
+(is (-> Nat Nat)
+ (function (plus_two x) (++ (++ x))))
```
That `->` thingie you see there is a macro for generating function types.
@@ -53,9 +53,9 @@ Well, we just need to define it!
```clojure
(def plus_two
- (: (-> Nat Nat)
- (function (_ x)
- (++ (++ x)))))
+ (is (-> Nat Nat)
+ (function (_ x)
+ (++ (++ x)))))
```
Or, alternatively:
diff --git a/documentation/book/the_lux_programming_language/chapter_5.md b/documentation/book/the_lux_programming_language/chapter_5.md
index fe36dc46d..1f92eff6f 100644
--- a/documentation/book/the_lux_programming_language/chapter_5.md
+++ b/documentation/book/the_lux_programming_language/chapter_5.md
@@ -31,9 +31,9 @@ Where `test`, `then` and `else` are arbitrary Lux expressions.
In terms of types, it works like this:
```clojure
-(: X (if (: Bit test)
- (: X then)
- (: X else)))
+(is X (if (is Bit test)
+ (is X then)
+ (is X else)))
```
Here is an example:
@@ -65,11 +65,11 @@ It looks like this:
And, in terms of types, it looks like this:
```clojure
-(: X (cond (: Bit test-1) (: X then-1)
- (: Bit test-2) (: X then-2)
- ...
- (: Bit test-n) (: X then-n)
- (: X else)))
+(is X (cond (is Bit test-1) (is X then-1)
+ (is Bit test-2) (is X then-2)
+ ...
+ (is Bit test-n) (is X then-n)
+ (is X else)))
```
Here is an example:
@@ -102,13 +102,13 @@ For instance, the `factorial'` function you saw in the previous chapter could ha
```clojure
(def (factorial' acc n)
(-> Nat Nat Nat)
- (case n
+ (when n
0 acc
_ (factorial' (n.* n acc) (-- n))
))
```
-As you may imagine, `case` is the pattern-matching macro.
+As you may imagine, `when` is the pattern-matching macro.
It takes the data you want to pattern-match against (in this case, the `n` variable), and then tests it against several patterns until it finds a match, in which case it executes its branch.
@@ -123,7 +123,7 @@ However, since it is binding a variable, that means we could have used `_` inste
```clojure
(def (factorial' acc n)
(-> Nat Nat Nat)
- (case n
+ (when n
0 acc
_ (factorial' (n.* _ acc) (-- _))
))
@@ -141,14 +141,14 @@ Here are a couple more examples so you can see the possibilities.
```clojure
(let [test true]
- (case test
+ (when test
#1 "Oh, yeah!"
#0 "Aw, hell naw!"
))
```
```clojure
-(case (list 1 2 3)
+(when (list 1 2 3)
{.#Item x {.#Item y {.#Item z {.#End}}}}
{.#Some (n.+ x (n.* y z))}
@@ -165,25 +165,25 @@ Also, you'll notice the introduction of a new macro, called `let`.
Its syntax looks like this:
```clojure
-(: X (let [var-1 expr-1
- var-2 expr-2
- ...
- var-n expr-n]
- (: X body)))
+(is X (let [var-1 expr-1
+ var-2 expr-2
+ ...
+ var-n expr-n]
+ (is X body)))
```
Where the types of the variables will correspond to those of their matching expressions, and the type of the `let` expression will be the same as that of its body.
Also, remember when I told you that you can use pattern-matching to bind variables?
-Well, guess what! `let` is implemented in terms of `case`, and it just gives you a more convenient way to bind variables than to go through all the trouble of doing pattern-matching.
+Well, guess what! `let` is implemented in terms of `when`, and it just gives you a more convenient way to bind variables than to go through all the trouble of doing pattern-matching.
Now, in the second example, we're deconstructing a list in order to extract its individual elements.
The `List` type is defined like this:
```clojure
-(type: (List a)
+(type (List a)
{#End}
{#Item a (List a)})
```
@@ -271,8 +271,8 @@ To see it in action, let's rewrite (once more!) our `factorial` function:
```clojure
(def (factorial n)
(-> Nat Nat)
- (loop [acc 1
- n n]
+ (loop (again [acc 1
+ n n])
(if (n.= +0 n)
acc
(again (n.* n acc) (-- n)))))
@@ -348,7 +348,7 @@ It's time to put that theory into practice... with an example:
```clojure
(def (iterate_list f list)
(All (_ a b) (-> (-> a b) (List a) (List b)))
- (case list
+ (when list
{.#End}
{.#End}
diff --git a/documentation/book/the_lux_programming_language/chapter_6.md b/documentation/book/the_lux_programming_language/chapter_6.md
index 61582d1bf..930d1bff6 100644
--- a/documentation/book/the_lux_programming_language/chapter_6.md
+++ b/documentation/book/the_lux_programming_language/chapter_6.md
@@ -9,7 +9,7 @@ We've talked about Lux types already, but only in a very high-level way.
On this chapter, you'll see how types are constructed, and hopefully that will give you some insight to understand better the subjects of later chapters.
```clojure
-(type: .public Type
+(type .public Type
(Rec Type
(Variant
{#Primitive Text (List Type)}
@@ -124,7 +124,7 @@ So, another way of thinking of `Nothing` is as the type of failed/erroneous comp
You can think of it as the super-type of all other types: the type of all values.
-This means that not only `(: Nat 123)`, but also `(: Any 123)`.
+This means that not only `(is Nat 123)`, but also `(is Any 123)`.
This works because `Any` does not give you any specific information about a value, it only tells you that a value exists, regardless of what its specific type happens to be.
@@ -141,7 +141,7 @@ You might think that dummy values are, well, _dumb_, but they show up all the ti
Consider the `Maybe` type:
```clojure
-(type: .public (Maybe a)
+(type .public (Maybe a)
(Variant
{#None}
{#Some a}))
@@ -162,7 +162,7 @@ Well, `Any`thing, really.
So the type definition for `Maybe` is equivalent to this:
```clojure
-(type: .public (Maybe a)
+(type .public (Maybe a)
{#None Any} ... Alternatively, {#None []}
{#Some a})
```
@@ -317,13 +317,13 @@ That may sound odd (if you come from Java or other languages with nominal types)
`#Named` gives Lux's type-system a bit of a nominal feel for the convenience of programmers.
-## Regarding Error Messages
+## Regarding error messages
When you get error messages from the type-checker during your coding sessions, types will show up in intuitive ways most of the time, with a few exceptions you might want to know about.
-Existential types show up in error messages like `⟨e:246⟩` (where 246 is the ID of the type).
+Existential types show up in error messages like `+246` (where 246 is the ID of the type).
-Whereas type-variables show up like `⌈v:278⌋`.
+Whereas type-variables show up like `-278`.
Those types tend to show up when there are errors in the definition of some polymorphic function.
diff --git a/documentation/book/the_lux_programming_language/chapter_7.md b/documentation/book/the_lux_programming_language/chapter_7.md
index 5c828585d..664d30592 100644
--- a/documentation/book/the_lux_programming_language/chapter_7.md
+++ b/documentation/book/the_lux_programming_language/chapter_7.md
@@ -63,20 +63,20 @@ They have a list of expected member values/functions, with their associated type
Here's an example:
```clojure
-(type: .public (Order a)
+(type .public (Order a)
(Interface
- (: (Equivalence a)
- &equivalence)
+ (is (Equivalence a)
+ equivalence)
- (: (-> a a Bit)
- <)))
+ (is (-> a a Bit)
+ <)))
```
That _interface_ definition comes from the `library/lux/abstract/order` module, and it deals with _ordered_ types; that is, types for which you can compare their values in ways that imply some sort of sequential order.
It's polymorphic/parameterized because this interface must be able to adapt to any type that fits its requirements.
-Also, you may notice that it has a member called `&equivalence`, of type `(Equivalence a)`.
+Also, you may notice that it has a member called `equivalence`, of type `(Equivalence a)`.
The reason is that interfaces can expand upon (or be based on) other interfaces (such as `Equivalence`).
@@ -99,12 +99,11 @@ If interfaces are record types, then that means implementations must be actual r
Let's take a look at how you make one:
```clojure
-(implementation: .public order
+(def .public order
(Order Frac)
-
- (def &equivalence ..equivalence)
-
- (def < ..<))
+ (implementation
+ (def equivalence ..equivalence)
+ (def < ..<)))
```
This implementation comes from `library/lux/math/number/frac`.
@@ -116,17 +115,17 @@ For implementations, the convention is just to name them as lower-cased versions
Here is another example, from the `library/lux/data/collection/list` module:
```clojure
-(implementation: .public monoid
+(def .public monoid
(All (_ a)
(Monoid (List a)))
+ (implementation
+ (def identity
+ {.#End})
- (def identity
- {.#End})
-
- (def (compose xs ys)
- (case xs
- {.#End} ys
- {.#Item x xs'} {.#Item x (compose xs' ys)})))
+ (def (compose xs ys)
+ (when xs
+ {.#End} ys
+ {.#Item x xs'} {.#Item x (compose xs' ys)}))))
```
The reason why implementations have names (besides the fact that they are definitions like any other), is that you can _usually_ construct multiple valid implementations for the same combination of interfaces and parameter types.
@@ -155,7 +154,7 @@ We've put functions and values inside our implementations.
It's time to get them out and use them.
-There are 2 main ways to use the stuff inside your implementations: `use` and `#`.
+There are 2 main ways to use the stuff inside your implementations: `use` and `at`.
Let's check them out.
@@ -163,11 +162,11 @@ Let's check them out.
... Opens an implementation and generates a definition for each of its members (including nested members).
... For example:
-(open library/lux/math/number/int.order "i::[0]")
+(use "i::[0]" library/lux/math/number/int.order)
... Will generate:
-(def .private i::= (# library/lux/math/number/int.order =))
-(def .private i::< (# library/lux/math/number/int.order <))
+(def .private i::= (at library/lux/math/number/int.order =))
+(def .private i::< (at library/lux/math/number/int.order <))
```
The `use` macro serves as a directive that creates private/un-exported definitions in your module for every member of a particular implementation.
@@ -178,22 +177,24 @@ You may also give it an optional _aliasing pattern_ for the definitions, in case
```clojure
... Allows accessing the value of a implementation's member.
-(: (-> Int Text)
- (# library/lux/math/number/int.decimal encoded))
+(is (-> Int Text)
+ (at library/lux/math/number/int.decimal encoded))
... Also allows using that value as a function.
-(# library/lux/math/number/int.decimal encoded +123)
+(at library/lux/math/number/int.decimal encoded +123)
... => "+123"
```
-`#` is for when you want to use individual parts of a implementation immediately in your code, instead of opening them first.
+`at` is for when you want to use individual parts of a implementation immediately in your code, instead of opening them first.
- Psss! Did you notice `#` is _piping compatible_?
+ Psss! Did you notice `at` is _piping compatible_?
Also, you don't really need to worry about boilerplate related to using implementations.
-There is a module called `library/lux/type/implicit` which gives you a macro called `##` for using implementations without actually specifying which one you need.
+There is a module called `library/lux/type/implicit` which gives you a macro called `a/an` for using implementations without actually specifying which one you need.
+
+ Psss! This macro also has 2 shorter aliases: `a` and `an`.
The macro infers everything for you based on the types of the arguments, the expected type of the expression, and the implementations available in the environment.
@@ -209,9 +210,9 @@ And to exemplify it for you, here's a function from the `library/lux/abstract/mo
(def .public (each monad f xs)
(All (_ M a b)
(-> (Monad M) (-> a (M b)) (List a) (M (List b))))
- (case xs
+ (when xs
{.#End}
- (# monad in {.#End})
+ (at monad in {.#End})
{.#Item x xs'}
(do monad
diff --git a/documentation/book/the_lux_programming_language/chapter_8.md b/documentation/book/the_lux_programming_language/chapter_8.md
index 2759ad62d..36a1161af 100644
--- a/documentation/book/the_lux_programming_language/chapter_8.md
+++ b/documentation/book/the_lux_programming_language/chapter_8.md
@@ -37,11 +37,11 @@ That wrapper happens to be a type, as **all** `Functor` wrappers are types.
But not just any type. You see, functors have requirements.
```clojure
-(type: .public (Functor f)
+(type .public (Functor f)
(Interface
- (: (All (_ a b)
- (-> (-> a b) (f a) (f b)))
- each)))
+ (is (All (_ a b)
+ (-> (-> a b) (f a) (f b)))
+ each)))
```
This is the `Functor` interface, from `library/lux/abstract/functor`.
@@ -61,9 +61,10 @@ Remember that `Maybe` type we talked about?
Let's see how it plays with `Functor`.
```clojure
-(type: .public (Maybe a)
- {.#None}
- {.#Some a})
+(type .public (Maybe a)
+ (Variant
+ {.#None}
+ {.#Some a}))
```
We've seen `Maybe` before, but now we can analyse out how it's implemented.
@@ -73,13 +74,13 @@ We've seen `Maybe` before, but now we can analyse out how it's implemented.
Here is its `Functor` implementation.
```clojure
-(implementation: .public functor
+(def .public functor
(Functor Maybe)
-
- (def (each f ma)
- (case ma
- {.#None} {.#None}
- {.#Some a} {.#Some (f a)})))
+ (implementation
+ (def (each f ma)
+ (when ma
+ {.#None} {.#None}
+ {.#Some a} {.#Some (f a)}))))
... This one lives in the library/lux/data/maybe module, though.
```
@@ -104,13 +105,13 @@ Oh, and remember our `iterate_list` function from [chapter 5](chapter_5.md)?
Turns out, that's just the `Functor` implementation from `library/lux/data/collection/list`:
```clojure
-(implementation: .public functor
+(def .public functor
(Functor List)
-
- (def (each f ma)
- (case ma
- {.#End} {.#End}
- {.#Item a ma'} {.#Item (f a) (each f ma')})))
+ (implementation
+ (def (each f ma)
+ (when ma
+ {.#End} {.#End}
+ {.#Item a ma'} {.#Item (f a) (each f ma')}))))
```
Not bad.
@@ -131,21 +132,21 @@ However, to make them really easy to use, you might want to add some extra funct
One thing you may have noticed about the `Functor` interface is that you have a way to operate on functorial values, but you don't have any _standardized_ means of creating them.
-I mean, you can use the `list` and `list&` macros to create lists and the `.#None` and `.#Some` tags for `Maybe`, but there is no unified way for creating **any** functorial value.
+I mean, you can use the `list` and `library/lux/data/collection/list.partial` macros to create lists and the `.#None` and `.#Some` tags for `Maybe`, but there is no unified way for creating **any** functorial value.
Well, let me introduce you to `Monad`:
```clojure
-(type: .public (Monad m)
+(type .public (Monad m)
(Interface
- (: (Functor m)
- &functor)
- (: (All (_ a)
- (-> a (m a)))
- in)
- (: (All (_ a)
- (-> (m (m a)) (m a)))
- conjoint)))
+ (is (Functor m)
+ functor)
+ (is (All (_ a)
+ (-> a (m a)))
+ in)
+ (is (All (_ a)
+ (-> (m (m a)) (m a)))
+ conjoint)))
```
This interface extends `Functor` with both the capacity to wrap a normal value `in` a functorial structure, and to join 2 layers of functorial structure into a single, `conjoint` one.
@@ -161,7 +162,7 @@ To get a taste for it, let's check out another functorial type.
Remember what I said about error-handling?
```clojure
-(type: .public (Try a)
+(type .public (Try a)
(Variant
{#Failure Text}
{#Success a}))
@@ -172,32 +173,32 @@ This type expresses errors as `Text` values (and it lives in the `library/lux/co
Here are the relevant `Functor` and `Monad` implementations:
```clojure
-(implementation: .public functor
+(def .public functor
(Functor Try)
-
- (def (each f ma)
- (case ma
- {#Failure msg}
- {#Failure msg}
-
- {#Success datum}
- {#Success (f datum)})))
-
-(implementation: .public monad
+ (implementation
+ (def (each f ma)
+ (when ma
+ {#Failure msg}
+ {#Failure msg}
+
+ {#Success datum}
+ {#Success (f datum)}))))
+
+(def .public monad
(Monad Try)
-
- (def &functor ..functor)
-
- (def (in a)
- {#Success a})
-
- (def (join mma)
- (case mma
- {#Failure msg}
- {#Failure msg}
-
- {#Success ma}
- ma)))
+ (implementation
+ (def functor ..functor)
+
+ (def (in a)
+ {#Success a})
+
+ (def (join mma)
+ (when mma
+ {#Failure msg}
+ {#Failure msg}
+
+ {#Success ma}
+ ma))))
```
If you listen to functional programmers, you'll likely get the impression that the invention of monads rivals the invention of the wheel.
@@ -211,7 +212,7 @@ Let's see that in action:
```clojure
(.require
[library
- [lux "*"
+ [lux (.except)
[data
[collection
["[0]" list]]]]])
@@ -232,56 +233,56 @@ _It's magic!_
Not really. It's just the `Monad` for `List`:
```clojure
-(implementation: .public functor
+(def .public functor
(Functor List)
-
- (def (each f ma)
- (case ma
- {.#End}
- {.#End}
-
- {.#Item a ma'}
- {.#Item (f a) (each f ma')})))
-
-(implementation: .public mix
+ (implementation
+ (def (each f ma)
+ (when ma
+ {.#End}
+ {.#End}
+
+ {.#Item a ma'}
+ {.#Item (f a) (each f ma')}))))
+
+(def .public mix
(Mix List)
-
- (def (mix f init xs)
- (case xs
- {.#End}
- init
+ (implementation
+ (def (mix f init xs)
+ (when xs
+ {.#End}
+ init
- {.#Item x xs'}
- (mix f (f x init) xs'))))
+ {.#Item x xs'}
+ (mix f (f x init) xs')))))
-(implementation: .public monoid
+(def .public monoid
(All (_ a) (Monoid (List a)))
-
- (def identity
- {.#End})
-
- (def (composite xs ys)
- (case xs
- {.#End}
- ys
+ (implementation
+ (def identity
+ {.#End})
- {.#Item x xs'}
- {.#Item x (compose xs' ys)})))
+ (def (composite xs ys)
+ (when xs
+ {.#End}
+ ys
+
+ {.#Item x xs'}
+ {.#Item x (compose xs' ys)}))))
(use "[0]" ..monoid)
-(implementation: .public monad
+(def .public monad
(Monad List)
-
- (def &functor ..functor)
+ (implementation
+ (def functor ..functor)
- (def (in a)
- {.#Item a {.#End}})
+ (def (in a)
+ {.#Item a {.#End}})
- (def (conjoint list_of_lists)
- (mix composite
- identity
- (reversed list_of_lists))))
+ (def (conjoint list_of_lists)
+ (mix composite
+ identity
+ (reversed list_of_lists)))))
... The mix function is for doing incremental iterative computations.
... Here, we're using it to build the total output list by composing/concatenating all the input lists in our `list_of_lists`.
@@ -302,7 +303,7 @@ These macros always show up at the right time to saves us from our hurdles!
```clojure
(.require
[library
- [lux "*"
+ [lux (.except)
[data
["[0]" maybe]]]])
diff --git a/documentation/book/the_lux_programming_language/chapter_9.md b/documentation/book/the_lux_programming_language/chapter_9.md
index a01740f09..175ad8486 100644
--- a/documentation/book/the_lux_programming_language/chapter_9.md
+++ b/documentation/book/the_lux_programming_language/chapter_9.md
@@ -25,7 +25,7 @@ But the Lux compiler opens itself for usage within Lux programs and provides Lux
The `Lux` type enters the stage.
```clojure
-(type: .public Lux
+(type .public Lux
(Rec Lux
(Record
[#info Info
@@ -60,7 +60,7 @@ You can actually write computations that can read and even modify (_careful with
This turns out to be massively useful when implementing a variety of powerful macros.
-For example, remember the `use` and `#` macros from [chapter 7](chapter_7.md)?
+For example, remember the `use` and `at` macros from [chapter 7](chapter_7.md)?
They actually look up the typing information for the structures you give them to figure out the names of members and generate the code necessary to get that functionality going.
@@ -81,7 +81,7 @@ I won't go into detail about what's available, but you'll quickly get an idea of
However, one thing I _will_ say is that those functions rely heavily on the `Meta` type, which is defined thusly:
```clojure
-(type: .public (Meta a)
+(type .public (Meta a)
(-> Lux (Either Text [Lux a])))
```
diff --git a/documentation/book/the_lux_programming_language/conclusion.md b/documentation/book/the_lux_programming_language/conclusion.md
index 755677005..1c7407af3 100644
--- a/documentation/book/the_lux_programming_language/conclusion.md
+++ b/documentation/book/the_lux_programming_language/conclusion.md
@@ -14,7 +14,7 @@ My mission with Lux has been (and continues to be) to create a language that max
Lux is still in its adolescence.
-What you have learned is Lux version 0.6.5.
+What you have learned is Lux version 0.7.0.
In future releases, much more power will be added to the language, more platforms will be within reach of Lux programmers, and better performance will be achieved, with little to no effort on the side of programmers.