![]() |
VOOZH | about |
We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.
Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.
Follow TNS on your favorite social media networks.
Become a TNS follower on LinkedIn.
Check out the latest featured and trending stories while you wait for your first TNS newsletter.
import gleam/io
pub fn main() {
io.println("hello world!")
}
> brew install gleam
[dependencies] gleam_stdlib = ">= 0.34.0 and < 2.0.0"
import argv
import envoy
import gleam/io
import gleam/result
pub fn main() {
case argv.load().arguments {
["get", name] -> get(name)
_ -> io.println("Usage: get <name>")
}
}
fn get(name: String) -> Nil {
let value = envoy.get(name) |> result.unwrap("")
io.println(format_pair(name, value))
}
fn format_pair(name: String, value: String) -> String {
name <> "=" <> value
}
main entry point, we have two functions. They use exactly the same format as we saw in Virgil. It turns out that type annotations are optional, but considered good practice. Now, we get a bit functional. The argv load does what you expect, and pulls in a list of hopefully exactly two strings — with the first string equal to “get”. This is used in a case statement.
As a quick aside, the Gleam case is a little more flexible than in most non-functional languages. Here we see a lists’ contents being compared:
let result = case x {
[] -> "Empty list"
[1] -> "List of just 1"
[4, ..] -> "List starting with 4"
[_, _] -> "List of 2 elements"
_ -> "Some other list"
}
_ represents a default, and the possible cases are exhaustively checked.
Going back to our environment variable reading code, if the pattern isn’t a list of two strings, then the helper text is spat out. Otherwise, it calls the get function.
We see the pipe function, which just helps to make long functional calls a little more readable from left to right.
let value = envoy.get(name) |> result.unwrap("")
let value = result.unwrap(envoy.get(name),"")
name <> "=" <> value
null, no implicit conversions, and no exceptions. So if it compiles, you are good. Also, there is no numerical operator overloading, so the code for adding integers is different to that for adding floats:
io.debug(1 + 1) //ints io.debug(1.0 +. 1.5) //floats
case statement.
We get custom types, which we pattern match over. So we are part of the way there:
pub type Season {
Spring
Summer
Autumn
Winter
}
fn weather(season: Season) -> String {
case season {
Spring -> "Mild"
Summer -> "Hot"
Autumn -> "Windy"
Winter -> "Cold"
}
}
import gleam/io
pub type Travel {
Walk(hours: Int)
Cycle(hours: Int)
Drive(hours: Int, speed: Int)
}
pub fn main() {
let walking = Walk(1)
let cycling = Cycle(1)
let bus_trip = Drive(2, 50)
let trip = [walking, cycling, bus_trip]
io.debug(trip)
}
// [Walk(hours: 1), Cycle(hours: 1), Drive(hours: 2, speed: 50)]
I don’t think I can associate a method inside a type, but I can access the record values to get a similar result as we got in Virgil. I’ll leave this as an exercise for a more fluent user!
For someone like me who doesn’t work with functional code much, Gleam is very approachable and doesn’t immediately confront me with terminology like “currying” and other functional shocks. But it should be a good way to get you to appreciate the immutable advantages of programming if you are not already an advocate.