Thread overview
startsWith using an array of needles
Aug 20, 2013
Byron
Aug 20, 2013
Jonathan M Davis
Aug 20, 2013
Byron
Aug 20, 2013
Jonathan M Davis
Aug 20, 2013
Jonathan M Davis
Aug 20, 2013
H. S. Teoh
Aug 20, 2013
bearophile
Aug 20, 2013
Jonathan M Davis
August 20, 2013
I am trying to use startsWith with an array of needles.  Failes with not being able to match any functions.  Not sure if there is a work around.

const auto ignore = [".git/", ".gitignore"];

foreach(DirEntry e; getcwd.dirEntries(SpanMode.depth).filter!(a => !a.name.startsWith(ignore))) {
		writeln(e.name);
	}


-Byron
August 20, 2013
On Tuesday, August 20, 2013 17:58:19 Byron wrote:
> I am trying to use startsWith with an array of needles. Failes with not being able to match any functions. Not sure if there is a work around.
> 
> const auto ignore = [".git/", ".gitignore"];
> 
> foreach(DirEntry e; getcwd.dirEntries(SpanMode.depth).filter!(a
> => !a.name.startsWith(ignore))) {
> writeln(e.name);
> }

startsWith dosen't take an array of needles. It takes a variadic list of them. So, it needs to be something more like

!a.name.startsWith(".git/", ".gitignore")

If you want to save the list though, you can use std.typetuple.TypeTuple and an alias:

alias TypeTuple!(".git/", ".gitignore") ignore;

At that point, the rest of your code should work as-is.

- Jonathan M Davis
August 20, 2013
On Tuesday, 20 August 2013 at 16:51:35 UTC, Jonathan M Davis wrote:
> On Tuesday, August 20, 2013 17:58:19 Byron wrote:
>> I am trying to use startsWith with an array of needles. Failes
>> with not being able to match any functions. Not sure if there is
>> a work around.
>> 
>> const auto ignore = [".git/", ".gitignore"];
>> 
>> foreach(DirEntry e; getcwd.dirEntries(SpanMode.depth).filter!(a
>> => !a.name.startsWith(ignore))) {
>> writeln(e.name);
>> }
>
> startsWith dosen't take an array of needles. It takes a variadic list of them.
> So, it needs to be something more like
>
> !a.name.startsWith(".git/", ".gitignore")
>
> If you want to save the list though, you can use std.typetuple.TypeTuple and
> an alias:
>
> alias TypeTuple!(".git/", ".gitignore") ignore;
>
> At that point, the rest of your code should work as-is.
>
> - Jonathan M Davis

What if I want to load my ignore list from a file?
August 20, 2013
Jonathan M Davis:

> startsWith dosen't take an array of needles. It takes a variadic list of them.

All the argument after the first of startsWith could be required to be of the same type, for this D offers:

void foo(T)(T[] items...) {}
void main() {
    foo(1);
    foo(1, 2);
    foo(1, 2, 3);
    foo([1]);
    foo([1, 2]);
    foo([1, 2, 3]);
}


Isn't it better to modify startsWith a little like this?

Bye,
bearophile
August 20, 2013
On Tuesday, August 20, 2013 19:14:08 Byron wrote:
> On Tuesday, 20 August 2013 at 16:51:35 UTC, Jonathan M Davis
> 
> wrote:
> > On Tuesday, August 20, 2013 17:58:19 Byron wrote:
> >> I am trying to use startsWith with an array of needles. Failes
> >> with not being able to match any functions. Not sure if there
> >> is
> >> a work around.
> >> 
> >> const auto ignore = [".git/", ".gitignore"];
> >> 
> >> foreach(DirEntry e; getcwd.dirEntries(SpanMode.depth).filter!(a
> >> => !a.name.startsWith(ignore))) {
> >> writeln(e.name);
> >> }
> > 
> > startsWith dosen't take an array of needles. It takes a
> > variadic list of them.
> > So, it needs to be something more like
> > 
> > !a.name.startsWith(".git/", ".gitignore")
> > 
> > If you want to save the list though, you can use
> > std.typetuple.TypeTuple and
> > an alias:
> > 
> > alias TypeTuple!(".git/", ".gitignore") ignore;
> > 
> > At that point, the rest of your code should work as-is.
> > 
> > - Jonathan M Davis
> 
> What if I want to load my ignore list from a file?

Then you'll have to make separate calls to startsWith. The number of arguments has to be known at compile time, so unless the number of arguments from the file is always the same, and you have a variable per argument, you can't do it. But unless the needles have similar prefixes, there isn't going to be much of an efficiency hit from multiple calls.

