Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
eval, feval, global

Subject: eval, feval, global

From: Yuri Geshelin

Date: 26 Mar, 2008 20:25:05

Message: 1 of 50

1) Why are eval, feval considered not elegant and banned in
programming contests? I often use eval, why should a good
programmer stay away from it?

2) Same question about GLOBAL.

Yuri

Subject: eval, feval, global

From: John D'Errico

Date: 26 Mar, 2008 20:54:02

Message: 2 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<fsebf0$43u$1@fred.mathworks.com>...
> 1) Why are eval, feval considered not elegant and banned in
> programming contests? I often use eval, why should a good
> programmer stay away from it?
>
> 2) Same question about GLOBAL.
>
> Yuri

I use eval, well almost never.

If you are using eval to create variable names,
especially sequences of variables, this is poor
coding style. Use an array instead. After all
Matlab is designed to work with arrays. Eval
is evil.

In terms of programming contests, I think I
recall that there were some potential hacking
issues with eval.

As for globals, again, I never use global
variables. I can't think of a use I've had
for them for many years. They can make
debugging an interesting task. And since
all they do is change how variables are
passed around, why bother with them?
Stuff your parameters into a structure that
gets passed around. Use nested functions.

Its like goto. Yes, you can use the construct,
but there are just too many good alternatives,
and the net result of gotos liberally spread
around your code is almost always bad. The
same logic applies to globals. They encourage
sloppy programming.

John

Subject: eval, feval, global

From: Matthew Simoneau

Date: 26 Mar, 2008 21:42:01

Message: 3 of 50

Hi Yuri,

EVAL should rarely be used. Most of the time, there's a
much more efficient way to accomplish the same thing. Here
are some notes on this subject:

http://www.mathworks.com/support/tech-notes/1100/1103.html

The use of global variables is debatable, but there's
nothing at all wrong with FEVAL. In fact, there are some
nice programming patterns that you can implement no other way.

All that being said, the reason these are banned from the
contest has nothing to do with good programming practices.
These constructs are banned to increase the security in the
environment which automatically scores the entries.

Thanks for your interest,
Matthew

Subject: eval, feval, global

From: Peter Boettcher

Date: 26 Mar, 2008 22:01:39

Message: 4 of 50

"Yuri Geshelin" <geshelin@hotmail.com> writes:

> 1) Why are eval, feval considered not elegant and banned in
> programming contests? I often use eval, why should a good programmer
> stay away from it?

It is hard for MATLAB to accelerate (slow) and it creates hard-to-read
code. There is usually an alternative with dynamic field names of
structures, arrays, cell arrays, etc.

If there's a code pattern you think you need eval for, post it here, and
see if we can help.


-Peter

Subject: eval, feval, global

From: Yuri Geshelin

Date: 27 Mar, 2008 03:22:04

Message: 5 of 50

Thanks to everyone who replied. I agree with John about
GLOBAL.

As for EVAL, as Peter suggested, let me show you my code,
which I found useful.

(Actually, there are two situations, in which I use EVAL,
but I will start with presenting the 1st one, as it is
perhaps the more controversial.)

Suppose we have 2 arrays of equal length:

a = [15 23 35 43];
b = [ 2 11 8 3];

and we need an algorithm, which constructs output array c
as follows:

c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
43 43]

Here is a simple function construct_array1, which
accomplishes this task.

% *************************** top of construct_array1
function c = construct_array1(a,b)

c = [];
for i = 1 : length(a)
    c = [c ones(1,b(i))*a(i)];
end

% *************************** end of construct_array1

And here is another function construct_array, which
accomplishes the same task.

% *************************** top of construct_array
function c = construct_array(a,b)

if length(a) ~= length(b)
    error('arrays a and b should be of equal lengths!')
end

k = floor(log10(max(a)))+1;
i = floor(log10(max(b)))+1;
n = length(a);
m = ones(n,1);
c = eval(['[' ...
    reshape([char([m*'o' m*'n' m*'e' m*'s' m*'(' m*'1'
m*',']) ...
    reshape(sprintf(['%' num2str(i) 'd'],b),i,n)' ...
    char([m*')' m*'*']) ...
    reshape(sprintf(['%' num2str(k) 'd'],a),k,n)' ...
    char(m*' ')]',1,n*(k+i+10)) ']']);
% *************************** end of construct_array

Think this is crazy? However, let us test both functions:

>> t = cputime; construct_array1(1:10,1000001:1000010);
cputime-t

ans =

     1.1875

>> t = cputime; construct_array(1:10,1000001:1000010);
cputime-t

ans =

     0.4531

(I was afraid that matlab would crash, but it did not.)

This was experimented on

MATLAB Version 7.0.4.365 (R14) Service Pack 2
Operating System: Microsoft Windows XP Version 5.1 (Build
2600: Service Pack 2)
Pentuim(R) 4 CPU 3.20 GHz, 1.00 GB of RAM.

My implementation is thus 2.6 times faster than the use of
a loop.
I admit that this can be costly in terms of RAM, because
the text string supplied to eval can
be huge. But in my practice, the arrays are not too long
(way shorter than in the test case).
The cpu time is saved because I call my function many times
in a loop.

Yuri

Subject: eval, feval, global

From: Yuri Geshelin

Date: 27 Mar, 2008 03:31:02

Message: 6 of 50

Just realized that I could have written

char(m*'ones(1,')

instead of

char([m*'o' m*'n' m*'e' m*'s' m*'(' m*'1' m*','])

but this is a minor issue here.

Yuri

Subject: eval, feval, global

From: Sven

Date: 27 Mar, 2008 04:22:02

Message: 7 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<fsf3ss$e2e$1@fred.mathworks.com>...
> Thanks to everyone who replied. I agree with John about
> GLOBAL.
>
> As for EVAL, as Peter suggested, let me show you my code,
> which I found useful.
>
> (Actually, there are two situations, in which I use EVAL,
> but I will start with presenting the 1st one, as it is
> perhaps the more controversial.)
>
> Suppose we have 2 arrays of equal length:
>
> a = [15 23 35 43];
> b = [ 2 11 8 3];
>
> and we need an algorithm, which constructs output array c
> as follows:
>
> c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
> 43 43]
>
> Here is a simple function construct_array1, which
> accomplishes this task.
>
> % *************************** top of construct_array1
> function c = construct_array1(a,b)
>
> c = [];
> for i = 1 : length(a)
> c = [c ones(1,b(i))*a(i)];
> end
>
> % *************************** end of construct_array1
>
> And here is another function construct_array, which
> accomplishes the same task.
>
> % *************************** top of construct_array
> function c = construct_array(a,b)
>
> if length(a) ~= length(b)
> error('arrays a and b should be of equal lengths!')
> end
>
> k = floor(log10(max(a)))+1;
> i = floor(log10(max(b)))+1;
> n = length(a);
> m = ones(n,1);
> c = eval(['[' ...
> reshape([char([m*'o' m*'n' m*'e' m*'s' m*'(' m*'1'
> m*',']) ...
> reshape(sprintf(['%' num2str(i) 'd'],b),i,n)' ...
> char([m*')' m*'*']) ...
> reshape(sprintf(['%' num2str(k) 'd'],a),k,n)' ...
> char(m*' ')]',1,n*(k+i+10)) ']']);
> % *************************** end of construct_array
>
> Think this is crazy? However, let us test both functions:
>
> >> t = cputime; construct_array1(1:10,1000001:1000010);
> cputime-t
>
> ans =
>
> 1.1875
>
> >> t = cputime; construct_array(1:10,1000001:1000010);
> cputime-t
>
> ans =
>
> 0.4531
>
> (I was afraid that matlab would crash, but it did not.)
>
> This was experimented on
>
> MATLAB Version 7.0.4.365 (R14) Service Pack 2
> Operating System: Microsoft Windows XP Version 5.1 (Build
> 2600: Service Pack 2)
> Pentuim(R) 4 CPU 3.20 GHz, 1.00 GB of RAM.
>
> My implementation is thus 2.6 times faster than the use of
> a loop.
> I admit that this can be costly in terms of RAM, because
> the text string supplied to eval can
> be huge. But in my practice, the arrays are not too long
> (way shorter than in the test case).
> The cpu time is saved because I call my function many times
> in a loop.
>
> Yuri
>


Hi Yuri,

I haven't tested exactly how much, but I'm sure
preallocating your result array will significantly speed up
the non-eval version of the function.

Eg:

startIdx = 1;
c = zeros(1,sum(b));
for i = 1:length(b)
    c((0:b(i)-1) + startIdx) = ones(1,b(i))*a(i);
    startIdx = startIdx + b(i);
end

And I'm sure this can be improved further still.

Cheers,
Sven.

Subject: eval, feval, global

From: Sven

Date: 27 Mar, 2008 04:51:25

Message: 8 of 50

"Sven " <sven.holcombe@gmail.deleteme.com> wrote in message
<fsf7da$g1$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <fsf3ss$e2e$1@fred.mathworks.com>...
> > Thanks to everyone who replied. I agree with John about
> > GLOBAL.
> >
> > As for EVAL, as Peter suggested, let me show you my code,
> > which I found useful.
> >
> > (Actually, there are two situations, in which I use EVAL,
> > but I will start with presenting the 1st one, as it is
> > perhaps the more controversial.)
> >
> > Suppose we have 2 arrays of equal length:
> >
> > a = [15 23 35 43];
> > b = [ 2 11 8 3];
> >
> > and we need an algorithm, which constructs output array c
> > as follows:
> >
> > c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
> > 43 43]
> >
> > Here is a simple function construct_array1, which
> > accomplishes this task.
> >
> > % *************************** top of construct_array1
> > function c = construct_array1(a,b)
> >
> > c = [];
> > for i = 1 : length(a)
> > c = [c ones(1,b(i))*a(i)];
> > end
> >
> > % *************************** end of construct_array1
> >
> > And here is another function construct_array, which
> > accomplishes the same task.
> >
> > % *************************** top of construct_array
> > function c = construct_array(a,b)
> >
> > if length(a) ~= length(b)
> > error('arrays a and b should be of equal lengths!')
> > end
> >
> > k = floor(log10(max(a)))+1;
> > i = floor(log10(max(b)))+1;
> > n = length(a);
> > m = ones(n,1);
> > c = eval(['[' ...
> > reshape([char([m*'o' m*'n' m*'e' m*'s' m*'(' m*'1'
> > m*',']) ...
> > reshape(sprintf(['%' num2str(i) 'd'],b),i,n)' ...
> > char([m*')' m*'*']) ...
> > reshape(sprintf(['%' num2str(k) 'd'],a),k,n)' ...
> > char(m*' ')]',1,n*(k+i+10)) ']']);
> > % *************************** end of construct_array
> >
> > Think this is crazy? However, let us test both functions:
> >
> > >> t = cputime; construct_array1(1:10,1000001:1000010);
> > cputime-t
> >
> > ans =
> >
> > 1.1875
> >
> > >> t = cputime; construct_array(1:10,1000001:1000010);
> > cputime-t
> >
> > ans =
> >
> > 0.4531
> >
> > (I was afraid that matlab would crash, but it did not.)
> >
> > This was experimented on
> >
> > MATLAB Version 7.0.4.365 (R14) Service Pack 2
> > Operating System: Microsoft Windows XP Version 5.1 (Build
> > 2600: Service Pack 2)
> > Pentuim(R) 4 CPU 3.20 GHz, 1.00 GB of RAM.
> >
> > My implementation is thus 2.6 times faster than the use of
> > a loop.
> > I admit that this can be costly in terms of RAM, because
> > the text string supplied to eval can
> > be huge. But in my practice, the arrays are not too long
> > (way shorter than in the test case).
> > The cpu time is saved because I call my function many times
> > in a loop.
> >
> > Yuri
> >
>
>
> Hi Yuri,
>
> I haven't tested exactly how much, but I'm sure
> preallocating your result array will significantly speed up
> the non-eval version of the function.
>
> Eg:
>
> startIdx = 1;
> c = zeros(1,sum(b));
> for i = 1:length(b)
> c((0:b(i)-1) + startIdx) = ones(1,b(i))*a(i);
> startIdx = startIdx + b(i);
> end
>
> And I'm sure this can be improved further still.

Well I took the couple of mins to test this. I stand
corrected. My function is:

startIdx = 1;
c = zeros(1,sum(b));
for i = 1:length(b)
    c((0:b(i)-1) + startIdx) = a(i);
    startIdx = startIdx + b(i);
end

Running above function 100 times:
>> tic; for i=1:100, temp_function(1:12,500000:500011); end, toc
Elapsed time is 44.180691 seconds.

Running with the eval version you posted:
>> tic; for i=1:100, temp_function(1:12,500000:500011); end, toc
Elapsed time is 18.499473 seconds.

Still much faster avoiding the loop...

Cheers,
Sven.

Subject: eval, feval, global

From: Duane Hanselman

Date: 27 Mar, 2008 10:07:22

Message: 9 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message >
Suppose we have 2 arrays of equal length:
>
> a = [15 23 35 43];
> b = [ 2 11 8 3];
>
> and we need an algorithm, which constructs output array c
> as follows:
>
> c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
> 43 43]
>
> Here is a simple function construct_array1, which
> accomplishes this task.

Try the function MMREPEAT from the File Exchange. It does
exactly this and does not use EVAL. Avoid EVAL!

Compare its speed to your two functions.

http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=1024&objectType=file


Duane Hanselman

Subject: eval, feval, global

From: Duane Hanselman

Date: 27 Mar, 2008 10:07:22

Message: 10 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message >
Suppose we have 2 arrays of equal length:
>
> a = [15 23 35 43];
> b = [ 2 11 8 3];
>
> and we need an algorithm, which constructs output array c
> as follows:
>
> c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
> 43 43]
>
> Here is a simple function construct_array1, which
> accomplishes this task.

Try the function MMREPEAT from the File Exchange. It does
exactly this and does not use EVAL. Avoid EVAL!

Compare its speed to your two functions.

http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=1024&objectType=file


Duane Hanselman

Subject: eval, feval, global

From: Duane Hanselman

Date: 27 Mar, 2008 10:07:22

Message: 11 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message >
Suppose we have 2 arrays of equal length:
>
> a = [15 23 35 43];
> b = [ 2 11 8 3];
>
> and we need an algorithm, which constructs output array c
> as follows:
>
> c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
> 43 43]
>
> Here is a simple function construct_array1, which
> accomplishes this task.

Try the function MMREPEAT from the File Exchange. It does
exactly this and does not use EVAL. Avoid EVAL!

Compare its speed to your two functions.

http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=1024&objectType=file


Duane Hanselman

Subject: eval, feval, global

From: Duane Hanselman

Date: 27 Mar, 2008 10:07:41

Message: 12 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message >
Suppose we have 2 arrays of equal length:
>
> a = [15 23 35 43];
> b = [ 2 11 8 3];
>
> and we need an algorithm, which constructs output array c
> as follows:
>
> c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
> 43 43]
>
> Here is a simple function construct_array1, which
> accomplishes this task.

