When programming in MatLab, I miss many features from
the C language, but for most of these features this is
quite rare, perhaps once a week or month. The one exception
is the += operator (as well as the ++ operator) which
I miss having nearly every time that I program in
Matlab - (which lately is nearly every day). I haven't
run across any way to do this in MatLab. Is there a way?
If not, doesn't this bug every body else as much as me?
For instance, suppose I have a quantity:
foobar(messy_expression1+messy_expression2).fieldxyz.somedata(tmoagf)
Now if this was c, to add two to this, one would simply append "+= 2"
However in Matlab ... well it is so ugly I can't even
bring myself to put it in this message. One has to either
repeat the whole mess which is error prone and difficult
to read, or introduce intermediate variables that
distracts one from understanding the program flow.
Other than that, Matlab suits me far better than c or
c++, partly because of the types of problems I am usually working on.
Appreciate any comments ...
Thanks
~Paul
I don't think there is a way to achieve what you are after since
Matlab passes arguments to functions by value. The closest thing
I can imagine is to write a function plusplus(x) and use it like
x = plusplus(x)
Yes, but couldn't the Mathworks put something like this
into to language? I think they can do many things that
we couldn't merely by adding our own functions.
I suspect they must have a philosophical reason for
not providing this functionality, althought I can't
imagine what that might be. (It's just too damn useful.)
> The closest thing I can imagine is to write
> a function plusplus(x) and use it like x = plusplus(x)
That doesn't help much. For one, the x=plusplus(x)
notation requires one to write the "x" twice which
is a good part of the problem. Not to mention the
readability issue.
~Paul
You could write a mex function say pp(x) that modifies the value of the
argument passed.
Here's a quick solution:
function inc(x)
evalin('caller',[x '=' x '+1;'])
then to use it you simply do the following
x=24;
inc x
now x will have the value 25
this passes the characterstring name of x to the function inc, which
increments it in the current workspace by a call to evalin.
no typing x twice!
Duane
Cute idea Duane. With some error checks added ...
John
function plusone(varname)
% increments the variable named by the character string in varname
% usage: plusone x
%
% Arguments: (input)
% varname - string containing the name of a variable to be
% incremented in the caller workspace.
if (nargin<1) || ~ischar(varname)
error('varname must be character name of a variable in caller ws')
end
try
evalin('caller',[varname '=' varname '+1;'])
catch
error(['Increment to ''',varname,''' failed'])
end
> Cute idea Duane. With some error checks added ...
> John
> function plusone(varname) ...
Yes, I like that idea.
I worry a bit about efficiency however.
Most times it doesn't matter, but it would be
nice not to have to think much about it.
For that reason I might forgo to error checks
suggested by John.
Still - even better if TMW would put it into the language :)
~Paul
makecounter.m is a demo function included only as an illustration of one
use of nested functions. If you don't like its behavior, you can make
your own function to do whatever you need. How about something like this:
function s = makeandycounter(c)
s.GetValue = @getValue;
s.IncrementValue = @incrementValue;
function v = getValue()
v = c;
end
function incrementValue()
c = c + 1;
end
end
--
Steve Eddins
Development Manager, Image Processing Group
The MathWorks, Inc.
Just out of curiosity, if += were part of MATLAB, what do you think this
should do?
% Block 1
a = 0;
a(ones(1, 10)) += 1;
a
I can think of at least two plausible answers ... and I'm sure half the
people who would use += would want one of them, and half would want the
other :)
That's not the worst case I can think of ... if you thought that one was
easy, what should these three blocks of code give?
% Block 2
a = 0;
a([1 1 1]) += a(1);
a
% Block 3
a = 0;
a([1 1 1]) += [a(1) 2 a(1)];
a
% Block 4
a = [0 0];
a([1 2 1]) += a([2 1 2]);
a
--
Steve Lord
sl...@mathworks.com
Hi Steve,
I see what you mean and I'm sure some people would want/expect some
weird things, but I'll bet *most* people would be happy if
<A> += 1
does the same thing as
<A> = <A> + 1
for all possible expressions, <A>. For example,
a(k) += 1 is equivalent to a(k) = a(k) + 1
a.field += 1 is equivalent to a.field = a.field + 1
I don't think anyone wants to do anything fancy; they just want not to
have to retype some long expression. Does anyone disagree?
I don't feel strongly about this issue myself since it doesn't add any
functionality. It's what Pythonistas (Python advocates) call "syntactic
sugar".
--
Doug Schwarz
dmschwarz&urgrad,rochester,edu
Make obvious changes to get real email address.
> > I can think of at least two plausible answers ... and I'm sure half the
> > people who would use += would want one of them, and half would want the
> > other :)
... again for brevity...
> I see what you mean and I'm sure some people would want/expect some
> weird things, but I'll bet *most* people would be happy if
>
> <A> += 1
>
> does the same thing as
>
> <A> = <A> + 1
>
> for all possible expressions, <A>. ...
I agree w/ Doug's interpretation. The other advantage TMW has is that
since Matlab is a proprietary language, any construct means exactly what
TMW decides it should mean... :)
That said, of course there will always be the odd request, but I would
think this one would be pretty well accepted as above.
I don't know what rules TMW has for determining syntax rules internally
as compared to some formal standard process, but I'm sure that just as
in any standards process for a language such as Fortran or C there would
have to be a significant amount of effort in determining where there are
possible ambiguitities for the parser and rules devised for
implementation.
In many ways, of course, one could view Matlab's whole existence is one
of "syntactic sugar" replacing loops in Fortran... :)
Perhaps you could consider it sugar, but I think
it is more meat and potatoes. After all, don't you
think you would use it in almost every program longer
than a page or two?
I've expanded on Steve's idea by creating the
function below. Pretty useful I think - although
not nearly as useful as a native += operator.
~Paul
function s = counter(c)
% examples:
%
% z = counter();
%
% z.get()
% ans = 0
%
% z.inc()
% ans = 1
%
% z.inc()
% ans = 2
%
% z.inc(199)
% ans = 201
%
% z.dec()
% ans = 200
%
% z.inc(eye(3))
% ans = [201 200 200; 200 201 200; 200 200 201]
%
%
% w = counter([10 50]);
%
% w.get()
% ans = 10 50
%
% w.inc()
% ans = 11 51
%
% w.dec(11)
% ans = 0 40
%
% w.inc([1i pi])
% ans = 0+1.0000i 43.1416
if ~nargin c=0; end;
s.get = @Cget;
s.inc = @Cinc;
s.dec = @Cdec;
function v = Cget()
v = c;
end
function v = Cinc(x)
if ~nargin x = 1; end;
c = c + x;
v = c;
end
function v = Cdec()
if ~nargin x = 1; end;
c = c - x;
v = c;
end
end
I'm not sure I understand what the problem is, but why do you have to
retype a long expression??
%A is the long expression
A='exp(k*x)+sin(x)';
%Now increase A with 1: A=A+1
%This will work with strings:
A=[A,'+1']
A =
exp(k*x)+sin(x)+1
Per
>> Duane
>
>
> Cute idea Duane. With some error checks added ...
> function plusone(varname)
> % increments the variable named by the character string in varname
> % usage: plusone x
> %
> % Arguments: (input)
> % varname - string containing the name of a variable to be
> % incremented in the caller workspace.
>
> if (nargin<1) || ~ischar(varname)
> error('varname must be character name of a variable in caller
> ws')
> end
>
> try
> evalin('caller',[varname '=' varname '+1;'])
> catch
> error(['Increment to ''',varname,''' failed'])
> end
>
I always include generous error checking in code I write, especially
if it is meant for public consumption. I didn't in this case because
I didn't want anything to cloud the simplicity of the solution.
You could/should include calls to the function exist to see if the
variable exists in the caller workspace. You could/should check to
see if the variable contained numeric data.
Or you could just let MATLAB return whatever error it wanted when you
did something silly, which is what my original function would do.
Or you could do nothing more than use the try-catch block you used to
hide the MATLAB error and report silliness to the user.
Duane
> > I don't feel strongly about this issue myself since it
> > doesn't add any functionality. It's what Pythonistas
> > (Python advocates) call "syntactic sugar".
> > Doug Schwarz
>
> Perhaps you could consider it sugar, but I think
> it is more meat and potatoes. After all, don't you
> think you would use it in almost every program longer
> than a page or two?
Perhaps we write different kinds of programs. I use that paradigm only
occasionally. I do agree that += would be nice to have as long as there
are no unforeseen consequences. So now we sit back and see if anyone
can think of any.
Consider something like:
A(a+b+c+d) = A(a+b+c+d) + 5;
If the variable names are suitable discriptive,
that expression would start to get uncomfortably
long. One choice would be:
temp = a+b+c+d;
A(temp) = A(temp) + 5;
although this introduces a variable that doesn't really
add any clearity to the program. Wouldn't this be better?
A(a+b+c+d) += 5;
As ones data structures become more complicated, this problem gets
worse.
The counter program doesn't really help for this
situation, although the "inc" function suggested
earlier could help. For the above we could write:
inc A(a+b+c+c) 5;
where inc is defined in the function below.
By the way, can anyone tell me how to combine
the two evalin calls in this function into a
single evalin call?
> I do agree that += would be nice to have as long as
> there are no unforeseen consequences.
> Doug Schwarz
There are just about always unforeseen consequences :)
----------------------------------------------------
function v = inc(x,i)
% examples:
%
% >> abc = [3 33];
% >> inc abc
% ans = 4 34
%
% >> inc abc 100
% ans = 104 134
%
% >> a.field1 = 5;
% >> a.field2 = [2 4 6 8];
%
% >> inc a.field1
% ans = 6
% >> inc a.field2 100
% ans = 102 104 106 108
%
% >> inc a.field2(3) 100
% ans = 206
%
% >> a.field2
% ans = 102 104 206 108
if nargin<2 i = '1'; end;
evalin('caller',[x '=' x '+' i ';']);
v = evalin('caller',x);
% end of function inc ------------
But there are 2 credible ways (maybe more?) to look at the expression
Steve wrote -- which is the problem: a(k) += 1
if k has repeated indices -- which is what Steve was trying to get at.
They both map to reasonable behavior.
1) a(k) = a(k) + 1;
for repeated k, a(k) would only increase by 1
2) for ind = 1:length(k)
a(k(i)) = a(k(i)) + 1;
end
for repeated k, a(k) would have the +1 statements accumulate
So that's the main conundrum - what behavior to have with repeated
indices. We've asked before and gotten mixed answers before. Feel free
to add your own thoughts now.
--Loren
Consider something like:
A(a+b+c+d) = A(a+b+c+d) + 5;
If the variable names are suitable discriptive,
that expression would start to get uncomfortably
long. One choice would be:
temp = a+b+c+d;
A(temp) = A(temp) + 5;
although this introduces a variable that doesn't really
add any clearity to the program. Wouldn't this be better?
A(a+b+c+d) += 5;
%%%
It is better to structurize your fileds!
Exemple below:
arguments={'Length','displacement','factor'};
%known variables of course!
fun='Meanspreaddistance'; %instead of A
expr=[fun,'(',arguments{1}];
for j=2:length(arguments)
expr=[expr,'+',arguments{j}];
end
expr=[expr,')'];
%Now operate on expr: A=A+5 or whatever
%apply multiple times is ok...
expr=[expr,'+5']
expr=['(',expr,')^2']
expr=['(',expr,')^2']
expr =
((Meanspreaddistance(Length+displacement+factor)+5)^2)^2
/Per
> In article <see-71ED10.1...@news.frontiernet.net>,
> s...@sig.for.address.edu says...
[snip]
> > ... I'll bet *most* people would be happy if
> >
> > <A> += 1
> >
> > does the same thing as
> >
> > <A> = <A> + 1
> >
> > for all possible expressions, <A>. For example,
> >
> > a(k) += 1 is equivalent to a(k) = a(k) + 1
> >
> > a.field += 1 is equivalent to a.field = a.field + 1
[snip]
>
> But there are 2 credible ways (maybe more?) to look at the expression
> Steve wrote -- which is the problem: a(k) += 1
>
> if k has repeated indices -- which is what Steve was trying to get at.
> They both map to reasonable behavior.
>
> 1) a(k) = a(k) + 1;
> for repeated k, a(k) would only increase by 1
> 2) for ind = 1:length(k)
> a(k(i)) = a(k(i)) + 1;
> end
> for repeated k, a(k) would have the +1 statements accumulate
>
> So that's the main conundrum - what behavior to have with repeated
> indices. We've asked before and gotten mixed answers before. Feel free
> to add your own thoughts now.
>
> --Loren
Hi Loren,
I understand completely about the repeated indices. I think, for
simplicity, that MATLAB should treat += as I described above. In other
words, all the += will do is obviate writing a complicated expression
twice, but will do the same thing as if it was there twice, warts and
all. So,
<expression 1> += <expression 2>
will do the same thing as
<expression 1> = <expression 1> + <expression 2>
always, including evaluating <expression 1> twice unless you know that
it won't make a difference. (In general, an index could be a function
evaluation with side effects.)
I don't think anyone asking for this feature wants to do anything fancy
with accumulation. You have to define what it will do in these unusual
cases, of course, but I don't think it matters very much as long as it
is spelled out in the documentation.