- Jonathan M Davis
August 20, 2013
On Tuesday, August 20, 2013 19:14:08 Byron wrote:
> On Tuesday, 20 August 2013 at 16:51:35 UTC, Jonathan M Davis
> 
> wrote:
> > On Tuesday, August 20, 2013 17:58:19 Byron wrote:
> >> I am trying to use startsWith with an array of needles. Failes
> >> with not being able to match any functions. Not sure if there
> >> is
> >> a work around.
> >> 
> >> const auto ignore = [".git/", ".gitignore"];
> >> 
> >> foreach(DirEntry e; getcwd.dirEntries(SpanMode.depth).filter!(a
> >> => !a.name.startsWith(ignore))) {
> >> writeln(e.name);
> >> }
> > 
> > startsWith dosen't take an array of needles. It takes a
> > variadic list of them.
> > So, it needs to be something more like
> > 
> > !a.name.startsWith(".git/", ".gitignore")
> > 
> > If you want to save the list though, you can use
> > std.typetuple.TypeTuple and
> > an alias:
> > 
> > alias TypeTuple!(".git/", ".gitignore") ignore;
> > 
> > At that point, the rest of your code should work as-is.
> > 
> > - Jonathan M Davis
> 
> What if I want to load my ignore list from a file?

Then you'll have to make separate calls to startsWith. The number of arguments has to be known at compile time, so unless the number of arguments from the file is always the same, and you have a variable per argument, you can't do it. But unless the needles have similar prefixes, there isn't going to be much of an efficiency hit from multiple calls.

- Jonathan M Davis
August 20, 2013
On Tuesday, August 20, 2013 19:32:57 bearophile wrote:
> Jonathan M Davis:
> > startsWith dosen't take an array of needles. It takes a variadic list of them.
> 
> All the argument after the first of startsWith could be required to be of the same type, for this D offers:
> 
> void foo(T)(T[] items...) {}
> void main() {
> foo(1);
> foo(1, 2);
> foo(1, 2, 3);
> foo([1]);
> foo([1, 2]);
> foo([1, 2, 3]);
> }
> 
> 
> Isn't it better to modify startsWith a little like this?

Things get messy when you try and do stuff like that thanks to being able to have arrays of arrays and whatnot. We already have issues with several functions where you're forced to give them strings instead of characters. Type-safe variadics are particularly bad thanks to the fact that they acccept both indivdual elements and an array.

Also, allowing what you suggest would increase the risk of bugs when you meant to do something like search for a string in an array of strings but accidentally give it a string to search in. Right now, stuff like that gets caught.

- Jonathan M Davis
August 20, 2013
On Tue, Aug 20, 2013 at 03:16:28PM -0400, Jonathan M Davis wrote:
> On Tuesday, August 20, 2013 19:14:08 Byron wrote:
> > On Tuesday, 20 August 2013 at 16:51:35 UTC, Jonathan M Davis
> > 
> > wrote:
> > > On Tuesday, August 20, 2013 17:58:19 Byron wrote:
> > >> I am trying to use startsWith with an array of needles. Failes with not being able to match any functions. Not sure if there is a work around.
> > >> 
> > >> const auto ignore = [".git/", ".gitignore"];
> > >> 
> > >> foreach(DirEntry e; getcwd.dirEntries(SpanMode.depth).filter!(a
> > >> => !a.name.startsWith(ignore))) {
> > >> writeln(e.name);
> > >> }
> > > 
> > > startsWith dosen't take an array of needles. It takes a variadic list of them.  So, it needs to be something more like
> > > 
> > > !a.name.startsWith(".git/", ".gitignore")
> > > 
> > > If you want to save the list though, you can use
> > > std.typetuple.TypeTuple and
> > > an alias:
> > > 
> > > alias TypeTuple!(".git/", ".gitignore") ignore;
> > > 
> > > At that point, the rest of your code should work as-is.
> > > 
> > > - Jonathan M Davis
> > 
> > What if I want to load my ignore list from a file?
> 
> Then you'll have to make separate calls to startsWith. The number of arguments has to be known at compile time, so unless the number of arguments from the file is always the same, and you have a variable per argument, you can't do it.  But unless the needles have similar prefixes, there isn't going to be much of an efficiency hit from multiple calls.
[...]

And if you're worried about efficiency, I suggest constructing and caching a regex for doing the matching. It will be better than a long series of startsWith calls if your ignore list is large.


T

-- 
"640K ought to be enough" -- Bill G., 1984. "The Internet is not a primary goal for PC usage" -- Bill G., 1995. "Linux has no impact on Microsoft's strategy" -- Bill G., 1999.