Order of Evaluation

classic Classic list List threaded Threaded
5 messages Options
fi
Reply | Threaded
Open this post in threaded view
|

Order of Evaluation

fi
Dear List,

consider the following functions (assumed free of side effects). The
functions themself do not matter. Here are some simple examples for
clearness:


f = @(x) x .^ pi + log(x);   % ... some expression ...
g = @(x) sin(x) * exp(-x/5); % ... another expression ...
h = @(x) sqrt(x .^ cos(x));  % ... normally a costly (in time) expression ...

% and last:

y = @(x) f(h(x)) + g(h(x));

% here h(x) will be evaluated twice. This is inefficient, especially
% if y() is evaluated frequently (e.g. in finding roots or
% integrating).
%
% Unfortunately Octave (like Matlab) does not have a sequence operator like C.
% So constructs like the following lead to syntax errors:

y = @(x) H = h(x), f(H) + g(H); % also wrong if in brackets

% The only idea I found was:

y = @(x) f(H = h(x)) + g(H);

This works, but is this safe? Does Octave guarantee to evaluate
expressions like sums or products from left to right?  Will this hold
for the future? What if some day Octave will be parallelized and the
summands are caculated indepentently from each other? Is there any
way to calculate H definitively in advance inside y()?



Best Regards

Torsten Finke



--
------------------------------------------------------------------------
Torsten Finke
[hidden email]
------------------------------------------------------------------------


Reply | Threaded
Open this post in threaded view
|

Re: Order of Evaluation

Mike Miller-4
On Mon, Aug 19, 2019 at 20:56:00 +0200, [hidden email] wrote:

> Dear List,
>
> consider the following functions (assumed free of side effects). The
> functions themself do not matter. Here are some simple examples for
> clearness:
>
>
> f = @(x) x .^ pi + log(x);   % ... some expression ...
> g = @(x) sin(x) * exp(-x/5); % ... another expression ...
> h = @(x) sqrt(x .^ cos(x));  % ... normally a costly (in time) expression ...
>
> % and last:
>
> y = @(x) f(h(x)) + g(h(x));
>
> % here h(x) will be evaluated twice. This is inefficient, especially
> % if y() is evaluated frequently (e.g. in finding roots or
> % integrating).
> %
> % Unfortunately Octave (like Matlab) does not have a sequence operator like C.
> % So constructs like the following lead to syntax errors:
>
> y = @(x) H = h(x), f(H) + g(H); % also wrong if in brackets
>
> % The only idea I found was:
>
> y = @(x) f(H = h(x)) + g(H);
You could try using eval or evalin to evaluate a compound expression
inside an anonymous function, for example

    y = @(x) evalin ("caller", "H = h(x); f(H) + g(H)");

Couldn't you simply define another auxiliary y1 function, for example

    y1 = @(x) f(x) + g(x);
    y = @(x) y1(h(x));

Lastly, you could define y as a true function rather than an anonymous
function

    function res = y(x); H = h(x); res = f(H) + g(H); endfunction

Is there a reason to constrain yourself to use only anonymous functions?

--
mike



signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Order of Evaluation

Octave - General mailing list
In reply to this post by fi
On 8/19/19 2:56 PM, [hidden email] wrote:
y = @(x) H = h(x), f(H) + g(H); % also wrong if in brackets

I thought it would work to create a 'fake' compound statement:

y = @(x) if true  H = h(x), f(H) + g(H) end;

but this somehow fails, as if the conditional was not evaluated---the function does not return anything.

Given that  "if true 123 end" returns 123, and "y = @(x) 123 ;" returns a function returning 123, why does

y = @(x) if true 123 end ;

fail to return anything? (Octave 4.2.2 on Linux)

In any case, https://octave.org/doc/v4.2.0/Anonymous-Functions.html suggests that anonymous functions aren't universally useful and recommends simply using function handles.




fi
Reply | Threaded
Open this post in threaded view
|

Re: Order of Evaluation

fi
On Mon, Aug 19, 2019 at 06:37:41PM -0400, Przemek Klosowski via Help list for GNU Octave wrote:

> On 8/19/19 2:56 PM, [hidden email] wrote:

