Naming, naming, naming.
I've never heard of a "glob search", but I like the idea of implementing it in vba. One thing I know, is that I don't expect vba to read like python, so
os.SEP would be clearer as
os.PathSeparator, or even better, as
path.Separator. Now I do have a tendency to go by .net naming standards, but really, anything other than a YELLCASE
SEP would be cleaner and clearer.
Even the python community seems to agree that using
os.sep makes for clearer code - I'd use
os.path.sep to make it very clear that it's the path separator and I recommend you use
os.path.sep for clarity, since it's a path separator, not an OS separator. So I'd go with
path.Sep to maintain Pythonish naming.
Looking at your linked question, I see @RubberDuck already recommended using better names for your constants; sorry to reiterate the same advice here.
I know python loves
snake_case, but in vba that kind of casing is potentially confusing (for class methods, more specifically) - I'd recommend sticking to language's
PascalCase naming convention, and using a consistent
camelCase for locals and parameters, for readability's sake (the actual VB/VBA conventions would go
PascalCase all the way, but I find that maddening). I find
pat_list would really benefit from simply being called
patterns, or more accurately,
patternParts - the
_list suffix feels Hungarian, and seems to reflect the type, which could just as well be a regular
Collection - I like that you're using your own
List type though.
The documentation I've found actually calls its sole parameter
Return a possibly-empty list of path names that match pathname, which must be a string containing a path specification. pathname can be either absolute (like
/usr/src/Python-1.5/Makefile) or relative (like
../../Tools/*/*.gif), and can contain shell-style wildcards.
You haven't shown us how the client code might use this function, and it's.. pretty hard to guess just by looking at this post, without diving into the
os implementation - I'd have to jump to the definition of
os.SubItems to figure out why I need to pass a
root parameter on top of a
Looking at your added example call, I think it could be worth combining the two parameters into a single
pathName parameter, making the function callable like this:
The difficulty would be to parse the string and differenciate the
root from the
pattern - splitting on path separator and using anything to the left of a part that contains any wildcard as the
root, and everything else as the
pattern, would certainly be possible, and would make it a better API IMO; the
pattern parts are really two parts of the same string, that you've split in two because it's more convenient to do so since the implementation calls
os.SubItems which wants a
root parameter - in other words, splitting that string in two is really only leaking implementation details into the API.
Function as a local variable
I don't like this:
Set GlobRecurse = New List
GlobRecurse.Extend GlobRecurse(folder, pat_list, index + 1)
While this certainly works, it is rather ugly. Not because of multiple assignments (roughly requivalent to multiple [non-returning]
return statements), but because the function's name is being used a local
List variable, happily being appended to.
I would much rather see this:
Private Function GlobRecurse(ByVal root As String, ByVal pat_list As List, ByVal index As Integer) As List
Dim result As List
If index = pat_list.Count Then
Set result = os.SubItems(root, pat_list(index))
Set result = New List
Dim folder As Variant
For Each folder In os.SubFolders(root, pat_list(index))
result.Extend GlobRecurse(folder, pat_list, index + 1)
Set GlobRecurse = result
Especially with the recursive nature of the function, you'll want to avoid repeating the function's name for no reason. My rule of thumb, is to never read from the function identifier, only to assign it.