Gleam is a type-safe and scalable language for the Erlang virtual machine and JavaScript runtimes. Today Gleam v1.11.0 has been published.
30% faster? Really?
The title of this article makes a bold claim: Gleam compiled to JavaScript being 30% faster! Gleam doesn't add any additional runtime when compiling to JavaScript, and the generated code is very much like the JavaScript a human would write, so this is an accomplishment we're very happy with.
First, a benchmark. Lustre is a frontend web framework for Gleam, capable of both SPA style and LiveView style functionality. It has a virtual DOM implementation with comparable performance to established frameworks in other languages, such as React and Elm. It is one of the most widely used Gleam packages, and certainly the most widely used Gleam web framework.
Lustre's virtual DOM diffing is implemented in Gleam, so improving its performance will benefit many Gleam users, and it will serve as a good benchmark to demonstrate the improvements. The charts below show the number of operations per second for diffing HTML tables of various sizes (higher is better).
10 rows
100 rows
1000 rows
Without any modification to Lustre itself it has got 30% faster! All other Gleam projects compiling to JavaScript can expect to similar performance improvements, with greater improvements to projects with more complex pattern matching.
OK, how does it work?
Gleam has a single flow control construct, the case expression. It runs top-to-bottom checking to see which of the given patterns match the value.
pub fn greet(person: Person) -> String {
case person {
Teacher(students: [], ..) -> "Hello! No students today?"
Student(name: "Daria", ..) -> "Hi Daria"
Student(subject: "Physics", ..) -> "Don't be late for Physics"
Teacher(name:, ..) | Student(name:, ..) -> "Hello, " <> name <> "!"
}
}
Prior to this release, when compiling to JavaScript code results in if else
chain, as can be seen in the code below.
export function greet(person) {
if (isTeacher(person) && isEmpty(person.students)) {
return "Hello! No students today?";
} else if (isStudent(person) && person.name === "Daria") {
return "Hi Daria";
} else if (isStudent(person) && person.subject === "Physics") {
return "Don't be late for Physics";
} else if (isTeacher(person)) {
return "Hello, " + person.name + "!";
} else {
return "Hello, " + person.name + "!";
}
}
Disclaimer: This code has been lightly edited for clarity, but all aspects related to this implementation change remain the same.
This is very understandable and human looking code, but it's not as efficient
as possible. For example, if the value is a Student
with a name other than
"Daria" and a subject other than "Physics" then the isTeacher
and isStudent
functions are each called twice, resulting in wasted work.
Similar problems arise with other patterns, especially with the list type as it
would need to be traversed multiple times to check various elements within
them.
The new and improved approach is to transform the linear sequence of checks
into a decision tree, where each check is performed the minimum number of
times to find the matching clause as quickly as possible. This decision tree is
then compiled into a series of nested if else
statements in JavaScript.
export function greet(person) {
if (isTeacher(person)) {
if (isEmpty(person.students)) {
return "Hello! No students today?";
} else {
return "Hello, " + person.name + "!";
}
} else {
if (person.name === "Daria") {
return "Hi Daria";
} else {
if (person.subject === "Physics") {
return "Don't be late for Physics";
} else {
return "Hello, " + person.name + "!";
}
}
}
}
This does result in a small increase in code size (up to 15% in our tests), but the uniform nature of the extra code is well suited to compression, with minification and brotli compression completely removing this extra size and producing the same application bundle size as with previous Gleam versions.
We have only implemented this optimisation for the JavaScript target and not the Erlang one as the Erlang Virtual machine implements this optimisation itself! It is done for us automatically there.
As part of this work the compilers analysis of pattern matching was enhanced, notably around bit-array patterns. It can now identify when a clause with a bit array pattern is unreachable because it only matches values that a previous clause also matches, such as the second clause here:
case payload {
<<first_byte, _:bits>> -> first_byte
<<1, _:bits>> -> 1
_ -> 0
}
Efficient compilation of pattern matching is a surprisingly challenging problem, and we would not have had so much success without academic research on the subject. In particular we would like to acknowledge "How to compile pattern matching", by Jules Jacobs and "Efficient manipulation of binary data using pattern matching", by Per Gustafsson and Konstantinos Sagonas. Thank you.
This is the culmination of work that was started before Gleam v1, and has been desired for much longer. A huge thank you to Giacomo Cavalieri for this final piece.
But that's not all! There's lots more new things in this release. Let's take a look.
Testing with assert
Types and static analysis are wonderful tools to help you write code, but you're always going to need to test programs to know they are working correctly. Gleam the language historically doesn't have any built-in testing functionality, so test libraries define assertion functions that can be used in tests.
pub fn hello_test() {
telephone.ring()
|> should.equal("Hello, Joe!")
}
This has worked well enough to be productive, but it's not the world-class experience we want in Gleam. These assertion functions are just that: they are functions. All they can do is take arguments and return values. They can't know anything about the code that produced those arguments, or the context from which they are being called. The debugging information that a Gleam test framework can provide with this is quite limited to compared to other languages that have either built-in assertion capabilities, a macro system, or other similar features.
Gleam isn't a language about types, it's a language about productivity and
developer joy. This sub-par testing experience wasn't up to our high standards,
and with this release we've made a big step towards correcting that with the
addition of assert
.
pub fn hello_test() {
assert telecom.ring() == "Hello, Joe!"
}
This new syntax panics if the given expression evaluates to False
. What makes
it different to conditionally calling the existing panic
syntax is that the
runtime error is annotated with information about the expression that evaluated
to False
, so test frameworks can provide detailed debugging information in
the event of a test failure.
Here's the output that the gleeunit
test framework will use. Other Gleam test
frameworks may go further with even better formats!
...............
assert test/my_app_test.gleam:215
test: my_app_test.hello_test
code: assert telecom.ring() == "Hello, Joe!"
left: "Hello, Mike!"
right: literal
info: Assertion failed.
..........
25 tests, 1 failures
Note how the test framework has enough information to show the assertion code
as it was written in the source file, and can show the values for the left and
right of the ==
operator.
As well as operators it can also understand function calls and show what each argument is.
........
assert test/my_app_test.gleam:353
test: my_app_test.system_test
code: assert telecom.is_up(key, strict, 2025)
0: "My WIFI"
1: True
2: literal
info: My internet must always be up!
.................
25 tests, 1 failures
In that example there was a custom assertion message, displayed under the
info
key. This is provided the same way as custom messages for Gleam's todo
and panic
syntaxes, using the as
keyword.
pub fn system_test() {
let key = "My WIFI"
let strict = True
assert telecom.is_up(key, strict, 2025)
as "My internet must always be up!"
}
Upgrading from gleeunit
's assertion functions to the new assert
syntax is a
slow and tedious job for a human to do, so Gears has made a helpful command
line tool to do it automatically! Run
it and your codebase will be updated for you in just a second.
Thank you Surya Rose for this! It will make a big difference to all Gleam programmers testing their programs.
gleam dev
A Gleam application typically has two main
functions, one in src/
for
running the application, and one in test/
for running the tests. The
application main function can be run with the console command gleam run
, and
the test one with the command gleam test
.
This is easy enough to understand, but what if you have some other code you
need to run in development? For example, if you're making a backend web
application you might want to have some extra code that configures a local
development database, or compiles some frontend assets. Where would you put the
code that does this?
This is development code that you do not want to ship to production (extra code and dependencies is a potential security risk), and having code that can make destructive changes to the database in production is an accident waiting to happen!
The traditional wisdom is to put a new module and main
function the test/
directory (as this code isn't included in production) and then to run it with
gleam run --module $THE_MODULE
. Placing non-test code in a directory called
test
isn't very intuitive, so it's not uncommon for people to place it in
src
instead, resulting in development code and dependencies accidentally
being published.
This release adds a new source directory for development code, dev/
. Code in
the dev/
directory can import src/
code and use development dependencies,
and the $PACKAGENAME_dev
module's main
function can be run with the new
gleam dev
console command. This should hopefully be a more satisfying and
easy to understand system, preventing future mistakes.
Thank you Surya Rose!
Help with understanding immutability
Gleam is an immutable language, which means that values are not updated in-place, instead new values are constructed from older values, with the desired changes applied. If you are familiar with mutable languages this may seem inefficient, but immutable languages apply some clever optimisations to get excellent performance and memory usage.
It's possible for people new to the immutable style to get confused, accidentally discarding the new updated version of some data. For example:
pub fn call_api(token: String) -> Response(String) {
let req = sdk.new_api_request()
request.set_header(req, "authentication", "Bearer " <> token)
http_client.send(req)
}
Can you spot the bug?
The set_header
function returns a new request value, but it is not assigned
to a variable, so the original request value without the authentication
header is sent instead. The bug is fixed by passing the output of each function
into the next one.
pub fn call_api(token: String) -> Response(String) {
sdk.new_api_request()
|> request.set_header("authentication", "Bearer " <> token)
|> http_client.send
}
To help avoid this mistake the compiler will now emit a warning when a function without any side effects is called but the return value isn't used. For example the following code:
fn go() -> Int {
add(1, 2)
add(3, 4)
}
Will produce the following warning:
warning: Unused value
┌─ /src/main.gleam:4:3
│
4 │ add(1, 2)
│ ^^^^^^^^^ This value is never used
This expression computes a value without any side effects, but then the
value isn't used at all. You might want to assign it to a variable, or
delete the expression entirely if it's not needed.
Thank you Surya Rose!
JavaScript bit array improvements
Gleam has a powerful literal syntax for constructing and parsing binary data, a much loved feature common to BEAM languages. Gleam supports this syntax when compiling to Erlang or to JavaScript, but some aspects of the syntax were not yet usable on JavaScript. This release adds support for UTF-16 and UTF-32 encoded segments of data.
Thank you Surya Rose!
Playing nicely with POSIX
The Gleam build tool has a gleam export erlang-shipment
command for compiling
and preparing a project for deployment to a server or similar. It includes a
script for starting the Erlang virtual machine and running the program, but
unfortunately it was written in a way that meant that the program would not
receive POSIX exit signals.
Christopher De Vries has fixed this problem. Thank you Christopher!
Generated documentation improvements
When publishing a package to Hex, the BEAM ecosystem package repository, the Gleam build tool will generate and upload HTML documentation for the code.
When generating documentation, the build tool now prints type variable using the same names as were used in the source code, making it easier to understand what these type parameters are. For example, previously this function would have been rendered like this:
pub fn from_list(entries: List(#(a, b))) -> Dict(a, b)
But now is rendered as the following:
pub fn from_list(entries: List(#(key, value))) -> Dict(key, value)
Another area of the documentation that has been improved is how types imported from other modules are displayed. These types are now displayed with their module qualifiers, and hovering over them shows the full module name. For example, this code:
import gleam/dynamic/decode
pub fn something_decoder() -> decode.Decoder(Something) {
...
}
Will now generate the following documentation:
pub fn something_decoder() -> decode.Decoder(Something)
Hovering over the decode.Decoder
text will show the following:
gleam/dynamic/decode.{type Decoder}
Clicking on decode.Decoder
will take you to the documentation for that type.
Thank you Surya Rose!
Yet more fault tolerance
Gleam's compiler implements fault tolerant analysis. This means that when there is some error in the code that means it is invalid and cannot be compiled, the compiler can still continue to analyse the code to the best of its ability, ignoring the invalid parts. Because of this Gleam language server can have a good understanding of the code and provide IDE feature even when the codebase is in an invalid state.
This release makes the analysis of lists, tuples, negation operators, panic
,
echo
and todo
, function parameters, and function labels fault tolerant.
We're covering all the last remaining little case to make the language server
information as fresh and accurate as possible!
Thank you Giacomo Cavalieri and Surya Rose!
Labels in inexhaustive case expression errors
Gleam has exhaustiveness checking. This means that pattern matching flow control must handle all the possible values that the type being matched on could be. If there are any clauses missing then the program is incomplete, and the compiler will return a helpful error showing the missing patterns.
This error has been improved to include record field labels, as can be seen at the bottom of this example:
Inexhaustive patterns: Unused value
┌─ /src/main.gleam:6:3
│
6 │ ╭ case person {
8 │ │ Teacher(name:) -> io.println("Good morning!")
7 │ │ Student(name: "Samara", age: 27) -> io.println("Hello Samara!")
9 │ │ }
│ ╰───^
This case expression does not have a pattern for all possible values. If it
is run on one of the values without a pattern then it will crash.
The missing patterns are:
Student(name:, age:)
This improvement has also upgraded the code action to add missing patterns to a
case
expression, now when the missing clauses are added to the code they will
include record labels.
Thank you Surya Rose!
Fill labels code action for patterns
The language server has a code action for filling in possible labels for a function or record. This can be a convenient time saver when writing code, especially if you can't immediately remember what labels the arguments use.
This code action has been upgraded to also work with records in patterns. In
this code the Person
record pattern is missing two of its fields, so running
the code action will add them for you.
pub type Person {
Person(name: String, age: Int, job: String)
}
pub fn age(person: Person) {
- let Person(age:) = person
+ let Person(age:, name:, job:) = person
age
}
Thank you Surya Rose!
Bit array truncation warning
The compiler now raises a warning when it can tell that an int segment with a literal value is going to be truncated. This will help folks understand a behaviour that may be unexpected.
warning: Truncated bit array segment
┌─ /src/main.gleam:4:5
│
4 │ <<258>>
│ ^^^ You can safely replace this with 2
This segment is 1 byte long, but 258 doesn't fit in that many bytes. It
would be truncated by taking its first byte, resulting in the value 2.
Thank you Giacomo Cavalieri!
Better language server support for constants
Gleam's language server has historically been missing hover, autocompletion, and go-to definition within constants. Surya Rose has corrected this by implementing these features. Thank you Surya!
Generate function code action improvements
Gleam's language server has a code action for generating the outline of a function that is used in the code but does not yet exist.
It has been upgraded to now choose better argument names based on the labels
and variables used. For example, if the code action is run on the
not-yet-defined function named remove
:
pub fn main() -> List(Int) {
let list = [1, 2, 3]
let number = 1
remove(each: number, in: list)
//^^^^^^ This function doesn't exist yet!
}
The language server will then generate the outline of the missing function, and the code will look like this:
pub fn main() -> List(Int) {
let list = [1, 2, 3]
let number = 1
remove(each: number, in: list)
}
fn remove(each number: Int, in list: List(Int)) -> List(Int) {
todo
}
Thank you Giacomo Cavalieri!
Generate variant code action
The language server now provides a code action to automatically generate a new custom type variant, similar to the generate function code action.
In this example the UserPressedButton
variant does not exist, but the
compiler can tell from the way that it is used that if it did exist it would be
a variant of the Msg
custom type.
pub type Msg {
ServerSentResponse(Json)
}
pub fn view() -> Element(Msg) {
div([], [
button([on_click(UserPressedButton)], [text("Press me!")])
// ^^^^^^^^^^^^^^^^^ This doesn't exist yet!
])
}
Triggering the code action on the UserPressedButton
will add it to the Msg
type:
pub type Msg {
ServerSentResponse(Json)
+ UserPressedButton(String)
}
The code action understood the code well enough to know that this new variant
holds a string value, as that is what the on_click
function does with it in
this example. If the variant was used with labels then the labels would be
included in the definition also.
Thank you Giacomo Cavalieri! Another excellent code action for "top-down" style programmers.
Remove unused imports code action improvements
For a long time the Gleam language server has included a code action for removing unused imports, but it wouldn't work as well as desired for imports that include unqualified types and values: they would still remain after running the action.
import a_module.{type Unused, unused, used}
pub fn main() {
used
}
Triggering the code action will remove all unused types and values:
import a_module.{used}
pub fn main() {
used
}
Thank you Giacomo Cavalieri!
Windows ARM binaries
We provide precompiled executables for each Gleam release, supporting Windows, macOS, and Linux. Gleam users and package management systems can download and use these executables instead of compiling the Gleam project from scratch, which takes a long time.
Jonatan Männchen has added an ARM64 Windows build. This is useful as ARM based development machines are becoming more and more common. Thank you Jonatan!
And the rest
And thank you to the bug fixers and experience polishers: Ariel Parker, Giacomo Cavalieri, Louis Pilfold, Mathieu Darse, Matias Carlander, Samuel Cristobal, and Surya Rose.
For full details of the many fixes and improvements they've implemented see the changelog.
A call for support
Gleam is not owned by a corporation; instead it is entirely supported by sponsors, most of which contribute between $5 and $20 USD per month, and Gleam is my sole source of income.
We have made great progress towards our goal of being able to appropriately pay the core team members, but we still have further to go. Please consider supporting the project or core team members Giacomo Cavalieri and Surya Rose on GitHub Sponsors.
Thank you to all our sponsors! And especially our top sponsor: Lambda.
- Aaron Gunderson
- Abel Jimenez
- ad-ops
- Adam Brodzinski
- Adam Johnston
- Adam Wyłuda
- Adi Iyengar
- Adrian Mouat
- Ajit Krishna
- Aleksei Gurianov
- Alembic
- Alex Houseago
- Alex Manning
- Alex Viscreanu
- Alexander Koutmos
- Alexander Stensrud
- Alexandre Del Vecchio
- Ameen Radwan
- Andrea Bueide
- AndreHogberg
- Antharuu
- Anthony Khong
- Anthony Maxwell
- Anthony Scotti
- Arthur Weagel
- Arya Irani
- Azure Flash
- Barry Moore
- Bartek Górny
- Ben Martin
- Ben Marx
- Ben Myles
- Benjamin Kane
- Benjamin Moss
- bgw
- Bjarte Aarmo Lund
- Bjoern Paschen
- Brad Mehder
- Brett Cannon
- Brett Kolodny
- Brian Dawn
- Brian Glusman
- Bruce Williams
- Bruno Michel
- bucsi
- Cam Ray
- Cameron Presley
- Carlo Munguia
- Carlos Saltos
- Chad Selph
- Charlie Duong
- Charlie Govea
- Chew Choon Keat
- Chris Donnelly
- Chris King
- Chris Lloyd
- Chris Ohk
- Chris Rybicki
- Chris Vincent
- Christopher David Shirk
- Christopher De Vries
- Christopher Dieringer
- Christopher Jung
- Christopher Keele
- CJ Salem
- Clifford Anderson
- Coder
- Cole Lawrence
- Colin
- Comamoca
- Comet
- Constantin (Cleo) Winkler
- Corentin J.
- Daigo Shitara
- Damir Vandic
- Dan
- Dan Dresselhaus
- Dan Strong
- Danielle Maywood
- Danny Arnold
- Danny Martini
- David Bernheisel
- David Cornu
- Dennis Dang
- dennistruemper
- devinalvaro
- Diemo Gebhardt
- DoctorCobweb
- Donnie Flood
- Dylan Anthony
- Dylan Carlson
- Ed Hinrichsen
- Edon Gashi
- Eileen Noonan
- eli
- elke
- Emma
- EMR Technical Solutions
- Endo Shogo
- Eric Koslow
- Erik Terpstra
- erikareads
- ErikML
- erlend-axelsson
- Ernesto Malave
- Ethan Olpin
- Evaldo Bratti
- Evan Johnson
- evanasse
- Fabrizio Damicelli
- Fede Esteban
- Felix
- Fernando Farias
- Filip Figiel
- Florian Kraft
- Francis Hamel
- frankwang
- G-J van Rooyen
- Gabriel Vincent
- gamachexx
- Gavin Panella
- Geir Arne Hjelle
- Georg Hartmann
- George
- Georgi Martsenkov
- ggobbe
- Giacomo Cavalieri
- Giovanni Kock Bonetti
- Graham Vasquez
- Grant Everett
- Guilherme de Maio
- Guillaume Heu
- Guillaume Hivert
- Hammad Javed
- Hannes Nevalainen
- Hannes Schnaitter
- Hans Raaf
- Hayleigh Thompson
- Hazel Bachrach
- Henning Dahlheim
- Henrik Tudborg
- Henry Warren
- Heyang Zhou
- Hubert Małkowski
- Iain H
- Ian González
- Ian M. Jones
- Igor Montagner
- inoas
- Isaac
- Isaac Harris-Holt
- Isaac McQueen
- István Bozsó
- Ivar Vong
- Jacob Lamb
- Jake Cleary
- Jake Wood
- Jakob Ladegaard Møller
- James Birtles
- James MacAulay
- Jan Pieper
- Jan Skriver Sørensen
- Jean Niklas L'orange
- Jean-Adrien Ducastaing
- Jean-Luc Geering
- Jean-Marc QUERE
- Jen Stehlik
- Jerred Shepherd
- jiangplus
- Jimpjorps™
- Joey Kilpatrick
- Joey Trapp
- Johan Strand
- John Björk
- John Pavlick
- John Strunk
- Jojor
- Jon Lambert
- Jonas E. P
- Jonas Hedman Engström
- jooaf
- Joseph Lozano
- Joshua Steele
- Julian Hirn
- Julian Lukwata
- Julian Schurhammer
- Justin Lubin
- Jérôme Schaeffer
- KamilaP
- Kemp Brinson
- Kero van Gelder
- Kevin Schweikert
- Kramer Hampton
- Kritsada Sunthornwutthikrai
- Krzysztof Gasienica-Bednarz
- Leah Ulmschneider
- Leandro Ostera
- Lee Jarvis
- Lennon Day-Reynolds
- Leon Qadirie
- Leonardo Donelli
- Lexx
- lidashuang
- Lily Rose
- Lucas Pellegrinelli
- Lukas Bjarre
- Luke Amdor
- Luna
- Manuel Rubio
- Marcos
- marcusandre
- Mariano Uvalle
- Marius Kalvø
- Mark Dodwell
- Mark Holmes
- Mark Markaryan
- Martin Janiczek
- Martin Poelstra
- Martin Rechsteiner
- martonkaufmann
- Mat Warger
- Matt Champagne
- Matt Heise
- Matt Mullenweg
- Matt Robinson
- Matt Savoia
- Matt Van Horn
- Matthew Jackson
- Matthew Whitworth
- Max McDonnell
- metame
- METATEXX GmbH
- Metin Emiroğlu
- Michael Duffy
- Michael Jones
- Michael Mazurczak
- Michael McClintock
- Mikael Karlsson
- Mike Roach
- Mikey J
- MoeDev
- MzRyuKa
- n8n - Workflow Automation
- Natanael Sirqueira
- Nathaniel Knight
- NFIBrokerage
- Nick Chapman
- Nick Reynolds
- Nicklas Sindlev Andersen
- NicoVIII
- Niket Shah
- Nikolai Steen Kjosnes
- Ninaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
- NineFX
- Nomio
- Ocean
- Olaf Sebelin
- OldhamMade
- Oliver Medhurst
- Oliver Tosky
- ollie
- optizio
- Patrick Wheeler
- Paul Guse
- Pedro Correa
- Pete Jodo
- Peter Rice
- Philpax
- Pierrot
- Qdentity
- Race Williams
- Rasmus
- Raúl Chouza
- re.natillas
- Redmar Kerkhoff
- Reilly Tucker Siemens
- Renato Massaro
- Renovator
- Richard Viney
- Rico Leuthold
- Rintaro Okamura
- Ripta Pasay
- Robert Attard
- Robert Ellen
- Robert Malko
- Rodrigo Álvarez
- Ronan Harris
- Rotabull
- Rupus Reinefjord
- Ruslan Ustitc
- Sam Aaron
- Sam Zanca
- sambit
- Sammy Isseyegh
- Savva
- Saša Jurić
- Scott Trinh
- Scott Wey
- Scott Zhu Reeves
- Sean Cribbs
- Sean Jensen-Grey
- Sean Roberts
- Sebastian Porto
- Seve Salazar
- Shane Poppleton
- Shuqian Hon
- Sigma
- simone
- Stefan
- Stefan Hagen
- Steinar Eliassen
- Stephen Belanger
- Strandinator
- Sławomir Ehlert
- Theo Harris
- Thomas
- Thomas Coopman
- Thomas Ernst
- Tim Brown
- Timo Sulg
- Tom Schuster
- Tomasz Kowal
- tommaisey
- Tristan de Cacqueray
- Tristan Sloughter
- Tudor Luca
- tymak
- Valerio Viperino
- Vassiliy Kuzenkov
- Vic Valenzuela
- Victor Rodrigues
- Viv Verner
- Volker Rabe
- Walton Hoops
- Weizheng Liu
- Willyboar
- Wilson Silva
- Xucong Zhan
- Yamen Sader
- Yasuo Higano
- yoshi~
- Zsombor Gasparin
- ZWubs
- ~1847917
- ~1867501
- Éber Freitas Dias