Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I want to make Private functions.

From my point of view, being a Private function means that the function is not accessible from other packages. For that purpose I wrote the following code. But my private function can be called in another package. I don't want that.

(*Package 1*)
BeginPackage["Test1`"];
Begin["`Private`"];
Test1`Private`function1[x_] := x
End[];
EndPackage[];
(*Package 2*)
BeginPackage["Test2`"]
function2[x_] := Test1`Private`function1[x]
EndPackage[]

As you can see from the above code, function1 is a private function in Test1. That same function when called in Test2 is still accessible, but I don't want that.

How can I resolve this.

Can anyone help me?

share|improve this question
2  
Perhaps you would care to explain why you want this behaviour? –  user21 Apr 30 '13 at 13:45
    
@ruebenko for functions protection purpose.I want like that –  subbu Apr 30 '13 at 13:49
    
from what do you want to protect it? It can not be done. –  user21 Apr 30 '13 at 13:55
3  
If you're trying to protect against accidentally calling the Test1 private function from outside that context, then just don't use its context inside Test2. If, however, you're trying to hide the definition of that private function, use other techniques, e.g., Encode. –  murray Apr 30 '13 at 14:49
1  
Unless the package is loaded before the user has a chance to execute code, they can't. The definitions of most of the built-in functions, including Unprotect, SetAttributes, and SetDelayed, can be modified, and there is no guarantee that they work as advertised at the time the package is loaded. Any tricks played by the package to hide the function from the user can also be played on the package to disable the hiding functionality. –  Tobias Hagge Apr 30 '13 at 23:18

2 Answers 2

The following should make it pretty difficult to use function1 elsewhere:

BeginPackage["Test1`"];
f2::usage = "f2 usage message";
Begin["`" <> StringJoin @@ RandomChoice[CharacterRange["a", "z"], 30] <> "`"];
function1[x_] := x;
f2[x_] := 2 function1[x];
SetAttributes[f2, {Protected, ReadProtected, Locked}];
End[];
EndPackage[];

The trick is not to use the Private context, but a randomly named one.

f2, which uses function1, just works:

f2[2]

4

However, no information about function1 is leaked:

?function1

Information::notfound: Symbol function1 not found. >>

?? f2

f2 usage message

Attributes[f2]={Locked,Protected,ReadProtected}

Saving this using Encode and reading it using Get will prevent most casual users from peeking into the function's definition.

share|improve this answer
2  
Khm, what about code completion or just plain old Names["Test1`*`*"] –  Ajasja Apr 30 '13 at 15:33
    
The way I understood the OP's question, "The trick is not to use the Private context" in the other package is the right answer here. +1 –  István Zachar Apr 30 '13 at 15:55
    
@Ajasja Something like: Unprotect[Names]; Names["Test1**"] = "Nothing here"; Protect[Names]; SetAttributes[Names, Locked]; ? BTW Code completion stops for me at Test1` . I don't get anything more than that. –  Sjoerd C. de Vries Apr 30 '13 at 16:17
    
@Ajasja ?"Test1`*`*" leaks information too. I guess I'd have to overload that as well. –  Sjoerd C. de Vries Apr 30 '13 at 17:50
    
If the objective is to make these functions uncallable except at package load time, perhaps it's worth adding a Condition on $Context as well? Or maybe pass an additional argument that has to take a particular (secret) value in order for the function to work? –  Oleksandr R. May 1 '13 at 3:03

You could make your function an inline function.

BeginPackage["Test1`"];
(*this is a function with several invocations, which we'd like to inline*)
function2[x_Integer] := 2 + 1
function2[x_Symbol] := x

ReleaseHold[
  Hold[
    (*Non-private definitions go here*)
    privateCaller[y_] :=
      (Print["This is some functionality."];
       function1[y]+function2[y]
      )
  ] /.
    (*inline definitions go here*)
    {
      function1[y_] :> (Print["function1 is not a defined function."]; y),
      With[{z = DownValues[function2]}, patt:function2[x_] :> Replace[patt, z]]
    }
]
Clear[function2]
EndPackage[]

After EndPackage, the symbols function1 and function2 have no downvalues, so unless the user can read your package definitions (which they can, if they are determined), they have no way to invoke these functions.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.