> >y = @(x) H = h(x), f(H) + g(H); % also wrong if in brackets
>
> I thought it would work to create a 'fake' compound statement:
>
> y = @(x) if true  H = h(x), f(H) + g(H) end;
>
> but this somehow fails, as if the conditional was not evaluated---the
> function does not return anything.
>
> Given that  "if true 123 end" returns 123, and "y = @(x) 123 ;" returns a
> function returning 123, why does
>
> y = @(x) if true 123 end ;
>
> fail to return anything? (Octave 4.2.2 on Linux)

I think Octave does this because Matlab does it.

It seems, that only real expressions (that are composed from operator
which really return a value) are allowed in anonymous
functions. The if clause seems to be interpreted as a statement which
does not return anything. There are other examples: the statement

y = x = 3; % will fail in Matlab, because assignment is a statement
           % and not an operation.

In Octave the assigment is an operation which returns a value and so
Octave accepts multiple assignment.


> In any case, https://octave.org/doc/v4.2.0/Anonymous-Functions.html suggests
> that anonymous functions aren't universally useful and recommends simply
> using function handles.

yes, but in this case my expressions are basically simple and I try to
increase the performance (which I believe is an advantage of anonymous
functions).




Best Regards

Torsten Finke






--
------------------------------------------------------------------------
Dr.-Ing. Torsten Finke
[hidden email]
GnuPG-Key: 1024D/8F2300D8
Fingerprint: B929 7FA5 4D2E E9B6 C55C  8A0B 7DF4 86E9 8F23 00D8
------------------------------------------------------------------------


fi
Reply | Threaded
Open this post in threaded view
|

Re: Order of Evaluation

fi
In reply to this post by Mike Miller-4
On Mon, Aug 19, 2019 at 03:17:00PM -0700, Mike Miller wrote:

> On Mon, Aug 19, 2019 at 20:56:00 +0200, [hidden email] wrote:
> > Dear List,
> >
> > consider the following functions (assumed free of side effects). The
> > functions themself do not matter. Here are some simple examples for
> > clearness:
> >
> >
> > f = @(x) x .^ pi + log(x);   % ... some expression ...
> > g = @(x) sin(x) * exp(-x/5); % ... another expression ...
> > h = @(x) sqrt(x .^ cos(x));  % ... normally a costly (in time) expression ...
> >
> > % and last:
> >
> > y = @(x) f(h(x)) + g(h(x));
> >
> > % here h(x) will be evaluated twice. This is inefficient, especially
> > % if y() is evaluated frequently (e.g. in finding roots or
> > % integrating).
> > %
> > % Unfortunately Octave (like Matlab) does not have a sequence operator like C.
> > % So constructs like the following lead to syntax errors:
> >
> > y = @(x) H = h(x), f(H) + g(H); % also wrong if in brackets
> >
> > % The only idea I found was:
> >
> > y = @(x) f(H = h(x)) + g(H);
>
> You could try using eval or evalin to evaluate a compound expression
> inside an anonymous function, for example
>
>     y = @(x) evalin ("caller", "H = h(x); f(H) + g(H)");

that is an interesting application of the somewhat exotiv
"evalin()". But I am afraid, that the evaluation could have a
performance impact. My goal was to increase the performance as much as
possible.


> Couldn't you simply define another auxiliary y1 function, for example
>
>     y1 = @(x) f(x) + g(x);
>     y = @(x) y1(h(x));

This trick is great and it is robust even if the order of evaluation
is not guaranteed.


> Lastly, you could define y as a true function rather than an anonymous
> function
>
>     function res = y(x); H = h(x); res = f(H) + g(H); endfunction
>
> Is there a reason to constrain yourself to use only anonymous functions?

I have noticed, that anonymous functions are handled faster than true
functions (but maybe this is wrong for recent versions of Octave). My
expressions are basically simple and my goal was maximum performance
(because evaluation takes place frequently).



Thanks for your advice and

best regards

Torsten Finke







--
------------------------------------------------------------------------
Dr.-Ing. Torsten Finke
[hidden email]
GnuPG-Key: 1024D/8F2300D8
Fingerprint: B929 7FA5 4D2E E9B6 C55C  8A0B 7DF4 86E9 8F23 00D8
------------------------------------------------------------------------