Thread Subject: Identifying workspaces

Subject: Identifying workspaces

From: Cygnine

Date: 9 Feb, 2010 04:07:04

Message: 1 of 18

I'm running Matlab R2008b. I would like to be able to determine whether a current workspace is the 'base' workspace. ('base' in the same context as the assignin and evalain statements.)

For example, I'd like to run something like

>> which_space_am_i_in()

and have it return 'base', or true, or something indicating the command-line workspace versus some workspace inside a function.

The basic functionality I'm looking for is I want a function to act differently depending if it's called from the command line (could be a script run from the command line) or from some other function.

Are there any builtin functions or simple ways to do this?

Subject: Identifying workspaces

From: Doug Schwarz

Date: 9 Feb, 2010 04:11:44

Message: 2 of 18

In article <hkqn18$ni2$1@fred.mathworks.com>,
 "Cygnine " <cygnine@remove.this.gmail.com> wrote:

> I'm running Matlab R2008b. I would like to be able to determine whether a
> current workspace is the 'base' workspace. ('base' in the same context as the
> assignin and evalain statements.)
>
> For example, I'd like to run something like
>
> >> which_space_am_i_in()
>
> and have it return 'base', or true, or something indicating the command-line
> workspace versus some workspace inside a function.
>
> The basic functionality I'm looking for is I want a function to act
> differently depending if it's called from the command line (could be a script
> run from the command line) or from some other function.
>
> Are there any builtin functions or simple ways to do this?


Check out dbstack.

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

Subject: Identifying workspaces

From: Cygnine

Date: 9 Feb, 2010 04:24:03

Message: 3 of 18

Doug Schwarz <see@sig.for.address.edu> wrote in message
> Check out dbstack.

Well, it's less elegant than I would've hoped, but I guess (length(dbstack)==1) provides a reasonable logical test. Thanks for the info.

Subject: Identifying workspaces

From: Steven Lord

Date: 9 Feb, 2010 15:01:24

Message: 4 of 18


"Cygnine " <cygnine@remove.this.gmail.com> wrote in message
news:hkqn18$ni2$1@fred.mathworks.com...
> I'm running Matlab R2008b. I would like to be able to determine whether a
> current workspace is the 'base' workspace. ('base' in the same context as
> the assignin and evalain statements.)
>
> For example, I'd like to run something like
>
>>> which_space_am_i_in()
>
> and have it return 'base', or true, or something indicating the
> command-line workspace versus some workspace inside a function.
> The basic functionality I'm looking for is I want a function to act
> differently depending if it's called from the command line (could be a
> script run from the command line) or from some other function.

Okay, I'll bite -- what's your use case? What should your function do
differently if called from the command line than if it's called from a
function?

--
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ

Subject: Identifying workspaces

From: Matt J

Date: 9 Feb, 2010 15:33:21

Message: 5 of 18

Here's what I use, but beware trying to using it in debug mode. The dbstack command is insensitive to dbup/dbdown etc...


function where
%The current location in the function stack



[s,wsi]=dbstack('-completenames') ;
 

str='In base workspace';


if length(s)>1,

  str=s(2).file;
  
end


disp(' ');
disp([' ' str]);
disp(' ');

Subject: Identifying workspaces

From: Cygnine

Date: 9 Feb, 2010 16:08:05

Message: 6 of 18

"Steven Lord" <slord@mathworks.com> wrote in message <hkrtc0$3l2$1@fred.mathworks.com>...
> Okay, I'll bite -- what's your use case? What should your function do
> differently if called from the command line than if it's called from a
> function?

Well, isn't that a doozy of a question. At the end of this message, just remember: you asked :)

