From 8196ab379495ab00c11b74b55b6f2fabd99ab351 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Mon, 20 Sep 2021 23:01:35 -0400 Subject: Updates and fixes for the book. --- .../book/the_lux_programming_language/chapter_3.md | 119 +++++++++++---------- 1 file changed, 65 insertions(+), 54 deletions(-) (limited to 'documentation/book/the_lux_programming_language/chapter_3.md') diff --git a/documentation/book/the_lux_programming_language/chapter_3.md b/documentation/book/the_lux_programming_language/chapter_3.md index a08fbc618..8565e24e3 100644 --- a/documentation/book/the_lux_programming_language/chapter_3.md +++ b/documentation/book/the_lux_programming_language/chapter_3.md @@ -4,13 +4,13 @@ _Where you will learn the what Lux code is made of._ --- -# Syntax for data-types +## Syntax for data-types * `Bit`s look like this: ```clojure -#0 ## false -#1 ## true +#0 ... false +#1 ... true ``` * `Nat`s look like this: @@ -63,8 +63,8 @@ _Where you will learn the what Lux code is made of._ * Variants look like this: ```clojure -#Foo -(#Bar 10 +20.0 "thirty") +{#Foo} +{#Bar 10 +20.0 "thirty"} ``` * Tuples look like this: @@ -76,30 +76,20 @@ _Where you will learn the what Lux code is made of._ * Records look like this: ```clojure -{#name "Lux" #paradigm #Functional #platforms (list #JVM)} +[#name "Lux" #paradigm {#Functional} #platforms (list {#JVM})] ``` **Note**: As you can see, commas (`,`) can be used as separators for the numeric literals. --- -From looking at this, we can see a few interesting bits we haven't discussed. - -One is that the hash (`#`) character is overloaded. - -In the last chapter we saw it being used for comments, but now we're seeing it being used as a prefix for _some weird "label" thingies_ (more on that in a moment). - -To avoid reserving many characters for the language, Lux overloads the hash (`#`) character in situations where it can be used unambiguously. That way, most characters can be used by anyone without fear of stepping on the feet of the language. - ---- - -Regarding _those label thingies_ we saw earlier, they're called **tags**, and the reason they're not mentioned as part of Lux's data-types is that they're not really data-types; they're just part of the language syntax. +Regarding _those label thingies_ we saw earlier, they're called **labels**, and the reason they're not mentioned as part of Lux's data-types is that they're not really data-types; they're just part of the language syntax. They're used as part of the syntax for data-types, but they're not data-types in themselves. -Also, you can't just use anything you want as a tag, as you first have to declare them. +Also, you can't just use anything you want as a label, as you first have to declare them. -We'll talk more about tags a bit later, when we talk about defining types. +We'll talk more about labels a bit later, when we talk about defining types. --- @@ -111,41 +101,57 @@ Also, just from looking at the syntax for unit and tuples, you can see that they In the section for variants, you can see 2 different alternatives, and you might wonder how do they differ. -Well, a variant is a pair of a tag and a _single_ value. That's right, I said **single** value; so you might be wondering how come we're associating 3 values with the `#Bar` tag. +Well, a variant is a pair of a _label_ (referred to as a _tag_) and a _single_ value. -It's pretty simple, actually. Whenever you're trying to create a variant with more than one value, Lux just wraps all the values inside a tuple for you. +That's right, I said **single** value; so you might be wondering how come we're associating 3 values with the `#Bar` tag. -So, `(#Bar 10 +20.0 "thirty")` is the same as `(#Bar [10 +20.0 "thirty"])`. +It's pretty simple, actually: whenever you're trying to create a variant with more than one value, Lux just wraps all the values inside a tuple for you. + +So, `{#Bar 10 +20.0 "thirty"}` is the same as `{#Bar [10 +20.0 "thirty"]}`. Now, you might be thinking: _what's up with that `#Foo` variant?_ -Well, sometimes you only care about a variant for its tag, and not for any value it may hold (for example, if you're trying to use a variant type as an enumeration). In that case, you'll want to pair the tag with an empty value (since it has to be paired with something). +Well, sometimes you only care about a variant for its tag, and not for any value it may hold (for example, if you're trying to use a variant type as an enumeration). + +In that case, you'll want to pair the tag with an empty value (since it has to be paired with something). -That's right! You've just witnessed **unit** value in action and you didn't even know it. If you just write the name of the tag without any parentheses, Lux will stick a **unit** in there for you. +That's right! You've just witnessed **unit** value in action and you didn't even know it. -That means `#Foo` is the same as ``(#Foo [])``. +If you just write the tag in braces, with nothing else in there, Lux will stick a **unit** in there for you. + +That means `{#Foo}` is the same as `{#Foo []}`. --- You might have noticed that I mentioned **records** in this chapter, but not in the previous chapter, where I also talked about the basic data-types Lux offers. -The reason is that records are a bit of a magic trick in Lux. That means records are not really a data-type that's distinct from the other ones. In fact, records just offer you an alternative syntax for writing tuples. +The reason is that records are a bit of a magic trick in Lux. + +That means records are not really a data-type that's distinct from the other ones. -That's right! `{#name "Lux" #paradigm #Functional #platforms (list #JVM)}` could mean the same as `["Lux" #Functional (list #JVM)]`, depending on the ordering imposed by the tags. +In fact, records just offer you an alternative syntax for writing tuples. + +That's right! `[#name "Lux" #paradigm {#Functional} #platforms (list {#JVM})]` could mean the same as `["Lux" {#Functional} (list {#JVM})]`, depending on the ordering imposed by the _slots_ (which is the name given to record _labels_). --- -Remember when I said that you needed to declare your tags? Well, depending on the order in which you declare them, that means that `#name` could point to the first element in the tuple, or to another position entirely. Also, in the same way that tags have a numeric value when it comes to their usage in tuples/records, that's also the case for variants. +Remember when I said that you needed to declare your labels? + +Well, depending on the order in which you declare them, that means that `#name` could point to the first element in the tuple, or to another position entirely. -For example, the `List` type has two tags: `#.End` and `#.Item`. The `#.End` tag has value 0, while the `#.Item` tag has value 1. That's what allows Lux to the able to identify which option it is working with at runtime when you're dealing with variants. +Also, in the same way that labels have a numeric value when it comes to their usage in tuples/records, that's also the case for variants. -Tags belong to the module in which they were declared, and you must use the module name (or an alias) as a prefix when using tags. That is why I've written `#.End` and `#.Item`, instead of `#End` and `#Item`. However, you may forgo the prefixes if you're referring to tags which were defined in the same module in which they're being used. +For example, the `List` type has two tags: `.#End` and `.#Item`. -Finally, you may have noticed that, unlike all other data-types, variants re-use some syntax that you're already seen before: _the parentheses_. Clearly, we didn't build our program by creating a bunch of variants, so, what's going on? +The `.#End` tag has value 0, while the `.#Item` tag has value 1. -Well, the parenthesis delimit the syntax of what is called a **form** in Lux. This is actually an old concept that's very familiar to those with experience with other Lisp-like languages. Basically, a form is a composite expression or statement. +That's what allows Lux to the able to identify which option it is working with at runtime when you're dealing with variants. -When the form starts with a tag, Lux interprets that to be a variant. +Labels belong to the module in which they were declared, and you must use the module name (or an alias) as a prefix when using tags. + +That is why I've written `.#End` and `.#Item`, instead of `#End` and `#Item`. + +However, you may forgo the prefixes if you're referring to tags which were defined in the same module in which they're being used. ## Types for data-types @@ -155,7 +161,7 @@ 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 `:` (I know, _real cute_). You use it like this: `(: 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. @@ -171,38 +177,41 @@ Now that we know about type annotations, I'll show you some types by giving you (: Text "YOLO") (type: Some_Enum - #primitive - #tuple - #variant) + (Variant + {#Primitive} + {#Variant} + {#Tuple})) (: [Int [Text Some_Enum] Bit] - [10 ["nested" #tuple] .false]) + [10 ["nested" {#Tuple}] .false]) (type: Quux - #Foo - (#Bar Int Frac Text)) + (Variant + {#Foo} + {#Bar Int Frac Text})) -(: Quux #Foo) +(: Quux {#Foo}) -(: Quux (#Bar 10 +20.0 "thirty")) +(: Quux {#Bar 10 +20.0 "thirty"}) (type: Lang - {#name Text - #paradigm Paradigm - #platforms (List Platform)}) + (Record + [#name Text + #paradigm Paradigm + #platforms (List Platform)])) (: Lang - {#name "Lux" - #paradigm #Functional - #platforms (list #JVM)}) + [#name "Lux" + #paradigm {#Functional} + #platforms (list {#JVM})]) (: Lang - ["Lux" #Functional (list #JVM)]) + ["Lux" {#Functional} (list {#JVM})]) (: [Text Paradigm (List Platform)] - {#name "Lux" - #paradigm #Functional - #platforms (list #JVM)}) + [#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`. @@ -211,13 +220,15 @@ _What is that `type:` thingie?_ It's just a macro for defining types. We'll learn more about it in a future chapter. -The tags that get mentioned in the type definition get automatically declared, and the order in which they appear determines their value. `#Foo` came first, so it's value is 0. `#Bar`, as you may guess, gets the value 1. +The labels that get mentioned in the type definition get automatically declared, and the order in which they appear determines their value. + +`#Foo` came first, so its value is 0. `#Bar`, as you may guess, gets the value 1. Also, you might be wondering what's the difference between `List` and `list`. Well, the first one is the type of lists (or a type-constructor for list types, however you want to look at it). The second one is a _macro_ for constructing actual list values. `List` can only take one argument (the type of the list elements), while `list` can take any number of arguments (the elements that make up the list value). --- -Again, we haven't mentioned functions. But if you're impatient to learn about them, just click the link below. +Again, we haven't mentioned functions. But the next chapter is about them. See you in [the next chapter](chapter_4.md)! -- cgit v1.2.3