How to make a function file in Ocatve with multiple functions - octave

I know that you can make a function file in Octave in which the file name is the same as the function which defines one function, but I would like to define multiple functions in one file. Is there any way to do this, or do I need a separate file for each function.

In this answer I will assume that your main objective is a tidy workspace rather than explicitly a one-file requirement.
Let's get the one-file approach out of the way. You can create a script m-file (not a function m-file), and define a number of command-line functions there. The octave manual has a section on this. Here's an example:
% in file loadfunctionDefinitions.m
1; % statement with side-effect, to mark this file as a script. See docs.
function Out = Return1(); Out = 1; end
function Out = Return2(); Out = 2; end
% ... etc
% in your main octave session / main script:
X = Return1() + Return2();
However, this is generally not recommended. Especially if you would require matlab compatible code, since matlab introduced 'script-local functions' much later than octave, and decided to do it in a manner incompatible to the existing octave implementation: matlab expects script-local functions to be defined at the end of the script; octave expects them to be defined before first use. However, if you use normal function files, everything is fine.
While I appreciate the "I don't like a folder full of functions" sentiment, the one-function-per-file approach actually has a lot of benefits (especially if you program from the terminal, which makes a wealth of tools twice as useful). E.g. you can easily use grep to find which functions make use of a particular variable. Or compare changes in individual functions from different commits, etc.
Typically the problem is more one of having such function files littering the directory, when other important files are present, e.g. data etc, and having so many files in one place makes finding what you want hard to spot, and feels untidy. But rather than have a single file with command-line definitions, there are a number of other approaches you can take, which are probably also better from a programmatic point of view, e.g.:
Simply create a 'helper functions' folder, and add it to your path.
Use subfunctions in your main functions whenever this is appropriate, to minimize the number of unnecessary files
Use a private functions folder
Use a 'package directory', i.e. a folder starting with the character '+', which creates a namespace for the functions contained inside. E.g. ~/+MyFunctions/myfun.m would be accessed from ~/ via MyFunctions.myfun(), without having to add +MyFunctions to the path (in fact you're not supposed to).
Create a proper class directory, and make your functions methods of that class
The last option may also achieve a one-file solution, if you use a newer-style classdef based class, which allows you to define methods in the same file as the class definition. Note however that octave-support for classdef-defined classes is still somewhat limited.

Related

Bindgen: How to include all functions in some files but only certain functions in other files?

I have two folders that I want to create bindings for:
Include: - I need everything in this folder
Src: - I only need 3 functions (of many) from one file (of many)
All of the required files are included in wrapper.h.
I can create bindings for the correct functions in src by using:
bindings.allowlist_function("myfunc")
However this then means that bindgen only creates bindings for those functions explicitly mentioned. Not the other files in the wrapper.
Is there a way to create the bindings as I wish?
Note: This code is auto-generated so I can't simply move the function.
Furthermore, there are a lot of custom types that are required by these functions and the allowlist_function method brings all of those over automatically. So I need a way to mix allowlist and the files the wrapper.h. I can't manually transfer the functions over as these files change semi-frequently and I am trying to prevent issues in FFI mismatch that manual copying introduces.
**With further research: **
I have found that in Bindgens source code it shows an allowlist_file which suggests it would allow me to allowlist my wrapper and the specific functions.
if let Some(hidden_files) = matches.values_of("allowlist-file") {
for file in hidden_files {
builder = builder.allowlist_file(file);
}
This is included on the documentation at:
https://rust-lang.github.io/rust-bindgen/allowlisting.html
However, when you follow the links it is not in the builder docs and can't be found when running the code. I am confused as to whether this method really exists?

Can I use global variable instead of passing parameters?

I have a Javascript project which one of its script receive a parameter. Instead of passing this parameters throughout function chains can I declare it one as global and have other functions referring to it instead?
What if there are many scripts in the project? Can these access this global variable somehow? I need to have it persistent to the duration of the execution only.
Note that this project can be called by various users and at once. As it is sometimes invoked through a webapp I am not sure User cache would be appropriate.
Thanks!
Don't use Global variables for Apps Script Services. For example:
var SS_SERVICE = SpreadsheetApp;
Recently this started causing an error message. If this changes, please edit the answer at that time.
Also, if you do not use the var keyword to define a variable, then it automatically gets put into the global scope. So, if by mistake, you fail to put var in front of your variable, then the code still runs and may work, but you may be unaware of what is really happening with your code. If you defined and used another variable with the same name in a different function, and also mistakenly made that variable a global, and one function called the other function, then there could be a conflict with the variable values.
All Apps Script .gs files can access all other .gs script files. There doesn't need to be any link between script files, or inclusion into other script files. You can call a function from another script file, as long as it's in the same project.
And global variables defined in one file are accessible to other files.
You don't want to use public Cache for information specific to that user. But there is private Cache. And Cache expires, so unless it's for something like timing how long a user is logged in, you might not want to use it.
If you have lots of code, and create functions for reasons of orderly structure and access to multiple other functions, then passing data might be undesirable. So, yes, you can use global variables. It's considered "Bad Practice" by some to use global variables, but then we are getting into personal opinion.

Best practice for writing equivalent powershell scripts and functions

I have a script that takes in multiple parameters, and that I've documented with proper help comments (e.g. .SYNOPSIS, .DESCRIPTION, .PARAMETER). Several different users in my organization are going to use this powershell script, some who know powershell and will call it from powershell with specific parameter values, and some who don't know powershell and will simply right-click on the script file in Windows Explorer and choose Run with PowerShell (so the parameters will use their default values).
My conundrum is what is the best way to do this in powershell without a bunch of duplicate code. The way I see it, these are my options:
1 - Just write a DoStuff.ps1 script that provides default values for all parameters. This allows it to be ran directly from Windows Explorer, but feels clunky for the powershell users that want to use it as a function from their own scripts, since instead of writing:
Do-Stuff param1 param1
they will be doing:
.\DoStuff.ps1 param1 param2
2 - Within DoStuff.ps1, move the operations it performs into a DoStuff function, and after the function declaration call the DoStuff function with the parameters passed into the script. This would still allow the script to be ran from Windows Explorer, as well as developers to dot source the script into their own scripts so they can access the function. The downside is that when the developers dot source the script, the script is going to call the function with the default parameters (unless I allow them to provide an optional Switch parameter to the script that triggers the function to not be called). Even with this though, it means that I would have to duplicate all of the scripts help text so that it shows for both the script and the function (description, parameter descriptions, etc.).
I can't think of any other options. Ideally I would just be able to write functions in .ps1 file and tag a function with a "default" keyword so that if the script is called, that function is ran by default; but I don't think PowerShell provides anything like this.
What do you think is the best approach in this situation. Is there something I'm overlooking or don't know about? Thanks.
but feels clunky for the powershell users that want to use it as a function from their own scripts
Default parameters would seem, based on your description, to be the best (or, at least, least-worse) approach.
But rather than naming your script DoStuff.ps1 name it and call it so it can be called more like an internal function:
Name it with the dash: Do-Stuff.ps1
Remember you don't need to specify the ps1
If the script is in a folder in $env:Path then you don't need to specify a path.
Also consider a script can load a module from a relative path: you could put most of the code in a script module which the front end (right click on it) script loads and calls into it. Script authors load the module themselves.

How to tell the PhpStorm IDE that a constant exists?

The IDE (PS-117.65) is complaining that some of constants aren't defined.
I've defined them in a loop in another file. Can I put a doc comment at the top of this file to inform it about the constants? The usual /** #var and #global syntax doesn't seem to work for constants.
There is no known to me PHPDoc comment to do that.
But you can "fake" them -- create some const.php file and place it anywhere in a project (you can even place it in separate folder outside the project and attach it as External Library or as separate Content Root).
In this file -- define those constants with in a normal way: define("CONST_NAME", "value"); The "value" part can be anything (as long as types are matching -- useful for inspections/code analysis) -- it really depends where those constant will be used (e.g. if they are used in include/require statements, then it may be beneficial to have some real (or close to it) values there).

Why can't Matlab see my function?

My function is definitely working; it's tested and was at one point being recognized.
Here's the function prototype:
function [X Y] = calculateEllipse(x, y, a, b, angle)
%# Code here
end
Here's the call I'm making from the Matlab terminal:
calculateEllipse (612, 391, 107, 60, 331)
Here's the error popping out at me:
??? Undefined function or method 'calculateEllipse' for input arguments of
type 'double'.
Now, I am 100% positive I am in the same directory as the function. I even used
addpath('C:\path-to-function')
to make sure. It's just not working, and I'm baffled.
Any help is appreciated.
To summarise other posts, here is a workflow for determining the cause of the problem.
You mistyped the name of the function. Check the function definition and make sure it really it called calculateEllipse.
You saved the function to a file named something other than the function name. Check the filename of the function and make sure it matches the function name.
The folder containing the function name isn't on the MATLAB path. There are several ways to check this. Type path to see the current path, or which calculateEllipse to find the location that MATLAB is using for that file. (If there is a problem, that last command will display 'calculateEllipse' not found.. Note that addpath does not permanently update the path, so when you close down MATLAB, the path will be reset. Use savepath for this.
The folder containing the function is a subdirectory of matlabroot. These folders are reserved for fully fledged toolboxes; bad things happen when you store your code here. See Bob's answer for more information.
Other useful things to check are:
Can you call other functions that are stored in the same folder?
If you save the function in a different folder, will it run then?
Adding to what Jeff said; another possibility is that you placed the function somewhere inside of your MATLAB installation. By default MATLAB does't re-search its own file structure for new files; it assumes that its internal file structure remains unchanging. Make sure that you're saving the file (which, as Jeff pointed out, must be named calculateEllipse.m) somewhere outside of your MATLAB installation.
See https://www.mathworks.com/help/matlab/matlab_env/toolbox-path-caching-in-the-matlab-program.html, or go to the MathWorks web site and search for
path cache
for more information.
The key to this problem is this: %Has no license available. This implies that a function in the directory of the function you are trying to use has the same name as a function in a toolbox you do not own. MATLAB by default disables the whole directory and not just the function of the same name in a toolbox you do not own. Here is an example:
files in directory:
myfunction.m
scoobydoo.m
blackman.m
If I do not own the "Signal processing toolbox," then blackman.m will disable the whole directory.
I can think of a couple of reasons this could happen.
First, as Jeff said, you could have named the file 'calcEllipse.m' instead of 'calculateEllipse.m'. In which case you need to rename the function to be the same as the m file you saved.
Second, you have not added the correct path. There is no reason for this to give an error to my knowledge otherwise. Double check that you have added the path to the m file that is being saved. An easy way to check is if you type in 'calculateEll' and then press tab, does the autocomplete work? If not you are out of the path.
Hope it is one of those thing you can quickly fix!