# Mimicking named arguments, a good idea? (programming style)

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_]:=

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_]:=

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...?

• "[...] 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. – Kuba Dec 10 '20 at 11:28
• @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). – Picaud Vincent Dec 10 '20 at 11:38
• 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. – Daniel Lichtblau Dec 10 '20 at 13:51
• @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). – Picaud Vincent Dec 10 '20 at 14:02
• I don't really see how this is different from just making Mean and Variance options of the function, to be honest. – Sjoerd Smit Mar 8 at 14:17

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}
];

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.

• Thank you @Kuba, that looks very interesting. I will have a look. – Picaud Vincent Mar 8 at 9:56