July 04, 2013
On 7/4/13 12:20 AM, Russel Winder wrote:
> On Wed, 2013-07-03 at 22:04 -0700, Andrei Alexandrescu wrote:
>> Evidence we've done the right thing by emphasizing ranges instead of
>> opApply.
>>
>> http://www.reddit.com/r/programming/comments/1hl2qr/rust_07_released/
>> https://mail.mozilla.org/pipermail/rust-dev/2013-June/004599.html
>
> I am not sure you can make that deduction. The question of internal vs.
> external iterators is not black and white.

One might have said I thought so if I wrote e.g. "completely eliminated opApply in favor of ranges". D is a multi-paradigm language. That being said, there is value in Occam reduction of the core/preferred abstractions to be used throughout. D put its bet on ranges (i.e. external iteration), not opApply (internal iteration).

> Native still seems to be in the 1990s OO vs. functional war: internal OR
> external. cf. C++, Go, D, Rust, Haskell, OCaml, F#, etc.

I think this characterization is a tad unfair to D. We clearly and deliberately espouse interoperation of paradigms: the const/immutable qualifiers bridge mutability with immutability, safe/system/trusted allow interoperation of system and safe code, opApply complements ranges. At each step we foster seamless integration of major paradigms, not forcing a choice between them.

> But I get too serious and philosophical. It is perhaps because I have
> just finished a two day workshop guiding people to consider these
> questions in a very practical way so as to improve their software
> development.

Those can be real fun.


Andrei
July 04, 2013
On 7/4/13 1:18 AM, Timon Gehr wrote:
> On 07/04/2013 07:04 AM, Andrei Alexandrescu wrote:
>> Evidence we've done the right thing by emphasizing ranges instead of
>> opApply.
>>
>> http://www.reddit.com/r/programming/comments/1hl2qr/rust_07_released/
>> https://mail.mozilla.org/pipermail/rust-dev/2013-June/004599.html
>>
>> Andrei
>
> Well, probably, but implementing ranges is still too tedious.
> It is very likely that rust is going to fix that.

Let's see.

> It should be as simple as:
>
> auto map(alias a,R)(R r){
> foreach(x;r)
> yield a(x);
> }

Nonono. This gives you an input range. The current map() gives a range of the same category as the range passed. This is a major issue with yield. It does make it easy to implement input ranges, but I'm glad we did not build with it.

Andrei
July 04, 2013
On 07/04/2013 03:42 PM, Andrei Alexandrescu wrote:
> On 7/4/13 1:18 AM, Timon Gehr wrote:
>> On 07/04/2013 07:04 AM, Andrei Alexandrescu wrote:
>>> Evidence we've done the right thing by emphasizing ranges instead of
>>> opApply.
>>>
>>> http://www.reddit.com/r/programming/comments/1hl2qr/rust_07_released/
>>> https://mail.mozilla.org/pipermail/rust-dev/2013-June/004599.html
>>>
>>> Andrei
>>
>> Well, probably, but implementing ranges is still too tedious.
>> It is very likely that rust is going to fix that.
>
> Let's see.
>
>> It should be as simple as:
>>
>> auto map(alias a,R)(R r){
>>     foreach(x;r)
>>         yield a(x);
>> }
>
> Nonono. This gives you an input range.

(Note: I was stating a requirement on simplicity.)

I haven't specified that it will give you an input range. If the programmer can figure out the length etc. the compiler will often be able to do so as well. Maybe it's too much magic to make yield just work though.

Another possibility is to implement a DSEL in a library, but all my experiments in this direction pretty much fail quite early because DMD does not know how to deal with moderately complex analysis dependencies (yet?), and has gotten a lot worse recently. I think this issue needs more attention. DMD makes it seem legitimate by spitting out 'forward reference errors' whenever its rather poor heuristic fails. Are there plans for fixing that? (I have ideas and a proof-of-concept implementation that will go open source soon. Incidentally it is currently locked to DMD 2.060 because of the aforementioned regressions.)

> The current map() gives a range of the same category as the range passed.

I'm pretty well aware of that. :o)

> This is a major issue with
> yield. It does make it easy to implement input ranges, but I'm glad we
> did not build with it.
>
> Andrei


July 04, 2013
I see yield as a tool only for when you only want to create input ranges easily. There is a definite value in the other range types, but yield is useful for when you just want to produce an input range quickly.
July 04, 2013
On Thursday, July 04, 2013 19:28:29 w0rp wrote:
> I see yield as a tool only for when you only want to create input ranges easily. There is a definite value in the other range types, but yield is useful for when you just want to produce an input range quickly.

And given how useless pure input ranges are, I really don't see much value in that. About all they give you is the ability to iterate over a set of values once. The other range types are _far_ more powerful, and pure input ranges should be avoided as much as possible IMHO.

