July 27, 2012
On 27-Jul-12 20:15, Jesse Phillips wrote:
> On Friday, 27 July 2012 at 13:10:46 UTC, Stuart wrote:
>> On Friday, 27 July 2012 at 03:00:25 UTC, Brad Anderson wrote:
>>>
>>> D equivalent: iota(0, int.max, 2).map!(a => /* do something with even
>>> numbers */)();
>>
>> I think you're missing the point. The purpose isn't to generate a
>> sequence of numbers, but to illustrate how the Yield keyword is used
>> in VB.NET. Sure, getting a sequence of numbers may be straightforward,
>> but what about a lazy-populated list of all files on a computer? That
>> can be done using Yield - and more importantly, WRITTEN like a normal
>> synchronous function. Let's see you do that with map.
>
> You wouldn't use map for that, that would be silly.
>
> Taking a look at DirIteratorImpl[1] in std.file suggest there is a lot
> of setup to navigate the filesystem on Windows. How does Yield help with
> that logic?
>

It should be more straightforward as DirIteratorImpl does maintain stack of directories/searches as it goes.

The yield version could simply use recursion and yield a-la opApply version that was there before.

But this advantage is unimportant since arbitrary deep recursion is a security risk (especially for servers that typically use threads with tiny stacks).

> 1.
> https://github.com/D-Programming-Language/phobos/blob/master/std/file.d#L2397
>
>
> Seriously I'll take my composing ranges over iterators any day.


-- 
Dmitry Olshansky
July 27, 2012
On Friday, 27 July 2012 at 01:56:33 UTC, Stuart wrote:
> On Friday, 27 July 2012 at 00:10:31 UTC, Brad Anderson wrote:
>> D uses ranges instead of iterators. You can read more about them here: http://ddili.org/ders/d.en/ranges.html
>>
>> I find ranges to be a vast improvement over iterators personally (I use iterators extensively in C++ for my job and lament not having ranges regularly).
>>
>>
> On Friday, 27 July 2012 at 00:17:21 UTC, H. S. Teoh wrote:
>> D has something far superior: ranges.
>>
>> 	http://www.informit.com/articles/printerfriendly.aspx?p=1407357&rll=1
>>
>> Even better, they are completely implemented in the library. No
>> unnecessary language bloat just to support them.
>
> I'm not very well up on ranges. I understand the general [1 ... 6] type of ranges, but I really don't see how custom range functions could be as useful as the Yield support in VB.NET.

Yes, I think H. S. Teoh wrote what that without knowing what C#/VB iterators actually are.

.NET has a concept of "enumerators" which are basically equivalent to D's "input ranges". Both enumerators and input ranges are easier to use and safer than C++ iterators. Neither enumerators nor input ranges require any language support to use, but both C# and D have syntactic sugar for them in the form of the foreach statement. Both C# and D input ranges can be infinite.

C#/VB "iterators", however, are an additional syntactic sugar that transforms a function into a state machine that provides an enumerator (or "enumerable"). These are indeed very useful, and missing from D. Here is an example of an iterator that I updated today:

public IEnumerable<IMapOverlay> Overlays() {
	foreach (var ps in _patterns)
	{
		yield return ps.RouteLine;
		yield return ps.PermShapes;
		if (ps.Selected)
			yield return ps.SelShapes;
	}
}

It does not work like opApply; the compiler creates a heap object that implements IEnumerable or IEnumerator (depending on the return value that you ask for -- it is actually IEnumerator that works like a forward ranges, but foreach only accepts IEnumerable, which is a factory for IEnumerators)

In D you could use opApply to do roughly the same thing, but in that case the caller cannot treat the opApply provider like an ordinary collection (e.g. IIUC, the caller cannot use map or filter on the results).
July 27, 2012
On Fri, 27 Jul 2012 16:05:07 +0200, Kagamin <spam@here.lot> wrote:

> Hmm... do you have a use case besides Duff's device and porting legacy code?

I've used it once, when the other option was a pyramid of 15 if statements.
Not saying it couldn't be done without, obviously, but it was clearly the
better option.

-- 
Simen
July 27, 2012
On Fri, 27 Jul 2012 18:15:45 +0200, Jesse Phillips <Jessekphillips+D@gmail.com> wrote:

> Seriously I'll take my composing ranges over iterators any day.

Thing is, them C# iterators are a lot more like D input ranges (and
sometimes forward ranges) than they are C++ iterators.

Given that, they are as composable as D ranges.