Try the function MMREPEAT from the File Exchange. It does
exactly this and does not use EVAL. Avoid EVAL!

Compare its speed to your two functions.

http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=1024&objectType=file


Duane Hanselman

Subject: eval, feval, global

From: John D'Errico

Date: 27 Mar, 2008 10:57:01

Message: 13 of 50

"Duane Hanselman" <masteringmatlab@yahoo.spam.com> wrote in message
<fsfrld$fep$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message >
> Suppose we have 2 arrays of equal length:
> >
> > a = [15 23 35 43];
> > b = [ 2 11 8 3];
> >
> > and we need an algorithm, which constructs output array c
> > as follows:
> >
> > c = [15 15 <23 repeated 11 times> <35 repeated 8 times> 43
> > 43 43]
> >
> > Here is a simple function construct_array1, which
> > accomplishes this task.
>
> Try the function MMREPEAT from the File Exchange. It does
> exactly this and does not use EVAL. Avoid EVAL!
>
> Compare its speed to your two functions.
>
> http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?
objectId=1024&objectType=file
>
>
> Duane Hanselman

It seems ironic that Duane's response about
mmrepeat got repeated by the website. 8-)

The point I'll make is that Yuri's problem,
which he solves using eval in a rather
inelegant way, is far more efficiently
solved using mmrepeat.

Eval is very rarely necessary. (As opposed
to feval, which I'll agree does have some
uses.)

John

Subject: eval, feval, global

From: Duane Hanselman

Date: 27 Mar, 2008 11:25:03

Message: 14 of 50

>
> It seems ironic that Duane's response about
> mmrepeat got repeated by the website. 8-)

Sorry about that. My browser froze up and I had to kill it
to regain control of my computer. Somehow in the process,
multiple submissions were made. I take responsibility and am
sorry for the inconvenience.

Duane

Subject: eval, feval, global

From: Phil Goddard

Date: 27 Mar, 2008 11:47:01

Message: 15 of 50


Although mmrepeat is elegent, for Yuri's test case it is
almost as slow as Yuri's original (inefficient) loop.

I suspect that timing for this is highly data dependent
(i.e. depends heavily on the values in the second vector),
however for me (and Yuri's test case) the following loop
significantly beats all curently proposed approaches:

%%%%%%% Cut here
function c = construct_array4(a,b)

eIdx = cumsum(b);
sIdx = [1 eIdx(1:end-1)+1];

c = nan(1,eIdx(end));
for idx = 1:length(eIdx)
    c(sIdx(idx):eIdx(idx)) = a(idx);
end
%%%%%%% Cut here

However, the bottom line is still that EVAL can and should
be avoided.

Phil.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 27 Mar, 2008 12:50:21

Message: 16 of 50

Many thanks to everyone who replied.

The fastest algorithm is Phil's. Assuming that its time is
unity, here is the cpu time summary of the following test
case:

t = cputime; <code_name>(1:10,1000001:1000010); <code_time>
= cputime-t;

-------------------------------------

Phil's construct_array4.m - 1.00
My awkward EVAL implementation (construct_array.m) - 1.67
mmrepeat - 3.40
Sven's code - 3.47
My original version (no preallocation) - 4.00

------------------------------------

You convinced me that EVAL is beatable.

I will get back to you shortly and present another
situation, in which I make use of eval.

Subject: eval, feval, global

From: Duane Hanselman

Date: 27 Mar, 2008 13:07:02

Message: 17 of 50

"Phil Goddard" <philgoddardNOSPAM@telus.net> wrote in
message <fsg1fl$p8e$1@fred.mathworks.com>...
>
> Although mmrepeat is elegent, for Yuri's test case it is
> almost as slow as Yuri's original (inefficient) loop.

This is interesting. I wrote mmrepeat before JIT existed. So
it was the best then, but now JIT and a good FOR loop is faster!

Needless to say, I am not going to go back and revise every
piece of code I have to find these differences!

Thanks everyone for the good thread.

Subject: eval, feval, global

From: Peter Boettcher

Date: 27 Mar, 2008 15:00:41

Message: 18 of 50

"Yuri Geshelin" <geshelin@hotmail.com> writes:

> Many thanks to everyone who replied.
>
> The fastest algorithm is Phil's. Assuming that its time is
> unity, here is the cpu time summary of the following test
> case:
>
> t = cputime; <code_name>(1:10,1000001:1000010); <code_time>
> = cputime-t;
>
> -------------------------------------
>
> Phil's construct_array4.m - 1.00
> My awkward EVAL implementation (construct_array.m) - 1.67
> mmrepeat - 3.40
> Sven's code - 3.47
> My original version (no preallocation) - 4.00
>
> ------------------------------------
>
> You convinced me that EVAL is beatable.

That said, sometimes you have work to do, and a solution with eval leaps
to mind. Great. Use it and get on with life. Maybe that solution
takes less time to write/maintain than some other fancier vectorizing
thing. In your case, I would suggest leaving your simple loop in place
in a comment to illustrate what is happening, with a note that the eval
version is inexplicably faster.

In 98% of the cases we see here, the use of eval is due to a failure to
understand arrays, the difference between literal strings and string
variables, etc. These cases are easily correctable, and the switch away
from eval leads to code which is better by any and all metrics.


-Peter

Subject: eval, feval, global

From: Yuri Geshelin

Date: 27 Mar, 2008 17:45:04

Message: 19 of 50

All right, here is the second typical situation, in which I
use EVAL. It is not about computational cost, just a
programming habit.


I have PLOT in the body of my function, and sometimes I
want to do


plot(A.TEMP)


at other times it would be another text string:


plot(A.PSAL)


At the time of the call to the function I do not know,
which field should be plotted.
So I pass the array of text strings in the function (it
gets passed for other reasons, too):


prop = {'TEMP', 'PSAL', ...........}


And once I compute the index of the required field (irf), I
do this:


eval(['plot(A.' prop{irf} ')'])


Clumsy, but I got very much used to it. What would be your
recommendation?


(I wanted to stay away from CASE, because the number of
fields is quite big).


Thanks,


Yuri

Subject: eval, feval, global

From: us

Date: 27 Mar, 2008 17:52:03

Message: 20 of 50

"Yuri Geshelin":
<SNIP evil eval evergreen...

> eval(['plot(A.' prop{irf} ')'])
> What would be your recommendation

one of the solutions

     a.b=1:10;
     a.cc=1+a.b;
     a.ddd=2+a.b;
     f={'b','cc','ddd'};
     plot(a.(f{1}));
     hold on;
     plot(a.(f{2}));

us

Subject: eval, feval, global

From: Yuri Geshelin

Date: 27 Mar, 2008 18:08:02

Message: 21 of 50

"us " <us@neurol.unizh.ch> wrote in message <fsgms3$nv8
$1@fred.mathworks.com>...
> "Yuri Geshelin":
> <SNIP evil eval evergreen...
>
> > eval(['plot(A.' prop{irf} ')'])
> > What would be your recommendation
>
> one of the solutions
>
> a.b=1:10;
> a.cc=1+a.b;
> a.ddd=2+a.b;
> f={'b','cc','ddd'};
> plot(a.(f{1}));
> hold on;
> plot(a.(f{2}));
>
> us

Thanks us,

for filling yet another gap in my knowldege of matlab. I
did not know that a.(f{3}) is a valid reference to a
structure's field. No more questions.

Yuri

Subject: eval, feval, global

From: John D'Errico

Date: 27 Mar, 2008 18:25:06

Message: 22 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<fsgmf0$fcd$1@fred.mathworks.com>...
> All right, here is the second typical situation, in which I
> use EVAL. It is not about computational cost, just a
> programming habit.
>
>
> I have PLOT in the body of my function, and sometimes I
> want to do
>
>
> plot(A.TEMP)
>
>
> at other times it would be another text string:
>
>
> plot(A.PSAL)
>
>
> At the time of the call to the function I do not know,
> which field should be plotted.
> So I pass the array of text strings in the function (it
> gets passed for other reasons, too):
>
>
> prop = {'TEMP', 'PSAL', ...........}
>
>
> And once I compute the index of the required field (irf), I
> do this:
>
>
> eval(['plot(A.' prop{irf} ')'])
>
>
> Clumsy, but I got very much used to it. What would be your
> recommendation?
>
>
> (I wanted to stay away from CASE, because the number of
> fields is quite big).

Another sloppy programming habit, encouraged
by eval.

Use getfield, or better, dynamic field names.

John

Subject: eval, feval, global

From: sfreeman

Date: 28 Mar, 2008 12:20:03

Message: 23 of 50

...to come up with annother part of the original topic:

As I have to work with code from guys, who do not bother to
use 'clear global', I have started to use
appdata(0,...)
with a structure instead of global variables in code
without GUI. Anybody knows about problems using it?

Regards,
Rainer

PS: I agree on 'eval' as bad style and that it can be
replaced, even when I use str2num with GUI programming
quite often (which uses 'eval' ;o) - ).
'feval' I see frequently in "Libraries", which wrap several
functions into one file - are there better alternatives out
there.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 28 Mar, 2008 13:39:02

Message: 24 of 50

Hi,

I think the problem can be the same as in the case of
GLOBAL. As Matthew mentioned, it can make debugging an
interesting task. I realize this now. You secure yourself
from the guys who do not bother to use 'clear global', but
you are still likely to make your own mistakes when there
are dozens of variables are passed in many functions. In
this sense, it's just another form of GLOBAL.

Yuri

"sfreeman " <crush35@gmx.net> wrote in message
<fsinpi$e2q$1@fred.mathworks.com>...
> ...to come up with annother part of the original topic:
>
> As I have to work with code from guys, who do not bother
to
> use 'clear global', I have started to use
> appdata(0,...)
> with a structure instead of global variables in code
> without GUI. Anybody knows about problems using it?
>
> Regards,
> Rainer
>
> PS: I agree on 'eval' as bad style and that it can be
> replaced, even when I use str2num with GUI programming
> quite often (which uses 'eval' ;o) - ).
> 'feval' I see frequently in "Libraries", which wrap
several
> functions into one file - are there better alternatives
out
> there.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 30 Mar, 2008 23:32:01

Message: 25 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<fsebf0$43u$1@fred.mathworks.com>...
> 1) Why are eval, feval considered not elegant and banned
in
> programming contests? I often use eval, why should a good
> programmer stay away from it?
>
> 2) Same question about GLOBAL.
>
> Yuri
>

Sorry for bringing this up again. It's about the second
issue: the use of GLOBAL. When John said that it "can make
debugging an interesting task", I thought I had grasped the
subject and agreed with him. But now I think I
misunderstand something.

Let me present you with a situation, which I ran across. It
probably has to do with John’s remark. I was writing a GUI.
It took me a while, I would put it off and get back to it
in months. I was using dozens of GLOBAL variables. One day
I realized that I needed to fix a bug in a button’s
callback. I quickly wrote up a function, which takes care
of the glitch. This should have been very simple, but I got
an error message at the stage, when I least expected it.
Here is what happened. I had global variable PROP and
forgot about it, because I wasn’t working on my GUI for a
month. Now, in order to accomplish the task at hand, I
happened to use variable PROP again, but for a totally
different purpose... And again, I declared it as global. No
comments.....

This was what I recalled when John said that globals "can
make debugging an interesting task". I do realize that this
is a potential source of errors. But in terms of my
example, please explain me how exactly I should follow
these John’s recommendations:

"Stuff your parameters into a structure that gets passed
around. Use nested functions."

I know how to use CLASS, if this is of any help. I just
don't see how this would prevent me from making the same
mistake.

Any comments on John D’Errico’s message of 26 March are
appreciated.

Thanks,

Yuri

Subject: eval, feval, global

From: Steven Lord

Date: 31 Mar, 2008 00:18:11

Message: 26 of 50


"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
news:fsp7th$j9u$1@fred.mathworks.com...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <fsebf0$43u$1@fred.mathworks.com>...
>> 1) Why are eval, feval considered not elegant and banned
> in
>> programming contests? I often use eval, why should a good
>> programmer stay away from it?
>>
>> 2) Same question about GLOBAL.
>>
>> Yuri
>>
>
> Sorry for bringing this up again. It's about the second
> issue: the use of GLOBAL. When John said that it "can make
> debugging an interesting task", I thought I had grasped the
> subject and agreed with him. But now I think I
> misunderstand something.

