Inside a procedure, local variables are evaluated only one level. Of what good is this, one might ask?

Well, for one thing it allows you to do checks or manipulations of an unevaluated function call without having that function call be evaluated over again. I mean, for function calls to routines which don't happen to remember earlier results.

This is a revision of an Answer of a while back. I think it's worth repeating, or making more clear. Consider fsolve. It doesn't have `option remember`, so it doesn't remember earlier results. That's probably a good thing since if it did then it would have to also take account of environment ascpects like Digits (or else go wrong like this...).

And when fsolve doesn't find a root it (generally, except for maybe univariate polynomials and trivial cases, or bugs) returns unevaluated.

This behaviour quite often makes sense, since it doesn't do much symbolic analysis and doesn't set out to prove whether there is a root or not. It's not `solve`. Failure by fsolve to find a root might just be because it wasn't lucky enough in choosing initial guesses, etc. (If you really don't like `fsolve` as the example here, then just think of some routine you write yourself, without option remember.)

The issue is: how can you test whether the "result" is some number or just an unevaluated function call. How do you test for success?

Let's try it using a type-check, and we'll do it both inside a procedure as well as at the "top-level" (ie. outside any procedure). What we'll see is that inside a procedure it take about half the time.

First, let's run some code all outside any procedure (ie. at the top-level).

> restart:

> res := fsolve(exp(t^2*4)-0.333, t); # ...returns unevaluated

/ / 2\ \
fsolve\exp\4 t / - 0.333, t/

> if type(res,numeric) then
> res;
> else
> "no solution found";
> end if;

"no solution found"

> st:=time():
> for i from 1 to 10 do
> # these will all fail
> res := fsolve(exp(t^2*i)-0.333, t);
> if type(res,numeric) then
> res;
> else
> "no solution found";
> end if;
> end do:
> time()-st;

7.375

Now let's repeat all that in a new session, but doing each computation and type-check test inside a procedure that we create.

> restart:

> p := proc(x)
> local res;
> res := fsolve(exp(t^2*x)-0.333, t);
> if type(res,numeric) then
> res;
> else
> "no solution found";
> end if;
> end proc:

> p(4);

"no solution found"

> st:=time():
> for i from 1 to 10 do
> p(i); # these will all fail
> end do:
> time()-st;

4.313

The difference is because at the top-level the invocations of

  type(res, numeric)

will cause res to get fully evaluated once more. And if res has been assigned an unevaluated `fsolve` function call then that evaluation will make fsolve get called all over again. So at the top-level the failing fsolve calls each get done twice.

We can demonstrate that this duplicated effort actually happens. We'll start a new session. First we'll do the original attempt, and assign the failed result (unevaluated function call) to `res`.

> restart:
> infolevel[fsolve]:=2: # to show that it does the work

> res := fsolve(exp(t^2*4)-0.333, t);

fsolve/TestOneIteratorMulti: Secant3 with initial point: 0 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 1 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -1/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -13/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -5/11 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -29/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -27/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -19/13 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 27/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -61/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -49/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -45/19 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -33/31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 11/53 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 33/31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 43/21 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 49/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 57/7 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 63 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -125/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -123/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -119/9 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -113/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -105/23 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -99/29 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -91/37 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -61/67 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -51/77 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -19/109 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -7/121 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -1/127 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 1/127 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 65/63 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 87/41 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 89/39 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 99/29 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 101/27 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 105/23 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 117/11 0

/ / 2\ \
fsolve\exp\4 t / - 0.333, t/

And now we'll do the type-check, again at the top-level,

> if type(res,numeric) then
> res;
> else
> "no solution found";
> end if;

fsolve/TestOneIteratorMulti: Secant3 with initial point: 0 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 1 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -1/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -13/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -5/11 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -29/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -27/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -19/13 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 27/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -61/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -49/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -45/19 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -33/31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 11/53 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 33/31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 43/21 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 49/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 57/7 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 63 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -125/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -123/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -119/9 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -113/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -105/23 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -99/29 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -91/37 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -61/67 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -51/77 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -19/109 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -7/121 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -1/127 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 1/127 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 65/63 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 87/41 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 89/39 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 99/29 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 101/27 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 105/23 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 117/11 0

"no solution found"

So there you have it. A complete duplication of the failed attempt, just while trying to check whether the result was numeric (ie. success). When done inside a procedure, that duplicated computation is not done. The computational effort is made just once.

> restart:

> infolevel[fsolve]:=2:

> p := proc(x)
> local res;
> res := fsolve(exp(t^2*x)-0.333, t);
> if type(res,numeric) then
> res;
> else
> "no solution found";
> end if;
> end proc:

> p(4);

fsolve/TestOneIteratorMulti: Secant3 with initial point: 0 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 1 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -1/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -13/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -5/11 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -29/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -27/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -19/13 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 27/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -61/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -49/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -45/19 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -33/31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 11/53 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 33/31 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 43/21 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 49/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 57/7 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 63 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -125/3 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -123/5 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -119/9 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -113/15 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -105/23 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -99/29 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -91/37 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -61/67 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -51/77 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -19/109 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -7/121 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: -1/127 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 1/127 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 65/63 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 87/41 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 89/39 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 99/29 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 101/27 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 105/23 0
fsolve/TestOneIteratorMulti: Secant3 with initial point: 117/11 0

"no solution found"

This is just one of many ways in which using procedures can benefit your Maple use.

acer


Please Wait...