On Wed, Aug 19, 2009 at 18:48, Derek Baum <derek.b...@paremus.com> wrote:

> OK, I think I now understand the problem FELIX-1471 is trying to solve.
> Sorry it's taken so long :-(
>
> I have my own example that demonstrates it,
> just to confirm that I have the same understanding.
>
>  > x = <echo aa; <echo ab; echo ac | grep -n a | tac>>
>  aa
>       1  ab     3  ac
>  IllegalArgumentException: Command not found:  *:1
>
> The return value of tac (and the value assigned to x) is
>  "     1  ab     3  ac".
> The problem is that the <> used for grouping also evaluates the result,
> causing the exception.
>

Exactly.


>
> FELIX-1471 proposes using () for grouping and $() for evaluation.
> So the above example would become:
>  > x = (echo aa; (echo ab; echo ac | grep -n a | tac))
>

Not sure about this one.
I guess i've been fooled in my testing by the fact that when evaluating a
command, you have two results: the output on the console and the object
returned by the command.
We need to handle both at some point.
But for this, we need to exactly define when the returned object will be
printed to the console (or the piped output stream).

This example also use an assignement, which we need to clearly defines what
it means.
When you have "x = ...", it intuitively implies that x will take the value
expressed by "..." whatever it is.
So if we have a simple value:
> x = a
it means x will store the string "a"
If you have
> x = { echo $args }
it means x will store the closure.
The next question is what happens when "..." is defined by multiple tokens:
> x = a b
What does that mean ?  I'm not sure of the answer.
Currently, everything following the = is considered a closure that is
executed, so
> x = echo a
would mean x store the string "a".
This only works because FELIX-1325 has not been applied, so that
> x = a
also works, because executing "a" would return "a".
However,
> x = echo
would currently store "" in x, which might be confusing.
The patch for FELIX-1325 alter this behavior and reject any assignment with
multiple arguments.
So that
> x = a ; echo $x
a
> x = "echo a" ; echo $x
echo a
> x = $(echo a) ; echo $x
a

So I think the following should be written:
> x = (echo aa; (echo ab; echo ac | grep -n a | tac)) ; echo $x
  1 ab   3 ac



> and
>  > installandstart = { <installbundle <$baseURI resolve $0>> start }
>
> would become:
>  > installandstart = { $(installbundle $($baseURI resolve $0)) start }
>

Right, I agree.


>
> FWIW I still think it is possible to solve this without introducing $(),
> just by stopping <> at the start of a statement from evaluating:
>
>  ka...@root> x = <echo aa; <echo ab; echo ac | grep -n a | tac>>
>  aa
>       1  ab     3  ac
>  ka...@root> <osgi:echo a b>
>  a b
>  ka...@root> <<osgi:echo a b>>
>  a b
>  ka...@root> <<bundle 0> tostring>
>  org.apache.felix.framework [0]
>

This made me think a bit differently.  The real issue is not about grouping
/ evaluating.
Currently, the < > operator means: evaluate the command line inside and
return the value.
The real problem comes from the fact that the number of evaluations is
wrong.
So I came up with a new simplier patch that I think solve the issue while
keeping <> as you mentionned.
I've attached it to FELIX-1471 and it's available at
https://issues.apache.org/jira/secure/attachment/12417086/FELIX-1471-2.patch
It also includes a fix for FELIX-1325 and FELIX-1498, and introduce a new
"eval" keywork.
So we should have
> echo a
a
> <echo a>
a
> <<echo a>>
a
> eval echo echo a
echo a
> eval <echo echo a>
a


Let me know what you think, but this looks like a cleaner solution.



> However, the $() approach works fine too and so I'm happy to support this,
> so we can get this issue resolved.
>

