I'm trying out organising my matlab code into packages, but having to use fully qualified names in nested package functions is killing me.
Say I have a package called +myPack that looks like this:
+myPack
bar.m
baz.m
The bar function might look like
function bar()
myPack.baz()
end
This is all fine and logical. However, +myPack is a componant that will be reused in multiple other packages. Lets say one looks like this:
+mySuperPack
foo.m
+myPack
bar.m
baz.m
This time, foo calls bar, which in turn calls baz. However, the original code for bar will fail because I have not used the fully qualified name
mySuperPack.myPack.baz()
Obviously +myPack doesn't know which super pack it is in, so I can't do that.
This also stops you from being able to use static methods in classes that are in packages; the class has to know which package it is in to call its own static methods, which seems crazy.
Is there any way to use nested packages like this, or am I doing packages totally wrong?
Instead of writing
mySuperPack.myPack.baz()
you can write
import mySuperPack.myPack.*
baz()
You only need to write the import statement once. Unfortunately (and this is one of the few things that really bugs me with MATLAB) import only imports into the current workspace, so you need to write it once per function/method.
I really wish you could just write it once at the top of a file, and have it import into all functions in the file, or at the top of a class and have it import into all methods of the class, but there you go. At least it's better than always needing fully qualified names everywhere.
PS on the issue of static methods: although you might typically call them as ClassName.staticMethodName, or pkgName.ClassName.staticMethodName, if you have an object obj of that class, you can also call it using obj.staticMethodName. Obviously that's not always relevant, but if you're calling a static method from within a normal method it can be convenient, as you don't need to mention (or import) the package.
Related
I have a Swift application that uses a module, and I need to call a global function that is in the application from the module, is this possible?
To perhaps explain a little better, this is a test app structure:
CallbackTestApp contains a function foo(), I would like to call it from Module1 or File, will swift allow this?
edit #1
More details have been requested on what is the background of my issue, hopefully, this will not turn out to be an XY situation.
There's a tool developed by my company that process the application source* code and in some places add function call (ignore the why etc, have to be generic here.). Those function calls are exactly to foo() which then does some magic (btw, no return value and no arguments are allowed), if the application does not use modules or if modules are excluded from the processing then all is fine (Linker does not complain that the function is not defined), if there are modules then nothing works since I did not found a way to inject foo() (yet).
*Not exactly the source code, actually the bitcode is processed, the tool get the source, use llvm toolchain to generate bitcode, do some more magic and then add the call to foo() by generating it's mangled name and adding a swiftcall
Not actually sure those additional details will help.
Let's say I have some MATLAB code that uses some functions.
I don't want to define the functions in the same file as the code that uses
the functions.
On the other hand, the solution of making an m file for each function is also not good for me because I don't want a lot of files.
What I want is something like a utils file that holds those functions, from which I can import the functions like we do in python, for example.
What would you recommend?
What you probably want is to use a package, which is kind of like a python module in that it is a folder that can hold multiple files. You do this by putting a + at the beginning of the folder name, like +mypackage. You can then access the functions and classes in the folder using package.function notation similar to Python without it polluting the global list of functions (only the package is added to the global list, rather than every function in it). You can also import individual functions or classes. However, you always have to use the full function path, there is no such thing as relative paths like in Python.
However, if you really want multiple functions per file, probably the best you can do is create a top-level function that returns a struct of function handles for the other functions in the file, and then access the function handles from that struct. Since MATLAB doesn't require the use of () with functions that don't require any inputs, this would superficially behave similarly to a python module (although I don't know how it will affect performance).
I know this is a pain in the neck. There is no reason mathworks couldn't allow using files as packages like they currently do for folders, such as by putting + at the beginning of the file name. But they don't.
A solution close to what you are looking for could be the use of classes. A class contains methods that can be public (visible from outside) or private (only visible from inside). Implementations of the methods of a class can be either in multiple files or in the same file.
Here is a simplistic example
classdef Class1
methods (Static)
function Hello
disp('hello');
end
function x = Add(a,b)
x = Class1.AddInternal(a,b);
end
end
methods (Static, Access=private)
function x = AddInternal(a,b)
x = a+ b;
end
end
end
Example of use-:
>> Class1.Hello
hello
>> Class1.Add(1,2)
ans =
3
>> Class1.AddInternal(2,3)
Error using Class1.AddInternal
Cannot access method 'AddInternal' in class 'Class1'.
I have some code for solving a puzzle game called nurikabe, recently I've been rewriting it to OOP (still learning) and have the following structure:
# CNurikabe.py
from includes import Board, Validation, Heuristics
class CNurikabe(object):
...
# CValidation.py
from includes import Board, Heuristics
class CValidation(object):
...
# CHeuristics.py
from includes import Board
class CHeuristics(object):
...
# CBoard.py
class CBoard(object):
def __init__(self, filename):
# Vars shared by every class
self.x, self.y, self.z, self.t = self.parseData(filename)
# run.py
from CNurikabe import CNurikabe
nurikabe = CNurikabe()
nurikabe.solve('output')
# includes.py
from CBoard import CBoard
Board = CBoard('data.dat')
from CHeuristics import CHeuristics
Heuristics = CHeuristics()
from CValidation import CValidation
Validation = CValidation()
CBoard class has info which has to be shared among all the other classes (such as board dimensions, number coordinates, etc), also I want it to be instantiated once, if possible preventing dependency injection (unnecessarily passing the filename to each class init method, for example)
The classes are needed to access the following:
CValidation class use: CBoard and CHeuristics
CHeuristics class use: CBoard
CNurikabe class use: CBoard, CValidation and CHeuristics
The code I have, works just as expected. I can call other class' methods within the other classes just the way I want it, for example:
# CNurikabe.py:
class CNurikabe(object):
def someFunc(self):
for i in range(Board.dimensionx):
Heuristics.doSomeStuff()
Validation.doSomeMore()
But I've read maybe too much about how globals are evil. Also the code inside includes.py is a bit hackish, because if I change the order of the imports the program won't run, complaining about being unable to import some names.
I also tried another way, only instantiating globally the CBoard class and then, for the other classes, creating an instance of the classes I need. But I felt that was kinda repetitive, creating an unique global instance of CHeuristics inside each class, for example, and that still wouldn't solve the CBoard global problem.
I also thought about creating an instance inside each class's init, but then the code would be very verbose, having to call for example: self.Heuristics.doSomeStuff()
So my question is what would be a better approach to structure this? I've read about singleton patterns (which may be overkill, since it's a small project), and endless ways of doing it for multiple languages like C++ and PHP. Actually The way I'm doing it resembles that of the "extern Class instance;" way of doing it in C++, long time ago I was working on a C++ project that had that style and I liked it, didn't see any problems with it, although the class instances were global.
Globals are evil. However, you probably need a singleton pattern that encapsulate some things together. My experience from C++ and Python is that you can nicely use the hybrid character of the language and use a module in the role of singleton. (If you think more about it, module variables play the role of a singleton member variables, plain functions in the module resemble methods of a singleton.)
This way I suggest to put the board functionality into board.py heuristic functionality into heuristic.py,..., convert the methods to functions, self.variable to variable and use:
import board
import heuristic
import validation
...
class CNurikabe: # the explicit (object) base class is not needed in Python 3
def someFunc(self):
for i in range(board.dimensionx):
heuristics.doSomeStuff()
validation.doSomeMore()
Think about the import board as about getting the reference to the singleton instance -- which actually is, because there is a single instance of the module object. And it will be syntactically the same as your older code -- except getting the instance (the module) will be easier.
Update: Once you need more instances, you should think in classes again. However, passing objects is very cheap operation in Python -- you only copy reference values (technically the address, i.e. 4 or 8 bytes). Once you get the reference value, you can easily assign it to a local variable. (Every assignment in Python means copying the reference value, hence sharing the access to the assigned object. This way, there is actually no need for global variables, and no excuse to use global variables.
Using local variables, the syntax again remains the same.
I have a directory with some helper functions that should be put into a package. Step one is obviously naming the directory something like +mypackage\ so I can call functions with mypackage.somefunction. The problem is, some functions depend on one another, and apparently MATLAB requires package functions to call functions in the very same package still by explicitly stating the package name, so I'd have to rewrite all function calls. Even worse, should I decide to rename the package, all function calls would have to be rewritten as well. These functions don't even work correctly anymore when I cd into the directory as soon as its name starts with a +.
Is there an easier solution than rewriting a lot? Or at least something self-referential like import this.* to facilitate future package renaming?
edit I noticed the same goes for classes and static methods, which is why I put the self-referential part into this separate question.
In truth, I don't know that you should really be renaming your packages often. It seems to me that the whole idea behind a package in MATLAB is to organize a set of related functions and classes into a single collection that you could easily use or distribute as a "toolbox" without having to worry about name collisions.
As such, placing functions and classes into packages is like a final step that you perform to make a nice polished collection of tools, so you really shouldn't have much reason to rename your packages. Furthermore, you should only have to go through once prepending the package name to package function calls.
... (pausing to think if what I'm about to suggest is a good idea ;) ) ...
However, if you really want to avoid having to go through your package and prepend your function calls with a new package name, one approach would be to use the function mfilename to get the full file path for the currently running package function, parse the path string to find the parent package directories (which start with "+"), then pass the result to the import function to import the parent packages. You could even place these steps in a separate function packagename (requiring that you also use the function evalin):
function name = packagename
% Get full path of calling function:
callerPath = evalin('caller', 'mfilename(''fullpath'')');
% Parse the path string to get package directories:
name = regexp(callerPath, '\+(\w)+', 'tokens');
% Format the output:
name = strcat([name{:}], [repmat({'.'}, 1, numel(name)-1) {''}]);
name = [name{:}];
end
And you could then place this at the very beginning of your package functions to automatically have them include their parent package namespace:
import([packagename '.*']);
Is this a good idea? Well, I'm not sure what the computational impacts will be if you're doing this every time you call a package function. Also, if you have packages nested within packages you will get output from packagename that looks like this:
'mainpack.subpack.subsubpack'
And the call to import will only include the immediate parent package subsubpack. If you also want to include the other parent packages, you would have to sequentially remove the last package from the above string and import the remainder of the string.
In short, this isn't a very clean solution, but it is possible to make your package a little easier to rename in this way. However, I would still suggest that it's better to view the creation of a package as a final step in the process of creating a core set of tools, in which case renaming should be an unlikely scenario and prepending package function calls with the package name would only have to be done once.
I have been exploring answers to the same question and I have found that combining package with private folders can allow most or all of the code to be used without modification.
Say you have
+mypackage\intfc1.m
+mypackage\intfc2.m
+mypackage\private\foo1.m
+mypackage\private\foo2.m
+mypackage\private\foo3.m
Then from intfc1, foo1, foo2, and foo3 are all reachable without any package qualifiers or import statements, and foo1, foo2, and foo3 can also call each other without any package qualifiers or import statements. If foo1, foo2, or foo3 needs to call intfc1 or intfc2, then that needs qualification as mypackage.intfc1 or an import statement.
In the case that you have a large set of mutually interdependent functions and a small number of entry points, this reduces the burden of adding qualifiers or import statements.
To go even further, you could create new wrapper functions at the package level with the same name as private functions
+mypackage\foo1.m <--- new interface layer wraps private foo1
+mypackage\private\foo1.m <--- original function
where for example +mypackage\foo1.m might be:
function answer = foo1(some_parameter)
answer = foo1(some_parameter); % calls private function, not itself
end
This way, unlike the intfc1 example above, all the private code can run without modification. In particular there is no need for package qualifiers when calling any other function, regardless of whether it is exposed by a wrapper at the package level.
With this configuration, all functions including the package-level wrappers are oblivious of the package name, so renaming the package is nothing more than renaming the folder.
I am starting to learn, MEF and one important thing in it is that I can mark some item (class, propety,method) with Export attribute so that, who ever wants use it will create Import attribute on an instance varaible and use it. How does this mapping happen and when does it happen? Is the import happen lazily on demand or all the composition happen at the start up? Sorry for the ignorant question, I am trying to understand the flow.
It happens in a phase called "Composition". First you create a container and load all your possible sources of parts into it, and then you Compose it. When you do the composition, it resolves all the dependencies and throws an exception if it can't resolve them all properly.
In general, your parts get instantiated during composition (and if you set a break point in the constructor of your part classes, you will see the break point hit during your call to Compose()). However, you can override this in a straightforward way if you use Lazy<T> as the type of your import (assuming you exported your part as type T).
To see how the composition works, take a look at the Compose() method here.