-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for first-class functions in expressions #7010
Comments
cc @mapbox/studio @mapbox/maps-design @mapbox/maps-ios @mapbox/maps-android |
Yep! but I think the restrictions need to be a bit broader than that to prevent recursion. Some cases that come time mind are:
Would we need to construct a graph of all possible function calls and check for cycles? |
Oof, yeah good call, @ansis... I'd originally omitted |
Hi Folks, as a developer recently using the Exp syntax I was seeing if I could add some developer perspective as a swift iOS developer. 🧑⚖️ Full disclosureThis is very green observation into the modeling structure/available info, so I don't have the context as to why/how it was approached previously. 🗒️ ContextGiven the Expression is providing a wrapper for JSON, it doesn't easily convey what options are available, or how to leverage them. This could lead to user mistakes when entering, as well as a harder hurdle to step through to figure out how to customize a display on a platform (eg. iOS) 👀 Personal ObservationWhile I see stuff like this on web often (find/replace), now that I use a strongly typed system, requests like this have left me uneasy making these white-box knowledge mutations. In this example, learning the string/const and expression structure was not obvious. Without that example, I don't know if I would have been able to figure it out. Current Example of Layer opacity configuration
vs If possible, a strongly typed closure syntax that could wrap these model requirements could make development much quicker (allowing for auto-complete), and less abstract (strongly typed) to configure.
Additionally, When reading the concern about recursion, as a developer I don't see this is as big of an issue as the worry around it. Given verbose
eg.
Tools to assist: Instruments -> Leaks, CPU, Crash Reports, Thread sanitizer ModelingWhen reviewing the code base, I see that this expression modeling closely aligns with the underlying JSON to support Encode/Decode support. While not yet obvious how to model, I can assure you, if we want to make the map customization experiencing easier for developers, closure syntax + strong modeling would create a friendly novice playground. |
We've now seen two cases where first-class functions would make sense:
replace
operation (see Implement "regex" expression that returns an array of match groups or… #6228 (comment))reduce
function for aggregating feature properties on clustered data ([WIP] add cluster mapreduce feature to style spec #7004)Let's explore adding function types to the expression language and a syntax for defining (and applying?) function values. Initial proposal to get things started:
A function value is defined with
["fn", "a", "b", "c", (etc.), function_body_expression]
, where a, b, c, ... are parameter names, andfunction_expression
is an expression that may include["var", paramter_name]
expressions to reference parameter values. There is no way to explicitly specify a function's parameter or return types: they must be inferable from the context in which it is being used.Examples:
A function is applied with
["apply", fn_expression, a_expr, b_expr, (etc.)]
, wherea_expr
,b_expr
, etc. are the arguments to thefn_expression
.Example:
function_body_expression
is lexically scoped: it can reference anylet
vars that are in scope at the site of the"fn"
definition. Recursion is not allowed: if the"fn"
definition itself is being bound to a variable, that variable is not in scope withinfunction_body_expression
.Subtyping: if a function of type
(T) -> U
is expected, then a function(X) -> Y
is valid as long asT
is a subtype ofX
andY
is a subtype ofU
. E.g.: if(string, value) -> value
is expected, then(string, string) -> number
is valid.The text was updated successfully, but these errors were encountered: