eww
eww copied to clipboard
[FEATURE] Let-in syntax in simplexpr
Description of the requested feature
The more complexity simplexpr allows for, the more use there would be for variables within expressions. Given #324, it might make sense to try and come up with some unified syntax or principle for this, although having separate syntax in simplexpr might not be an issue, either. Alternatively, it could be stated that it'd make sense to just rely on the local variables requested in #324, and have separate expressions.
However, I could still see having let-in syntax for simplexpr explicitly be a worthwhile addition.
Proposed configuration syntax
let foo = "hi"; bar = "ho"; in foo + bar
let
foo = "hi"
bar = "ho"
in
foo + bar
(not sure about newline sensitive stuff here, not really a fan :/
Additional context
One alternative to this has been proposed with the with
function in #407
The with
function from #407 works as follows:
-
with(name, value, expression)
: Evaluate the simple expression (which must be a string), where the variablename
has valuevalue
Example:
with('a', '{"0": "hello ", "1": "world"}', 'a[0] + a[1]')
hello world
That implementation can be found here: https://github.com/MartinJM/eww/commit/a4e2095a8a6d50dab28cd69681fe2eb818e15226
I do have a question about the let-in syntax: What would the scope of the variable be? The first expression after the in
, or all expressions until the end?
If I may also add my own opinions:
If (Simplexpr) variables are not supported in local variables, I think it would make sense to have a different syntax. If the syntax is the same, I think it will lead people to believe that the functionality is the same as well.
I'm personally also not really a fan of newline-based stuff. But besides that, I think that newlines in a Simplexpr aren't really supported at the moment? At least, I haven't found a way to have them in a Simplexpr.
Would it make sense to instead follow what ml does here with
let
; reserved keywords let you know where the next def starts, and what part is a name
val a = someValDef
val b = someValDefAgain
in
; some expr using a & b
end ; clear closing here
Is the in
really necessary ? Can't we just have the variables be implicitly scoped to the whole expression ?
Also for the newlines, maybe just add a end delimiter like a coma ?
let a = valOrExpr, a + 1 ; Or any other expression that uses a
Is the
in
really necessary ? Can't we just have the variables be implicitly scoped to the whole expression ? Also for the newlines, maybe just add a end delimiter like a coma ?let a = valOrExpr, a + 1 ; Or any other expression that uses a
I would say that while in
isn't strictly necessary, it decreases the cognitive and implementation overhead of the feature.
On the cognitive side, I would much prefer to have a clear delimitation between definition list and use.
For instance, how would you go about telling a new user that while this is allowed
let
len = length(list)
first = list[0]
len == 1 ? first : "${first} of ${len}
end
this is not
let
len = length(list)
len == 0 ? "Nothing" :
first = list[0]
len == 1 ? "${first}" : "${first} of ${len}
you would probably get some "not in definition scope" error at line 4, but it would be unclear why (especially if a user hasn't used this specific functional construct before).
let
val len = length(list)
in
len == 0 ? "nothing" :
; The def scope has clearly ended, so writing this is clearly incorrect as it does not have a scope
first = list[0]
len == 1 ? "${first}" : "${first} of ${len}
end