Note: for now, Dark is only supported for Chrome with browser extensions disabled.
At heart, Dark is an expression-oriented programming language. This aspect of Dark enables powerful features like live values and trace-driven development. This section introduces a simple way to think about the structure of Dark programs within the editor.
When writing code in Dark, you are building up expressions, relying heavily on autocomplete.
A blank expression acts as a placeholder where you can type to create a
different expression. The value of a blank expression is
it needs to be completed in order to be useful.
Once a blank is filled in, it won't be a blank anymore:
2 is an integer expression with the value 2.
Types of Expressions
In addition to blanks, there are also many other types of expressions.
Atomic Expressions include:
- Integers (whole numbers like
- Floats (numbers like
- Strings (text in double quotes)
- Bools (true and false)
There are also more complex expressions:
For more on the language features of each type of expression, visit the Language Overview. Examples of how these expressions are used in the editor are below.
Expressions in Dark are nested. For example, a multiplication expression is a compound expression with two sub-expressions as operands:
Filling a blank with an expression with sub-parts introduces a new blank for each of them.
In the expression 2 * 3, these sub-expressions are filled with the expressions 2 and 3:
The value of the expression
2 * 3 is
6. This is equivalent to saying
2 * 3
2 * 3 is an expression, it can itself be a subexpression of a compound
expression. Consider the expression
1 + 2 * 3, which has the value
7. It is
a compound expression with a binary operator
+ and two subexpressions as
2 * 3.
This nesting of expressions applies to all parts of the language, not just to mathematical expressions. When defining a variable in Dark, you use a let expression, which has 3 parts: a variable name, a value (an expression!) bound to that variable, and a body (another expression!) within which you can use the name as an expression to stand in for the value:
Here's a let with 3 blanks in Dark:
If expressions have 3 parts: a boolean conditional expression and two branches, a then and else expression. The value of the conditional expression determines whether the then or else expression is evaluated. The value of the evaluated branch becomes the value of the if expression as a whole.
Here's a conditional in Dark:
match expressions provide conditional evaluation of one or more expression
branches. They may also introduce new variable bindings. Every match has a
single value expression that is evaluated once and matched against one or more
patterns. The first pattern that matches the evaluated value indicates the
expression to evaluate. The value of the evaluated expression becomes the value
of the match as a whole.
Pipelines are a key part of the Dark language. They allow you to create a chain of expressions, where each chain is an input to the next expression in the sequence.
To start one, select the code that has the result that you want to pipe, and hit
shift-enter or type
Partials (Partially Completed Expressions)
While you are typing or deleting, you'll often see partially completed expressions like this:
The text in red is the partial, and the gray text behind it indicates what was there before. Note that partials evaluate to whatever was there before:
...until you complete them from the autocomplete:
To add comments to your Dark code, start a line with
let _ = and add a string
containing the comment you'd like to include.
Refactoring and editing code
Dark supports unlimited undo/redo in a single element. Undo with
Cmd-Z and redo with
You can copy/paste selections, which is often used for refactoring.
It may be helpful to note that copy/paste only works in Dark between handlers at this time. Copying JSON from an external source will paste into your handlers in Dark, but if you write code in the Dark language in your text editor of choice, that code will not paste. We hope to improve this experience in the future.
If you’re looking to do something that is not immediately available, chances are
it’s in the command palette (accessed by hitting
This includes the common refactoring tools:
- Extract a function or variable for re-use
- Create a type
- Wrap the current expression in a let (insert let here)
- Insert a let-expression above this one
- Wrap an expression in an if, if-then, or if-else