Skip to content

Symbols and Operators

Stephan Tabor edited this page May 17, 2015 · 28 revisions

Arithmetic Operations

++ - Unary Plus

++ARG

Javascript's + operator. Converts an argument to a number. Right associative.

-- - Unary Minus

--ARG

Javascript's - operator. Converts an argument to a negative number. Right associative.

+ - Addition / String Concat

a + b

Javascript's + operator. Adds two arguments. Left associative.

- - Subtraction

a - b

Javascript's - operator. Subtracts the rhs from the lhs. Left associative.

* - Multiplication

a * b

Javascript's * operator. Multiplies two arguments. Left associative.

/ - Division

a / b

Javascript's / operator. Divides the LHS by the RHS. Left associative.

% - mod

a % b

Javascript's % operator. Calculates LHS mod RHS. Left associative.

Logical Operators

! - Logical Not

!a

Logical not. Right associative.

|| - Logical Or

a || b

Logical or using short circuit evaluation. Left associative.

&& - Logical And

a && b

Logical and using short circuit evaluation. Left associative.

? : : - Ternary

? 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.

?? - Check Operator

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

Relational Operators

== - Equality

a == b

Equality comparison with type conversion. Returns boolean. Left associative.

=== - Strict Equality

a === b

Equality comparison that does not perform type conversion. Returns boolean. Left associative.

!= - Inequality

a != b

Inequality comparison with type conversion. Returns boolean. Left associative.

!== - Strict Inequality

a !== b

Inequality comparison that does not perform type conversion. Returns boolean. Left associative.

< - Less Than

a < b

Returns whether LHS is less than RHS. Left associative.

<= - Less Than or Equal To

a <= b

Returns whether LHS is less than or equal to RHS. Left associative.

> - Greater Than

a > b

Returns whether LHS is greater than RHS. Left associative.

>= - Greater Than or Equal To

a >= b

Returns whether LHS is greater than or equal to RHS. Left associative.

instanceof - Instance of

a instanceof b

Returns whether LHS is an instance of the class on the RHS. Left associative.

Bitwise Operators

~ - Bitwise Not

~a

Right associative.

| - Bitwise Or

a | b

Left associative.

& - Bitwise And

a & b

Left associative.

^ - Bitwise Xor

a ^ b

Left associative.

>> - Left Arithmetic Shift

a >> b

Left associative.

>>> - Left Logical Shift

a >>> b

Left associative.

<< - Right Shift

a << b

Left associative.

Object Operators

., .(x) - Member Access

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

Function Operators

f x - Function Application

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(...) - Function Call

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

@ - Partial Application Operator

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.

\> and \>> - Forward Composition Operator

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

<\ and <<\ - Reverse Composition Operator

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

|> - Pipe Operator

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

|>> - PipeN Operator

Apply an array-like of zero or more args to a function.

var (|>>) := \args f -> f.apply(null, args);

<| - Reverse Pipe Operator

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

<<| - Reverse PipeN Operator

Apply an array-like of zero or more args to a function.

var (<<|) := \f args -> f.apply(null, args);

Precedence

Operator precedence from lowest to highest:

  1. = - nonassociative
  2. delete - nonassociative
  3. , - left
  4. : - left
  5. let in - let body, \ -> - function body - right
  6. ? - conditional expression - left
  7. || - left, lazy
  8. && - left, lazy
  9. |> |>> - left, <| <<| - right
  10. \>, \>> - right, <\, <<\ - left
  11. | - left
  12. ^ - left
  13. & - left
  14. ==, !=, ===, !== - left
  15. <, >, <=, >=, instanceof - left
  16. <<, >>, <<< - left
  17. +, - - left
  18. *, /, % - left
  19. ?? - left, lazy
  20. !, ~, ++, -- - right
  21. f x - function application - left
  22. @ - left
  23. new - left
  24. ``x.z, x.(z)`, `f(x)`, `f(x, y)` - left
  25. (1 + 2) - grouping - nonassociative
Clone this wiki locally