On Fri, 14 May 2010 06:57:17 you wrote:
> Le 12/05/2010 07:33, Andrew Clarke a écrit :
> <snip>
> 
> > Ok, that's what I was thinking. My original expression was a bit
> > more complex than this:
> >
> >      if [[ -n "$list" || ( $# -gt 1 &&  -t 0 &&  -t 1 ) ]]; then
> 
> well, in the current case, there is no really advantage of using ((
>  )) somewhere.
> 
True - if it can't be done. The old [[ ]] allows it to be simple without 
excessive tokens. I've already learned so much about (( )) and it's 
limits - thanks guys

> if you dislike the -gt, you may use > in place, the result will be
>  the same :
> 
>        if [[ -n "$list" || ( $# > 1 && -t 0 && -t 1 ) ]]; then
> 
Not quite. compare:

if [[ 3 > 2 ]]; then echo yes; else echo no; fi
if [[ 10 > 2 ]]; then echo yes; else echo no; fi

-gt is arithmetic, > is string. I wonder how many scripts have this 
lurking as an occasionally manifested bug?

I am not concerned with using -gt style operators. They keep springing 
up in languages (I've most recently seen it in Windows Powershell) and I 
have no moral objection to their existence in that syntactical form.

However, I realise that the ( ) in my very first expression is 
redundant. I remember a time when [[ ]] did not seem to like more than 
one && or || in a row. Back on HP-UX 10 I think, or maybe more recently. 
I've had that "workaround" as a habit for a long time too.

> > Where list can be '' or 1
> >
> > the -n "$list" can be substituted with ((list)) as long as the
> > unset value of $list is set to 0 - but then the expression maps to:
> >
> >      if (( $# > 1 )) && [[ -t 0 &&  -t 1 ]] || ((list)); then
> 
> IMHO, this is not equivalent to the first expression; it would
>  something like be :
> 
>        if ( (( $# > 1 )) && [[ -t 0 &&  -t 1 ]] ) || ((list)); then
> or
>        if ( (( $# > 1 )) && [[ -t 0 &&  -t 1 ]] ) || [[ -n ${list}
>  ]]; then
> 
> note the ( ... )
> 

I tested that before posting and I think I'm correct. In lists of 
command pipelines, || and && have the same precedence in that part of 
the ksh grammar. So putting the test of $list to the end makes the flow 
correct. Here's a test which shows that my un-parenthesized version is a 
correct equivalent, and also how a naive rewrite would be wrong due to 
the equal precedence of || and &&.

while read a b c; do
    echo -n $a $b $c :

    # intention: fully parenthesized
    if [[ $a -eq 1 || ( $b -eq 1 && $c -eq 1 ) ]]
      then echo -n " A=T"
      else echo -n " A=F"
    fi

    # possible unparenth'd rewrite which is wrong
    if ((a)) || ((b)) && ((c))
      then echo -n " B=T"
      else echo -n " B=F"
    fi

    # my rewrite (equivalent)
    if ((b)) && ((c)) || ((a))
      then echo -n " C=T"
      else echo -n " C=F"
    fi

    # your rewrite
    if ( ((b)) && ((c)) ) || ((a))
      then echo -n " D=T"
      else echo -n " D=F"
    fi

    echo
done <<++
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
++

I agree it's a bit tragic to see:

"The symbols && and || also have equal precedence."

in the shell man pages for lists (section Commands, discussing simple 
commands, pipelines and lists) but that's the way it is.



_______________________________________________
ast-users mailing list
[email protected]
https://mailman.research.att.com/mailman/listinfo/ast-users

Reply via email to