I'm in the process of hacking Matlab's builtin function representation (actually, I'm pretty much done). I'm a fan of the way Python handles things myself. Right now I've tweaked things with the packages I've written that I can do things like:

>> from finite_difference.matrices import central_second_order_matrix as d2

And this creates a function handle d2 in whichever workspace from which it's called. Unfortunately, I write lots of functions and frequently forget information about it (# of inputs, order of inputs, what the original function d2 was called, etc.).

To solve this, I've created a class FunctionNode, and each instance of FunctionNode corresponds to an m-file in a package. Now I've overloaded subsref for this object so that using function calling syntax, i.e. f(blah1, blah2), works exactly the same way as a function handle. However, going through Matlab's internal processing structure of overloading subsref appears to take a considerable amount of time (and my codes call lots of FunctionNodes multiple times). This is why the "from" statement only imports the function handle and not the entire FunctionNode instance -- for speed.

However, when I'm at the command line, I'd like to access my helpstring for a function imported using "from". I don't think I can do this using Matlab's implementation of a function handle. Sooooo, if I type a from statement at the command prompt or a script, I probably don't care about the extra time necessary to pass through subsref, but I DO care about helpstrings, function locations, etc. So at the command line I want to import the FunctionNode instance.

But inside a function, unless I'm debugging, then I have absolutely no need for helpstrings, etc., so I just want to import the function handle.

And all of this is just a way for me to create nice Python-like importing structures in Matlab so that I don't have to pollute namespaces with all of the bazillions of functions that I use (plus I create different functions with the same name...Matlab doesn't like that). I'm not aware of a clean way to do this in Matlab. (I don't like messing around with the PATH variable, and I am aware of Matlab's builtin import statement...I don't like it.).

Oh, and Matt J:

Thanks for the more in-depth implementation. I won't be needing this functionality in debug mode, so that's ok.

Subject: Identifying workspaces

From: Matt J

Date: 9 Feb, 2010 16:38:04

Message: 7 of 18

"Cygnine " <cygnine@remove.this.gmail.com> wrote in message <hks195$fpc$1@fred.mathworks.com>...

> And all of this is just a way for me to create nice Python-like importing structures in Matlab so that I don't have to pollute namespaces with all of the bazillions of functions that I use (plus I create different functions with the same name...Matlab doesn't like that). I'm not aware of a clean way to do this in Matlab. (I don't like messing around with the PATH variable, and I am aware of Matlab's builtin import statement...I don't like it.).
============================

Well, you said you don't like to mess with the path, but I'll just point you regardless to my FEX submission which does precisely that.

http://www.mathworks.com/matlabcentral/fileexchange/26221-namespace-scoping-operator

If you read the fine print, you'll see that there are some hazards, but the hazard is mainly if one of the functions you're trying to import is itself a path-manipulating function, which you say is already something you try to avoid.

Subject: Identifying workspaces

From: Cygnine

Date: 9 Feb, 2010 16:54:04

Message: 8 of 18

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message
> http://www.mathworks.com/matlabcentral/fileexchange/26221-namespace-scoping-operator
>
> If you read the fine print, you'll see that there are some hazards, but the hazard is mainly if one of the functions you're trying to import is itself a path-manipulating function, which you say is already something you try to avoid.

Huh, that seems pretty snazzy. Obviously I don't understand the implementation yet, but it seems that it should be robust for most purposes. However, for me a big issue is speed (I run codes that collect many files from many different packages together). You do mention that path switching might be a little slow, and add this to whatever overhead is incurred by nesting things inside a class, and it might be too much for me.

Nevertheless, I'll probably download this and take a look-see. Thanks!

Subject: Identifying workspaces

From: Matt J

Date: 9 Feb, 2010 18:46:05

Message: 9 of 18


> Huh, that seems pretty snazzy. Obviously I don't understand the implementation yet, but it seems that it should be robust for most purposes. However, for me a big issue is speed (I run codes that collect many files from many different packages together). You do mention that path switching might be a little slow, and add this to whatever overhead is incurred by nesting things inside a class, and it might be too much for me.
=========================

Well, keep in mind the alternative syntax shown in Example 2

            newspace(Obj); %switches to temporary path
   
               %do stuff
   
            oldspace(Obj); %switches back to original path


The code in the "do stuff" section will execute under the temporary path with whatever speed it normally would in MATLAB. So, as long as these computations in that block are numerous enough or intensive enough that the CPU time is much longer than the time it takes to switch paths, the overhead due to path-switching will be 2nd order.

