[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: locally changing global variables
From: |
Jaroslav Hajek |
Subject: |
Re: locally changing global variables |
Date: |
Tue, 18 May 2010 07:53:12 +0200 |
On Tue, May 18, 2010 at 7:43 AM, John W. Eaton <address@hidden> wrote:
> On 10-May-2010, Jaroslav Hajek wrote:
>
> | Octave's global pseudo-variables are a useful tool for customizing
> | Octave's settings, yet they present problems when a function is
> | dependent on a particular state of a certain variable. A typical
> | instance in my work is console output magic used for progress tracking
> | of a lengthy task that may be delayed or even completely spoiled by
> | the pager. A temporary change of a particular variable can be achieved
> | by unwind_protect:
> |
> | function progress(n)
> | old_pso = page_screen_output (false);
> | unwind_protect
> |
> | for i = 1:n
> | printf ("\r%d", i);
> | pause (0.25);
> | endfor
> | printf ("\rdone.\n");
> |
> | unwind_protect_cleanup
> | page_screen_output (old_pso);
> | end_unwind_protect
> | endfunction
> |
> | this is, however, somewhat wordy and ugly, requiring the programmer to
> | enclose the whole function body in an unwind_protect block, and
> | explicitly invent the variable name for storing the old value.
> |
> | What I propose is to enable calling the pseudo-variables with a
> | "local" option argument, requesting the variable to be restored when
> | the current function exits. Thus, the previous function could be
> | written like this:
> |
> | function progress(n)
> | page_screen_output (false, "local");
> |
> | for i = 1:n
> | printf ("\r%d", i);
> | pause (0.25);
> | endfor
> | printf ("\rdone.\n");
> | endfunction
> |
> | this is, of course, much more readable.
> |
> | An incomplete (no ChangeLogs & no docs) patch is attached. The patch
> | implements the cleanup action very efficiently, reusing the existing
> | unwind_protect frame inside the calling function. Hence, besides being
> | more readable, the second form should also be more efficient. Multiple
> | variables may be changed at any point in the function, and they will
> | all be restored (in the reverse order) at the very end of the
> | function.
> |
> | Comments? Suggestions?
>
> Sorry for the late reply on this. I don't object to this change as it
> does make temporary settings somewhat easier.
>
> Do your current changes apply only to internal variables? How can
> something similar be done for variables that are managed entirely by a
> user-defined function? For example, one nice thing about switching
> from actual variables for user preferences to functions was that we
> made it possible for users to write functions like
>
> function retval = my_special_value (val)
> persistent curr_val = "default_value";
> if (nargin == 1)
> if (nargout > 0)
> retval = curr_val;
> endif
> curr_val = val;
> elseif (nargin == 0)
> retval = curr_val;
> else
> print_usage ();
> endif
> endfunction
>
> Is it possible to adapt a function like this to accept a second
> "local" argument?
>
Currently, I think not. It would be possible if we had a working
onCleanup implementation. Despite we have unwind_protect, which is, in
most practical ways, more versatile, onCleanup being an object allows
for doing magic, such as injecting a cleanup action to caller scope
(which could be the solution here). I'll start a separate thread about
this.
--
RNDr. Jaroslav Hajek, PhD
computing expert & GNU Octave developer
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz