Tweakflow REPL
Tweakstreet uses tweakflow as its underlying expression language. All values in tweakstreet like flow parameters, variables, and step settings, are tweakflow expressions that you supply directly or indirectly through configuration dialogs, selection widgets, and formulas.
You can launch an interactive tweakflow session on the command line to evaluate and develop tweakflow expressions and libraries.
The tweakflow script
You can run an interactive tweakflow session on the command line using the tweakflow
script. You need to use the appropriate script for your platform.
Running on Linux and macOS
Use the bin/tweakflow.sh
script with the repl
command to run an interactive session on the command line.
λ:tweakstreet $ bin/tweakflow.sh repl
tweakflow interactive shell \? for help, \q to quit
std.tf>\q
λ:tweakstreet $
Running on Windows
Use the bin\tweakflow.bat
script with the repl
command to to run an interactive session on the windows command line.
C:\path\to\tweakstreet> bin\tweakflow.bat repl
tweakflow interactive shell \? for help, \q to quit
std.tf>\q
C:\path\to\tweakstreet>
Working on the REPL
Usage details and examples are available in the official tweakflow REPL documentation.
Evaluating expressions
Just type in an expression to have the REPL evaluate it:
> 1+2
3
> "Hello".. " " .. "World"
"Hello World"
The prompt shows you which module context you are in. You can reference all names visible in the module you are in. By default this is the standard library context, so you can use standard library functions.
std.tf> data.map([1, 2, 3], (x) -> x*x)
[1, 4, 9]
std.tf> strings.length("foo")
3
Multi-line mode
The REPL accepts single line entry by default. If you want to use an expression that spans multiple lines, open multiline mode using \e
and close it again using \e
. The REPL indicates with a *
in the prompt that it is in multi-line mode.
std.tf> \e
std.tf* let {
std.tf* a: 3;
std.tf* b: 4;
std.tf* }
std.tf* a+b
std.tf* \e
7
std.tf>
Defining variables
You can define interactive variables using var_name: expression
syntax. You can then reference your variables in your expressions and definitions.
> a: 3
3
> b: 4
4
> c: a+b
7
All variables are re-evaluated on each command, so changing a variable definition changes all dependent values.
> x: 3
3
> y: x
3
> x: "foo"
"foo"
> y
"foo"
You can view your interactive variable definitions using the \vars
command.
> \vars
5 interactive variables defined
a: 3
b: 4
c: a+b
x: "foo"
y: x
You can view their current values using the \inspect
command.
> \inspect
a: 3
b: 4
c: 7
`$`: "foo"
x: "foo"
y: "foo"
The $
variable is internally maintained by the REPL to hold the last evaluation result. You can only view it using \inspect
. It cannot be referenced in your expressions.
Tweakstreet modules
Tweakstreet comes with the modules is supplementing the tweakflow standard library. You can switch to them using \load
.
std.tf> \load tweakstreet/json
json.tf> json.parse('{"hello": "world"}')
{
:hello "world"
}
User-defined modules
You can load your own module files through the \load
command. Let’s say you have a module file on your disk:
# acme.tf
import data, regex, strings from 'std';
alias strings.replace as replace;
alias data.map as map;
alias data.slices as slices;
alias strings.join as join;
alias strings.upper_case as upper_case;
library product_codes {
remove_whitespace:
regex.replacing('\s+', ""); # function that removes any whitespace from a string
normalize: (string x) ->
->> (x)
# remove whitespace, "f-oo bar" -> "f-oobar"
(x) -> remove_whitespace(x),
# remove any dashes # "f-oobar" -> "foobar"
(x) -> replace(x, "-", ""),
# split to a list of blocks of up to 4 chars "foobar" -> ["foob", "ar"]
(x) -> let {
# "foobar" -> [["f", "o", "o", "b"], ["a", "r"]]
blocks: slices(x as list, 4);
}
# [["f", "o", "o", "b"], ["a", "r"]] -> ["foob", "ar"]
map(blocks, (block) -> join(block)),
# place dashes between blocks converting to single string ["foob", "ar"] -> "foob-ar"
(blocks) -> join(blocks, "-"),
# upper case all characters "foob-ar" -> "FOOB-AR"
upper_case;
}
Load it in the REPL:
> \load /path/to/acme.tf
acme.tf>
You are now in the context of the acme module, and can reference all names in this module.
acme.tf> product_codes.normalize("ah-78277-Nz")
"AH78-277N-Z"
User-defined modules are re-evaluated on each command, so if you change and save your module file and re-run the function, it will automatically use the new version.
For example, if we change acme.tf:
- blocks: slices(x as list, 4);
+ blocks: slices(x as list, 3);
We can re-run the function, without leaving the REPL:
acme.tf> product_codes.normalize("ah-78277-Nz")
"AH7-827-7NZ"