I don't know if that secnario applies to you...

Subject: Identifying workspaces

From: Cygnine

Date: 9 Feb, 2010 20:00:21

Message: 10 of 18

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message
> Well, keep in mind the alternative syntax shown in Example 2
>
> newspace(Obj); %switches to temporary path
>
> %do stuff
>
> oldspace(Obj); %switches back to original path
>
>
> The code in the "do stuff" section will execute under the temporary path with whatever speed it normally would in MATLAB. So, as long as these computations in that block are numerous enough or intensive enough that the CPU time is much longer than the time it takes to switch paths, the overhead due to path-switching will be 2nd order.

Well, it turns out that such a scenario probably will apply to me. I certainly know that CPU time is significantly wasted if I overload subsref. I'll have to test it out to see if it applies when I change the path on the fly as well.

Subject: Identifying workspaces

From: Cygnine

Date: 9 Feb, 2010 20:15:21

Message: 11 of 18

Well, nobody likes a double-post, but it turns out that dbstack didn't quite solve my problem. (Or at least I don't know how to use it to solve the problem.)

If I run

[s, index] = dbstack

at the command line, s has length 0 and index is 1. Fine.

If copy+paste that into a script and run it, then s has length 1 and index is 1. Fine.

If I copy+past that into a function and run it *from the command line*, then s has length 1 and index is 1. Fine.

If I run the aforementioned function *from a script*, then s has length 2 and index is 1. Not fine.

I want to be able to say from the last two instances that the workspace from which the function was called is the base workspace. I don't see how I can determine that from the given information of dbstack. How do I ask dbstack to tell me that the enclosing m-file is a function or a script? I don't think the "file" or "name" field of the struct s give me that information.

In particular, I don't understand what "index" is supposed to be. The help file for dbstack states that it's the "current workspace index". I cannot find any (other) reference to "workspace index" in Matlab's product help or from Google. So either dbstack does not really help me entirely,

Subject: Identifying workspaces

From: Doug Schwarz

Date: 9 Feb, 2010 21:09:46

Message: 12 of 18

In article <hksfop$fuj$1@fred.mathworks.com>,
 "Cygnine " <cygnine@remove.this.gmail.com> wrote:

> Well, nobody likes a double-post, but it turns out that dbstack didn't quite
> solve my problem. (Or at least I don't know how to use it to solve the
> problem.)
>
> If I run
>
> [s, index] = dbstack
>
> at the command line, s has length 0 and index is 1. Fine.
>
> If copy+paste that into a script and run it, then s has length 1 and index is
> 1. Fine.
>
> If I copy+past that into a function and run it *from the command line*, then
> s has length 1 and index is 1. Fine.
>
> If I run the aforementioned function *from a script*, then s has length 2 and
> index is 1. Not fine.
>
> I want to be able to say from the last two instances that the workspace from
> which the function was called is the base workspace. I don't see how I can
> determine that from the given information of dbstack. How do I ask dbstack to
> tell me that the enclosing m-file is a function or a script? I don't think
> the "file" or "name" field of the struct s give me that information.
>
> In particular, I don't understand what "index" is supposed to be. The help
> file for dbstack states that it's the "current workspace index". I cannot
> find any (other) reference to "workspace index" in Matlab's product help or
> from Google. So either dbstack does not really help me entirely,

Try nargin('junk'). If junk.m is a function it returns the number of
input arguments. If junk.m is a script you get an error.

By the way, are you familiar with packages in MATLAB? You can package a
bunch of functions in a directory named with a +. For example, if there
is a directory, '+mycode', on the MATLAB path and it contains fcn.m, you
call that function with

  mycode.fcn()

and there is no conflict with any other fcn.m on your path. I know it's
not the same as Python and its import statement in that you have to use
the full package name, but maybe it's better than the non-standard
kludge you're working on now. Just a thought.

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

Subject: Identifying workspaces

From: Matt J

Date: 9 Feb, 2010 21:51:02

Message: 13 of 18

