Gleam
- File size
- 10.7KB
- Lines of code
- 270
Gleam
Functional language that transpiles to BEAM (Erlang's Virtual Machine) bytecode to build scalable, maintainable systems.
Comments
// ----- COMMENT -----
// this is a single-line comment
/*
this is a
multi-line comment
in Gleam
*/
Printing
// ----- PRINTING -----
// io.print() => receives a string argument that it then prints to the stdout without a newline being included
// io.println() => receives a string argument that it then prints to the stdout, automatically including a newline
io.print("this does not include a newline and one must be explicitly specified if desired\n")
io.println("this automatically includes a newline")
Quickstart
// ----- QUICKSTART -----
// strong statically-typed language
// emphasizes safety, performance and Erlang's concurrency model
// all execution code within your Gleam file runs from the main function fn main(), similar to all other C-style languages
// notably differing from C-style traditions, Gleam is not a semicolon-delimited language
// import => brings the required libraries into the local scope of the present Gleam file, note that Gleam has full access to all existing Erlang libraries and frameworks
// : => declares the datatype of a given constant and variable, allowing for type declaration
// let => declares a variable with a mutable value that can be reassigned after declaration and initialisation
// const => declares a constant with an immutable value that cannot be reassigned after declaration and initialisation
import gleam/io
pub fn main() { // main function
let name = "gooked" // string variable
const AGE: Int = 30 // integer constant
io.println("hello " ++ name ++ " and welcome to the world from a " ++ to_string(AGE) ++ " years old Gleam program")
}
Types
// ----- TYPE -----
// Int => stores signed and unsigned integer number values
// Float => stores signed and unsigned floating point number values
// Bool => true, false
// Atom => stores a constant value identified by its name where atoms are declared with a : colon prefacing the atom value, the equivalent of atoms in Elixir, symbols in Ruby and keywords in Common Lisp and Clojure
// String => stores a string value declared within "" double quotation marks, note that characters are handled as strings in Gleam
// BitString => stores a sequence of bits or bytes mostly used to store binary data, declared within <<>> double angle brackets
Operators
// ----- OPERATOR -----
// --- ARITHMETIC OPERATOR ---
+ // addition
- // subtraction
* // multiplication
/ // division
% // modulo
^ // exponentiation
// --- COMPARISON OPERATOR ---
== // complete equality check for both value and type
!= // complete inequality check for both value and type
> // comparison operator
< // comparison operator
>= // comparison operator
<= // comparison operator
// --- LOGICAL OPERATOR ---
&& // logical and
|| // logical or
! // logical not
Control structures
// ----- CONTROL STRUCTURE -----
// --- CONDITIONALS ---
// IF ELSE IF ELSE
let x = 10
if x < 0 {
io.println("x is negative")
} else if x == 0 {
io.println("x is zero")
} else {
io.println("x is positive")
}
// CASE -> _
// provides a degree of pattern-matching in Gleam similar to languages like Rust, the equivalent of switch case and match case constructs in other languages
// heavily used in Gleam for completeness and literate, safe programming
// -> => specifies the relationship between a given predicate case condition and the logic that should execute if that condition is met
// _ => specifies the logic for a default fall-through case where all other predicate case conditions are left unmet
let x = 3
case x {
1 -> io.println("One")
2 -> io.println("Two")
3 -> io.println("Three")
_ -> io.println("Other")
}
// --- LOOPS ---
// since Gleam is a functional language, it carries over many hallmarks of the functional paradigm, including the absence of conventional loop constructs
// instead, user-defined higher-order functions (and occasionally recursion) are used for traversal and iteration over iterable data structures
// HIGHER ORDER FUNCTIONS
// the below are one way to implement some standard higher-order functions, note the express use of case -> _ constructs
// map => applies a specified function to each element of the iterable structure and returns the transformed structure
// foreach => applies a specified function to each element of the iterable structure in place in memory and does not return anything
// filter => filters each element of an iterable structure based off a specified predicate function
// reduce => reduces an iterable structure to a single value using a specified accumulator function by folding to the left
// foldr => reduces an iterable structure to a single value using a specified accumulator function by folding to the right
pub fn map_list(lst: List(Int), f: fn(Int) -> Int) -> List(Int) {
case lst {
[] -> []
[head | tail] -> [f(head) | map_list(tail, f)]
}
}
pub fn for_each(lst: List(Int), f: fn(Int) -> ()) {
case lst {
[] -> ()
[head | tail] -> {
f(head)
for_each(tail, f)
}
}
}
pub fn filter_list(lst: List(Int), predicate: fn(Int) -> Bool) -> List(Int) {
case lst {
[] -> []
[head | tail] -> if predicate(head) { [head | filter_list(tail, predicate)] } else { filter_list(tail, predicate) }
}
}
pub fn reduce_list(lst: List(Int), f: fn(Int, Int) -> Int, initial: Int) -> Int {
case lst {
[] -> initial
[head | tail] -> reduce_list(tail, f, f(initial, head))
}
}
pub fn foldr_list(lst: List(Int), f: fn(Int, Int) -> Int, initial: Int) -> Int {
case lst {
[] -> initial
[head | tail] -> f(head, foldr_list(tail, f, initial))
}
}
// RECURSION
// Gleam also allows for recursion to allow for more complex iteration over iterable structures
pub fn factorial(n: Int) -> Int {
case n {
0 -> 1 // base case
_ -> n * factorial(n - 1) // recursive case
}
}
Data structures
// ----- DATA STRUCTURE -----
// Tuple => fixed-size ordered collection of elements of multiple datatypes declared within () round brackets
// List => dynamically-sized ordered collection of elements of the same datatype declared within [] straight brackets
// Map => unordered collection of key-value pairs declared within %{} percentage sign and curly braces, the equivalent of dictionaries in Python and tables in Lua and PHP
// Type => user-defined collection of comma-delimited named fields and their datatypes declared within {} curly braces, allowing for modelling of representative data in your Gleam program through type aliases, the equivalent of structs in Go and Rust
let anExampleTuple: (String, Int) = ("Alice", 30)
let anExampleList: List(Int) = [1, 2, 3, 4, 5]
let anExampleMap: Map(String, String) = %{ "red" => "#FF0000", "green" => "#00FF00", "blue" => "#0000FF" }
type anExampleRecord = {
name: String,
age: Int
}
type coordinate = {
X: String,
Y: String
}
Functions
// ----- FUNCTION -----
// similar to other functional languages, Gleam features implicit return of the last expression within a function, there is no explicit return keyword used traditionally in Gleam
// fn <functionName> ( <functionParameter(s)> : <functionParameterDatatype(s)> ) -> {returnDatatype(s)} { <functionBodyDefinition> } => declaration and definition of a named function
// fn ( <functonParameter(s)> : <functionParameterDatatype(s)> ) -> <returnDatatype(s)> { <functionBodyDefinition> } => declaration and definition of an anonymous function that is normally assigned to a named variable as seen below
fn greet(name: String) { // a named void function
io.println("Hello, " ++ name ++ "!")
}
greet("Alice")
fn square(x: Int) -> Int { // a named integer function
x * x // implicit return of the last expression in the function
}
let double = fn(x: Int) -> Int { x * 2 } // an anonymous function