27

Tried Googling, but couldn't find anything.
I have a few files and folders in my current MATLAB folder.
One of those folders is called 'Map' and it has a 'map1.m' file which I want to call from my code in the current MATLAB folder.
In my code, I can't call it like this:

/Map/map1;

but I can do so like this:

cd Map;
map1;
cd ..;

Somehow the above method seems incorrect. Is there a more elegant way to do it?

Amro
  • 123,847
  • 25
  • 243
  • 454
Nav
  • 19,885
  • 27
  • 92
  • 135
  • 2
    You have to add the folder to the [MATLAB path](http://www.mathworks.com/help/techdoc/ref/path.html). This has been covered already in these other questions: [Importing matlab functions in matlab](http://stackoverflow.com/q/2841499/52738), [matlab search path](http://stackoverflow.com/q/2129646/52738) – gnovice May 27 '11 at 14:07
  • 1
    @gnovice: This is NOT a duplicate. The script _can_ be run without modifying the path, and the current question seems to ask that, instead of how to modify the path. The links above are useful additional info. – abcd May 27 '11 at 14:40
  • 1
    There is a caveat with your approach @yoda, namely that it will only work on scripts. The answer provided by @gnovice will work for both functions and scripts, so further clarification is required from the OP. In fact the title does mention function, so I'm tending to go with @gnovice on this one. – jmetz May 27 '11 at 17:20
  • @mutzmatron: It will work with functions that don't require an input. And since OP specifically mentioned that he can call his function/script as `map1` from its parent folder, it means that it is either a script or a function that doesn't require any input variables. My answer is perfectly fine in this case. – abcd May 27 '11 at 17:27
  • @yoda: Ok so it will work for the special case of zero-input functions. I don't think that constitutes a useful answer though, and the more general approach would be to add the path. I'm not sure why you interpreted the question as specifying that the path should not be modified (re. your reply to @gnovice comment) – jmetz May 27 '11 at 17:30
  • @mutzmatron: I don't see how answering OP's specific question correctly constitutes an unhelpful answer. Sure, there are cases where it won't work (I'll probably edit it in to make it obvious), but to claim that it _cannot_ be done without adding the path is incorrect and misleading. There are reasons why one would not want to add a folder to the path and use this approach instead. – abcd May 27 '11 at 17:35
  • 1
    @yoda: Actually as you mention in your post, `run` is a convenience function. If you check out the source code, it is pretty much just what the OP does manually, in function form! I.e. it extracts the directory from the input, cd's to it, calls the function, and returns to the original directory. Therefore, is is not going to be the same as calling the code from the current directory, which the OP asks for (for example they may have other functions in the current directory which they also need...). – jmetz May 27 '11 at 17:41
  • @mutzmatron: Yes, if you read the documentation, it says that right there. I'm aware of this, which is why I wrote in the first line "...without adding... _manually_ " – abcd May 27 '11 at 17:43
  • @mutzmatron: The key part is _it returns back to the folder_ after executing the function, and so any function called there after will be in the path, and will work. I don't advocate using run. I have never used it and never will. But as an answer the OP's question, yes `run` can be used. – abcd May 27 '11 at 17:45
  • 1
    @yoda - Ok I see your point. However, as you mention, you will never use `run` yourself, and therefore while technically your answer can be used, I still don't think it's a good one wrt coding practices, and would still advocate the modification of the path variable _a la_ `addpath`. Thank you for clarifying your reasoning though. I do agree with you that in it's current form, it's not clear whether the OP is a duplicate of `addpath`-type questions, though I suspect that it may be. – jmetz May 27 '11 at 17:52
  • @mutzmatron: I agree with you w.r.t. coding practice. However, I _try_ to refrain from advocating any change in the way they go about their code, although it does slip in at times. For e.g., I think I have decent coding habits, but I'm not at all a programmer. Programming is just a necessary evil for me, and there are some things that I do that would make a seasoned programmer cringe. However, although I might see his point, I might not wish to modify my habits because the benefits are small _for me_. So in general, I just try to answer the question and leave the proselytizing for later. – abcd May 27 '11 at 18:03
  • 2
    Wow, almost a flame war. OP sounds like a less experienced Matlab programmer. For less experienced programmers, we should tell them the approach that's likely to work best, and point out the assumptions implicit in the question, rather than just narrowly, literally answering exactly what they asked, and having them follow an approach that's likely to have a bunch of problems in practice. I'm dropping in an alternate answer, let's vote on how to do it! – Andrew Janke May 27 '11 at 20:54
  • 1
    BTW, +1 to gnovice since my answer is just his approach, plus some argumentation in favor of it. – Andrew Janke May 27 '11 at 21:04

