Print a string followed by a newline.
IO.puts("Hello, World!")
Print a value without a newline.
Print a debug representation of any value. Returns the value unchanged (useful in pipes).
list
|> IO.inspect()
|> Enum.map() do |x| x * 2 end
String.upcase("hello") # => "HELLO"
String.downcase("WORLD") # => "world"
Remove leading and trailing whitespace.
Return the number of characters.
Split a string into a list.
String.split("a,b,c", ",") # => ["a", "b", "c"]
String.contains?("hello world", "world") # => true
Replace all occurrences.
String.replace("foo bar foo", "foo", "baz") # => "baz bar baz"
String.starts_with?("hello", "he") # => true
String.ends_with?("hello", "lo") # => true
String.slice("hello world", 6, 5) # => "world"
Parse strings to numbers.
All Enum functions take a list as the first argument and a block/function as the last.
Transform each element.
Enum.map([1, 2, 3]) do |x| x * 2 end
# => [2, 4, 6]
Keep elements where predicate is truthy.
Enum.filter([1, 2, 3, 4]) do |x| x > 2 end
# => [3, 4]
Fold a list into a single value.
Enum.reduce([1, 2, 3, 4, 5], 0) do |x, acc| x + acc end
# => 15
Iterate for side effects. Returns :ok.
Enum.each(names) do |name|
IO.puts("Hello, " <> name)
end
Return {:ok, element} for the first match, or :not_found.
Check if any/all elements match a predicate.
Return the number of elements.
Sort a list, optionally with a comparator.
Reverse a list.
Join list elements into a string.
Enum.join(["a", "b", "c"], ", ") # => "a, b, c"
Map then flatten one level.
Return the first/last element, or :not_found for empty lists.
Return the number of elements.
Reverse the list.
Flatten nested lists one level deep.
Concatenate two lists.
Check if an element is in the list.
Merge two maps. Keys in map2 override map1.
Map.merge(%{a: 1}, %{b: 2}) # => %{a: 1, b: 2}
Get a value by key.
Return a new map with the key set.
Return all keys or values as a list.
Check if a key exists.
Return a new map with the key removed.
Read an environment variable. Returns the value as a string, or nil if not set.
port = System.get_env("PORT")
# => "4000" or nil
Read with a default value.
port = System.get_env("PORT", "3000")
Set an environment variable.
System.put_env("DEBUG", "true")
Generate a random UUID v4 string.
id = UUID.v4()
# => "550e8400-e29b-41d4-a716-446655440000"
Returns the current Unix timestamp in seconds.
now = DateTime.now()
# => 1711540800
Convert a Unix timestamp to an ISO 8601 string.
DateTime.to_iso8601(1704067200)
# => "2024-01-01T00:00:00Z"
Parse an ISO 8601 string to a Unix timestamp.
{:ok, ts} = DateTime.from_iso8601("2024-01-01T00:00:00Z")
# ts => 1704067200
Returns the difference in seconds between two timestamps.
diff = DateTime.diff(later, earlier)
# => 3600 (1 hour)
Format a timestamp using strftime-style directives (%Y, %m, %d, %H, %M, %S).
DateTime.format(ts, "%Y-%m-%d")
# => "2024-01-01"
DateTime.format(ts, "%Y-%m-%d %H:%M:%S")
# => "2024-01-01 00:00:00"
Structured JSON logging to stderr. Each log line includes a timestamp, level, message, and optional metadata.
Logger.info("user created")
Logger.info("user created", %{user_id: 42})
Output:
{"level":"info","msg":"user created","user_id":42,"ts":"2026-03-27T12:00:00Z"}Logger.warn("slow query", %{duration_ms: 450})
Logger.error("db connection failed", %{reason: "timeout"})
Logger.debug("checkpoint", %{step: 3})
Hash data with the given algorithm. Returns a hex-encoded binary.
Supported algorithms: :sha256, :sha384, :sha512, :sha, :md5.
hash = Crypto.hash(:sha256, "hello")
# => "2cf24dba5fb0a30e26e83b2ac5b9e29e..."
Compute an HMAC. Returns a hex-encoded binary.
hmac = Crypto.hmac(:sha256, "secret", "data")
Generate n cryptographically secure random bytes.
token = Crypto.random_bytes(32)
Base64 encode and decode.
encoded = Crypto.base64_encode(token)
decoded = Crypto.base64_decode(encoded)
Encode a map, list, or value to a JSON binary string. Atom keys are converted to strings.
JSON.encode(%{name: "Alice", age: 30})
# => "{\"name\":\"Alice\",\"age\":30}"
Decode a JSON binary string to a map with atom keys.
data = JSON.decode("{\"name\":\"Bob\",\"count\":5}")
data.name # => "Bob"
data.count # => 5
These are available as bare function calls anywhere in Winn code:
to_string(42) # => "42"
to_string(:hello) # => "hello"
to_integer("123") # => 123
to_float(5) # => 5.0
to_atom("hello") # => :hello
inspect({:ok, 42}) # => "{ok,42}"
Also available via module prefix:
String.to_integer(str)— parse integerString.to_float(str)— parse float
Assert that expr is true. Raises an assertion error on false.
assert(1 + 1 == 2)
Assert that two values are strictly equal (=:=). On failure, shows the expected and actual values.
assert_equal("hello", String.downcase("HELLO"))
Marks a module as a test module. Test functions must be named test_* with zero arguments.
module UserTest
use Winn.Test
def test_greeting()
result = "Hello, " <> "Alice"
assert_equal("Hello, Alice", result)
end
end
Run with winn test. See CLI Reference for details.