uwefladrich / scriptengine

A lightweight and extensible framework for execution scripts written in YAML.
GNU General Public License v3.0
15 stars 4 forks source link

Define a sequence for a loop #107

Closed oloapinivad closed 8 months ago

oloapinivad commented 8 months ago

Is there a way to define a sequece into a loop?

The structure below works pretty well:

- base.echo: 
    msg: "I have {{mouse}} mouses in my office."
  loop: 
    with: mouse
    in: [0, 1, 2, 4, 5]

But what if I want to define the amount of loops only? I would expect something like this to work building on python

- base.context:
    mouses: 5

- base.echo: 
    msg: "I have {{mouse}} mouses in my office."
  loop: 
    with: mouse
    in: range(0, {{mouses}}

How can I achieve the same result with ScriptEngine? Thanks?

uwefladrich commented 8 months ago

It is possible:

- base.context:
    mice: 13
- base.echo:
    msg: "Hello, this is mouse no. {{m}}!"
  loop:
    with: m
    in: "[{% for k in range(mice) %}{{k+1}},{% endfor %}]"

The trick is to produce with Jinja something that looks like a YAML list. This is what the in: expression does in the example above. So it is maybe not as easy as you wish, but possible :grin:

oloapinivad commented 8 months ago

Aaaaaah I see I need to work with jinja instead of python.

Do you it is possible with the current structure ScriptEngine to define in the future "extensions" or "aliases" so that we can simplify jinja commands into something more user-friendly? I mean, in the long term I think the more we can extend and collaborare in the development of SE the better will be also for ECE4.

PS thanks for spotting the grammar error :-)

uwefladrich commented 8 months ago

Before addressing the "extensions" question (I'll put that in another comment), let me propose another version of the mice code, which may structure the code a bit better and make it, in a way, more "user-friendly":

 - base.context:
    population: 13
    mice: !noparse "[{% for k in range(population) %}{{k+1}},{% endfor %}]"

# ... later ...

- base.echo:
    msg: "Hello, this is mouse no. {{item}}!"
  loop: "{{mice}}"

That does not make the Jinja expression disappear, but it makes the loop code a lot cleaner and puts the complexity on the spot where it is needed, i.e. creating the list of mice. Moreover, one can reuse the mice list.

uwefladrich commented 8 months ago

... I was about to write a longer comment, when a thought struck me:

- base.echo:
    msg: "Hello, this is mouse no. {{item+1}}!"
  loop: "{{range(5)|list}}

I guess that this version meets the simplicity criterion?

It also proves the point I was going to make anyway: one of the fundamental principles of ScriptEngine is to rely on YAML and Jinja. All the heavy lifting to parse the scripts is done there. And I always found (so far) that it pays off to keep the extra rules on syntax (i.e. the SE specific part) as small as possible. It is much easier to code (SE is not a huge code base), maintain, document, and learn.

So this example illustrates that using the potential of Jinja is better than coding for extra syntax. This being said, there are exceptions. There are a couple of extra Jinja filters that SE defines and that extend the Jinja language (string_to_datetime, string_to_date, basename, dirname, exists, path_join). Adding new (SE specific) Jinja filters is easily coded and they follow the general Jinja syntax, so they are easy to understand.

And I also admit that following the YAML+Jinja-only approach does introduce some limitations. But so far I think the advantages outweigh the limitations.

oloapinivad commented 8 months ago

Thanks, this looks great. I think that I understood the underlying mechanism of SE, and I agree that if there is a way to do things in jinja it is absolutely better to use it instead of overriding with complex structures.

One thing that it might be useful to have is to - whenever there are cases like this one, where specific syntax are required and it is not trivial to create them - to add a few lines in the documentation so that is easier to find how to do this!

oloapinivad commented 8 months ago

I am closing this, thanks again!

uwefladrich commented 8 months ago

One thing that it might be useful to have is to - whenever there are cases like this one, where specific syntax are required and it is not trivial to create them - to add a few lines in the documentation so that is easier to find how to do this!

There is a part in the documentation that concerns loops. It explains part of the solution above, but not the use of the list filter with range. You think it could be added there? It will be difficult to foresee and document all use cases, though.

oloapinivad commented 8 months ago

Yes, I think that suits well since it was the part of the docs that I searched to find this information before opening the PR!