Wisp

Wisp

< Go back

Wisp is a lisp like language written in C.

  • STACK C

Language

Polish Notation

λwisp> + 1 2 4
7
λwisp> ** 2 2 2 2
256.000000
λwisp> list (/ 5 2) (// 5 2) (% 5 2)
(2.500000 2 1)

Variables

λwisp> = {x} 5
()
λwisp> x
5

Functions

Functions are defined using the f keyword. Functions are first class citizens and can be passed around. Lambda functions are defined using the \ keyword.

λwisp> f {is-even?} {n} {== (% n 2) 0}
()
λwisp> is-even? 4
true
λwisp> is-even? 5
false
λwisp> = {is-odd?} (\ {n} {not (is-even? n)})
()
λwisp> is-odd? 4
false

Functions support multiple arguments and support partial application. If a function is called with fewer arguments than it expects, it returns a new function which is bound to the arguments passed, and can be called with the remaining arguments later. This can be repeated until all arguments are passed, only then the function is evaluated.

λwisp> f {triplet-app} {a b c} {+ a b c}
()
λwisp> = {pair-add-5} {triplet-add 5}
()
λwisp> = {add-15} (pair-add-5 10)
()
λwisp> add-15 10
25

Pipes

Pipes can be created with |> (|> is the ligature for |>) allow composition of functions in an ergonomic way. They also support templates using the ? syntax. ? in statements is replaced with the result of the previous statement, or the initial value if it is the first statement. If there is no ? in the statement, the result is appended to the end of the statement.

(print (|> "hello" {
  {+ ? " world!!"}
  {+ "!!"}
  {str-split}
  {reduce-left
    ( {acc e} {+ acc " " e})}
}))
"! ! h e l l o    w o r l d ! !"

The builtin |> eagerly evaluates pipes but lazily evaluated pipes can be made in wisp itself.

(f {+>} {pipe-line init} {
    (|> init pipe-line)
})

Pipes created using +> are lazily evaluated. and can be executed separately from creation.

Examples

wisp> f {double} {x} {* n 2}
()
wisp> f {square} {x} {** n 2}
()
wisp> f {halve} {a b} {/ n 2}
()
wisp> = {double-square-halve} (+> {{double} {square} {halve}})
()
wisp> double-square-halve 10
200.000000
wisp> = {double-cube-quarter} (+> {{+ ? ?} {** ? 3} {/ ? 4}})
()
wisp> double-cube-quarter 2
16.000000
λwisp> f {double} {x} {* n 2}
()
λwisp> f {square} {x} {** n 2}
()
λwisp> f {halve} {a b} {/ n 2}
()
λwisp> = {double-square-halve} (+> {{double} {square} {halve}})
()
λwisp> double-square-halve 10
200.000000
λwisp> = {double-cube-quarter} (+> {{+ ? ?} {** ? 3} {/ ? 4}})
()
λwisp> double-cube-quarter 2
16.000000

List Functions

λwisp> filter is-even? {1 2 3 4 5  7 8 9 10}
{2 4 8 10}
λwisp> = {strings} {"a" "nice" "list" "of" "strings"}
()
λwisp> map len strings
{1 4 4 2 7}
λwisp> reduce-left + strings
"anicelistofstrings"
λwisp> reduce-right (\ {acc e} {+ acc " " e}) strings
"strings of list nice a"
λwisp> f {add-with-space} {a b} {+ a " " b}
()
λwisp> fold-left add-with-space "Start:" strings
"Start: a nice list of strings"
λwisp> fold-right add-with-space "End:" strings
"End: strings of list nice a"

Fibonacci

(f {fib} {n} {
  if (< n 2)
    {n}
    {+ (fib (- n 1)) (fib (- n 2))}
})

# (== name "main") is used to check if the script is being run as a script or being imported as a module, like in python
(if (== name "main")
  {print (fib 30)}
)
55
Contact
220 smtp.example.com ESMTP Postfix
HELO client.example.com
250 smtp.example.com
MAIL FROM: <me@mydomain.com>
250 Ok
RCPT TO: <hi@zaeem.dev>
250 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
From: "Me" <me@mydomain.com>
To: "Jasir" <hi@zaeem.dev>
Date: $Tue, 16 Sep 2025 17:17:43 GMT
Subject: Complaint Mail

Hi Jasir,
Your site gave me a virus. I am very upset.
Yours truly,
Me
.
250 Ok: queued as 12345
QUIT
221 Bye

Say Hi!

You can reach me at mailto:hi@zaeem.dev

Site best viewed at 1920x1080 in Your Browser