Closed yrahul3910 closed 11 months ago
The use case is something of this form:
[`cat {file}` for file in files]
It might be better to implement something like zx's Promise.all
, like so:
map(
lambda file: `cat {file}`
files
)
However, this might still be complicated to implement, so instead, an easier solution might be to use the formatter syntax, like so:
all_contents = files.foreach(file)`cat {file}`
This is slightly inspired by C++ lambdas. I'm not sure if this is expressive enough, for example. What if I'd like to mutate my list in-place? The above syntax would call for
files = files.foreach(file)`cat {file}`
A C++-like syntax would instead be closer to:
files.foreach(&file)`cat {file}`
Of course, the two can co-exist, and users have the freedom to stick with the former. This new syntax, while being less Pythonic, has an advantage, however: it allows us to expand the formatter syntax to involve attributes. For example, when we implement #9, we might do
files.foreach[a](&file)`long_process {file}`
where the a
attribute means async.
To address the incoming question of multi-line commands to map, those should be abstracted to a function, as done in progres.
A C++-like syntax would instead be closer to:
files.foreach(&file)`cat {file}`
The obvious downside, of course, is we now need even uglier syntax to specify a formatter for each of those mapped commands. I suppose we could do something like this:
files.foreach[a](&file):list.str`long_process {file}`
This, sadly, is quite ugly.
I propose passing (idx, value)
pairs to the callable (the user-defined formatter) instead. Moreover, the addition of &
and =
could complicate things (see below), so it should not be done.
Here is a regex that captures this syntax (regexr).
([a-zA-Z0-9()_.]+)(?:\.(foreach|other)(\[[a-z]+\])?(\([a-zA-Z0-9_]+(?:,\s*?[a-zA-Z0-9_]+)*\))(?::([^`]*))?)?`
where other
is a placeholder for other potential future additions.
Internally, we would pass enumerate(<matched first group>)
. Therefore, the correct usage would be:
files.foreach[a](idx, file):list.str`cat {file}`
For dicts, we could do something similar:
mydict.items().foreach(idx, (key, val)):list.str`cat {key}: {val}`
As to the &
and =
, it is immediately obvious why this is troublesome: it is invalid to use &
with the index, and we don't want the hassle of syntax checking. As such, that will not be implemented.
Implementing this now. Attributes will be implemented as a separate feature.
There is one major known issue: list and dict comprehensions. Specifically, the following syntax is not yet supported:
That is, while comprehensions themselves are fine, using template strings within them is not.