-- 
Simen
July 27, 2012
On Friday, 27 July 2012 at 15:09:38 UTC, Graham Fawcett wrote:
> On Friday, 27 July 2012 at 13:10:46 UTC, Stuart wrote:
>> On Friday, 27 July 2012 at 03:00:25 UTC, Brad Anderson wrote:
>>>
>>> D equivalent: iota(0, int.max, 2).map!(a => /* do something with even numbers */)();
>>
>> I think you're missing the point. The purpose isn't to generate a sequence of numbers, but to illustrate how the Yield keyword is used in VB.NET. Sure, getting a sequence of numbers may be straightforward, but what about a lazy-populated list of all files on a computer? That can be done using Yield - and more importantly, WRITTEN like a normal synchronous function. Let's see you do that with map.
>
> That's easy:
>
>   [...elided code...]
>   auto entries = dirEntries(BASE_DIR, SpanMode.breadth);

Ah, but that depends upon the pre-existence of the dirEntries() function. I think perhaps you're missing the point - which is that "Yield" allows you to WRITE a function synchronously which will then be executed lazily, as an iterator. What you have demonstrated there is USING a lazy function. How would I write, in D, a function that would lazily assemble some data and return it as a lazy collection? I mean, without calling existing lazy functions.

Unless ranges (which I admit to knowing very little about) can do this, I respectfully request that Yield be supported in D.

> You should spend some time using ranges before drawing conclusions about them.

Is there a good tutorial on them? I didn't see one on the website.
July 27, 2012
On Friday, 27 July 2012 at 15:27:58 UTC, Alex Rønne Petersen wrote:
> On 27-07-2012 14:56, Stuart wrote:

>> In any case, isn't it the job of the compiler to unroll loops? Why
>> should the coder have to do this himself? Unless of course he's using a
>> thin shitty wrapper over assembly language that claims falsely to be a
>> high-level language - i.e. C.
>
> It was a high-level language at the time it was created.

Quite possibly. But the definition of "high level" has since changed, and C no longer qualifies. Yet proponents of C/C++ continue to froth at the mouth and claim it's a decent language.

Why is D so awesome? Because it's not C.
July 27, 2012
On Friday, 27 July 2012 at 15:42:27 UTC, Sean Kelly wrote:
> On Jul 27, 2012, at 8:05 AM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>
> core.thread.Fiber has yield and has been used as the basis for this style of iterator.  See Mikola Lysenko's talk from the D conference a few years ago.

I think perhaps you are confusing two different meanings of yield. I am not talking about threading. The VB.NET "yield" and "iterator" keywords can be used just as well in a single-threaded application.

http://mattmc3.blogspot.co.uk/2011/04/vbnet-finally-gets-yield-statement.html
July 27, 2012
On Friday, July 27, 2012 20:47:32 Stuart wrote:
> On Friday, 27 July 2012 at 15:09:38 UTC, Graham Fawcett wrote:
> > You should spend some time using ranges before drawing conclusions about them.
> 
> Is there a good tutorial on them? I didn't see one on the website.

There's not. There should be. But someone needs to write one. They're used heavily in Phobos and a fair bit is explained in the library docs, but we really need a general overview and explanation of the concept and how Phobos uses them.

The best thing that we have at the moment is a chapter in a book on D that Ali Çehreli wrote in Turkish and has been translating to English. It's freely avaiable online:

http://ddili.org/ders/d.en/ranges.html

- Jonathan M Davis
July 27, 2012
On Friday, 27 July 2012 at 16:15:46 UTC, Jesse Phillips wrote:
>
> Taking a look at DirIteratorImpl[1] in std.file suggest there is a lot of setup to navigate the filesystem on Windows. How does Yield help with that logic?

Well, off the top of my head, you could use something like:

   Public Iterator Function AllFiles(RootDirectory As String) As IEnumerable(Of String)
      Dim Roots As New Queue(Of String) From {RootDirectory}
      While Roots.Any
         Dim Root = Roots.Pop
         Roots.AddRange(IO.Directory.GetDirectories(Root))
         For Each Filename in IO.Directory.GetFiles(Root)
            Yield Filename
         Next
      End While
   End Function

July 27, 2012
On Friday, July 27, 2012 20:52:37 Stuart wrote:
> I think perhaps you are confusing two different meanings of yield. I am not talking about threading. The VB.NET "yield" and "iterator" keywords can be used just as well in a single-threaded application.

>From what you've been saying, it sounds like yield is probably the equivalent
of declaring a range type in place and using it, which is quite doable but is somewhat more verbose. In most basic cases though, a function probably already exists in std.algorithm that will let you do what you want to do by only providing a lambda function rather than a new range. And the more complex cases have enough implementation that the boilerplate range type declarations are small in comparison. Maybe we _should_ look at providing a better mechanism for creating range types in-place at some point, but what we have - particularly with std.algorithm - is already quite powerful, and I rarely see the need (if ever) to declare a range in-place.

Regardless, with where D is right now, there's no way that such a feature would be added the language itself any time soon. It's probably possible to provide a library solution though, where you just give lambda functions for empty, front, and popFront, which would make creating a basic input range in place quite easy.

- Jonathan M Davis