In Matlab private functions are those stored in subdirectories with the name private. They have a restriction of visibility that: "you cannot call the private function from the command line or from functions outside the parent of the private folder" (https://se.mathworks.com/help/matlab/matlab_prog/private-functions.html).
EDIT: Octave tries to follow this: "if the path to func1 is directory/func1.m, and if func2 is found in the directory directory/private/func2.m, then func2 is only available for use of the functions, like func1, that are found in directory." (https://octave.org/doc/v6.2.0/Private-Functions.html)
I'm using Octave 6.2.
I have a couple of functions that I want to make private, say A and B. They have some common part, so it is natural to separate out this part and create another function, say C, to be called from interiors of A and B.
I placed C in the same private directory as A and B, and it seems that this construction is not allowed by the language, as I get an error saying that C is undefined. I find it counterintuitive, nonetheless, this could be expected according to the above quote from documentation of Octave, saying that private functions are visible only from the parent directory.
I tried placing a nested private subdirectory within the first one (with the relative path "private/private") as a workaround, but it doesn't solve the problem, and I still get an error with undefined C.
Thus, the only way to call C from private A and B seems to be to make it publicly visible, even though from the code architecture point of view C should not be public, since it is called only by private functions. Another way would be to keep copies of the same code of C within both A and B - with all bad consequences of the violation of the DRY principle.
EDIT: As indicated in the comments this problem seems to be Octave specific. In Matlab you can access private functions from other private functions.
My question is: What is the proper way of maintaining common parts of private functions in Octave?
EDIT2: The problem indeed seems to be a bug in the current version of Octave. The MWE provided by carandraug works fine unless...
I found that the following sequence is a mininal-not working-example making the bug explicit: 1) A.m and C.m are in the directory, A.m calls B.m. B.m is in directory/private, initially NOT calling C.m. Evaluation of A works fine. 2) Modify B.m to call C. Evaluation of A still works fine. 3) Move C.m to private. Evaluation of A returns error with C undefined.
On the other hand the following sequence (the one occurring in most situations) doesn't reveal the error: 1') A.m and C.m in directory, A.m calls B.m. B.m is in private, this time calling C.m Evaluation of A works fine. 3') Move C.m to private. Evaluation of A still works fine.
So, step 2) for some reason is crutial for the bug to occur.
EDIT3: For fresh Octave from GUI this is how it works for me (on Windows 10 Pro 20H2, maybe this matters):
>> cd C:\Octave\test\
>> ls
Volume in drive C is Windows
Volume Serial Number is XXXX-XXXX
Directory of C:\Octave\test
[.] [..] A.m C.m [private]
2 File(s) 101 bytes
3 Dir(s) 129 967 509 504 bytes free
>> A
this is A
this is B
>> % now edit B to call C
>> A
this is A
this is B
this is C
>> movefile("C.m", "private/C.m")
ans = 1
>> A
this is A
this is B
error: 'C' undefined near line 3, column 3
error: called from
B at line 3 column 3
A at line 3 column 3
What you suggest should work in Octave so I believe your error is elsewhere. Can you provide a minimal example of how it is not working? Here's mine working in Octave:
$ cat dd/A.m
function A ()
disp('this is A')
B()
endfunction
$ cat dd/private/B.m
function B ()
disp('this is B')
C()
endfunction
$ cat dd/private/C.m
function C ()
disp('this is C')
endfunction
$ octave --path 'dd' --eval 'A()'
this is A
this is B
this is C