How to set deeper patterns in arguments within function definitions. For example if an argument must be a list of 1 or more strings

Suppose I want to define a function whose argument must be a List of only Strings and List must have at least one member. I know how to require that the Head must be a List but how does one qualify List members within an argument? I really don't want to resort pattern matching inside the body of my definitions or trailing a conditional pattern outside my definitions.

This is what I have so far along with a few test cases...

fn[arg_List && AllTrue[arg, StringQ] && Length@arg > 0] :=
Block[{}, arg];
fn[{"a", "b", "c"}] (* should return {"a","b","c"} *)
fn[{1, "b", "c"}]
fn[{}]


Unfortunately it produces no errors which in this case would have been very helpful.

• does it work if you replace it with fn[arg_List /; (AllTrue[arg, StringQ] && Length@arg > 0)] := Module[{}, arg]; ? btw, why Block there? Why not use normal Module? Oct 28 at 8:11
• @Nasser thank you that worked!!! i try not to use modules unless absolutely necessary because they require more memory and are slower than blocks. Oct 28 at 8:18
• because they require more memory and are slower than blocks I did not know this. I use Modules all the time, since Block scoping is a little confusing to me. But if they work for you, that should work then. Oct 28 at 8:20
• You could also do fn[arg_ /; VectorQ[arg, StringQ] && arg != {}] := ... Oct 28 at 8:46

When imposing restrictions on patterns, there are typically two options:

• Use Condition (/;) to specify an arbitrary expression as test. (This is what was shown in the comments)

fn[arg_List /; (AllTrue[arg, StringQ] && Length@arg > 0)] := Module[{}, arg];
fn[arg_ /; VectorQ[arg, StringQ] && arg != {}] := Module[{}, arg];


This is most flexible, but can be significantly slower, since the pattern matcher has to ask the kernel to evaluate the condition

• Use structural patterns: The pattern arg_List is mostly equivalent to arg:{___}, where Pattern (:) gives the name, and the {___} is "anything that looks like a list with zero or more arguments (see BlankNullSequence, ___). To require at least one element, use BlankSequence (__). You can also specify a head for these elements, e.g. __String. So the pattern here would be:

fn[arg:{__String}] := Module[{}, arg];


If each element should follow a more complex pattern, you can use Repeated (..) and RepeatedNull (...). So to require e.g. a list of lists of strings, use

fn[arg:{{__String}...}] := Module[{}, arg];


If the condition on the single elements is more complex, you can use PatternTest (?):

fn[arg:{__String?(StringStartsQ["a"])}] := Module[{}, arg];


This example requires a list of strings starting with a.

• you really kicked ass on this answer. you dispel many mysteries behind conditional patterns for arguments that should have been better explained in the official documentation. Oct 28 at 11:24
• if i wanted this fn[arg:{__String}]  but wanted to require all strings have StringLength > 0 not sure how to add that. Nov 11 at 16:12
• @JulesManson I would do it similar to the last example, so e.g. (StringLength[#]>0&) instead of (StringContainsQ["a"]) Nov 11 at 23:11