2
$\begingroup$

I have written an elaborate code that contains a collection of functions for the user and a bunch of auxiliary functions whose existence I would like to hide away from the user. I've written my code in a separate .nb file which I run. I intend the user to do work on a separate clean notebook.

But in v9, when I (the user) starts typing something that resembles one of these auxiliary functions, it appears in Mathematica's autocompletion bar. Is there a way for me to 'hide' these functions, while keeping the ones that are intended for the user?

For example, I have defined:

fooAuxiliary[n_] := (-1)^n*HarmonicNumber[n+1];

foo[x_] := fooAuxiliary[Floor[x]]*Sin[x]

with the user given access to call foo but not fooAuxiliary.

$\endgroup$
7
  • 1
    $\begingroup$ Does it show up in the suggestion bar or in the autocompletion? I think you mean the latter... If you write a package and put the auxiliary functions in a private context, then the autocompletion only shows the functions that you've exposed publicly (although, they can autocomplete the others if they add the private context too) $\endgroup$
    – rm -rf
    Jan 25, 2013 at 2:26
  • $\begingroup$ Oh sorry, yes; I meant the autocompletion. I will make edit. But I also don't know how to write a package... $\endgroup$
    – QuantumDot
    Jan 25, 2013 at 2:28
  • 2
    $\begingroup$ @NickStranniy, why did you delete the answer? $\endgroup$
    – Rojo
    Jan 25, 2013 at 2:57
  • $\begingroup$ @Rojo Possibly because the OP's tone seemed like they were mocking the answer... $\endgroup$
    – rm -rf
    Jan 25, 2013 at 16:47
  • $\begingroup$ @QuantumDot I think you should just write a package and leave fooAuxiliaryfunction in the ``Private``` context of the package. $\endgroup$
    – Ajasja
    Jan 25, 2013 at 17:12

2 Answers 2

4
$\begingroup$

In addition to the suggestion of using a separate context (which I think is a good one), in the answer by Nick Stranniy, you can use some of the OO extensions which allow one to call methods on some objects (instances). In this way, method names themselves will not have any definitions, so effectively the implementation gets hidden. If the user is determined, s/he can still reverse-engineer this, but it is harder and one has to understand the inner workings of such OO extension.

For example, the one I described here will do. Here is a simple example. Assuming that you installed it (installation instructions on the GitHub page for it linked to from the mentioned answer), first we load it:

Needs["OO`"];
$ContextPath = DeleteCases[$ContextPath, "OO`Methods`"];

The second line is needed to avoid shadowing, but is not strictly necessary if the code is in some package / context. Now, here is a simple class (type) definition:

DeclareType[BasicTrigFunctions][
  OO`Methods`Sin[x_] := Sin[x],
  OO`Methods`Cos[x_] := Cos[x],
  OO`Methods`Tan[x_] := Tan[x],
  OO`Methods`Cot[x_] := Cot[x]
]

Note that the symbols OO`Methods`Sin etc don't acquire any definitions themselves. Yet, you can create an object of this type and use methods (which are essentially static methods here), e.g. like

obj = BasicTrigFunctions[{}];
obj@OO`Methods`Sin[x]

(* Sin[x] *)

Now you can, for example, create your own functions as follows:

ClearAll[mySin, myCos, myTan, myCot];
With[{obj =  BasicTrigFunctions[{}]},
   mySin[x_] := obj@OO`Methods`Sin[x];
   myCos[x_] := obj@OO`Methods`Cos[x];
   myTan[x_] := obj@OO`Methods`Tan[x];
   myCot[x_] := obj@OO`Methods`Cot[x];
]

You can check that these functions will work just as well as the original trig.functions we started from, but if the user inspects their definitions, s/he will be stopped at the obj level. Hacking deeper is possible but quite non-trivial, so for non-expert users this kind of obfuscation can be good enough.

Note also, that while right now it is not yet possible, I plan to add the object serializing functionality, so that one would be able to save the created object and then load it back into another Mathematica session without actually loading the OO` package. When this is in place, it will make the obfuscation even better, since there won't be a source code available to help with reverse-engineering.

So, as I said: while it won't be particularly hard to reverse-engineer this setup, it should at least help with hiding the definitions from the auto-completion.

$\endgroup$
5
$\begingroup$

You can hide it in another context:

xxxContext`fooAuxiliary[n_] := (-1)^n*HarmonicNumber[n + 1];
foo[x_] := xxxContext`fooAuxiliary[Floor[x]]*Sin[x]
$\endgroup$
4
  • $\begingroup$ Do you mean I am supposed to hope the user doesn't start writing xxx...? $\endgroup$
    – QuantumDot
    Jan 25, 2013 at 2:30
  • $\begingroup$ Yes. In v9 autocompletion shows even Mathematica's own auxiliary functions if user starts typing something like Internal`A. $\endgroup$ Jan 25, 2013 at 2:38
  • 2
    $\begingroup$ @NickStranniy 3 users (myself included) have voted to undelete your answer, because even though the OP doesn't seem to appreciate it, the answer is valid and a good one and will be helpful to others. This is, in effect, what happens when you use a package and put the definitions in a private context — something I already suggested and was also dismissed by the OP $\endgroup$
    – rm -rf
    Jan 25, 2013 at 17:40
  • $\begingroup$ As I said in my comment to you under the original question, I really didn't mean to put on a negative tone. I was trying to get at the motivation of how your answer works. So sorry! $\endgroup$
    – QuantumDot
    Jan 25, 2013 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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