6

Woud there be an elegant way to use a held option ?

For example if I need to pass by reference several variables but I don't always need all of them, it can be useful. For example if I want to append an element to a List/Association/Dataset.

I've managed to make something work but it's not very usable.

l = {};
ClearAll@ffff;
Options[ffff] = {"a" -> Hold[l]};
ffff[x_, OptionsPattern[]] := Function[Null, AppendTo[#, x], HoldFirst] @@ OptionValue["a"];
ffff[2]
l
Kuba
  • 136,707
  • 13
  • 279
  • 740
faysou
  • 10,999
  • 3
  • 50
  • 125

2 Answers2

12

I'd do something like this:

l = {};
ClearAll@ffff;
Options[ffff] = {"a" :> l};
ffff[x_, OptionsPattern[]] := 
  OptionValue[Automatic, Automatic, "a", Function[v, AppendTo[v, x], HoldFirst]]

That is, use RuleDelayed instead of Rule to define your held option, and then use extended syntax of OptionValue.

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
3

As an improvement to Leonid's answer I've added a helper function, to avoid the Function syntax everytime.

l={};
ClearAll@ffff;
Options[ffff]={"a":>l};
heldOptionAppendTo[x_]:=Function[{v},AppendTo[v,x],HoldFirst];
ffff[x_,OptionsPattern[]]:=OptionValue[Automatic,Automatic,"a",heldOptionAppendTo[x]]  

Some other similar useful functions. The great thing about Leonid's method and the OptionValue fourth argument is that we truly have access to the optional variable without an evaluation leak.

heldOptionSetKey[key_,value_]:=Function[{v},v[key]=value,HoldFirst];
heldOptionSetPart[part__,value_]:=Function[{v},v[[part]]=value,HoldFirst];
heldOptionIncrement[]:=Function[{v},v++,HoldFirst];
faysou
  • 10,999
  • 3
  • 50
  • 125