├── .gitignore ├── CNAME ├── _posts ├── v0.16.0 │ ├── .gitignore │ ├── .gitattributes │ ├── Makefile │ ├── out │ │ ├── hello.js │ │ ├── counter.js │ │ ├── dogs.js │ │ └── multiples.js │ └── src │ │ ├── hello.gleam │ │ ├── counter.gleam │ │ ├── dogs.gleam │ │ └── multiples.gleam ├── 2019-04-15-hello-gleam.md ├── 2019-08-07-gleam-v0.3-released.md ├── 2019-12-25-gleam-v0.6-released.md ├── 2019-09-19-gleam-v0.4-released.md ├── 2020-03-01-gleam-v0.7-released.md └── 2023-04-30-introducing-the-gleam-package-index.md ├── book ├── .nojekyll ├── favicon.png ├── FontAwesome │ └── fonts │ │ ├── FontAwesome.ttf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── fonts │ ├── open-sans-v17-all-charsets-300.woff2 │ ├── open-sans-v17-all-charsets-600.woff2 │ ├── open-sans-v17-all-charsets-700.woff2 │ ├── open-sans-v17-all-charsets-800.woff2 │ ├── open-sans-v17-all-charsets-italic.woff2 │ ├── open-sans-v17-all-charsets-300italic.woff2 │ ├── open-sans-v17-all-charsets-600italic.woff2 │ ├── open-sans-v17-all-charsets-700italic.woff2 │ ├── open-sans-v17-all-charsets-800italic.woff2 │ ├── open-sans-v17-all-charsets-regular.woff2 │ ├── source-code-pro-v11-all-charsets-500.woff2 │ ├── fonts.css │ └── SOURCE-CODE-PRO-LICENSE.txt ├── javascript │ ├── plausible.js │ └── highlightjs-gleam.js ├── tour │ ├── todo.html │ ├── type-annotations │ └── type-annotations.html ├── css │ ├── print.css │ └── general.css ├── ayu-highlight.css ├── highlight.css ├── favicon.svg └── tomorrow-night.css ├── fonts ├── Lexend.woff2 ├── Outfit.woff ├── Lexend-700.woff2 └── CascadiaMono.woff2 ├── images ├── og-image.png ├── sponsors │ ├── memo.png │ ├── nine-fx.png │ └── alembic.svg ├── news │ ├── gleam-v0.21-released │ │ ├── hover.mp4 │ │ ├── hover.webm │ │ ├── compile.mp4 │ │ ├── compile.webm │ │ ├── formatting.mp4 │ │ ├── formatting.webm │ │ ├── goto-definition.mp4 │ │ ├── goto-definition.webm │ │ └── lsp-languages-editors.png │ ├── gleam-v0.14-released │ │ └── night-mode.png │ ├── gleam-v0.23-released │ │ ├── docs-search.mp4 │ │ └── docs-search.webm │ ├── gleam-v0.28-released │ │ └── docs-hover.png │ ├── gleam-v0.7-released │ │ ├── import-cycle.png │ │ ├── type-error.png │ │ └── incorrect-number-of-patterns.png │ ├── gleam-v0.29-released │ │ └── autocompletion.png │ ├── gleam-v0.20-released │ │ └── github-syntax-highlighting.png │ └── gleam-v0.26-released │ │ └── deno_hr_circle.svg ├── sponsor-heart.svg ├── waves.svg ├── pride-wall.svg ├── lucy-charcoal-2.svg └── lucy-pink-2.svg ├── img ├── gleam-0-13-docs-link.jpg ├── gleam-0-13-docs-version.jpg ├── lucy-pink-3.svg └── lucy-pink.svg ├── _layouts ├── post.html ├── page.html ├── layout.html └── old.html ├── javascript ├── plausible.js ├── main.js └── highlightjs-gleam.js ├── _includes ├── chartbar.html ├── hljs.html └── page-header.html ├── README.md ├── news.html ├── Makefile ├── book-src ├── tour │ ├── type-aliases.md │ ├── expression-blocks.md │ ├── README.md │ ├── let-bindings.md │ ├── tuples.md │ ├── external-types.md │ ├── comments.md │ ├── lists.md │ ├── constants.md │ ├── bools.md │ ├── ints-and-floats.md │ ├── strings.md │ ├── todo-and-panic.md │ ├── result.md │ ├── assert.md │ ├── use.md │ ├── external-functions.md │ ├── modules.md │ ├── case-expressions.md │ ├── bit-strings.md │ └── functions.md └── SUMMARY.md ├── book.toml ├── .well-known └── webfinger ├── writing-gleam ├── example-projects.md ├── creating-a-project.md ├── using-the-project.md ├── documenting-the-project.md ├── command-line-reference.sh ├── gleam-toml.md └── command-line-reference.md ├── _config.yml ├── mailing-list.md ├── community.md ├── getting-started.md ├── documentation.md ├── styles └── highlighting.css └── deployment └── fly.md /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | gleam.run 2 | -------------------------------------------------------------------------------- /_posts/v0.16.0/.gitignore: -------------------------------------------------------------------------------- 1 | *.gleam_module 2 | -------------------------------------------------------------------------------- /_posts/v0.16.0/.gitattributes: -------------------------------------------------------------------------------- 1 | out linguist-generated=true 2 | -------------------------------------------------------------------------------- /book/.nojekyll: -------------------------------------------------------------------------------- 1 | This file makes sure that Github Pages doesn't process mdBook's output. 2 | -------------------------------------------------------------------------------- /book/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/favicon.png -------------------------------------------------------------------------------- /fonts/Lexend.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/fonts/Lexend.woff2 -------------------------------------------------------------------------------- /fonts/Outfit.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/fonts/Outfit.woff -------------------------------------------------------------------------------- /images/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/og-image.png -------------------------------------------------------------------------------- /fonts/Lexend-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/fonts/Lexend-700.woff2 -------------------------------------------------------------------------------- /fonts/CascadiaMono.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/fonts/CascadiaMono.woff2 -------------------------------------------------------------------------------- /images/sponsors/memo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/sponsors/memo.png -------------------------------------------------------------------------------- /images/sponsors/nine-fx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/sponsors/nine-fx.png -------------------------------------------------------------------------------- /img/gleam-0-13-docs-link.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/img/gleam-0-13-docs-link.jpg -------------------------------------------------------------------------------- /img/gleam-0-13-docs-version.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/img/gleam-0-13-docs-version.jpg -------------------------------------------------------------------------------- /book/FontAwesome/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/FontAwesome/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/hover.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/hover.mp4 -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/hover.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/hover.webm -------------------------------------------------------------------------------- /_posts/v0.16.0/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build 2 | build: 3 | rm -rf out 4 | gleam compile-package --name example --target javascript --src src --out out 5 | -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/compile.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/compile.mp4 -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/compile.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/compile.webm -------------------------------------------------------------------------------- /book/FontAwesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/FontAwesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /book/FontAwesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/FontAwesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /book/FontAwesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/FontAwesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /book/FontAwesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/FontAwesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-300.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-600.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-700.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-800.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-800.woff2 -------------------------------------------------------------------------------- /images/news/gleam-v0.14-released/night-mode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.14-released/night-mode.png -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/formatting.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/formatting.mp4 -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/formatting.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/formatting.webm -------------------------------------------------------------------------------- /images/news/gleam-v0.23-released/docs-search.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.23-released/docs-search.mp4 -------------------------------------------------------------------------------- /images/news/gleam-v0.28-released/docs-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.28-released/docs-hover.png -------------------------------------------------------------------------------- /images/news/gleam-v0.7-released/import-cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.7-released/import-cycle.png -------------------------------------------------------------------------------- /images/news/gleam-v0.7-released/type-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.7-released/type-error.png -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-italic.woff2 -------------------------------------------------------------------------------- /images/news/gleam-v0.23-released/docs-search.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.23-released/docs-search.webm -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-300italic.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-600italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-600italic.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-700italic.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-800italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-800italic.woff2 -------------------------------------------------------------------------------- /book/fonts/open-sans-v17-all-charsets-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/open-sans-v17-all-charsets-regular.woff2 -------------------------------------------------------------------------------- /book/fonts/source-code-pro-v11-all-charsets-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/book/fonts/source-code-pro-v11-all-charsets-500.woff2 -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/goto-definition.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/goto-definition.mp4 -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/goto-definition.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/goto-definition.webm -------------------------------------------------------------------------------- /images/news/gleam-v0.29-released/autocompletion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.29-released/autocompletion.png -------------------------------------------------------------------------------- /images/news/gleam-v0.21-released/lsp-languages-editors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.21-released/lsp-languages-editors.png -------------------------------------------------------------------------------- /images/news/gleam-v0.20-released/github-syntax-highlighting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.20-released/github-syntax-highlighting.png -------------------------------------------------------------------------------- /images/news/gleam-v0.7-released/incorrect-number-of-patterns.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pietroppeter/gleam-website/main/images/news/gleam-v0.7-released/incorrect-number-of-patterns.png -------------------------------------------------------------------------------- /_layouts/post.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | --- 4 |
5 |

6 | Published {{ page.date | date: "%d %b, %Y" }} by {{ page.author }} 7 |

8 | {{ content }} 9 |
10 | -------------------------------------------------------------------------------- /javascript/plausible.js: -------------------------------------------------------------------------------- 1 | let script = document.createElement("script"); 2 | script.async = true; 3 | script.defer = true; 4 | script.src = "https://plausible.io/js/plausible.js"; 5 | script.dataset.dataDomain = "gleam.run"; 6 | document.body.appendChild(script); 7 | -------------------------------------------------------------------------------- /book/javascript/plausible.js: -------------------------------------------------------------------------------- 1 | let script = document.createElement("script"); 2 | script.async = true; 3 | script.defer = true; 4 | script.src = "https://plausible.io/js/plausible.js"; 5 | script.dataset.dataDomain = "gleam.run"; 6 | document.body.appendChild(script); 7 | -------------------------------------------------------------------------------- /_includes/chartbar.html: -------------------------------------------------------------------------------- 1 |
  • 2 | 10 |
  • 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Gleam website 2 | 3 | https://gleam.run 4 | 5 | 6 | ## Run the website locally 7 | 8 | Install `github-pages` (requires Ruby) 9 | 10 | ```sh 11 | gem install github-pages 12 | gem install webrick # For Ruby3.x 13 | ``` 14 | 15 | and run `make serve` in root directory. 16 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: layout 3 | --- 4 | {% include hljs.html %} 5 | 6 | {% capture header_content %} 7 |

    {{ page.title }}

    8 |

    {{ page.subtitle }}

    9 | {% endcapture %} 10 | {% include page-header.html image=page.header_image content=header_content %} 11 | 12 |
    13 | {{ content }} 14 |
    15 | -------------------------------------------------------------------------------- /images/sponsor-heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /book/tour/todo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Redirecting... 6 | 7 | 8 | 9 | 10 |

    Redirecting to... ./todo-and-panic.html.

    11 | 12 | 13 | -------------------------------------------------------------------------------- /book/tour/type-annotations: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Redirecting... 6 | 7 | 8 | 9 | 10 |

    Redirecting to... ./let-bindings.html.

    11 | 12 | 13 | -------------------------------------------------------------------------------- /book/tour/type-annotations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Redirecting... 6 | 7 | 8 | 9 | 10 |

    Redirecting to... ./let-bindings.html.

    11 | 12 | 13 | -------------------------------------------------------------------------------- /news.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: News log 4 | subtitle: What's happening in the Gleam world? 5 | --- 6 | 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build 2 | build: ## Build the book 3 | sh writing-gleam/command-line-reference.sh > writing-gleam/command-line-reference.md 4 | rm -fr book 5 | mdbook build --dest-dir book/ 6 | 7 | .PHONY: serve 8 | serve: ## Run the book dev server 9 | jekyll server --watch --safe --port 3000 --drafts 10 | 11 | .PHONY: help 12 | help: 13 | @cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z_-]+:.*?## .*$$' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' 14 | -------------------------------------------------------------------------------- /book-src/tour/type-aliases.md: -------------------------------------------------------------------------------- 1 | # Type aliases 2 | 3 | Type aliases are a way of creating a new name for an existing type. This is 4 | useful when the name of the type may be long and awkward to type repeatedly. 5 | 6 | Here we are giving the type `List(#(String, String))` the new name 7 | `Headers`. This may be useful in a web application where we want to write 8 | multiple functions that return headers. 9 | 10 | ```gleam 11 | pub type Headers = 12 | List(#(String, String)) 13 | ``` 14 | -------------------------------------------------------------------------------- /book-src/tour/expression-blocks.md: -------------------------------------------------------------------------------- 1 | # Expression blocks 2 | 3 | Every block in Gleam is an expression. All expressions in the block are 4 | executed, and the result of the last expression is returned. 5 | 6 | ```gleam 7 | let value: Bool = { 8 | "Hello" 9 | 42 + 12 10 | False 11 | } // => False 12 | ``` 13 | 14 | Expression blocks can be used instead of parentheses to change the precedence 15 | of operations. 16 | 17 | ```gleam 18 | let celsius = { fahrenheit - 32 } * 5 / 9 19 | ``` 20 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["Louis Pilfold"] 3 | multilingual = false 4 | src = "book-src" 5 | title = "The Gleam Book" 6 | 7 | [output.html] 8 | additional-js = ["javascript/highlightjs-gleam.js", "javascript/plausible.js"] 9 | git-repository-url = "https://github.com/gleam-lang/website" 10 | git-repository-icon = "fa-github" 11 | 12 | [output.html.redirect] 13 | "tour/type-annotations" = "./let-bindings.html" 14 | "tour/type-annotations.html" = "./let-bindings.html" 15 | "tour/todo.html" = "./todo-and-panic.html" 16 | -------------------------------------------------------------------------------- /book-src/tour/README.md: -------------------------------------------------------------------------------- 1 | # Language Tour 2 | 3 | In this book we explore the fundamentals of the Gleam language, namely its 4 | syntax, core data structures, flow control features, and static type system. 5 | If you have some prior programming experience this will hopefully be enough 6 | to get you started with Gleam. 7 | 8 | In some sections we touch on the runtime representation of various features. 9 | This is useful for programmers with Erlang or Elixir experience who wish to 10 | use Gleam alongside these languages. If you are using Gleam alone this 11 | information can be safely ignored. 12 | -------------------------------------------------------------------------------- /images/waves.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /_includes/hljs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /_posts/v0.16.0/out/hello.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export function main() { 4 | let input = query_selector("[data-hello-input]"); 5 | let display = query_selector("[data-hello-display]"); 6 | let sync = () => { 7 | let text = get(input, "value"); 8 | return set(display, "innerText", text); 9 | }; 10 | return set(input, "oninput", sync); 11 | } 12 | 13 | function query_selector(arg0) { 14 | return document.querySelector(arg0) 15 | } 16 | 17 | function get(from, property) { 18 | return Reflect.get(from, property) 19 | } 20 | 21 | function set(on, property, to) { 22 | return Reflect.set(on, property, to) 23 | } 24 | -------------------------------------------------------------------------------- /_posts/v0.16.0/src/hello.gleam: -------------------------------------------------------------------------------- 1 | pub fn main() { 2 | let input = query_selector("[data-hello-input]") 3 | let display = query_selector("[data-hello-display]") 4 | let sync = fn() { 5 | let text = get(from: input, property: "value") 6 | set("innerText", on: display, to: text) 7 | } 8 | set("oninput", on: input, to: sync) 9 | } 10 | 11 | external type Element 12 | 13 | external fn query_selector(String) -> Element = 14 | "" "document.querySelector" 15 | 16 | external fn get(from: Element, property: String) -> String = 17 | "" "Reflect.get" 18 | 19 | external fn set(on: Element, property: String, to: anything) -> Bool = 20 | "" "Reflect.set" 21 | -------------------------------------------------------------------------------- /book-src/tour/let-bindings.md: -------------------------------------------------------------------------------- 1 | # Let bindings 2 | 3 | A value can be given a name using `let`. Names can be reused by later let 4 | bindings, but the values contained are _immutable_, meaning the values 5 | themselves cannot be changed. 6 | 7 | ```gleam 8 | let x = 1 9 | let y = x 10 | let x = 2 11 | 12 | x // => 2 13 | y // => 1 14 | ``` 15 | 16 | ## Type annotations 17 | 18 | A type annotation can be added to a let binding. 19 | 20 | ```gleam 21 | let x: Int = 1 22 | ``` 23 | 24 | These annotations are optional and while they are checked, they do not aid the 25 | type checker. Gleam code is always fully type checked with or without type 26 | annotations. 27 | -------------------------------------------------------------------------------- /.well-known/webfinger: -------------------------------------------------------------------------------- 1 | { 2 | "subject": "acct:lpil@hachyderm.io", 3 | "aliases": [ 4 | "https://hachyderm.io/@lpil", 5 | "https://hachyderm.io/users/lpil" 6 | ], 7 | "links": [ 8 | { 9 | "rel": "http://webfinger.net/rel/profile-page", 10 | "type": "text/html", 11 | "href": "https://hachyderm.io/@lpil" 12 | }, 13 | { 14 | "rel": "self", 15 | "type": "application/activity+json", 16 | "href": "https://hachyderm.io/users/lpil" 17 | }, 18 | { 19 | "rel": "http://ostatus.org/schema/1.0/subscribe", 20 | "template": "https://hachyderm.io/authorize_interaction?uri={uri}" 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /writing-gleam/example-projects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Example projects 3 | subtitle: Talk is cheap, show me the code! 4 | layout: page 5 | --- 6 | 7 | When learning a new language it can often be useful to have example code to 8 | refer to and learn from, so here are some examples: 9 | 10 | 11 | ## [TodoMVC](https://github.com/gleam-lang/example-todomvc) 12 | 13 | An example todo-list web application, built with the Gleam HTTP library. 14 | 15 | 16 | ## [The Gleam standard library](https://github.com/gleam-lang/stdlib) 17 | 18 | A collection of modules for working with the common data structures of Gleam. 19 | 20 | 21 | ## [Awesome Gleam](https://github.com/gleam-lang/awesome-gleam) 22 | 23 | A list of libraries and projects from the community. 24 | -------------------------------------------------------------------------------- /javascript/main.js: -------------------------------------------------------------------------------- 1 | function showPride() { 2 | document.body.classList.toggle("pride"); 3 | } 4 | 5 | function expandSponsorsSection() { 6 | document.documentElement.style.setProperty("--sponsors-max-height", "5000px"); 7 | } 8 | 9 | if (new Date().getMonth() === 5) showPride(); 10 | 11 | for (let element of document.querySelectorAll("[data-show-pride]")) { 12 | element.addEventListener("click", showPride); 13 | } 14 | 15 | for (let element of document.querySelectorAll("[data-randomise-order]")) { 16 | let children = Array.from(element.children); 17 | children.sort(() => Math.random() - 0.5); 18 | element.replaceChildren(...children); 19 | } 20 | 21 | for (let element of document.querySelectorAll("[data-expand-sponsors]")) { 22 | element.addEventListener("click", expandSponsorsSection); 23 | } 24 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | baseurl: "" 2 | url: "https://gleam.run/" 3 | 4 | markdown: kramdown 5 | 6 | permalink: "/news/:title/" 7 | 8 | title: Gleam 9 | description: Gleam is a fast, friendly, and functional language for building type-safe, scalable systems! 10 | 11 | plugins: 12 | - jekyll-redirect-from 13 | - jekyll-feed 14 | 15 | whitelist: 16 | - jekyll-redirect-from 17 | - jekyll-feed 18 | 19 | exclude: 20 | - README 21 | - Makefile 22 | - book-src 23 | 24 | include: 25 | - .well-known 26 | 27 | defaults: 28 | - 29 | scope: 30 | path: "" # all files 31 | type: posts # limit to posts 32 | values: 33 | layout: post 34 | 35 | # Syntax highlighting is handled by highlight.js 36 | highlighter: kramdown 37 | kramdown: 38 | syntax_highlighter_opts: 39 | disable: true 40 | -------------------------------------------------------------------------------- /book-src/tour/tuples.md: -------------------------------------------------------------------------------- 1 | # Tuples 2 | 3 | Lists are good for when we want a collection of one type, but sometimes we want 4 | to combine multiple values of different types. In this case tuples are a quick 5 | and convenient option. 6 | 7 | Gleam provides two ways to construct or match on tuples: the `#(1, 2, 3)` format, 8 | introduced in Gleam 0.15.0, and the original `tuple(1, 2, 3)` format which will 9 | be removed in a future version of Gleam. 10 | 11 | ```gleam 12 | #(10, "hello") // Type is #(Int, String) 13 | #(1, 4.2, [0]) // Type is #(Int, Float, List(Int)) 14 | ``` 15 | 16 | Once you have a tuple the values contained can be accessed using the `.0` 17 | accessor syntax. 18 | 19 | ```gleam 20 | let my_tuple = #("one", "two") 21 | let first = my_tuple.0 // "one" 22 | let second = my_tuple.1 // "two" 23 | ``` 24 | -------------------------------------------------------------------------------- /book/css/print.css: -------------------------------------------------------------------------------- 1 | 2 | #sidebar, 3 | #menu-bar, 4 | .nav-chapters, 5 | .mobile-nav-chapters { 6 | display: none; 7 | } 8 | 9 | #page-wrapper.page-wrapper { 10 | transform: none; 11 | margin-left: 0px; 12 | overflow-y: initial; 13 | } 14 | 15 | #content { 16 | max-width: none; 17 | margin: 0; 18 | padding: 0; 19 | } 20 | 21 | .page { 22 | overflow-y: initial; 23 | } 24 | 25 | pre > .buttons { 26 | z-index: 2; 27 | } 28 | 29 | a, a:visited, a:active, a:hover { 30 | color: #4183c4; 31 | text-decoration: none; 32 | } 33 | 34 | h1, h2, h3, h4, h5, h6 { 35 | page-break-inside: avoid; 36 | page-break-after: avoid; 37 | } 38 | 39 | pre, code { 40 | page-break-inside: avoid; 41 | white-space: pre-wrap; 42 | } 43 | 44 | .fa { 45 | display: none !important; 46 | } 47 | -------------------------------------------------------------------------------- /book-src/tour/external-types.md: -------------------------------------------------------------------------------- 1 | # External type 2 | 3 | In addition to importing external functions we can also import external types. 4 | Gleam knows nothing about the runtime representation of these types and so 5 | they cannot be pattern matched on, but they can be used with external 6 | functions that know how to work with them. 7 | 8 | To write an external type define a type but don't give it any constructors. Here 9 | is an example of importing a `Queue` data type and some functions from Erlang's 10 | `queue` module to work with the new `Queue` type. 11 | 12 | ```gleam 13 | pub type Queue(a) 14 | 15 | @external(erlang, "queue", "new") 16 | pub fn new() -> Queue(a) 17 | 18 | @external(erlang, "queue", "len") 19 | pub fn length(queue: Queue(a)) -> Int 20 | 21 | @external(erlang, "queue", "in") 22 | pub fn push(new: a, queue: Queue(a)) -> Queue(a) 23 | ``` 24 | -------------------------------------------------------------------------------- /book-src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Language tour](./tour/README.md) 4 | - [Comments](./tour/comments.md) 5 | - [Strings](./tour/strings.md) 6 | - [Bools](./tour/bools.md) 7 | - [Ints & Floats](./tour/ints-and-floats.md) 8 | - [Let bindings](./tour/let-bindings.md) 9 | - [Expression blocks](./tour/expression-blocks.md) 10 | - [Lists](./tour/lists.md) 11 | - [Tuples](./tour/tuples.md) 12 | - [Case expressions](./tour/case-expressions.md) 13 | - [Functions](./tour/functions.md) 14 | - [Modules](./tour/modules.md) 15 | - [Custom types](./tour/custom-types.md) 16 | - [Result](./tour/result.md) 17 | - [Assert](./tour/assert.md) 18 | - [Todo & Panic](./tour/todo-and-panic.md) 19 | - [Constants](./tour/constants.md) 20 | - [Type aliases](./tour/type-aliases.md) 21 | - [Bit strings](./tour/bit-strings.md) 22 | - [Use](./tour/use.md) 23 | - [External functions](./tour/external-functions.md) 24 | - [External types](./tour/external-types.md) 25 | -------------------------------------------------------------------------------- /book-src/tour/comments.md: -------------------------------------------------------------------------------- 1 | # Comments 2 | 3 | Gleam allows you to write comments in your code. 4 | 5 | Here’s a simple comment: 6 | 7 | ```gleam 8 | // Hello, world! 9 | ``` 10 | 11 | In Gleam, comments must start with two slashes and continue until the end of the 12 | line. For comments that extend beyond a single line, you’ll need to include 13 | `//` on each line, like this: 14 | 15 | ```gleam 16 | // Hello, world! I have a lot to say, so much that it will take multiple 17 | // lines of text. Therefore, I will start each line with // to denote it 18 | // as part of a multi-line comment. 19 | ``` 20 | 21 | Comments can also be placed at the end of lines containing code: 22 | 23 | ```gleam 24 | pub fn add(x, y) { 25 | x + y // here we are adding two values together 26 | } 27 | ``` 28 | 29 | Comments may also be indented: 30 | 31 | ```gleam 32 | pub fn multiply(x, y) { 33 | // here we are multiplying x by y 34 | x * y 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /_posts/v0.16.0/out/counter.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export function main() { 4 | let increment = query_selector("[data-counter-increment]"); 5 | let decrement = query_selector("[data-counter-decrement]"); 6 | let display = query_selector("[data-counter-display]"); 7 | let add = (diff) => { 8 | return set(display, "innerText", get_value(display) + diff); 9 | }; 10 | set(increment, "onclick", () => { return add(1); }); 11 | return set(decrement, "onclick", () => { return add(-1); }); 12 | } 13 | 14 | function get_value(element) { 15 | return parse_int(get(element, "innerText")); 16 | } 17 | 18 | function query_selector(arg0) { 19 | return document.querySelector(arg0) 20 | } 21 | 22 | function get(from, property) { 23 | return Reflect.get(from, property) 24 | } 25 | 26 | function set(on, property, to) { 27 | return Reflect.set(on, property, to) 28 | } 29 | 30 | function parse_int(arg0) { 31 | return parseInt(arg0) 32 | } 33 | -------------------------------------------------------------------------------- /mailing-list.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: layout 3 | title: Mailing list 4 | description: The Gleam at-most-monthly mailing list 5 | --- 6 | {% capture header_content %} 7 |
    8 |

    Wanna keep in touch?

    9 | 11 |

    12 | We'll send you at most one newsletter a month, and we'll never share 13 | your email with anyone else. 14 |

    15 |

    16 | This site is protected by reCAPTCHA and the Google 17 | Privacy Policy and 18 | Terms of Service apply. 19 |

    20 |
    21 | {% endcapture %} 22 | {% include page-header.html image="/images/lucy-charcoal-2.svg" alt="Lucy the star, Gleam's mascot" 23 | content=header_content %} 24 | -------------------------------------------------------------------------------- /_posts/v0.16.0/src/counter.gleam: -------------------------------------------------------------------------------- 1 | pub fn main() { 2 | let increment = query_selector("[data-counter-increment]") 3 | let decrement = query_selector("[data-counter-decrement]") 4 | let display = query_selector("[data-counter-display]") 5 | let add = fn(diff) { 6 | set("innerText", on: display, to: get_value(display) + diff) 7 | } 8 | set("onclick", on: increment, to: fn() { add(1) }) 9 | set("onclick", on: decrement, to: fn() { add(-1) }) 10 | } 11 | 12 | fn get_value(element) { 13 | element 14 | |> get(property: "innerText") 15 | |> parse_int 16 | } 17 | 18 | external type Element 19 | 20 | external fn query_selector(String) -> Element = 21 | "" "document.querySelector" 22 | 23 | external fn get(from: Element, property: String) -> String = 24 | "" "Reflect.get" 25 | 26 | external fn set(on: Element, property: String, to: anything) -> Bool = 27 | "" "Reflect.set" 28 | 29 | external fn parse_int(String) -> Int = 30 | "" "parseInt" 31 | -------------------------------------------------------------------------------- /writing-gleam/creating-a-project.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating a project 3 | layout: page 4 | --- 5 | 6 | The `gleam new` command can be used to generate a new Gleam project. 7 | 8 | ```sh 9 | gleam new my_fantastic_library 10 | cd my_fantastic_library 11 | ``` 12 | 13 | You'll now have a project with this structure: 14 | 15 | ``` 16 | . 17 | ├── gleam.toml 18 | ├── README.md 19 | ├── src 20 | │   └── my_fantastic_library.gleam 21 | └── test 22 | └── my_fantastic_library_test.gleam 23 | 24 | 2 directories, 4 files 25 | ``` 26 | 27 | Regular Gleam code goes in the `src` directory, and the tests for this code 28 | go in the `test` directory. 29 | 30 | You can run your project with the `gleam run` command and test it with the 31 | `gleam test` command. 32 | 33 | 34 | ## Continuous integration 35 | 36 | All Gleam projects come preconfigured for GitHub Actions CI. Push your 37 | project to GitHub to have the tests and linting run automatically for new 38 | commits and pull requests. 39 | 40 | -------------------------------------------------------------------------------- /images/pride-wall.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /_includes/page-header.html: -------------------------------------------------------------------------------- 1 | 34 | -------------------------------------------------------------------------------- /book-src/tour/lists.md: -------------------------------------------------------------------------------- 1 | # List 2 | 3 | Lists are ordered collections of values. They're one of the most common data 4 | structures in Gleam. 5 | 6 | Lists are _homogeneous_, meaning all the elements of a List must be of the 7 | same type. Attempting to construct a list of multiple types of element will 8 | result in the compiler presenting a type error. 9 | 10 | ```gleam 11 | [1, 2, 3, 4] // List(Int) 12 | [1.22, 2.30] // List(Float) 13 | [1.22, 3, 4] // Type error! 14 | ``` 15 | 16 | Prepending to a list is very fast, and is the preferred way to add new values. 17 | 18 | ```gleam 19 | [1, ..[2, 3]] // => [1, 2, 3] 20 | ``` 21 | 22 | Note that all data structures in Gleam are immutable so prepending to a list 23 | does not change the original list. Instead it efficiently creates a new list 24 | with the new additional element. 25 | 26 | ```gleam 27 | let x = [2, 3] 28 | let y = [1, ..x] 29 | 30 | 31 | x // => [2, 3] 32 | y // => [1, 2, 3] 33 | ``` 34 | 35 | ## Stdlib references 36 | 37 | - [gleam/list](https://hexdocs.pm/gleam_stdlib/gleam/list.html) 38 | - [gleam/iterator](https://hexdocs.pm/gleam_stdlib/gleam/iterator.html) 39 | -------------------------------------------------------------------------------- /_posts/v0.16.0/out/dogs.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const url = "https://dog.ceo/api/breeds/image/random"; 4 | 5 | export function main() { 6 | let button = query_selector("[data-dogs-button]"); 7 | let img = query_selector("[data-dogs-img]"); 8 | new_dog(img); 9 | return set(button, "onclick", () => { return new_dog(img); }); 10 | } 11 | 12 | function new_dog(img) { 13 | return then( 14 | then(fetch(url), get_json_body), 15 | (json) => { 16 | set(img, "src", get(json, "message")); 17 | return resolve_promise(undefined); 18 | }, 19 | ); 20 | } 21 | 22 | function query_selector(arg0) { 23 | return document.querySelector(arg0) 24 | } 25 | 26 | function get(from, property) { 27 | return Reflect.get(from, property) 28 | } 29 | 30 | function set(on, property, to) { 31 | return Reflect.set(on, property, to) 32 | } 33 | 34 | function fetch(arg0) { 35 | return globalThis.fetch(arg0) 36 | } 37 | 38 | function get_json_body(arg0) { 39 | return Response.prototype.json.call(arg0) 40 | } 41 | 42 | function then(arg0, arg1) { 43 | return Promise.prototype.then.call(arg0, arg1) 44 | } 45 | 46 | function resolve_promise(arg0) { 47 | return Promise.resolve(arg0) 48 | } 49 | -------------------------------------------------------------------------------- /community.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Gleam Community 3 | subtitle: Welcome, friend! It's good to have you 4 | layout: page 5 | --- 6 | 7 | You can talk to and get help from other Gleam community members in the 8 | following forums: 9 | 10 | - [Gleam's web chat on Discord][2]. 11 | - [Gleam discussions on Github][3]. 12 | - [Gleam's threads on the Erlang Forums][4] 13 | 14 | 15 | ## Code of Conduct 16 | 17 | The Gleam community is a space where we treat each other kindly and with 18 | respect. Please read and adhere to our community [code of conduct][1]. 19 | 20 | If you need help or have encountered anyone violating our code of conduct 21 | please send a message to us via one of the channels below. We will ensure the 22 | issue is resolved and your identity will be kept private. 23 | 24 | - Messaging the `@moderators` group on the [Gleam Discord chat][2]. 25 | - Messaging the [@gleamlang][5] account on Twitter. 26 | - Emailing [hello@gleam.run](mailto:hello@gleam.run). 27 | 28 | [1]: https://github.com/gleam-lang/gleam/blob/main/CODE_OF_CONDUCT.md 29 | [2]: https://discord.gg/Fm8Pwmy 30 | [3]: https://github.com/gleam-lang/gleam/discussions 31 | [4]: https://erlangforums.com/gleam 32 | [5]: https://twitter.com/gleamlang 33 | -------------------------------------------------------------------------------- /book/ayu-highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | Based off of the Ayu theme 3 | Original by Dempfi (https://github.com/dempfi/ayu) 4 | */ 5 | 6 | .hljs { 7 | display: block; 8 | overflow-x: auto; 9 | background: #191f26; 10 | color: #e6e1cf; 11 | } 12 | 13 | .hljs-comment, 14 | .hljs-quote { 15 | color: #5c6773; 16 | font-style: italic; 17 | } 18 | 19 | .hljs-variable, 20 | .hljs-template-variable, 21 | .hljs-attribute, 22 | .hljs-attr, 23 | .hljs-regexp, 24 | .hljs-link, 25 | .hljs-selector-id, 26 | .hljs-selector-class { 27 | color: #ff7733; 28 | } 29 | 30 | .hljs-number, 31 | .hljs-meta, 32 | .hljs-builtin-name, 33 | .hljs-literal, 34 | .hljs-type, 35 | .hljs-params { 36 | color: #ffee99; 37 | } 38 | 39 | .hljs-string, 40 | .hljs-bullet { 41 | color: #b8cc52; 42 | } 43 | 44 | .hljs-title, 45 | .hljs-built_in, 46 | .hljs-section { 47 | color: #ffb454; 48 | } 49 | 50 | .hljs-keyword, 51 | .hljs-selector-tag, 52 | .hljs-symbol { 53 | color: #ff7733; 54 | } 55 | 56 | .hljs-name { 57 | color: #36a3d9; 58 | } 59 | 60 | .hljs-tag { 61 | color: #00568d; 62 | } 63 | 64 | .hljs-emphasis { 65 | font-style: italic; 66 | } 67 | 68 | .hljs-strong { 69 | font-weight: bold; 70 | } 71 | 72 | .hljs-addition { 73 | color: #91b362; 74 | } 75 | 76 | .hljs-deletion { 77 | color: #d96c75; 78 | } 79 | -------------------------------------------------------------------------------- /getting-started.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: Getting started 4 | subtitle: On your marks, get set, go! 5 | redirect_from: 6 | - "/book/getting-started/index.html" 7 | --- 8 | 9 | ## Get an overview of Gleam 10 | 11 | To get an overview of the Gleam language check out the 12 | [language tour](/book/tour/). 13 | 14 | 15 | ## Learn Gleam with the Exercism course 16 | 17 | Exercism is a platform for learning programming languages through practice. 18 | Their [Gleam course](https://exercism.io/tracks/gleam) is a great way to learn 19 | the language and get mentored by experienced Gleam developers. 20 | 21 | 22 | ## Install Gleam 23 | 24 | [Install Gleam on your computer](/getting-started/installing/) and add a plugin 25 | for your text editor to start writing Gleam programs. 26 | 27 | 28 | ## Creating a project 29 | 30 | The `gleam new [name]` command can be used to [generate a new Gleam project](https://gleam.run/writing-gleam/creating-a-project/). 31 | 32 | 33 | ## Running a project 34 | 35 | The `gleam run` command can be used to [run the Gleam project](https://gleam.run/writing-gleam/using-the-project). 36 | 37 | 38 | ## Documentation 39 | 40 | Further cheatsheets, awesome-gleam, FAQ, example projects and more in [the documentation](https://gleam.run/documentation/). 41 | 42 | 43 | -------------------------------------------------------------------------------- /book-src/tour/constants.md: -------------------------------------------------------------------------------- 1 | # Constants 2 | 3 | Gleam's module constants provide a way to use a certain fixed value in 4 | multiple places in a Gleam project. 5 | 6 | ```gleam 7 | pub const start_year = 2101 8 | pub const end_year = 2111 9 | 10 | pub fn is_before(year: Int) -> Bool { 11 | year < start_year 12 | } 13 | 14 | pub fn is_during(year: Int) -> Bool { 15 | start_year <= year && year <= end_year 16 | } 17 | ``` 18 | 19 | Like all values in Gleam constants are immutable and their values cannot be 20 | changed, so they cannot be used as global mutable state. 21 | 22 | When a constant is referenced the value is inlined by the compiler, so they 23 | can be used in case expression guards. 24 | 25 | ```gleam 26 | pub const start_year = 2101 27 | pub const end_year = 2111 28 | 29 | pub describe(year: Int) -> String { 30 | case year { 31 | year if year < start_year -> "Before" 32 | year if year > end_year -> "After" 33 | _ -> "During" 34 | } 35 | } 36 | ``` 37 | 38 | ## Type annotations 39 | 40 | Constants can also be given type annotations. 41 | 42 | ```gleam 43 | pub const name: String = "Gleam" 44 | pub const size: Int = 100 45 | ``` 46 | 47 | These annotations serve as documentation or can be used to provide a more 48 | specific type than the compiler would otherwise infer. 49 | -------------------------------------------------------------------------------- /_posts/v0.16.0/src/dogs.gleam: -------------------------------------------------------------------------------- 1 | const url = "https://dog.ceo/api/breeds/image/random" 2 | 3 | pub fn main() { 4 | let button = query_selector("[data-dogs-button]") 5 | let img = query_selector("[data-dogs-img]") 6 | new_dog(img) 7 | set(on: button, property: "onclick", to: fn() { new_dog(img) }) 8 | } 9 | 10 | fn new_dog(img) { 11 | fetch(url) 12 | |> then(get_json_body) 13 | |> then(fn(json) { 14 | set(on: img, property: "src", to: get(json, "message")) 15 | resolve_promise(Nil) 16 | }) 17 | } 18 | 19 | external type Element 20 | 21 | external type Response 22 | 23 | external type Json 24 | 25 | external type Promise(value) 26 | 27 | external fn query_selector(String) -> Element = 28 | "" "document.querySelector" 29 | 30 | external fn get(from: Json, property: String) -> Json = 31 | "" "Reflect.get" 32 | 33 | external fn set(on: Element, property: String, to: anything) -> Bool = 34 | "" "Reflect.set" 35 | 36 | external fn fetch(String) -> Promise(Response) = 37 | "" "fetch" 38 | 39 | external fn get_json_body(Response) -> Promise(Json) = 40 | "" "Response.prototype.json.call" 41 | 42 | external fn then(Promise(a), fn(a) -> Promise(b)) -> Promise(b) = 43 | "" "Promise.prototype.then.call" 44 | 45 | external fn resolve_promise(value) -> Promise(value) = 46 | "" "Promise.resolve" 47 | -------------------------------------------------------------------------------- /book-src/tour/bools.md: -------------------------------------------------------------------------------- 1 | # Bool 2 | 3 | A Bool can be either `True` or `False`. 4 | 5 | Gleam defines a handful of operators that work with Bools. 6 | 7 | ```gleam 8 | False && False // => False 9 | False && True // => False 10 | True && False // => False 11 | True && True // => True 12 | 13 | False || False // => False 14 | False || True // => True 15 | True || False // => True 16 | True || True // => True 17 | ``` 18 | 19 | `&&` and `||` are _short circuiting_, meaning they don't evaluate the right 20 | hand side if they don't have to. 21 | 22 | `&&` evaluates the right hand side if the left hand side is `True`. 23 | 24 | `||` evaluates the right hand side if the left hand side is `False`. 25 | 26 | Gleam supports negation of Bools using either the `!` operator or the 27 | `bool.negate` function from the `gleam/bool` module. 28 | 29 | ```gleam 30 | !True // => False 31 | !False // => True 32 | ``` 33 | 34 | ## Erlang interop 35 | 36 | While written in the code using a capital letter, they are represented at 37 | runtime with the atoms `true` and `false`, making them compatible with Elixir 38 | and Erlang's booleans. 39 | 40 | This is important if you want to use Gleam and Elixir or Erlang together in 41 | one project. 42 | 43 | ```gleam 44 | // Gleam 45 | True 46 | False 47 | ``` 48 | 49 | ```erlang 50 | % Erlang 51 | true. 52 | false. 53 | ``` 54 | 55 | ## Stdlib references 56 | 57 | - [gleam/bool](https://hexdocs.pm/gleam_stdlib/gleam/bool.html) 58 | -------------------------------------------------------------------------------- /documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Documentation 3 | subtitle: Learn all about programming in Gleam! 4 | layout: page 5 | --- 6 | 7 | ## Learning Gleam 8 | 9 | - [Getting started](/getting-started) 10 | - [Language tour](/book/tour) 11 | - Writing Gleam 12 | - [Creating a project](/writing-gleam/creating-a-project) 13 | - [Running the project](/writing-gleam/using-the-project) 14 | - [Documenting the project](/writing-gleam/documenting-the-project) 15 | - [Example projects](/writing-gleam/example-projects) 16 | 17 | ## Gleam references 18 | 19 | - [The Gleam Package Index](https://packages.gleam.run) 20 | - [Gleam's standard library documentation](https://hexdocs.pm/gleam_stdlib/) 21 | - [The "Awesome Gleam" resource list](https://github.com/gleam-lang/awesome-gleam) 22 | - [gleam.toml config file reference](/writing-gleam/gleam-toml) 23 | - [Command line reference](/writing-gleam/command-line-reference) 24 | 25 | ## Cheatsheets 26 | 27 | - [Gleam for Elixir users](/cheatsheets/gleam-for-elixir-users) 28 | - [Gleam for Elm users](/cheatsheets/gleam-for-elm-users) 29 | - [Gleam for Erlang users](/cheatsheets/gleam-for-erlang-users) 30 | - [Gleam for PHP users](/cheatsheets/gleam-for-php-users) 31 | - [Gleam for Python users](/cheatsheets/gleam-for-python-users) 32 | - [Gleam for Rust users](/cheatsheets/gleam-for-rust-users) 33 | 34 | ## Deployment 35 | 36 | - [Deploying on Fly.io](/deployment/fly) 37 | 38 | ## About Gleam 39 | 40 | - [Frequently asked questions](/frequently-asked-questions) 41 | -------------------------------------------------------------------------------- /_posts/v0.16.0/src/multiples.gleam: -------------------------------------------------------------------------------- 1 | pub fn main() { 2 | let numerator = query_selector("[data-multiples-numerator]") 3 | let denominator = query_selector("[data-multiples-denominator]") 4 | let display = query_selector("[data-multiples-display]") 5 | let sync = fn() { sync(display, numerator, denominator) } 6 | set("onchange", on: numerator, to: sync) 7 | set("onchange", on: denominator, to: sync) 8 | sync() 9 | } 10 | 11 | fn sync(display, numerator, denominator) { 12 | let numerator = parse_int(get(numerator, "value")) 13 | let denominator = parse_int(get(denominator, "value")) 14 | let text = case numerator % denominator { 15 | 0 -> 16 | to_string(numerator) 17 | |> append(" is a multiple of ") 18 | |> append(to_string(denominator)) 19 | _ -> 20 | to_string(numerator) 21 | |> append(" is not a multiple of ") 22 | |> append(to_string(denominator)) 23 | } 24 | set(on: display, property: "innerText", to: text) 25 | } 26 | 27 | external type Element 28 | 29 | external fn query_selector(String) -> Element = 30 | "" "document.querySelector" 31 | 32 | external fn get(from: Element, property: String) -> String = 33 | "" "Reflect.get" 34 | 35 | external fn set(on: Element, property: String, to: anything) -> Bool = 36 | "" "Reflect.set" 37 | 38 | external fn append(String, String) -> String = 39 | "" "String.prototype.concat.call" 40 | 41 | external fn to_string(Int) -> String = 42 | "" "String" 43 | 44 | external fn parse_int(String) -> Int = 45 | "" "parseInt" 46 | -------------------------------------------------------------------------------- /book/highlight.css: -------------------------------------------------------------------------------- 1 | /* 2 | * An increased contrast highlighting scheme loosely based on the 3 | * "Base16 Atelier Dune Light" theme by Bram de Haan 4 | * (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/dune) 5 | * Original Base16 color scheme by Chris Kempson 6 | * (https://github.com/chriskempson/base16) 7 | */ 8 | 9 | /* Comment */ 10 | .hljs-comment, 11 | .hljs-quote { 12 | color: #575757; 13 | } 14 | 15 | /* Red */ 16 | .hljs-variable, 17 | .hljs-template-variable, 18 | .hljs-attribute, 19 | .hljs-tag, 20 | .hljs-name, 21 | .hljs-regexp, 22 | .hljs-link, 23 | .hljs-name, 24 | .hljs-selector-id, 25 | .hljs-selector-class { 26 | color: #d70025; 27 | } 28 | 29 | /* Orange */ 30 | .hljs-number, 31 | .hljs-meta, 32 | .hljs-built_in, 33 | .hljs-builtin-name, 34 | .hljs-literal, 35 | .hljs-type, 36 | .hljs-params { 37 | color: #b21e00; 38 | } 39 | 40 | /* Green */ 41 | .hljs-string, 42 | .hljs-symbol, 43 | .hljs-bullet { 44 | color: #008200; 45 | } 46 | 47 | /* Blue */ 48 | .hljs-title, 49 | .hljs-section { 50 | color: #0030f2; 51 | } 52 | 53 | /* Purple */ 54 | .hljs-keyword, 55 | .hljs-selector-tag { 56 | color: #9d00ec; 57 | } 58 | 59 | .hljs { 60 | display: block; 61 | overflow-x: auto; 62 | background: #f6f7f6; 63 | color: #000; 64 | } 65 | 66 | .hljs-emphasis { 67 | font-style: italic; 68 | } 69 | 70 | .hljs-strong { 71 | font-weight: bold; 72 | } 73 | 74 | .hljs-addition { 75 | color: #22863a; 76 | background-color: #f0fff4; 77 | } 78 | 79 | .hljs-deletion { 80 | color: #b31d28; 81 | background-color: #ffeef0; 82 | } 83 | -------------------------------------------------------------------------------- /book-src/tour/ints-and-floats.md: -------------------------------------------------------------------------------- 1 | # Int and Float 2 | 3 | Gleam's main number types are Int and Float. 4 | 5 | ## Ints 6 | 7 | Ints are "whole" numbers. 8 | 9 | Binary, octal, and hexadecimal ints begin with `0b`, `0o`, and `0x` respectively. 10 | 11 | ```gleam 12 | 1 13 | 2 14 | -3 15 | 4001 16 | 0b00001111 17 | 0o17 18 | 0xF 19 | ``` 20 | 21 | Gleam has several operators that work with Ints. 22 | 23 | ```gleam 24 | 1 + 1 // => 2 25 | 5 - 1 // => 4 26 | 5 / 2 // => 2 27 | 3 * 3 // => 9 28 | 5 % 2 // => 1 29 | 30 | 2 > 1 // => True 31 | 2 < 1 // => False 32 | 2 >= 1 // => True 33 | 2 <= 1 // => False 34 | ``` 35 | 36 | Underscores can be added to Ints for clarity. 37 | 38 | ```gleam 39 | 1_000_000 // One million 40 | ``` 41 | 42 | ## Floats 43 | 44 | Floats are numbers that have a decimal point. 45 | 46 | ```gleam 47 | 1.5 48 | 2.0 49 | -0.1 50 | ``` 51 | 52 | Floats also have their own set of operators. 53 | 54 | ```gleam 55 | 1.0 +. 1.4 // => 2.4 56 | 5.0 -. 1.5 // => 3.5 57 | 5.0 /. 2.0 // => 2.5 58 | 3.0 *. 3.1 // => 9.3 59 | 60 | 2.0 >. 1.0 // => True 61 | 2.0 <. 1.0 // => False 62 | 2.0 >=. 1.0 // => True 63 | 2.0 <=. 1.0 // => False 64 | ``` 65 | 66 | Underscores can also be added to Floats for clarity. 67 | 68 | ```gleam 69 | 1_000_000.0 // One million 70 | ``` 71 | 72 | Scientific notation can also be used with Floats: 73 | 74 | ```gleam 75 | 1.01e3 // 1010 76 | 15.1e-3 // 0.0151 77 | ``` 78 | 79 | ## Stdlib references 80 | 81 | - [gleam/float](https://hexdocs.pm/gleam_stdlib/gleam/float.html) 82 | - [gleam/int](https://hexdocs.pm/gleam_stdlib/gleam/int.html) 83 | -------------------------------------------------------------------------------- /_posts/v0.16.0/out/multiples.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | export function main() { 4 | let numerator = query_selector("[data-multiples-numerator]"); 5 | let denominator = query_selector("[data-multiples-denominator]"); 6 | let display = query_selector("[data-multiples-display]"); 7 | let sync$1 = () => { return sync(display, numerator, denominator); }; 8 | set(numerator, "onchange", sync$1); 9 | set(denominator, "onchange", sync$1); 10 | return sync$1(); 11 | } 12 | 13 | function sync(display, numerator, denominator) { 14 | let numerator$1 = parse_int(get(numerator, "value")); 15 | let denominator$1 = parse_int(get(denominator, "value")); 16 | let text = (() => { let $ = numerator$1 % denominator$1; 17 | if ($ === 0) { 18 | return append( 19 | append(to_string(numerator$1), " is a multiple of "), 20 | to_string(denominator$1), 21 | ); 22 | } else { 23 | return append( 24 | append(to_string(numerator$1), " is not a multiple of "), 25 | to_string(denominator$1), 26 | ); 27 | } })(); 28 | return set(display, "innerText", text); 29 | } 30 | 31 | function query_selector(arg0) { 32 | return document.querySelector(arg0) 33 | } 34 | 35 | function get(from, property) { 36 | return Reflect.get(from, property) 37 | } 38 | 39 | function set(on, property, to) { 40 | return Reflect.set(on, property, to) 41 | } 42 | 43 | function append(arg0, arg1) { 44 | return String.prototype.concat.call(arg0, arg1) 45 | } 46 | 47 | function to_string(arg0) { 48 | return String(arg0) 49 | } 50 | 51 | function parse_int(arg0) { 52 | return parseInt(arg0) 53 | } 54 | -------------------------------------------------------------------------------- /book-src/tour/strings.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | In Gleam Strings can be written as text surrounded by double quotes. 4 | 5 | ```gleam 6 | "Hello, Gleam!" 7 | ``` 8 | 9 | They can span multiple lines. 10 | 11 | ```gleam 12 | "Hello 13 | Gleam!" 14 | ``` 15 | 16 | Under the hood Strings are [UTF-8](https://en.wikipedia.org/wiki/UTF-8) encoded binaries 17 | and can contain any valid unicode. 18 | 19 | ```gleam 20 | "👩‍💻 こんにちは Gleam 💫" 21 | ``` 22 | 23 | ## Concatenation 24 | 25 | The concatenation operator can be used to join strings together. 26 | 27 | ```gleam 28 | let x = "Joe" 29 | "Hello, " <> x <> "!" 30 | // "Hello, Joe!" 31 | ``` 32 | 33 | ## Escape Sequences 34 | 35 | Gleam supports common string escape sequences. Here's all of them: 36 | 37 | | Sequence | Result | 38 | | -------- | --------------- | 39 | | `\n` | Newline | 40 | | `\r` | Carriage Return | 41 | | `\t` | Tab | 42 | | `\"` | Double Quote | 43 | | `\\` | Backslash | 44 | 45 | For example to include a double quote (`"`) character in a string literal it 46 | must be escaped by placing a backslash (`\`) character before it. 47 | 48 | ```gleam 49 | "Here is a double quote -> \" <-" 50 | ``` 51 | 52 | Similarly all backslash characters must be escaped: 53 | 54 | ```gleam 55 | // A Windows filepath C:\Users\Gleam 56 | "C:\\Users\\Gleam" 57 | 58 | // A Decorative border /\/\/\/\ 59 | "/\\/\\/\\/\\" 60 | ``` 61 | 62 | ## Stdlib references 63 | 64 | - [gleam/string](https://hexdocs.pm/gleam_stdlib/gleam/string.html) 65 | - [gleam/string_builder](https://hexdocs.pm/gleam_stdlib/gleam/string_builder.html) 66 | -------------------------------------------------------------------------------- /book-src/tour/todo-and-panic.md: -------------------------------------------------------------------------------- 1 | # Todo & Panic 2 | 3 | Gleam's `todo` and `panic` keywords are used to indicate that some code is not 4 | yet finished, or that a program has encountered an unrecoverable error and 5 | should crash. 6 | 7 | `todo` can be useful when designing a module, type checking functions and types 8 | but leaving the implementation of the functions until later. 9 | 10 | ```gleam 11 | fn favourite_number() -> Int { 12 | // The type annotations says this returns an Int, but we don't need 13 | // to implement it yet. 14 | todo 15 | } 16 | 17 | pub fn main() { 18 | favourite_number() * 2 19 | } 20 | ``` 21 | 22 | When this code is built Gleam will type check and compile the code to ensure 23 | it is valid, and the `todo` or `panic` will be replaced with code that crashes 24 | the program if that function is run. 25 | 26 | A message can be given as a form of documentation. The message will be printed 27 | in the error message when the code is run. 28 | 29 | ```gleam 30 | fn favourite_number() -> Int { 31 | todo as "We're going to decide which number is best tomorrow" 32 | } 33 | 34 | fn unreachable_function() -> Int { 35 | panic as "this function should never be called" 36 | } 37 | ``` 38 | 39 | When the compiler finds a `todo` it will print a warning, which can be useful 40 | to avoid accidentally forgetting to remove a `todo`. 41 | 42 | The warning also includes the expected type of the expression that needs to 43 | replace the `todo`. This can be a useful way of asking the compiler what type 44 | is needed if you are ever unsure. 45 | 46 | 47 | ```gleam 48 | fn main() { 49 | my_complicated_function( 50 | // What type does this function take again...? 51 | todo 52 | ) 53 | } 54 | ``` 55 | -------------------------------------------------------------------------------- /book-src/tour/result.md: -------------------------------------------------------------------------------- 1 | # `Result(value, error)` 2 | 3 | ```gleam 4 | pub type Result(value, reason) { 5 | Ok(value) 6 | Error(reason) 7 | } 8 | ``` 9 | 10 | Gleam doesn't have exceptions or `null` to represent errors in our programs, 11 | instead we have the `Result` type. If a function call fails, wrap the returned 12 | value in a `Result`, either `Ok` if the function was successful, or `Error` 13 | if it failed. 14 | 15 | ```gleam 16 | pub fn lookup(name, phone_book) { 17 | // ... we found a phone number in the phone book for the given name here 18 | Ok(phone_number) 19 | } 20 | ``` 21 | 22 | The `Error` type needs to be given a reason for the failure in order to 23 | return, like so: 24 | 25 | ```gleam 26 | pub type MyDatabaseError { 27 | InvalidQuery 28 | NetworkTimeout 29 | } 30 | 31 | pub fn insert(db_row) { 32 | // ... something went wrong connecting to a database here 33 | Error(NetworkTimeout) 34 | } 35 | ``` 36 | 37 | In cases where we don't care about the specific error enough to want to create 38 | a custom error type, or when the cause of the error is obvious without further 39 | detail, the `Nil` type can be used as the `Error` reason. 40 | 41 | ```gleam 42 | pub fn lookup(name, phone_book) { 43 | // ... That name wasn't found in the phone book 44 | Error(Nil) 45 | } 46 | ``` 47 | 48 | When we have a `Result` type returned to us from a function we can pattern 49 | match on it using `case` to determine whether we have an `Ok` result or 50 | an `Error` result. 51 | 52 | The standard library [gleam/result](https://hexdocs.pm/gleam_stdlib/gleam/result.html) module contains helpful functions for 53 | working with the `Result` type, make good use of them! 54 | 55 | ## Stdlib references 56 | 57 | - [gleam/result](https://hexdocs.pm/gleam_stdlib/gleam/result.html) 58 | -------------------------------------------------------------------------------- /book/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 7 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /writing-gleam/using-the-project.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using the project 3 | subtitle: Have some fun with Gleam code! 4 | layout: page 5 | redirect_from: 6 | - "/writing-gleam/running-the-project/index.html" 7 | --- 8 | 9 | ## Run the program 10 | 11 | Your Gleam program can be run with the `gleam run` terminal command. 12 | 13 | It will run the `main` function in the module with the same name as your 14 | project. This function is generated for you by default for new projects. 15 | 16 | 17 | ## Run the tests 18 | 19 | The tests for your project can be run by the `gleam test` command. 20 | 21 | This command will run the `main` function in the module with the same name as 22 | your project but with `_test` added to the end. For example, if your project is 23 | called `satsuma` it will run `satsuma_test.main`. 24 | 25 | You may want to use a test framework such as [gleeunit][gleeunit] to help you 26 | write and run your test code. 27 | 28 | [gleeunit]: https://github.com/lpil/gleeunit 29 | 30 | 31 | ## Add dependencies 32 | 33 | New dependency packages can be added using the `gleam add` command. 34 | 35 | ```sh 36 | # Add gleam_http as a dependency 37 | gleam add gleam_http 38 | 39 | # Add gleeunit as a dev-dependency 40 | gleam add gleeunit --dev 41 | ``` 42 | 43 | ## Run an Erlang shell 44 | 45 | An interactive Erlang shell can be started using the `gleam shell` command. 46 | 47 | ```sh 48 | gleam shell 49 | # Compiling my_project 50 | # Compiled in 0.53s 51 | # Running Erlang shell 52 | # Erlang/OTP 24 [erts-12.1.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 53 | # 54 | # Eshell V12.1.5 (abort with ^G) 55 | # 1> 56 | ``` 57 | 58 | Here we can try out our functions by typing them in: 59 | 60 | ```sh 61 | 1> my_fantastic_library:main(). 62 | # <<"Hello from my_fantastic_library">> 63 | ``` 64 | 65 | It's important to remember that this is an Erlang shell rather than a Gleam 66 | shell, so Erlang syntax must be used. Don't forget to put a `.` at the end of 67 | the expression otherwise the shell won't do anything. 68 | -------------------------------------------------------------------------------- /book-src/tour/assert.md: -------------------------------------------------------------------------------- 1 | # Assert 2 | 3 | Some times we have a function that can technically fail, but in practice we 4 | don't expect it to happen. For example our program may start by opening a 5 | file, if we know that the file is always going to be possible to open, then we 6 | don't want to complicate our program with handling an error that should never 7 | happen. 8 | 9 | Other times we have errors that may occur, but we don't have any way of 10 | realistically handling them within our program. For example if we have a web 11 | application that talks to a database when handling each HTTP request and that 12 | database stops responding, then we have a fatal error that cannot be recovered 13 | from. We could detect the error in our code, but what do we do then? We *need* 14 | the database to handle the request. 15 | 16 | Lastly we may think errors are possible, but we are writing a quick script or 17 | prototype application, so we want to only spend time on the success path for 18 | now. 19 | 20 | For these situations Gleam provides `assert`, a keyword that causes the 21 | program to crash if a pattern does not match. 22 | 23 | ```gleam 24 | let assert Ok(i) = parse_int("123") 25 | i // => 123 26 | ``` 27 | 28 | Here the `assert` keyword has been used to say "this function must return an 29 | `Ok` value" and we haven't had to write any error handling. The inner value 30 | is assigned the variable `i` and the program continues. 31 | 32 | ```gleam 33 | let assert Ok(i) = parse_int("not an int") 34 | ``` 35 | 36 | In this case the `parse_int` function returns an error, so the `Ok(i)` 37 | pattern doesn't match and so the program crashes. 38 | 39 | ## Surviving crashes 40 | 41 | Being fault tolerant and surviving crashes is a key part of Erlang's error 42 | handling strategy, and as an Erlang based language Gleam can also take 43 | advantage of this. To find out more about Erlang fault tolerance see the 44 | [Gleam OTP project][1] and the [Learn You Some Erlang chapter on 45 | supervisors][2]. 46 | 47 | [1]: https://github.com/gleam-lang/otp 48 | [2]: https://learnyousomeerlang.com/supervisors 49 | -------------------------------------------------------------------------------- /book/tomorrow-night.css: -------------------------------------------------------------------------------- 1 | /* Tomorrow Night Theme */ 2 | /* https://github.com/jmblog/color-themes-for-highlightjs */ 3 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */ 4 | /* https://github.com/jmblog/color-themes-for-highlightjs */ 5 | 6 | /* Tomorrow Comment */ 7 | .hljs-comment { 8 | color: #969896; 9 | } 10 | 11 | /* Tomorrow Red */ 12 | .hljs-variable, 13 | .hljs-attribute, 14 | .hljs-tag, 15 | .hljs-regexp, 16 | .ruby .hljs-constant, 17 | .xml .hljs-tag .hljs-title, 18 | .xml .hljs-pi, 19 | .xml .hljs-doctype, 20 | .html .hljs-doctype, 21 | .css .hljs-id, 22 | .css .hljs-class, 23 | .css .hljs-pseudo { 24 | color: #cc6666; 25 | } 26 | 27 | /* Tomorrow Orange */ 28 | .hljs-number, 29 | .hljs-preprocessor, 30 | .hljs-pragma, 31 | .hljs-built_in, 32 | .hljs-literal, 33 | .hljs-params, 34 | .hljs-constant { 35 | color: #de935f; 36 | } 37 | 38 | /* Tomorrow Yellow */ 39 | .ruby .hljs-class .hljs-title, 40 | .css .hljs-rule .hljs-attribute { 41 | color: #f0c674; 42 | } 43 | 44 | /* Tomorrow Green */ 45 | .hljs-string, 46 | .hljs-value, 47 | .hljs-inheritance, 48 | .hljs-header, 49 | .hljs-name, 50 | .ruby .hljs-symbol, 51 | .xml .hljs-cdata { 52 | color: #b5bd68; 53 | } 54 | 55 | /* Tomorrow Aqua */ 56 | .hljs-title, 57 | .css .hljs-hexcolor { 58 | color: #8abeb7; 59 | } 60 | 61 | /* Tomorrow Blue */ 62 | .hljs-function, 63 | .python .hljs-decorator, 64 | .python .hljs-title, 65 | .ruby .hljs-function .hljs-title, 66 | .ruby .hljs-title .hljs-keyword, 67 | .perl .hljs-sub, 68 | .javascript .hljs-title, 69 | .coffeescript .hljs-title { 70 | color: #81a2be; 71 | } 72 | 73 | /* Tomorrow Purple */ 74 | .hljs-keyword, 75 | .javascript .hljs-function { 76 | color: #b294bb; 77 | } 78 | 79 | .hljs { 80 | display: block; 81 | overflow-x: auto; 82 | background: #1d1f21; 83 | color: #c5c8c6; 84 | } 85 | 86 | .coffeescript .javascript, 87 | .javascript .xml, 88 | .tex .hljs-formula, 89 | .xml .javascript, 90 | .xml .vbscript, 91 | .xml .css, 92 | .xml .hljs-cdata { 93 | opacity: 0.5; 94 | } 95 | 96 | .hljs-addition { 97 | color: #718c00; 98 | } 99 | 100 | .hljs-deletion { 101 | color: #c82829; 102 | } 103 | -------------------------------------------------------------------------------- /book-src/tour/use.md: -------------------------------------------------------------------------------- 1 | # Use expressions 2 | 3 | Gleam lacks exceptions, macros, type classes, early returns, and a variety of 4 | other features, instead going all-in with just first-class-functions and pattern 5 | matching. 6 | 7 | This makes Gleam code easier to understand, but it can sometimes result in 8 | excessive indentation. 9 | 10 | ```gleam 11 | pub fn main() { 12 | logger.record_timing(fn() { 13 | database.connect(fn(db) { 14 | file.open("file.txt", fn(f) { 15 | // Do something with `f` here... 16 | }) 17 | }) 18 | }) 19 | } 20 | ``` 21 | 22 | This code doesn't look super pretty. Some folks might call this "callback hell". 23 | 24 | Gleam's `use` expression helps out here by enabling us to write code like this 25 | in an unindented style. The above code could be re-written using it like so: 26 | 27 | ```gleam 28 | pub fn main() { 29 | use <- logger.record_timing 30 | use db <- database.connect 31 | use f <- file.open("file.txt") 32 | // Do something with `f` here... 33 | } 34 | ``` 35 | 36 | The higher order function being called goes on the right hand side of the `<-` 37 | operator. It must take a callback function as its final argument. 38 | 39 | The argument names for the callback function go on the left hand side of the 40 | `<-` operator. The function can take any number of arguments, including zero. 41 | 42 | All the following code in the `{}` block becomes the body of the callback 43 | function. 44 | 45 | This is a very capable and useful feature, but excessive application of `use` 46 | may result in code that is unclear otherwise, especially to beginners. Often 47 | using the regular function call syntax will result in more approachable code! 48 | 49 | ## Syntactic sugar 50 | 51 | The `use` expression is syntactic sugar for a regular function call and an 52 | anonymous function. 53 | 54 | This code: 55 | 56 | ```gleam 57 | use a, b <- my_function 58 | next(a) 59 | next(b) 60 | ``` 61 | 62 | Expands into this code: 63 | 64 | ```gleam 65 | my_function(fn(a, b) { 66 | next(a) 67 | next(b) 68 | }) 69 | ``` 70 | 71 | To ensure that your `use` code works and is as understandable as possible, the 72 | right-hand-side ideally should be a function call rather than a pipeline, block, 73 | or other expression, which may be less clear. 74 | 75 | ```gleam 76 | use x <- result.try( 77 | current_user 78 | |> get_profile 79 | |> result.map_error(ProfileError) 80 | ) 81 | ``` 82 | -------------------------------------------------------------------------------- /styles/highlighting.css: -------------------------------------------------------------------------------- 1 | .highlight .c { color: #999988; font-style: italic } 2 | .highlight .k { font-weight: bold } 3 | .highlight .o { font-weight: bold } 4 | .highlight .cm { color: #999988; font-style: italic } 5 | .highlight .cp { color: #999999; font-weight: bold } 6 | .highlight .c1 { color: #999988; font-style: italic } 7 | .highlight .cs { color: #999999; font-weight: bold; font-style: italic } 8 | .highlight .gd { color: #000000; background-color: #ffdddd } 9 | .highlight .gd .x { color: #000000; background-color: #ffaaaa } 10 | .highlight .ge { font-style: italic } 11 | .highlight .gr { color: #aa0000 } 12 | .highlight .gh { color: #999999 } 13 | .highlight .gi { color: #000000; background-color: #ddffdd } 14 | .highlight .gi .x { color: #000000; background-color: #aaffaa } 15 | .highlight .go { color: #888888 } 16 | .highlight .gp { color: #555555 } 17 | .highlight .gs { font-weight: bold } 18 | .highlight .gu { color: #aaaaaa } 19 | .highlight .gt { color: #aa0000 } 20 | .highlight .kc { font-weight: bold } 21 | .highlight .kd { font-weight: bold } 22 | .highlight .kp { font-weight: bold } 23 | .highlight .kr { font-weight: bold } 24 | .highlight .kt { color: #445588; font-weight: bold } 25 | .highlight .m { color: #009999 } 26 | .highlight .s { color: #d14 } 27 | .highlight .na { color: #008080 } 28 | .highlight .nb { color: #0086B3 } 29 | .highlight .nc { color: #445588; font-weight: bold } 30 | .highlight .no { color: #008080 } 31 | .highlight .ni { color: #800080 } 32 | .highlight .ne { color: #990000; font-weight: bold } 33 | .highlight .nf { color: #990000; font-weight: bold } 34 | .highlight .nn { color: #555555 } 35 | .highlight .nt { color: #000080 } 36 | .highlight .nv { color: #008080 } 37 | .highlight .ow { font-weight: bold } 38 | .highlight .w { color: #bbbbbb } 39 | .highlight .mf { color: #009999 } 40 | .highlight .mh { color: #009999 } 41 | .highlight .mi { color: #009999 } 42 | .highlight .mo { color: #009999 } 43 | .highlight .sb { color: #d14 } 44 | .highlight .sc { color: #d14 } 45 | .highlight .sd { color: #d14 } 46 | .highlight .s2 { color: #d14 } 47 | .highlight .se { color: #d14 } 48 | .highlight .sh { color: #d14 } 49 | .highlight .si { color: #d14 } 50 | .highlight .sx { color: #d14 } 51 | .highlight .sr { color: #009926 } 52 | .highlight .s1 { color: #d14 } 53 | .highlight .ss { color: #990073 } 54 | .highlight .bp { color: #999999 } 55 | .highlight .vc { color: #008080 } 56 | .highlight .vg { color: #008080 } 57 | .highlight .vi { color: #008080 } 58 | .highlight .il { color: #009999 } 59 | -------------------------------------------------------------------------------- /writing-gleam/documenting-the-project.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Documenting the project 3 | subtitle: Self-documenting is cool but documented is better 4 | layout: page 5 | --- 6 | 7 | If our project is a library it is important that it is well documented so that 8 | people understand how to use the code. 9 | 10 | ## Modules and functions 11 | 12 | To document modules and functions Gleam supports two special comments, `///` 13 | which is for documenting types and functions, and `////` which is for 14 | documenting the module as a whole. 15 | 16 | ```gleam 17 | //// This module contains some useful functions for working 18 | //// with numbers. 19 | //// 20 | //// For more information see [this website](https://example.com). 21 | 22 | 23 | import gleam/result 24 | 25 | /// A type for representing numbers 26 | pub type Number { 27 | /// This constructor is used when the number is an Int 28 | I(Int) 29 | 30 | /// This constructor is used when the number is an Float 31 | F(Float) 32 | } 33 | 34 | /// Returns the next number 35 | /// 36 | /// # Examples 37 | /// 38 | /// > successor(1) 39 | /// 2 40 | /// 41 | pub fn successor(i: Int) -> Int { 42 | i + 1 43 | } 44 | 45 | /// Returns a number held by an Ok record, returning a default if the 46 | /// Result is an Error record. 47 | /// 48 | /// # Examples 49 | /// 50 | /// > from_result(Ok(1)) 51 | /// 1 52 | /// 53 | /// > from_result(Error(Nil)) 54 | /// 0 55 | /// 56 | pub fn from_result(result: Result(Int, e)) -> Int { 57 | result.unwrap(result, 0) 58 | } 59 | ``` 60 | 61 | Once documentation comments have been added Gleam can generate HTML 62 | documentation for the project. 63 | 64 | ## Additional documentation pages 65 | 66 | To add additional pages to the documentation for the project that aren't 67 | automatically generated, simply define them in Markdown and add them to 68 | `gleam.toml` as follows: 69 | 70 | ```toml 71 | name = "my_awesome_gleam_app" 72 | 73 | [documentation] 74 | pages = [ 75 | { title = "Hello", path = "hello.html", source = "docs/hello_world.md" }, 76 | { title = "Testing", path = "testing.html", source = "docs/testing.md" }, 77 | ] 78 | 79 | ``` 80 | 81 | Links will automatically be generated for these additional pages and the 82 | Markdown will be converted into HTML documentation. 83 | 84 | Your project's `README.md` file will automatically be used to generate the 85 | default page for the documentation. 86 | 87 | ## Building documentation 88 | 89 | The documentation can be built locally using this command, which renders the 90 | documentation to the build directory. 91 | 92 | ```sh 93 | gleam docs build 94 | ``` 95 | -------------------------------------------------------------------------------- /_layouts/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% capture title %}{% if page.title %}{{ page.title | strip }} – {% endif %}Gleam{% endcapture %} 6 | {% capture default_description %}The Gleam programming language{% endcapture %} 7 | {% capture description %}{% if page.description %}{{ page.description | strip }}{% else %}{{ default_description }}{% 8 | endif %}{% endcapture %} 9 | 10 | 11 | 12 | {% feed_meta %} 13 | 14 | {{ title }} 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {{ content }} 36 | 37 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /book-src/tour/external-functions.md: -------------------------------------------------------------------------------- 1 | # External function 2 | 3 | Gleam is just one of many languages on the Erlang virtual machine and JavaScript 4 | runtimes. At times we may want to use functions from these other languages in 5 | our Gleam programs. To enable this Gleam allows the importing of _external 6 | functions_, which may be written in any language on the same runtime. 7 | 8 | External functions are typically written in a different language with a 9 | different type system, so the compiler is unable to determine the type of the 10 | function and instead the programmer must inform the compiler the type. 11 | 12 | Gleam trusts that the type given is correct so an inaccurate type annotation 13 | can result in unexpected behaviour and crashes at runtime. Be careful! 14 | 15 | 16 | ## Erlang external functions 17 | 18 | The Erlang `rand` module has a function named `uniform` that takes no 19 | arguments and returns a `Float`. 20 | 21 | The Elixir module `IO` has a function named `inspect` that takes any value, 22 | prints it, and returns the same value. 23 | 24 | If we want to import these functions and use them in our program we would do 25 | so like this: 26 | 27 | ```gleam 28 | @external(erlang, "rand", "uniform") 29 | pub fn random_float() -> Float 30 | 31 | // Elixir modules start with `Elixir.` 32 | @external(erlang, "Elixir.IO", "inspect") 33 | pub fn inspect(value: a) -> a 34 | ``` 35 | 36 | ## JavaScript external functions 37 | 38 | When importing a JavaScript function the path to the module is given instead of 39 | the module name. 40 | 41 | ```javascript 42 | // In src/my-module.mjs 43 | export function run() { 44 | return 0; 45 | } 46 | ``` 47 | 48 | ```gleam 49 | // In src/my_program.gleam 50 | @external(javascript, "./my-module.js" "run") 51 | pub fn run() -> Int 52 | ``` 53 | 54 | Gleam uses the JavaScript import syntax, so any module imported must use the 55 | esmodule export syntax, and if you are using the NodeJS runtime the file 56 | extension must be `.mjs`. 57 | 58 | ## Multi-target external functions 59 | 60 | An external implementation can be provided for multiple targets by given the 61 | `@external` attribute multiple times. 62 | 63 | ```gleam 64 | @external(erlang, "rand" "uniform") 65 | @external(javascript, "./my-module.js" "random") 66 | pub fn random() -> Float 67 | ``` 68 | 69 | The appropriate implementation will be chosen based on the target the program is 70 | being compiled for. 71 | 72 | ## Gleam fallbacks 73 | 74 | A Gleam implementation can be given as a fallback for when no external 75 | implementation has been specified for the current target. 76 | 77 | ```gleam 78 | @external(erlang, "lists" "reverse") 79 | pub fn reverse(items: List(a)) -> List(a) { 80 | do_reverse(items, []) 81 | } 82 | 83 | fn do_reverse(items: List(a), accumulator: List(a)) -> List(a) { 84 | case items { 85 | [] -> accumulator 86 | [first, ..rest] -> do_reverse(rest, [first, ..accumulator]) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /javascript/highlightjs-gleam.js: -------------------------------------------------------------------------------- 1 | hljs.registerLanguage("gleam", function (hljs) { 2 | const KEYWORDS = 3 | "as assert case const fn if import let panic use opaque pub todo type"; 4 | const STRING = { 5 | className: "string", 6 | variants: [{ begin: /"/, end: /"/ }], 7 | contains: [hljs.BACKSLASH_ESCAPE], 8 | relevance: 0, 9 | }; 10 | const NAME = { 11 | className: "variable", 12 | begin: "\\b[a-z][a-z0-9_]*\\b", 13 | relevance: 0, 14 | }; 15 | const DISCARD_NAME = { 16 | className: "comment", 17 | begin: "\\b_[a-z][a-z0-9_]*\\b", 18 | relevance: 0, 19 | }; 20 | const NUMBER = { 21 | className: "number", 22 | variants: [ 23 | { 24 | // binary 25 | begin: "\\b0[bB](?:_?[01]+)+", 26 | }, 27 | { 28 | // octal 29 | begin: "\\b0[oO](?:_?[0-7]+)+", 30 | }, 31 | { 32 | // hex 33 | begin: "\\b0[xX](?:_?[0-9a-fA-F]+)+", 34 | }, 35 | { 36 | // dec, float 37 | begin: "\\b\\d(?:_?\\d+)*(?:\\.(?:\\d(?:_?\\d+)*)*)?", 38 | }, 39 | ], 40 | relevance: 0, 41 | }; 42 | 43 | return { 44 | name: "Gleam", 45 | aliases: ["gleam"], 46 | contains: [ 47 | hljs.C_LINE_COMMENT_MODE, 48 | STRING, 49 | { 50 | // bit string 51 | begin: "<<", 52 | end: ">>", 53 | contains: [ 54 | { 55 | className: "keyword", 56 | beginKeywords: 57 | "binary bits bytes int float bit_string bit_array bits utf8 utf16 " + 58 | "utf32 utf8_codepoint utf16_codepoint utf32_codepoint signed " + 59 | "unsigned big little native unit size", 60 | }, 61 | KEYWORDS, 62 | STRING, 63 | NAME, 64 | DISCARD_NAME, 65 | NUMBER, 66 | ], 67 | relevance: 10, 68 | }, 69 | { 70 | className: "function", 71 | beginKeywords: "fn", 72 | end: "\\(", 73 | excludeEnd: true, 74 | contains: [ 75 | { 76 | className: "title", 77 | begin: "[a-z][a-z0-9_]*\\w*", 78 | relevance: 0, 79 | }, 80 | ], 81 | }, 82 | { 83 | className: "attribute", 84 | begin: "@", 85 | end: "\\(", 86 | excludeEnd: true, 87 | }, 88 | { 89 | className: "keyword", 90 | beginKeywords: KEYWORDS, 91 | }, 92 | { 93 | // Type names and constructors 94 | className: "title", 95 | begin: "\\b[A-Z][A-Za-z0-9]*\\b", 96 | relevance: 0, 97 | }, 98 | { 99 | className: "operator", 100 | begin: "[+\\-*/%!=<>&|.]+", 101 | relevance: 0, 102 | }, 103 | NAME, 104 | DISCARD_NAME, 105 | NUMBER, 106 | ], 107 | }; 108 | }); 109 | hljs.initHighlightingOnLoad(); 110 | -------------------------------------------------------------------------------- /book/javascript/highlightjs-gleam.js: -------------------------------------------------------------------------------- 1 | hljs.registerLanguage("gleam", function (hljs) { 2 | const KEYWORDS = 3 | "as assert case const fn if import let panic use opaque pub todo type"; 4 | const STRING = { 5 | className: "string", 6 | variants: [{ begin: /"/, end: /"/ }], 7 | contains: [hljs.BACKSLASH_ESCAPE], 8 | relevance: 0, 9 | }; 10 | const NAME = { 11 | className: "variable", 12 | begin: "\\b[a-z][a-z0-9_]*\\b", 13 | relevance: 0, 14 | }; 15 | const DISCARD_NAME = { 16 | className: "comment", 17 | begin: "\\b_[a-z][a-z0-9_]*\\b", 18 | relevance: 0, 19 | }; 20 | const NUMBER = { 21 | className: "number", 22 | variants: [ 23 | { 24 | // binary 25 | begin: "\\b0[bB](?:_?[01]+)+", 26 | }, 27 | { 28 | // octal 29 | begin: "\\b0[oO](?:_?[0-7]+)+", 30 | }, 31 | { 32 | // hex 33 | begin: "\\b0[xX](?:_?[0-9a-fA-F]+)+", 34 | }, 35 | { 36 | // dec, float 37 | begin: "\\b\\d(?:_?\\d+)*(?:\\.(?:\\d(?:_?\\d+)*)*)?", 38 | }, 39 | ], 40 | relevance: 0, 41 | }; 42 | 43 | return { 44 | name: "Gleam", 45 | aliases: ["gleam"], 46 | contains: [ 47 | hljs.C_LINE_COMMENT_MODE, 48 | STRING, 49 | { 50 | // bit string 51 | begin: "<<", 52 | end: ">>", 53 | contains: [ 54 | { 55 | className: "keyword", 56 | beginKeywords: 57 | "binary bits bytes int float bit_string bit_array bits utf8 utf16 " + 58 | "utf32 utf8_codepoint utf16_codepoint utf32_codepoint signed " + 59 | "unsigned big little native unit size", 60 | }, 61 | KEYWORDS, 62 | STRING, 63 | NAME, 64 | DISCARD_NAME, 65 | NUMBER, 66 | ], 67 | relevance: 10, 68 | }, 69 | { 70 | className: "function", 71 | beginKeywords: "fn", 72 | end: "\\(", 73 | excludeEnd: true, 74 | contains: [ 75 | { 76 | className: "title", 77 | begin: "[a-z][a-z0-9_]*\\w*", 78 | relevance: 0, 79 | }, 80 | ], 81 | }, 82 | { 83 | className: "attribute", 84 | begin: "@", 85 | end: "\\(", 86 | excludeEnd: true, 87 | }, 88 | { 89 | className: "keyword", 90 | beginKeywords: KEYWORDS, 91 | }, 92 | { 93 | // Type names and constructors 94 | className: "title", 95 | begin: "\\b[A-Z][A-Za-z0-9]*\\b", 96 | relevance: 0, 97 | }, 98 | { 99 | className: "operator", 100 | begin: "[+\\-*/%!=<>&|.]+", 101 | relevance: 0, 102 | }, 103 | NAME, 104 | DISCARD_NAME, 105 | NUMBER, 106 | ], 107 | }; 108 | }); 109 | hljs.initHighlightingOnLoad(); 110 | -------------------------------------------------------------------------------- /deployment/fly.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Deploying on Fly.io 3 | subtitle: Run Gleam all over the world. No ops required. 4 | layout: page 5 | redirect_from: 6 | - "/deploying-gleam-on-fly/index.html" 7 | --- 8 | 9 | [Fly.io](https://fly.io) is a convenient and easy to use deployment platform 10 | with a generous [free allowance](https://fly.io/docs/about/pricing/). They're 11 | also a sponsor of the Gleam project, thank you Fly! 12 | 13 | ## Prepare an application 14 | 15 | We will need a Gleam backend web application to deploy in this guide, so first 16 | we will make one. If you already have an application skip to the next section. 17 | 18 | Create a new Gleam project and add the required dependencies. 19 | 20 | ```sh 21 | gleam new my_web_app 22 | cd my_web_app 23 | gleam add mist gleam_http gleam_erlang 24 | ``` 25 | 26 | Open up `src/my_web_app.gleam` and replace the contents with this code that 27 | defines a micro web application. 28 | 29 | ```gleam 30 | import mist 31 | import gleam/erlang/process 32 | import gleam/bit_builder 33 | import gleam/http/response.{Response} 34 | 35 | pub fn main() { 36 | let assert Ok(_) = mist.run_service(8080, web_service, max_body_limit: 4_000_000) 37 | process.sleep_forever() 38 | } 39 | 40 | fn web_service(_request) { 41 | let body = bit_builder.from_string("Hello, Joe!") 42 | Response(200, [], body) 43 | } 44 | ``` 45 | 46 | Now we have a web application that listens on port 8080 and can be started with 47 | `gleam run`. 48 | 49 | 50 | ## Add a Dockerfile 51 | 52 | We can use Fly's support for containers to build the application and prepare it 53 | for deployment. 54 | 55 | Add a file named `Dockerfile` with these contents: 56 | 57 | ```dockerfile 58 | FROM ghcr.io/gleam-lang/gleam:v0.22.0-erlang-alpine 59 | 60 | # Add project code 61 | COPY . /build/ 62 | 63 | # Compile the project 64 | RUN cd /build \ 65 | && gleam export erlang-shipment \ 66 | && mv build/erlang-shipment /app \ 67 | && rm -r /build 68 | 69 | # Run the server 70 | WORKDIR /app 71 | ENTRYPOINT ["/app/entrypoint.sh"] 72 | CMD ["run"] 73 | ``` 74 | 75 | 76 | ## Set up the Fly.io CLI 77 | 78 | Follow the instructions [here](https://fly.io/docs/getting-started/installing-flyctl/) 79 | to install Flyctl, the command-line interface for the Fly.io platform. 80 | 81 | Once installed use the CLI to sign up (or log in if you already have a Fly.io 82 | account). 83 | 84 | ```sh 85 | fly auth signup 86 | # OR 87 | fly auth login 88 | ``` 89 | 90 | Fly's free allowance is enough to run the Gleam application but new accounts 91 | need a payment card to be added, to prevent people from abusing Fly's free 92 | service. 93 | 94 | 95 | ## Deploy the application 96 | 97 | From within the project use the Fly CLI to create and run your application on 98 | their platform. 99 | 100 | ``` 101 | flyctl launch 102 | ``` 103 | 104 | The CLI will ask you a series of questions: 105 | 106 | - What should the application should be named. 107 | - What Fly organisation should the application belong to. 108 | - What region the application should be deployed to. 109 | - Whether you would like a PostgreSQL database to go with the application. 110 | 111 | Once you have answered these it will build the application using the docker 112 | file. Once deployed you can open it in a web browser by running `flyctl open`. 113 | 114 | To deploy future versions of the application run `flyctl deploy` after saving 115 | any changes to the source code. 116 | -------------------------------------------------------------------------------- /_posts/2019-04-15-hello-gleam.md: -------------------------------------------------------------------------------- 1 | --- 2 | author: Louis Pilfold 3 | title: Hello, Gleam! 4 | subtitle: There's a new friendly language in town 5 | tags: 6 | - Release 7 | --- 8 | 9 | Gleam has reached v0.1! Happy first release-day Gleam! 10 | 11 | ## What's Gleam? 12 | 13 | Gleam is a functional programming language for writing maintainable and 14 | scalable concurrent systems. If you enjoy the actor based concurrency model 15 | and durable runtime of Erlang and Elixir, and the sound type system of 16 | OCaml, ReasonML, or Elm then I hope you will enjoy Gleam. 17 | 18 | It looks something like this: 19 | 20 | ```gleam 21 | pub enum User = 22 | | LoggedIn(String) 23 | | Guest 24 | 25 | pub fn check(user) { 26 | case user { 27 | | LoggedIn("Al") -> "Hi Al!" 28 | | LoggedIn(name) -> "Welcome back!" 29 | | Guest -> "Hello! Please log in" 30 | } 31 | } 32 | ``` 33 | 34 | 35 | ## What is it like? 36 | 37 | Gleam supports generics, algebraic data types, modules as a first-class 38 | data-type, and row typed maps to enable flexible and permissive function 39 | interfaces. 40 | 41 | The type system aims to provide compile time safety and easy refactoring 42 | without burdening the programmer with verbose annotations or boilerplate. 43 | Types are completely inferred, though future releases will allow programmers 44 | to add optional type annotations if desired. 45 | 46 | Gleam compiles to Erlang and runs on the battle proven 47 | Erlang virtual machine, making it suitable for writing massively concurrent 48 | systems that are fault tolerant and relatively easy to reason about. 49 | 50 | The Erlang ecosystem is full of great libraries, languages, and applications, 51 | so Gleam makes it straightforward to import functions written in other BEAM 52 | languages and use them in your program. Gleam also aims to be a good citizen, 53 | so any library or application written in Gleam can be used by any other BEAM 54 | language without fuss or performance overhead. 55 | 56 | 57 | ## What is it for? 58 | 59 | Thanks to its Erlang heritage Gleam excels at low latency, high concurrency, 60 | networked applications such as web application backends, databases, or message 61 | brokers. Erlang and Elixir are also highly suited for embedded applications, 62 | so perhaps Gleam will be useful there too. 63 | 64 | Gleam's type system gives it an edge in rapidly evolving problem spaces as it 65 | helps the programmer refactor quickly and safely by supplying precise and 66 | useful error messages until the change is fully applied. 67 | 68 | 69 | ## What is it not for? 70 | 71 | It doesn't run in a browser or on a mobile device, and doesn't have a graphics 72 | library, so it's not suited for GUI applications. It doesn't have the 73 | near-instant boot time and easy distribution of a native binary so it's not 74 | the best for command line applications. It isn't fast at crunching numbers so 75 | you won't use it for statistical analysis. 76 | 77 | 78 | ## Is it good? 79 | 80 | Yes, I think so. But then it would be silly if I say otherwise, wouldn't it? 81 | 82 | Perhaps don't put it into production just yet, but it's usable enough for pet 83 | projects and toy applications. 🚀 84 | 85 | 86 | ## Sounds interesting. What now? 87 | 88 | Check out [the website](http://gleam.run) for more information, and check out 89 | the project on [GitHub](https://github.com/lpil/gleam). 90 | 91 | If you've any questions or want to get involved join the IRC channel 92 | `#gleam-lang` on Freenode. 93 | 94 | Thanks for reading! :) 95 | -------------------------------------------------------------------------------- /book-src/tour/modules.md: -------------------------------------------------------------------------------- 1 | # Modules 2 | 3 | Gleam programs are made up of bundles of functions and types called modules. 4 | Each module has its own namespace and can export types and values to be used 5 | by other modules in the program. 6 | 7 | ```gleam 8 | // inside module src/nasa/rocket_ship.gleam 9 | 10 | fn count_down() { 11 | "3... 2... 1..." 12 | } 13 | 14 | fn blast_off() { 15 | "BOOM!" 16 | } 17 | 18 | pub fn launch() { 19 | [ 20 | count_down(), 21 | blast_off(), 22 | ] 23 | } 24 | ``` 25 | 26 | Here we can see a module named `nasa/rocket_ship`, the name determined by the 27 | filename `src/nasa/rocket_ship.gleam`. Typically all the modules for one 28 | project would live within a directory with the name of the project, such as 29 | `nasa` in this example. 30 | 31 | For the functions `count_down` and `blast_off` we have omitted the `pub` 32 | keyword, so these functions are _private_ module functions. They can only be 33 | called by other functions within the same module. 34 | 35 | 36 | ## Import 37 | 38 | To use functions or types from another module we need to import them using the 39 | `import` keyword. 40 | 41 | ```gleam 42 | // inside module src/nasa/moon_base.gleam 43 | 44 | import nasa/rocket_ship 45 | 46 | pub fn explore_space() { 47 | rocket_ship.launch() 48 | } 49 | ``` 50 | 51 | The statement `import nasa/rocket_ship` creates a new variable with the name 52 | `rocket_ship` and the value of the `rocket_ship` module. 53 | 54 | In the `explore_space` function we call the imported module's public `launch` 55 | function using the `.` operator. If we had attempted to call `count_down` it 56 | would result in a compile time error as this function is private to the 57 | `rocket_ship` module. 58 | 59 | 60 | ## Named import 61 | 62 | It is also possible to give a module a custom name when importing it using the 63 | `as` keyword. 64 | 65 | ```gleam 66 | import unix/cat 67 | import animal/cat as kitty 68 | ``` 69 | 70 | This may be useful to differentiate between multiple modules that would have 71 | the same default name when imported. 72 | 73 | 74 | ## Unqualified import 75 | 76 | Values and types can also be imported in an unqualified fashion. 77 | 78 | ```gleam 79 | import animal/cat.{Cat, stroke} 80 | 81 | pub fn main() { 82 | let kitty = Cat(name: "Nubi") 83 | stroke(kitty) 84 | } 85 | ``` 86 | 87 | This may be useful for values that are used frequently in a module, but 88 | generally qualified imports are preferred as it makes it clearer where the 89 | value is defined. 90 | 91 | 92 | ## The prelude module 93 | 94 | There is one module that is built into the language, the `gleam` prelude 95 | module. By default its types and values are automatically imported into 96 | every module you write, but you can still chose to import it the regular way. 97 | This may be useful if you have created a type or value with the same name as 98 | an item from the prelude. 99 | 100 | ```gleam 101 | import gleam 102 | 103 | /// This definition locally overrides the `Result` type 104 | /// and the `Ok` constructor. 105 | pub type Result { 106 | Ok 107 | } 108 | 109 | /// The original `Result` and `Ok` can still be used 110 | pub fn go() -> gleam.Result(Int) { 111 | gleam.Ok(1) 112 | } 113 | ``` 114 | 115 | The prelude module contains these types: 116 | 117 | - `BitString` 118 | - `Bool` 119 | - `Float` 120 | - `Int` 121 | - `List(element)` 122 | - `Nil` 123 | - `Result(value, error)` 124 | - `String` 125 | - `UtfCodepoint` 126 | 127 | And these values: 128 | 129 | - `Error` 130 | - `False` 131 | - `Nil` 132 | - `Ok` 133 | - `True` 134 | 135 | ## Documentation 136 | 137 | You may add user facing documentation at the head of modules with a module 138 | documentation comment `////` per line. Markdown is supported and this text 139 | will be included with the module's entry in generated HTML documentation. 140 | -------------------------------------------------------------------------------- /_posts/2019-08-07-gleam-v0.3-released.md: -------------------------------------------------------------------------------- 1 | --- 2 | author: Louis Pilfold 3 | title: Gleam v0.3 released! 4 | tags: 5 | - Release 6 | --- 7 | 8 | [Gleam](https://github.com/lpil/gleam) has reached v0.3! Let's take a look at 9 | some of the new features introduced since v0.1. 10 | 11 | ## Module namespaces 12 | 13 | Modules can now be namespaced, allowing use of short, convenient module names 14 | without the risk of collisions with other Gleam or Erlang modules. 15 | 16 | To use a namespace create a directory with the name of your namespace inside 17 | the `src/` directory and put your modules in there. As an example, if I'm 18 | making the hot new food delivery app `snackr` I might choose to have a 19 | directory structure like this: 20 | 21 | ``` 22 | src/ 23 | └── snackr 24 |    ├── customer.gleam 25 |    ├── payment.gleam 26 |    └── food 27 |       ├── falafel.gleam 28 |       ├── pizza.gleam 29 |       └── salad.gleam 30 | ``` 31 | 32 | Once created these modules can be brought into scope using the `import` 33 | statement. 34 | 35 | ```gleam 36 | import snackr/customer 37 | import snackr/food/falafel 38 | 39 | fn eat_lunch(louis) { 40 | customer:eat(louis, falafel:new()) 41 | } 42 | ``` 43 | 44 | It's now possible to use multiple modules with the same name, so for 45 | convenience modules can be given a name when imported. 46 | 47 | ```gleam 48 | import space/rocket as spaceship 49 | import salad/rocket as leafy_green 50 | ``` 51 | 52 | 53 | ## Type annotations 54 | 55 | Gleam's type inference doesn't require any annotations to understand the types 56 | of all your code and provide full type safety, but we might still want to add 57 | some for documentation, or to specify more restrictive types then Gleam might 58 | otherwise infer. 59 | 60 | It looks a little something like this: 61 | 62 | ```gleam 63 | fn is_empty(list: List(a)) -> Bool { 64 | list == [] 65 | } 66 | ``` 67 | 68 | 69 | ## Easier installation 70 | 71 | Precompiled Gleam binaries for Linux and OSX can now be downloaded from the 72 | [Gleam GitHub release page](https://github.com/lpil/gleam/releases) so it's no 73 | longer required to install Rust on your machine and build the compiler from 74 | source. 75 | 76 | Victor Borja has kindly created an `asdf` version manager [plugin for 77 | Gleam](https://github.com/vic/asdf-gleam), so for asdf users installing Gleam 78 | is as easy as `asdf install gleam v0.3.0`. 79 | 80 | For Docker fans the Gleam compiler has been packaged as a Docker image tagged 81 | as [`lpil/gleam`](https://hub.docker.com/r/lpil/gleam). 82 | 83 | 84 | ## Easier project creation 85 | 86 | Previously Gleam projects were created using a rebar3 plugin. This worked but 87 | was one more thing to install, and there was to good way of ensuring that you 88 | have an up to date version of the plugin to match your Gleam installation. 89 | 90 | Now project creation is handled by the `gleam` binary itself, so to get 91 | started with Gleam run `gleam new my_cool_project` and it'll generate all 92 | that's required. 93 | 94 | If you've got `rebar_gleam` installed it's safe to delete it from your 95 | `~/.config/rebar3/rebar.config` as it's no longer used. 96 | 97 | 98 | ## The rest 99 | 100 | In addition to these features there's been a number of other improvements to 101 | the quality of the error messages, the generated code, and a handful of bug 102 | fixes. 😊 103 | 104 | If you want to try out the new version of Gleam head over to the [installation 105 | page](https://gleam.run/getting-started/installing-gleam.html). I'd love to 106 | hear how you find it and get your feedback so Gleam can continue to improve. 107 | 108 | 109 | ## Code BEAM lite Berlin 110 | 111 | On the 11th of October 2019 I'll be speaking at [Code BEAM lite 112 | Berlin](https://codesync.global/conferences/code-beam-lite-berlin-2019/) about 113 | Gleam. If you're attending (or are in Berlin but not attending) say Hello! 114 | -------------------------------------------------------------------------------- /book/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | /* Open Sans is licensed under the Apache License, Version 2.0. See http://www.apache.org/licenses/LICENSE-2.0 */ 2 | /* Source Code Pro is under the Open Font License. See https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL */ 3 | 4 | /* open-sans-300 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 5 | @font-face { 6 | font-family: 'Open Sans'; 7 | font-style: normal; 8 | font-weight: 300; 9 | src: local('Open Sans Light'), local('OpenSans-Light'), 10 | url('open-sans-v17-all-charsets-300.woff2') format('woff2'); 11 | } 12 | 13 | /* open-sans-300italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 14 | @font-face { 15 | font-family: 'Open Sans'; 16 | font-style: italic; 17 | font-weight: 300; 18 | src: local('Open Sans Light Italic'), local('OpenSans-LightItalic'), 19 | url('open-sans-v17-all-charsets-300italic.woff2') format('woff2'); 20 | } 21 | 22 | /* open-sans-regular - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 23 | @font-face { 24 | font-family: 'Open Sans'; 25 | font-style: normal; 26 | font-weight: 400; 27 | src: local('Open Sans Regular'), local('OpenSans-Regular'), 28 | url('open-sans-v17-all-charsets-regular.woff2') format('woff2'); 29 | } 30 | 31 | /* open-sans-italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 32 | @font-face { 33 | font-family: 'Open Sans'; 34 | font-style: italic; 35 | font-weight: 400; 36 | src: local('Open Sans Italic'), local('OpenSans-Italic'), 37 | url('open-sans-v17-all-charsets-italic.woff2') format('woff2'); 38 | } 39 | 40 | /* open-sans-600 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 41 | @font-face { 42 | font-family: 'Open Sans'; 43 | font-style: normal; 44 | font-weight: 600; 45 | src: local('Open Sans SemiBold'), local('OpenSans-SemiBold'), 46 | url('open-sans-v17-all-charsets-600.woff2') format('woff2'); 47 | } 48 | 49 | /* open-sans-600italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 50 | @font-face { 51 | font-family: 'Open Sans'; 52 | font-style: italic; 53 | font-weight: 600; 54 | src: local('Open Sans SemiBold Italic'), local('OpenSans-SemiBoldItalic'), 55 | url('open-sans-v17-all-charsets-600italic.woff2') format('woff2'); 56 | } 57 | 58 | /* open-sans-700 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 59 | @font-face { 60 | font-family: 'Open Sans'; 61 | font-style: normal; 62 | font-weight: 700; 63 | src: local('Open Sans Bold'), local('OpenSans-Bold'), 64 | url('open-sans-v17-all-charsets-700.woff2') format('woff2'); 65 | } 66 | 67 | /* open-sans-700italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 68 | @font-face { 69 | font-family: 'Open Sans'; 70 | font-style: italic; 71 | font-weight: 700; 72 | src: local('Open Sans Bold Italic'), local('OpenSans-BoldItalic'), 73 | url('open-sans-v17-all-charsets-700italic.woff2') format('woff2'); 74 | } 75 | 76 | /* open-sans-800 - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 77 | @font-face { 78 | font-family: 'Open Sans'; 79 | font-style: normal; 80 | font-weight: 800; 81 | src: local('Open Sans ExtraBold'), local('OpenSans-ExtraBold'), 82 | url('open-sans-v17-all-charsets-800.woff2') format('woff2'); 83 | } 84 | 85 | /* open-sans-800italic - latin_vietnamese_latin-ext_greek-ext_greek_cyrillic-ext_cyrillic */ 86 | @font-face { 87 | font-family: 'Open Sans'; 88 | font-style: italic; 89 | font-weight: 800; 90 | src: local('Open Sans ExtraBold Italic'), local('OpenSans-ExtraBoldItalic'), 91 | url('open-sans-v17-all-charsets-800italic.woff2') format('woff2'); 92 | } 93 | 94 | /* source-code-pro-500 - latin_vietnamese_latin-ext_greek_cyrillic-ext_cyrillic */ 95 | @font-face { 96 | font-family: 'Source Code Pro'; 97 | font-style: normal; 98 | font-weight: 500; 99 | src: url('source-code-pro-v11-all-charsets-500.woff2') format('woff2'); 100 | } 101 | -------------------------------------------------------------------------------- /writing-gleam/command-line-reference.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script uses the gleam compiler CLI to generate markdown 4 | # from its own help output. 5 | 6 | set -e 7 | 8 | trim() { 9 | sed 's/^[[:space:]]*//' | sed 's/[[:space:]]*$//' 10 | } 11 | 12 | printerr() { 13 | echo >&2 "$(basename "$0"): $*" 14 | } 15 | 16 | gleam_help="$(gleam help)" 17 | 18 | if ! echo "$gleam_help" | grep -q 'SUBCOMMANDS:'; then 19 | # Updating should be easy, just change the patterns to match the new output. 20 | # Try it, remove this error, and see what the diff looks like! 21 | printerr "Looks like gleam is using a clap version other than 3, please update this script." 22 | exit 1 23 | fi 24 | 25 | printerr "Assuming clap version 3 when parsing help output." 26 | HEADING_PATTERN='^[A-Z][A-Z]*:' 27 | SUBCOMMAND_HEADING='^SUBCOMMANDS:' 28 | USAGE_HEADING='^USAGE:' 29 | OPTIONS_HEADING='^OPTIONS:' 30 | 31 | drop_headings() { 32 | grep -v "$HEADING_PATTERN" 33 | } 34 | 35 | find_description() { 36 | # all lines up to the first heading, except the first line 37 | sed -n "2,/$HEADING_PATTERN/p" | drop_headings | trim 38 | } 39 | 40 | find_subcommands() { 41 | # all lines between the SUBCOMMANDS heading and the next heading 42 | sed -n "/$SUBCOMMAND_HEADING/,/$HEADING_PATTERN/p" | drop_headings | trim | cut -d' ' -f1 43 | } 44 | 45 | find_usage() { 46 | # all lines between the USAGE heading and the next heading 47 | sed -n "/$USAGE_HEADING/,/$HEADING_PATTERN/p" | drop_headings | trim 48 | } 49 | 50 | find_options() { 51 | # grep returns 1 if no matches, we need to ignore that for the pipeline to work. 52 | set +e 53 | # All lines between the OPTIONS heading and the next heading, 54 | # except tje --help option as it is not useful in these docs. 55 | # Option descriptions can span multiple lines, hence the funky '§' business to join them. 56 | sed -n "/$OPTIONS_HEADING/,/$HEADING_PATTERN/p" | drop_headings | tr '\n' '§' | sed -E 's/§ *-/\n-/g' | sed 's/§ */ /g' | trim | grep -v -- '--help' 57 | set -e 58 | } 59 | 60 | # Render markdown help for a subcommand, or a subcommand under it. 61 | show_docs() { 62 | subcommand="$1" 63 | subsubcommand="$2" 64 | 65 | help="$(cat)" 66 | 67 | if [ -z "$subsubcommand" ]; then 68 | heading="## \`$subcommand\`" 69 | else 70 | heading="### \`$subcommand $subsubcommand\`" 71 | 72 | subsubsubcommand=$(echo "$help" | find_subcommands) 73 | if [ -n "$subsubsubcommand" ]; then 74 | printerr "Subcommand \`$subcommand $subsubcommand\` has subcommands, this is not supported" 75 | exit 1 76 | fi 77 | 78 | fi 79 | 80 | description=$(echo "$help" | find_description) 81 | usage=$(echo "$help" | find_usage) 82 | options=$(echo "$help" | find_options) 83 | 84 | echo 85 | echo "$heading" 86 | echo 87 | echo \`"$usage"\` 88 | echo 89 | echo "$description" 90 | echo 91 | if [ -n "$options" ]; then 92 | echo "| Option | Description |" 93 | echo "| ------ | ----------- |" 94 | echo "$options" | sed 's/^/| \`/' | sed -E 's/( +|$)/\`| /' 95 | fi 96 | } 97 | 98 | cat < 106 | 107 | The \`gleam\` command uses subcommands to access different parts of the functionality: 108 | EOF 109 | 110 | # Note: lsp is a "hidden" command so it will not be shown by `gleam help` 111 | subcommands=$(echo "$gleam_help" | find_subcommands) 112 | 113 | for subcommand in $subcommands; do 114 | 115 | command_help=$(gleam help "$subcommand") 116 | echo "$command_help" | show_docs "$subcommand" 117 | 118 | for subsubcommand in $(echo "$command_help" | find_subcommands); do 119 | 120 | if [ "$subsubcommand" = "help" ]; then 121 | continue 122 | fi 123 | 124 | subcommand_help=$(gleam help "$subcommand" "$subsubcommand") 125 | echo "$subcommand_help" | show_docs "$subcommand" "$subsubcommand" 126 | 127 | done 128 | 129 | done 130 | -------------------------------------------------------------------------------- /book/fonts/SOURCE-CODE-PRO-LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /book-src/tour/case-expressions.md: -------------------------------------------------------------------------------- 1 | # Case 2 | 3 | The `case` expression is the most common kind of flow control in Gleam code. It 4 | allows us to say "if the data has this shape then do that", which we call 5 | _pattern matching_. 6 | 7 | Here we match on an `Int` and return a specific string for the values 0, 1, 8 | and 2. The final pattern `n` matches any other value that did not match any of 9 | the previous patterns. 10 | 11 | ```gleam 12 | case some_number { 13 | 0 -> "Zero" 14 | 1 -> "One" 15 | 2 -> "Two" 16 | n -> "Some other number" // This matches anything 17 | } 18 | ``` 19 | 20 | Pattern matching on a `Bool` value is the Gleam alternative to the `if else` 21 | statement found in other languages. 22 | 23 | ```gleam 24 | case some_bool { 25 | True -> "It's true!" 26 | False -> "It's not true." 27 | } 28 | ``` 29 | 30 | Gleam's `case` is an expression, meaning it returns a value and can be used 31 | anywhere we would use a value. For example, we can name the value of a case 32 | expression with a `let` binding. 33 | 34 | ```gleam 35 | let description = 36 | case True { 37 | True -> "It's true!" 38 | False -> "It's not true." 39 | } 40 | 41 | description // => "It's true!" 42 | ``` 43 | 44 | 45 | ## Destructuring 46 | 47 | A `case` expression can be used to destructure values that 48 | contain other values, such as tuples and lists. 49 | 50 | ```gleam 51 | case xs { 52 | [] -> "This list is empty" 53 | [a] -> "This list has 1 element" 54 | [a, b] -> "This list has 2 elements" 55 | _other -> "This list has more than 2 elements" 56 | } 57 | ``` 58 | 59 | It's not just the top level data structure that can be pattern matched, 60 | contained values can also be matched. This gives `case` the ability to 61 | concisely express flow control that might be verbose without pattern matching. 62 | 63 | ```gleam 64 | case xs { 65 | [[]] -> "The only element is an empty list" 66 | [[], ..] -> "The 1st element is an empty list" 67 | [[4], ..] -> "The 1st element is a list of the number 4" 68 | other -> "Something else" 69 | } 70 | ``` 71 | 72 | Pattern matching also works in `let` bindings, though patterns that do not 73 | match all instances of that type may result in a runtime error. 74 | 75 | ```gleam 76 | let [a] = [1] // a is 1 77 | let [b] = [1, 2] // Runtime error! The pattern has 1 element but the value has 2 78 | ``` 79 | 80 | # String matching 81 | 82 | The string concatenate operator can be used to match against strings that have a 83 | given prefix. 84 | 85 | ```gleam 86 | case x { 87 | "Hello, " <> name -> name 88 | _ -> "other" 89 | } 90 | ``` 91 | 92 | If the variable `x` references the string `"Hello, Joe"` then this case 93 | expression would evaluate to the string `"Joe"`. 94 | 95 | For any other strings it would evaluate to the string `"other"`. 96 | 97 | ## Matching on multiple values 98 | 99 | Sometimes it is useful to pattern match on multiple values at the same time, 100 | so `case` supports having multiple subjects. 101 | 102 | ```gleam 103 | case x, y { 104 | 1, 1 -> "both are 1" 105 | 1, _ -> "x is 1" 106 | _, 1 -> "y is 1" 107 | _, _ -> "neither is 1" 108 | } 109 | ``` 110 | 111 | 112 | ## Assigning names to sub-patterns 113 | 114 | Sometimes when pattern matching we want to assign a name to a value while 115 | specifying its shape at the same time. We can do this using the `as` keyword. 116 | 117 | ```gleam 118 | case xs { 119 | [[_, ..] as inner_list] -> inner_list 120 | other -> [] 121 | } 122 | ``` 123 | 124 | 125 | ## Checking equality and ordering in patterns 126 | 127 | The `if` keyword can be used to add a guard expression to a case clause. Both 128 | the patterns have to match and the guard has to evaluate to `True` for the 129 | clause to match. The guard expression can check for equality or ordering for 130 | `Int` and `Float`. 131 | 132 | ```gleam 133 | case xs { 134 | [a, b, c] if a == b && b != c -> "ok" 135 | _other -> "ko" 136 | } 137 | ``` 138 | 139 | ```gleam 140 | case xs { 141 | [a, b, c] if a >. b && a <=. c -> "ok" 142 | _other -> "ko" 143 | } 144 | ``` 145 | 146 | 147 | ## Alternative clause patterns 148 | 149 | Alternative patterns can be given for a case clause using the `|` operator. If 150 | any of the patterns match then the clause matches. 151 | 152 | Here the first clause will match if the variable `number` holds 2, 4, 6 or 8. 153 | 154 | ```gleam 155 | case number { 156 | 2 | 4 | 6 | 8 -> "This is an even number" 157 | 1 | 3 | 5 | 7 -> "This is an odd number" 158 | _ -> "I'm not sure" 159 | } 160 | ``` 161 | 162 | If the patterns declare variables then the same variables must be declared in 163 | all patterns, and the variables must have the same type in all the patterns. 164 | 165 | 166 | ```gleam 167 | case list { 168 | [1, x] | x -> x // Error! Int != List(Int) 169 | _ -> 0 170 | } 171 | ``` 172 | -------------------------------------------------------------------------------- /writing-gleam/gleam-toml.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: gleam.toml 3 | subtitle: Configure your Gleam project 4 | layout: page 5 | --- 6 | 7 | All Gleam projects require a `gleam.toml` configuration file. The `toml` 8 | configuration format is documented at [toml.io](https://toml.io/). 9 | 10 | ```toml 11 | # The name of your project (required) 12 | name = "my_project" 13 | 14 | # The version of your project (required) 15 | version = "1.0.0" 16 | 17 | # The licences which this project uses, in SPDX format (optional) 18 | licences = ["Apache-2.0", "MIT"] 19 | 20 | # A short description of your project (optional) 21 | # This will be displayed on the package page if the project is published to 22 | # the Hex package repository. 23 | description = "Gleam bindings to..." 24 | 25 | # The target to default to when compiling or running Gleam code 26 | # Accepted values are "erlang" and "javascript". Defaults to "erlang". 27 | target = "erlang" 28 | 29 | # The source code repository location (optional) 30 | # This will be used in generated documentation and displayed on Hex. 31 | repository = { type = "github", user = "example", repo = "my_project" } 32 | # It can also be one of these formats 33 | # repository = { type = "gitlab", user = "example", repo = "my_project" } 34 | # repository = { type = "bitbucket", user = "example", repo = "my_project" } 35 | # repository = { type = "custom", url = "https://example.com/my_project" } 36 | 37 | # Links to any related website (optional) 38 | # This will be displayed in generated documentation and on Hex. 39 | links = [ 40 | { title = "Home page", href = "https://example.com" }, 41 | { title = "Other site", href = "https://another.example.com" }, 42 | ] 43 | 44 | # Modules that should be considered "internal" and will not be included in 45 | # generated documentation. Note this currently only affects documentation; 46 | # public types and functions defined in these modules are still public. 47 | # 48 | # Items in this list are "globs" that are matched against module names. See: 49 | # https://docs.rs/glob/latest/glob/struct.Pattern.html 50 | # 51 | # The default value is as below, with the `name` of your project substituted in 52 | # place of "my_app". 53 | internal_modules = [ 54 | "my_app/internal", 55 | "my_app/internal/*", 56 | ] 57 | 58 | # The version of the Gleam compiler that the package requires (optional) 59 | # An error is raised if the version of the compiler used to compile the package 60 | # does not match this requirement. 61 | gleam = ">= 0.30.0" 62 | 63 | # The Hex packages the project needs to compile and run (optional) 64 | # Uses the Hex version requirement format 65 | # https://hexdocs.pm/elixir/Version.html#module-requirements 66 | [dependencies] 67 | gleam_stdlib = "~> 0.18" 68 | gleam_erlang = "~> 0.2" 69 | gleam_http = "~> 2.1" 70 | # Local dependencies can be specified with a path 71 | my_other_project = { path = "../my_other_project" } 72 | 73 | # The Hex packages the project needs for the tests (optional) 74 | # These will not be included if the package is published to Hex. 75 | # This table cannot include any packages that are already found in the 76 | # `dependencies` table. 77 | [dev-dependencies] 78 | gleeunit = "~> 0.3" 79 | gleam_bitwise = "~> 0.3" 80 | 81 | # Documentation specific configuration (optional) 82 | [documentation] 83 | # Additional markdown pages to be included in generated HTML docs (optional) 84 | pages = [ 85 | { title = "My Page", path = "my-page.html", source = "./path/to/my-page.md" }, 86 | ] 87 | 88 | # Erlang specific configuration (optional) 89 | [erlang] 90 | # The name of the OTP application module, if the project has one (optional) 91 | # Typically Gleam projects do not use the Erlang/OTP implicit application boot 92 | # system and so typically do not define this. 93 | # If specified the module must implement the OTP application behaviour. 94 | # https://www.erlang.org/doc/man/application.html 95 | application_start_module = "my_app/application" 96 | 97 | # The names of any OTP applications that need to be started in addition to the 98 | # ones from the project dependencies (optional) 99 | extra_applications = ["inets", "ssl"] 100 | 101 | # JavaScript specific configuration (optional) 102 | [javascript] 103 | # Generate TypeScript .d.ts files 104 | typescript_declarations = true 105 | 106 | # Which JavaScript runtime to use with `gleam run`, `gleam test` etc. 107 | runtime = "node" # or "deno" 108 | 109 | # Configuration specific to the Deno runtime (optional) 110 | # https://deno.land/manual@v1.30.0/basics/permissions#permissions 111 | [javascript.deno] 112 | allow_all = false 113 | allow_sys = false 114 | allow_ffi = false 115 | allow_hrtime = false 116 | 117 | # A bool or list of environment variables 118 | allow_env = ["DATABASE_URL"] 119 | 120 | # A bool or a list of IP addresses or hostnames (optionally with ports) 121 | allow_net = ["example.com:443"], 122 | 123 | # A bool or a list of paths 124 | allow_run = ["./bin/migrate.sh"], 125 | allow_read = ["./database.sqlite"], 126 | allow_write = ["./database.sqlite"], 127 | ``` 128 | -------------------------------------------------------------------------------- /_layouts/old.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% capture title %}{% if page.title %}{{ page.title | strip }} – {% endif %}Gleam{% endcapture %} 5 | {% capture description %}{% if page.description %}{{ page.description | strip }}{% else %}The Gleam programming language{% endif %}{% endcapture %} 6 | 7 | 8 | {{ title }} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {% feed_meta %} 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 47 | 48 | {{ content }} 49 | 50 | 96 | 97 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /book/css/general.css: -------------------------------------------------------------------------------- 1 | /* Base styles and content styles */ 2 | 3 | @import 'variables.css'; 4 | 5 | :root { 6 | /* Browser default font-size is 16px, this way 1 rem = 10px */ 7 | font-size: 62.5%; 8 | color-scheme: var(--color-scheme); 9 | } 10 | 11 | html { 12 | font-family: "Open Sans", sans-serif; 13 | color: var(--fg); 14 | background-color: var(--bg); 15 | text-size-adjust: none; 16 | -webkit-text-size-adjust: none; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | font-size: 1.6rem; 22 | overflow-x: hidden; 23 | } 24 | 25 | code { 26 | font-family: var(--mono-font) !important; 27 | font-size: var(--code-font-size); 28 | } 29 | 30 | /* make long words/inline code not x overflow */ 31 | main { 32 | overflow-wrap: break-word; 33 | } 34 | 35 | /* make wide tables scroll if they overflow */ 36 | .table-wrapper { 37 | overflow-x: auto; 38 | } 39 | 40 | /* Don't change font size in headers. */ 41 | h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { 42 | font-size: unset; 43 | } 44 | 45 | .left { float: left; } 46 | .right { float: right; } 47 | .boring { opacity: 0.6; } 48 | .hide-boring .boring { display: none; } 49 | .hidden { display: none !important; } 50 | 51 | h2, h3 { margin-top: 2.5em; } 52 | h4, h5 { margin-top: 2em; } 53 | 54 | .header + .header h3, 55 | .header + .header h4, 56 | .header + .header h5 { 57 | margin-top: 1em; 58 | } 59 | 60 | h1:target::before, 61 | h2:target::before, 62 | h3:target::before, 63 | h4:target::before, 64 | h5:target::before, 65 | h6:target::before { 66 | display: inline-block; 67 | content: "»"; 68 | margin-left: -30px; 69 | width: 30px; 70 | } 71 | 72 | /* This is broken on Safari as of version 14, but is fixed 73 | in Safari Technology Preview 117 which I think will be Safari 14.2. 74 | https://bugs.webkit.org/show_bug.cgi?id=218076 75 | */ 76 | :target { 77 | scroll-margin-top: calc(var(--menu-bar-height) + 0.5em); 78 | } 79 | 80 | .page { 81 | outline: 0; 82 | padding: 0 var(--page-padding); 83 | margin-top: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */ 84 | } 85 | .page-wrapper { 86 | box-sizing: border-box; 87 | } 88 | .js:not(.sidebar-resizing) .page-wrapper { 89 | transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */ 90 | } 91 | 92 | .content { 93 | overflow-y: auto; 94 | padding: 0 5px 50px 5px; 95 | } 96 | .content main { 97 | margin-left: auto; 98 | margin-right: auto; 99 | max-width: var(--content-max-width); 100 | } 101 | .content p { line-height: 1.45em; } 102 | .content ol { line-height: 1.45em; } 103 | .content ul { line-height: 1.45em; } 104 | .content a { text-decoration: none; } 105 | .content a:hover { text-decoration: underline; } 106 | .content img, .content video { max-width: 100%; } 107 | .content .header:link, 108 | .content .header:visited { 109 | color: var(--fg); 110 | } 111 | .content .header:link, 112 | .content .header:visited:hover { 113 | text-decoration: none; 114 | } 115 | 116 | table { 117 | margin: 0 auto; 118 | border-collapse: collapse; 119 | } 120 | table td { 121 | padding: 3px 20px; 122 | border: 1px var(--table-border-color) solid; 123 | } 124 | table thead { 125 | background: var(--table-header-bg); 126 | } 127 | table thead td { 128 | font-weight: 700; 129 | border: none; 130 | } 131 | table thead th { 132 | padding: 3px 20px; 133 | } 134 | table thead tr { 135 | border: 1px var(--table-header-bg) solid; 136 | } 137 | /* Alternate background colors for rows */ 138 | table tbody tr:nth-child(2n) { 139 | background: var(--table-alternate-bg); 140 | } 141 | 142 | 143 | blockquote { 144 | margin: 20px 0; 145 | padding: 0 20px; 146 | color: var(--fg); 147 | background-color: var(--quote-bg); 148 | border-top: .1em solid var(--quote-border); 149 | border-bottom: .1em solid var(--quote-border); 150 | } 151 | 152 | kbd { 153 | background-color: var(--table-border-color); 154 | border-radius: 4px; 155 | border: solid 1px var(--theme-popup-border); 156 | box-shadow: inset 0 -1px 0 var(--theme-hover); 157 | display: inline-block; 158 | font-size: var(--code-font-size); 159 | font-family: var(--mono-font); 160 | line-height: 10px; 161 | padding: 4px 5px; 162 | vertical-align: middle; 163 | } 164 | 165 | :not(.footnote-definition) + .footnote-definition, 166 | .footnote-definition + :not(.footnote-definition) { 167 | margin-top: 2em; 168 | } 169 | .footnote-definition { 170 | font-size: 0.9em; 171 | margin: 0.5em 0; 172 | } 173 | .footnote-definition p { 174 | display: inline; 175 | } 176 | 177 | .tooltiptext { 178 | position: absolute; 179 | visibility: hidden; 180 | color: #fff; 181 | background-color: #333; 182 | transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */ 183 | left: -8px; /* Half of the width of the icon */ 184 | top: -35px; 185 | font-size: 0.8em; 186 | text-align: center; 187 | border-radius: 6px; 188 | padding: 5px 8px; 189 | margin: 5px; 190 | z-index: 1000; 191 | } 192 | .tooltipped .tooltiptext { 193 | visibility: visible; 194 | } 195 | 196 | .chapter li.part-title { 197 | color: var(--sidebar-fg); 198 | margin: 5px 0px; 199 | font-weight: bold; 200 | } 201 | 202 | .result-no-output { 203 | font-style: italic; 204 | } 205 | -------------------------------------------------------------------------------- /_posts/2019-12-25-gleam-v0.6-released.md: -------------------------------------------------------------------------------- 1 | --- 2 | author: Louis Pilfold 3 | title: Gleam v0.6 released! 🎄 4 | tags: 5 | - Release 6 | --- 7 | 8 | Merry Christmas! Following in the Ruby tradition we're having a release on 9 | Christmas day, and so [Gleam](https://github.com/gleam-lang/gleam) v0.6 is here! 10 | 11 | This release has one big change to how we define data structures in Gleam. To 12 | understand it lets take a look at how structs and enums have worked up until 13 | this point. 14 | 15 | ```gleam 16 | struct Cat { 17 | name: String 18 | age: Int 19 | } 20 | ``` 21 | 22 | Structs are collections of named values. Under the hood they are represented 23 | as Erlang tuples, so `Cat("Nubi", 2)` would be `{<<"Nubi">>, 2}` in Erlang. 24 | 25 | ```gleam 26 | enum SchoolPerson { 27 | Teacher(String, Subject) 28 | Student(String) 29 | } 30 | ``` 31 | 32 | Enum are also collections of values, only this time the values are not named. 33 | One way in which enums are more capable than structs is that they can have 34 | more than one constructor, so for example a SchoolPerson enum type can be 35 | either a Teacher or a Student. 36 | 37 | Like structs enums are tuples at runtime, only they have their constructor 38 | name as the first element to help distinguish them, so `Student("Louis")` 39 | would be `{student, <<"Louis">>}` in Erlang. This atom tag makes enums 40 | compatible with Erlang records, allowing easier use within projects written in 41 | Erlang or Elixir. 42 | 43 | So the differences between structs and enums were: 44 | 45 | 1. Struct fields can have names. 46 | 2. Enums are Erlang record compatible. 47 | 3. Enums can have more than one constructor. 48 | 49 | In v0.5 things changed a little. 50 | 51 | It turned out that being able to label fields so they have names was useful, 52 | so enums gained labelled arguments (as did functions). 53 | 54 | It turns out that being Erlang record compatible with a tag atom was useful 55 | for Erlang interop and for runtime debugging, so structs got this too. 56 | 57 | At which point the only difference between enums and structs are the number of 58 | constructors, and there's nothing stopping someone from defining an enum with 59 | a single constructor. 60 | 61 | Structs became a subset of enums, so why have both? 62 | 63 | 64 | ## Custom types 65 | 66 | With v0.6 rather than structs and enums we have _custom types_. Here's how the 67 | two examples above would be written using the new syntax: 68 | 69 | ```gleam 70 | type Cat { 71 | Cat(name: String, age: Int) 72 | } 73 | ``` 74 | Cat is a custom type has a single constructor called Cat. 75 | 76 | ```gleam 77 | type SchoolPerson { 78 | Teacher(name: String, class: Subject) 79 | Student(name: String) 80 | } 81 | ``` 82 | 83 | SchoolPerson is a custom type has a Teacher constructor and a Student constructor. 84 | 85 | ```gleam 86 | let louis = Student(name: "Louis") 87 | ``` 88 | 89 | In keeping with Erlang and Elixir an instance of one of these custom types is 90 | called a record. The variable `louis` is a Student record, and it has the type 91 | SchoolPerson. 92 | 93 | This change makes the languages simpler (both to the user and within the 94 | compiler), and hopefully it'll make Gleam a little easier to learn too. :) 95 | 96 | 97 | ## Tuples 98 | 99 | After this change `struct` is no longer a keyword, and it doesn't make much 100 | sense to have a concept of anonymous structs without named structs, so 101 | anonymous structs have been renamed _tuples_. 102 | 103 | ```gleam 104 | let pair = tuple(1, "two") 105 | ``` 106 | 107 | 108 | ## The rest 109 | 110 | There's been a number a smattering of bug fixes in this release, see the 111 | [changelog](https://github.com/gleam-lang/gleam/blob/master/CHANGELOG.md) for 112 | further details. 113 | 114 | If you want to try out the new version of Gleam head over to the [installation 115 | page][installation]. I'd love to hear how you find it and get your feedback so 116 | Gleam can continue to improve. 117 | 118 | Want to view some existing Gleam projects? Head on over to the 119 | [awesome-gleam][awesome-gleam] list. Looking for something to build in 120 | Gleam? Check out [the suggestions tracker][suggestions]. 121 | 122 | [awesome-gleam]: https://github.com/gleam-lang/awesome-gleam 123 | [suggestions]: https://github.com/gleam-lang/suggestions/issues 124 | [installation]: https://gleam.run/getting-started/installing-gleam.html 125 | 126 | 127 | ## Thanks 128 | 129 | Lastly, a huge thank you to the contributors to and sponsors of Gleam since 130 | last release! 131 | 132 | - [Adam Brodzinski](https://github.com/AdamBrodzinski) 133 | - [Christian Wesselhoeft](https://github.com/xtian) 134 | - [Devon Estes](https://github.com/devonestes) 135 | - [John Palgut](https://github.com/Jwsonic) 136 | - [Matt Widmann](https://github.com/mgwidmann) 137 | - [Michał Łępicki](https://github.com/michallepicki) 138 | - [OvermindDL1](https://github.com/OvermindDL1) 139 | - [RJ Dellecese](https://github.com/rjdellecese) 140 | - [Sebastian Porto](https://github.com/sporto) 141 | - [Stefan Hagen](https://github.com/sthagen) 142 | - [ontofractal](https://github.com/ontofractal) 143 | - [Štefan Ľupták](https://github.com/EskiMag) 144 | 145 | 146 | If you would like to help make strongly typed programming on the Erlang 147 | virtual machine a production-ready reality please consider [sponsoring 148 | Gleam][sponsor] via the GitHub Sponsors program. 149 | 150 | Thank you! And have a fantastic new year! 💜 151 | 152 | [sponsor]: https://github.com/sponsors/lpil 153 | -------------------------------------------------------------------------------- /_posts/2019-09-19-gleam-v0.4-released.md: -------------------------------------------------------------------------------- 1 | --- 2 | author: Louis Pilfold 3 | title: Gleam v0.4 released! 4 | tags: 5 | - Release 6 | --- 7 | 8 | [Gleam](https://github.com/lpil/gleam) has reached v0.4! This version has some 9 | new features, bug fixes, and some breaking changes. Let's take a look. 10 | 11 | 12 | ## Structs 13 | 14 | Gleam's map and tuple type has been removed and replaced with structs, which 15 | have many of the benefits of both. 16 | 17 | Like maps structs are collections of named values, each with their own type. 18 | Unlike maps they are named, so two structs are not the same type just because 19 | they have the same fields by coincidence, making Gleam's type system a little 20 | stricter by default. 21 | 22 | Like tuples structs have constant access time, they do not need to be linearly 23 | scanned in order to find a field to access it. 24 | 25 | Unlike either struct types are declared up-front by the `struct` keyword. 26 | 27 | ```gleam 28 | pub struct Cat { 29 | name: String 30 | cuteness: Int 31 | } 32 | ``` 33 | 34 | Once declared the newly defined constructor can be used to create instances of 35 | the struct. 36 | 37 | ```gleam 38 | pub fn cats() { 39 | let cat1 = Cat(name: "Nubi", cuteness: 2001) 40 | let cat2 = Cat(cuteness: 1805, name: "Biffy") 41 | 42 | // Alternatively fields can be given without labels 43 | let cat3 = Cat("Ginny", 1950) 44 | 45 | [cat1, cat2, cat3] 46 | } 47 | ``` 48 | 49 | One downside to structs is that they are less convenient for returning more 50 | than one value from a function than tuples were, as struct types need to be 51 | pre-declared. To negate this inconvenience the standard library declares `Pair` 52 | and `Triple` types in the `gleam/pair` and `gleam/triple` modules. If you wish 53 | to return more than 3 values from a function it is recommended to create a 54 | struct and name the values to make it more clear what they are. 55 | 56 | 57 | ## Comparison operators 58 | 59 | The next breaking change is to how the comparison operators `>`, `>=`, `<`, 60 | and `<=` work. Previously these operators would take any two values of the 61 | same type and determine which is larger according to Erlang's ordering of 62 | values. This is convenience but may result in surprising behaviour when used 63 | with custom types such as enums. 64 | 65 | For example, with the `Order` enum we would expect `Gt` (greater than) to be 66 | larger than `Lt` (less than), but according to Erlang's value ordering this is 67 | not the case. 68 | 69 | ```gleam 70 | enum Order = 71 | | Gt 72 | | Eq 73 | | Lt 74 | ``` 75 | ```gleam 76 | Gt > Lt // => False 77 | ``` 78 | 79 | From this version on `>`, `>=`, `<`, and `<=` only accept Ints as arguments 80 | to avoid this surprising behaviour, and the `>.` `>=.` `<.` and `<=.` 81 | comparison operators have been added for comparing Floats. 82 | 83 | For ordering other types comparison functions can be found in the standard 84 | library, such as `order.compare` and `bool.compare`. 85 | 86 | 87 | ## Second class modules 88 | 89 | Modules are no longer first class values in Gleam, meaning they can no longer 90 | be assigned to variables or used as arguments to functions. 91 | 92 | First class modules were inspired by OCaml and intended to be a way to work 93 | with Erlang _behaviours_ such as `gen_stage` from within Gleam. However after 94 | several months of using modules in Gleam it became clear that taking OCaml's 95 | first class modules but not their functor module system resulted in Gleam's 96 | modules being far less useful. 97 | 98 | First class functions combined with Gleam's other data structures is 99 | sufficient to use Erlang behaviours, while being easier to construct and 100 | compose, so first class modules were determined not to be the ideal solution 101 | here either. 102 | 103 | With first class modules removed we no longer need a special syntax for 104 | accessing a field on a module, so the `:` operator has been removed and 105 | replaced with the `.` operator, making it the universal operator for accessing 106 | a named field on a module or container data type in Gleam. 107 | 108 | ```gleam 109 | import gleam/list 110 | 111 | pub fn main() { 112 | list.reverse([1, 2, 3]) 113 | } 114 | ``` 115 | 116 | With the removal of modules and maps Gleam's type system has become simpler, 117 | less structural and more nominal in style. This puts us in a good position to 118 | do research into new forms of polymorphism such as type classes or traits! 119 | 120 | 121 | ## The rest 122 | 123 | In addition to these features there's been a number of other improvements to 124 | the quality of the error messages, the generated code, and a handful of bug 125 | fixes. 😊 126 | 127 | If you want to try out the new version of Gleam head over to the [installation 128 | page](https://gleam.run/getting-started/installing-gleam.html). I'd love to 129 | hear how you find it and get your feedback so Gleam can continue to improve. 130 | 131 | 132 | ## Code BEAM lite Berlin 133 | 134 | On the 11th of October 2019 I'll be speaking at [Code BEAM lite 135 | Berlin](https://codesync.global/conferences/code-beam-lite-berlin-2019/) about 136 | Gleam. If you're attending (or want to recommend to me good things to do on a 137 | weekend in Berlin) say Hello! 138 | 139 | 140 | ## Thanks 141 | 142 | Lastly, a huge thank you to the code contributors to this release! 143 | 144 | - [Al Dee](https://github.com/scripttease) 145 | - [Benjamin Reynolds](https://github.com/benreyn) 146 | - [Dirk Gadsden](https://github.com/dirk) 147 | - [epj009](https://github.com/epj009) 148 | -------------------------------------------------------------------------------- /book-src/tour/bit-strings.md: -------------------------------------------------------------------------------- 1 | # Bit strings 2 | 3 | Gleam has a convenient syntax for working directly with binary data called a 4 | Bit String. Bit Strings represent a sequence of 1s and 0s. 5 | 6 | Bit Strings are written literally with opening brackets `<<`, any number of bit 7 | string segments separated by commas, and closing brackets `>>`. 8 | 9 | ## Bit String Segments 10 | 11 | By default a Bit String segment represents 8 bits, also known as 1 byte. 12 | 13 | ```gleam 14 | // This is the number 3 as an 8 bit value. 15 | // Written in binary it would be 00000011 16 | <<3>> 17 | ``` 18 | 19 | You can also specify a bit size using either short hand or long form. 20 | 21 | ```gleam 22 | // These are the exact same value as above 23 | // Shorthand 24 | <<3:8>> 25 | 26 | // Long Form 27 | <<3:size(8)>> 28 | ``` 29 | 30 | You can specify any positive integer as the bit size. 31 | 32 | ```gleam 33 | // This is not same as above, remember we're working with a series of 1s and 0s. 34 | // This Bit String is 16 bits long: 0000000000000011 35 | <<3:size(16)>> 36 | ``` 37 | 38 | You can have any number of segments separated by commas. 39 | 40 | ```gleam 41 | // This is True 42 | <<0:4, 1:3, 1:1>> == <<3>> 43 | ``` 44 | 45 | ## Bit String Segment Options 46 | 47 | There are a few more options you can attach to a segment to describe its size 48 | and bit layout. 49 | 50 | `unit()` lets you create a segment of repeating size. The segment will 51 | represent `unit * size` number of bits. If you use `unit()` you must also have 52 | a `size` option. 53 | 54 | ```gleam 55 | // This is True 56 | <<3:size(4)-unit(4)>> == <<3:size(16)>> 57 | ``` 58 | 59 | The `utf8`, `utf16` and `utf32` options let you put a String directly into a 60 | Bit String. 61 | 62 | ```gleam 63 | <<"Hello Gleam 💫":utf8>> 64 | ``` 65 | 66 | The `bit_string` option lets you put any other Bit String into a Bit String. 67 | 68 | ```gleam 69 | let a = <<0:1, 1:1, 1:1>> 70 | <> == <<"a":utf8>> // True 71 | ``` 72 | 73 | Here Is the full list of options and their meaning: 74 | 75 | ### Options in Values 76 | 77 | | Option | Meaning | 78 | | ---------- | ------------------------------------------------------ | 79 | | bit_string | a bitstring that is any bit size | 80 | | float | default size of 64 bits | 81 | | int | default size of 8 bits | 82 | | size | the size of the segment in bits | 83 | | unit | how many times to repeat the segment, must have a size | 84 | | big | big endian | 85 | | little | little endian | 86 | | native | endianness of the processor | 87 | | utf8 | a string to encode as utf8 codepoints | 88 | | utf16 | a string to encode as utf16 codepoints | 89 | | utf32 | a string to encode as utf32 codepoints | 90 | 91 | ### Options in Patterns 92 | 93 | | Option | Meaning | 94 | | --------------- | ------------------------------------------------------ | 95 | | binary | a bitstring that is a multiple of 8 bits | 96 | | bit_string | a bitstring that is any bit size | 97 | | float | float value, size of exactly 64 bits | 98 | | int | int value, default size of 8 bits | 99 | | big | big endian | 100 | | little | little endian | 101 | | native | endianness of the processor | 102 | | signed | the captured value is signed | 103 | | unsigned | the captured value is unsigned | 104 | | size | the size of the segment in bits | 105 | | unit | how many times to repeat the segment, must have a size | 106 | | utf8 | an exact string to match as utf8 codepoints | 107 | | utf16 | an exact string to match as utf16 codepoints | 108 | | utf32 | an exact string to match as utf32 codepoints | 109 | | utf8_codepoint | a single valid utf8 codepoint | 110 | | utf16_codepoint | a single valid utf16 codepoint | 111 | | utf32_codepoint | a single valid utf32 codepoint | 112 | 113 | ## Values vs Patterns 114 | 115 | Bit Strings can appear on either the left or the right side of an equals sign. 116 | On the left they are called **patterns**, and on the right they are called 117 | **values**. 118 | 119 | This is an important distinction because values and patterns have slightly 120 | different rules. 121 | 122 | ### Rules for Patterns 123 | 124 | You can match on a variable length segment with the `bit_string` or `binary` 125 | options. A pattern can have at most 1 variable length segment and it must be 126 | the last segment. 127 | 128 | In a pattern the types `utf8`, `utf16`, and `utf32` must be an exact string. 129 | They cannot be a variable. There is no way to match a variable length section 130 | of a binary with an exact encoding. 131 | 132 | You can match a single variable codepoint with `utf8_codepoint`, 133 | `utf16_codepoint`, and `utf32_codepoint` which will match the correct number of 134 | bytes depending on the codepoint size and data. 135 | 136 | ## Further Reading 137 | 138 | Gleam inherits its Bit String syntax and handling from Erlang. You can find the 139 | Erlang documentation 140 | [here](https://erlang.org/doc/reference_manual/expressions.html#bit_syntax). 141 | 142 | ## Stdlib references 143 | 144 | - [gleam/bit_string](https://hexdocs.pm/gleam_stdlib/gleam/bit_string.html) 145 | - [gleam/bit_builder](https://hexdocs.pm/gleam_stdlib/gleam/bit_builder.html) 146 | -------------------------------------------------------------------------------- /writing-gleam/command-line-reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Command line reference 3 | subtitle: Getting Gleam things done in the terminal 4 | layout: page 5 | --- 6 | 7 | 8 | 9 | The `gleam` command uses subcommands to access different parts of the functionality: 10 | 11 | ## `add` 12 | 13 | `gleam add [OPTIONS] ...` 14 | 15 | Add new project dependencies 16 | 17 | | Option | Description | 18 | | ------ | ----------- | 19 | | `--dev`| Add the packages as dev-only dependencies 20 | 21 | ## `build` 22 | 23 | `gleam build [OPTIONS]` 24 | 25 | Build the project 26 | 27 | | Option | Description | 28 | | ------ | ----------- | 29 | | `-t, --target `| The platform to target [possible values: erlang, javascript] 30 | | `--warnings-as-errors`| Emit compile time warnings as errors 31 | 32 | ## `check` 33 | 34 | `gleam check` 35 | 36 | Type check the project 37 | 38 | 39 | ## `clean` 40 | 41 | `gleam clean` 42 | 43 | Clean build artifacts 44 | 45 | 46 | ## `deps` 47 | 48 | `gleam deps ` 49 | 50 | Work with dependency packages 51 | 52 | 53 | ### `deps download` 54 | 55 | `gleam deps download` 56 | 57 | Download all dependency packages 58 | 59 | 60 | ### `deps list` 61 | 62 | `gleam deps list` 63 | 64 | List all dependency packages 65 | 66 | 67 | ### `deps update` 68 | 69 | `gleam deps update` 70 | 71 | Update dependency packages to their latest versions 72 | 73 | 74 | ## `docs` 75 | 76 | `gleam docs ` 77 | 78 | Render HTML documentation 79 | 80 | 81 | ### `docs build` 82 | 83 | `gleam docs build [OPTIONS]` 84 | 85 | Render HTML docs locally 86 | 87 | | Option | Description | 88 | | ------ | ----------- | 89 | | `--open`| Opens the docs in a browser after rendering 90 | 91 | ### `docs publish` 92 | 93 | `gleam docs publish` 94 | 95 | Publish HTML docs to HexDocs 96 | 97 | This command uses this environment variables: 98 | 99 | - HEXPM_USER: (optional) The Hex username to authenticate with. 100 | - HEXPM_PASS: (optional) The Hex password to authenticate with. 101 | 102 | 103 | ### `docs remove` 104 | 105 | `gleam docs remove --package --version ` 106 | 107 | Remove HTML docs from HexDocs 108 | 109 | This command uses this environment variables: 110 | 111 | - HEXPM_USER: (optional) The Hex username to authenticate with. 112 | - HEXPM_PASS: (optional) The Hex password to authenticate with. 113 | 114 | | Option | Description | 115 | | ------ | ----------- | 116 | | `--package The name of the package`| 117 | | `--version The version of the docs to remove`| 118 | 119 | ## `export` 120 | 121 | `gleam export ` 122 | 123 | Export something useful from the Gleam project 124 | 125 | 126 | ### `export erlang-shipment` 127 | 128 | `gleam export erlang-shipment` 129 | 130 | Precompiled Erlang, suitable for deployment 131 | 132 | 133 | ### `export hex-tarball` 134 | 135 | `gleam export hex-tarball` 136 | 137 | 138 | 139 | 140 | ## `format` 141 | 142 | `gleam format [OPTIONS] [FILES]...` 143 | 144 | Format source code 145 | 146 | | Option | Description | 147 | | ------ | ----------- | 148 | | `--check`| Check if inputs are formatted without changing them 149 | | `--stdin`| Read source from STDIN 150 | 151 | ## `help` 152 | 153 | `gleam help [SUBCOMMAND]...` 154 | 155 | Print this message or the help of the given subcommand(s) 156 | 157 | 158 | ## `hex` 159 | 160 | `gleam hex ` 161 | 162 | Work with the Hex package manager 163 | 164 | 165 | ### `hex retire` 166 | 167 | `gleam hex retire [MESSAGE]` 168 | 169 | Retire a release from Hex 170 | 171 | This command uses this environment variables: 172 | 173 | - HEXPM_USER: (optional) The Hex username to authenticate with. 174 | - HEXPM_PASS: (optional) The Hex password to authenticate with. 175 | 176 | 177 | ### `hex unretire` 178 | 179 | `gleam hex unretire ` 180 | 181 | Un-retire a release from Hex 182 | 183 | This command uses this environment variables: 184 | 185 | - HEXPM_USER: (optional) The Hex username to authenticate with. 186 | - HEXPM_PASS: (optional) The Hex password to authenticate with. 187 | 188 | 189 | ## `lsp` 190 | 191 | `gleam lsp` 192 | 193 | Run the language server, to be used by editors 194 | 195 | 196 | ## `new` 197 | 198 | `gleam new [OPTIONS] ` 199 | 200 | Create a new project 201 | 202 | | Option | Description | 203 | | ------ | ----------- | 204 | | `--name `| Name of the project 205 | | `--skip-git`| Skip git initialization and creation of .gitignore, .git/* and .github/* files 206 | | `--skip-github`| Skip creation of .github/* files 207 | | `--template