Let's say you write a function, foo, that uses a global variable x. It
works perfectly fine on its own.

Now I write a function, baz, that uses a global variable x. It too works
perfectly fine on its own.

Finally, someone else finds your foo function and my baz function, which are
perfect for the application he or she is writing. That person creates a
function, foobarbaz that uses your foo function and my baz function. They
find that the foobarbaz function doesn't work, and are confused as to why it
doesn't work. Each of the subfunctions works well on their own, and each
piece of code in the subfunctions that work with the x variable appear to be
working correctly.

Now this is a small example, with just three functions involved. It
wouldn't be _that_ hard to notice that both subfunctions are working with
the same global variable. Now picture a larger project, where there are ten
or twenty functions involved. Tracing how each one interacts with the
others via global variables will quickly become messy.

> Let me present you with a situation, which I ran across. It
> probably has to do with John’s remark. I was writing a GUI.
> It took me a while, I would put it off and get back to it
> in months. I was using dozens of GLOBAL variables. One day
> I realized that I needed to fix a bug in a button’s
> callback. I quickly wrote up a function, which takes care
> of the glitch. This should have been very simple, but I got
> an error message at the stage, when I least expected it.
> Here is what happened. I had global variable PROP and
> forgot about it, because I wasn’t working on my GUI for a
> month. Now, in order to accomplish the task at hand, I
> happened to use variable PROP again, but for a totally
> different purpose... And again, I declared it as global. No
> comments.....

Don't worry. I don't think you're alone in having done that at one time or
another.

> This was what I recalled when John said that globals "can
> make debugging an interesting task". I do realize that this
> is a potential source of errors. But in terms of my
> example, please explain me how exactly I should follow
> these John’s recommendations:
>
> "Stuff your parameters into a structure that gets passed
> around. Use nested functions."

If all of your parameters are stored in a struct array that get passed from
function to function, any change to the parameters have to be made to the
struct array and returned from those functions, so you know where and when
those parameters were changed. That helps in debugging.

In the example I posted above, if foobarfaz has to pass parameters as inputs
to foo and baz, then any changes to the parameters in foo won't affect baz
unless they are returned from foo and the modified parameters passed into
baz.

--
Steve Lord
slord@mathworks.com

Subject: eval, feval, global

From: ImageAnalyst

Date: 31 Mar, 2008 00:59:45

Message: 27 of 50

On Mar 30, 8:18=A0pm, "Steven Lord" <sl...@mathworks.com> wrote:
> "Yuri Geshelin" <geshe...@hotmail.com> wrote in message
>
> news:fsp7th$j9u$1@fred.mathworks.com...
>
>
>
>
>
> > "Yuri Geshelin" <geshe...@hotmail.com> wrote in message
> > <fsebf0$43...@fred.mathworks.com>...
> >> 1) Why are eval, feval considered not elegant and banned
> > in
> >> programming contests? I often use eval, why should a good
> >> programmer stay away from it?
>
> >> 2) Same question about GLOBAL.
>
> >> Yuri
>
> > Sorry for bringing this up again. It's about the second
> > issue: the use of GLOBAL. When John said that it "can make
> > debugging an interesting task", I thought I had grasped the
> > subject and agreed with him. But now I think I
> > misunderstand something.
>
> Let's say you write a function, foo, that uses a global variable x. =A0It
> works perfectly fine on its own.
>
> Now I write a function, baz, that uses a global variable x. =A0It too work=
s
> perfectly fine on its own.
>
> Finally, someone else finds your foo function and my baz function, which a=
re
> perfect for the application he or she is writing. =A0That person creates a=

> function, foobarbaz that uses your foo function and my baz function. =A0Th=
ey
> find that the foobarbaz function doesn't work, and are confused as to why =
it
> doesn't work. =A0Each of the subfunctions works well on their own, and eac=
h
> piece of code in the subfunctions that work with the x variable appear to =
be
> working correctly.
>
> Now this is a small example, with just three functions involved. =A0It
> wouldn't be _that_ hard to notice that both subfunctions are working with
> the same global variable. =A0Now picture a larger project, where there are=
 ten
> or twenty functions involved. =A0Tracing how each one interacts with the
> others via global variables will quickly become messy.
>
> > Let me present you with a situation, which I ran across. It
> > probably has to do with John’s remark. I was writing a GUI.
> > It took me a while, I would put it off and get back to it
> > in months. I was using dozens of GLOBAL variables. One day
> > I realized that I needed to fix a bug in a button’s
> > callback. I quickly wrote up a function, which takes care
> > of the glitch. This should have been very simple, but I got
> > an error message at the stage, when I least expected it.
> > Here is what happened. I had global variable PROP and
> > forgot about it, because I wasn’t working on my GUI for a
> > month. Now, in order to accomplish the task at hand, I
> > happened to use variable PROP again, but for a totally
> > different purpose... And again, I declared it as global. No
> > comments.....
>
> Don't worry. =A0I don't think you're alone in having done that at one time=
 or
> another.
>
> > This was what I recalled when John said that globals "can
> > make debugging an interesting task". I do realize that this
> > is a potential source of errors. But in terms of my
> > example, please explain me how exactly I should follow
> > these John’s recommendations:
>
> > "Stuff your parameters into a structure that gets passed
> > around. Use nested functions."
>
> If all of your parameters are stored in a struct array that get passed fro=
m
> function to function, any change to the parameters have to be made to the
> struct array and returned from those functions, so you know where and when=

> those parameters were changed. =A0That helps in debugging.
>
> In the example I posted above, if foobarfaz has to pass parameters as inpu=
ts
> to foo and baz, then any changes to the parameters in foo won't affect baz=

> unless they are returned from foo and the modified parameters passed into
> baz.
>
> --
> Steve Lord
> sl...@mathworks.com- Hide quoted text -
>
> - Show quoted text -


----------------------------------------------------------------
But Steven, can you pass your structure variable into a callback
function for a button on your GUI? As far as I know the answer is
No. You're limited to the 3 default callback arguments (hObject,
etc.). Let's say your callback function needs to use some variable
that has been set by some other function in your program. It's this
situation where I use global variables because I don't know of other
anyway to get variables into the function (i.e. ones that aren't
retrievable from one of the other GUI controls). If there is a way to
get variables into a callback function without using global variables,
let me know.
Thanks,
ImageAnalyst

Subject: eval, feval, global

From: Doug Schwarz

Date: 31 Mar, 2008 02:03:13

Message: 28 of 50

In article
<5f332995-1a52-4cb2-bf08-59807891b2bf@l42g2000hsc.googlegroups.com>,
 ImageAnalyst <imageanalyst@mailinator.com> wrote:

[snip]

> But Steven, can you pass your structure variable into a callback
> function for a button on your GUI? As far as I know the answer is
> No. You're limited to the 3 default callback arguments (hObject,
> etc.). Let's say your callback function needs to use some variable
> that has been set by some other function in your program. It's this
> situation where I use global variables because I don't know of other
> anyway to get variables into the function (i.e. ones that aren't
> retrievable from one of the other GUI controls). If there is a way to
> get variables into a callback function without using global variables,
> let me know.
> Thanks,
> ImageAnalyst


Sure there is: the old way (using the UserData of the GUI figure) and
the new way (using nested functions). The following two functions do
the same thing:


%-------------- demogui2.m --------------------------------
function demogui2(cmd)
if nargin == 0
    cmd = 'init';
end
 
switch cmd
    case 'init' % Initialize GUI application
        myname = mfilename;
        fig = figure('Position',[0 0 150 90],...
            'CreateFcn',{@movegui,'center'},...
            'NumberTitle','off',...
            'Name',myname,...
            'CloseRequestFcn',[myname,' close'],...
            'Resize','off');
        info.count = 1;
        uicontrol('Style','pushbutton',...
            'Position',[20 20 50 20],...
            'String','Down',...
            'CallBack',[myname,' dec'])
        uicontrol('Style','pushbutton',...
            'Position',[80 20 50 20],...
            'String','Up',...
            'CallBack',[myname,' inc'])
        info.editbox = uicontrol('Style','edit',...
            'Position',[45 50 60 20],...
            'String',num2str(info.count),...
            'CallBack',[myname,' edit']);
        set(fig,'UserData',info,...
            'HandleVisibility','callback')
 
    case 'dec' % Decrement counter
        fig = gcbf;
        info = get(fig,'UserData');
        info.count = info.count - 1;
        set(info.editbox,'String',num2str(info.count))
        set(fig,'UserData',info)
 
    case 'inc' % Increment counter
        fig = gcbf;
        info = get(fig,'UserData');
        info.count = info.count + 1;
        set(info.editbox,'String',num2str(info.count))
        set(fig,'UserData',info)
 
    case 'edit' % Enter value in edit box
        fig = gcbf;
        info = get(fig,'UserData');
        newcount = sscanf(get(info.editbox,'String'),'%d');
        if ~isempty(newcount)
            info.count = newcount;
        end
        set(info.editbox,'String',num2str(info.count))
        set(fig,'UserData',info)
 
    case 'close' % Close requested
        fig = gcbf;
        myname = get(fig,'Name');
        answer = questdlg(['Really close ',myname,'?'],...
            '','Yes','No','No');
        if strcmp(answer,'Yes')
            delete(fig)
        end
 
end
%----------------------------------------------------------


%-------------- demogui2_new.m ----------------------------
function demogui2_new
 
fig = figure('Position',[0 0 150 90],...
    'CreateFcn',{@movegui,'center'},...
    'NumberTitle','off',...
    'Name',mfilename,...
    'CloseRequestFcn',@close,...
    'Resize','off');
count = 1;
uicontrol('Style','pushbutton',...
    'Position',[20 20 50 20],...
    'String','Down',...
    'CallBack',@dec)
uicontrol('Style','pushbutton',...
    'Position',[80 20 50 20],...
    'String','Up',...
    'CallBack',@inc)
editbox = uicontrol('Style','edit',...
    'Position',[45 50 60 20],...
    'String',num2str(count),...
    'CallBack',@edit);
set(fig,'HandleVisibility','callback')
 
    % Decrement counter
    function dec(varargin)
        count = count - 1;
        set(editbox,'String',num2str(count))
    end
 
    % Increment counter
    function inc(varargin)
        count = count + 1;
        set(editbox,'String',num2str(count))
    end
 
    % Enter value in edit box
    function edit(varargin)
        newcount = sscanf(get(editbox,'String'),'%d');
        if ~isempty(newcount)
            count = newcount;
        end
        set(editbox,'String',num2str(count))
    end
 
    % Close requested
    function close(varargin)
        myname = get(fig,'Name');
        answer = questdlg(['Really close ',myname,'?'],...
            '','Yes','No','No');
        if strcmp(answer,'Yes')
            delete(fig)
        end
    end
 
end
%----------------------------------------------------------

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 31 Mar, 2008 14:21:01

Message: 29 of 50


> In the example I posted above, if foobarfaz has to pass
parameters as inputs
> to foo and baz, then any changes to the parameters in foo
won't affect baz
> unless they are returned from foo and the modified
parameters passed into
> baz.
>

Steve, do you suggest to use only input / output args as a
way of communication between functions? This may present
another problem, but first I want to make sure I don't
misunderstand you.

In any case, if all we are talking about is the neat
organization of such communication, then I don't see why I
cannot still use globals in the following way:

global common_block_01 common_block_02 ...

where each of common_block_xx is a structure with many
fields. This way, you focus on what you are doing. To make
it yet more secure, I can name those variables
my_project_common_block_01 my_project_common_block_02 ...

If someone decides to make use of my function, he / she
will simply ignore these globals (or deliberately make use
of them).

(I was raised on fortran :) )

Yuri

Subject: eval, feval, global

From: Yuri Geshelin

Date: 31 Mar, 2008 14:30:21