- Jonathan M Davis
July 04, 2013
On Thursday, 4 July 2013 at 18:06:51 UTC, Jonathan M Davis wrote:
> On Thursday, July 04, 2013 19:28:29 w0rp wrote:
>> I see yield as a tool only for when you only want to create input
>> ranges easily. There is a definite value in the other range
>> types, but yield is useful for when you just want to produce an
>> input range quickly.
>
> And given how useless pure input ranges are, I really don't see much value in
> that. About all they give you is the ability to iterate over a set of values
> once. The other range types are _far_ more powerful, and pure input ranges
> should be avoided as much as possible IMHO.
>
> - Jonathan M Davis

To be fair, most of the time all you want to do is iterate over the range, so while they aren't powerful, they are sufficient most of the time.
July 04, 2013
Jonathan M Davis:

> And given how useless pure input ranges are, I really don't see much value in
> that. About all they give you is the ability to iterate over a set of values
> once. The other range types are _far_ more powerful, and pure input ranges
> should be avoided as much as possible IMHO.

Python generators are essentially input ranges, you can go only forward, and they yield their results only once:


>>> g = (i ** 2 for i in xrange(5))
>>> list(g)
[0, 1, 4, 9, 16]
>>> list(g)
[]
>>> def gen():
...     for i in xrange(5):
...         yield i * i
...
>>> g = gen()
>>> list(g)
[0, 1, 4, 9, 16]
>>> list(g)
[]


Yet in Python they are used everywhere. I define input ranges often in D and I think they are useful.

Having a built-in "yield" in a language is quite handy. Take a look at the Python and the second D solutions here:
http://rosettacode.org/wiki/Same_Fringe

Bye,
bearophile
July 04, 2013
On Thursday, 4 July 2013 at 18:06:51 UTC, Jonathan M Davis wrote:
> On Thursday, July 04, 2013 19:28:29 w0rp wrote:
>> I see yield as a tool only for when you only want to create input
>> ranges easily. There is a definite value in the other range
>> types, but yield is useful for when you just want to produce an
>> input range quickly.
>
> And given how useless pure input ranges are, I really don't see much value in
> that. About all they give you is the ability to iterate over a set of values
> once. The other range types are _far_ more powerful, and pure input ranges
> should be avoided as much as possible IMHO.
>
> - Jonathan M Davis

InputRanges aren't useless, that's just wrong. When chaining ranges together, you are locked to the most limited range available. If you use network IO, database access, and many other comment tasks, you are left with InputRanges.

While the other range types are certainly more powerful, and a definite path to take when implementing libraries, like std.algorithm, sometimes you just don't need all of that power. Yield is much simpler, and when that's all you need, why complicate matters?
July 04, 2013
On Thu, Jul 04, 2013 at 08:23:01PM +0200, Peter Alexander wrote:
> On Thursday, 4 July 2013 at 18:06:51 UTC, Jonathan M Davis wrote:
> >On Thursday, July 04, 2013 19:28:29 w0rp wrote:
> >>I see yield as a tool only for when you only want to create input ranges easily. There is a definite value in the other range types, but yield is useful for when you just want to produce an input range quickly.
> >
> >And given how useless pure input ranges are, I really don't see much value in that. About all they give you is the ability to iterate over a set of values once. The other range types are _far_ more powerful, and pure input ranges should be avoided as much as possible IMHO.
[...]

I disagree. Most of the time you only want to iterate over a set of values once, and input ranges are perfectly suited for that. I'm a stickler for requiring the minimum to be functional -- if a function only needs to iterate the range once, then it should only require an input range, nothing more.


> To be fair, most of the time all you want to do is iterate over the range, so while they aren't powerful, they are sufficient most of the time.

+1. That's not to say other range types aren't useful; they are very useful (and necessary) in certain contexts. But more often than not, what I do with a range requires nothing more than an input range.


T

-- 
It's bad luck to be superstitious. -- YHL
July 04, 2013
On Thursday, July 04, 2013 20:23:01 Peter Alexander wrote:
> To be fair, most of the time all you want to do is iterate over the range, so while they aren't powerful, they are sufficient most of the time.

ll pure input ranges are really good for is simple iteration, because it's _frequently_ the case you need at least a forward range in order to do much in the way of algorithms with ranges, so unless you're just not using std.algorithm and its ilk much, I don't see how you could possibly think that pure input ranges weren't anything but annoying. There's just so limiting in comparison to every other range type that I think that they should be avoided as much as possible.

Sometimes, you're stuck, because the nature of the type that you're dealing with forces it to be a pure input range, but you just can't take advantage of many algorithms with pure input ranges, which means that you have to write a lot more code or use std.array.array in order to use the various algorithms, forcing you to allocate when it should be completely unnecessary.

If all you're doing with ranges is iteration, then you're under-utilizing them IMHO.

- Jonathan m Davis