> I have tested the latest FELIX-1471.patch and it mostly works OK:
>
> > echo aa; (echo ab; echo ac | grep -n a | tac)
> aa
>     1  ab     3  ac
>
> but fails when the result of () is in an assignment:
>
> ka...@root> x = (echo aa; (echo ab; echo ac | grep -n a | tac))
> org.osgi.framework.InvalidSyntaxException: expected value|substring
>        at org.apache.felix.framework.FilterImpl.<init>(FilterImpl.java:81)
>         at
> org.apache.felix.framework.Felix.getServiceReferences(Felix.java:2893)
>
> Derek
>
> 2009/8/18 Guillaume Nodet <gno...@gmail.com>
> >
> > On Tue, Aug 18, 2009 at 09:17, Derek Baum <derek.b...@paremus.com>
> wrote:
> >
> > > 2009/8/17 Guillaume Nodet <gno...@gmail.com>
> > >
> > > >
> > > > So in short, the patch does the following:
> > > >  * replace <> with $()
> > > >  * use ( ) for grouping commands when on the edge of the command
> > > >  * make the number of evaluation predictable
> > > >  * have a syntax and semantic which is mostly (fully) in sync with
> bash
> > > >  * re-evaluate / split expanded arguments that are not quoted
> > >
> > >
> > >
> > > I can still see no reason for having () and $() as two separate
> operators.
> > > This unncessarily compllicates syntax without adding any new
> capability.
> > >
> > > You previously gave the following example to demonstrate the need for a
> > > separate grouping operator:
> > >
> > > >The grouping operator is imho needed to be able to order pipes and
> > > columns:
> > > >  (echo a ; echo b) | tac
> > > >  echo a ; (echo b | tac)
> > >
> > > However, this example works fine with the existing <> execution quotes:
> > >
> > > ka...@root> <echo a; echo b> | tac
> > > ab
> > > ka...@root> echo a; <echo b | tac>
> > > a
> > > b
> > >
> > > Do you have any other example or use case that demonstrates the need
> for a
> > > separate grouping operator?
> > >
> > > () in bash is NOT only used for grouping - it executes the command
> within
> > > (), just like the existing <>.
> > > $() in bash executes and captures stdout into a string - equivalent to
> > > <command args | tac> in gogo.
> > >
> >
> > Well the key difference between those operators in bash is the number of
> > times the evaluation happen.
> >
> > ( ) does not change the number of times a command will be evaluated,
> that's
> > why i call it grouping.
> > What i mean is that if you remove the ( ), the commands will be executed
> the
> > same number of time.
> >   echo a       => echo a
> >   ( echo a )    => echo a
> >  ( ( echo a ) )   => echo a
> > All of those will produce the same result.
> >
> > $( ) will increment the number of evaluation each time it's used, and is
> > therefore not idemptotent.
> >       echo echo echo a    =>  echo echo a
> >      $(echo echo echo a)  => echo a
> >    $( $( echo echo echo a) ) => a
> >
> > I don't really see how we can conflate both operators using < > or any
> other
> > syntax.
> > With the current state of gogo, you're not really sure how many times
> > evaluation will happen.
> >
> >
> > >
> > > To try to understand the need for separate () and $() operators, I have
> > > taken the gogo TestParser.java from the FELIX-1471.patch and replaced
> both
> > > $() and () with <>. I then ran the test against the unpatched code.
> > >
> > > All tests worked except some newly added tests within
> > > testGroupingAndEvaluation() like:
> > >
> > > assertEquals("a", c.execute("<echo echo a>") + "");
> > >
> > > This fails because <echo echo a> evaluates to the String "echo a",
> which is
> > > then evaluated as a command and the command 'echo a' is not found.
> > >
> > > assertEquals("a", c.execute("$(echo echo a)") + "");
> > >
> > > This works because of the complex re-parsing done by $() that you
> describe
> > > below.
> >
> >
> > Right, and I think this reparsing of arguments should be done anyway.  So
> > maybe we need a separate jira for that one.
> >
> > I think I understood where our uncomprehension comes from.  I first
> started
> > to have a look at FELIX-1325 (throwing an exception when the can't be
> found,
> > even if it has no arguments).   The problem is that all those issues are
> > linked.
> > What you describe above works only because when you have a single token
> on
> > the command line and that no command is found, the token is simply
> returned.
> > This means that in all the above examples, the number of evaluation is
> not
> > really important, because executing "a" will return "a".
> > This hides some real issues imho, as the following tests, that all pass
> on
> > trunk show:
> >
> >        assertEquals("echo echo", c.execute("echo echo echo"));
> >        assertEquals("echo", c.execute("<echo echo echo>"));
> >        assertEquals("", c.execute("<<echo echo echo>>"));
> >
> >        assertEquals("echo a", c.execute("echo echo a"));
> >        assertEquals("a", c.execute("<echo echo a>"));
> >        assertEquals("a", c.execute("<<echo echo a>>"));
> >
> >
> > So the behavior of  < > is that it run the command(s) inside it *and*
> > evaluates it.  It's not only grouping.
> >
> > Now, let's take an example:
> >
> >        assertEquals("a", c.execute("echoout \"a\nb\" | grep a |
> capture"));
> >        assertEquals("b", c.execute("echoout \"a\nb\" | grep b |
> capture"));
> >        assertEquals("ab", c.execute("<echoout \"a\nb\" | grep a |
> capture>
> > ; <echoout \"a\nb\" | grep b | capture> | capture"));
> >
> >        assertEquals("", c.execute("<echoout \"echo\ngrep\" | grep echo |
> > capture> ; <echoout \"echo\ngrep\" | grep grep | capture> | capture"));
> >
> > The first two tests are ok.  The third test is equivalent to "test1 ;
> test2
> > | capture".
> > Remember that atm ';' takes precedence over '|'.
> >
> > Now the last test is the same as the third one, but with different
> values.
> > The output should be "echogrep", but isn't, due to the additional
> > evaluation.
> > The third test would also fail if we apply FELIX-1325 afaik.
> >
> >
> > >
> > > In bash, if you need to re-parse some text, you use the 'eval' command:
> > >
> > > $ eval $(echo echo '$HOME')
> > > /Users/derek
> > >
> > > We could take exactly the same approach in gogo, by adding a simple
> eval
> > > command for use on the rare occassions when it is required.
> > >
> > > Derek
> > >
> > >
> > >
> > > >
> > > >
> > > > I'm happy to discuss things further, but the major problem is related
> to
> > > > make the evaluation predictable, which sounds easy, but is not really
> ...
> > > > And this require to re-evaluate / split the expanded arguments.
> > > > See the following example:
> > > >        assertEquals("a", c.execute("$($(echo echo echo a)) |
> capture"));
> > > > The "echo echo echo a" command is executed and prints "echo echo a".
> This
> > > > result is inside $() so it has to be interpreted as a full command
> line,
> > > > not
> > > > as a single argument which would be a string "echo echo a" as this
> would
> > > > return a command not found.
> > > >
> > > >
> > >
> >
> >
> >
> > --
> > Cheers,
> > Guillaume Nodet
> > ------------------------
> > Blog: http://gnodet.blogspot.com/
> > ------------------------
> > Open Source SOA
> > http://fusesource.com
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Reply via email to