How to pass options WAS: ... Seemingly simple gridbox question
- To: mathgroup at smc.vnet.net
- Subject: [mg37707] How to pass options WAS: [mg37668]... Seemingly simple gridbox question
- From: "Wolf, Hartmut" <Hartmut.Wolf at t-systems.com>
- Date: Sat, 9 Nov 2002 00:29:19 -0500 (EST)
- Sender: owner-wri-mathgroup at wolfram.com
>-----Original Message----- >From: DrBob [mailto:majort at cox-internet.com] To: mathgroup at smc.vnet.net >Sent: Friday, November 08, 2002 8:14 AM >To: mathgroup at smc.vnet.net >Subject: [mg37707] [mg37668] RE: [mg37656] RE: [mg37562] RE: [mg37536] Re: >Seemingly simple gridbox question > > >I think you're saying Sequence[] is always an acceptable replacement for >an argument that otherwise would be missing, while Null would not always >be acceptable. > >If so, that's very useful information. > >Bobby > ---snipped-- Bobby, that's not quite what I wanted to express: this was not related to arguments in general, but to the treatment of options. Almost ever, options are passed by a BlankNullSequence pattern variable. (And almost ever there exists a default for them.) Let's first just look at the passing of parameters in general: In[249]:= Remove[g] In[250]:= g[a_, b_:0, c___] := Print["arg 1 = ", ToString[a], "; arg 2 = ", ToString[b], "; arglist 3 = ", ToString[{c}]] In[251]:= g[1] >From In[251]:= "arg 1 = 1; arg 2 = 0; arglist 3 = {}" In[252]:= g[1, 2] >From In[252]:= "arg 1 = 1; arg 2 = 2; arglist 3 = {}" In[253]:= g[1, 2, 3] >From In[253]:= "arg 1 = 1; arg 2 = 2; arglist 3 = {3}" In[254]:= g[1, 2, 3, 4] >From In[254]:= "arg 1 = 1; arg 2 = 2; arglist 3 = {3, 4}" In[255]:= g[, , ,] >From In[255]:= "arg 1 = Null; arg 2 = Null; arglist 3 = {Null, Null}" In[256]:= g[1, Sequence[], 3, 4] >From In[256]:= "arg 1 = 1; arg 2 = 3; arglist 3 = {4}" In[257]:= g[1, 2, Sequence[]] >From In[257]:= "arg 1 = 1; arg 2 = 2; arglist 3 = {}" In[258]:= g[1, 2, Sequence[], 4] >From In[258]:= "arg 1 = 1; arg 2 = 2; arglist 3 = {4}" What I told, applies for cases In[257] and In[258] but not for In[256] which would shift a parameter (3) into a wrong slot (2). Of course you would never type such things, but when we calculate options conditionally (as I did), we have to deal with the case that "no option" results. For that Sequence[] is an appropriate value, Null normally not. Case In[255] (or any Null at the place of an option) is not acceptable because it will early or late run into this problem: In[284]:= expr /. {a -> 1, Null} >From In[284]:= ReplaceAll::"reps": "{{a -> 1, Null} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing." Out[284]= expr /.{a -> 1, Null} If you program defensively, you always should protect your options parameter by the function OptionQ: In[278]:= Remove [f] In[279]:= f[opts___?OptionQ] := Print[{opts}] In[280]:= f[a -> 1, b :> 2] >From In[280]:= {a -> 1, b :> 2} In[281]:= f[] >From In[281]:= {} In[282]:= f[{}] >From In[282]:= {{}} In[283]:= f[, a -> 1] Out[283]= f[Null, a -> 1] Furthermore you should adapt your coding to OptionQ, as also this... In[285]:= f[a -> 1, {{b :> 2, {{{c -> 3}, {}}}}, d -> 4}] >From In[285]:= {a -> 1, {{b :> 2, {{{c -> 3}, {}}}}, d -> 4}} ...passed. This is done exactly because options may accumulate through nested calls, and also {} can now be understood as "no option specified" at any place. This may be done e.g. as in Graphics`Graphics`: ScaledPlot[funcs_List,{x_Symbol,xmin_,xmax_},opts___?OptionQ] := Module[{scale, ..., ao, ...}, {scale, ao} = {ScaleFunction, AxesOrigin} /. Flatten[{opts, Options[ScaledPlot]}]; ... ] i.e. Flatten[{opts}] and combine with default Options[...] appropriately. But, alas, not all functions treat their option parameters in such a clean way; so the wary programmer moves sequence-objects to option slots, Sequence[] is the choice for "no option specified". -- Hartmut Wolf