BuckleScript 4.0.0 (Part Two)
bs-platform
4.0.0 introduces a new runtime representation for optionals.
While beforehand None
was represented at runtime as 0
and Some("hello")
as an array ["hello"]
, the new representation tries to unbox optionals as much as possible.
Now None
is represented as undefined
and Some("hello")
simply as "hello"
.
Generally speaking, Some(v)
is represented as v
, i.e. unboxed. The only exception is when v
itself is None
or Some(...(Some(None))
, in which case a special boxed representation is used.
The construction of new values Some(-)
, and pattern matching | Some(-) => ...
, perform some case analysis to decide when to box or unbox values. In the absence of nested optionals, the result of both operations will always be the indentity.
Because of that, it's possible to use type-based optimization to avoid performing case analysis in the first place.
So while the generic function (x) => Some(x)
will generate code to check wheter x
should be boxed, the more type-specific function (x:int) => Some(x)
is just compiled as the identity function, as it's clear from the type that no boxing is required.
For a high-level formalization of the boxing and unboxing operations, as well as the polymorphic comparison functions, see this gist.
One design choice was whether to represent None
as null
or as undefined
. The choice of undefined
was made because this allows a direct mapping for optional labeled arguments. As a consequence null
is never boxed, so e.g. Some(null)
is represented as null
.