Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Leaving values for options unevaluated in Mathematica

I'm having some problems with writing a function that takes options. One of the option values is a function. I one to get at this value but keep it unevaluated. I tried every single thing I could possibly think of but nothing worked so far.

Basically, to illustrate this is what I tried:

SetAttributes[Foo, HoldRest];
Options[Foo] = {Blah -> None}

Foo[x_, OptionsPattern[]] :=
    Module[{blah},

        blah = OptionValue[Automatic, Automatic, Blah, Hold];
        .
        .
        .

Then when I have:

func[a_, b_, c_] := a + b + c;

I'd like to be able to call Foo with:

Foo[2, Blah -> func[1, 2, 3]]

And have the "blah" variable (inside Foo) to be unevaluated, i.e. blah = func[1, 2, 3].

Thanks for all the help in advance!

Edit:

For reasons that are too long to elaborate, I cannot use RuleDelayed (:>). I'm trying to write a function that will be in a package, used by other people that don't really know Mathematica, so they would have no clue what :> is. Using rules (->) for specifying options and their values is the standard way and they familiar with that.

So to further illustrate, let's say that I'm trying to write a number generator function that takes a function that generates the actual number as one of it's options:

Options[GenerateNumbers] = {GeneratorFunction -> None};

GenerateNumbers[n_, OptionsPattern[]] :=
    Module[{func},

        func = OptionValue[GeneratorFunction];
        Table[func, {n}]
    ]     
]

Now, if I called this function with values as follows:

GenerateNumbers[5, GeneratorFunction -> RandomReal[10]]

It would return a list of 5 numbers that are the same, since RandomReal[10] gets evaluated once and not at every iteration of Table. I want to prevent this. The problem is more complicated but it's along these lines.

Thanks!

like image 492
Gabor Avatar asked Dec 16 '22 17:12

Gabor


2 Answers

Use a name for the OptionsPattern and then wrap the captured sequence object with a List and an Unevaluated. A very minimal way of capturing the right-hand side for Blah is:

SetAttributes[Foo, HoldRest]; Options[Foo] = {Blah -> None};
Foo[x_, opts : OptionsPattern[]] :=
 Module[{blah},
  blah = OptionValue[Foo, Unevaluated[{opts}], Blah, Hold];
  blah]

Testing it out:

In[2]:= Foo[x, Blah -> (1 + 1)]
Out[2]= Hold[1 + 1]
like image 175
Pillsy Avatar answered Dec 24 '22 12:12

Pillsy


Why don't you use RuleDelayed?

Foo[2, Blah :> func[1, 2, 3]]

In this case blah=Hold[func[1, 2, 3]] as expected.

like image 36
Alexey Popkov Avatar answered Dec 24 '22 11:12

Alexey Popkov