Eval in FuncScript
FuncScript is a superset of JSON that lets you promote property values into expressions. The
evalkeyword helps you focus on results and write cleaner code by avoiding intermediate variables.
What is FuncScript?
FuncScript1 is a superset of JSON that lets you promote property values into expressions. Instead of static literals, { x: 1 + 2; } is perfectly legal. You can execute FuncScript using fs-cli2 (the command line interface) or experiment in FuncScript Studio3 (a web-based environment).
This article assumes you have basic knowledge of FuncScript. If you’re new to it, I recommend starting with the official documentation or reading my previous articles: fs-cli basics and functions in FuncScript.
What is eval?
Even though FuncScript code is typically written inside {}, it doesn’t mean we can’t do anything outside braces. Just like Python, Node, or Lua have their own REPL4 environments, FuncScript has fs-cli - which lets us execute simple code without worrying about wrapping everything in a file structure. It’s similar to using run5 to do 4 + 5 in C or C++ without the main function.
So the following is also legal in FuncScript:
fs-cli '4 + 3'
# Type: Integer
# Value: 7
Keep in mind that you need to quote your argument with "" or '' for fs-cli, otherwise unexpected things will happen. For more about fs-cli syntax, please read my first view on fs-cli.
Two ways to run FuncScript
There are two main ways to run FuncScript: FuncScript Studio (a web-based editor) and fs-cli (command line interface).
The main difference is the method of input. In fs-cli, everything we call code must be passed as fs-cli 'arg' where arg is the code. Using quotes is a must (or at least recommended) because things like fs-cli 4 + 4 will only read the first 4 and miss everything after the first argument.
# This is WRONG - fs-cli only sees "4"
fs-cli 4 + 4
# Type: Integer
# Value: 4
# This is CORRECT
fs-cli '4 + 4'
# Type: Integer
# Value: 8
This means fs-cli eval 4 + 4 is an invalid expression. The solution is quoting it as fs-cli 'eval 4 + 4'.
In FuncScript Studio, eval 4 + 4 works directly since it’s an editor environment. You can access the playground at funcscript.org/fsstudio.
Eval with different types
As long as we follow the same format, we can use eval with any type:
fs-cli 'eval "Hello, Esubalew"'
# Type: String
# Value: "Hello, Esubalew"
fs-cli 'eval [3, 3]'
# Type: List
# Value: [3, 3]
fs-cli 'eval {}'
# Type: KeyValueCollection
# Value: {}
fs-cli 'eval {age: 10, name: "cool"}'
# Type: KeyValueCollection
# Value: { "age": 10, "name": "cool" }
The same applies in FuncScript Studio, except we don’t use the outer quotes:
eval {age: 10, name: "cool"}
// Output: { "age": 10, "name": "cool" }
Eval with expressions inside braces
We can use eval inside {} to combine values:
fs-cli '{name: "Esubalew"; full: "Hello, " + name;}'
# Type: KeyValueCollection
# Value: { "name": "Esubalew", "full": "Hello, Esubalew" }
fs-cli '{a: 10; b: 20; sum: a + b;}'
# Type: KeyValueCollection
# Value: { "a": 10, "b": 20, "sum": 30 }
But what if we want to avoid the intermediate sum key and just evaluate to the sum directly?
The problem with missing keys
Can we do something like this?
fs-cli '{a: 10; b: 20; a + b}'
Will this result in 30? No, it will not. The {} object violates the key: value syntax because a + b is without a key.
fs-cli '{a: 10; b: 20; a + b}'
# Failed to parse expression
This is where eval becomes powerful. By taking eval inside {}, we can return the result directly:
fs-cli '{a: 10; b: 20; eval a + b;}'
# Type: Integer
# Value: 30
Focusing on results with eval
Consider this example where we want to transform a list:
{
doubled: [1, 2] map (number) => number * 2;
}
// Output: { "doubled": [2, 4] }
But what if we just want the result without the doubled key?
{
eval [1, 2] map (number) => number * 2;
}
// Output: [2, 4]
We can also access specific elements:
fs-cli '{number: [1, 2] map (n) => n * 2; eval number[0]}'
# Type: Integer
# Value: 2
A practical example
Let’s revisit an example from my previous article:
{
rate: 1/100;
numbers: Range(1, 2);
multiply: (number) => {
old: number;
newer: number * rate;
};
multiplied: numbers map (number) => multiply(number);
}
This returns everything including intermediate steps:
{
rate: 0.01,
numbers: [1, 2],
multiply: "[Function]",
multiplied: [{ old: 1, newer: 0.01 }, { old: 2, newer: 0.02 }],
}
Instead of showing all the intermediate variables like rate and the function, we can focus on the result:
{
rate: 1/100;
numbers: Range(1, 2);
multiply: (number) => {
old: number;
newer: number * rate;
};
multiplied: numbers map (number) => multiply(number);
eval multiplied;
}
// Output: [{ old: 1, newer: 0.01 }, { old: 2, newer: 0.02 }]
We can go even further and focus on a very specific result:
{
rate: 1/100;
numbers: Range(1, 2);
multiply: (number) => {
old: number;
newer: number * rate;
};
multiplied: numbers map (number) => multiply(number);
eval multiplied[0].newer;
}
// Output: 0.01
When eval has no effect
Please note that using eval on a value that’s already a direct return is useless:
fs-cli 'range(1, 10)'
# Type: List
# Value: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
fs-cli 'range(1, 10)[0]'
# Type: Integer
# Value: 1
fs-cli 'eval range(1, 10)[0]'
# Type: Integer
# Value: 1
Here adding eval is of no effect. Think of it like doing eval 1 which just returns 1.
Eval with functions
If we have a function (what I call a “key function” - learn more at my functions article) that returns a multiplied value:
{
multi: (x) => x * 2;
}
// Output: { "multi": "[Function]" }
We can use it by expanding:
{
multi: (x) => x * 2;
play: multi(2);
}
// Output: { "multi": "[Function]", "play": 4 }
But what if we just want a function that returns a number? This time eval is very important:
fs-cli '{multi: (x) => x * 2; eval multi(2)}'
# Type: Integer
# Value: 4
Eval with Reduce
Let’s use eval with Reduce, a powerful built-in function. Reduce takes these parameters:
list- the list to reducelambda- a function that takes(currentState, currentValue)and returns the new stateinitialValue- the starting value
Let’s sum numbers from 1 to 10:
{
numbers: range(1, 10);
sum: Reduce(numbers, (stateNow, number) => stateNow + number, 0);
}
// Output: { "numbers": [1, 2, ...10], "sum": 55 }
We can simplify by passing the range directly:
{
sum: Reduce(range(1, 10), (stateNow, number) => stateNow + number, 0);
}
// Output: { "sum": 55 }
Using eval, we can return just the number without a key:
{
sum: Reduce(range(1, 10), (stateNow, number) => stateNow + number, 0);
eval sum;
}
// Output: 55
We can also remove the sum: key entirely:
{
eval Reduce(range(1, 10), (stateNow, number) => stateNow + number, 0);
}
// Output: 55
And since we don’t have key-value pairs anymore, we can even get rid of {}:
fs-cli 'eval Reduce(range(1,10), (s, n) => s + n, 0)'
# Type: Integer
# Value: 55
Eval in conditional expressions
Before finishing the exploration of eval, let’s also see another example: eval in conditional expressions.
The rule in FuncScript when it comes to conditions follows this pattern: key: if condition then assignValue else assignOther - where assignOther is used when the condition is unsatisfied.
{
value: 10;
message: if value > 0 then "oh at least positive" else "damn negative";
}
// Output: { value: 10, message: "oh at least positive" }
So here we can use eval to directly evaluate the if result without needing an intermediate key:
{
value: 10;
eval if value > 0 then "oh at least positive" else "damn negative";
}
// Output: "oh at least positive"
Conclusion
The eval keyword in FuncScript is a powerful tool for:
- Focusing on results - Skip intermediate variables and return exactly what you need
- Cleaner output - Avoid KeyValueCollection wrappers when you just want a value
- Flexible expressions - Use both inside and outside
{}depending on your context - Working with functions - Extract return values from lambda expressions
Remember: eval is most useful when you’re inside
{}and want to avoid intermediate keys. Outside braces, it’s often redundant since expressions already evaluate directly.
Want to read this in another format? Read on CS
1 FuncScript is a superset of JSON that overlaps with much of JavaScript syntax yet introduces its own twists. FuncScript
2 fs-cli is the command line interface for executing FuncScript expressions. fs-cli
3 FuncScript Studio is a web-based environment for experimenting with FuncScript. FuncScript Studio
4 A read–eval–print loop (REPL), also termed an interactive toplevel or language shell, is a simple interactive computer programming environment that takes single user inputs, executes them, and returns the result to the user. Read–eval–print loop
5 run is a universal multi-language runner and smart REPL written in Rust that lets you execute code in 25+ languages from the command line. run