3 Answers3

40

You can run the file without adding the folder to your path manually, using the run command, which is specifically for such cases. From the documentation:

run is a convenience function that runs scripts that are not currently on the path.

You call your function/script as

run /Map/map1 

If you want to run the function/script by merely entering its name and not with the full (or relative) path, then you should add the folder to your path.

As noted by @mutzmatron, you cannot use run to call functions with input/output arguments. So, unless if it's a script/function without input/output arguments, using run will not work and you'll have to add the folder to your path.


EDIT

Just as a matter of good coding practice, and to work in cases where your function has inputs/outputs, adding/removing the folder from your path is the correct way to go. So for your case,

addpath /Map
...

map1;

...
rmpath /Map

The important thing is that your function call is sandwiched between the addpath and rmpath commands. If you have functions of the same name in both folders, then you should sandwich it tighter i.e., a line before and a line after, so as to avoid conflicts.

Community
  • 1
  • 1
abcd
  • 41,765
  • 7
  • 81
  • 98
  • 1
    Coolio! Addpath and rmpath were exactly what I needed. Thanks :) – Nav May 28 '11 at 08:38
  • this does not run a function with an argument. – Lord Loh. Aug 18 '14 at 19:10
  • 1
    @LordLoh., the point is that it _can_, whereas `run /script` can't. – yak Oct 03 '14 at 05:49
  • 1
    I'm sorry but adding and removing the path is ***NOT*** good coding practice. It does not preserve the state of the path, in the event that `Map` is already on the path beforehand. Still, it's the only way to accomplish what should be a simple task. I strongly favour organising functions with namespaces (last part of @Andrew Janke's answer) – Sanjay Manohar Dec 03 '15 at 11:50
  • 1
    Like @SanjayManohar says this approach is not ideal. What if an exception is thrown before reaching rmpath? Any better ideas? In Matlab finally clause cannot be used like in python, right? – Taro Kiritani Feb 15 '17 at 23:12
  • the rough equivalent to `finally` is to just use `try...catch` then put the code after -- this is fine as long as you don't re-throw the exception. I added an alternative answer below. – Sanjay Manohar Feb 17 '17 at 00:30
7

Just add all those directories to the Matlab path with addpath like gnovice suggests. Then you'll be able to call the functions normally, and they'll be visible to which(), help(), depfun(), and the other Matlab meta-programming commands. You can put the addpath() calls in your startup.m file to have them automatically appear each time you start Matlab.

Changing the path with addpath/map1()/rmpath each time has some drawbacks.

  • It's a performance hit because you're adding path manipulation to each call.
  • Functions in different directories won't be able to see each other.
  • It'll be harder to write and debug functions because the path context in which they execute will change dynamically, and won't be the same as what you see when you're in the editor and the base workspace.
  • You need additional error handling code to make sure the path is properly restored if the called function errors out.
  • This won't work with the Matlab Compiler, if you want to deploy this code at some point.

And using run() or cd() yourself is ugly, because relative paths are going to have problems.

If you really want to separate the functions in the subdirectories so they can't "see" each other, you can make those directories namespaces by putting a "+" in front of their names, and then qualify the function calls with the namespace, like Map.map1().

Andrew Janke
  • 23,508
  • 5
  • 56
  • 85
  • Useful tips! For me, what'll work easily for now is to use addpath in the beginning of my program and place rmpath at the end of the program. So no performance hits :) – Nav May 28 '11 at 08:48
0

Just to contribute to the path-altering debate...

One way to make it a bit "safer" is to write

% start of my code: create function handles 
% to the functions I need:
try
   cd Map
   map1_func = @map1;
catch mexception
end
cd ..

This tries to preserve the current directory, and you get a handle to the function in a different directory.

Only thing is, this method won't work if map1 relies upon other functions in the Map directory.

Sanjay Manohar
  • 6,920
  • 3
  • 35
  • 58