Published 12 Jul, 2023 by Louis Pilfold
Gleam is a type safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v0.30.0 has been released, let’s take a look at what’s new.
Local dependencies
Gleam’s build tool has always had support for Hex, the package repository for the Erlang ecosystem. It now additionally supports local dependencies, allowing you to depend on other Gleam projects without pushing them to the repository.
# gleam.toml
name = "my_project"
[dependencies]
gleam_stdlib = "~> 0.30"
my_other_project = { path = "../my_other_project" }
You may want to use local dependencies when testing your project before publishing, when working on multiple related packages, or to enforce a certain dependency structure between parts of your codebase, such as ensuring a domain layer does not depend on a web framework.
One way I will be using this feature is to have a package of shared types and functions that I can use in both the Gleam Erlang backend and the Gleam JavaScript frontend of my web applications.
Thank you Miles Silberling-Cook for this feature!
Enhanced externals
Gleam can without any overhead import and call functions written in other languages on the runtime, such as Erlang, Elixir, JavaScript, and TypeScript.
If I wanted to define a public function that used FFI (foreign function interface) to halt the runtime I could do it like this:
/// Halt the runtime with the given exit code.
pub fn halt(code: Int) -> Nil {
native_halt(code)
}
if erlang {
external fn native_halt(Int) -> Nil =
"erlang" "halt"
}
if javascript {
external fn native_halt(Int) -> Nil =
"./my_javascript_module.mjs" "halt"
}
Here a public function with a documentation comment calls a private function, and conditional compilation is used to define the private function differently depending on the target runtime.
I think you’ll agree that it is quite verbose and repetitive; of the 14 lines of code in this example only 4 are meaningful.
Conditional compilation gives the programmer little in the way of guidance on how to structure their code, so other approaches can be found today in published Gleam packages:
Some packages only support a single target runtime, as such they may omit the conditional compilation entirely, documenting the supported target in their README. These packages will not work on other runtimes, and may fail to compile with a cryptic message.
Other packages omit the non-conditional facade function entirely, instead making the two conditional functions public. This approach is more concise but without any link between the two different implementations there can be drift, with types and functions either intentionally or unintentionally differing.
With Gleam v0.30.0 the FFI has been redesigned to address all these issues. The above example is now written like this:
/// Halt the runtime with the given exit code.
@external(erlang, "erlang", "halt")
@external(javascript, "./my_javascript_module.mjs", "halt")
pub fn halt(code: Int) -> Nil
This is much more concise, and the single function header ensures the various targets are kept in sync.
What’s more the compiler can now always infer what targets a function is implemented for, which in future we can use for dead code elimination and to show supported targets for packages on the Gleam package index website.
Panic! Todo!
Gleam has todo
and panic
keywords that can be used to crash the program when
code is reached that is either unfinished or should never be reached. If you
wanted to give a custom message to that crash for todo
you would have written
it like this:
pub fn main() {
todo("I really need to finish this...")
}
This syntax resulted in some confusion where people would think that these keywords are functions, and try to assign them to values. To make it clearer the syntax for providing a custom message has been changed to this:
pub fn main() {
todo as "I really need to finish this..."
}
This syntax may be extended in future for assertions and other error messages.
Any order aliases
Previously type aliases could only refer to aliases defined earlier in the same module. This restriction has been lifted, so this mundane looking code will now compile.
pub type Bill = List(#(String, Euro))
pub type Euro = Int
Build tool improvements
Gleam packages can now specify the minimum version of Gleam required to build them.
# gleam.toml
name = "my_project"
gleam = ">= 0.30.0"
If a user attempts to build a package with a version that doesn’t meet the specified version constraint an error will be emitted.
And lastly, the gleam remove
command has been added to remove dependencies
from a package, to complement the existing gleam add
command.
Thank you Miles Silberling-Cook and Mateusz Bil for these features!
Thanks
Gleam is made possible by the support of all the kind people and companies who have very generously sponsored or contributed to the project. Thank you all!
If you like Gleam consider sponsoring or asking your employer to sponsor Gleam development. I work full time on Gleam and your kind sponsorship is how I pay my bills!
- Aaron Gunderson
- Adam Brodzinski
- Adam Mokan
- Adi Iyengar
- Alembic
- Alex Manning
- Alexander Koutmos
- Alexander Stensrud
- Alexandre Del Vecchio
- Ali Farhadi
- Andrea Tupini
- Anthony Khong
- Anthony Scotti
- Arnaud Berthomier
- Barry Moore
- Ben Marx
- Ben Myles
- Benjamin Peinhardt
- brettkolodny
- Brian Glusman
- Bruno Michel
- Cade DuPont
- Carlo Gilmar
- Carlos Saltos
- Chew Choon Keat
- Chris Lloyd
- Chris Ohk
- Christopher Keele
- clangley
- Clay
- Cole Lawrence
- Colin
- Cosmo Shin (신의하)
- Cristine Guadelupe
- Damir Vandic
- Dan Dresselhaus
- Danielle Maywood
- Danny Martini
- Dave Lucia
- David Armstrong Lewis
- David Bernheisel
- David Flanagan
- David Sancho
- Dennis Dang
- Edon Gashi
- Elliott Pogue
- Erik Terpstra
- Ernesto Malave
- etopiei
- Fernando Farias
- Filip Figiel
- Florian Kraft
- fly.io
- Giacomo Cavalieri
- Graeme Coupar
- Guilherme de Maio
- Gustavo Villa
- Harry Bairstow
- Hayleigh Thompson
- Henry Warren
- Hex
- Ian González
- Ingmar Gagen
- inoas
- Ivar Vong
- j
- James MacAulay
- Jan Skriver Sørensen
- Jechol Lee
- Jen Stehlik
- jiangplus
- John Björk
- John Gallagher
- John Palgut
- Jonas Hedman Engström
- Kayla Washburn
- Kieran Gill
- Kris Jenkins
- Lars Wikman
- Leon Qadirie
- lidashuang
- Manuel Rubio
- Marius Kalvø
- Mark Holmes
- Mark Markaryan
- Markus
- Markus Pettersson
- Marshall Bowers
- Martin Janiczek
- Mathias Jean Johansen
- Matt Van Horn
- Matthias Benkort
- max-tern
- Michael Chris Lopez
- Michael Duffy
- Michael Jones
- Michael Kumm
- Mike Roach
- Mikko Ahlroth
- Miles Silberling-Cook
- Natanael Sirqueira
- Nathaniel Knight
- Nick Reynolds
- Nicklas Sindlev Andersen
- NineFX
- Noah Betzen
- OldhamMade
- Ole Michaelis
- ontofractal
- Parker Selbert
- Paul Gideon Dann
- Pete Jodo
- Praveen Perera
- qingliangcn
- Raúl Chouza
- Redmar Kerkhoff
- Rico Leuthold
- Robert Attard
- Robert Ellen
- rubytree
- Ryan Winchester
- Sam Aaron
- Sammy Isseyegh
- Sascha Wolf
- Saša Jurić
- Scott Wey
- Sean Jensen-Grey
- Sebastian Porto
- Sebastien Lacoste
- SEKUN
- Seve Salazar
- Shuqian Hon
- Signal Insights
- Simone Vittori
- Stefan Luptak
- Steven Joseph
- Strand Communications
- Szymon Wygnański
- Terje Bakken
- Theo Harris
- Tomasz Kowal
- Tristan de Cacqueray
- Tristan Sloughter
- Victor Borja
- Weizheng Liu
- Willyboar
- Wilson Silva
- Wojtek Mach
- Yasuo Higano
- Yu Matsuzawa
- Zsombor Gasparin
Thanks for reading! Happy hacking! 💜