Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: zmathfunc: min, max, sum throw error if result equals 0
- X-seq: zsh-workers 48606
- From: Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: Re: zmathfunc: min, max, sum throw error if result equals 0
- Date: Fri, 16 Apr 2021 19:50:28 +0000
- Archived-at: <https://zsh.org/workers/48606>
- In-reply-to: <CAH+w=7ZFbOJc16r6JX4Lr6uPdVRji_=RmY3WZVBK9GtXzxjPmA@mail.gmail.com>
- List-id: <zsh-workers.zsh.org>
- References: <m2pn0aj4y2.fsf@zaclys.net> <20210307171712.GA9936@tarpaulin.shahaf.local2> <CAH+w=7bPz5u9-mQPbmPmbo=8Cz8em7JmbSn-sp8eZzuvFW3mnQ@mail.gmail.com> <ee7c107d-8bfb-4063-85e8-a7638ae0f951@www.fastmail.com> <CAH+w=7ZFbOJc16r6JX4Lr6uPdVRji_=RmY3WZVBK9GtXzxjPmA@mail.gmail.com>
Again sorry for the delay on getting back to this.
Bart Schaefer wrote on Sun, Mar 07, 2021 at 18:25:00 -0800:
> On Sun, Mar 7, 2021 at 1:57 PM Daniel Shahaf <d.s@xxxxxxxxxxxxxxxxxx> wrote:
> >
> > Bart Schaefer wrote on Sun, 07 Mar 2021 21:39 +00:00:
> >
> > > Is it worth testing invalid cases? Such as uses outside math context
> > > where the arguments are not syntax checked?
> >
> > If you have ideas, feel free to write them and post them; I'll
> > transplant them into Z02 once I have committed it.
>
> One possibility below; I'll follow up if I think of more.
>
> With your patch adding "true" at the end, we get this:
>
> % zsh_math_func_min "foo bar" x y z
> zsh_math_func_min:7: bad math expression: operator expected at `bar'
> zsh_math_func_min:7: bad math expression: operator expected at `bar'
> zsh_math_func_min:7: bad math expression: operator expected at `bar'
> zsh_math_func_min:9: bad math expression: operator expected at `bar'
> toltec-ubuntu% echo $?
> 0
>
> Doesn't seem as though anything that prints that many error messages
> should return zero.
>
Patch below.
> > > Because of the way math context works, if any of $@ is a string that
> > > can be interpreted as a math expression, the above will evaluate it at
> > > least twice (and up to $# times in the case of $1). This could have
> > > side-effects.
> >
> > Could you post a regression test for this?
>
> In thinking more about it, I believe this only matters when the
> function is called outside of math context. In math context, the
> arguments are all going to be evaluated down to numbers before they
> are passed to the function.
>
> % (( x = 0 )); zsh_math_func_min "x += 2" 4 5 6
> % print $x
> 8
> % (( (x = 0), min("x += 2", 4, 5, 6) ))
> % print $x
> 2
I see. Still, going to fix this, if only because those min() max()
sum() implementations are virtually the only example of `functions -M`
in the tree, and it'd be good to have a complete example.
> > Related to code as it is in master, are «(( $arg < result ))» and
> > «(( arg < result ))» equivalent?
>
> No, but again math context matters.
>
> % arg="x += 2" x=0 result=0
> % (( $arg > result )) && result=$arg
> % print $result $x $(( result )) $x
> x += 2 1 3 3
> % x=0 result=0
> % (( arg > result )) && (( result=arg ))
> % print $result $x $(( result )) $x
> 4 4 4 4
Nice. So the first one interpolates $arg as in double-quoted strings
and then parses the string " x += 2 > result ", where the > operator has
higher precedence, and «2 > result» evaluates to 1, and the «print» then
evaluates everything left to right; whereas the latter sees «arg» and
tries to evaluate that _as a number_, which works out to 2 (with a side
effect), so the condition evaluates to true, and the assignment on the
RHS then works out to 4 (with a side effect). Clear as a cloudless day ☺
Many thanks.
Daniel
diff --git a/Functions/Math/zmathfunc b/Functions/Math/zmathfunc
index 8e4b78549..28f21e562 100644
--- a/Functions/Math/zmathfunc
+++ b/Functions/Math/zmathfunc
@@ -6,7 +6,12 @@ zsh_math_func_min() {
shift
local arg
for arg ; do
- (( $arg < result )) && result=$arg
+ (( $arg < result ))
+ case $? in
+ (0) result=$arg;;
+ (1) ;;
+ (*) return $?;;
+ esac
done
(( result ))
true # Careful here: `return 0` evaluates an arithmetic expression
@@ -19,7 +24,12 @@ zsh_math_func_max() {
shift
local arg
for arg ; do
- (( $arg > result )) && result=$arg
+ (( $arg > result ))
+ case $? in
+ (0) result=$arg;;
+ (1) ;;
+ (*) return $?;;
+ esac
done
(( result ))
true # Careful here: `return 0` evaluates an arithmetic expression
@@ -31,7 +41,7 @@ zsh_math_func_sum() {
local sum
local arg
for arg ; do
- (( sum += $arg ))
+ (( sum += arg ))
done
(( sum ))
true # Careful here: `return 0` evaluates an arithmetic expression
- References:
- zmathfunc: min, max, sum throw error if result equals 0
- Re: zmathfunc: min, max, sum throw error if result equals 0
- Re: zmathfunc: min, max, sum throw error if result equals 0
- Re: zmathfunc: min, max, sum throw error if result equals 0
- Re: zmathfunc: min, max, sum throw error if result equals 0
Messages sorted by:
Reverse Date,
Date,
Thread,
Author