Message: 30 of 50

Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-494CA7.22033630032008@71-129-133-66.dollamir.com>...
> In article
> <5f332995-1a52-4cb2-bf08-
59807891b2bf@l42g2000hsc.googlegroups.com>,
> ImageAnalyst <imageanalyst@mailinator.com> wrote:
>
> [snip]
>
> > But Steven, can you pass your structure variable into a
callback
> > function for a button on your GUI? As far as I know
the answer is
> > No. You're limited to the 3 default callback arguments
(hObject,
> > etc.). Let's say your callback function needs to use
some variable
> > that has been set by some other function in your
program. It's this
> > situation where I use global variables because I don't
know of other
> > anyway to get variables into the function (i.e. ones
that aren't
> > retrievable from one of the other GUI controls). If
there is a way to
> > get variables into a callback function without using
global variables,
> > let me know.
> > Thanks,
> > ImageAnalyst
>
>
> Sure there is: the old way (using the UserData of the GUI
figure) and
> the new way (using nested functions). The following two
functions do
> the same thing:
>
>
> %-------------- demogui2.m -------------------------------
-
> function demogui2(cmd)
> if nargin == 0
> cmd = 'init';
> end
>
> switch cmd
> case 'init' % Initialize GUI application
> myname = mfilename;
> fig = figure('Position',[0 0 150 90],...
> 'CreateFcn',{@movegui,'center'},...
> 'NumberTitle','off',...
> 'Name',myname,...
> 'CloseRequestFcn',[myname,' close'],...
> 'Resize','off');
> info.count = 1;
> uicontrol('Style','pushbutton',...
> 'Position',[20 20 50 20],...
> 'String','Down',...
> 'CallBack',[myname,' dec'])
> uicontrol('Style','pushbutton',...
> 'Position',[80 20 50 20],...
> 'String','Up',...
> 'CallBack',[myname,' inc'])
> info.editbox = uicontrol('Style','edit',...
> 'Position',[45 50 60 20],...
> 'String',num2str(info.count),...
> 'CallBack',[myname,' edit']);
> set(fig,'UserData',info,...
> 'HandleVisibility','callback')
>
> case 'dec' % Decrement counter
> fig = gcbf;
> info = get(fig,'UserData');
> info.count = info.count - 1;
> set(info.editbox,'String',num2str(info.count))
> set(fig,'UserData',info)
>
> case 'inc' % Increment counter
> fig = gcbf;
> info = get(fig,'UserData');
> info.count = info.count + 1;
> set(info.editbox,'String',num2str(info.count))
> set(fig,'UserData',info)
>
> case 'edit' % Enter value in edit box
> fig = gcbf;
> info = get(fig,'UserData');
> newcount = sscanf(get(info.editbox,'String'),'%
d');
> if ~isempty(newcount)
> info.count = newcount;
> end
> set(info.editbox,'String',num2str(info.count))
> set(fig,'UserData',info)
>
> case 'close' % Close requested
> fig = gcbf;
> myname = get(fig,'Name');
> answer = questdlg(['Really close ',myname,'?'],...
> '','Yes','No','No');
> if strcmp(answer,'Yes')
> delete(fig)
> end
>
> end
> %---------------------------------------------------------
-
>
>
> %-------------- demogui2_new.m ---------------------------
-
> function demogui2_new
>
> fig = figure('Position',[0 0 150 90],...
> 'CreateFcn',{@movegui,'center'},...
> 'NumberTitle','off',...
> 'Name',mfilename,...
> 'CloseRequestFcn',@close,...
> 'Resize','off');
> count = 1;
> uicontrol('Style','pushbutton',...
> 'Position',[20 20 50 20],...
> 'String','Down',...
> 'CallBack',@dec)
> uicontrol('Style','pushbutton',...
> 'Position',[80 20 50 20],...
> 'String','Up',...
> 'CallBack',@inc)
> editbox = uicontrol('Style','edit',...
> 'Position',[45 50 60 20],...
> 'String',num2str(count),...
> 'CallBack',@edit);
> set(fig,'HandleVisibility','callback')
>
> % Decrement counter
> function dec(varargin)
> count = count - 1;
> set(editbox,'String',num2str(count))
> end
>
> % Increment counter
> function inc(varargin)
> count = count + 1;
> set(editbox,'String',num2str(count))
> end
>
> % Enter value in edit box
> function edit(varargin)
> newcount = sscanf(get(editbox,'String'),'%d');
> if ~isempty(newcount)
> count = newcount;
> end
> set(editbox,'String',num2str(count))
> end
>
> % Close requested
> function close(varargin)
> myname = get(fig,'Name');
> answer = questdlg(['Really close ',myname,'?'],...
> '','Yes','No','No');
> if strcmp(answer,'Yes')
> delete(fig)
> end
> end
>
> end
> %---------------------------------------------------------
-
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Doug, thanks for sharing very valuable ideas with us. But
it seems that demogui2 is not what ImageAnalyst was asking
for. ImageAnalyst wants to pass a structure, while in
demogui2 it is a text string that gets passed. You can also
pass something like num2str(n) as the part of a text
string, but with structure, it won't work.

In both functions, demogui2 and demogui2_new, nothing at
all gets passed into the body of a separate function. In
the demogui2 example, it does not matter, because you can
still use the same technique to call another function
instead of making a recursive call. As for demogui2_new, it
does not help communication between two functions that
reside in separate files.

Yuri

Subject: eval, feval, global

From: Yuri Geshelin

Date: 31 Mar, 2008 15:51:03

Message: 31 of 50

> Doug, thanks for sharing very valuable ideas with us. But
> it seems that demogui2 is not what ImageAnalyst was
asking
> for. ImageAnalyst wants to pass a structure, while in
> demogui2 it is a text string that gets passed. You can
also
> pass something like num2str(n) as the part of a text
> string, but with structure, it won't work.
>
> In both functions, demogui2 and demogui2_new, nothing at
> all gets passed into the body of a separate function. In
> the demogui2 example, it does not matter, because you can
> still use the same technique to call another function
> instead of making a recursive call. As for demogui2_new,
it
> does not help communication between two functions that
> reside in separate files.
>
> Yuri
>

Sorry about this. I just realized that I can specify

'CallBack'{@function_name,s})

where s is a structure.

Taking my words back.

Yuri

Subject: eval, feval, global

From: Doug Schwarz

Date: 31 Mar, 2008 16:10:52

Message: 32 of 50

In article <fsr197$2mn$1@fred.mathworks.com>,
 "Yuri Geshelin" <geshelin@hotmail.com> wrote:

> > Doug, thanks for sharing very valuable ideas with us. But
> > it seems that demogui2 is not what ImageAnalyst was
> asking
> > for. ImageAnalyst wants to pass a structure, while in
> > demogui2 it is a text string that gets passed. You can
> also
> > pass something like num2str(n) as the part of a text
> > string, but with structure, it won't work.
> >
> > In both functions, demogui2 and demogui2_new, nothing at
> > all gets passed into the body of a separate function. In
> > the demogui2 example, it does not matter, because you can
> > still use the same technique to call another function
> > instead of making a recursive call. As for demogui2_new,
> it
> > does not help communication between two functions that
> > reside in separate files.
> >
> > Yuri
> >
>
> Sorry about this. I just realized that I can specify
>
> 'CallBack'{@function_name,s})
>
> where s is a structure.
>
> Taking my words back.
>
> Yuri

Yes, you can do that, but the value of s is fixed at the time of the
generation of the callback so I don't think that's what ImageAnalyst
wants either.

demogui2 demonstrates the standard method of communicating data between
components of a gui, namely via the userdata of the gui figure. It
doesn't matter whether the functions reside in the same m-file or not.

demogui2_new demonstrates the method of writing a gui using nested
functions. In this case, you are correct that these various callback
functions must all be in the same m-file. However, inside one of these
callback functions you can call any other function you want, passing it
any parameters that are part of the workspace of the main gui function.
The only caveat is that you must instantiate any such variables in the
main function, even if just as empty matrices.

If you are having trouble with any of this just post a small example of
something you think must be done with global variables and I'd be glad
to show you how to do it without.

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 31 Mar, 2008 18:07:01

Message: 33 of 50

Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-8DB03B.12111531032008@71-129-133-66.dollamir.com>...
> In article <fsr197$2mn$1@fred.mathworks.com>,
> "Yuri Geshelin" <geshelin@hotmail.com> wrote:
>
> Yes, you can do that, but the value of s is fixed at the
time of the
> generation of the callback so I don't think that's what
ImageAnalyst
> wants either.
>
> demogui2 demonstrates the standard method of
communicating data between
> components of a gui, namely via the userdata of the gui
figure. It
> doesn't matter whether the functions reside in the same m-
file or not.
>
> demogui2_new demonstrates the method of writing a gui
using nested
> functions. In this case, you are correct that these
various callback
> functions must all be in the same m-file. However,
inside one of these
> callback functions you can call any other function you
want, passing it
> any parameters that are part of the workspace of the main
gui function.
> The only caveat is that you must instantiate any such
variables in the
> main function, even if just as empty matrices.
>
> If you are having trouble with any of this just post a
small example of
> something you think must be done with global variables
and I'd be glad
> to show you how to do it without.
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Thanks Doug,

I will simplify my real situation. I have function
refresh_all.

%%%%%%%%%%%% top of refresh_all
function refresh_all

% array of handles to the selected curves whose color has
to be changed:
global final_handles

set(final_handles,'color','red')
%%%%%%%%%%%% bottom of refresh_all

I also have a callback to a button that invokes
refresh_all. The idea is, lots of other multipurpose
functions alter 1-D array final_handles (via global) before
the user clicks the button.

Yuri

Subject: eval, feval, global

From: Steven Lord

Date: 31 Mar, 2008 21:19:53

Message: 34 of 50


"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
news:fsqs0d$ljr$1@fred.mathworks.com...
>
>> In the example I posted above, if foobarfaz has to pass
> parameters as inputs
>> to foo and baz, then any changes to the parameters in foo
> won't affect baz
>> unless they are returned from foo and the modified
> parameters passed into
>> baz.
>>
>
> Steve, do you suggest to use only input / output args as a
> way of communication between functions? This may present
> another problem, but first I want to make sure I don't
> misunderstand you.

I try to do this where possible. One exception I make is for callback
functions; those can "communicate" through the states of the objects in the
GUI, although that sometimes leads to debugging trouble as well. We've seen
threads in the past on CSSM where a user changed the handles structure
inside a second function that was called by a first function, used GUIDATA
to update the GUI's copy of the handles structure from inside the second
function, then promptly used the older copy of the handles structure that
still existed in the first function's workspace and couldn't figure out why
their changes weren't recognized.

> In any case, if all we are talking about is the neat
> organization of such communication, then I don't see why I
> cannot still use globals in the following way:
>
> global common_block_01 common_block_02 ...
>
> where each of common_block_xx is a structure with many
> fields. This way, you focus on what you are doing. To make
> it yet more secure, I can name those variables
> my_project_common_block_01 my_project_common_block_02 ...
>
> If someone decides to make use of my function, he / she
> will simply ignore these globals (or deliberately make use
> of them).
>
> (I was raised on fortran :) )

Let's say that you have a function that creates a set of constants as
globals.

function generateconstants
global e piover2 naturallog2
e = exp(1);
piover2 = pi/2;
naturallog2 = log(2);

You use this generateconstants at the top of your function.

function myfunction
global e piover2 naturallog2
generateconstants;
pisquaredover4 = piover2^2;

Now what if you want to add in a new constant, say pi^2/6? You need to
modify generateconstants:

function generateconstants
global e piover2 naturallog2 pisquaredover6
e = exp(1);
piover2 = pi/2;
naturallog2 = log(2);
pisquaredover6 = pi^2/6;

every place in your code where you want to use pisquaredover6, AND the
global declarations (which may be at the top of your function, dozens or
hundreds of lines of code away from where you want to use pisquaredover6.)
If you forget to modify the global declarations, in the best case scenario
you'll receive an "undefined function or variable" error. In the worst case
scenario, where your first use of the should-be-global variable is to assign
a value to it, your changes to the should-be-global variable will be lost
when the function exits, subsequent code will use the stale global value,
and you will get a wrong answer.

With a struct array:

function G = generateconstants
G.e = exp(1);
G.piover2 = pi/2;
G.naturallog2 = log(2);

function myfunction
G = generateconstants;
pisquaredover4 = (G.piover2)^2;

Now if you want to add in a constant pisquaredover6, it's easy and the only
places you need to modify are a line of code in generateconstants and the
code where you actually want to use it:

function G = generateconstants
G.e = exp(1);
G.piover2 = pi/2;
G.naturallog2 = log(2);
G.pisquaredover6 = pi^2/6;

function myfunction
G = generateconstants;
pisquaredover4 = (G.piover2)^2;
pisquared = (G.pisquaredover6)*6;

This is just my opinion, of course.

--
Steve Lord
slord@mathworks.com

Subject: eval, feval, global

From: Yuri Geshelin

Date: 31 Mar, 2008 23:12:01

Message: 35 of 50

"Steven Lord" <slord@mathworks.com> wrote in message
<fsrkhp$q9s$1@fred.mathworks.com>...

> I try to do this where possible. One exception I make is
for callback
> functions; those can "communicate" through the states of
the objects in the
> GUI, although that sometimes leads to debugging trouble
as well. We've seen
> threads in the past on CSSM where a user changed the
handles structure
> inside a second function that was called by a first
function, used GUIDATA
> to update the GUI's copy of the handles structure from
inside the second
> function, then promptly used the older copy of the
handles structure that
> still existed in the first function's workspace and
couldn't figure out why
> their changes weren't recognized.
>

Thanks Steve, this is useful.

> Let's say that you have a function that creates a set of
constants as
> globals.
>
> function generateconstants
> global e piover2 naturallog2
> e = exp(1);
> piover2 = pi/2;
> naturallog2 = log(2);
>
> You use this generateconstants at the top of your
function.
>
> function myfunction
> global e piover2 naturallog2
> generateconstants;
> pisquaredover4 = piover2^2;
>
> Now what if you want to add in a new constant, say
pi^2/6? You need to
> modify generateconstants:
>
> function generateconstants
> global e piover2 naturallog2 pisquaredover6
> e = exp(1);
> piover2 = pi/2;
> naturallog2 = log(2);
> pisquaredover6 = pi^2/6;
>
> every place in your code where you want to use
pisquaredover6, AND the
> global declarations (which may be at the top of your
function, dozens or
> hundreds of lines of code away from where you want to use
pisquaredover6.)
> If you forget to modify the global declarations, in the
best case scenario
> you'll receive an "undefined function or variable"
error. In the worst case
> scenario, where your first use of the should-be-global
variable is to assign
> a value to it, your changes to the should-be-global
variable will be lost
> when the function exits, subsequent code will use the
stale global value,
> and you will get a wrong answer.
>
> With a struct array:
>
> function G = generateconstants
> G.e = exp(1);
> G.piover2 = pi/2;
> G.naturallog2 = log(2);
>
> function myfunction
> G = generateconstants;
> pisquaredover4 = (G.piover2)^2;
>
> Now if you want to add in a constant pisquaredover6, it's
easy and the only
> places you need to modify are a line of code in
generateconstants and the
> code where you actually want to use it:
>
> function G = generateconstants
> G.e = exp(1);
> G.piover2 = pi/2;
> G.naturallog2 = log(2);
> G.pisquaredover6 = pi^2/6;
>
> function myfunction
> G = generateconstants;
> pisquaredover4 = (G.piover2)^2;
> pisquared = (G.pisquaredover6)*6;
>
> This is just my opinion, of course.
>
> --
> Steve Lord
> slord@mathworks.com
>
>

