Do We Have Functions in FuncScript?

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 article on fs-cli basics.

Do functions exist in FuncScript?

Well, I don’t know if there is a “function” in FuncScript in the modern programming language sense.

A function is nothing but a block of code that does something specific. The main ideas are: (1) we can have separated concerns where we do tasks step by step, and (2) we can make code reusable. Instead of hardcoding everything, we can have a block of code dedicated to a specific task.

We don’t have a way of creating a function in the format traditional programming languages use, but we can achieve it in a way that looks like JSON. Please remember that FuncScript is nothing but a powerful JSON.

Everything in braces is a function

To make things easier, let’s assume FuncScript code is JSON, and the JSON itself is a function. So let’s say everything in {} is a function where the key is the name of the function and the value is the return value.

To be more specific, if we have a FuncScript code {a: 10;}, that means a is the name of the function and 10 is what the function a returns.

Please note that in reality everything with {} is called KeyValueCollection, but we must pretend it’s not for this exploration.

Here’s how we can run this in fs-cli:

fs-cli '{a: 10}'
Type: KeyValueCollection
Value:
{
  "a": 10
}

From here on, I’ll show FuncScript code and output separately for clarity. You can run these in fs-cli or FuncScript Studio.

Let’s achieve this same thing in Rust to make a connection with traditional programming languages. I’ll use run4 for simplicity:

run rust
run universal REPL. Type :help for commands.
rust>>> fn ten() -> i32 { 10 }
rust>>> ten()
10

That’s essentially what we just did in FuncScript - or even simpler!

To make it cleaner and return only 10 instead of the whole KeyValueCollection, we use eval:

{
  a: 10;
  eval a;
}

Output:

10;

So that’s the most basic function in FuncScript.

But where are the parentheses?

You might ask: where is the () - the parameter symbol that can either be empty or hold some parameters? Like we see in Rust: fn ten() -> i32 { 10 }.

Let’s first look at Python - to create a simple “hello” function, then adapt it to FuncScript:

python>>> def say_hello(): return 'Hello'
python>>> say_hello()
'Hello'

Now let’s adapt this in FuncScript - maybe in an even simpler way than Python:

{
  say_hello: () => "hello";
  eval say_hello();
}

Output:

"hello";

If we want to make it a two-step process, we can remove the eval and see the full structure:

{
  say_hello: () => "hello";
  result: say_hello();
}

Output:

{
  say_hello: "[Function]",
  result: "hello",
};

Functions with parameters

What if we have parameters, like printing “Hello, name” where name is an argument the function receives?

In Python:

python>>> name = "Esubalew"
python>>> def say_hello(name): return "hello " + name
python>>> say_hello(name)
'hello Esubalew'

Now let’s do the exact same thing in FuncScript:

{
  name: "Esubalew";
  say_hello: (name) => "Hello " + name;
  eval say_hello();
}

Output:

"Hello Esubalew";

Or if we don’t have the argument ready and want to pass it at runtime:

{
  say_hello: (name) => "Hello " + name;
  eval say_hello("Augustus");
}

Output:

"Hello Augustus";

Complex transformations with functions

FuncScript can handle deeper and more complex tasks. Let’s assume we want to multiply a range of numbers with some rate and write a function that does that:

{
  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 },
];

Remove eval and FuncScript shows the whole structure:

{
  rate: 1/100;
  numbers: Range(1, 2);
  multiply: (number) => {
    old: number;
    newer: number * rate;
  };
  multiplied: numbers map (number) => multiply(number);
}

Output:

{
  rate: 0.01,
  numbers: [1, 2],
  multiply: "[Function]",
  multiplied: [
    { old: 1, newer: 0.01 },
    { old: 2, newer: 0.02 },
  ],
};

The eval keyword can also help us extract specific values:

{
  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;

Simplifying step by step

If we want to make the function more flexible, we can pass parameters instead of using external bindings:

{
  multiply: (number, rate) => {
    old: number;
    newer: number * rate;
  };
  multiplied: Range(1, 6) map (number) => multiply(number, 1/100);
  eval multiplied;
}

Output:

[
  { old: 1, newer: 0.01 },
  { old: 2, newer: 0.02 },
  { old: 3, newer: 0.03 },
  { old: 4, newer: 0.04 },
  { old: 5, newer: 0.05 },
];

Or even shorter with inline lambdas:

{
  multiplied: Range(1, 2) map (n) => {
    old: n;
    newer: n / 100;
  };
  eval multiplied;
}

Output:

[
  { old: 1, newer: 0.01 },
  { old: 2, newer: 0.02 },
];

Or get rid of naming entirely and go fully inline:

{
  eval Range(1, 2) map (n) => {
    old: n;
    newer: n / 100;
  };
}

Output:

[
  { old: 1, newer: 0.01 },
  { old: 2, newer: 0.02 },
];

Conclusion

So, do we have functions in FuncScript? Not in the traditional function or def keyword sense. But we absolutely have:

  • Lambda expressions: (param) => expression
  • Named bindings: Store lambdas as reusable values
  • Higher-order functions: map, and other helpers that accept functions
  • Closures: Lambdas can reference outer bindings like rate

FuncScript takes a different approach. Instead of defining functions as separate entities, everything lives inside the JSON-like structure. Your “functions” are just properties that happen to hold lambdas. This makes FuncScript feel less like traditional programming and more like building reactive, self-computing documents.

The beauty is in the simplicity: what starts as {a: 10} can evolve into complex transformations while maintaining that familiar JSON shape.


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