// Functions are everywhere, and in this language, they are very flexible.
// This is an introduction to the basics of how functions are made and used.
// First, we need to understand what exactly a function is.
// The most basic function returns the same thing every time.
// This function just returns the number 5:
myFunction = fn: 5;
// To call this function, we can do this:
myFunction();
// Now for something more useful...
// We can use parameters to make our function work for us.
// This is a function that returns whatever you give it:
doNothing = fn x: x;
doNothing(5); // Returns the number 5
// We can also use several parameters.
// This function adds the two numbers you give it:
add = fn (a, b): a + b;
add(1, 2); // Returns 3
// What if you don't want to put in all of the parameters?
// Use the `?` character as a placeholder:
add(1, ?);
// This is called partial application, and it can be very useful.
addOne = add(1, ?); // Returns fn b: 1 + b
addOne(2); // Returns 3
// You can put the placeholder anywhere:
otherAddOne = add(?, 1); // Returns fn a: a + 1
// Note how the functions addOne and otherAddOne are different,
// even though they behave the same way mathematically.
// The placeholder simply ignores the parameter it is placed on.
// There is also one more thing to know,
// instead of putting placeholders last, you can ignore the parameters:
addOne = add(1); // Returns fn b: 1 + b
// That's all fine and dandy, but what can you actually use it for?
// Let's make a function that doubles every item in an array of numbers:
double = fn n: 2*n;
doubleArray = map(double); // Or map(double, ?)
doubleArray([1, 2, 3]); // Returns [2, 4, 6]
// Now for something a little more complicated.
// This finds the sum of all the multiples of 3 or 5 below 1000:
multiples = fn n: (n % 3 == 0) || (n % 5 == 0);
reduce(add, 0, filter(multiples, [0..999]));
// That kinda sucks, you can barely tell what's happening...
// How can we call these functions in a way that makes more sense?
[0..999] ->
filter(multiples) ->
reduce(add, 0);
// So now we can see the flow of data easily,
// the flow arrow, `->`, puts the value to the left of it into
// the function to the right of it. This is the alternative way of calling functions.
// Asynchronicity is just a bit different from javascript
// These four expressions will simply evaluate in order, as if synchronous
res = fetchSomeJSON;
res -> console.log;
res -> process -> postJSON;
res -> doSomethingElse;
// We can call any function asynchronously by prefixing with the `go` keyword.
// This will call the functions in the same order as before,
// but there will be no waiting for the functions to return before moving on.
go doWhatever();
go doThisToo();
// Asynchronous behavior is designed to be almost invisible.
// This essentially means that `await` is always implied when you access
// an asynchronous return value. You will never have to interact with a promise.
/* JS:
async function http(url) {
const res = await fetch(url); return res.json(); }
// You can only use `await` within an async function
async wrapperFunction() { const json = await http(apiURL); }
*/
// DeltaZero equivalent:
http = fn url: fetch(url).json();
json = apiURL -> http;
// The one quirk is that if and match are special,
// We can write them like functions, but they are more
// accurately language constructs.
// This is the most basic use of if:
if { thisIsTrue: doThis(); };
// There is no need to say `then`, `else if`, or `else`:
if {
thisIsTrue: doThis();
elseIfThisIsTrue: thenThis();
defaultToThis();
};
// Nesting works just what you would expect:
if {
maybe: if {
false: this;
true: that;
};
this: that;
that;
};
// This is what `match` looks like:
match thisValue withThis: doThis();
// Here's an more extended example:
price = match fruit {
"Oranges": 0.59;
"Apples": 0.32;
"Bananas": 0.48;
"Cherries": 3;
"Mangoes", "Papayas": 2.79;
`Sorry, we are out of ${fruit}.` -> fail;
};
// Now realize that `if` is equivalent to `match true`.
// Could this also apply to functions?
// Of course, check out this factorial function:
factorial = fn: match args {
0: 1;
n: n * factorial(n-1);
};
// Or more usefully:
factorial = fn {
0: 1;
n: n * factorial(n-1);
};
// Function guards automatically match and assign to parameters.
// This computes the greatest common denominator using Euclid's algorithm.
gcd = fn {
(a, 0): a;
(a, b): gcd(b, a%b);
};
// Normal Strings
"Normal, single line string surrounded by double quotes";
'Normal, single line string surrounded by single quotes';
// Template Strings
`2 + 2 = ${2 + 2}`;
`This is a
multi-line
string`;