3
$\begingroup$

I have a function f and its downvalues. I want to code an extra downvalue for arguments of the form "part1:part2"

I don't understand why

f[a__~~":"~~b__] := {a,b}

does not work. I can only think of

f[string_String] /; StringMatchQ[string,__~~":"~~__] := StringCases[string, a__~~":"~~b__ :> {a,b}][[1]]

but this doesn't seem very smart as the string structure is examined two times.

$\endgroup$
  • $\begingroup$ a__~~":"~~b__ is a StringExpression, not a Pattern. Try Head[a__ ~~ ":" ~~ b__] vs Head[a_] $\endgroup$ – acl Feb 17 '14 at 23:25
  • $\begingroup$ Thanks, this explains my mistake $\endgroup$ – mete Feb 17 '14 at 23:37
  • $\begingroup$ Equivalent to the second: f[s_?(StringMatchQ[#, __ ~~ ":" ~~ __] &)] := StringSplit[s, ":"] $\endgroup$ – rm -rf Feb 17 '14 at 23:41
5
$\begingroup$

It doesn't work because it's simply not correct syntax. String patterns and expression patterns are not interchangeable. Each works only with its own set of functions: string patterns work only in StringMatchQ and expression patterns only work in MatchQ.

In function definitions you can only use expression patterns.

You can use something like this instead:

f[string_String] := 
 Module[{r}, r = StringCases[string, a__ ~~ ":" ~~ b__ :> {a, b}]; First[r] /; r =!= {}]

This special use of Condition inside Module makes it possible not to process the string twice yet still have a condition attached to the definition.

$\endgroup$
  • $\begingroup$ Ok, makes sense. I thought (hoped?) that you could throw anything into function definition $\endgroup$ – mete Feb 17 '14 at 23:28
  • $\begingroup$ @user2397318 Yes, you can use anything. Your definition is valid, it just doesn't have the meaning you expected. It will match f[x ~~ ":" ~~ y], which as acl said is the same as f[StringExpression[x, ":", y]]. $\endgroup$ – Szabolcs Feb 17 '14 at 23:30

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