|
"Jim Mutch" <jmutch@mit.edu> wrote in message
news:kid2oc$r51$1@newscl01ah.mathworks.com...
> "Steven_Lord" <slord@mathworks.com> wrote in message
> <kicgmk$okd$1@newscl01ah.mathworks.com>...
>
>> I know that you've seen the implementation I wrote in that message. I'm
>> guessing that didn't satisfy your needs -- what about it didn't?
>
>> Also, out of curiosity what would you expect z to contain after executing
>> the following code , assuming that MATLAB defined the operator using the
>> syntax (A ? B : C) [which I believe it would not, since the question mark
>> and COLON already have meanings in MATLAB. The question mark wouldn't be
>> ambiguous in most (or maybe even any) situations; the colon definitely
>> would in some common scenarios.(*)]
>>
>> A = eye(5);
>> B = magic(5);
>> C = ones(5);
>> z = A ? B : C
>
> I assume you mean the QUESTIONCOLON function.
Yes.
> What's missing is the short-circuiting of evaluation.
No.
> In C/C++, when you have the expression (A ? B : C) and A is false, the
> expression for B is never even *evaluated*. Similarly, if A is true, then
> the expression for C is never evaluated. This serves two purposes. (1)
> It saves execution time. (2) It lets you use "?:" to test for conditions
> under which an expression is invalid, in order to supply an alternative.
> For scalar inputs (which is all you have in C/C++) this works great. The
> original question was about sin(x) / x. In C/C++ you could just write:
>
> y = (x == 0) ? 1 : sin(x) / x;
>
> When (x == 0), the expression sin(x) / x is not even evaluated. (I have
> read the remarks about numerical instability near 0, and don't really want
> to get into it. This is just an example. My point is very general.)
>
> QUESTIONCOLON doesn't accomplish this. Both possible values, x1 and x2,
> get computed before QUESTIONCOLON even starts executing. Then it decides
> which one to use and which one to throw away. By that point, time has
> already been expended to compute both values, and any errors/warnings have
> already occurred.
Well, yes, x1 and x2 need to be evaluated since they're input arguments to
QUESTIONCOLON and so we need to know what to put in its workspace. But no,
no errors will be thrown or warnings issued unless you define the inputs
incorrectly. Let me copy that function and its help text here for reference.
function y = questioncolon(condition, x1, x2)
% QUESTIONCOLON M-file for C's ?: ternary operator
% Syntax: y = questioncolon(condition, x1, x2)
%
% The elements of the output matrix will be set as:
% y(condition==true) = x1(condition==true)
% y(condition==false) = x2(condition==false)
%
% x1 and x2 can be function handles or matrices the same size as condition
%
% Example:
% x = -10:10;
% y = questioncolon(x==0, @(z) 1, @(z) sin(x(z))./x(z));
y = zeros(size(condition));
y(condition) = x1(condition);
y(~condition) = x2(~condition);
In the example, note that the second and third inputs to QUESTIONCOLON are
_anonymous functions_ not numeric arrays. If you use that syntax yes, MATLAB
will need to construct those anonymous functions as part of calling the
function. But it will NOT call SIN or perform the division until the last
line of the function and will ONLY call SIN and perform the division for
those elements of x where (x == 0) is false (i.e. x ~= 0). If all the
elements of x are zero, that's going to be a pretty quick calculation. It's
not exactly short-circuiting, but it's pretty close.
x = zeros(1, 1e6);
z = ~(x == 0);
tic;
sin(x(z))./x(z);
toc
> I don't care about the specific syntax being the same as C/C++; I just
> want equivalent functionality. I want it to work just like an IF
> statement, but in a single expression. Maybe even use the same words?
> For example:
>
> X = if A then B else C;
That's already valid MATLAB syntax if you remove the then and add some
commas, though it's not a single expression (and so is not eligible to be
used in an anonymous function.)
> This would be semantically equivalent to:
>
> if A then
> X = B; % only executed if A is true!
> else
> X = C; % only executed if A is false!
> end
>
> Now, I don't see a way of defining something like this for nonscalar
> inputs that includes short-circuiting. And since short-circuiting is
> really the only good reason for requesting a language feature, instead of
> just using something like QUESTIONCOLON, I say don't even try. I want
> something that works like an IF statement. IF statements aren't
> vectorized either: I believe if the condition returns a nonscalar result,
> for an IF statement there is an implicit "any()" around the condition.
> You go one way or the other, and only once.
ALL, not ANY.
> Under this definition, the answer to your example is that it would return
> exactly magic(5).
Given that IF does ALL, I think it's safe to amend your respond to ones(5)
since not ALL the elements of A are nonzero. But yes, that's one
possibility.
> If anyone can think of a reasonable way to define "?:" for nonscalar
> inputs that includes short-circuiting I'd be curious to hear it.
Eric Sampson posted the second possibility in his message, using elements of
B corresponding to true elements in the condition and elements of C
corresponding to false elements in the condition. If this hypothetical
ternary operator behaved this way, it may be reasonable that if ALL the
elements in the condition were true or false we could skip executing the
other piece entirely.
The third possibility I thought of would be to do what the short-circuit AND
and OR operators do. Compare
thisWorks = (1:10 == 5) | (1:10 == 7) % non-short-circuiting
thisDoesNotWork = (1:10 == 5) || (1:10 == 7) % short-circuiting
http://www.mathworks.com/help/matlab/ref/or.html
That may be a wee bit too strict, though.
--
Steve Lord
slord@mathworks.com
To contact Technical Support use the Contact Us link on
http://www.mathworks.com
|