9
$\begingroup$
?? GeneralUtilities`UnpackOptions

    HoldPattern[GeneralUtilities`Control`PackagePrivate`s:(_=_GeneralUtilities`UnpackOptions)]^:=
GeneralUtilities`MacroEvaluate[GeneralUtilities`Control`PackagePrivate`s]

    HoldPattern[GeneralUtilities`Control`PackagePrivate`sd:(_:=_GeneralUtilities`UnpackOptions)]^:=
GeneralUtilities`MacroEvaluate[GeneralUtilities`Control`PackagePrivate`sd]

    HoldPattern[GeneralUtilities`Control`PackagePrivate`tsd:(_/:_:=_GeneralUtilities`UnpackOptions)]^:=
GeneralUtilities`MacroEvaluate[GeneralUtilities`Control`PackagePrivate`tsd]

If we use GeneralUtilities`PrintDefinitions we'll get:

As the information,the GeneralUtilities`UnpackOptions seem to can extracts the definition of a certain option?But how to use it?

$\endgroup$
4
  • $\begingroup$ Related, possibly: mathematica.stackexchange.com/questions/114184/… $\endgroup$
    – Michael E2
    Commented Jan 22, 2017 at 3:00
  • $\begingroup$ @yode I don't have UnpackOptions in version 10.1.0. Would you please include the function definition in your question? I have an idea of what this may be for but I need to see more. $\endgroup$
    – Mr.Wizard
    Commented Jan 22, 2017 at 3:28
  • $\begingroup$ @MichaelE2 Good link.Thanks. :) $\endgroup$
    – yode
    Commented Jan 22, 2017 at 4:03
  • $\begingroup$ @Mr.Wizard done. :) $\endgroup$
    – yode
    Commented Jan 22, 2017 at 4:10

1 Answer 1

11
$\begingroup$

(analysis current as of Mathematica V11.0.1)

UnpackOptions is a macro that provides a convenient notation for accessing option values within a function definition.

At definition time, it transforms a source macro expression of the form:

UnpackOptions[option1, option2]

into an expanded expression of the form:

{option1, option2} = OptionValue @ {"Option1", "Option2"}

Note how the actual option names are generated automatically from the variable names which will receive the option values. The first character of the option name will be capitalized unless the variable name starts with a "$" (which will be dropped from the option name).

Examples

Examples of UnpackOptions can be found in numerous source files distributed with Mathematica. Here is one:

{ $InstallationDirectory, "SystemFiles", "Components"
, "MXNetLink", "Kernel", "DataIterators.m"
} // FileNameJoin // NotebookOpen

For instance, the definition of MXDataRandomizer starts like this:

MXDataRandomizer[assoc_Association, OptionsPattern[]] := CatchFailure @ Scope[
    UnpackOptions[context, dataType];
    If[!AllSameBy[Values@assoc, Length], Panic["DifferentLengths"]];
    ...

If we load this package and inspect the in-memory definition of MXDataRandomizer, we will find the expanded macro:

Needs["GeneralUtilities`"]
Needs["MXNetLink`"]

PrintDefinitionsLocal[MXDataRandomizer]

(*
    MXDataRandomizer[assoc_Association, OptionsPattern[]] := Catch[
        Block[{context, dataType, randIndices, randomizedAssoc},
            {context, dataType} = OptionValue @ {"Context", "DataType"};
            If[!AllSameBy[Values @ assoc, Length],
            ...
*)

Also note how the macro CatchFailure expanded into a Catch expression, and how the implicit scoping macro Scope expanded into an explicit Block construct.
[as an aside, the use of Block here instead of Module is very dodgy]

Viewing Macro Definitions

The definition of UnpackOptions itself, along with many other macros, can be inspected by evaluating:

Needs["GeneralUtilities`"]

PrintDefinitions[MacroRules]

Ensuring Macros Get Triggered

Beware that macros are only expanded when they appear as the top-level head on the right-hand side of a definition. This limitation is due to the fact that macros are implemented as up-values on Set, SetDelayed and TagSetDelayed.

Since UnpackOptions is not useful as a top-level expression, it needs to be contained within another macro to be used effectively. In the case of MXDataRandomizer it was contained within the body of the top-level macro CatchFailure.

Should we not want to use other macros like CatchFailure or Scope, there is a convenient macro called UseMacros that will do nothing but trigger macro expansion:

Options[f] = {A -> 10, B -> 20};
f[x_, OptionsPattern[]] :=
  UseMacros @ Module[{a, b}, UnpackOptions[a, b]; {x, a, b}]

f[1]
(* {1, 10, 20} *)
$\endgroup$
1
  • $\begingroup$ I don't have the function, or MacroEvaluate, in 10.1.0 but this is exactly what I thought it might do. I have seen that expansion many times internally and I even wrote my own version of this once. Thanks for satisfying my curiosity. :-) $\endgroup$
    – Mr.Wizard
    Commented Jan 22, 2017 at 6:37

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.