enum template shorthand and short circuit evaluation
Should this work? It seems like the short circuit booleans are not working: import std.traits; enum isPrimitive(T) = isBasicType!T || (isArray!T && isBasicType! (ForeachType!T)); void main() { assert(isPrimitive!int); assert(isPrimitive!char); assert(isPrimitive!string); assert(isPrimitive!(byte[])); assert(!isPrimitive!test1); assert(!isPrimitive!test2); assert(!isPrimitive!test3); } class test1 {} struct test2 {} interface test3 {} dmd test C:\D\dmd2\windows\bin\..\..\src\phobos\std\traits.d(5762): Error: invalid foreach aggregate 0 test.d(5): Error: template instance std.traits.ForeachType!int error instantiating test.d(9):instantiated from here: isPrimitive!int test.d(9): Error: template instance test.isPrimitive!int error instantiating C:\D\dmd2\windows\bin\..\..\src\phobos\std\traits.d(5762): Error: invalid foreach aggregate '\xff' test.d(5): Error: template instance std.traits.ForeachType!char error instantiating test.d(10):instantiated from here: isPrimitive!char test.d(10): Error: template instance test.isPrimitive!char error instantiating C:\D\dmd2\windows\bin\..\..\src\phobos\std\traits.d(5762): Error: invalid foreach aggregate null test.d(5): Error: template instance std.traits.ForeachType!(test1) error instantiating test.d(14):instantiated from here: isPrimitive!(test1) test.d(14): Error: template instance test.isPrimitive!(test1) error instantiating C:\D\dmd2\windows\bin\..\..\src\phobos\std\traits.d(5762): Error: invalid foreach aggregate test2() test.d(5): Error: template instance std.traits.ForeachType!(test2) error instantiating test.d(15):instantiated from here: isPrimitive!(test2) test.d(15): Error: template instance test.isPrimitive!(test2) error instantiating C:\D\dmd2\windows\bin\..\..\src\phobos\std\traits.d(5762): Error: invalid foreach aggregate null test.d(5): Error: template instance std.traits.ForeachType!(test3) error instantiating test.d(16):instantiated from here: isPrimitive!(test3) test.d(16): Error: template instance test.isPrimitive!(test3) error instantiating DMD32 D Compiler v2.065 But this style works: template isPrimitive(T) { static if(isBasicType!T || (isArray!T && isBasicType!(ForeachType!T))) { enum isPrimitive = true; } else { enum isPrimitive = false; } } -Byron
Re: splitter for strings
On Monday, 9 June 2014 at 20:01:05 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 19:47:29 UTC, Chris wrote: Uh, I see, I misread the signature of std.string.strip(). So that's one option now, to strip all trailing hyphens with std.string.strip(). Well, I'll give it a shot tomorrow. No, you read the documentation of std.*STRING*.strip correctly. I'm suggesting you use the one from std.*ALGORITHM*. The signatures are mutually exclusive, so you don't need to qualify them. Ah, ok, talking about not seeing the forest for the trees ...
Re: splitter for strings
On Monday, 9 June 2014 at 19:54:08 UTC, Chris wrote: I think it makes sense to put any generic range based algorithms (split and so forth) into std.algorithm. It's always my first port of call, when I have a range. However, that you can do std.string.split([1, 2, 3], 2); is not exactly a desirable situation. Right, but "split(hello world)" *is* string specific. It makes sense for strings only. It doens't make sense to write "split([1, 2, 3])", which is why I'm unsatisfied with the current situation.
Re: splitter for strings
On Monday, 9 June 2014 at 19:47:29 UTC, Chris wrote: Uh, I see, I misread the signature of std.string.strip(). So that's one option now, to strip all trailing hyphens with std.string.strip(). Well, I'll give it a shot tomorrow. No, you read the documentation of std.*STRING*.strip correctly. I'm suggesting you use the one from std.*ALGORITHM*. The signatures are mutually exclusive, so you don't need to qualify them.
Re: splitter for strings
On Monday, 9 June 2014 at 18:09:07 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 17:57:24 UTC, Steven Schveighoffer wrote: I think we are confusing things here, I was talking about strip :) strip and split are actually both pretty much in the same boat actually in regards to that, so just 's/split/strip/g', and the same answer will apply. "split" (and "splitter") actually have it a bit more complicated, because historically, if you imported both string and algorithm, then "split(myString)" will create an ambiguous call. The issue is that you can't do selective imports when you already have a local object with the same name, so algorithm had: auto split(String)(String myString) { return std.string.split(myString); } rather than public import std.string : split; I tried to "fix" the issue by removing "split(String)" from algorithm, but that created some breakage. So Andrei just came down and put *everything* in algorithm, and added an "public import std.algorithm : split" in std.string. This works, but it does mean that: 1. string unconditionally pulls algorithm. 2. You can do things like: std.string.split([1, 2, 3], 2); IMO, the "strip" solution is better :/ If we could split up std.algorithm into individual modules, that would probably help. -Steve Yes. I think it makes sense to put any generic range based algorithms (split and so forth) into std.algorithm. It's always my first port of call, when I have a range. However, that you can do std.string.split([1, 2, 3], 2); is not exactly a desirable situation.
Re: splitter for strings
On Monday, 9 June 2014 at 15:52:24 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 15:19:05 UTC, Chris wrote: On Monday, 9 June 2014 at 14:47:45 UTC, Steven Schveighoffer wrote: On Mon, 09 Jun 2014 10:39:39 -0400, Chris wrote: Atm, I have auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); Which looks more elegant and gives me what I want. IMO, the module that handles the splitting of hyphenated words should be able to deal with cases like "blah-" without the input being prepared in a certain way. It's not mishandled. It's handled exactly as I would have expected. If "blah-" and "blah" result in the same thing, then how do you know the difference? Stripping any possible leading or trailing hyphens is much more efficient than checking every single word to see if it's empty. However, if you have an instance of "--", your solution will remove the extra empty string, whereas mine does not. Not sure if that's important. -Steve It is important. "blah--" should come out as "blah". The logic is along the following lines: if (canFind(w, "-")) { auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); if (parts.data.length == 1) { // false alarm. Trailing hyphen } } The more common case is that it's not a trailing hyphen. std.string.strip() only works for whitespaces. Would be nice to have something like that for random characters. strip(s, '-') or strip(s, ['-', '+', '@']) http://dlang.org/phobos/std_algorithm.html#strip w = w.strip('-'); if (canFind(w, "-")) { ... Uh, I see, I misread the signature of std.string.strip(). So that's one option now, to strip all trailing hyphens with std.string.strip(). Well, I'll give it a shot tomorrow.
Re: splitter for strings
On Monday, 9 June 2014 at 17:57:24 UTC, Steven Schveighoffer wrote: I think we are confusing things here, I was talking about strip :) strip and split are actually both pretty much in the same boat actually in regards to that, so just 's/split/strip/g', and the same answer will apply. "split" (and "splitter") actually have it a bit more complicated, because historically, if you imported both string and algorithm, then "split(myString)" will create an ambiguous call. The issue is that you can't do selective imports when you already have a local object with the same name, so algorithm had: auto split(String)(String myString) { return std.string.split(myString); } rather than public import std.string : split; I tried to "fix" the issue by removing "split(String)" from algorithm, but that created some breakage. So Andrei just came down and put *everything* in algorithm, and added an "public import std.algorithm : split" in std.string. This works, but it does mean that: 1. string unconditionally pulls algorithm. 2. You can do things like: std.string.split([1, 2, 3], 2); IMO, the "strip" solution is better :/ If we could split up std.algorithm into individual modules, that would probably help. -Steve Yes.
Re: splitter for strings
On Mon, 09 Jun 2014 12:06:13 -0400, monarch_dodra wrote: On Monday, 9 June 2014 at 15:54:29 UTC, Steven Schveighoffer wrote: On Mon, 09 Jun 2014 11:49:29 -0400, monarch_dodra wrote: On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer wrote: Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve It's in algorithm, because it's more generic than just strings. Ugh.. This makes things difficult. If I want to work with strings, I import std.string. I understand that the algorithm is applicable to all types, but this makes for some awkward coding. What if you wanted to use both? Surely we can come up with a better solution than this. -Steve I think we are confusing things here, I was talking about strip :) There's 2 different issues: The first, is that "split(string)" was pre-existing in std.string, and *then* split was introduced in algorithm. Where ideally (?) everything would have been placed in the same module, we true to avoid moving things around now. The second thing is that "split" without any predicate/item can only make sense for strings, but not for generic ranges. For what it's worth, I find it makes sense. Well, I suppose it should probably work if you try both strip and strip('-')... and indeed it does. It is not as bad as I thought (I thought they would conflict). It still leaves me a bit uneasy that std.string does not provide everything you would need to work with strings. But we don't want std.string importing std.algorithm, or at least we don't want it importing ALL of std.algorithm. If we could split up std.algorithm into individual modules, that would probably help. -Steve
Re: DMD Compiler Version Dependent Conditional Compilation
Thx
Re: DMD Compiler Version Dependent Conditional Compilation
On Monday, 9 June 2014 at 17:36:10 UTC, Nordlöw wrote: Can I use the version keyword or static if to perform conditional compilation that depends on the version of DMD? The __VERSION__ magic token should do the job. David
DMD Compiler Version Dependent Conditional Compilation
Can I use the version keyword or static if to perform conditional compilation that depends on the version of DMD? I typicall something like version(>= DMD_2.0.66) { // use new byChar, byWchar, byDchar, byCodepoint } else { // use old style slower version } If so how?
Re: findBack: find a needle in a haystack from the back
using retro seems inefficient because of all the decodings Phobos git master just got support for next-gen string processing: https://github.com/D-Programming-Language/phobos/pull/2043 I believe x.byChar.retro is what you want
Re: win64 as orphan?
i agree with you, but you should have posted in "announce", so that adrei can use it for some marketing. i too wait now for a long, long time to use it with win64. i am also giving up - i guess it will stay a linux/apple show. maybe, as a multiple os compiler, you can use lazarus or code typhon. cheers. On Monday, 9 June 2014 at 15:04:19 UTC, trail wrote: will the sorry state of the win64 headers and programs like dfl be fixed or is it time to leave the language to linux and move on to something else?
Re: hijacking override from template mixin
On Monday, 9 June 2014 at 15:54:21 UTC, Ivan Kazmenko wrote: I'd expect a "multiple overrides of same function" error, much like if I just paste the mixin code by hand. Is that a bug or working by design? In the latter case, please explain the reasoning. AFAIK, the rationale is that *should* a colision happen, the local symbol shadows the mixed-in symbol. Doing this avoid breaking your code just because someone added an extra member in their mixin, which happened to conflict with one of yours. The idea is that you can workaround the issue by "naming" your mixin templates. Then, when you want to access members of the mixin template, you *know* it'll always work, regardless of what else may have been declared in your class. That said, for something like virrtual functions, things get a bit trickier, since your *aren't* supposed to call them explicitly... I don't know if bug, or just surprising behavior.
Re: splitter for strings
On Monday, 9 June 2014 at 15:54:29 UTC, Steven Schveighoffer wrote: On Mon, 09 Jun 2014 11:49:29 -0400, monarch_dodra wrote: On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer wrote: Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve It's in algorithm, because it's more generic than just strings. Ugh.. This makes things difficult. If I want to work with strings, I import std.string. I understand that the algorithm is applicable to all types, but this makes for some awkward coding. What if you wanted to use both? Surely we can come up with a better solution than this. -Steve There's 2 different issues: The first, is that "split(string)" was pre-existing in std.string, and *then* split was introduced in algorithm. Where ideally (?) everything would have been placed in the same module, we true to avoid moving things around now. The second thing is that "split" without any predicate/item can only make sense for strings, but not for generic ranges. For what it's worth, I find it makes sense.
Re: splitter for strings
On Mon, 09 Jun 2014 11:49:29 -0400, monarch_dodra wrote: On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer wrote: Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve It's in algorithm, because it's more generic than just strings. Ugh.. This makes things difficult. If I want to work with strings, I import std.string. I understand that the algorithm is applicable to all types, but this makes for some awkward coding. What if you wanted to use both? Surely we can come up with a better solution than this. -Steve
hijacking override from template mixin
The D language pays certain attention to avoiding hijacking [1]. So I was surprised when I hijacked a function override from a template mixin by mistake. Here is a commented example. The comments explain the relevant part of the life cycle of the program. - // Start with class A with method fun returning "A". class A { string fun () {return "A";} } // Subclass B will return "B" instead. class B: A { override string fun () {return "B";} } // Turns out a common need is to return "MT", // so we will create a mixin template MT for it // to reduce boilerplate. mixin template MT () { override string fun () {return "MT";} } // We use MT in our new subclass C. class C: A { mixin MT; } // Both a mixed-in override and a regular one // by a refactoring mistake, what happens? class D: A { mixin MT; override string fun () {return "D";} } // Let's find out. void main () { import std.stdio; writeln (new B ().fun ()); // B writeln (new C ().fun ()); // MT writeln (new D ().fun ()); // D, not MT } - I'd expect a "multiple overrides of same function" error, much like if I just paste the mixin code by hand. Is that a bug or working by design? In the latter case, please explain the reasoning. Also, if there is a "better" tool than a template mixin in the situation explained in the comments, please point me to it. [1] http://dlang.org/hijack.html
Re: splitter for strings
On Monday, 9 June 2014 at 15:19:05 UTC, Chris wrote: On Monday, 9 June 2014 at 14:47:45 UTC, Steven Schveighoffer wrote: On Mon, 09 Jun 2014 10:39:39 -0400, Chris wrote: Atm, I have auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); Which looks more elegant and gives me what I want. IMO, the module that handles the splitting of hyphenated words should be able to deal with cases like "blah-" without the input being prepared in a certain way. It's not mishandled. It's handled exactly as I would have expected. If "blah-" and "blah" result in the same thing, then how do you know the difference? Stripping any possible leading or trailing hyphens is much more efficient than checking every single word to see if it's empty. However, if you have an instance of "--", your solution will remove the extra empty string, whereas mine does not. Not sure if that's important. -Steve It is important. "blah--" should come out as "blah". The logic is along the following lines: if (canFind(w, "-")) { auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); if (parts.data.length == 1) { // false alarm. Trailing hyphen } } The more common case is that it's not a trailing hyphen. std.string.strip() only works for whitespaces. Would be nice to have something like that for random characters. strip(s, '-') or strip(s, ['-', '+', '@']) http://dlang.org/phobos/std_algorithm.html#strip w = w.strip('-'); if (canFind(w, "-")) { ...
Re: splitter for strings
On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer wrote: Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve It's in algorithm, because it's more generic than just strings.
Re: splitter for strings
On Monday, 9 June 2014 at 14:47:45 UTC, Steven Schveighoffer wrote: On Mon, 09 Jun 2014 10:39:39 -0400, Chris wrote: Atm, I have auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); Which looks more elegant and gives me what I want. IMO, the module that handles the splitting of hyphenated words should be able to deal with cases like "blah-" without the input being prepared in a certain way. It's not mishandled. It's handled exactly as I would have expected. If "blah-" and "blah" result in the same thing, then how do you know the difference? Stripping any possible leading or trailing hyphens is much more efficient than checking every single word to see if it's empty. However, if you have an instance of "--", your solution will remove the extra empty string, whereas mine does not. Not sure if that's important. -Steve It is important. "blah--" should come out as "blah". The logic is along the following lines: if (canFind(w, "-")) { auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); if (parts.data.length == 1) { // false alarm. Trailing hyphen } } The more common case is that it's not a trailing hyphen. std.string.strip() only works for whitespaces. Would be nice to have something like that for random characters. strip(s, '-') or strip(s, ['-', '+', '@'])
win64 as orphan?
will the sorry state of the win64 headers and programs like dfl be fixed or is it time to leave the language to linux and move on to something else?
Re: splitter for strings
On Mon, 09 Jun 2014 10:39:39 -0400, Chris wrote: Atm, I have auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); Which looks more elegant and gives me what I want. IMO, the module that handles the splitting of hyphenated words should be able to deal with cases like "blah-" without the input being prepared in a certain way. It's not mishandled. It's handled exactly as I would have expected. If "blah-" and "blah" result in the same thing, then how do you know the difference? Stripping any possible leading or trailing hyphens is much more efficient than checking every single word to see if it's empty. However, if you have an instance of "--", your solution will remove the extra empty string, whereas mine does not. Not sure if that's important. -Steve
Re: splitter for strings
On Monday, 9 June 2014 at 14:21:21 UTC, Steven Schveighoffer wrote: On Mon, 09 Jun 2014 07:04:11 -0400, Chris wrote: On Monday, 9 June 2014 at 10:54:09 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 10:23:16 UTC, Chris wrote: Ok, thanks. I'll keep that in mind for the next version. Seems to me to also work with 2.065 and 2.064. From the library reference: assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); Note the 2 spaces between hello and world and "If a range with one separator is given, the result is a range with two empty elements." Right, it allows you to distinguish cases where the range starts or ends with the separator. My problem was that if I have input like auto word = "bla-"; it will return parts.data.length == 2, so I would have to check parts.data[1] != "". This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in "bla-") length > 2 // do something else One thing you could do is strip any leading or trailing hyphens: assert("-bla-".chomp("-").chompPrefix("-").split('-').length == 1); Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve Atm, I have auto parts = appender!(string[]); w.splitter('-').filter!(a => !a.empty).copy(parts); Which looks more elegant and gives me what I want. IMO, the module that handles the splitting of hyphenated words should be able to deal with cases like "blah-" without the input being prepared in a certain way. Now I have: if (parts.data.length == 1) { // false alarm. Trailing hyphen }
Re: splitter for strings
On Mon, 09 Jun 2014 07:04:11 -0400, Chris wrote: On Monday, 9 June 2014 at 10:54:09 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 10:23:16 UTC, Chris wrote: Ok, thanks. I'll keep that in mind for the next version. Seems to me to also work with 2.065 and 2.064. From the library reference: assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); Note the 2 spaces between hello and world and "If a range with one separator is given, the result is a range with two empty elements." Right, it allows you to distinguish cases where the range starts or ends with the separator. My problem was that if I have input like auto word = "bla-"; it will return parts.data.length == 2, so I would have to check parts.data[1] != "". This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in "bla-") length > 2 // do something else One thing you could do is strip any leading or trailing hyphens: assert("-bla-".chomp("-").chompPrefix("-").split('-').length == 1); Just looked at std.string for a strip function that allows custom character strippage, but apparently not there. The above is quite awkward. -Steve
Re: splitter for strings
On Monday, 9 June 2014 at 12:16:30 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 11:40:24 UTC, Chris wrote: On Monday, 9 June 2014 at 11:16:18 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 11:04:12 UTC, Chris wrote: From the library reference: assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); and "If a range with one separator is given, the result is a range with two empty elements." My problem was that if I have input like auto word = "bla-"; it will return parts.data.length == 2, so I would have to check parts.data[1] != "". This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in "bla-") length > 2 // do something else You can just pipe in an extra "filter!(a=>!a.empty)", and it'll do what you want: put(parts, w.splitter('-').filter!(a=>!a.empty)()); The rational for this behavior, is that it preserves the "total amount of information" from your input. EG: assert(equal(myString.spliter(sep).join(sep), myString)); If the empty tokens were all stripped out, that wouldn't work, you'd have lost information about how many separators there actually were, and where they were. I see, I've already popped in a filter. I only wonder how much of a performance loss that is. Probably negligible. Arguably, none, since someone has to do the check anyways. If it's not done "outside" of splitter, it has to be done inside... Yes, of course. I just thought if it's done in the library function, the optimization might be better than when it is done in my code. (filter!() is arguably also in the library :)
Re: splitter for strings
On Monday, 9 June 2014 at 11:40:24 UTC, Chris wrote: On Monday, 9 June 2014 at 11:16:18 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 11:04:12 UTC, Chris wrote: From the library reference: assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); and "If a range with one separator is given, the result is a range with two empty elements." My problem was that if I have input like auto word = "bla-"; it will return parts.data.length == 2, so I would have to check parts.data[1] != "". This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in "bla-") length > 2 // do something else You can just pipe in an extra "filter!(a=>!a.empty)", and it'll do what you want: put(parts, w.splitter('-').filter!(a=>!a.empty)()); The rational for this behavior, is that it preserves the "total amount of information" from your input. EG: assert(equal(myString.spliter(sep).join(sep), myString)); If the empty tokens were all stripped out, that wouldn't work, you'd have lost information about how many separators there actually were, and where they were. I see, I've already popped in a filter. I only wonder how much of a performance loss that is. Probably negligible. Arguably, none, since someone has to do the check anyways. If it's not done "outside" of splitter, it has to be done inside...
Re: findBack: find a needle in a haystack from the back
On Monday, 9 June 2014 at 07:58:25 UTC, Timothee Cour via Digitalmars-d-learn wrote: Is there a more idiomatic/elegant way to achieve the following, while remaining as efficient as possible? Same question in the simpler case n==0? using retro seems inefficient because of all the decodings // returns the largest suffix of a that contains no more than n times c string findBack(string a, char c, size_t n=0){ auto b=cast(immutable(ubyte)[])a; auto val=cast(ubyte)c; size_t counter=0; for(ptrdiff_t i=cast(ptrdiff_t)b.length - 1; i>=0; i--){ if(b[i]==c){ if(counter>=n) return cast(string)a[i+1..$]; counter++; } } return a; } //unittest{ void test3(){ auto c='\n'; string a="abc1\nabc2\nabc3"; assert(a.findBack(c,0)=="abc3"); assert(a.findBack(c,1)=="abc2\nabc3"); assert(a.findBack(c,2)=="abc1\nabc2\nabc3"); assert(a.findBack(c,3)=="abc1\nabc2\nabc3"); } If you are going to cast the string to ubyte[] anyway, why not just do this before using retro?
Re: splitter for strings
On Monday, 9 June 2014 at 11:16:18 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 11:04:12 UTC, Chris wrote: From the library reference: assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); and "If a range with one separator is given, the result is a range with two empty elements." My problem was that if I have input like auto word = "bla-"; it will return parts.data.length == 2, so I would have to check parts.data[1] != "". This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in "bla-") length > 2 // do something else You can just pipe in an extra "filter!(a=>!a.empty)", and it'll do what you want: put(parts, w.splitter('-').filter!(a=>!a.empty)()); The rational for this behavior, is that it preserves the "total amount of information" from your input. EG: assert(equal(myString.spliter(sep).join(sep), myString)); If the empty tokens were all stripped out, that wouldn't work, you'd have lost information about how many separators there actually were, and where they were. I see, I've already popped in a filter. I only wonder how much of a performance loss that is. Probably negligible.
Re: splitter for strings
On Monday, 9 June 2014 at 11:04:12 UTC, Chris wrote: From the library reference: assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); and "If a range with one separator is given, the result is a range with two empty elements." My problem was that if I have input like auto word = "bla-"; it will return parts.data.length == 2, so I would have to check parts.data[1] != "". This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in "bla-") length > 2 // do something else You can just pipe in an extra "filter!(a=>!a.empty)", and it'll do what you want: put(parts, w.splitter('-').filter!(a=>!a.empty)()); The rational for this behavior, is that it preserves the "total amount of information" from your input. EG: assert(equal(myString.spliter(sep).join(sep), myString)); If the empty tokens were all stripped out, that wouldn't work, you'd have lost information about how many separators there actually were, and where they were.
Re: splitter for strings
On Monday, 9 June 2014 at 10:54:09 UTC, monarch_dodra wrote: On Monday, 9 June 2014 at 10:23:16 UTC, Chris wrote: Ok, thanks. I'll keep that in mind for the next version. Seems to me to also work with 2.065 and 2.064. From the library reference: assert(equal(splitter("hello world", ' '), [ "hello", "", "world" ])); and "If a range with one separator is given, the result is a range with two empty elements." My problem was that if I have input like auto word = "bla-"; it will return parts.data.length == 2, so I would have to check parts.data[1] != "". This is too awkward. I just want the parts of the word, i.e. length == 2 // grab [0] grab [1] length == 1 // grab [0] (no second part, as in "bla-") length > 2 // do something else
Re: splitter for strings
On Monday, 9 June 2014 at 10:23:16 UTC, Chris wrote: Ok, thanks. I'll keep that in mind for the next version. Seems to me to also work with 2.065 and 2.064.
Re: splitter for strings
On Monday, 9 June 2014 at 10:14:40 UTC, bearophile wrote: Chris: auto word = "bla-bla"; auto parts = appender!(string[]); w.splitter('-').copy(parts); // parts.data.length == 3 ["bla", "", "bla"] With the current dmd 2.066alpha this code: void main() { import std.stdio, std.string, std.algorithm; const txt = "bla-bla"; txt.split("-").writeln; txt.splitter("-").writeln; txt.splitter('-').writeln; } Prints: ["bla", "bla"] ["bla", "bla"] ["bla", "bla"] Bye, bearophile Ok, thanks. I'll keep that in mind for the next version.
Re: splitter for strings
Chris: auto word = "bla-bla"; auto parts = appender!(string[]); w.splitter('-').copy(parts); // parts.data.length == 3 ["bla", "", "bla"] With the current dmd 2.066alpha this code: void main() { import std.stdio, std.string, std.algorithm; const txt = "bla-bla"; txt.split("-").writeln; txt.splitter("-").writeln; txt.splitter('-').writeln; } Prints: ["bla", "bla"] ["bla", "bla"] ["bla", "bla"] Bye, bearophile
splitter for strings
Say I wanna split a string that contains hyphens. If I use std.algorithm.splitter I end up with empty elements for each hyphen, e.g.: auto word = "bla-bla"; auto parts = appender!(string[]); w.splitter('-').copy(parts); // parts.data.length == 3 ["bla", "", "bla"] This is not ideal for my purposes, so I filter like so: auto parts = appender!(string[]); foreach (p; word.splitter('-')) { if (p != "") { parts ~= p; } } or even better like so: w.splitter('-').filter!(a => a != "").copy(parts); I wonder, however, whether this is ideal or whether regex's split would be a better match (pardon the pun!). I try to avoid regex when ever possible since they are more awkward to use and usually more expensive.
findBack: find a needle in a haystack from the back
Is there a more idiomatic/elegant way to achieve the following, while remaining as efficient as possible? Same question in the simpler case n==0? using retro seems inefficient because of all the decodings // returns the largest suffix of a that contains no more than n times c string findBack(string a, char c, size_t n=0){ auto b=cast(immutable(ubyte)[])a; auto val=cast(ubyte)c; size_t counter=0; for(ptrdiff_t i=cast(ptrdiff_t)b.length - 1; i>=0; i--){ if(b[i]==c){ if(counter>=n) return cast(string)a[i+1..$]; counter++; } } return a; } //unittest{ void test3(){ auto c='\n'; string a="abc1\nabc2\nabc3"; assert(a.findBack(c,0)=="abc3"); assert(a.findBack(c,1)=="abc2\nabc3"); assert(a.findBack(c,2)=="abc1\nabc2\nabc3"); assert(a.findBack(c,3)=="abc1\nabc2\nabc3"); }