Issue #11331 has been updated by Henrik Lindberg.

Brice Figureau wrote:
> Henrik Lindberg wrote:
> > After some discussion on #puppet-dev an idea was raised that a more 
> > function call style (as opposed to method call style) may be more 
> > appreciated. 
> > The pull request is now updated with this.
> > 
> > These are now equivalent:
> > [...]
> > 
> > It is still the same foreach function, only difference is in who gets to 
> > make the call (Function, or MethodCall).
> 
> I didn't fully the development nor this ticket, but I really think the syntax 
> should be a bit more distinct from ruby blocks. I mean puppet is a different 
> language, and should always be (or we should all use the ruby dsl).
> 
> I'd favor something like this that more closely looks like puppet code to me:
<pre>
FOREACH rvalue { parameters => statements } 
</pre>
> Also, I'm not sure I got the underlying reasons for the syntax with an 
> expression instead of a statement (unless it is a requirement from the 
> existing > grammar and racc being fiddly). But if you could merge both syntax 
> to my aforementioned example that'd be perfect :)

To support the exact syntax you propose, FOREACH must be made into a keyword. 
The proposed implementation would require adding () around the parameters (or 
it becomes ambiguous).
<pre>
FOREACH(rvalue) { parameters => statements}
</pre>

There are additional difficulties with recognizing { $a => statements } as it 
is a potential conflict with hash (currently hash only allows NAME or quoted 
text, but there is no reason (other than obvious grammar conflicts) why it 
should not allow variable value. I am more or less convinced that a syntactic 
marker is needed to make the lambda part recognizable (which it is if FOREACH 
is made into a keyword).

IMO, making foreach into a keyword requires waiting to puppet 4 as it is a 
backwards incompatible change, and it is also neither extensible nor general. 
If it is ok to forever after not being able to evaluate a variable as a hash 
entry key, then the proposed syntax can be supported with the small change that 
the argument must be enclosed in parentheses.

Finally, the quirk in the current implementation (that a = is required before 
an expression lambda to turn it into a statement), can be removed when/if the 
grammar is transformed from being statement oriented to being expression 
oriented (this is exploratory work that I am doing right now with very 
promising results).

You are right that Puppet Language is not Ruby, but still, a concrete syntax 
has to be used, and Ruby happen to have one that fits very well. Whatever we 
do, the functor ("foreach"), the LHS value, what to pick (one or several things 
at a time), what to call these parameters, and then one or several 
statements/expressions are naturally needed whatever way we choose. Since I 
felt that stealing $ as the opening of a {} to mean it is a parameterized 
puppet block was stealing too much "grammatical space",  I opted for a known 
syntax from Ruby as opposed to inventing something different.

I did consider placing the fat arrow first i.e. `{=>parameters`, but that list 
need a terminator as the first statement may start with a variable, there are 
several to choose from `':', ';', '|' - the one I considered the best of these 
were ';' as it has less of a tendency to cause confusion with '::' in qualified 
variables even if it would work technically - i.e. that would mean your example 
would look like this:

<pre>
foreach(rvalue) { =>parameters; statements}
</pre>
If you want to use a block without parameters you would have to do something 
like:
<pre>
foreach(rvalue) { ; statements}
foreach(rvalue) { =>; statements}
foreach(rvalue) { => statements} # does not work as statements may start with 
variable
</pre>

To be compared with what I propose:
<pre>
foreach(rvalue) { |parameters| statements }
rvalue.foreach { |parameters| statements }

foreach(rvalue) { || statements }
rvalue.foreach { || statements }

</pre>

I also considered placing the block parameters before the block but this leads 
to other clashes.

----------------------------------------
Feature #11331: Add 'foreach' structure in manifests
https://projects.puppetlabs.com/issues/11331#change-82165

Author: Steve Shipway
Status: Needs Decision
Priority: High
Assignee: J.D. Welch
Category: language
Target version: 3.x
Affected Puppet version: 
Keywords: ux backlog
Branch: https://github.com/puppetlabs/puppet/pull/1420


I doubt this would be simple to do, but it would be very useful to be able to 
do something like this:

    $variable = [ 'a', 'b', 'c' ]
    foreach $loop $variable {
      file { "/tmp/$loop": content=>"I am file $loop"; }
    }

While it is already possible to use an array as a namevar to get something 
similar, it doesnt allow you to have calculated parameters as well.

This would not be expected to break the declarative nature of puppet, though it 
would bring in a new variable scope in the loop.

Using a define with an array for the namevar would work provided the top level 
could not be called multiple times.

We want to have something like this:

    define firewall($users,$port) {
      iptables::open { $users: port=>$port; }
    }
    node foo {
      $webusers = [ 'fred', 'sid' ]
      $sshusers = [ 'fred', 'joe' ]
      firewall { port80: users=>$webusers, port=>80; }
      firewall { port22: users=>$sshusers, port=>22; }
    }

This example would fail because the iptables::open define is called with user 
'fred' two times (although with a different port parameter).  If we could 
instead have a foreach iteration then something like this would be useable:

    define firewall($users,$port) {
      foreach $users {
        iptables::open { "$loop:$port": user=>$loop, port=>$port; }
      }
    }

This would ensure a unique namevar for iptables::open.  We would also be able 
to do things like initialise an array of users with different metadata 
parameters (eg, their full names pulled form LDAP)



-- 
You have received this notification because you have either subscribed to it, 
or are involved in it.
To change your notification preferences, please click here: 
http://projects.puppetlabs.com/my/account

-- 
You received this message because you are subscribed to the Google Groups 
"Puppet Bugs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to puppet-bugs+unsubscr...@googlegroups.com.
To post to this group, send email to puppet-bugs@googlegroups.com.
Visit this group at http://groups.google.com/group/puppet-bugs?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to