digitalmars.D.learn - splitter, compilation issue
- sigod (29/29) Oct 27 2015 Here's simple code:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/18) Oct 27 2015 split's documentation says that it requires a ForwardRange but the
- sigod (6/27) Oct 27 2015 It still doesn't work.
- Adam D. Ruppe (7/10) Oct 27 2015 You need to .save at the beginning so when you hit the split
- =?UTF-8?Q?Ali_=c3=87ehreli?= (3/12) Oct 27 2015 I knew that! :p
- Jonathan M Davis via Digitalmars-d-learn (16/44) Oct 27 2015 Well, split calls splitter, and it doesn't make much of an attempt to ch...
- sigod (3/7) Oct 27 2015 Looks like one more way to improve documentation.
- sigod (5/5) Oct 27 2015 Well, problem boils down to `splitter` having a greater
- Adam D. Ruppe (16/18) Oct 27 2015 You could, but I'd say the same thing there - it is no bug, the
- sigod (7/13) Oct 27 2015 I don't expect different answer there. Main idea is to increase
- sigod (3/18) Oct 27 2015 Posted it here: http://stackoverflow.com/q/33380674/944911
- Adam D. Ruppe (22/23) Oct 27 2015 You know, I was just writing an answer for this and I kinda
Here's simple code: import std.algorithm; import std.array; import std.file; void main(string[] args) { auto t = args[1].readText() .splitter('\n') .filter!(e => e.length) .split("---") ; } Looks like it should work, but it won't compile. DMD 2.068.2 fails with this error: Error: template std.algorithm.iteration.splitter cannot deduce function from argument types !()(FilterResult!(__lambda2, Result), string), candidates are: ... Error: template instance std.array.split!(FilterResult!(__lambda2, Result), string) error instantiating It compiles if I insert `.array` before `.split(...`. Am I missing something? Or it's a bug? I've tried to make a brief search in the bug tracker, but didn't found anything. P.S. dpaste gives very strange error: /d712/f815.d(8): Error: unterminated character constant /d712/f815.d(9): Error: unterminated character constant ... and so on
Oct 27 2015
On 10/27/2015 01:58 PM, sigod wrote:Here's simple code: import std.algorithm; import std.array; import std.file; void main(string[] args) { auto t = args[1].readText() .splitter('\n') .filter!(e => e.length) .split("---") ; } Looks like it should worksplit's documentation says that it requires a ForwardRange but the output of filter is an InputRange. (I can't imagine now why split has that requirement.) Ali
Oct 27 2015
On Tuesday, 27 October 2015 at 21:45:10 UTC, Ali Çehreli wrote:On 10/27/2015 01:58 PM, sigod wrote:It still doesn't work. src\phobos\std\array.d(1562): Error: template std.algorithm.iteration.splitter cannot deduce function from argument types !()(Result, string) Sorry, I should've simplified example more.Here's simple code: import std.algorithm; import std.array; import std.file; void main(string[] args) { auto t = args[1].readText() .splitter('\n') .filter!(e => e.length) .split("---") ; } Looks like it should worksplit's documentation says that it requires a ForwardRange but the output of filter is an InputRange. (I can't imagine now why split has that requirement.) Ali
Oct 27 2015
On Tuesday, 27 October 2015 at 21:45:10 UTC, Ali Çehreli wrote:split's documentation says that it requires a ForwardRange but the output of filter is an InputRange. (I can't imagine now why split has that requirement.)You need to .save at the beginning so when you hit the split point, it can present the whole string as front. You don't know if you've hit the split point until after you've done a fair amount of popFront calls, so if you haven't saved it before, it is impossible to return the first element before the splitter string.
Oct 27 2015
On 10/27/2015 02:55 PM, Adam D. Ruppe wrote:On Tuesday, 27 October 2015 at 21:45:10 UTC, Ali Çehreli wrote:I knew that! :p Alisplit's documentation says that it requires a ForwardRange but the output of filter is an InputRange. (I can't imagine now why split has that requirement.)You need to .save at the beginning so when you hit the split point, it can present the whole string as front. You don't know if you've hit the split point until after you've done a fair amount of popFront calls, so if you haven't saved it before, it is impossible to return the first element before the splitter string.
Oct 27 2015
On Tuesday, October 27, 2015 20:58:56 sigod via Digitalmars-d-learn wrote:Here's simple code: import std.algorithm; import std.array; import std.file; void main(string[] args) { auto t = args[1].readText() .splitter('\n') .filter!(e => e.length) .split("---") ; } Looks like it should work, but it won't compile. DMD 2.068.2 fails with this error: Error: template std.algorithm.iteration.splitter cannot deduce function from argument types !()(FilterResult!(__lambda2, Result), string), candidates are: ... Error: template instance std.array.split!(FilterResult!(__lambda2, Result), string) error instantiating It compiles if I insert `.array` before `.split(...`. Am I missing something? Or it's a bug? I've tried to make a brief search in the bug tracker, but didn't found anything. P.S. dpaste gives very strange error: /d712/f815.d(8): Error: unterminated character constant /d712/f815.d(9): Error: unterminated character constant ... and so onWell, split calls splitter, and it doesn't make much of an attempt to check its arguments in its template constraint, mostly passing the buck onto splitter, since it's really just a wrapper around splitter that calls array on the result. You could actually reduce your code down to something more like auto t = "hello".filter!"true"().splitter(" "); and you'd have the same problem. And looking at splitter's template constraint, it requires either a narrow string (which the result of filter is not) or a range for which hasSlicing is true (which is not the case for the result of filter). Whether splitter could be implemented without that (e.g. returning a range of Take), I don't know, but it's pretty clear that the current implementation requires slicing, and if you're using filter, that means that you'd need to do something like use array to convert it to a range which _can_ be sliced to pass to split or splitter. - Jonathan M Davis
Oct 27 2015
On Tuesday, 27 October 2015 at 21:54:33 UTC, Jonathan M Davis wrote:Well, split calls splitter, and it doesn't make much of an attempt to check its arguments in its template constraint, mostly passing the buck onto splitter, since it's really just a wrapper around splitter that calls array on the result.Looks like one more way to improve documentation.
Oct 27 2015
Well, problem boils down to `splitter` having a greater constraints than most functions can meet. Thanks everyone for clarification. P.S. Maybe I should repost my question on SO? I really thought it was a bug, so I posted it here.
Oct 27 2015
On Tuesday, 27 October 2015 at 22:18:55 UTC, sigod wrote:P.S. Maybe I should repost my question on SO? I really thought it was a bug, so I posted it here.You could, but I'd say the same thing there - it is no bug, the algorithm legitimately needs that functionality to split successfully. At the same time, filter legitimately needs to /drop/ that functionality to work efficiently. So the error kinda sucks (maybe i should write this as a tip, whenever you see that pattern, adding a .array can work around it), but it isn't a bug. The reason splitter doesn't try to automatically buffer or something like that is that std.algorithm tries to be as low cost as possible in all cases, and asks you to be aware of and pay the cost when it needs to occur. So if it needs a buffer and can't get one for free, it fails to compile, so you are aware of the problem and can provide one that works best for you (or just stick in .array somewhere to do an easy, generic solution)
Oct 27 2015
On Tuesday, 27 October 2015 at 22:33:32 UTC, Adam D. Ruppe wrote:On Tuesday, 27 October 2015 at 22:18:55 UTC, sigod wrote:I don't expect different answer there. Main idea is to increase language presence and therefore popularity. I saw someone (I think it was Martin Nowak) somewhere saying that maybe we should move questions from Learn forum to SO.P.S. Maybe I should repost my question on SO? I really thought it was a bug, so I posted it here.You could, but I'd say the same thing thereor just stick in .array somewhere to do an easy, generic solutionWhich completely works in this case. Since I'm writing just a code generation tool, which I'll need to use just a few times.
Oct 27 2015
On Tuesday, 27 October 2015 at 22:56:07 UTC, sigod wrote:On Tuesday, 27 October 2015 at 22:33:32 UTC, Adam D. Ruppe wrote:Posted it here: http://stackoverflow.com/q/33380674/944911 Only removed `filter` from code.On Tuesday, 27 October 2015 at 22:18:55 UTC, sigod wrote:I don't expect different answer there. Main idea is to increase language presence and therefore popularity. I saw someone (I think it was Martin Nowak) somewhere saying that maybe we should move questions from Learn forum to SO.P.S. Maybe I should repost my question on SO? I really thought it was a bug, so I posted it here.You could, but I'd say the same thing thereor just stick in .array somewhere to do an easy, generic solutionWhich completely works in this case. Since I'm writing just a code generation tool, which I'll need to use just a few times.
Oct 27 2015
On Wednesday, 28 October 2015 at 00:07:23 UTC, sigod wrote:Only removed `filter` from code.You know, I was just writing an answer for this and I kinda changed my mind. Without filter... I think splitter.splitter ought to work. The implementation requires slicing unless you pass it a predicate. Only that overload works on minimal forward ranges. This compiles: import std.algorithm; import std.array; import std.stdio; void main(string[] args) { auto t = "foo\nbar\ncool---beans" .splitter('\n') .filter!(e => e.length) .splitter!(a => a == "bar") ; writeln(t); } It returns [["foo"], ["cool---beans"]]; it split it on the "bar" line in the middle. I think that might be basically what you want.
Oct 27 2015