24 | ```
25 |
--------------------------------------------------------------------------------
/posts/gleam-v0.3-released.djot:
--------------------------------------------------------------------------------
1 | [Gleam](https://github.com/lpil/gleam) has reached v0.3! Let's take a look at
2 | some of the new features introduced since v0.1.
3 |
4 | ## Module namespaces
5 |
6 | Modules can now be namespaced, allowing use of short, convenient module names
7 | without the risk of collisions with other Gleam or Erlang modules.
8 |
9 | To use a namespace create a directory with the name of your namespace inside
10 | the `src/` directory and put your modules in there. As an example, if I'm
11 | making the hot new food delivery app `snackr` I might choose to have a
12 | directory structure like this:
13 |
14 | ```
15 | src/
16 | └── snackr
17 | ├── customer.gleam
18 | ├── payment.gleam
19 | └── food
20 | ├── falafel.gleam
21 | ├── pizza.gleam
22 | └── salad.gleam
23 | ```
24 |
25 | Once created these modules can be brought into scope using the `import`
26 | statement.
27 |
28 | ```gleam
29 | import snackr/customer
30 | import snackr/food/falafel
31 |
32 | fn eat_lunch(louis) {
33 | customer:eat(louis, falafel:new())
34 | }
35 | ```
36 |
37 | It's now possible to use multiple modules with the same name, so for
38 | convenience modules can be given a name when imported.
39 |
40 | ```gleam
41 | import space/rocket as spaceship
42 | import salad/rocket as leafy_green
43 | ```
44 |
45 |
46 | ## Type annotations
47 |
48 | Gleam's type inference doesn't require any annotations to understand the types
49 | of all your code and provide full type safety, but we might still want to add
50 | some for documentation, or to specify more restrictive types then Gleam might
51 | otherwise infer.
52 |
53 | It looks a little something like this:
54 |
55 | ```gleam
56 | fn is_empty(list: List(a)) -> Bool {
57 | list == []
58 | }
59 | ```
60 |
61 |
62 | ## Easier installation
63 |
64 | Precompiled Gleam binaries for Linux and OSX can now be downloaded from the
65 | [Gleam GitHub release page](https://github.com/lpil/gleam/releases) so it's no
66 | longer required to install Rust on your machine and build the compiler from
67 | source.
68 |
69 | Victor Borja has kindly created an `asdf` version manager [plugin for
70 | Gleam](https://github.com/vic/asdf-gleam), so for asdf users installing Gleam
71 | is as easy as `asdf install gleam v0.3.0`.
72 |
73 | For Docker fans the Gleam compiler has been packaged as a Docker image tagged
74 | as [`lpil/gleam`](https://hub.docker.com/r/lpil/gleam).
75 |
76 |
77 | ## Easier project creation
78 |
79 | Previously Gleam projects were created using a rebar3 plugin. This worked but
80 | was one more thing to install, and there was to good way of ensuring that you
81 | have an up to date version of the plugin to match your Gleam installation.
82 |
83 | Now project creation is handled by the `gleam` binary itself, so to get
84 | started with Gleam run `gleam new my_cool_project` and it'll generate all
85 | that's required.
86 |
87 | If you've got `rebar_gleam` installed it's safe to delete it from your
88 | `~/.config/rebar3/rebar.config` as it's no longer used.
89 |
90 |
91 | ## The rest
92 |
93 | In addition to these features there's been a number of other improvements to
94 | the quality of the error messages, the generated code, and a handful of bug
95 | fixes. 😊
96 |
97 | If you want to try out the new version of Gleam head over to the [installation
98 | page](https://gleam.run/getting-started/installing-gleam.html). I'd love to
99 | hear how you find it and get your feedback so Gleam can continue to improve.
100 |
101 |
102 | ## Code BEAM lite Berlin
103 |
104 | On the 11th of October 2019 I'll be speaking at [Code BEAM lite
105 | Berlin](https://codesync.global/conferences/code-beam-lite-berlin-2019/) about
106 | Gleam. If you're attending (or are in Berlin but not attending) say Hello!
107 |
--------------------------------------------------------------------------------
/posts/gleam-v0.4-released.djot:
--------------------------------------------------------------------------------
1 | [Gleam](https://github.com/lpil/gleam) has reached v0.4! This version has some
2 | new features, bug fixes, and some breaking changes. Let's take a look.
3 |
4 |
5 | ## Structs
6 |
7 | Gleam's map and tuple type has been removed and replaced with structs, which
8 | have many of the benefits of both.
9 |
10 | Like maps structs are collections of named values, each with their own type.
11 | Unlike maps they are named, so two structs are not the same type just because
12 | they have the same fields by coincidence, making Gleam's type system a little
13 | stricter by default.
14 |
15 | Like tuples structs have constant access time, they do not need to be linearly
16 | scanned in order to find a field to access it.
17 |
18 | Unlike either struct types are declared up-front by the `struct` keyword.
19 |
20 | ```gleam
21 | pub struct Cat {
22 | name: String
23 | cuteness: Int
24 | }
25 | ```
26 |
27 | Once declared the newly defined constructor can be used to create instances of
28 | the struct.
29 |
30 | ```gleam
31 | pub fn cats() {
32 | let cat1 = Cat(name: "Nubi", cuteness: 2001)
33 | let cat2 = Cat(cuteness: 1805, name: "Biffy")
34 |
35 | // Alternatively fields can be given without labels
36 | let cat3 = Cat("Ginny", 1950)
37 |
38 | [cat1, cat2, cat3]
39 | }
40 | ```
41 |
42 | One downside to structs is that they are less convenient for returning more
43 | than one value from a function than tuples were, as struct types need to be
44 | pre-declared. To negate this inconvenience the standard library declares `Pair`
45 | and `Triple` types in the `gleam/pair` and `gleam/triple` modules. If you wish
46 | to return more than 3 values from a function it is recommended to create a
47 | struct and name the values to make it more clear what they are.
48 |
49 |
50 | ## Comparison operators
51 |
52 | The next breaking change is to how the comparison operators `>`, `>=`, `<`,
53 | and `<=` work. Previously these operators would take any two values of the
54 | same type and determine which is larger according to Erlang's ordering of
55 | values. This is convenience but may result in surprising behaviour when used
56 | with custom types such as enums.
57 |
58 | For example, with the `Order` enum we would expect `Gt` (greater than) to be
59 | larger than `Lt` (less than), but according to Erlang's value ordering this is
60 | not the case.
61 |
62 | ```gleam
63 | enum Order =
64 | | Gt
65 | | Eq
66 | | Lt
67 | ```
68 | ```gleam
69 | Gt > Lt // => False
70 | ```
71 |
72 | From this version on `>`, `>=`, `<`, and `<=` only accept Ints as arguments
73 | to avoid this surprising behaviour, and the `>.` `>=.` `<.` and `<=.`
74 | comparison operators have been added for comparing Floats.
75 |
76 | For ordering other types comparison functions can be found in the standard
77 | library, such as `order.compare` and `bool.compare`.
78 |
79 |
80 | ## Second class modules
81 |
82 | Modules are no longer first class values in Gleam, meaning they can no longer
83 | be assigned to variables or used as arguments to functions.
84 |
85 | First class modules were inspired by OCaml and intended to be a way to work
86 | with Erlang _behaviours_ such as `gen_stage` from within Gleam. However after
87 | several months of using modules in Gleam it became clear that taking OCaml's
88 | first class modules but not their functor module system resulted in Gleam's
89 | modules being far less useful.
90 |
91 | First class functions combined with Gleam's other data structures is
92 | sufficient to use Erlang behaviours, while being easier to construct and
93 | compose, so first class modules were determined not to be the ideal solution
94 | here either.
95 |
96 | With first class modules removed we no longer need a special syntax for
97 | accessing a field on a module, so the `:` operator has been removed and
98 | replaced with the `.` operator, making it the universal operator for accessing
99 | a named field on a module or container data type in Gleam.
100 |
101 | ```gleam
102 | import gleam/list
103 |
104 | pub fn main() {
105 | list.reverse([1, 2, 3])
106 | }
107 | ```
108 |
109 | With the removal of modules and maps Gleam's type system has become simpler,
110 | less structural and more nominal in style. This puts us in a good position to
111 | do research into new forms of polymorphism such as type classes or traits!
112 |
113 |
114 | ## The rest
115 |
116 | In addition to these features there's been a number of other improvements to
117 | the quality of the error messages, the generated code, and a handful of bug
118 | fixes. 😊
119 |
120 | If you want to try out the new version of Gleam head over to the [installation
121 | page](https://gleam.run/getting-started/installing-gleam.html). I'd love to
122 | hear how you find it and get your feedback so Gleam can continue to improve.
123 |
124 |
125 | ## Code BEAM lite Berlin
126 |
127 | On the 11th of October 2019 I'll be speaking at [Code BEAM lite
128 | Berlin](https://codesync.global/conferences/code-beam-lite-berlin-2019/) about
129 | Gleam. If you're attending (or want to recommend to me good things to do on a
130 | weekend in Berlin) say Hello!
131 |
132 |
133 | ## Thanks
134 |
135 | Lastly, a huge thank you to the code contributors to this release!
136 |
137 | - [Al Dee](https://github.com/scripttease)
138 | - [Benjamin Reynolds](https://github.com/benreyn)
139 | - [Dirk Gadsden](https://github.com/dirk)
140 | - [epj009](https://github.com/epj009)
141 |
--------------------------------------------------------------------------------
/posts/gleam-v0.6-released.djot:
--------------------------------------------------------------------------------
1 | Merry Christmas! Following in the Ruby tradition we're having a release on
2 | Christmas day, and so [Gleam](https://github.com/gleam-lang/gleam) v0.6 is here!
3 |
4 | This release has one big change to how we define data structures in Gleam. To
5 | understand it lets take a look at how structs and enums have worked up until
6 | this point.
7 |
8 | ```gleam
9 | struct Cat {
10 | name: String
11 | age: Int
12 | }
13 | ```
14 |
15 | Structs are collections of named values. Under the hood they are represented
16 | as Erlang tuples, so `Cat("Nubi", 2)` would be `{<<"Nubi">>, 2}` in Erlang.
17 |
18 | ```gleam
19 | enum SchoolPerson {
20 | Teacher(String, Subject)
21 | Student(String)
22 | }
23 | ```
24 |
25 | Enum are also collections of values, only this time the values are not named.
26 | One way in which enums are more capable than structs is that they can have
27 | more than one constructor, so for example a SchoolPerson enum type can be
28 | either a Teacher or a Student.
29 |
30 | Like structs enums are tuples at runtime, only they have their constructor
31 | name as the first element to help distinguish them, so `Student("Louis")`
32 | would be `{student, <<"Louis">>}` in Erlang. This atom tag makes enums
33 | compatible with Erlang records, allowing easier use within projects written in
34 | Erlang or Elixir.
35 |
36 | So the differences between structs and enums were:
37 |
38 | 1. Struct fields can have names.
39 | 2. Enums are Erlang record compatible.
40 | 3. Enums can have more than one constructor.
41 |
42 | In v0.5 things changed a little.
43 |
44 | It turned out that being able to label fields so they have names was useful,
45 | so enums gained labelled arguments (as did functions).
46 |
47 | It turns out that being Erlang record compatible with a tag atom was useful
48 | for Erlang interop and for runtime debugging, so structs got this too.
49 |
50 | At which point the only difference between enums and structs are the number of
51 | constructors, and there's nothing stopping someone from defining an enum with
52 | a single constructor.
53 |
54 | Structs became a subset of enums, so why have both?
55 |
56 |
57 | ## Custom types
58 |
59 | With v0.6 rather than structs and enums we have _custom types_. Here's how the
60 | two examples above would be written using the new syntax:
61 |
62 | ```gleam
63 | type Cat {
64 | Cat(name: String, age: Int)
65 | }
66 | ```
67 | Cat is a custom type has a single constructor called Cat.
68 |
69 | ```gleam
70 | type SchoolPerson {
71 | Teacher(name: String, class: Subject)
72 | Student(name: String)
73 | }
74 | ```
75 |
76 | SchoolPerson is a custom type has a Teacher constructor and a Student constructor.
77 |
78 | ```gleam
79 | let louis = Student(name: "Louis")
80 | ```
81 |
82 | In keeping with Erlang and Elixir an instance of one of these custom types is
83 | called a record. The variable `louis` is a Student record, and it has the type
84 | SchoolPerson.
85 |
86 | This change makes the languages simpler (both to the user and within the
87 | compiler), and hopefully it'll make Gleam a little easier to learn too. :)
88 |
89 |
90 | ## Tuples
91 |
92 | After this change `struct` is no longer a keyword, and it doesn't make much
93 | sense to have a concept of anonymous structs without named structs, so
94 | anonymous structs have been renamed _tuples_.
95 |
96 | ```gleam
97 | let pair = tuple(1, "two")
98 | ```
99 |
100 |
101 | ## The rest
102 |
103 | There's been a number a smattering of bug fixes in this release, see the
104 | [changelog](https://github.com/gleam-lang/gleam/blob/master/CHANGELOG.md) for
105 | further details.
106 |
107 | If you want to try out the new version of Gleam head over to the [installation
108 | page][installation]. I'd love to hear how you find it and get your feedback so
109 | Gleam can continue to improve.
110 |
111 | Want to view some existing Gleam projects? Head on over to the
112 | [awesome-gleam][awesome-gleam] list. Looking for something to build in
113 | Gleam? Check out [the suggestions tracker][suggestions].
114 |
115 | [awesome-gleam]: https://github.com/gleam-lang/awesome-gleam
116 | [suggestions]: https://github.com/gleam-lang/suggestions/issues
117 | [installation]: https://gleam.run/getting-started/installing-gleam.html
118 |
119 |
120 | ## Thanks
121 |
122 | Lastly, a huge thank you to the contributors to and sponsors of Gleam since
123 | last release!
124 |
125 | - [Adam Brodzinski](https://github.com/AdamBrodzinski)
126 | - [Christian Wesselhoeft](https://github.com/xtian)
127 | - [Devon Estes](https://github.com/devonestes)
128 | - [John Palgut](https://github.com/Jwsonic)
129 | - [Matt Widmann](https://github.com/mgwidmann)
130 | - [Michał Łępicki](https://github.com/michallepicki)
131 | - [OvermindDL1](https://github.com/OvermindDL1)
132 | - [RJ Dellecese](https://github.com/rjdellecese)
133 | - [Sebastian Porto](https://github.com/sporto)
134 | - [Stefan Hagen](https://github.com/sthagen)
135 | - [ontofractal](https://github.com/ontofractal)
136 | - [Štefan Ľupták](https://github.com/EskiMag)
137 |
138 |
139 | If you would like to help make strongly typed programming on the Erlang
140 | virtual machine a production-ready reality please consider [sponsoring
141 | Gleam][sponsor] via the GitHub Sponsors program.
142 |
143 | Thank you! And have a fantastic new year! 💜
144 |
145 | [sponsor]: https://github.com/sponsors/lpil
146 |
--------------------------------------------------------------------------------
/posts/gleam-v0.7-released.djot:
--------------------------------------------------------------------------------
1 | It has been two months since the last one, so now it's time for another Gleam
2 | release! Let's see what's new this time:
3 |
4 | ## Improved error messages
5 |
6 | Since the last release we've put a lot of work into the error messages emitted
7 | by the compiler. The most common and arguably the most important type of error
8 | is the type error, so we want it to be as clear and as friendly as possible.
9 |
10 | Here's what it looks like with Gleam v0.7:
11 |
12 | ``` =html
13 |
14 | ```
15 |
16 | This is a big improvement over previous versions which would struggle with
17 | highlighting multi-line code sections, and would state the problem as being
18 | `Int != Float` rather than `List(Int) != List(Float)`.
19 |
20 | Other improved error messages include the import cycle error message:
21 |
22 | ``` =html
23 |
24 | ```
25 |
26 | Error messages for invalid patterns in case expressions:
27 |
28 | ``` =html
29 |
30 | ```
31 |
32 | And a slew of error messages relating to errors when trying to read or write
33 | files in a Gleam project.
34 |
35 | Gleam aims to be an exceptionally friendly and productive language, so error
36 | messages are important. If there are any errors that you find confusing or
37 | unclear please get in touch and let us know!
38 |
39 | In adding these new error messages we discovered a bug in rebar3 where unicode
40 | characters would be printed incorrectly in some circumstances. This bug is now
41 | fixed now but if you find your errors look incorrect please try upgrading
42 | your rebar3 version by running `rebar3 local upgrade`.
43 |
44 |
45 | ## Alternative patterns
46 |
47 | Sometimes when writing case expressions we want multiple different clauses to
48 | be able to trigger the same clause with different shaped data. To meet this
49 | need we're introducing alternative patterns, separated by the `|` operator.
50 |
51 | In this case expression the first clause will match if the variable `number`
52 | holds 2, 4, 6 or 8.
53 |
54 | ```gleam
55 | case number {
56 | 2 | 4 | 6 | 8 -> "This is an even number"
57 | 1 | 3 | 5 | 7 -> "This is an odd number"
58 | _ -> "I'm not sure"
59 | }
60 | ```
61 |
62 |
63 | ## Clause guards
64 |
65 | Sometimes when pattern matching we want to assert that two variables have the
66 | same value. Before this release we'd need to nested case expressions, now we
67 | have clause guards.
68 |
69 | ```gleam
70 | case xs {
71 | [a, b] if a == b -> "Two equal elements"
72 | [a, b] if a != b -> "Two unequal elements"
73 | _other -> "Something else"
74 | }
75 | ```
76 |
77 |
78 | ## Named sub-patterns
79 |
80 | Sometimes when pattern matching we want to assign a name to a value while
81 | specifying it's shape at the same time. With this release we can now do this
82 | using the `as` keyword.
83 |
84 | ```gleam
85 | case xs {
86 | [[_, _] as inner_list] -> inner_list
87 | other -> []
88 | }
89 | ```
90 |
91 |
92 | ## Type aliases
93 |
94 | Sometimes it can be tiring writing long type names in function annotations
95 | such as `Result(List(tuple(String, String)), Nil)`, often we'd rather write a
96 | short alias instead such as `Option(Headers)`. With type aliases this is now
97 | possible.
98 |
99 |
100 | ```gleam
101 | pub type Option(value) =
102 | Result(value, Nil)
103 |
104 | pub type Headers =
105 | List(tuple(String, String))
106 |
107 | pub fn headers() -> Option(Headers) {
108 | Ok([tuple("x-served-by", "Gleam")])
109 | }
110 | ```
111 |
112 | The `Option(value)` alias above is often pretty useful! If you want to use it
113 | it is defined in the `gleam/result` module of the Gleam standard library.
114 |
115 |
116 | ## Windows support
117 |
118 | The Gleam compiler's test suite is now running successfully on Windows, and a
119 | Windows binary is being compiled for new releases. If you're developing on
120 | Windows please do give it a try and let us know of any problems you encounter.
121 |
122 |
123 | ## The rest
124 |
125 | In addition to these changes there's been a bunch of bug fixes, performance
126 | improvements, and refactorings to the compiler. Please see the
127 | [changelog](https://github.com/gleam-lang/gleam/blob/master/CHANGELOG.md) for
128 | more detail.
129 |
130 | If you want to try out the new version of Gleam head over to the [installation
131 | page][installation]. I'd love to hear how you find it and get your feedback so
132 | Gleam can continue to improve.
133 |
134 | Want to view some existing Gleam projects? Head on over to the
135 | [awesome-gleam][awesome-gleam] list. Looking for something to build in
136 | Gleam? Check out [the suggestions tracker][suggestions].
137 |
138 | [awesome-gleam]: https://github.com/gleam-lang/awesome-gleam
139 | [suggestions]: https://github.com/gleam-lang/suggestions/issues
140 | [installation]: https://gleam.run/getting-started/installing-gleam.html
141 |
142 |
143 | ## Thanks
144 |
145 | Lastly, a huge thank you to the contributors to and sponsors of Gleam since
146 | last release!
147 |
148 | - [Ahmad Sattar](https://github.com/thehabbos007)
149 | - [Anthony Bullard](https://github.com/gamebox)
150 | - [BSKY](https://github.com/imbsky)
151 | - [Christian Wesselhoeft](https://github.com/xtian)
152 | - [Guilherme Pasqualino](https://github.com/ggpasqualino)
153 | - [JHZheng](https://github.com/zjhmale)
154 | - [John Palgut](https://github.com/Jwsonic)
155 | - [RJ Dellecese](https://github.com/rjdellecese)
156 | - [Stefan Hagen](https://github.com/sthagen)
157 | - [ontofractal](https://github.com/ontofractal)
158 | - [szTheory](https://github.com/szTheory)
159 |
160 |
161 | If you would like to help make strongly typed programming on the Erlang
162 | virtual machine a production-ready reality please consider [sponsoring
163 | Gleam][sponsor] via the GitHub Sponsors program.
164 |
165 | Thanks for reading! Have fun! 💜
166 |
167 | [sponsor]: https://github.com/sponsors/lpil
168 |
--------------------------------------------------------------------------------
/posts/gleams-new-interactive-language-tour.djot:
--------------------------------------------------------------------------------
1 | Gleam is a type safe and scalable language for the Erlang virtual machine and
2 | JavaScript runtimes. Today Gleam's new language tour has been launched, a way to
3 | try and to learn Gleam without having to install anything on your computer.
4 | Check it out, it looks like this:
5 |
6 | ``` =html
7 |
8 | ```
9 |
10 | The language tour guides you through the language, from the basics to the most
11 | advanced features, introducing each concept in a way that builds on what has
12 | come before. Gleam is a small and consistent language, designed to be as easy to
13 | learn and predictable as possible, so the tour manages to cover the entire
14 | language while still being a relatively short read. Once you've completed the
15 | tour you'll know everything you need to know to write your own Gleam programs,
16 | or make contributions to existing ones.
17 |
18 | The examples and any code you write are compiled and execute entirely
19 | within the browser, rather sending the code to a build server for processing.
20 | This coupled with Gleam's fast compilation speed means that the tour is
21 | super-snappy. You can experiment and try things without getting bogged down
22 | waiting for the results to come back.
23 |
24 | We're super happy with how this work has turned out, and we're hoping that this
25 | will make it easier than ever for people to go from "Gleam sounds interesting"
26 | to "I can write code in Gleam!".
27 |
28 | Sound good? Find it at [https://tour.gleam.run/](https://tour.gleam.run/) ✨
29 |
30 |
31 | ## How does it work?
32 |
33 | Gleam's [compiler][compiler] is written in Rust, and all input/output is
34 | provided to it via dependency injection. This means that it's possible to
35 | replace the command-line interface that reads and writes to files with an
36 | in-memory one which can be compiled to [WebAssembly][wasm] and run in the
37 | browser.
38 |
39 | [compiler]: https://github.com/gleam-lang/gleam/
40 | [wasm]: https://webassembly.org/
41 |
42 | Gleam compiles to either Erlang or JavaScript, so in the language tour
43 | JavaScript is used as the target, and this compiled code can be executed
44 | directly in the browser. Executing the code is a little tricky as Gleam outputs
45 | esmodules, which cannot run using JavaScript's `eval` function.
46 | Instead the compiled code is base64 encoded and dynamically imported as a data
47 | URL, after which the `main` function can be called.
48 |
49 | ```javascript
50 | const encoded = btoa(unescape(encodeURIComponent(code)));
51 | const module = await import("data:text/javascript;base64," + encoded);
52 | module.main();
53 | ```
54 |
55 | The other tricky part is that we need the code to be able to import and use
56 | modules from the standard library. Compiled Gleam code uses relative paths to
57 | import other Gleam modules. These paths get edited slightly in the tour to point
58 | to where we have a precompiled copy of the standard library, which the browser can
59 | download as needed. Another approach here would have been to include a
60 | JavaScript bundler in the browser, but this more lightweight approach works well
61 | for our needs.
62 |
63 | The compiler is fast, but it's important that the website and the browser
64 | remain responsive even on slower hardware, or if compilation is slow for some
65 | other unexpected reason. To avoid this problem compilation and execution is done
66 | in a different thread to the browser's UI using JavaScript [Web Workers][workers].
67 |
68 | [workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
69 |
70 | The [CodeFlask][codeflask] library is used to provide the code editor and syntax
71 | highlighting. This was selected as it's a lightweight and easy to use text
72 | editor that has just the features we need, and no more.
73 |
74 | [codeflask]: https://kazzkiq.github.io/CodeFlask
75 |
76 | The website is a static site that is deployed to [GitHub Pages][pages]. Rather
77 | than using any specific static site generator it is built using a small Gleam
78 | program that can be found [here](https://github.com/gleam-lang/language-tour).
79 |
80 | [pages]: https://pages.github.com/
81 |
82 |
83 | ## All the thanks
84 |
85 | Thanks to [John Doneth](https://github.com/JohnDoneth) for his work getting the
86 | compiler to work within the browser, and to
87 | [Enderchief](https://github.com/Enderchief) for taking this further still.
88 |
89 | Thanks to [Hayleigh Thompson](https://github.com/hayleigh-dot-dev/) for her
90 | JavaScript witchcraft, including but not limited to helping us figure out what
91 | our options are for executing esmodules in the browser.
92 |
93 | Thanks to [Hazel Bachrach](https://github.com/hibachrach/) for testing the tour
94 | and suggesting use of a second thread, to keep the experience good for folks on
95 | all devices.
96 |
97 | Thanks to [Dillon Mulroy](https://github.com/dmmulroy), [Giacomo Cavalieri](https://github.com/giacomocavalieri/), [inoas](https://github.com/inoas/), and [jimpjorps](https://github.com/hunkyjimpjorps/)
98 | for giving feedback on the content of the tour, as well as unpicking my many
99 | typos and grammatical errors.
100 |
101 | This has been a long project, so I'm sure I've missed some important people. I'm
102 | very grateful for everyone's help, thank you.
103 |
104 | ## Support Gleam development
105 |
106 | If you like Gleam consider becoming a sponsor or asking your employer to
107 | [sponsor Gleam development](https://github.com/sponsors/lpil). I work full time
108 | on Gleam and your kind sponsorship is how I pay my bills.
109 |
110 | Thanks for reading! Happy hacking! 💜
111 |
--------------------------------------------------------------------------------
/posts/hello-gleam.djot:
--------------------------------------------------------------------------------
1 | Gleam has reached v0.1! Happy first release-day Gleam!
2 |
3 | ## What's Gleam?
4 |
5 | Gleam is a functional programming language for writing maintainable and
6 | scalable concurrent systems. If you enjoy the actor based concurrency model
7 | and durable runtime of Erlang and Elixir, and the sound type system of
8 | OCaml, ReasonML, or Elm then I hope you will enjoy Gleam.
9 |
10 | It looks something like this:
11 |
12 | ```gleam
13 | pub enum User =
14 | | LoggedIn(String)
15 | | Guest
16 |
17 | pub fn check(user) {
18 | case user {
19 | | LoggedIn("Al") -> "Hi Al!"
20 | | LoggedIn(name) -> "Welcome back!"
21 | | Guest -> "Hello! Please log in"
22 | }
23 | }
24 | ```
25 |
26 | ## What is it like?
27 |
28 | Gleam supports generics, algebraic data types, modules as a first-class
29 | data-type, and row typed maps to enable flexible and permissive function
30 | interfaces.
31 |
32 | The type system aims to provide compile time safety and easy refactoring
33 | without burdening the programmer with verbose annotations or boilerplate.
34 | Types are completely inferred, though future releases will allow programmers
35 | to add optional type annotations if desired.
36 |
37 | Gleam compiles to Erlang and runs on the battle proven
38 | Erlang virtual machine, making it suitable for writing massively concurrent
39 | systems that are fault tolerant and relatively easy to reason about.
40 |
41 | The Erlang ecosystem is full of great libraries, languages, and applications,
42 | so Gleam makes it straightforward to import functions written in other BEAM
43 | languages and use them in your program. Gleam also aims to be a good citizen,
44 | so any library or application written in Gleam can be used by any other BEAM
45 | language without fuss or performance overhead.
46 |
47 |
48 | ## What is it for?
49 |
50 | Thanks to its Erlang heritage Gleam excels at low latency, high concurrency,
51 | networked applications such as web application backends, databases, or message
52 | brokers. Erlang and Elixir are also highly suited for embedded applications,
53 | so perhaps Gleam will be useful there too.
54 |
55 | Gleam's type system gives it an edge in rapidly evolving problem spaces as it
56 | helps the programmer refactor quickly and safely by supplying precise and
57 | useful error messages until the change is fully applied.
58 |
59 |
60 | ## What is it not for?
61 |
62 | It doesn't run in a browser or on a mobile device, and doesn't have a graphics
63 | library, so it's not suited for GUI applications. It doesn't have the
64 | near-instant boot time and easy distribution of a native binary so it's not
65 | the best for command line applications. It isn't fast at crunching numbers so
66 | you won't use it for statistical analysis.
67 |
68 |
69 | ## Is it good?
70 |
71 | Yes, I think so. But then it would be silly if I say otherwise, wouldn't it?
72 |
73 | Perhaps don't put it into production just yet, but it's usable enough for pet
74 | projects and toy applications. 🚀
75 |
76 |
77 | ## Sounds interesting. What now?
78 |
79 | Check out [the website](http://gleam.run) for more information, and check out
80 | the project on [GitHub](https://github.com/lpil/gleam).
81 |
82 | If you've any questions or want to get involved join the IRC channel
83 | `#gleam-lang` on Freenode.
84 |
85 | Thanks for reading! :)
86 |
--------------------------------------------------------------------------------
/posts/introducing-the-gleam-package-index.djot:
--------------------------------------------------------------------------------
1 | Gleam is a member of the BEAM family of languages, alongside Erlang, Elixir, and
2 | others. As such Gleam packages are distributed on [Hex.pm][hex], the
3 | package manager for the BEAM ecosystem. Hex provides an excellent experience,
4 | but up until now there has been one small problem: discovering Gleam packages.
5 |
6 | There are thousands of packages on Hex, and while Gleam projects can use
7 | packages written in Erlang or Elixir, most of the time we want to use packages
8 | that are either written in Gleam or already have Gleam bindings. Hex does not
9 | currently provide a way to search by language, so finding these packages is more
10 | difficult than it should be.
11 |
12 | To solve this problem we have created the [Gleam package index][packages], a
13 | website for exploring the Gleam subset of the Hex repository. ✨
14 |
15 | Today it provides a list of all the Gleam packages on Hex as well as a text
16 | search, and future we could add fancy Gleam specific features such as
17 | [searching by type information][elm-search], or [language server integration][lsp]
18 | so packages can be discovered directly from your editor.
19 |
20 | [hex]: https://hex.pm/
21 | [packages]: https://packages.gleam.run/
22 | [elm-search]: https://klaftertief.github.io/elm-search/
23 | [lsp]: /news/v0.21-introducing-the-gleam-language-server/
24 |
25 | ## How does it work?
26 |
27 | The package index is a web application written using the
28 | [`gleam_http`][gleam_http] package. It talks to a PostgreSQL database which it
29 | populates with Gleam packages found by crawling the Hex JSON API. All of this is
30 | deployed to [Fly][fly], who kindly sponsor Gleam's development.
31 |
32 | [gleam_http]: https://github.com/gleam-lang/http
33 | [fly]: https://fly.io/
34 |
35 | In `gleam_http` a web service is a simple function that takes the `Request` type
36 | as an argument and returns the `Response` type. We want some extra data (a
37 | database connection) alongside the request when responding, so we create a
38 | `Context` type that can hold the request and any other data we need.
39 |
40 | ```gleam
41 | pub type Context {
42 | Context(db: pgo.Connection, request: Request(BitString))
43 | }
44 |
45 | /// This function takes a database connection and returns as
46 | /// service function that will response to individual requests
47 | /// by calling `handle_request`.
48 | ///
49 | pub fn make_service(db: pgo.Connection) {
50 | fn(request) {
51 | let context = Context(db, request)
52 | handle_request(context)
53 | }
54 | }
55 | ```
56 |
57 | The `handle_request` function calls the appropriate function for the requested
58 | path, passing the context along with it. Thanks to Gleam's pattern matching we
59 | don't need a complex and slow router abstraction, we can use the super fast and
60 | familiar `case` expression, like any other Gleam code.
61 |
62 | ```gleam
63 | pub fn handle_request(context: Context) {
64 | let path = request.path_segments(context.request)
65 | case path {
66 | [] -> search(context)
67 | ["styles.css"] -> stylesheet()
68 | _ -> redirect(to: "/")
69 | }
70 | }
71 | ```
72 |
73 | The handler functions are where the logic of responding to requests lives. In
74 | the `search` handler we get the search term (if any) from the request, search
75 | the database for appropriate packages, render HTML from the list of packages,
76 | and return a response with this HTML to the user.
77 |
78 | ```gleam
79 | fn search(context: Context) -> Response(String) {
80 | // Search in the database for packages
81 | let term = get_search_parameter(context.request)
82 | let assert Ok(packages) = database.search(context.db, term)
83 |
84 | // Render HTML to show the results
85 | let html = packages_page(packages, term)
86 |
87 | // Return a response
88 | response.new(200)
89 | |> response.set_header("content-type", "text/html; charset=utf-8")
90 | |> response.set_body(html)
91 | }
92 | ```
93 |
94 | For rendering HTML we are using [Nakai][nakai], a package for writing HTML on
95 | the server (or anywhere) in a somewhat similar style to Elm or React, giving us
96 | fully type checked HTML within Gleam.
97 |
98 | [nakai]: https://nakaixo.github.io/
99 |
100 | ```gleam
101 | fn packages_page(packages: List(Package), term: String) -> String {
102 | html.Html([], [
103 | html.head([
104 | meta([charset("utf-8")]),
105 | meta([name("viewport"), content("width=device-width, initial-scale=1")]),
106 | link([rel("stylesheet"), href("/styles.css")]),
107 | title_text([], "Gleam Packages"),
108 | ]),
109 | // ... etc
110 | ```
111 |
112 | Once the service is written we can serve it using [Mist][mist], Alex Manning's
113 | pure Gleam web server. Mist is a fantastic demonstration of Gleam's maturity and
114 | what the language is capable of, and [in benchmarks][benchmarks] it is
115 | comfortably faster than Cowboy, the most commonly used Erlang web server.
116 |
117 | [mist]: https://github.com/rawhat/mist
118 | [benchmarks]: https://github.com/rawhat/http-benchmarks
119 |
120 | ```gleam
121 | pub fn main() {
122 | let assert Ok(key) = os.get_env("HEX_API_KEY")
123 | let db = index.connect()
124 |
125 | // Start syncing new releases every 60 seconds
126 | let sync = fn() { sync_new_gleam_releases(key, db) }
127 | let assert Ok(_) = periodically(sync, waiting: 60 * 1000)
128 |
129 | // Start the web server
130 | let service = web.make_service(db)
131 | let assert Ok(_) = mist.run_service(3000, service, max_body_limit: 4_000_000)
132 | io.println("Started listening on http://localhost:3000 ✨")
133 |
134 | // Put the main process to sleep while the web server handles traffic
135 | process.sleep_forever()
136 | }
137 | ```
138 |
139 | Here in the main function we start two actors, one that periodically syncs new
140 | releases from the Hex API, and one that runs the web server. I won't go into
141 | detail of the syncing process here, but in short it queries the Hex API for
142 | packages ordered by time of last update, and iterates across pages until it has
143 | found all the packages that have been updated since the last time it ran.
144 |
145 | If you'd like to see more of how this project works the source code is available
146 | [on GitHub][source]. I hope you enjoy using the package index, and do let us
147 | know if you have any ideas or suggestions!
148 |
149 | [source]: https://github.com/gleam-lang/packages
150 |
151 |
152 | Happy hacking! 💖
153 |
--------------------------------------------------------------------------------
/posts/introducing-the-gleam-roadmap.djot:
--------------------------------------------------------------------------------
1 | Often people ask "Hey Louis! What's coming next in Gleam?"
2 |
3 | It's a tricky question to answer. Gleam is a community project rather than a
4 | corporate one, so often many things are happening at once. As the project leader
5 | I have my own priorities, but it's up to individual contributors to decide what
6 | they find valuable and fun enough to work on. Often the most useful way to
7 | respond is to give an overview of the upcoming features that I think are most
8 | exciting or impactful, and directing them to the changelog and the issue tracker
9 | if they want to learn more.
10 |
11 | To help with this, and to give folks a quicker way to access this information
12 | than waiting for me to reply on the Gleam discord server, I've created the
13 | Gleam development roadmap. It lists the most impactful features, past,
14 | present, and future, and I'll update it with each new Gleam release. I hope you
15 | find it useful!
16 |
17 | ``` =html
18 |