Doug Schwarz <see@sig.for.address.edu> wrote in message <see-99AAD7.16094609022010@news.frontiernet.net>...

> By the way, are you familiar with packages in MATLAB? You can package a
> bunch of functions in a directory named with a +. For example, if there
> is a directory, '+mycode', on the MATLAB path and it contains fcn.m, you
> call that function with
>
> mycode.fcn()
>
> and there is no conflict with any other fcn.m on your path.

However, if inside mycode.fcn() a call is to be made to another function fnc2() which is also in the +mycode package, then it too must use the syntax mycode.fcn2() and so in with every function call. As well as being a cumbersome syntax, this means that, if you are given a library of mfiles that was not initially written as a package, it is very tedious to convert it. This is one of the main reasons I resorted to my FEX tool.

Subject: Identifying workspaces

From: Matt J

Date: 9 Feb, 2010 22:28:04

Message: 14 of 18

"Cygnine " <cygnine@remove.this.gmail.com> wrote in message <hks195$fpc$1@fred.mathworks.com>...

> To solve this, I've created a class FunctionNode, and each instance of FunctionNode corresponds to an m-file in a package. Now I've overloaded subsref for this object so that using function calling syntax, i.e. f(blah1, blah2), works exactly the same way as a function handle. However, going through Matlab's internal processing structure of overloading subsref appears to take a considerable amount of time (and my codes call lots of FunctionNodes multiple times).
===================

Even if that is true, by the way, it probably only means you are committing the classic MATLAB sin of trying to do a for-loop over computations that are better off being vectorized. For the overhead of going through subsref to be significant, the rest of the computations done by a single call to f(blah1,blah2) would have to be lightning fast. But we never do a loop over lightning fast function calls in MATLAB. We make one function call in a vectorized way.

Consider the following class, for example, which is essentially a subsref-driven function handle to the sin() function


classdef myClass

  methods
      function out=subsref(ob,S)
          
          out=sin(S.subs{:});
      end
      
  end
  
end


Now take the data

X=rand(3000);
FancyHandle=myClass;

and compare the following timings. Essentially, there's no difference.

>> clear z, tic; z=sin(x);toc
Elapsed time is 0.287017 seconds.

>> clear z, tic; z=FancyHandle(x);toc
Elapsed time is 0.261119 seconds.

Subject: Identifying workspaces

From: Cygnine

Date: 9 Feb, 2010 23:15:06

Message: 15 of 18

Doug Schwarz <see@sig.for.address.edu> wrote in message
> Try nargin('junk'). If junk.m is a function it returns the number of
> input arguments. If junk.m is a script you get an error.