Steve,

You are absolutely right when you describe how errors
occur. There is only one thing that surprises me in your
example. When you call generateconstants from myfunction to
retrieve G.piover2 and G.pisquaredover6, isn’t it a waste
of cpu to reassign G.e and G.naturallog2? To get even more
computationally frugal, G.piover2 and G.pisquaredover6
(which we do need), can also be calculated just once. I
thought matlab has means of passing these variables in a
way other then global. For example, how about making calls
to a function, in which structure G is declared as
persistent? Another possibility was mentioned by sfreeman:
to use setappdata(0... and getappdata(0...

But in any case, the use of structures just helps organize
your data, right? But if so, then why not using the
strategy that I proposed earlier? I mean, combine the
structure and global approach. To rework your example,

function generateconstants
global common_block_G
common_block_G.e = exp(1);
common_block_G.piover2 = pi/2;
common_block_G.naturallog2 = log(2);
common_block_G.any_variable = 3;

Now suppose some function, which also has global
common_block_G, changes common_block_G.any_variable:

common_block_G.any_variable = 5;

And then in the body of yet another function, which also
has global common_block_G, all you have to do is reference
common_block_G.any_variable. No need to bother with
common_block_G.e, common_block_G.naturallog2 etc. This
seems to be the fastest approach.

I am not insisting or arguing, just trying to come to grips
with your line of thinking. You guys are trendsetters in
matlab, and your opinion is very valuable to me.

I don’t mind breaking my sloppy programming habits and
learning good ones, just tell me: do you sacrifice
computational efficiency to safe programming, is that it?

Thanks,

Yuri

Subject: eval, feval, global

From: ImageAnalyst

Date: 31 Mar, 2008 23:54:51

Message: 36 of 50

On Mar 30, 10:03=A0pm, Doug Schwarz <s...@sig.for.address.edu> wrote:
> In article
> <5f332995-1a52-4cb2-bf08-59807891b...@l42g2000hsc.googlegroups.com>,
>
> =A0ImageAnalyst <imageanal...@mailinator.com> wrote:
>
> [snip]
>
> > But Steven, can you pass your structure variable into a callback
> > function for a button on your GUI? =A0As far as I know the answer is
> > No. =A0You're limited to the 3 default callback arguments (hObject,
> > etc.). =A0Let's say your callback function needs to use some variable
> > that has been set by some other function in your program. =A0It's this
> > situation where I use global variables because I don't know of other
> > anyway to get variables into the function (i.e. ones that aren't
> > retrievable from one of the other GUI controls). =A0If there is a way to=

> > get variables into a callback function without using global variables,
> > let me know.
> > Thanks,
> > ImageAnalyst
>
> Sure there is: the old way (using the UserData of the GUI figure) and
> the new way (using nested functions). =A0The following two functions do
> the same thing:
>
> %-------------- demogui2.m --------------------------------
> function demogui2(cmd)
> if nargin =3D=3D 0
> =A0 =A0 cmd =3D 'init';
> end
>
> switch cmd
> =A0 =A0 case 'init' % Initialize GUI application
> =A0 =A0 =A0 =A0 myname =3D mfilename;
> =A0 =A0 =A0 =A0 fig =3D figure('Position',[0 0 150 90],...
> =A0 =A0 =A0 =A0 =A0 =A0 'CreateFcn',{@movegui,'center'},...
> =A0 =A0 =A0 =A0 =A0 =A0 'NumberTitle','off',...
> =A0 =A0 =A0 =A0 =A0 =A0 'Name',myname,...
> =A0 =A0 =A0 =A0 =A0 =A0 'CloseRequestFcn',[myname,' close'],...
> =A0 =A0 =A0 =A0 =A0 =A0 'Resize','off');
> =A0 =A0 =A0 =A0 info.count =3D 1;
> =A0 =A0 =A0 =A0 uicontrol('Style','pushbutton',...
> =A0 =A0 =A0 =A0 =A0 =A0 'Position',[20 20 50 20],...
> =A0 =A0 =A0 =A0 =A0 =A0 'String','Down',...
> =A0 =A0 =A0 =A0 =A0 =A0 'CallBack',[myname,' dec'])
> =A0 =A0 =A0 =A0 uicontrol('Style','pushbutton',...
> =A0 =A0 =A0 =A0 =A0 =A0 'Position',[80 20 50 20],...
> =A0 =A0 =A0 =A0 =A0 =A0 'String','Up',...
> =A0 =A0 =A0 =A0 =A0 =A0 'CallBack',[myname,' inc'])
> =A0 =A0 =A0 =A0 info.editbox =3D uicontrol('Style','edit',...
> =A0 =A0 =A0 =A0 =A0 =A0 'Position',[45 50 60 20],...
> =A0 =A0 =A0 =A0 =A0 =A0 'String',num2str(info.count),...
> =A0 =A0 =A0 =A0 =A0 =A0 'CallBack',[myname,' edit']);
> =A0 =A0 =A0 =A0 set(fig,'UserData',info,...
> =A0 =A0 =A0 =A0 =A0 =A0 'HandleVisibility','callback')
>
> =A0 =A0 case 'dec' % Decrement counter
> =A0 =A0 =A0 =A0 fig =3D gcbf;
> =A0 =A0 =A0 =A0 info =3D get(fig,'UserData');
> =A0 =A0 =A0 =A0 info.count =3D info.count - 1;
> =A0 =A0 =A0 =A0 set(info.editbox,'String',num2str(info.count))
> =A0 =A0 =A0 =A0 set(fig,'UserData',info)
>
> =A0 =A0 case 'inc' % Increment counter
> =A0 =A0 =A0 =A0 fig =3D gcbf;
> =A0 =A0 =A0 =A0 info =3D get(fig,'UserData');
> =A0 =A0 =A0 =A0 info.count =3D info.count + 1;
> =A0 =A0 =A0 =A0 set(info.editbox,'String',num2str(info.count))
> =A0 =A0 =A0 =A0 set(fig,'UserData',info)
>
> =A0 =A0 case 'edit' % Enter value in edit box
> =A0 =A0 =A0 =A0 fig =3D gcbf;
> =A0 =A0 =A0 =A0 info =3D get(fig,'UserData');
> =A0 =A0 =A0 =A0 newcount =3D sscanf(get(info.editbox,'String'),'%d');
> =A0 =A0 =A0 =A0 if ~isempty(newcount)
> =A0 =A0 =A0 =A0 =A0 =A0 info.count =3D newcount;
> =A0 =A0 =A0 =A0 end
> =A0 =A0 =A0 =A0 set(info.editbox,'String',num2str(info.count))
> =A0 =A0 =A0 =A0 set(fig,'UserData',info)
>
> =A0 =A0 case 'close' % Close requested
> =A0 =A0 =A0 =A0 fig =3D gcbf;
> =A0 =A0 =A0 =A0 myname =3D get(fig,'Name');
> =A0 =A0 =A0 =A0 answer =3D questdlg(['Really close ',myname,'?'],...
> =A0 =A0 =A0 =A0 =A0 =A0 '','Yes','No','No');
> =A0 =A0 =A0 =A0 if strcmp(answer,'Yes')
> =A0 =A0 =A0 =A0 =A0 =A0 delete(fig)
> =A0 =A0 =A0 =A0 end
>
> end
> %----------------------------------------------------------
>
> %-------------- demogui2_new.m ----------------------------
> function demogui2_new
>
> fig =3D figure('Position',[0 0 150 90],...
> =A0 =A0 'CreateFcn',{@movegui,'center'},...
> =A0 =A0 'NumberTitle','off',...
> =A0 =A0 'Name',mfilename,...
> =A0 =A0 'CloseRequestFcn',@close,...
> =A0 =A0 'Resize','off');
> count =3D 1;
> uicontrol('Style','pushbutton',...
> =A0 =A0 'Position',[20 20 50 20],...
> =A0 =A0 'String','Down',...
> =A0 =A0 'CallBack',@dec)
> uicontrol('Style','pushbutton',...
> =A0 =A0 'Position',[80 20 50 20],...
> =A0 =A0 'String','Up',...
> =A0 =A0 'CallBack',@inc)
> editbox =3D uicontrol('Style','edit',...
> =A0 =A0 'Position',[45 50 60 20],...
> =A0 =A0 'String',num2str(count),...
> =A0 =A0 'CallBack',@edit);
> set(fig,'HandleVisibility','callback')
>
> =A0 =A0 % Decrement counter
> =A0 =A0 function dec(varargin)
> =A0 =A0 =A0 =A0 count =3D count - 1;
> =A0 =A0 =A0 =A0 set(editbox,'String',num2str(count))
> =A0 =A0 end
>
> =A0 =A0 % Increment counter
> =A0 =A0 function inc(varargin)
> =A0 =A0 =A0 =A0 count =3D count + 1;
> =A0 =A0 =A0 =A0 set(editbox,'String',num2str(count))
> =A0 =A0 end
>
> =A0 =A0 % Enter value in edit box
> =A0 =A0 function edit(varargin)
> =A0 =A0 =A0 =A0 newcount =3D sscanf(get(editbox,'String'),'%d');
> =A0 =A0 =A0 =A0 if ~isempty(newcount)
> =A0 =A0 =A0 =A0 =A0 =A0 count =3D newcount;
> =A0 =A0 =A0 =A0 end
> =A0 =A0 =A0 =A0 set(editbox,'String',num2str(count))
> =A0 =A0 end
>
> =A0 =A0 % Close requested
> =A0 =A0 function close(varargin)
> =A0 =A0 =A0 =A0 myname =3D get(fig,'Name');
> =A0 =A0 =A0 =A0 answer =3D questdlg(['Really close ',myname,'?'],...
> =A0 =A0 =A0 =A0 =A0 =A0 '','Yes','No','No');
> =A0 =A0 =A0 =A0 if strcmp(answer,'Yes')
> =A0 =A0 =A0 =A0 =A0 =A0 delete(fig)
> =A0 =A0 =A0 =A0 end
> =A0 =A0 end
>
> end
> %----------------------------------------------------------
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Thanks Doug. I'll give them a try when I get the chance.
Regards,
ImageAnalyst

Subject: eval, feval, global

From: Raphael Austin

Date: 1 Apr, 2008 18:35:12

Message: 37 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<fsebf0$43u$1@fred.mathworks.com>...
> 1) Why are eval, feval considered not elegant and banned
in
> programming contests? I often use eval, why should a good
> programmer stay away from it?
>
> 2) Same question about GLOBAL.
>
> Yuri
>

Despite all the responses here as to why you shouldn't use
it, I can think of plenty of cases where it is the only
solution. For example, I recently wrote a matlab function
that would read an input file that contained two columns of
the form:

VarName, Value

I allowed the Value column to have math operations in it
e.g.
Var1 sin(4/5)*sqrt(3)

Without the eval I don't know how else I would have been
able to do this.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 1 Apr, 2008 19:23:02

Message: 38 of 50

"Raphael Austin" <raphael.austin@jhuapl.edu> wrote in
message <fstv90$774$1@fred.mathworks.com>...
> "Yuri Geshelin" <geshelin@hotmail.com> wrote in message
> <fsebf0$43u$1@fred.mathworks.com>...
> > 1) Why are eval, feval considered not elegant and
banned
> in
> > programming contests? I often use eval, why should a
good
> > programmer stay away from it?
> >
> > 2) Same question about GLOBAL.
> >
> > Yuri
> >
>
> Despite all the responses here as to why you shouldn't
use
> it, I can think of plenty of cases where it is the only
> solution. For example, I recently wrote a matlab
function
> that would read an input file that contained two columns
of
> the form:
>
> VarName, Value
>
> I allowed the Value column to have math operations in it
> e.g.
> Var1 sin(4/5)*sqrt(3)
>
> Without the eval I don't know how else I would have been
> able to do this.
>
>

Hi,

Perhaps you are right. BTW, matlab has a family of ez*.m
programs: ezsurf, ezplot, etc. They all use eval.

Yuri

Subject: eval, feval, global

From: Doug Schwarz

Date: 4 Apr, 2008 18:33:48

Message: 39 of 50

In article <fsr985$qea$1@fred.mathworks.com>,
 "Yuri Geshelin" <geshelin@hotmail.com> wrote:

> Doug Schwarz <see@sig.for.address.edu> wrote in message
> <see-8DB03B.12111531032008@71-129-133-66.dollamir.com>...
> > In article <fsr197$2mn$1@fred.mathworks.com>,
> > "Yuri Geshelin" <geshelin@hotmail.com> wrote:
> >
> > Yes, you can do that, but the value of s is fixed at the
> time of the
> > generation of the callback so I don't think that's what
> ImageAnalyst
> > wants either.
> >
> > demogui2 demonstrates the standard method of
> communicating data between
> > components of a gui, namely via the userdata of the gui
> figure. It
> > doesn't matter whether the functions reside in the same m-
> file or not.
> >
> > demogui2_new demonstrates the method of writing a gui
> using nested
> > functions. In this case, you are correct that these
> various callback
> > functions must all be in the same m-file. However,
> inside one of these
> > callback functions you can call any other function you
> want, passing it
> > any parameters that are part of the workspace of the main
> gui function.
> > The only caveat is that you must instantiate any such
> variables in the
> > main function, even if just as empty matrices.
> >
> > If you are having trouble with any of this just post a
> small example of
> > something you think must be done with global variables
> and I'd be glad
> > to show you how to do it without.
> >
> > --
> > Doug Schwarz
> > dmschwarz&ieee,org
> > Make obvious changes to get real email address.
>
> Thanks Doug,
>
> I will simplify my real situation. I have function
> refresh_all.
>
> %%%%%%%%%%%% top of refresh_all
> function refresh_all
>
> % array of handles to the selected curves whose color has
> to be changed:
> global final_handles
>
> set(final_handles,'color','red')
> %%%%%%%%%%%% bottom of refresh_all
>
> I also have a callback to a button that invokes
> refresh_all. The idea is, lots of other multipurpose
> functions alter 1-D array final_handles (via global) before
> the user clicks the button.
>
> Yuri

