mavoweb / mavo

Create web applications entirely by writing HTML and CSS!
https://mavo.io
MIT License
2.83k stars 178 forks source link

Special keyword to define mapping functions in expressions #1010

Open LeaVerou opened 8 months ago

LeaVerou commented 8 months ago

We've often struggled with how to let authors define inline functions in expressions, the concept of an arrow function seeming too out of reach for them. This would be useful for many things:

Note that unlike Coda, we don't need things like CountIf() or All() since we can always do things like count(foo > 2) > 1, but they may be useful as sugar.

Coda’s formula language solves this in an interesting way: They allow for a special CurrentValue keyword, which essentially represents the closest list item. In Mavo’s syntax, presumably this could be $value or $current?

There is the problem of referring to outer currentvalues, which they solve with a special scoping function. I think that's suboptimal, I can think of two alternative ways to deal with it, which can be combined:

DmitrySharabin commented 8 months ago

They allow for a special CurrentValue keyword, which essentially represents the closest list item. In Mavo’s syntax, presumably this could be $value or $current.

Correct me if I’m wrong, but we already have $item, which represents exactly what you described—the closest list item. Can’t we simply re-use it? What am I missing?

LeaVerou commented 7 months ago

They allow for a special CurrentValue keyword, which essentially represents the closest list item. In Mavo’s syntax, presumably this could be $value or $current.

Correct me if I’m wrong, but we already have $item, which represents exactly what you described—the closest list item. Can’t we simply re-use it? What am I missing?

$item (and $this) are fixed within the same execution: they refer to data from the nearest node that matches certain criteria. $value has no meaning outside iterative functions, which loop over a list and $value refers to the current value each time.

Some examples (assume we had map() and sort() functions):

Hypotenuse using numbers in a list:

sqrt(sum(map(numbers, pow($value, 2))))

Filter a list and only keep even numbers:

filter(numbers, $value mod 2 = 0)

Single line pivot table: From a list of flights, to stats about outbound airports:

map(flights by outbound, group(outbound: $value.outbound, count: count($value.$items))

This can already be expressed with current syntax like so:

filter(numbers, numbers mod 2 = 0)

or

numbers where numbers mod 2 = 0

Similarly, it enables patterns like

people.sort($value.name, "asc")

(map each person to their name, then sort based on that)

DmitrySharabin commented 7 months ago

Makes sense. Thank you!

LeaVerou commented 1 week ago

Makes sense. Thank you!

Does it? I’m re-reading it now and I have no idea what I was thinking. 🙃