The Gleam Tour is helpful.
import
golfs
The order of top-level statements doesn't matter. Hence, if a top-level statement ends in }
, it shouldn't be the last one (unless all do), otherwise you waste a byte:
import gleam/io pub fn main(){}pub fn main(){}import gleam/io
If you're using a module enough times, it can save to use as
:
int.a int.b int.c import gleam/inti.a i.b i.c import gleam/int as i
If you are using one or more functions from a module enough times, use an unqualified import (the module itself is still imported):
l.map l.map import gleam/list as lmap map import gleam/list.{map}l.map l.map l.min l.min import gleam/list as lmap map min min import gleam/list.{map,min}
as
can also be used within the {}
:
drop drop import gleam/list.{drop,map}d d import gleam/list.{drop as d,map}
You can both use an unqualified import and alias the module name (the alias takes 4 bytes instead of 5 in this case):
l.drop l.min map map import gleam/list.{map}as l
Looping
range
+map
Sometimes can be too long
list.map(list.range(1,100),fn(x){...})
fold
This method can be better than map
under certain circumstances, be still needs the list
import
list.fold(list.range(1,100),start,fn(acc,x){...;new_x})
fn
A recursive function would work well in many scenarios because you can just avoid the list
import altogether, this is usually the best way to loop
pub fn main(){f(100,100)}fn f(a,b){io.println(...)cond&&f(a*2,b/2)}
You can also use ||
instead of &&
if !cond
ends up shorter than cond
.
case
Generally it is better to avoid case
, but if you have to, and you know the possible values of your condition:
case a%20!=2{True->a _->0}case a%20{2->0 _->a}
Printing
Newlines within string literals are allowed, hence it might be possible to save a byte by using print
instead of println
and writing the newline out manually.
Sometimes you have to print a value if a condition cond
is satisfied, and, in such a case, you might be inclined to use case
; however, remember that print
and println
return Nil
, and Nil==Nil
, hence you can do one of these:
cond&&Nil!=io.println(str)!cond||Nil==io.println(str)
Nil
should be on the left side of the ==
, to save a space. The first version is always False
, and the second one is always True
(also consider if !cond
is shorter than cond
). If you want the expression's value to depend on cond
, change between ==
and !=
.
Unwrapping Result
s
Result types can be useful for production code, but they're near useless for code golf, since they almost always end up as successes. gleam_stdlib
provides unwrap
in gleam/result
, which returns the content of the Result
if it's Ok(...)
, and a default value if it's Error(...)
. For instance, unwrap(int.parse(str),0)
parses str
to an Int
, and returns 0
if str
doesn't have a valid integer.
However, to use it, you unfortunately have to include import gleam/result
in your code. Luckily, there is a shorter alternative, to just do the job manually, if you don't somehow need another function from gleam/result
(you might have to change the 0
to a value of the correct type):
result.unwrap(r,0)import gleam/resultcase r{Ok(x)->x _->0}
If you'd have to use unwrap
multiple times, making a new function is still cheaper:
u(q,0)u(r,0)import gleam/result.{unwrap as u}u(q)u(r)fn u(x){case x{Ok(x)->x _->0}}
If you have to handle different types, then you'll have to provide a default value, but literally reinventing unwrap
still saves:
u(q,0)u(r,"")import gleam/result.{unwrap as u}u(q,0)u(r,"")fn u(x,y){case x{Ok(x)->x _->y}}
ASCII value
To get the ASCII value of a character
let assert[a]=string.to_utf_codepoints("h")string.utf_codepoint_to_int(a)
Misc tips
case a{b->0 _->1}
->case a{b->0a->1}
string.to_graphemes(str)
->string.split(str,"")
list.each
->list.map
string.drop_start
->string.drop_left
string.pad_start
->string.pad_left
string.trim_start
->string.trim_left