Jump to page: 1 2
Thread overview
Re: D component programming is a joke (Was: Re: Component programming)
Aug 02, 2013
H. S. Teoh
Aug 02, 2013
Walter Bright
Aug 02, 2013
Timon Gehr
Aug 10, 2013
H. S. Teoh
Aug 10, 2013
Jonathan M Davis
Aug 04, 2013
bearophile
Aug 04, 2013
Andre Artus
Aug 10, 2013
Jonathan M Davis
Aug 12, 2013
Jacob Carlborg
Aug 10, 2013
H. S. Teoh
Aug 06, 2013
bearophile
Aug 10, 2013
H. S. Teoh
Aug 10, 2013
H. S. Teoh
August 02, 2013
On Thu, Aug 01, 2013 at 10:49:00PM -0700, Walter Bright wrote:
> On 8/1/2013 10:24 PM, H. S. Teoh wrote:
> >Once this last bit worked, though, everything fell into place quickly. After all unittests were passing, no more bugs were found!! The program can print beautifully laid out calendars with no problems whatsoever. I'm so in love with D right now... If I'd done this exercise in C or C++, I'd be spending the next 2 days debugging before I could present the code for the world to see. D ranges and unittest blocks are t3h k00l.
> 
> I think this is awesome, and this + your previous post are sufficient to create a great article!

OK, here's a draft of the article:

	http://wiki.dlang.org/User:Quickfur/Component_programming_with_ranges

