3
$\begingroup$

I'm trying to add a long list of pattern matching conditions to an existing function, which takes a variable number of arguments.

I know there are similar threads on this topic, but I was unable to make them work for the particular example I'd like to do.

Take the condition that says numerical objects should be factored out of the function argument.

lol[c_?NumericQ d_] := c lol[d]

lol[2]
lol[2 kk]

(* -> lol[2] *)
(* -> 2 lol[kk] *)

Now I would like it to be able to apply this condition to an arbitrary number of slots. For example I would like to write something like

lol[c_?NumericQ d__] := c lol[d]

lol[2]
lol[2 kk]
lol[2 kk, 3 jj]

(* -> lol[2] *)
(* -> 2 lol[kk] *)
(* -> 6 lol[kk,jj] *)

but instead

lol[2 kk, 3 jj]

simply returns

(* -> lol[2 kk, 3 jj] *)

Just to emphasise: it must be able to handle any number of inputs, I can't just code rules for 2 slots in addition to the rule for 1 slot. And the goal is to be able to update the properties of "lol" as a function, not just to produce a procedure that can factor Numeric objects out of functions (because I have an existing function that needs to have these properties but is too lengthy to paste her).

$\endgroup$
  • $\begingroup$ This looks to be a problem where both the input and output arguments of lol should be lists. You may then also want to consider ReplaceAll. $\endgroup$ – DavidC Nov 13 '16 at 14:21
  • $\begingroup$ I'm just wondering if I'll be able to use ReplaceAll to update the properties of an existing function... will give it a try $\endgroup$ – Jonathan Rayner Nov 13 '16 at 15:09
5
$\begingroup$

The answer is:

lol[left___, c_?NumericQ d_, right___] := c lol[left, d, right]
$\endgroup$
  • $\begingroup$ Can this approach handle the case of multiple slots with numerical multipliers as requested in the question? $\endgroup$ – MarcoB Nov 14 '16 at 1:06
  • $\begingroup$ @MarcoB Yes, it can. $\endgroup$ – QuantumDot Nov 14 '16 at 1:13
  • $\begingroup$ Confirmed, works perfectly on any number of slots. @QuantumDot Can you explain why it works? I've tried to think through what procedure Mathematica follows with the case of 1, 2, or 3 slots, but I'm lost. $\endgroup$ – Jonathan Rayner Nov 14 '16 at 6:48
  • $\begingroup$ @JonRayner ___ is BlankNullSequence and represents any number of arguments. When the pattern matcher encounters this in a pattern, it tries all possible combinations to match the pattern. $\endgroup$ – QuantumDot Nov 14 '16 at 14:52
1
$\begingroup$

I've got

lol[x : (PatternSequence[_?NumericQ _Symbol] ..)] :=
    (Times @@ {x}[[All, 1]]) lol[Sequence @@ {x}[[All, 2]]]

which gives

lol[2 k, 3 j]

6 lol[k, j]

lol[2 k, 3 j, 5 m]

30 lol[k, j, m]


Caveats:

lol[2 k, j]

lol[2 k, j]

lol[2 k, 1 j]

lol[2 k, j]

but

lol[2 k, 1. j]
  1. lol[k, j]

Also

lol[2 k, 7]

lol[2 k, 7]

but I'm not sure what should the function do in this case.


And a brute one:

Clear[lol]
lol[x__] := 
 Module[{y = List@x, coeffs, vars, c}, 
  vars = Variables /@ y // Flatten; 
  coeffs = Coefficient[##] & @@@ Transpose@{y, vars}; 
  c = Times @@ coeffs; c Defer@lol[##] & @@ vars]


lol[2 k, j]

2 lol[k, j]

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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