# One-Liners
A cookbook of idiomatic Deft one-liners. Each recipe shows the
preferred modern form. Use these as a reference when scripting.
## Process and Shell
# Capture stdout of a command def files ls -la # Run a subprocess and check exit def r [os/run "git" "status"] if ($r~exit == 0) { echo "clean" } # Run a shell-style pipeline def lines [os/shell "find . -name '*.dft' | wc -l"] # Get the script's own filename def argv [os/args] def script-name $argv(first) # Iterate shell output lines for line ps aux(lines) { echo $line } # Iterate shell output words for word ls(words) { echo $word }
## Files
# Read whole file as string def text [fs/read "config.json"] # Read lines into a list def lines [fs/read-lines "log.txt"] # Write a file fs/write "out.txt" $content # Append to a file fs/append "log.txt" "newline\n" # Check existence if [fs/exists? "config.json"] { ... } # List directory entries for entry [fs/list "."] { echo $entry~name } # Glob recursively for path [fs/glob "src/**/*.dft"] { echo $path } # Stat a file def info [fs/stat "file.dft"] echo $info~size echo $info~mtime # Make a directory fs/mkdir "build/out" # Path manipulation fs/join "a" "b" "c.dft" # => "a/b/c.dft" fs/base "/path/to/file.dft" # => "file.dft" fs/dir "/path/to/file.dft" # => "/path/to" fs/ext "file.dft" # => "dft" # Temp paths def tmp [fs/tmp-path ".json"] # /tmp/abc123.json
## Strings
# Length "hello"(len) # => 5 # Upper / lower "hello"(upper) # => HELLO "WORLD"(lower) # => world # Trim " hi "(trim) # => "hi" # Split and join "a,b,c"(split ",") # => @{a b c} @{a b c}(join "|") # => "a|b|c" # Replace "hello world"(replace "o" "0") # => "hell0 w0rld" # Test prefix / suffix / substring "hello"(starts-with? "he") # => true "hello"(ends-with? "lo") # => true "hello"(contains "ell") # => true # Substring "hello"(0 .. 3) # => "hel" "hello"(nth 1) # => "e" # Pad "5"(pad-left 3 "0") # => "005" # Printf-style formatting [format "%d times %#x is %e" 10 10 100] # => "10 times 0xa is 1.000000e+02" [format "%05.2f" 3.14] # => "03.14" # Lines / words "a\nb\nc"(lines) # => @{a b c} "a b c"(words) # => @{a b c} # Iterate chars for ch in "abc" { echo $ch }
## Numbers and Math
# Arithmetic (1 + 2) ((3 * 4) - 5) (10 mod 3) # => 1 # Comparison ($a < $b) ($x == 0) # Rounding (3.7)(floor) # => 3 (3.2)(ceil) # => 4 (3.5)(round) # => 4 # Min / max / clamp [min 3 7] # => 3 [max 3 7] # => 7 [clamp 15 0 10] # => 10 # Absolute value [abs -5] # => 5 # Specialised math [math/sqrt 16] # => 4 [math/pow 2 10] # => 1024 [math/sin [math/pi]] [math/sum @{1 2 3 4}] # => 10 [math/avg @{10 20 30}] # => 20 # Random [random] # => 0..max-int [random 100] # => 0..99 [math/random-range 10 20] # => 10..19
## Lists and Sequences
# Length / edges @{1 2 3}(len) # => 3 @{1 2 3}(first) # => 1 @{1 2 3}(last) # => 3 # Membership 3 in? @{1 2 3} # => true [in? @{1 2 3} 3] # => true (prefix form) # Slice @{1 2 3 4 5}(slice 1 3) # => @{2 3} # Reverse / sort / unique @{3 1 2}(sort) # => @{1 2 3} @{3 1 2}(reverse) # => @{2 1 3} @{1 1 2 3 3}(unique) # => @{1 2 3} # Append (mutating local) def xs @{} $xs << 1 $xs << 2 # xs is now @{1 2} # Append (pure) set ys [append $xs 3] # ys is @{1 2 3}, xs unchanged # Pipelines @{1 2 3 4 5} |> filter even? |> map { $it * 2 } |> collect # => @{4 8} # Reduce @{1 2 3 4 5} |> reduce 0 { ($acc + $it) } # => 15 # Find first match @{1 2 3 4} |> find { ($it > 2) } # => 3 # Existence @{1 2 3} |> any? { ($it > 2) } # => true @{1 2 3} |> all? { ($it > 0) } # => true # Group @{1 2 3 4} |> group { ($it % 2) == 0 } # => %{ :true @{2 4} :false @{1 3} } # Range [range 0 5] # => @{0 1 2 3 4} [range 0 10 2] # => @{0 2 4 6 8}
## Maps
# Construction def m %{ :a 1 :b 2 :c 3 } # Lookup $m~a # => 1 [get $m :a] # => 1 [get $m :missing 0] # => 0 (default) $m(:a) # => 1 (IFn form) # Add / remove [assoc $m :d 4] # => %{ :a 1 :b 2 :c 3 :d 4 } [dissoc $m :a] # => %{ :b 2 :c 3 } # Merge [merge %{ :a 1 } %{ :a 2 :b 3 }] # => %{ :a 2 :b 3 } # Keys / values / entries [keys $m] # => ^{:a :b :c} [values $m] # => @{1 2 3} [entries $m] # => @{ @{:a 1} @{:b 2} @{:c 3} } # Iterate for entry [entries $m] { echo "$entry~0 = $entry~1" } $m |> each { echo "$it~0 = $it~1" } # Nested assoc [assoc-in %{ :user %{} } @{ :user :name } "Alice"] # Nested lookup [get-in $user @{ :profile :name }] # => value, or nil if missing [get-in $user @{ :profile :age } :unknown] # => :unknown if missing
## Sets
def roles ^{:admin :user :guest} # Membership :admin in? $roles # => true # Add ($roles << :owner) # => ^{:admin :user :guest :owner} # Set ops [union ^{1 2} ^{2 3}] # => ^{1 2 3} [intersection ^{1 2 3} ^{2 3 4}] # => ^{2 3} [difference ^{1 2 3} ^{2 3 4}] # => ^{1} # Relations [subset? ^{1 2} ^{1 2 3}] # => true [superset? ^{1 2 3} ^{1 2}] # => true
## JSON / YAML
# Parse def data [json/parse $raw-text] def yaml-data [yaml/load "config.yaml"] # Stringify [json/stringify $data] [json/pretty $data] # indented # Round-trip [json/parse [json/stringify $data]]
## HTTP
# GET set r [http/get "https://api.github.com/repos/ziglang/zig"] def body [json/parse $r~body] echo $body~stargazers_count # POST with JSON def payload [json/stringify %{ :title "hello" }] http/post "https://example.com/api" $payload # Concurrent — task bodies see globals (snapshotted), not captured locals from "deft/stdext/async" import await-all def api "https://api.example.com" def futures @{ [deftask { [http/get "$api/a"] }] [deftask { [http/get "$api/b"] }] } def results [await-all $futures]
## SQLite
# Open def db [sqlite/open ":memory:"] # Schema sqlite/exec $db "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)" # Insert with params sqlite/exec $db "INSERT INTO users (name, age) VALUES (?, ?)" @{ "Alice" 30 } # Query def rows [sqlite/query $db "SELECT * FROM users"] for row $rows { echo "$row~name" } # Scalar def count [sqlite/scalar $db "SELECT COUNT(*) FROM users"] # Close sqlite/close $db
## Pattern Matching
# Dispatch match $status { 200 => "ok" 404 => "missing" _ => "other" } # Destructure match $entry { %{ :name $n :age $a } => "$n is $a" _ => "unknown" } # Tagged map match $result { %Ok{ :value $v } => $v %Err{ :message $m } => [throw $m] } # Range match $score { 90 .. 100 => "A" 80 .. 89 => "B" _ => "C" }
## Transducers
# Build a reusable pipeline def xf [comp [filter { ($it % 2) == 0 }] [map { $it * $it }] [take 5]] # Apply to different sinks/sources [into @{} xf [range 0 1000]] [into ^{} xf $other-source] [transduce xf + 0 [range 0 1000]] # sum
## Concurrency
# Async value — deftask runs the body on a real OS thread set f [deftask { [slow-op] }] # ... do other work ... def result [await $f] # Concurrent map — bodies must be self-contained (no captured locals) from "deft/stdext/async" import await-all def f1 [deftask { [http/get "https://a.example.com"] }] def f2 [deftask { [http/get "https://b.example.com"] }] def results [await-all @{$f1 $f2}] # One-shot timer after 5000 { echo "five seconds" } # Sleep sleep 100
## Git
def branch git rev-parse --abbrev-ref HEAD def hash git rev-parse HEAD def dirty git status --porcelain if not(empty? git status --porcelain) { echo "dirty tree" } # Files changed since main def changed git diff --name-only main(lines)
## Type Checks
[type 42] # => "number" [type "hi"] # => "string" [type %User{...}] # => "User" [is? "number" 42] # => true [nil? $x] [empty? $xs] [satisfies? $val "Drawable"]
## Time
def now [clock/seconds] def iso [clock/format $now "%Y-%m-%dT%H:%M:%S%z"] def later [clock/add $now 1 :hour] def parsed [clock/scan "2024-05-01" %{ :format "%Y-%m-%d" :timezone "UTC" }] def ms [clock/millis] def elapsed ($end - $start)
## Environment
def home [os/env "HOME"] def path [os/env "PATH"] def cwd [os/cwd] # Args def args [os/args] def argv $args(rest)
## Crypto
def hash [crypto/sha256 "hello"] def mac [crypto/hmac :sha256 "key" "data"] def salt [crypto/rand-hex 16] def token [crypto/rand 32] def encoded [crypto/b64-encode $data] def decoded [crypto/b64-decode $encoded]
## Compress
compress/gzip "file.txt" "file.txt.gz" compress/gunzip "file.txt.gz" "file.txt" compress/tgz-create @{"src"} "src.tar.gz" compress/tgz-extract "src.tar.gz" "out/" compress/list-tgz "src.tar.gz"
## See Also
- [Shell Scripting](shell-scripting) — narrative tutorial
- [Stdlib](stdlib) — full standard library catalogue
- [Pattern Matching](pattern-matching) — full pattern reference