Hm, I'm afraid I don't follow your line of logic. If I'm inside a function, how do I use this to gather information about the number of input arguments in the caller? I suppose I could do something with an evalin statement by grabbing the function name from dbstack. However, as I mentioned before, with the Pythonic methods, I (often) rename function handles locally to names that are different from the function name inside the file -- I don't think dbstack will jive with this. And `nargin' run at the command line or in a script returns garbage (that could turn out to be an integer).

> By the way, are you familiar with packages in MATLAB?

Yes. But for the reasons Matt J specified (and others), I prefer not to use it.

> I know it's not the same as Python and its import statement in that you have to use
> the full package name, but maybe it's better than the non-standard
> kludge you're working on now. Just a thought.

You have a valid point about the Matlab packages functionality being built-in already. However, from my (admittedly biased) point of view, my method is much easier to work with and has serious advantages over Matlab's packages with few drawbacks (the current concern being one of them). The concern of the current thread is really quite ancillary and almost cosmetic.

"Matt J " <mattjacREMOVE@THISieee.spam> wrote in message
> Even if that is true, by the way, it probably only means you are committing the classic > MATLAB sin of trying to do a for-loop over computations that are better off being
> vectorized. For the overhead of going through subsref to be significant, the rest of
> the computations done by a single call to f(blah1,blah2) would have to be lightning
> fast. But we never do a loop over lightning fast function calls in MATLAB. We make
> one function call in a vectorized way.

But it is not always possible to 'vectorize' code (e.g. if operations are inherently sequential). I always make pretty honest efforts to vectorize all code I write, but sometimes it's not possible (and sometimes it's not worth it). This happens often enough that I observe (significant) time penalties if I use a class instance to call a function rather than the handle directly. Besides, many of the codes I write do indeed perform fancy operations by creative uses of lightning-fast precompiled BLAS routines that drive Matlab's array backend; for moderately-sized arrays, the subsref call could double the required time. That's not acceptable to me.

And just as a comment: I'm not actually sure it's subsref that is the time restriction. It could just be that Matlab implementation of classes in general just isn't fast.

Subject: Identifying workspaces

From: Matt J

Date: 9 Feb, 2010 23:31:20

Message: 16 of 18


> But it is not always possible to 'vectorize' code (e.g. if operations are inherently sequential). I always make pretty honest efforts to vectorize all code I write, but sometimes it's not possible (and sometimes it's not worth it). This happens often enough that I observe (significant) time penalties if I use a class instance to call a function rather than the handle directly. Besides, many of the codes I write do indeed perform fancy operations by creative uses of lightning-fast precompiled BLAS routines that drive Matlab's array backend; for moderately-sized arrays, the subsref call could double the required time. That's not acceptable to me.
>
> And just as a comment: I'm not actually sure it's subsref that is the time restriction. It could just be that Matlab implementation of classes in general just isn't fast.
===============

Ver y well. But then it's pretty clear that the overhead has nothing to do with MATLAB classes. It's simply because you've written subsref in M-code and all M-code execution is slower in general than C-code, not just class methods. You could have coded subsref as a MEX file, for example, and then it would have been nice and fast...

Subject: Identifying workspaces

From: Joao Henriques

Date: 16 Apr, 2010 21:28:05

Message: 17 of 18

How about this:

if isempty(evalin('caller','mfilename'))
    %from command line
else
    %from function or script
end

It will let you see if the caller is the command line or something else.

---

I'm also a fan of Python, but when in Rome... I handle this problem "the Matlab way", so I make some effort to differentiate variable names when they will be used in the same project.

To handle different projects with overlapping names, I think most people have an "init" script in each project that calls addpath repeatedly to set up all the needed folders (I've seen many files in the File Exchange with this system). This requires some effort on the user's part (type "init" at the console), but an easy way to make it more automatic is to change the "init.m" to be something like this:

if exist('initialized_project_xyz','var')
  addpath abc
  addpath def
  ...
  initialized_project_xyz = true
end

Then "init" can be called at the beginning of all your main scripts, with negligible overhead. "addpath" already checks if you're adding a path that already exists, but is considerably slower.

I'm interested in this topic, so any improvement suggestion is very welcome :)

Subject: Identifying workspaces

From: Joao Henriques

Date: 16 Apr, 2010 21:38:20

Message: 18 of 18

"Joao Henriques" <remove_this_part_jotaf98@hotmail.com> wrote in message <hqakp5$fmp$1@fred.mathworks.com>...
> I'm also a fan of Python, but when in Rome... I handle this problem "the Matlab way", so I make some effort to differentiate variable names when they will be used in the same project.

And by variable names, I obviously meant "function names"...

---

I also found a neat trick to group many small functions inside the same M-file, which may interest you as it allows you to reduce the number of files and thus have less folders to mess with. Put this in one M-file:

function some_module = get_some_module()
    some_module.func_a = func_a;
    some_module.func_b = func_b;
end

function func_a()
    disp a
end

function func_b()
    disp b
end

Now you can "import" all the functions in that group:
some_module = get_some_module();

And call them:
some_module.func_a()
some_module.func_b()

It's like an importable module in a single file; useful when you have a group of many small but related functions; or as a generic module if you don't mind having a rather large M-file.

Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

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.

Tag Activity for This Thread
Tag Applied By Date/Time
namespace Matt J 9 Feb, 2010 16:55:25
workspace Cygnine 8 Feb, 2010 23:09:06
rssFeed for this Thread

Contact us at files@mathworks.com