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.

How can the actual definition of a function be hidden from a user?

I want the user of a notebook to be able to evaluate a real-valued function f of a real variable at any particular numeric input yet not be able to see the symbolic expression that defines it. E.g.:

f[x_]:=Exp[-x] Cos[2x]

Of course I know I want to hide the definition of f in a package, say func.m consisting of something like the following:

BeginPackage["func`"]
f::usage = "f[x] gives the value of the secret function f at x";

Begin["`Private`"]
f[x_]:=Exp[-x] Cos[2x]
SetAttributes[f,{ReadProtected,Locked}]
End[]

EndPackage[]

This package file would be Encoded and put into the same directory as a notebook, say work.nb where the user will work with the hidden definition. And this notebook would include, in an Initialization cell:

SetDirectory[NotebookDirectory[]]
Get["func`"]

But after that cell is evaluated, still evaluating

f[x]

unfortunately reveals the symbolic definition of f.

Is it possible somehow to hide the symbolic definition yet be able to evaluate f at arbitrary numeric input?

share|improve this question
    
Hmm... does it really show up even in a fresh mma session? Are you sure that you're loading the encoded file and not the plain text .m file (I think just Get["func`"] will load the m file)? I haven't tried it yet since I don't have a free kernel right now, but it seems like what you're suggesting should work... –  rm -rf Sep 14 '13 at 17:25
1  
Ohh... never mind. I see what your problem is. Just define f as f[x_?NumericQ] and that should fix it. –  rm -rf Sep 14 '13 at 17:27
    
@rm -rf: Yes, I just realized that's the way. For the record, please make that an answer. Or at least its part of the way. Clearly I need to take an additional step lest the more clever use try something like f[Pi] and begin to get a hint of the definition. Namely, use f[x_?NumericQ] := N[Exp[-x] Cos[2x]. –  murray Sep 14 '13 at 17:43
    
Ah, in that case you can just use _?NumberQ. I will make that an answer. –  rm -rf Sep 14 '13 at 18:01

1 Answer 1

up vote 6 down vote accepted

What you're suggesting seems fine to me. The only additional step necessary is to restrict the definition of f to only numeric values (i.e., keep it unevaluated for symbolic input). The way to do that would be to use the pattern test NumericQ on the input as:

Clear@f
f[x_?NumericQ] := Exp[-x] Cos[2 x] 

which will not evaluate for input such as f[x]. However, as you note, it will evaluate for symbolic forms of numerical values, such as Pi, E, GoldenRatio, etc., which can give the user a hint to the underlying form:

f /@ {E, Pi, GoldenRatio}
(* {E^-E Cos[2 E], E^-Pi, E^-GoldenRatio Cos[2 GoldenRatio]} *)

There are two solutions here:

  • If you want to provide a numerical output, you could just apply N on the RHS in the definition

    Clear@f
    f[x_?NumericQ] := N[Exp[-x] Cos[2 x]]
    
    f /@ {E, Pi, GoldenRatio}
    (* {0.0437182, 0.0432139, -0.197404} *)
    
  • If you want to keep it unevaluated, you could use NumberQ to restrict the pattern:

    Clear@f
    f[x_?NumberQ] := Exp[-x] Cos[2 x]
    
    f /@ {E, Pi, GoldenRatio}
    (* {f[E], f[Pi], f[GoldenRatio]} *)
    

If your user is smart enough, they can still work around this by tricking f to believe that a symbol x is also a numeric value (example using the NumericQ definition of f):

NumericQ[x] = True;
f[x]
(* 2.71828^(-1. x) Cos[2. x] *)

You can do the same with NumberQ after unprotecting it. To avoid this, you can include a dummy definition for _Symbol:

f[x_Symbol] := Null
share|improve this answer
    
-f: Yes, I already noted I'll want to wrap with N so as to hinder "decoding" the function by plugging in symbolic numerical entities such as Pi. –  murray Sep 14 '13 at 21:17
    
@murray Please also see my update. –  rm -rf Sep 14 '13 at 22:27
    
Unfortunately, I don't think the ploy f[x_Symbol] := Null works to avoid the NumericQ[x] = True attack. When I do that and then evaluate f[x] I obtain result 2.71828^(1. x) Cos[2. x]. –  murray Sep 16 '13 at 18:48
    
@murray Ah, I wasn't explicit — the definition for _Symbol should come before that for _?NumericQ. It won't work if you place it after. –  rm -rf Sep 16 '13 at 18:58
    
I wondered about the order. I knew that "general" rules are applied only after "particular case" rules, but I hadn't recalled seeing an explicit statement that otherwise it's the order that counts.I find it now, in the final paragraph of the exposition in tutorial/TheOrderingOf Definitions: "Whenever the appropriate ordering is not clear, Mathematica stores rules in the order you give them." –  murray Sep 17 '13 at 0:23

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.