-
Notifications
You must be signed in to change notification settings - Fork 3
Symbols and Operators
++ARG
Javascript's +
operator. Converts an argument to a number. Right associative.
--ARG
Javascript's -
operator. Converts an argument to a negative number. Right associative.
a + b
Javascript's +
operator. Adds two arguments. Left associative.
a - b
Javascript's -
operator. Subtracts the rhs from the lhs. Left associative.
a * b
Javascript's *
operator. Multiplies two arguments. Left associative.
a / b
Javascript's /
operator. Divides the LHS by the RHS. Left associative.
a % b
Javascript's %
operator. Calculates LHS mod RHS. Left associative.
!a
Logical not. Right associative.
a || b
Logical or using short circuit evaluation. Left associative.
a && b
Logical and using short circuit evaluation. Left associative.
? cond : suc : alt
Ternary operators with short circuit evaluation. Evaluate cond
and if it is true, return result from suc
, otherwise return result from alt
. Right associative.
o ?? f
, o ?? .a.b.c
The checked operator evaluates and applies the RHS to the LHS only when the LHS is truthy.
var (??) = \o f -> o && f o;
Like other logical ops, the RHS is only evaluated when the LHS is truthy.
One application of the ??
operator is writing safe member accessors expressions:
var o = null;
o??.a.b.c; // null
var getXSafe = (_ ?? .x);
getXSafe {'x': 3}; // 3
getXSafe null; // null
a == b
Equality comparison with type conversion. Returns boolean. Left associative.
a === b
Equality comparison that does not perform type conversion. Returns boolean. Left associative.
a != b
Inequality comparison with type conversion. Returns boolean. Left associative.
a !== b
Inequality comparison that does not perform type conversion. Returns boolean. Left associative.
a < b
Returns whether LHS is less than RHS. Left associative.
a <= b
Returns whether LHS is less than or equal to RHS. Left associative.
a > b
Returns whether LHS is greater than RHS. Left associative.
a >= b
Returns whether LHS is greater than or equal to RHS. Left associative.
a instanceof b
Returns whether LHS is an instance of the class on the RHS. Left associative.
~a
Right associative.
a | b
Left associative.
a & b
Left associative.
a ^ b
Left associative.
a >> b
Left associative.
a >>> b
Left associative.
a << b
Left associative.
o.x
, o.(0)
, o.(x + 1)
The member access operators get the value of a property on an object. There are two versions, o.x
to directly get the value of property 'x'
from object o
and o.(x)
which evaluates x
, converts this to a string, and gets the value of the property for this string on o
.
Member Access is left associative and both regular and computed members have the same precedence.
x.y.z; // (x.y).z
w.x.(0).z; // ( (w.x).(0) ).z
Call function f
with argument x
. This is equivalent to f(x)
.
Application is left associative and will always call f
with a single argument.
f 1 2 3; // f(1)(2)(3)
Application has lower precedence that curry, function calls, and member accesses.
f x.y(z) e.f
f(x.y(z))(e.f);
Reverse pipe can be used to force order of evaluation
f <| g y;
f(g(y));
f()
, f(x)
, f(x, y, ...)
Call function f
with zero or more arguments provided in a comma separated argument list. Left associative.
Function calls have the same precedence as member access expressions.
f.g.x(3).y // ( (f.g.x)(3) ).y
TARGET @ ARG1
, TARGET @ (ARG1, ARG2, ...)
Curry a function with a set of zero or more arguments. Returns a copy of the function.
var add = \x y -> x + y;
// Single argument curry
var add10 = add@10;
add10 3; // 13
add10 "abc"; //"10abc";
// Currying multiple args
var add10And3 = add @ (10, 3);
add10And13(); // 13
The this
binding of a function cannot be changed using the curry operator. Use Function.prototype.bind
for this.
Curry is left associative and has higher precedence then application
var f;
f @ 1 @ 2 @ 3;
// is the same as
(((f @ 1) @ 2) @ 3)
// or
f@(1, 2, 3)
// With application:
var f, map;
f map @ 3; // f (map @ 3)
Both the target function and the curried arguments are evaluated once when the curry expression is encountered, left to right. No type checks are performed so it is possible to curry non-functions, resulting in a runtime error.
The \>
and \>>
operators composes two functions into a new function. Using the \>
operator, the resulting function takes a single argument while the result of the \>>
takes an arbitrary number of arguments.
// Translation
var (\>) = \a b -> \x -> b(a(x));
var (\>>) = \a b -> \-args(...)-> b(a.apply(null, args));
The compose function is like F#'s >>
operator but the reverse of Haskell's .
.
The composition operators are right associative and have the lowest precedence than everything except the binary logical operators. Both \>
and \>>
have the same precedence, and also have the same precedence as the reverse composition operators. They have higher precedence than the pipe operator.
var f = (+ 10),
g = (_ / 2);
(g \> f)(4); // 12
(f \> g)(4); // 7
(g \> g \> f)(4); // (g \> (g \> f))(4) // 11
(g \> f \> f)(4); // 22
The <\
and <<\
operators behave the same as the corresponding regular
composition operators with their arguments flipped:
var (<\) = \f, g -> \x -> f(g(x));
var (<<\) = \g, g -> \-args(...)-> f(g.apply(null, args));
The reverse compose operators are left associative and have the same precedence as the forward compose operators:
var f = (+ 10),
g = (_ / 2);
(f <\ g)(10); // 15
(f <\ f <\ g)(10); // (f <\ (f <\ g))(10); // 25
(f <\ g \> f)(10); // ((f <\ g) \> f)(10); // 25
(f \> g <\ f)(10); // ((f \> g) <\ f)(10); // g(f(f(10))) // 15
The |>
operator applies a function on the right to input on the left.
var (|>) := \x f -> f(x);
The |>
is left associative and has lower precedence than the conditional and
compose expressions.
The pipe operator is useful for chaining multiple functions together in a more readable way.
var f = (+ 10),
g = (_ / 2);
// Basic
10 |> g; // 5
// Lower precedence than other binary ops
6 + 10 |> g; // (6 + 10) |> g; // 8
// Left associative
10 |> f |> g; // (10 |> f) |> g; // 10
// Lower precedence than compose
10 |> g \> f; // 10 |> (g \> f) // 15
// Higher precedence than logical ops
(0 |> g) ? 10 |> f : 5 |> f // (0 |> g) ? (10 |> f) : (5 |> f); // 15
Apply an array-like of zero or more args to a function.
var (|>>) := \args f -> f.apply(null, args);
The <|
operator behaves the same as the pipe operator with its arguments flipped:
var (<|) = \f x -> f(x);
This is the same as a normal function call, but because <|
has a lower precedence it allows parenthesis to be omitted:
// normal
f map (!);
f(map)(!);
// with pipe
f <| map (!);
f(map((!)));
The reverse pipe is right associative and has equal precedence as the regular pipe operator:
var f = (+ 10),
g = (_ / 2);
g <| 10; // 5
f <| 10 |> g; // g(f(10)); // 10
Apply an array-like of zero or more args to a function.
var (<<|) := \f args -> f.apply(null, args);
Operator precedence from lowest to highest:
-
=
- nonassociative -
delete
- nonassociative -
,
- left -
:
- left -
let in
- let body,\ ->
- function body - right -
?
- conditional expression - left -
||
- left, lazy -
&&
- left, lazy -
|>
|>>
- left,<|
<<|
- right -
\>
,\>>
- right,<\
,<<\
- left -
|
- left -
^
- left -
&
- left -
==
,!=
,===
,!==
- left -
<
,>
,<=
,>=
,instanceof
- left -
<<
,>>
,<<<
- left -
+
,-
- left -
*
,/
,%
- left -
??
- left, lazy -
!
,~
,++
,--
- right -
f x
- function application - left -
@
- left -
new
- left - ``x.z
,
x.(z)`, `f(x)`, `f(x, y)` - left -
(1 + 2)
- grouping - nonassociative