It looks like I may have to sort out some issues with compiler bugs before officially posting this article, though, since the code apparently fails to compile with many versions of DMD. :-(


T

-- 
Живёшь только однажды.
August 02, 2013
On 8/2/2013 3:02 PM, H. S. Teoh wrote:
> OK, here's a draft of the article:
>
> 	http://wiki.dlang.org/User:Quickfur/Component_programming_with_ranges
>
> It looks like I may have to sort out some issues with compiler bugs
> before officially posting this article, though, since the code
> apparently fails to compile with many versions of DMD. :-(

Get 'em up on bugzilla! (At least any that fail with HEAD.)


August 02, 2013
On 08/03/2013 12:02 AM, H. S. Teoh wrote:
> On Thu, Aug 01, 2013 at 10:49:00PM -0700, Walter Bright wrote:
>> On 8/1/2013 10:24 PM, H. S. Teoh wrote:
>>> Once this last bit worked, though, everything fell into place quickly.
>>> After all unittests were passing, no more bugs were found!! The program
>>> can print beautifully laid out calendars with no problems whatsoever.
>>> I'm so in love with D right now... If I'd done this exercise in C or
>>> C++, I'd be spending the next 2 days debugging before I could present
>>> the code for the world to see. D ranges and unittest blocks are t3h
>>> k00l.
>>
>> I think this is awesome, and this + your previous post are
>> sufficient to create a great article!
>
> OK, here's a draft of the article:
>
> 	http://wiki.dlang.org/User:Quickfur/Component_programming_with_ranges
>
> It looks like I may have to sort out some issues with compiler bugs
> before officially posting this article, though, since the code
> apparently fails to compile with many versions of DMD. :-(
>
>
> T
>

Also, you may want to replace some of the manually implemented ranges where this makes sense.

Eg, datesInYear can be expressed more to the point as:


auto datesInYear(int year){
    return Date(year,1,1).recurrence!((a,n)=>a[n-1]+1.dur!"days")
        .until!(a=>a.year>year);
}



(This closes over year though. The following version uses only closed lambdas by embedding year in the returned range object:


auto datesInYear(int year){
    return Date(year,1,1)
        .recurrence!((a,n)=>a[n-1]+1.dur!"days")
        .zip(year.repeat)
        .until!(a=>a[0].year>a[1]).map!(a=>a[0]);
})

August 03, 2013
On 2013-08-02 23:27:20 +0000, Timon Gehr said:
> Also, you may want to replace some of the manually implemented ranges where this makes sense.
> 
> Eg, datesInYear can be expressed more to the point as:
> 
> 
> auto datesInYear(int year){
>      return Date(year,1,1).recurrence!((a,n)=>a[n-1]+1.dur!"days")
>          .until!(a=>a.year>year);
> }
> 
> 
> 
> (This closes over year though. The following version uses only closed lambdas by embedding year in the returned range object:
> 
> 
> auto datesInYear(int year){
>      return Date(year,1,1)
>          .recurrence!((a,n)=>a[n-1]+1.dur!"days")
>          .zip(year.repeat)
>          .until!(a=>a[0].year>a[1]).map!(a=>a[0]);
> })

Would be nice to have a couple of these both explicit and also implemented with the stdlib.

Andrei


August 04, 2013
H. S. Teoh:

> OK, here's a draft of the article:
>
> 	http://wiki.dlang.org/User:Quickfur/Component_programming_with_ranges


Most of the code below is not tested. So my suggestions may contain bugs or mistakes.


A bit improved chunkBy could go in Phobos.

---------------

>For our purposes, though, we can't just do this in a loop, because it has to interface with the other components, which do not have a matching structure to a loop over dates.<

It's just because D doesn't yet have a yield designed like C#. "yield" for coroutines is a very nice kind of glue.

---------------

auto datesInYear(int year) {
    return Date(year, 1, 1)
        .recurrence!((a,n) => a[n-1] + dur!"days"(1))
        .until!(a => a.year > year);
}


===>


auto datesInYear(in uint year) pure /*nothrow*/
in {
    assert(year > 1900);
} body {
    return Date(year, 1, 1)
           .recurrence!((a, n) => a[n - 1] + dur!"days"(1))
           .until!(d => d.year > year);
}


I suggest to align the dots vertically like that. And generally _all_ variables/arguments that don't need to mutate should be const or immutable (or enum), unless holes in Phobos or in the type system or other factors prevent you to do it.

---------------

return chunkBy!"a.month()"(dates);

===>

return dates.chunkBy!q{ a.month };

---------------

byWeek() is not so simple. Most of its code is boilerplate code. Perhaps using a "yield" it becomes simpler.

---------------

string spaces(size_t n) {
    return repeat(' ').take(n).array.to!string;
}

===>

string spaces(in size_t n) pure nothrow {
    return std.array.replicate(" ", n);
}


Currently in programs that import both std.range and std.array you have to qualify the module for replicate.

In Python this is just:

' ' * n

---------------

auto buf = appender!string();

Perhaps this suffices:

appender!string buf;

---------------

string[] days = map!((Date d) => " %2d".format(d.day))(r.front)
                .array;

(not tested) ==>

const days = r.front.map!(d => " %2d".format(d.day)).array;

Or:

const string[] days = r
                      .front
                      .map!(d => " %2d".format(d.day))
                      .array;

---------------

If you put the days inside buf, do you really need to turn days into an array with array()?

string[] days = map!((Date d) => " %2d".format(d.day))(r.front)
                .array;
assert(days.length <= 7 - startDay);
days.copy(buf);


Isn't this enough?

auto days = r.front.map!(d => " %2d".format(d.day));

---------------

If not already present this array should go in std.datetime or core.time:

    static immutable string[] monthNames = [
        "January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"
    ];

---------------

return to!string(spaces(before) ~ name ~ spaces(after));

==> (untested)

return text(before.spaces, name, after.spaces);

Or maybe even just (untested):

return before.spaces ~ name ~ after.spaces;

---------------

auto formatMonth(Range)(Range monthDays)
    if (isInputRange!Range && is(ElementType!Range == Date))
{
    assert(!monthDays.empty);
    assert(monthDays.front.day == 1);

    return chain(
        [ monthTitle(monthDays.front.month) ],
        monthDays.byWeek().formatWeek());
}

===> (untested)

auto formatMonth(R)(R monthDays)
    if (isInputRange!R && is(ElementType!R == Date))
in {
    assert(!monthDays.empty);
    assert(monthDays.front.day == 1);
} body {
    return [monthDays.front.month.monthTitle]
           .chain(monthDays.byWeek.formatWeek);
}


Generally I suggest to use pre- and post conditions.

---------------

return months.map!((month) => month.formatMonth());

===> (untested)

return months.map!formatMonth;

---------------

.map!((r) =>

===>

.map!(r =>

---------------

int year = to!int(args[1]);

===>

int year = args[1].to!int;

---------------

On Rosettacode there is a shorter calendar:
http://rosettacode.org/wiki/Calendar#D

If you want we can put, as second D entry, your calendar code (without unittests) in that page too.

Bye,
bearophile
August 04, 2013
> Bearophile:
> If not already present this array should go in std.datetime or core.time:
>
>     static immutable string[] monthNames = [
>         "January", "February", "March", "April", "May", "June",
>         "July", "August", "September", "October", "November", "December"
>     ];

It should probably be picked up from the OS, to support localization.
August 06, 2013
H. S. Teoh:

> It looks like I may have to sort out some issues with compiler bugs
> before officially posting this article, though, since the code
> apparently fails to compile with many versions of DMD. :-(

If not already present, I suggest you to put a reduced version of the problems you have found (with map or something else) in Bugzilla. (Otherwise I'll try to do it later).

Bye,
bearophile
August 10, 2013
On Fri, Aug 02, 2013 at 06:07:02PM -0700, Andrei Alexandrescu wrote:
> On 2013-08-02 23:27:20 +0000, Timon Gehr said:
> >Also, you may want to replace some of the manually implemented ranges where this makes sense.
> >
> >Eg, datesInYear can be expressed more to the point as:
> >
> >
> >auto datesInYear(int year){
> >     return Date(year,1,1).recurrence!((a,n)=>a[n-1]+1.dur!"days")
> >         .until!(a=>a.year>year);
> >}
> >
> >(This closes over year though. The following version uses only closed lambdas by embedding year in the returned range object:
> >
> >
> >auto datesInYear(int year){
> >     return Date(year,1,1)
> >         .recurrence!((a,n)=>a[n-1]+1.dur!"days")
> >         .zip(year.repeat)
> >         .until!(a=>a[0].year>a[1]).map!(a=>a[0]);
> >})

Thanks! I replaced the code with the first version above. I decided that it's OK to close over year; it's a good example of the convenience of D closures. And I also don't feel like explaining the functional gymnastics of using zip and map just to avoid a closure. :)


> Would be nice to have a couple of these both explicit and also implemented with the stdlib.
[...]

I felt the article was approaching the long side, so I decided to just use Timon's simplified code instead of the original explicit implementation.

Or do you think it's better to have both, for comparison?


T

-- 
Ignorance is bliss... but only until you suffer the consequences!
August 10, 2013
On Saturday, August 03, 2013 01:27:20 Timon Gehr wrote:
> Also, you may want to replace some of the manually implemented ranges where this makes sense.
> 
> Eg, datesInYear can be expressed more to the point as:
> 
> 
> auto datesInYear(int year){
>      return Date(year,1,1).recurrence!((a,n)=>a[n-1]+1.dur!"days")
>          .until!(a=>a.year>year);
> }

You could also use std.datetime.Interval and do something like

auto datesInYear(int year)
{
    auto interval = Interval!Date(Date(year, 1, 1), Date(year + 1, 1, 1));
    return interval.fwdRange((a){return a + dur!"days"(1);});
}

I do think that I need to revisit how ranges work with intervals in std.datetime, as they're a bit clunky.

- Jonathan M Davis
August 10, 2013
On Fri, Aug 02, 2013 at 03:02:24PM -0700, H. S. Teoh wrote:
> On Thu, Aug 01, 2013 at 10:49:00PM -0700, Walter Bright wrote:
[...]
> > I think this is awesome, and this + your previous post are sufficient to create a great article!
> 
> OK, here's a draft of the article:
> 
> 	http://wiki.dlang.org/User:Quickfur/Component_programming_with_ranges
[...]

Alright, the article is done:

	http://wiki.dlang.org/Component_programming_with_ranges

I haven't linked it to the articles page yet, though. It'd be better if somebody else vetted it before it is included there, I think. :)


T

-- 
"Holy war is an oxymoron." -- Lazarus Long
« First   ‹ Prev
1 2