Implement functional programming (Clojure syntax) in Sass. Dart Sass only.
Anonymous functions in lambda-sass are implemented using S-expressions, such as (plus 1 2 3), which is represented as the Sass list data type under the hood. When defining anonymous functions, you can use _ for a single parameter or _1, _2, and so on for multiple parameters.
Only Iterator Functions and Threading Functions accept anonymous functions as arguments. Here are some examples:
reduce((plus _1 _2 _2), "#", ["a", "b", "c"]) // "#aabbcc"
thread-last(1, inc, (plus 10 5), dec, ("math.pow" 2)) // 65536
As you may have noticed in the example above, it is necessary to enclose the method name in quotes when using the Sass built-in modules. Failure to do so will result in a syntax error. It's important to note that all Sass built-in modules are already pre-included, so there's no need to import the module using @use "sass:math" at the beginning of your file.
It's exciting to have the ability to utilize the threading-like features of Clojure in Sass. In case you're not acquainted with threading macros, I recommend taking a look at this resource.
Many functions have two different ways of being called, known as arities: fn($list...) and fn([$list]). For instance, plus(1, 2, 3) and plus([1, 2, 3]) both result in the value 6.
Install lambda-sass
npm i -D lambda-sass
In vanilla projects, import the full path to lambda.scss:
@use "path/to/node_modules/lambda-sass/src/lambda.scss" as *;In some frameworks, like Next.js, which utilize the webpack sass-loader, it is possible to simply import the package name:
@use "lambda-sass" as *;plus($list...) or plus([$list])
plus(1, 2, 3) // 6
plus("#", "a", "b", "c") // "#abc"
plus([1, 2, 3]) // 6
plus(["#", "a", "b", "c"]) // "#abc"minus($number...) or minus([$number])
minus(1, 2, 3) // -4
minus([1, 2, 3]) // -4multiply($number...) or multiply([$number])
multiply(1, 2, 3) // 6
multiply([1, 2, 3]) // 6divide($number...) or divide([$number])
divide(1, 2, 3) // 0.16666666667
divide([1, 2, 3]) // 0.16666666667Remainder of dividing numerator by denominator.
rem($base, $div)
rem(10, 3) // 1
rem(-10, 3) // 2
rem(10, -3) // -2
rem(-10, -3) // -1Quotient of dividing numerator by denominator.
quot($base, $div)
quot(10, 3) // 3
quot(12, 3) // 4
quot(-5.9, 3) // -1
quot(10, -3) // -3inc($number)
inc(1) // 2dec($number)
dec(1) // 0odd($number)
odd(1) // true
odd(2) // falseeven($number)
even(1) // false
even(2) // truegreater($number...) or greater([$number])
greater(1, 2, 3, 4) // false
greater(4, 3, 2, 1) // true
greater([1, 2, 3, 4]) // false
greater([4, 3, 2, 1]) // truegreater-equal($number...) or greater-equal([$number])
greater-equal(1, 3, 3, 4) // false
greater-equal(4, 3, 3, 1) // true
greater-equal([1, 3, 3, 4]) // false
greater-equal([4, 3, 3, 1]) // trueless($number...) or less([$number])
less(1, 2, 3, 4) // true
less(4, 3, 2, 1) // false
less([1, 2, 3, 4]) // true
less([4, 3, 2, 1]) // falseless-equal($number...) or less-equal([$number])
less-equal(1, 3, 3, 4) // true
less-equal(4, 3, 3, 1) // false
less-equal([1, 3, 3, 4]) // true
less-equal([4, 3, 3, 1]) // falseequal($list...) or equal([$list])
equal(1, 1, 1) // true
equal(1, 2, 3) // false
equal("a", "a", "a") // true
equal("a", "b", "c") // false
equal([1, 1, 1]) // true
equal([1, 2, 3]) // false
equal(["a", "a", "a"]) // true
equal(["a", "b", "c"]) // falsenot-equal($list...) or not-equal([$list])
not-equal(1, 1, 1) // false
not-equal(1, 2, 3) // true
not-equal("a", "a", "a") // false
not-equal("a", "b", "c") // true
not-equal([1, 1, 1]) // false
not-equal([1, 2, 3]) // true
not-equal(["a", "a", "a"]) // false
not-equal(["a", "b", "c"]) // truefirst($list) or first($string)
first([1, 2, 3]) // 1
first("#abc") // "#"last($list) or last($string)
last([1, 2, 3]) // 3
last("#abc") // "c"rest($list) or rest($string)
rest([1, 2, 3]) // (2, 3)
rest("#abc") // ("a", "b", "c")reverse($list...) or reverse([$list])
reverse(1, 2, 3, 4) // (4, 3, 2, 1)
reverse([1, 2, 3, 4]) // (4, 3, 2, 1)range($start-from? = 0, $end-to, $step? = 1)
range(5) // (0 1 2 3 4)
range(-2, 5) // (-2 -1 0 1 2 3 4)
range(-2, 9, 3) // (-2 1 4 7)repeat($value, $times)
repeat(1, 5) // (1 1 1 1 1)
repeat("a", 5) // ("a" "a" "a" "a" "a")
repeat(((1, 2), 5) // ((1, 2) (1, 2) (1, 2) (1, 2) (1, 2))conj($list, $value)
conj(null, 1)); // [1]
conj([1, 2], 3); // [1, 2, 3]
conj([1, 2], [3, 4]); // [1, 2, 3, 4]
conj((a: 1, b: 2), (c: 3)); // (a: 1, b: 2, c: 3)map($function, $list...) or map($function, [$list])
map(inc, 1, 2, 3) // (2, 3, 4)
map((plus _ 1), 1, 2, 3) // (2, 3, 4)
map(inc, [1, 2, 3]) // (2, 3, 4)
map((plus _ 1), [1, 2, 3]) // (2, 3, 4)filter($function, $list...) or filter($function, [$list])
filter(odd, [1 2 3]) // (1 3)
filter((greater _ 1), [1 2 3]) // (2 3)
filter(odd, 1, 2, 3) // (1 3)
filter((greater _ 1), 1, 2, 3) // (2 3)redure($function, $init-value, $list...) or reduce($function, $init-value, [$list])
reduce((plus _1 _2), 0, 1, 2, 3) // 6
reduce((plus _1 _2 _2), "#", "a", "b", "c") // "#aabbcc"
reduce((plus _1 _2), 0, [1, 2, 3]) // 6
reduce((plus _1 _2 _2), "#", ["a", "b", "c"]) // "#aabbcc"some($function, $list...) or some($function, [$list])
some(even, -1, 0, 12) // true
some(even, -1, 3, 11) // false
some(even, [-1, 0, 12]) // true
some(even, [-1, 3, 11]) // falseevery($function, $list...) or every($function, [$list])
every(odd, -1, 3, 9) // true
every(odd, -1, 0, 9) // false
every(odd, [-1, 3, 9]) // true
every(odd, [-1, 0, 9]) // falseassoc($map, ($key, $value)...)
assoc((a: 1, b: 2), a, 3, b, 4) // (a: 3, b: 4)
assoc([1 2 3], 2, (a b)) // [1 (a b) 3]
assoc([1 2 3], 2, a, 3, b, 4, c, 5, d) // [1 a b c d]assoc-in($map, [$key], $value)
assoc-in((a: (b: (c: 1, d: 2))), [a b c], 2) // (a: (b: (c: 2, d: 2)))
assoc-in((1 (a (a b)) 3), [2 2 2], a) // (1 (a (a a)) 3)Same as the as-> macro in Clojure.
thread-as($init-value, $function...)
thread-as(1, inc, (plus 10 _ 5), dec, ("math.pow" _ 2)) // 256Same as the -> macro in Clojure.
thread-first($init-value, $function...)
thread-first(1, inc, (plus 10 5), dec, ("math.pow" 2)) // 256Same as the ->> macro in Clojure.
thread-last($init-value, $function...)
thread-last(1, inc, (plus 10 5), dec, ("math.pow" 2)) // 65536