14
$\begingroup$

I am trying to modify some code proposed here Part assignment is not a symbol

and I cannot manage to make Flatten work. I write

m = {0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.9, 1.0, 1.5, 1.6}; 
f[list_] := Flatten[Module[{titi = {r, x, y, u, v, n, l, w, s}}, 
  Transpose[{titi, Rest@list}]] /; Length[list] > Length[titi]];

and I get

f[m]

{{r, 0.3}, {x, 0.4}, {y, 0.5}, {u, 0.6}, {v, 0.7}, {n, 0.9}, {l, 1.}, {w, 1.5}, {s, 1.6}}

$\endgroup$
15
$\begingroup$

f[...] := Module[{...}, ... /; condition] is a very special syntax (documented in the Details section of Module). It only works if the right-hand side of the := operator contains a Module. In your example, it contains a Flatten, the Module being buried at a lower level.

What is important to remember is that a /; condition inside of a Module/Block/With must always go together with a := or :>. It is useful to think of /; as going with the := and not with Module.

In fact, normally we write

f[...] /; condition := ...

The reason to use

f[...] := Module[{...}, ... /; condition]

is to be able to use local Module variables in the condition. More precisely, the purpose is to avoid computing things twice. We might need to compute a quantity for the condition, but we may want to use the very same quantity when computing the result of the function. This would not be possible with f[...] /; condition := ....


As @kglr showed, putting the Flatten inside of the Module will fix this.

$\endgroup$
  • $\begingroup$ Wonderful explanation! (Say, we should be able to have memoized, then, functions which occur only under condition, utilizing a form of what we "normally" write within the memoization, yeah?) {checking my understanding, asking for an extension of your answer, if this requires another question to be prosed, I will need to learn fully what I can and cannot "ask" for in a comment!} As always, great work, very clear and understandable! $\endgroup$ – CA Trevillian May 20 at 11:53
  • $\begingroup$ Is it correct to say that this phenomena is due to Condition being programmed internally via pattern matching on Module/With/Block and not on f[Module/With/Block]? Is it also correct that this is nowhere mentioned in the docs (I didn't see it anyway)? Is it fair to say that this amounts to a general shortcoming of the entire pattern-matching based programming model? $\endgroup$ – berniethejet May 20 at 12:41
  • 3
    $\begingroup$ @berniethejet 1. It's implemented in terms of RuleCondition and $ConditionHold. These are not documented, and I never took the time to fully understand them, but you can search this site to find many discussions. 2. The syntax I described is documented under Details in the Module/Block/With doc pages. It is not widely known, but it's the way to implement the typical error-handling behaviour we see in built-in functions: if something goes wrong, the function does not evaluate. This feature is needed because thing often go wrong late in the processing. 3. I do not see any shortcoming. $\endgroup$ – Szabolcs May 20 at 12:48
  • $\begingroup$ Thanks @Szabolcs. I guess what I am trying to say is that for a new user there is no obvious reason why f[...] := Flatten[Module[{...}, ... /; condition]] shouldn't work. It is only once they understand that everything is based on pattern-matching that they can accept these sorts of seemingly arbitrary constraints. $\endgroup$ – berniethejet May 21 at 16:22
  • 1
    $\begingroup$ @berniethejet Yes, it's not obvious. I link to think of it as coming from the LHS: f[x_ /; IntegerQ[x]] := ... can be changed to f[x_] /; IntegerQ[x] := ... can be changed to f[x_] := ... /; Integer[Q] (!) can be changed to f[x_] := Module[{}, ...; ... /; IntegerQ[x]]. But there it stops. It does not go deeper. $\endgroup$ – Szabolcs May 21 at 16:40
10
$\begingroup$

Put Flatten inside Module:

ClearAll[f]
f[list_] := Module[{titi = {r, x, y, u, v, n, l, w, s}}, 
  Flatten@Transpose[{titi, Rest@list}] /; Length[list] > Length[titi]]

f[m]

{r, 0.3, x, 0.4, y, 0.5, u, 0.6, v, 0.7, n, 0.9, l, 1., w, 1.5, s, 1.6}

You could also use Riffle[titi, Rest@list] instead of Flatten[Transpose[{titi, Rest@list}]].

$\endgroup$
  • $\begingroup$ Does your last note imply that we can, in general, replace Flatten[Transpose[{settobeappliedtolist,Rest@list}]] with Riffle[settobeappliedtolist,Rest@list]? $\endgroup$ – CA Trevillian May 20 at 11:57
  • 1
    $\begingroup$ @CATrevillian, I think so. $\endgroup$ – kglr May 20 at 12:04
  • $\begingroup$ Many thanks everyone $\endgroup$ – Ruth Lazkoz May 21 at 8:05

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.