If you are going to have global variables then you might as well use
them, even from refresh_all. The whole point of this discussion is that
you can get rid of global variables completely. If you can show me a
full working application (as minimalist as you can make it) which uses
global variables in a way that can't figure out how to do without, I can
show you how to abolish them (or at least I'll try). I can't do
anything with the tiny fragment of an application you sent.

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 4 Apr, 2008 19:13:02

Message: 40 of 50

Thanks Doug,

OK, I will prepare a minimal fully working example.

What is refresh_all? I don't have this function.

Yuri

Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-FDDD39.14341204042008@71-129-133-66.dollamir.com>...
> In article <fsr985$qea$1@fred.mathworks.com>,
> "Yuri Geshelin" <geshelin@hotmail.com> wrote:
>
> > Doug Schwarz <see@sig.for.address.edu> wrote in message
> > <see-8DB03B.12111531032008@71-129-133-
66.dollamir.com>...
> > > In article <fsr197$2mn$1@fred.mathworks.com>,
> > > "Yuri Geshelin" <geshelin@hotmail.com> wrote:
> > >
> > > Yes, you can do that, but the value of s is fixed at
the
> > time of the
> > > generation of the callback so I don't think that's
what
> > ImageAnalyst
> > > wants either.
> > >
> > > demogui2 demonstrates the standard method of
> > communicating data between
> > > components of a gui, namely via the userdata of the
gui
> > figure. It
> > > doesn't matter whether the functions reside in the
same m-
> > file or not.
> > >
> > > demogui2_new demonstrates the method of writing a gui
> > using nested
> > > functions. In this case, you are correct that these
> > various callback
> > > functions must all be in the same m-file. However,
> > inside one of these
> > > callback functions you can call any other function
you
> > want, passing it
> > > any parameters that are part of the workspace of the
main
> > gui function.
> > > The only caveat is that you must instantiate any such
> > variables in the
> > > main function, even if just as empty matrices.
> > >
> > > If you are having trouble with any of this just post
a
> > small example of
> > > something you think must be done with global
variables
> > and I'd be glad
> > > to show you how to do it without.
> > >
> > > --
> > > Doug Schwarz
> > > dmschwarz&ieee,org
> > > Make obvious changes to get real email address.
> >
> > Thanks Doug,
> >
> > I will simplify my real situation. I have function
> > refresh_all.
> >
> > %%%%%%%%%%%% top of refresh_all
> > function refresh_all
> >
> > % array of handles to the selected curves whose color
has
> > to be changed:
> > global final_handles
> >
> > set(final_handles,'color','red')
> > %%%%%%%%%%%% bottom of refresh_all
> >
> > I also have a callback to a button that invokes
> > refresh_all. The idea is, lots of other multipurpose
> > functions alter 1-D array final_handles (via global)
before
> > the user clicks the button.
> >
> > Yuri
>
> If you are going to have global variables then you might
as well use
> them, even from refresh_all. The whole point of this
discussion is that
> you can get rid of global variables completely. If you
can show me a
> full working application (as minimalist as you can make
it) which uses
> global variables in a way that can't figure out how to do
without, I can
> show you how to abolish them (or at least I'll try). I
can't do
> anything with the tiny fragment of an application you
sent.
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 4 Apr, 2008 19:16:01

Message: 41 of 50

Pls ignore my silly question about refresh_all. I forgot
that this was my own example.


Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-FDDD39.14341204042008@71-129-133-66.dollamir.com>...
> In article <fsr985$qea$1@fred.mathworks.com>,
> "Yuri Geshelin" <geshelin@hotmail.com> wrote:
>
> > Doug Schwarz <see@sig.for.address.edu> wrote in message
> > <see-8DB03B.12111531032008@71-129-133-
66.dollamir.com>...
> > > In article <fsr197$2mn$1@fred.mathworks.com>,
> > > "Yuri Geshelin" <geshelin@hotmail.com> wrote:
> > >
> > > Yes, you can do that, but the value of s is fixed at
the
> > time of the
> > > generation of the callback so I don't think that's
what
> > ImageAnalyst
> > > wants either.
> > >
> > > demogui2 demonstrates the standard method of
> > communicating data between
> > > components of a gui, namely via the userdata of the
gui
> > figure. It
> > > doesn't matter whether the functions reside in the
same m-
> > file or not.
> > >
> > > demogui2_new demonstrates the method of writing a gui
> > using nested
> > > functions. In this case, you are correct that these
> > various callback
> > > functions must all be in the same m-file. However,
> > inside one of these
> > > callback functions you can call any other function
you
> > want, passing it
> > > any parameters that are part of the workspace of the
main
> > gui function.
> > > The only caveat is that you must instantiate any such
> > variables in the
> > > main function, even if just as empty matrices.
> > >
> > > If you are having trouble with any of this just post
a
> > small example of
> > > something you think must be done with global
variables
> > and I'd be glad
> > > to show you how to do it without.
> > >
> > > --
> > > Doug Schwarz
> > > dmschwarz&ieee,org
> > > Make obvious changes to get real email address.
> >
> > Thanks Doug,
> >
> > I will simplify my real situation. I have function
> > refresh_all.
> >
> > %%%%%%%%%%%% top of refresh_all
> > function refresh_all
> >
> > % array of handles to the selected curves whose color
has
> > to be changed:
> > global final_handles
> >
> > set(final_handles,'color','red')
> > %%%%%%%%%%%% bottom of refresh_all
> >
> > I also have a callback to a button that invokes
> > refresh_all. The idea is, lots of other multipurpose
> > functions alter 1-D array final_handles (via global)
before
> > the user clicks the button.
> >
> > Yuri
>
> If you are going to have global variables then you might
as well use
> them, even from refresh_all. The whole point of this
discussion is that
> you can get rid of global variables completely. If you
can show me a
> full working application (as minimalist as you can make
it) which uses
> global variables in a way that can't figure out how to do
without, I can
> show you how to abolish them (or at least I'll try). I
can't do
> anything with the tiny fragment of an application you
sent.
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 5 Apr, 2008 13:49:01

Message: 42 of 50

Ok, I now have a fully working example, which I tried to
make as short as possible. Below are 5 functions:
global_example, refresh_all, plot_all, random_pick,
time_pick. Execute global_example.m, and shouldn't be hard
to figure out what the application does.

%%%%%%%%%%%%%%% top of global_example
function global_example
figure(1),clf
set(1,'position',[100 500 300 300])
u1 = uicontrol('position',[ 20 20 100 30],'string','Random
pick','callback','random_pick');
u2 = uicontrol('position',[ 20 60 100 30],'string','Month
pick','callback','time_pick(2)');
u3 = uicontrol('position',[ 20 100 100 30],'string','Date
pick','callback','time_pick(3)');
u4 = uicontrol('position',[ 20 140 100 30],'string','Plot
all','callback','plot_all');
u5 = uicontrol('position',[180 140 100
30],'string','Refresh all','callback','refresh_all');
plot_all
%%%%%%%%%%%%%% bottom of global_example

%%%%%%%%%%%%%%% top of refresh_all
function refresh_all
global final_handles index_handles

if ishandle(final_handles)
   set(final_handles(index_handles),'color','r')
end
%%%%%%%%%%%%%%%%% bottom of refresh_all

%%%%%%%%%%%%%%% top of plot_all
function plot_all
global final_handles index_handles

index_handles = [];
figure(2), clf
set(2,'position',[600 500 300 300])
final_handles = plot(repmat(1:31,2,1),'color','b');
%%%%%%%%%%%%%%%%% bottom of plot_all

%%%%%%%%%%%%%%% top of random_pick
function random_pick
global index_handles
index_handles = [index_handles round(rand(1,5)*30)+1];
%%%%%%%%%%%%%%%%% bottom of random_pick

%%%%%%%%%%%%%%% top of time_pick
function time_pick(n)
global index_handles
c = clock;
index_handles = [index_handles c(n)];
%%%%%%%%%%%%%%%%% bottom of time_pick

Thanks Doug and everyone who will show me how to make do
without GLOBAL.

Yuri

Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-FDDD39.14341204042008@71-129-133-66.dollamir.com>...
> In article <fsr985$qea$1@fred.mathworks.com>,
> "Yuri Geshelin" <geshelin@hotmail.com> wrote:
>
> > Doug Schwarz <see@sig.for.address.edu> wrote in message
> > <see-8DB03B.12111531032008@71-129-133-
66.dollamir.com>...
> > > In article <fsr197$2mn$1@fred.mathworks.com>,
> > > "Yuri Geshelin" <geshelin@hotmail.com> wrote:
> > >
> > > Yes, you can do that, but the value of s is fixed at
the
> > time of the
> > > generation of the callback so I don't think that's
what
> > ImageAnalyst
> > > wants either.
> > >
> > > demogui2 demonstrates the standard method of
> > communicating data between
> > > components of a gui, namely via the userdata of the
gui
> > figure. It
> > > doesn't matter whether the functions reside in the
same m-
> > file or not.
> > >
> > > demogui2_new demonstrates the method of writing a gui
> > using nested
> > > functions. In this case, you are correct that these
> > various callback
> > > functions must all be in the same m-file. However,
> > inside one of these
> > > callback functions you can call any other function
you
> > want, passing it
> > > any parameters that are part of the workspace of the
main
> > gui function.
> > > The only caveat is that you must instantiate any such
> > variables in the
> > > main function, even if just as empty matrices.
> > >
> > > If you are having trouble with any of this just post
a
> > small example of
> > > something you think must be done with global
variables
> > and I'd be glad
> > > to show you how to do it without.
> > >
> > > --
> > > Doug Schwarz
> > > dmschwarz&ieee,org
> > > Make obvious changes to get real email address.
> >
> > Thanks Doug,
> >
> > I will simplify my real situation. I have function
> > refresh_all.
> >
> > %%%%%%%%%%%% top of refresh_all
> > function refresh_all
> >
> > % array of handles to the selected curves whose color
has
> > to be changed:
> > global final_handles
> >
> > set(final_handles,'color','red')
> > %%%%%%%%%%%% bottom of refresh_all
> >
> > I also have a callback to a button that invokes
> > refresh_all. The idea is, lots of other multipurpose
> > functions alter 1-D array final_handles (via global)
before
> > the user clicks the button.
> >
> > Yuri
>
> If you are going to have global variables then you might
as well use
> them, even from refresh_all. The whole point of this
discussion is that
> you can get rid of global variables completely. If you
can show me a
> full working application (as minimalist as you can make
it) which uses
> global variables in a way that can't figure out how to do
without, I can
> show you how to abolish them (or at least I'll try). I
can't do
> anything with the tiny fragment of an application you
sent.
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Subject: eval, feval, global

From: Doug Schwarz

Date: 5 Apr, 2008 16:24:03

Message: 43 of 50

In article <ft800d$jcr$1@fred.mathworks.com>,
 "Yuri Geshelin" <geshelin@hotmail.com> wrote:

> Ok, I now have a fully working example, which I tried to
> make as short as possible. Below are 5 functions:
> global_example, refresh_all, plot_all, random_pick,
> time_pick. Execute global_example.m, and shouldn't be hard
> to figure out what the application does.
>
> %%%%%%%%%%%%%%% top of global_example
> function global_example
> figure(1),clf
> set(1,'position',[100 500 300 300])
> u1 = uicontrol('position',[ 20 20 100 30],'string','Random
> pick','callback','random_pick');
> u2 = uicontrol('position',[ 20 60 100 30],'string','Month
> pick','callback','time_pick(2)');
> u3 = uicontrol('position',[ 20 100 100 30],'string','Date
> pick','callback','time_pick(3)');
> u4 = uicontrol('position',[ 20 140 100 30],'string','Plot
> all','callback','plot_all');
> u5 = uicontrol('position',[180 140 100
> 30],'string','Refresh all','callback','refresh_all');
> plot_all
> %%%%%%%%%%%%%% bottom of global_example
>
> %%%%%%%%%%%%%%% top of refresh_all
> function refresh_all
> global final_handles index_handles
>
> if ishandle(final_handles)
> set(final_handles(index_handles),'color','r')
> end
> %%%%%%%%%%%%%%%%% bottom of refresh_all
>
> %%%%%%%%%%%%%%% top of plot_all
> function plot_all
> global final_handles index_handles
>
> index_handles = [];
> figure(2), clf
> set(2,'position',[600 500 300 300])
> final_handles = plot(repmat(1:31,2,1),'color','b');
> %%%%%%%%%%%%%%%%% bottom of plot_all
>
> %%%%%%%%%%%%%%% top of random_pick
> function random_pick
> global index_handles
> index_handles = [index_handles round(rand(1,5)*30)+1];
> %%%%%%%%%%%%%%%%% bottom of random_pick
>
> %%%%%%%%%%%%%%% top of time_pick
> function time_pick(n)
> global index_handles
> c = clock;
> index_handles = [index_handles c(n)];
> %%%%%%%%%%%%%%%%% bottom of time_pick
>
> Thanks Doug and everyone who will show me how to make do
> without GLOBAL.
>
> Yuri


Hi Yuri,

Well, I had to correct a few problems with your example, but otherwise
it's a good one. I think I have correctly figured out what it is
supposed to do.

I have two ways of doing the same thing without any global variables.
The first uses nested functions. With nested functions we have cheated
a bit because a nested function can access variables in the calling
program and this is very much like global variables in that you have to
be careful when debugging because all variables do not get passed
explicitly into the nested function workspace. Nevertheless, it is a
good technique (IMO) because you don't have to worry about name
conflicts with variables in other programs.

The second example uses the method where, instead of globals, we pass
data around in a structure which gets stored in the UserData of the main
figure. It's a little more cumbersome because inside each subfunction
you have retrieve the UserData and then put it back at the end, but
because this is an explicit operation you might like it better than the
nested function approach.

If you have a really old version of MATLAB and don't have function
handles (the @ operator) then we can modify the second example to use
the switchyard technique. Let me know if you need that.

Anyway, here are the programs:

%-------------- nested_fcn_example.m ------------------------
function nested_fcn_example
fig = figure('position',[100 500 300 300]);
u1 = uicontrol('position',[ 20 20 100 30],...
    'string','Random pick',...
    'callback',@random_pick);
u2 = uicontrol('position',[ 20 60 100 30],...
    'string','Month pick',...
    'callback',{@time_pick,2});
u3 = uicontrol('position',[ 20 100 100 30],...
    'string','Date pick',...
    'callback',{@time_pick,3});
u4 = uicontrol('position',[ 20 140 100 30],...
    'string','Plot all',...
    'callback',@plot_all);
u5 = uicontrol('position',[180 140 100 30],...
    'string','Refresh all',...
    'callback',@refresh_all);
 
final_handles = [];
index_handles = [];
fig2 = [];
axes2 = [];
 
plot_all
 
    function refresh_all(varargin)
        if ~isempty(final_handles)
            set(final_handles(index_handles),'color','r')
        end
    end
 
    function plot_all(varargin)
        index_handles = [];
        if isempty(fig2)
            fig2 = figure('position',[600 500 300 300]);
            axes2 = gca;
        end
        final_handles = plot(axes2,repmat(1:31,2,1),'color','b');
    end
 
    function random_pick(varargin)
        index_handles = round(rand(1,5)*30)+1;
    end
 
    function time_pick(varargin)
        n = varargin{end};
        c = clock;
        index_handles = c(n);
    end
 
end
%------------ end nested_fcn_example.m ----------------------



%--------------- userdata_example.m -------------------------
function userdata_example
fig = figure('position',[100 500 300 300]);
u1 = uicontrol('position',[ 20 20 100 30],...
    'string','Random pick',...
    'callback',@random_pick);
u2 = uicontrol('position',[ 20 60 100 30],...
    'string','Month pick',...
    'callback',{@time_pick,2});
u3 = uicontrol('position',[ 20 100 100 30],...
    'string','Date pick',...
    'callback',{@time_pick,3});
u4 = uicontrol('position',[ 20 140 100 30],...
    'string','Plot all',...
    'callback',@plot_all);
u5 = uicontrol('position',[180 140 100 30],...
    'string','Refresh all',...
    'callback',@refresh_all);
 
info.final_handles = [];
info.index_handles = [];
info.fig2 = [];
info.axes2 = [];
 
set(fig,'UserData',info)
 
plot_all(u4)
 
 
function refresh_all(varargin)
fig = gcbf;
info = get(fig,'UserData');
if ~isempty(info.final_handles)
    set(info.final_handles(info.index_handles),'color','r')
end
 
 
function plot_all(varargin)
fig = get(varargin{1},'Parent');
info = get(fig,'UserData');
info.index_handles = [];
if isempty(info.fig2)
    info.fig2 = figure('position',[600 500 300 300]);
    info.axes2 = gca;
end
info.final_handles = plot(info.axes2,repmat(1:31,2,1),'color','b');
set(fig,'UserData',info)
 
 
function random_pick(varargin)
fig = gcbf;
info = get(fig,'UserData');
info.index_handles = round(rand(1,5)*30)+1;
set(fig,'UserData',info)
 
 
function time_pick(varargin)
fig = gcbf;
info = get(fig,'UserData');
n = varargin{end};
c = clock;
info.index_handles = c(n);
set(fig,'UserData',info)
%------------- end userdata_example.m -----------------------

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 6 Apr, 2008 13:41:02

Message: 44 of 50

Many thanks Doug,

for teaching me a good programming style. I went over your
examples, both are working nicely and make sense. I just
want to share some thoughts.

1) I like the nested approach better, because it is a bit
faster. Not that this is very important though. (And in
this case, it is not important at all).

2) Instead of using figure's userdata, you can use that of
the root (see sfreeman's post of 28 Mar). But this is a
potential source of errors, because you can dump too many
variables into this storage, while in the case of the
figure at hand, you will focus on that figure.

3) I understand, there is a third way of doing it - to make
a function recursively call itself, right? Something as you
posted here on 31 March.

4) Maybe there are yet more ways of doing it, e.g. to use a
constructor method, or to call a function, in which the
structure is declared as a persistent. I will explore it
when I will get a chance.

Yuri.

Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-5B0A29.12240405042008@71-129-133-66.dollamir.com>...
> In article <ft800d$jcr$1@fred.mathworks.com>,
> "Yuri Geshelin" <geshelin@hotmail.com> wrote:
>
> > Ok, I now have a fully working example, which I tried
to
> > make as short as possible. Below are 5 functions:
> > global_example, refresh_all, plot_all, random_pick,
> > time_pick. Execute global_example.m, and shouldn't be
hard
> > to figure out what the application does.
> >
> > %%%%%%%%%%%%%%% top of global_example
> > function global_example
> > figure(1),clf
> > set(1,'position',[100 500 300 300])
> > u1 = uicontrol('position',[ 20 20 100
30],'string','Random
> > pick','callback','random_pick');
> > u2 = uicontrol('position',[ 20 60 100
30],'string','Month
> > pick','callback','time_pick(2)');
> > u3 = uicontrol('position',[ 20 100 100
30],'string','Date
> > pick','callback','time_pick(3)');
> > u4 = uicontrol('position',[ 20 140 100
30],'string','Plot
> > all','callback','plot_all');
> > u5 = uicontrol('position',[180 140 100
> > 30],'string','Refresh all','callback','refresh_all');
> > plot_all
> > %%%%%%%%%%%%%% bottom of global_example
> >
> > %%%%%%%%%%%%%%% top of refresh_all
> > function refresh_all
> > global final_handles index_handles
> >
> > if ishandle(final_handles)
> > set(final_handles(index_handles),'color','r')
> > end
> > %%%%%%%%%%%%%%%%% bottom of refresh_all
> >
> > %%%%%%%%%%%%%%% top of plot_all
> > function plot_all
> > global final_handles index_handles
> >
> > index_handles = [];
> > figure(2), clf
> > set(2,'position',[600 500 300 300])
> > final_handles = plot(repmat(1:31,2,1),'color','b');
> > %%%%%%%%%%%%%%%%% bottom of plot_all
> >
> > %%%%%%%%%%%%%%% top of random_pick
> > function random_pick
> > global index_handles
> > index_handles = [index_handles round(rand(1,5)*30)+1];
> > %%%%%%%%%%%%%%%%% bottom of random_pick
> >
> > %%%%%%%%%%%%%%% top of time_pick
> > function time_pick(n)
> > global index_handles
> > c = clock;
> > index_handles = [index_handles c(n)];
> > %%%%%%%%%%%%%%%%% bottom of time_pick
> >
> > Thanks Doug and everyone who will show me how to make
do
> > without GLOBAL.
> >
> > Yuri
>
>
> Hi Yuri,
>
> Well, I had to correct a few problems with your example,
but otherwise
> it's a good one. I think I have correctly figured out
what it is
> supposed to do.
>
> I have two ways of doing the same thing without any
global variables.
> The first uses nested functions. With nested functions
we have cheated
> a bit because a nested function can access variables in
the calling
> program and this is very much like global variables in
that you have to
> be careful when debugging because all variables do not
get passed
> explicitly into the nested function workspace.
Nevertheless, it is a
> good technique (IMO) because you don't have to worry
about name
> conflicts with variables in other programs.
>
> The second example uses the method where, instead of
globals, we pass
> data around in a structure which gets stored in the
UserData of the main
> figure. It's a little more cumbersome because inside
each subfunction
> you have retrieve the UserData and then put it back at
the end, but
> because this is an explicit operation you might like it
better than the
> nested function approach.
>
> If you have a really old version of MATLAB and don't have
function
> handles (the @ operator) then we can modify the second
example to use
> the switchyard technique. Let me know if you need that.
>
> Anyway, here are the programs:
>
> %-------------- nested_fcn_example.m ---------------------
---
> function nested_fcn_example
> fig = figure('position',[100 500 300 300]);
> u1 = uicontrol('position',[ 20 20 100 30],...
> 'string','Random pick',...
> 'callback',@random_pick);
> u2 = uicontrol('position',[ 20 60 100 30],...
> 'string','Month pick',...
> 'callback',{@time_pick,2});
> u3 = uicontrol('position',[ 20 100 100 30],...
> 'string','Date pick',...
> 'callback',{@time_pick,3});
> u4 = uicontrol('position',[ 20 140 100 30],...
> 'string','Plot all',...
> 'callback',@plot_all);
> u5 = uicontrol('position',[180 140 100 30],...
> 'string','Refresh all',...
> 'callback',@refresh_all);
>
> final_handles = [];
> index_handles = [];
> fig2 = [];
> axes2 = [];
>
> plot_all
>
> function refresh_all(varargin)
> if ~isempty(final_handles)
> set(final_handles(index_handles),'color','r')
> end
> end
>
> function plot_all(varargin)
> index_handles = [];
> if isempty(fig2)
> fig2 = figure('position',[600 500 300 300]);
> axes2 = gca;
> end
> final_handles = plot(axes2,repmat
(1:31,2,1),'color','b');
> end
>
> function random_pick(varargin)
> index_handles = round(rand(1,5)*30)+1;
> end
>
> function time_pick(varargin)
> n = varargin{end};
> c = clock;
> index_handles = c(n);
> end
>
> end
> %------------ end nested_fcn_example.m -------------------
---
>
>
>
> %--------------- userdata_example.m ----------------------
---
> function userdata_example
> fig = figure('position',[100 500 300 300]);
> u1 = uicontrol('position',[ 20 20 100 30],...
> 'string','Random pick',...
> 'callback',@random_pick);
> u2 = uicontrol('position',[ 20 60 100 30],...
> 'string','Month pick',...
> 'callback',{@time_pick,2});
> u3 = uicontrol('position',[ 20 100 100 30],...
> 'string','Date pick',...
> 'callback',{@time_pick,3});
> u4 = uicontrol('position',[ 20 140 100 30],...
> 'string','Plot all',...
> 'callback',@plot_all);
> u5 = uicontrol('position',[180 140 100 30],...
> 'string','Refresh all',...
> 'callback',@refresh_all);
>
> info.final_handles = [];
> info.index_handles = [];
> info.fig2 = [];
> info.axes2 = [];
>
> set(fig,'UserData',info)
>
> plot_all(u4)
>
>
> function refresh_all(varargin)
> fig = gcbf;
> info = get(fig,'UserData');
> if ~isempty(info.final_handles)
> set(info.final_handles
(info.index_handles),'color','r')
> end
>
>
> function plot_all(varargin)
> fig = get(varargin{1},'Parent');
> info = get(fig,'UserData');
> info.index_handles = [];
> if isempty(info.fig2)
> info.fig2 = figure('position',[600 500 300 300]);
> info.axes2 = gca;
> end
> info.final_handles = plot(info.axes2,repmat
(1:31,2,1),'color','b');
> set(fig,'UserData',info)
>
>
> function random_pick(varargin)
> fig = gcbf;
> info = get(fig,'UserData');
> info.index_handles = round(rand(1,5)*30)+1;
> set(fig,'UserData',info)
>
>
> function time_pick(varargin)
> fig = gcbf;
> info = get(fig,'UserData');
> n = varargin{end};
> c = clock;
> info.index_handles = c(n);
> set(fig,'UserData',info)
> %------------- end userdata_example.m --------------------
---
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Subject: eval, feval, global

From: Doug Schwarz

Date: 6 Apr, 2008 18:18:16

Message: 45 of 50

[top posting repaired]

In article <ftajte$hpa$1@fred.mathworks.com>,
 "Yuri Geshelin" <geshelin@hotmail.com> wrote:

> Doug Schwarz <see@sig.for.address.edu> wrote in message
> <see-5B0A29.12240405042008@71-129-133-66.dollamir.com>...
> > In article <ft800d$jcr$1@fred.mathworks.com>,
> > "Yuri Geshelin" <geshelin@hotmail.com> wrote:
> >
> > > Ok, I now have a fully working example, which I tried
> to
> > > make as short as possible. Below are 5 functions:
> > > global_example, refresh_all, plot_all, random_pick,
> > > time_pick. Execute global_example.m, and shouldn't be
> hard
> > > to figure out what the application does.
> > >
> > > %%%%%%%%%%%%%%% top of global_example
> > > function global_example
> > > figure(1),clf
> > > set(1,'position',[100 500 300 300])
> > > u1 = uicontrol('position',[ 20 20 100
> 30],'string','Random
> > > pick','callback','random_pick');
> > > u2 = uicontrol('position',[ 20 60 100
> 30],'string','Month
> > > pick','callback','time_pick(2)');
> > > u3 = uicontrol('position',[ 20 100 100
> 30],'string','Date
> > > pick','callback','time_pick(3)');
> > > u4 = uicontrol('position',[ 20 140 100
> 30],'string','Plot
> > > all','callback','plot_all');
> > > u5 = uicontrol('position',[180 140 100
> > > 30],'string','Refresh all','callback','refresh_all');
> > > plot_all
> > > %%%%%%%%%%%%%% bottom of global_example
> > >
> > > %%%%%%%%%%%%%%% top of refresh_all
> > > function refresh_all
> > > global final_handles index_handles
> > >
> > > if ishandle(final_handles)
> > > set(final_handles(index_handles),'color','r')
> > > end
> > > %%%%%%%%%%%%%%%%% bottom of refresh_all
> > >
> > > %%%%%%%%%%%%%%% top of plot_all
> > > function plot_all
> > > global final_handles index_handles
> > >
> > > index_handles = [];
> > > figure(2), clf
> > > set(2,'position',[600 500 300 300])
> > > final_handles = plot(repmat(1:31,2,1),'color','b');
> > > %%%%%%%%%%%%%%%%% bottom of plot_all
> > >
> > > %%%%%%%%%%%%%%% top of random_pick
> > > function random_pick
> > > global index_handles
> > > index_handles = [index_handles round(rand(1,5)*30)+1];
> > > %%%%%%%%%%%%%%%%% bottom of random_pick
> > >
> > > %%%%%%%%%%%%%%% top of time_pick
> > > function time_pick(n)
> > > global index_handles
> > > c = clock;
> > > index_handles = [index_handles c(n)];
> > > %%%%%%%%%%%%%%%%% bottom of time_pick
> > >
> > > Thanks Doug and everyone who will show me how to make
> do
> > > without GLOBAL.
> > >
> > > Yuri
> >
> >
> > Hi Yuri,
> >
> > Well, I had to correct a few problems with your example,
> but otherwise
> > it's a good one. I think I have correctly figured out
> what it is
> > supposed to do.
> >
> > I have two ways of doing the same thing without any
> global variables.
> > The first uses nested functions. With nested functions
> we have cheated
> > a bit because a nested function can access variables in
> the calling
> > program and this is very much like global variables in
> that you have to
> > be careful when debugging because all variables do not
> get passed
> > explicitly into the nested function workspace.
> Nevertheless, it is a
> > good technique (IMO) because you don't have to worry
> about name
> > conflicts with variables in other programs.
> >
> > The second example uses the method where, instead of
> globals, we pass
> > data around in a structure which gets stored in the
> UserData of the main
> > figure. It's a little more cumbersome because inside
> each subfunction
> > you have retrieve the UserData and then put it back at
> the end, but
> > because this is an explicit operation you might like it
> better than the
> > nested function approach.
> >
> > If you have a really old version of MATLAB and don't have
> function
> > handles (the @ operator) then we can modify the second
> example to use
> > the switchyard technique. Let me know if you need that.
> >
> > Anyway, here are the programs:
> >
> > %-------------- nested_fcn_example.m ---------------------
> ---
> > function nested_fcn_example
> > fig = figure('position',[100 500 300 300]);
> > u1 = uicontrol('position',[ 20 20 100 30],...
> > 'string','Random pick',...
> > 'callback',@random_pick);
> > u2 = uicontrol('position',[ 20 60 100 30],...
> > 'string','Month pick',...
> > 'callback',{@time_pick,2});
> > u3 = uicontrol('position',[ 20 100 100 30],...
> > 'string','Date pick',...
> > 'callback',{@time_pick,3});
> > u4 = uicontrol('position',[ 20 140 100 30],...
> > 'string','Plot all',...
> > 'callback',@plot_all);
> > u5 = uicontrol('position',[180 140 100 30],...
> > 'string','Refresh all',...
> > 'callback',@refresh_all);
> >
> > final_handles = [];
> > index_handles = [];
> > fig2 = [];
> > axes2 = [];
> >
> > plot_all
> >
> > function refresh_all(varargin)
> > if ~isempty(final_handles)
> > set(final_handles(index_handles),'color','r')
> > end
> > end
> >
> > function plot_all(varargin)
> > index_handles = [];
> > if isempty(fig2)
> > fig2 = figure('position',[600 500 300 300]);
> > axes2 = gca;
> > end
> > final_handles = plot(axes2,repmat
> (1:31,2,1),'color','b');
> > end
> >
> > function random_pick(varargin)
> > index_handles = round(rand(1,5)*30)+1;
> > end
> >
> > function time_pick(varargin)
> > n = varargin{end};
> > c = clock;
> > index_handles = c(n);
> > end
> >
> > end
> > %------------ end nested_fcn_example.m -------------------
> ---
> >
> >
> >
> > %--------------- userdata_example.m ----------------------
> ---
> > function userdata_example
> > fig = figure('position',[100 500 300 300]);
> > u1 = uicontrol('position',[ 20 20 100 30],...
> > 'string','Random pick',...
> > 'callback',@random_pick);
> > u2 = uicontrol('position',[ 20 60 100 30],...
> > 'string','Month pick',...
> > 'callback',{@time_pick,2});
> > u3 = uicontrol('position',[ 20 100 100 30],...
> > 'string','Date pick',...
> > 'callback',{@time_pick,3});
> > u4 = uicontrol('position',[ 20 140 100 30],...
> > 'string','Plot all',...
> > 'callback',@plot_all);
> > u5 = uicontrol('position',[180 140 100 30],...
> > 'string','Refresh all',...
> > 'callback',@refresh_all);
> >
> > info.final_handles = [];
> > info.index_handles = [];
> > info.fig2 = [];
> > info.axes2 = [];
> >
> > set(fig,'UserData',info)
> >
> > plot_all(u4)
> >
> >
> > function refresh_all(varargin)
> > fig = gcbf;
> > info = get(fig,'UserData');
> > if ~isempty(info.final_handles)
> > set(info.final_handles
> (info.index_handles),'color','r')
> > end
> >
> >
> > function plot_all(varargin)
> > fig = get(varargin{1},'Parent');
> > info = get(fig,'UserData');
> > info.index_handles = [];
> > if isempty(info.fig2)
> > info.fig2 = figure('position',[600 500 300 300]);
> > info.axes2 = gca;
> > end
> > info.final_handles = plot(info.axes2,repmat
> (1:31,2,1),'color','b');
> > set(fig,'UserData',info)
> >
> >
> > function random_pick(varargin)
> > fig = gcbf;
> > info = get(fig,'UserData');
> > info.index_handles = round(rand(1,5)*30)+1;
> > set(fig,'UserData',info)
> >
> >
> > function time_pick(varargin)
> > fig = gcbf;
> > info = get(fig,'UserData');
> > n = varargin{end};
> > c = clock;
> > info.index_handles = c(n);
> > set(fig,'UserData',info)
> > %------------- end userdata_example.m --------------------
> ---
> >
> > --
> > Doug Schwarz
> > dmschwarz&ieee,org
> > Make obvious changes to get real email address.


> Many thanks Doug,
>
> for teaching me a good programming style. I went over your
> examples, both are working nicely and make sense. I just
> want to share some thoughts.
>
> 1) I like the nested approach better, because it is a bit
> faster. Not that this is very important though. (And in
> this case, it is not important at all).
>
> 2) Instead of using figure's userdata, you can use that of
> the root (see sfreeman's post of 28 Mar). But this is a
> potential source of errors, because you can dump too many
> variables into this storage, while in the case of the
> figure at hand, you will focus on that figure.

One of the advantages of using the UserData of the gui figure is that
you can open multiple copies of your application and when you make that
figure go away you delete all the data associated with that version. If
you store the data in the UserData of the root then you're either
limited to one instance of your application at a time or else you have
to manage multiple sets of data.


> 3) I understand, there is a third way of doing it - to make
> a function recursively call itself, right? Something as you
> posted here on 31 March.

Yes, that's the old method that was necessary before function handles.


> 4) Maybe there are yet more ways of doing it, e.g. to use a
> constructor method, or to call a function, in which the
> structure is declared as a persistent. I will explore it
> when I will get a chance.

Again, you will have to manage multiple sets of data if you want to be
able to have more than one instance of your application open so I don't
recommend it.

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 6 Apr, 2008 21:29:02

Message: 46 of 50

Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-1580A7.14181806042008@71-129-133-66.dollamir.com>...

> If you store the data in the UserData of the root then
> you're either limited to one instance of your application
> at a time or else you have to manage multiple sets of
> data.

And how can you have more than one instance of your
application at a time?

Subject: eval, feval, global

From: Doug Schwarz

Date: 7 Apr, 2008 12:31:39

Message: 47 of 50

In article <ftbfau$oqe$1@fred.mathworks.com>,
 "Yuri Geshelin" <geshelin@hotmail.com> wrote:

> Doug Schwarz <see@sig.for.address.edu> wrote in message
> <see-1580A7.14181806042008@71-129-133-66.dollamir.com>...
>
> > If you store the data in the UserData of the root then
> > you're either limited to one instance of your application
> > at a time or else you have to manage multiple sets of
> > data.
>
> And how can you have more than one instance of your
> application at a time?

Look at my demogui2 or demogui2_new that I posted in this thread on
March 30. You can start up as many of those as you want and they will
all operate independently. Try it!

  >> demogui2_new
  >> demogui2_new

You'll have to move one so they don't overlap.

You can't have more than one of your gui because in it you refer to a
specific figure handle. You have to let the program assign a new handle
and then store it with the other data for that instance. That's one of
the things I fixed when I re-wrote your example.

--
Doug Schwarz
dmschwarz&ieee,org
Make obvious changes to get real email address.

Subject: eval, feval, global

From: Yuri Geshelin

Date: 7 Apr, 2008 19:09:02

Message: 48 of 50

Hi Doug,

Ok, I see. Thanks a lot for your time.

Yuri

Doug Schwarz <see@sig.for.address.edu> wrote in message
<see-2C1F3E.08320307042008@71-129-133-66.dollamir.com>...
> In article <ftbfau$oqe$1@fred.mathworks.com>,
> "Yuri Geshelin" <geshelin@hotmail.com> wrote:
>
> > Doug Schwarz <see@sig.for.address.edu> wrote in message
> > <see-1580A7.14181806042008@71-129-133-
66.dollamir.com>...
> >
> > > If you store the data in the UserData of the root
then
> > > you're either limited to one instance of your
application
> > > at a time or else you have to manage multiple sets of
> > > data.
> >
> > And how can you have more than one instance of your
> > application at a time?
>
> Look at my demogui2 or demogui2_new that I posted in this
thread on
> March 30. You can start up as many of those as you want
and they will
> all operate independently. Try it!
>
> >> demogui2_new
> >> demogui2_new
>
> You'll have to move one so they don't overlap.
>
> You can't have more than one of your gui because in it
you refer to a
> specific figure handle. You have to let the program
assign a new handle
> and then store it with the other data for that instance.
That's one of
> the things I fixed when I re-wrote your example.
>
> --
> Doug Schwarz
> dmschwarz&ieee,org
> Make obvious changes to get real email address.

Subject: eval, feval, global

From: OkinawaDolphin

Date: 14 Apr, 2008 07:51:04

Message: 49 of 50

"Yuri Geshelin" <geshelin@hotmail.com> wrote in message
<fsebf0$43u$1@fred.mathworks.com>...
> 1) Why are eval, feval considered not elegant and banned
in
> programming contests? I often use eval, why should a good
> programmer stay away from it?

As other posters mentioned, this has technical reasons.
Some toolbox functions use eval or feval, so the
programmers at The MathWorks might not consider eval and
feval as a bad thing.

> 2) Same question about GLOBAL.

This might be related to problems that occur when several
functions with global variables are called. If two
functions written by different participants have global
variables with the same name, there are side effects.

Basically global variables should be avoided, but sometimes
this is just impossible. Last year I developped an
application that contained a GUI, an event handler for an
ActiveX server (completely unknown to the GUI!), a database
and a timer. Both the timer function and the ActiveX server
event handler had to access the GUI and the database. When
the event handler for the ActiveX server answered to an
event, the timer had to be stopped and started again. The
GUI contained a button for closing the program. Closing the
program means closing the database connection and the event
handler, too.

I think this would be completely impossible to implement
without a global variable. Also, I wonder if it is really
better to have an extremely long list of input and
parameters than to use a global struct that is initialized
when the program is launched and cleared when the program
is closed.

Note that one global variable contained all data that had
to be shared. Using a global variable or even several ones
requires a very clean programming style.

A lot of people have a very sloppy programming style. This
includes even physicists and engineers who are actually
considered to work very precisely.

Subject: eval, feval, global

From: John D'Errico

Date: 14 Apr, 2008 11:50:18

Message: 50 of 50

"OkinawaDolphin " <OkinawaDolphin@Hotmail.com> wrote in message
<ftv2d8$t8j$1@fred.mathworks.com>...

> Basically global variables should be avoided, but sometimes
> this is just impossible. Last year I developped an
> application that contained a GUI, an event handler for an
> ActiveX server (completely unknown to the GUI!), a database
> and a timer. Both the timer function and the ActiveX server
> event handler had to access the GUI and the database. When
> the event handler for the ActiveX server answered to an
> event, the timer had to be stopped and started again. The
> GUI contained a button for closing the program. Closing the
> program means closing the database connection and the event
> handler, too.
>
> I think this would be completely impossible to implement
> without a global variable.

I'll disagree. A nested function will suffice
quite nicely. It stays around without having
to keep your gui open. Global variables are
not needed.


> Also, I wonder if it is really
> better to have an extremely long list of input and
> parameters than to use a global struct that is initialized
> when the program is launched and cleared when the program
> is closed.
>
> Note that one global variable contained all data that had
> to be shared. Using a global variable or even several ones
> requires a very clean programming style.

A single global struct can be replaced by a
single struct that is passed around.

John

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us