Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: zmathfunc: min, max, sum throw error if result equals 0



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




Messages sorted by: Reverse Date, Date, Thread, Author