Examples

A collection of sel programs demonstrating common patterns.

Contents
  1. Fibonacci
    1. Tail-recursive (fast)
    2. Naive recursive (for illustration)
  2. Factorial
  3. List Operations
  4. Higher-Order Functions / Currying
  5. FizzBuzz
  6. Bitwise Operations
  7. Arbitrary-Precision Arithmetic
  8. String Output

Fibonacci

Tail-recursive (fast)

(let fib
  (fn fib (n a b)
    (if (= n 0)
      a
      (fib (- n 1) b (+ a b)))))

(println (fib 50 0 1))    ; 12586269025
(println (fib 100 0 1))   ; 354224848179261915075

Naive recursive (for illustration)

(let fibnaive
  (fn fibnaive (n)
    (if (< n 2)
      n
      (+ (fibnaive (- n 1))
         (fibnaive (- n 2))))))

(fibnaive 20)   ; 6765  (slow for large n)

Factorial

(let fac
  (fn fac (n acc)
    (if (= n 0)
      acc
      (fac (- n 1) (* acc n)))))

(println (fac 20 1))   ; 2432902008176640000
(println (fac 30 1))   ; bigint result, no overflow

List Operations

; --- building lists ---
(let iota
  (fn iota (n acc)
    (if (= n 0)
      acc
      (iota (- n 1) (cons n acc)))))

(let nums (iota 5 nil))   ; (1 2 3 4 5)

; --- map ---
(let map
  (fn map (f xs)
    (if (= xs nil)
      nil
      (cons (f (car xs)) (map f (cdr xs))))))

; --- filter ---
(let filter
  (fn filter (pred xs)
    (if (= xs nil)
      nil
      (if (pred (car xs))
        (cons (car xs) (filter pred (cdr xs)))
        (filter pred (cdr xs))))))

; --- fold ---
(let fold
  (fn fold (f acc xs)
    (if (= xs nil)
      acc
      (fold f (f acc (car xs)) (cdr xs)))))

; sum of squares of even numbers 1..10
(let evens
  (filter (fn (x) (= (% x 2) 0))
          (iota 10 nil)))

(let sumsq
  (fold (fn (acc x) (+ acc (* x x))) 0 evens))

(println sumsq)   ; 220  (4+16+36+64+100)

Higher-Order Functions / Currying

(let compose
  (fn (f g)
    (fn (x) (f (g x)))))

(let double  (fn (x) (* x 2)))
(let inc     (fn (x) (+ x 1)))

(let doublethen (compose inc double))
(doublethen 5)   ; => 11

(let incthen (compose double inc))
(incthen 5)   ; => 12

FizzBuzz

(let fizzbuzz
  (fn fizzbuzz (n)
    (if (= (% n 15) 0) (println "FizzBuzz")
    (if (= (% n  3) 0) (println "Fizz")
    (if (= (% n  5) 0) (println "Buzz")
                       (println n))))))

(let run
  (fn run (i limit)
    (if (> i limit)
      nil
      (let _ (fizzbuzz i)
        (run (+ i 1) limit)))))

(run 1 20)

Bitwise Operations

; count set bits (popcount)
(let popcount
  (fn popcount (n acc)
    (if (= n 0)
      acc
      (popcount (>> n 1) (+ acc (& n 1))))))

(popcount 255 0)   ; => 8
(popcount 1023 0)  ; => 10

Arbitrary-Precision Arithmetic

sel automatically uses bigint / bigfloat when values exceed native size:

; 2^100 — far beyond 64-bit integers
(let pow2
  (fn pow2 (n acc)
    (if (= n 0)
      acc
      (pow2 (- n 1) (* acc 2)))))

(println (pow2 100 1))
; 1267650600228229401496703205376

; exact pi to 50 decimal places (bigfloat literal)
(let pi 3.14159265358979323846264338327950288419716939937510)
(println pi)

String Output

(let greet
  (fn (name)
    (print "Hello, ")
    (println name)))

(greet "sel")    ; Hello, sel
(greet "world")  ; Hello, world