August 03, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 08/03/2013 01:05 AM, H. S. Teoh wrote:
>
> Actually, I just pulled git HEAD again, and it's still working fine.
> Maybe you just need to update your repo?
> ...
I think it pulled in the wrong version of druntime.
|
August 03, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Thursday, 1 August 2013 at 22:45:10 UTC, bearophile wrote:
> Walter Bright:
>
>> But consider that optimizers are built to optimize typical code patterns. Component programming is fairly non-existent in C and C++, and is new in D. Hence, optimizers are not set up to deal with those patterns (yet).
>
> I agree.
>
> GHC also works with a LLVM back-end, so those optimizations are done in some kind of middle-end.
>
> Probably a silly idea: perhaps we can collect some money, like 1000-2000 dollars, to pay for a 3 day long course for Walter (total about 15 hours) about such matters.
Who's giving the course and where will it be held?
'Modern Compiler Design' by D. Grune, et al. & 'Compiler Design - Analysis and Transformation' by H. Seidl, et al. discusses some basic optimizations for functional programs. But I'm pretty sure Walter is already familiar with these.
Taking an example from Ali's book "P' in D":
import std.stdio;
import std.algorithm;
void main()
{
auto values = [ 1, 2, 3, 4, 5 ];
writeln(values
.map!(a => a * 10)
.map!(a => a / 3)
.filter!(a => !(a % 2)));
}
As stated this implies 3 separate traversals of the list (or array to be specific) which is what a naïve implementation would do. But all three operations can run on the same traversal. Given that all three operations are monotonic functions (preserving the order and cardinality of the set, i.e. 1-1 mapping) they are also inherently parallelizable (i.e. amenable to auto vectorization or loop unrolling).
|
August 03, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andre Artus | On Saturday, 3 August 2013 at 13:35:56 UTC, Andre Artus wrote:
> import std.stdio;
> import std.algorithm;
> void main()
> {
> auto values = [ 1, 2, 3, 4, 5 ];
> writeln(values
> .map!(a => a * 10)
> .map!(a => a / 3)
> .filter!(a => !(a % 2)));
> }
>
> As stated this implies 3 separate traversals of the list (or array to be specific) which is what a naïve implementation would do.
In this example, no, as all involved ranges are evaluated lazily. (I see your general point, though.)
David
|
August 03, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On Saturday, 3 August 2013 at 13:46:38 UTC, David Nadlinger wrote:
> On Saturday, 3 August 2013 at 13:35:56 UTC, Andre Artus wrote:
>> import std.stdio;
>> import std.algorithm;
>> void main()
>> {
>> auto values = [ 1, 2, 3, 4, 5 ];
>> writeln(values
>> .map!(a => a * 10)
>> .map!(a => a / 3)
>> .filter!(a => !(a % 2)));
>> }
>>
>> As stated this implies 3 separate traversals of the list (or array to be specific) which is what a naïve implementation would do.
>
> In this example, no, as all involved ranges are evaluated lazily. (I see your general point, though.)
>
> David
I probably could have worded it better: I did not intend to imply that D follows the naïve implementation suggested. What I meant is that, on the face of it, given typical textbook implementations of map and filter you would be iterating 3 separate times. To be clear I don't know of any serious implementations of these algorithms that do not address this in some way.
|
August 03, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On 8/3/2013 6:46 AM, David Nadlinger wrote:
> In this example, no, as all involved ranges are evaluated lazily. (I see your
> general point, though.)
The rules for ranges do not specify if they are done eagerly, lazily, or in parallel. Meaning, of course, that a library writer could provide all three forms and the user could select which one he wanted.
|
August 05, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Friday, 2 August 2013 at 05:26:05 UTC, H. S. Teoh wrote:
> On Thu, Aug 01, 2013 at 10:34:24AM -0700, Walter Bright wrote:
>> On 8/1/2013 2:23 AM, John Colvin wrote:
>> >On Thursday, 1 August 2013 at 00:47:43 UTC, H. S. Teoh wrote:
>> >Add in some code examples and that could make a nice article.
>>
>> Yes, please!
>
> Alright, so I decided to prove my point about component programming by
> actually writing a fully-functional version of the calendar layout
> program, so that I have a solid piece of evidence that component
> programming lives up to its promise. :) In addition, I decided that for
> maximum reusability, I want the output lines available in an input
> range, with absolutely no binding to writeln whatsoever (except in
> main() where the range is handed to writeln for output). In retrospect,
> that was perhaps a bit too ambitious... I ran into a few roadblocks to
> actually get the code working, so it took me a lot longer than I
> anticipated to finish the code.
>
> However, I *will* say that I'm very proud of the code: already there are
> a few pieces that, if properly cleaned up and refined, probably deserve
> inclusion in Phobos. Reusability FTW!! Now, just tell me if you've ever
> seen a calendar layout program made of straightforward, reusable pieces.
> I for sure haven't. I tried looking at the C code for the Unix cal
> program once... It looked frighteningly similar to an IOCCC entry. :-/
>
> My D version, however, built using ranges through and through, has many
> pieces that are easily reusable. For example, if you wanted to output
> only a single month instead, you could just call join("\n") on the range
> of formatted month lines that the full year layout algorithm uses to
> splice lines from multiple months together -- it's *that* reusable.
>
> Anyway. Enough hand-waving in the air. Let the actual code speak for
> itself:
>
> https://github.com/quickfur/dcal/blob/master/dcal.d
>
> Now, w.r.t. the roadblocks I alluded to.
>
> When I first started working on the code, my goal was to maximize usage
> of existing Phobos facilities in order to show how many batteries D
> already comes with. As it turned out, I could only use basic Phobos
> components; some of the more complex pieces like frontTransversal, which
> would've been perfect for the bit that splices formatted month lines
> together, couldn't be used because it wasn't flexible enough to handle
> the insertion of fillers when some subranges are empty. In the end, I
> had to code that range by hand, and I can't say I'm that happy with it
> yet. But at least, it's nothing compared to the hairy complexity of the
> C version of cal.
>
> Another place where I wanted to use existing Phobos components was
> chunkBy. There's probably a way to do it if you think hard enough about
> it, but in the end I felt it was simpler to just write the code myself.
> Might be a failure on my part to recognize how to put existing Phobos
> ranges in a clever enough way to achieve what I wanted. I did try to do
> something similar to byWeek(), but somehow it didn't do what I wanted
> and I decided to just code it by hand instead of investigating further.
>
> By far the biggest roadblock I ran into was that after I wrote
> everything up to (and including) pasteBlocks, my unittests refused to
> work. Somehow, pasteBlocks kept repeating the first line of the output
> (the month names, if you look at the unittest) and refused to advance
> farther. Eventually I traced the problem to Lines.popFront(), which
> pops each subrange off the range of ranges. The problem is that this
> only works on some ranges, but not others; if you pass the output of
> formatMonths() straight to pasteBlocks(), it will NOT work. Why? Because
> pasteBlocks return a std.algorithm.Map object, which recreates the
> subrange each time, so Lines.popFront() is only popping a temporary copy
> of the subrange, not the real thing. I was about to give up and try
> another approach, when out of the blue I decided to try and see if I
> could stuff the range returned by formatMonths() into an array, and then
> pass *that* to pasteBlocks() -- and behold, it worked!!
>
> This was a totally unexpected fix, that a newbie probably would never
> have thought of, so this is a potential trap for newcomers to D who
> expect components to just be pluggable. In retrospect, it makes sense --
> you need to somehow buffer the ranges of formatted month lines
> *somewhere* in order to be able to splice them together out of their
> natural depth-first outer/inner range order. But this is not obvious at
> all from first glance; perhaps it's a sign of a leaky abstraction
> somewhere. We should probably look into why this is happening and how to
> fix it. And there should be a way to test for this in pasteBlocks'
> signature constraint so that future code won't fall into the same trap,
> but I can't think of one right now.
>
> 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.
>
>
> T
Good work! I've read the article yesterday. Very educational!
|
August 10, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On Sat, Aug 03, 2013 at 04:12:58AM +0200, Timon Gehr wrote: > On 08/03/2013 01:05 AM, H. S. Teoh wrote: > > > >Actually, I just pulled git HEAD again, and it's still working fine. > >Maybe you just need to update your repo? > >... > > I think it pulled in the wrong version of druntime. OK, I've written a simple replacement for 2.063 std.range.chunks inside a static if (__VERSION__ <= 2063) block, so you should be able to compile it now. The code has been pushed to github. T -- It is of the new things that men tire --- of fashions and proposals and improvements and change. It is the old things that startle and intoxicate. It is the old things that are young. -- G.K. Chesterton |
August 10, 2013 Re: D component programming is a joke (Was: Re: Component programming) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dejan Lekic | On Mon, Aug 05, 2013 at 02:11:32PM +0200, Dejan Lekic wrote: [...] > Good work! I've read the article yesterday. Very educational! Thanks! I did actually make a major revision to the article last night based on some feedback I got; I rewrote much of the first part of it, so if you're interested you might want to re-read it. T -- Caffeine underflow. Brain dumped. |
August 12, 2013 Re: Component programming | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris | On Wednesday, 31 July 2013 at 10:20:57 UTC, Chris wrote: > This is only losely related to D, but I don't fully understand the separation of component programming and OOP What the wikipedia entry is saying, in a roundabout way is: All objects are components, but not all components are objects. whereas in pure OOP: All components are objects. > In an OO framwork, the objects are basically components. It's the other way around. In OOP frameworks, components are objects, a small but important distinction. If you relax the insistance on all components being objects, then OOP becomes a subset of CP (component programming). > Walter's example (http://www.drdobbs.com/architecture-and-design/component-programming-in-d/240008321) > > void main() { > stdin.byLine(KeepTerminator.yes) // 1 > map!(a => a.idup). // 2 > array. // 3 > sort. // 4 > copy( // 5 > stdout.lockingTextWriter()); // 6 > } This is a design pattern called "pipes and filters", or simply, the pipeline. There appears to be a bit of confusion about this. Pipelines are a part of CP, but is not the whole of CP. Pipelines make use of a type of component called a "service". At its simplest, a service is a function, but it could be a larger construct or even a whole program. Basically a service takes input, processes it (with a possible side effect) and gives a response (output). Often CP is defined as being exclusively about services, while other definitions include objects and OOP. Functional programming is exclusively service oriented. Purists would insist on using either objects or services exclusively (OOP vs FP), but there is nothing wrong with working with both. Back to pipelines. In a pipeline, you have a chain of services in which the output of one service is given as the input for the next. In mathematics it is called "functional composition". The pipeline itself is a service in its own right. You can put together a pipeline of any length as long as the output -> input interfaces are compatible. In Walter's article, he goes further to make all interfaces the same to make the components interchangeable, but this is not necessary in general. Hope this helps to explain a few things. Regards Jason |
August 19, 2013 Re: Component programming | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jason den Dulk | On Monday, 12 August 2013 at 12:28:36 UTC, Jason den Dulk wrote:
> On Wednesday, 31 July 2013 at 10:20:57 UTC, Chris wrote:
>> This is only losely related to D, but I don't fully understand the separation of component programming and OOP
>
> What the wikipedia entry is saying, in a roundabout way is:
>
> All objects are components, but not all components are objects.
>
> whereas in pure OOP:
>
> All components are objects.
>
>> In an OO framwork, the objects are basically components.
>
> It's the other way around. In OOP frameworks, components are objects, a small but important distinction. If you relax the insistance on all components being objects, then OOP becomes a subset of CP (component programming).
>
>> Walter's example (http://www.drdobbs.com/architecture-and-design/component-programming-in-d/240008321)
>>
>> void main() {
>> stdin.byLine(KeepTerminator.yes) // 1
>> map!(a => a.idup). // 2
>> array. // 3
>> sort. // 4
>> copy( // 5
>> stdout.lockingTextWriter()); // 6
>> }
>
> This is a design pattern called "pipes and filters", or simply, the pipeline. There appears to be a bit of confusion about this. Pipelines are a part of CP, but is not the whole of CP.
>
> Pipelines make use of a type of component called a "service". At its simplest, a service is a function, but it could be a larger construct or even a whole program. Basically a service takes input, processes it (with a possible side effect) and gives a response (output).
>
> Often CP is defined as being exclusively about services, while other definitions include objects and OOP. Functional programming is exclusively service oriented.
>
> Purists would insist on using either objects or services exclusively (OOP vs FP), but there is nothing wrong with working with both.
>
> Back to pipelines. In a pipeline, you have a chain of services in which the output of one service is given as the input for the next. In mathematics it is called "functional composition". The pipeline itself is a service in its own right. You can put together a pipeline of any length as long as the output -> input interfaces are compatible. In Walter's article, he goes further to make all interfaces the same to make the components interchangeable, but this is not necessary in general.
>
> Hope this helps to explain a few things.
> Regards
> Jason
Thanks for the explanation, Jason.
Btw, I got an error message compiling dcal.d with ldmd2
dcal.d(34): Error: no property 'recurrence' for type 'Date'
It compiles with dmd and works.
|
Copyright © 1999-2021 by the D Language Foundation