6
$\begingroup$

With respect to code readability I like the possibility to use keyword (named) arguments.

I would like to have this under Mathematica, but AFAIK there is no native support for that.

By example, to define an inverse gamma distribution, I come with this approach:

createInverseGamma[Mean->m_,Variance->v_]:=
  With[{a=(m^2+2v)/v,b=m (m^2+v)/v},InverseGammaDistribution[a,b]];

createInverseGamma[Mean->m_,StandardDeviation->std_]:=
  createInverseGamma[Mean->m,Variance->std^2];

dist=createInverseGamma[Mean->1,StandardDeviation->2]

Mean[dist]             (* 1 *)
Variance[dist]         (* 4 *)

My question: do you see some drawbacks to this approach or do you have a better solution?

nb:

  • clearly some symbols have to be reserved and protected (here I use Mean, Variance etc... that are already defined).
  • this approach can interfere with Option, maybe it would be better to define something like foo[Mean=5] with "=" instead of ->

update:

here is an example with "=" instead of ->

SetAttributes[createInverseGamma,HoldAll];

createInverseGamma[Mean=m_,Variance=v_]:=
  With[{a=(m^2+2v)/v,b=m (m^2+v)/v},InverseGammaDistribution[a,b]];

createInverseGamma[Mean=m_,StandardDeviation=std_]:=
  createInverseGamma[Mean=m,Variance=std^2];

dist=createInverseGamma[Mean=1,StandardDeviation=2]

Mean[dist]             (* 1 *)
Variance[dist]         (* 4 *)

However I am even less sure that it has no deleterious side effect...?

$\endgroup$
8
  • $\begingroup$ "[...] it is usually possible to provide the values in any arbitrary order, [...]" - that's not the case here, right? You could use KeyValuePattern[{Mean -> m_, ...}] instead but I find KeyValuePattern quite code-obscuring. The call would have to have a single argument as well. $\endgroup$
    – Kuba
    Dec 10, 2020 at 11:28
  • $\begingroup$ @Kuba thank you for the comment, I will try. With "named" arguments I can accomodate any solution (with or without order restriction), I just want the approach to have no deleterious side effect and improve code readability (at least on the caller side). $\endgroup$ Dec 10, 2020 at 11:38
  • $\begingroup$ Could use strings for the names in the rule-based version, e.g. createInverseGamma["Mean"->m_,"Variance"->v_]:=... Not sure if this will achieve what you want though. $\endgroup$ Dec 10, 2020 at 13:51
  • $\begingroup$ @DanielLichtblau A priori I do not want to use strings as you cannot use pattern matching anymore. By example it is impossible to distinguish foo["Variance"->_] versus foo["Mean"->_] by example (AFAIK). $\endgroup$ Dec 10, 2020 at 14:02
  • $\begingroup$ I don't really see how this is different from just making Mean and Variance options of the function, to be honest. $\endgroup$ Mar 8, 2021 at 14:17

1 Answer 1

8
$\begingroup$

I was recently inspired by ES6 object desctructuring and made something that fits your needs.

It is part of https://github.com/kubaPod/Meh and I consider it beta but I don't care about proper prerelease since I have zero feedback anyway :)

(* ResourceFunction["GitHubInstall"]["kubapod", "meh"] *)

<< Meh`

ClearAll[foo]
foo//es6Decorate
foo[<|
         a_,
         b_Integer,
  "F" -> f_,
         g_:10,
  "J" -> j_:1
|>
]:={a,b,f,g,j}
foo@<|"b"->2,"a"->1,"F"->3|>
foo@<|"b"->2,"a"->1,"F"->3,"g"->100|>
foo@<|"b"->2.2,"a"->1,"F"->3|>

{1, 2, 3, 10, 1}

{1, 2, 3, 100, 1}

foo[<|"b" -> 2.2, "a" -> 1, "F" -> 3|>]

which seems to support what you need because you can do:

createInverseGamma // es6Decorate

createInverseGamma[<|"Mean" -> m_, "Variance" -> v_|>] := With[
  {a = (m^2 + 2 v)/v, b = m (m^2 + v)/v}
, InverseGammaDistribution[a, b]
];

createInverseGamma[<|"Mean" -> m_, "StandardDeviation" -> std_|>] := 
  createInverseGamma[<|"Mean" -> m, "Variance" -> std^2|>];

dist = createInverseGamma[<|"Mean" -> 1, "StandardDeviation" -> 2|>]

Mean[dist]             (*1*)
Variance[dist]         (*4*)

So yes, not exactly the same syntax but this answer is a side effect.

$\endgroup$
1
  • $\begingroup$ Thank you @Kuba, that looks very interesting. I will have a look. $\endgroup$ Mar 8, 2021 at 9:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.