www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - C++ vs Lisp

reply Walter Bright <newshound1 digitalmars.com> writes:
An oldie, but some very thought provoking observations on what makes a 
language productive:

http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt
May 17 2008
next sibling parent janderson <askme me.com> writes:
Walter Bright wrote:
 An oldie, but some very thought provoking observations on what makes 
a language productive:
 
http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt I wonder how D would perform? It looks like D could be as almost as streamlined as lisp with its built-in containers. It seems to me though that size of a program isn't everything. As you said before, repetition helps reduce errors. I think D provides better mechanisms for abstraction then lisp. I think that D allows one to work on much larger problems more effectively then lisp. I think there in lies the trade off. If/when D gains functional programming it will have the best of both worlds. -Joel
May 17 2008
prev sibling next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Walter Bright:
 An oldie, but some very thought provoking observations on what makes a 
 language productive:
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt
Dear Walter, take a look at my libs, they are much better than the EasySTL he talks about: http://www.fantascienza.net/leonardo/so/libs_d.zip This was my version of that code, written when I was a D newbie (there are things I have to learn still), 26 lines long: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=57497 With my libs it becomes even shorter/simpler. Bye, bearophile
May 17 2008
parent reply Dee Girl <deegirl noreply.com> writes:
bearophile Wrote:

 Walter Bright:
 An oldie, but some very thought provoking observations on what makes a 
 language productive:
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt
Dear Walter, take a look at my libs, they are much better than the EasySTL he talks about: http://www.fantascienza.net/leonardo/so/libs_d.zip
You have send these libraries earlier to me. Thank you for that! It looks interesting. But one problem is you use delegates. They are much slower than alias. I measured 3 - 5 times slower depending on task. Another problem is simpler. The documentation is hard. Why you put a zip file on web and inside it has html files? It should be inverse. It would be good to put html pages on the web. Also there is no link in the html files. It is hard to understand what library is doing. I am sure the library is good. But package looks bad ^_^ Thank you, Dee Girl
May 17 2008
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Dee Girl:
 Thank you for that! It looks interesting.
My pleasure.
But one problem is you use delegates. They are much slower than alias.
I measured 3 - 5 times slower depending on task.
From my benchmarks they behave well enough, you probably talk about unusual tasks. My libs are designed for the (large!) parts of the code where you don't need max running speed. To improve the situation you may need compiler support for list comphrensions, etc and/or macros.
 The documentation is hard. Why you put a zip file on web and inside it has
html 
 files? It should be inverse. It would be good to put html pages on the web.
I see, you are right, and I can fix this problem.
 Also there is no link in the html files. It is hard to understand what library
is doing.
What do you mean? (If you spot bugs please tell me) Bye and thank you, bearophile
May 17 2008
parent reply Dee Girl <deegirl noreply.com> writes:
bearophile Wrote:

 Dee Girl:
 Thank you for that! It looks interesting.
My pleasure.
But one problem is you use delegates. They are much slower than alias.
I measured 3 - 5 times slower depending on task.
From my benchmarks they behave well enough, you probably talk about unusual tasks. My libs are designed for the (large!) parts of the code where you don't need max running speed. To improve the situation you may need compiler support for list comphrensions, etc and/or macros.
Simplest task was increment a value many times. On my computer is 3 times slow. Then tried simple functions like counting zeros in array of it. It was more 4 times slower. If I like this slow I code python ^_^ If there is different tradeoff to choose then I agree your argument is good. But with alias approach you have both static and dynamic. The support is already, no need for more. Why choose the bad way instead of good way?
 The documentation is hard. Why you put a zip file on web and inside it has
html 
 files? It should be inverse. It would be good to put html pages on the web.
I see, you are right, and I can fix this problem.
 Also there is no link in the html files. It is hard to understand what library
is doing.
What do you mean? (If you spot bugs please tell me)
It is only that there is no central page. Or I can not find it. No description of all library. No links between one document and other documents. I get bored ^_^ In phobos I can easy jump from algorithm to conv or functional. Thank you, Dee Girl
May 17 2008
parent bearophile <bearophileHUGS lycos.com> writes:
Dee Girl:
 Simplest task was increment a value many times. On my computer is 3 times
slow. Then tried simple functions like counting zeros in array of it. It was
more 4 times slower. If I like this slow I code python ^_^
For those very simple operations numpy is probably faster than anything you can do in D... (you probably need assembler to go a bit faster). But compared to Python and Psyco my D libs are generally faster or much faster :-) My libs are designed to be flexible, despite not being as fast as normal D code. In the usually very limited spots where you need max speed you can use normal D code. delegates/functions are quite more flexible than the things you talk about. And closures even more.
 It is only that there is no central page. Or I can not find it. No description
of all library. No links between one document and other documents. I get bored
^_^ In phobos I can easy jump from algorithm to conv or functional. Thank you,
Dee Girl
I see, and you are right, I can fix this too (currently the "central page" is the one of the 'func' module, it introduces to the whole lib). Bye and thank you, bearophile
May 17 2008
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Dee Girl" <deegirl noreply.com> wrote in message 
news:g0nfdd$1c2m$1 digitalmars.com...
 bearophile Wrote:

 Walter Bright:
 An oldie, but some very thought provoking observations on what makes a
 language productive:
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt
Dear Walter, take a look at my libs, they are much better than the EasySTL he talks about: http://www.fantascienza.net/leonardo/so/libs_d.zip
You have send these libraries earlier to me. Thank you for that! It looks interesting. But one problem is you use delegates. They are much slower than alias. I measured 3 - 5 times slower depending on task.
Can you give an example of what you mean by using alias instead of delegates?
May 17 2008
parent reply Dee Girl <deegirl noreply.com> writes:
Nick Sabalausky Wrote:

 "Dee Girl" <deegirl noreply.com> wrote in message 
 news:g0nfdd$1c2m$1 digitalmars.com...
 bearophile Wrote:

 Walter Bright:
 An oldie, but some very thought provoking observations on what makes a
 language productive:
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt
Dear Walter, take a look at my libs, they are much better than the EasySTL he talks about: http://www.fantascienza.net/leonardo/so/libs_d.zip
You have send these libraries earlier to me. Thank you for that! It looks interesting. But one problem is you use delegates. They are much slower than alias. I measured 3 - 5 times slower depending on task.
Can you give an example of what you mean by using alias instead of delegates?
There was long discussion here. Maybe you did not read. void slowbad(delegate void() f) { f(); } void fastgood(alias f)() { f(); } void main() { void f() { } slowbad(&f); fastgood!(f); } Syntax is different but power is very different. std.algorithm uses alias always. Everybody else uses slowbad ^_^ Dee Girl
May 17 2008
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Dee Girl:
 Syntax is different but power is very different. std.algorithm uses alias
always. Everybody else uses slowbad ^_^ Dee Girl
D supports simple function pointers too, and just only delegates, but I see your point. I'll think about it... Bye, bearophile
May 17 2008
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Dee Girl" <deegirl noreply.com> wrote in message 
news:g0noqa$2rpf$1 digitalmars.com...
 There was long discussion here. Maybe you did not read.
Didn't see it, must have been on a different thread.
 void slowbad(delegate void() f)
 {
    f();
 }

 void fastgood(alias f)()
 {
    f();
 }

 void main()
 {
    void f() { }
    slowbad(&f);
    fastgood!(f);
 }

 Syntax is different but power is very different. std.algorithm uses alias 
 always. Everybody else uses slowbad ^_^ Dee Girl
Isn't that akin to forcing a function to be inlined? It sounds to me like, just as with normal function inlining, there are cases where that could backfire because of things like increased cache misses or increased register consumption (or are those outdated problems with inlining?).
May 17 2008
parent reply janderson <askme me.com> writes:
Nick Sabalausky wrote:
 "Dee Girl" <deegirl noreply.com> wrote in message 
 news:g0noqa$2rpf$1 digitalmars.com...
 There was long discussion here. Maybe you did not read.
Didn't see it, must have been on a different thread.
 void slowbad(delegate void() f)
 {
    f();
 }

 void fastgood(alias f)()
 {
    f();
 }

 void main()
 {
    void f() { }
    slowbad(&f);
    fastgood!(f);
 }

 Syntax is different but power is very different. std.algorithm uses alias 
 always. Everybody else uses slowbad ^_^ Dee Girl
Isn't that akin to forcing a function to be inlined? It sounds to me like, just as with normal function inlining, there are cases where that could backfire because of things like increased cache misses or increased register consumption (or are those outdated problems with inlining?).
Only if the compiler decided to inline the contents of f function. Even then if the compiler can inline f's contents, its probably going to beable to reduce the size of the program size somewhat. Normally the compiler is going to get it right with inlining. The above template will boil down to: void main() { void f() { } slowbad(&f); //May or maynot be inlined f(); } As you can see f() is one function call less then slowbad and doesn't have to do any of the other stuff slowbad would. -Joel
May 17 2008
parent reply "Nick Sabalausky" <a a.a> writes:
"janderson" <askme me.com> wrote in message 
news:g0o03o$k01$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Dee Girl" <deegirl noreply.com> wrote in message 
 news:g0noqa$2rpf$1 digitalmars.com...
 There was long discussion here. Maybe you did not read.
Didn't see it, must have been on a different thread.
 void slowbad(delegate void() f)
 {
    f();
 }

 void fastgood(alias f)()
 {
    f();
 }

 void main()
 {
    void f() { }
    slowbad(&f);
    fastgood!(f);
 }

 Syntax is different but power is very different. std.algorithm uses 
 alias always. Everybody else uses slowbad ^_^ Dee Girl
Isn't that akin to forcing a function to be inlined? It sounds to me like, just as with normal function inlining, there are cases where that could backfire because of things like increased cache misses or increased register consumption (or are those outdated problems with inlining?).
Only if the compiler decided to inline the contents of f function. Even then if the compiler can inline f's contents, its probably going to beable to reduce the size of the program size somewhat. Normally the compiler is going to get it right with inlining. The above template will boil down to: void main() { void f() { } slowbad(&f); //May or maynot be inlined f(); } As you can see f() is one function call less then slowbad and doesn't have to do any of the other stuff slowbad would.
But fastgood() is always inlined, right?
May 18 2008
parent reply janderson <askme me.com> writes:
Nick Sabalausky wrote:
 "janderson" <askme me.com> wrote in message 
 news:g0o03o$k01$1 digitalmars.com...
 Nick Sabalausky wrote:
 "Dee Girl" <deegirl noreply.com> wrote in message 
 news:g0noqa$2rpf$1 digitalmars.com...
 There was long discussion here. Maybe you did not read.
Didn't see it, must have been on a different thread.
 void slowbad(delegate void() f)
 {
    f();
 }

 void fastgood(alias f)()
 {
    f();
 }

 void main()
 {
    void f() { }
    slowbad(&f);
    fastgood!(f);
 }

 Syntax is different but power is very different. std.algorithm uses 
 alias always. Everybody else uses slowbad ^_^ Dee Girl
Isn't that akin to forcing a function to be inlined? It sounds to me like, just as with normal function inlining, there are cases where that could backfire because of things like increased cache misses or increased register consumption (or are those outdated problems with inlining?).
Only if the compiler decided to inline the contents of f function. Even then if the compiler can inline f's contents, its probably going to beable to reduce the size of the program size somewhat. Normally the compiler is going to get it right with inlining. The above template will boil down to: void main() { void f() { } slowbad(&f); //May or maynot be inlined f(); } As you can see f() is one function call less then slowbad and doesn't have to do any of the other stuff slowbad would.
But fastgood() is always inlined, right?
You'd have to get Walters for the final word however I can't see why the compiler would generate another function for fastgood other then to speed up compiler performance for duplicate templates. If your worried about a long fastgood function being inlined, then I suggest that that template has been made to long. Also pre-premature optimisation is not a good thing. Do what works for you then optimize later. In my experience things like using delegates over templates rarely matter. That is because the size of the rest of the code dwarfs the runtime spent there. People will run benchmarks on the specific piece of code and get some impressive benchmarks but they don't try running it in real world code. Many times optimisation works against maintainability and flexibility, yet having highly flexible code is the key to being able to focus optimizations on the code that matters. Having said that, its nice to have these optimizations in the standard libraries because I figure that with 1000's of users, someones/everyones code is going to benefit from it. It is also true that heavy use of templates can slow down code speed just as heavy use of delegates. I think its up to the engineer to make the correct judgment call, particularly after they've run the profiler. -Joel
May 18 2008
parent reply Dee Girl <deegirl noreply.com> writes:
janderson Wrote:
 You'd have to get Walters for the final word however I can't see why the 
 compiler would generate another function for fastgood other then to 
 speed up compiler performance for duplicate templates.  If your worried 
 about a long fastgood function being inlined, then I suggest that that 
 template has been made to long.  Also pre-premature optimisation is not 
 a good thing.  Do what works for you then optimize later.
It is not about inlining. I think this is confusion again, same made in discussion with title safer casts. It is about template instantiation. Which can affect inlining but is very different thing.
 In my experience things like using delegates over templates rarely 
 matter.  That is because the size of the rest of the code dwarfs the 
 runtime spent there.  People will run benchmarks on the specific piece 
 of code and get some impressive benchmarks but they don't try running it 
 in real world code. 
If you see 4 times faster in a function then all program will not be 4 times faster. Of course. But many programs have little core operation. For example wc has at its core reading file, character comparison and loop. If core has 4 times slower function maybe the cost is much.
 Many times optimisation works against 
 maintainability and flexibility, yet having highly flexible code is the 
 key to being able to focus optimizations on the code that matters.
General observation is correct. But phobos algorithm and compose are good but not inflexible.
 Having said that, its nice to have these optimizations in the standard 
 libraries because I figure that with 1000's of users, someones/everyones 
 code is going to benefit from it.
 It is also true that heavy use of templates can slow down code speed 
 just as heavy use of delegates.  I think its up to the engineer to make 
 the correct judgment call, particularly after they've run the profiler.
If you have many template instantiation code is big. Big makes code slow because cache effect. But with template you can limit size because you can write slowbad to use fastgood. Then only one fastgood is instantiated. But if you start with slowbad is nothing you can do. Thank you, Dee Girl
May 18 2008
parent janderson <askme me.com> writes:
Dee Girl wrote:
 janderson Wrote:
 You'd have to get Walters for the final word however I can't see why the 
 compiler would generate another function for fastgood other then to 
 speed up compiler performance for duplicate templates.  If your worried 
 about a long fastgood function being inlined, then I suggest that that 
 template has been made to long.  Also pre-premature optimisation is not 
 a good thing.  Do what works for you then optimize later.
It is not about inlining. I think this is confusion again, same made in discussion with title safer casts. It is about template instantiation. Which can affect inlining but is very different thing.
This was in regards to Nicks question.
 
 In my experience things like using delegates over templates rarely 
 matter.  That is because the size of the rest of the code dwarfs the 
 runtime spent there.  People will run benchmarks on the specific piece 
 of code and get some impressive benchmarks but they don't try running it 
 in real world code. 
If you see 4 times faster in a function then all program will not be 4 times faster. Of course. But many programs have little core operation. For example wc has at its core reading file, character comparison and loop. If core has 4 times slower function maybe the cost is much.
I agree. Read the last paragraph. This is taken out of context.
 
 Many times optimisation works against 
 maintainability and flexibility, yet having highly flexible code is the 
 key to being able to focus optimizations on the code that matters.
General observation is correct. But phobos algorithm and compose are good but not inflexible.
I agree.
 
 Having said that, its nice to have these optimizations in the standard 
 libraries because I figure that with 1000's of users, someones/everyones 
 code is going to benefit from it.
 It is also true that heavy use of templates can slow down code speed 
 just as heavy use of delegates.  I think its up to the engineer to make 
 the correct judgment call, particularly after they've run the profiler.
If you have many template instantiation code is big. Big makes code slow because cache effect. But with template you can limit size because you can write slowbad to use fastgood. Then only one fastgood is instantiated. But if you start with slowbad is nothing you can do. Thank you, Dee Girl
I agree. Read first paragraph.
May 18 2008
prev sibling next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Walter Bright wrote:
 An oldie, but some very thought provoking observations on what makes a 
 language productive:
 
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt 
Concise does not always mean readable, and reducing lines of code should *never* be a design goal. For example, if I removed many temporary variables and used long expressions (as is the style in many functional languages), I could probably chop off 1/5-1/4 of the LOC of my program, but debugging/fixing it would get much harder. Additionally, redundancy (as stated in the ";" topic) is not necessarily a bad thing as it helps reinforce meaning to readers.
May 17 2008
next sibling parent Walter Bright <newshound1 digitalmars.com> writes:
Robert Fraser wrote:
 Concise does not always mean readable, and reducing lines of code should 
 *never* be a design goal. For example, if I removed many temporary 
 variables and used long expressions (as is the style in many functional 
 languages), I could probably chop off 1/5-1/4 of the LOC of my program, 
 but debugging/fixing it would get much harder. Additionally, redundancy 
 (as stated in the ";" topic) is not necessarily a bad thing as it helps 
 reinforce meaning to readers.
There's good redundancy, and there's bad redundancy: http://reddit.com/info/6ip9w/comments/ http://dobbscodetalk.com/index.php?option=com_myblog&show=Redundancy-in-Programming-Languages.html&Itemid=29
May 17 2008
prev sibling next sibling parent reply Neal Alexander <WQEQWEUQY HOTMAIL.COM> writes:
Robert Fraser wrote:
 Walter Bright wrote:
 An oldie, but some very thought provoking observations on what makes a 
 language productive:

 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt 
Concise does not always mean readable, and reducing lines of code should *never* be a design goal. For example, if I removed many temporary variables and used long expressions (as is the style in many functional languages), I could probably chop off 1/5-1/4 of the LOC of my program, but debugging/fixing it would get much harder. Additionally, redundancy (as stated in the ";" topic) is not necessarily a bad thing as it helps reinforce meaning to readers.
Dunno heh, some functional languages tend to have a much easier time with spreading dense logic into smaller segments. Its not about just packing in as much logic as you can per line. You show the high level interaction between functions and abstract away the gory details of the implementation. f x = write x =<< mutate =<< read x where mutatate list = do ...
May 17 2008
parent Georg Wrede <georg nospam.org> writes:
Neal Alexander wrote:
 Robert Fraser wrote:
 Walter Bright wrote:

 An oldie, but some very thought provoking observations on what makes 
 a language productive:

 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt 
Concise does not always mean readable, and reducing lines of code should *never* be a design goal. For example, if I removed many temporary variables and used long expressions (as is the style in many functional languages), I could probably chop off 1/5-1/4 of the LOC of my program, but debugging/fixing it would get much harder. Additionally, redundancy (as stated in the ";" topic) is not necessarily a bad thing as it helps reinforce meaning to readers.
Dunno heh, some functional languages tend to have a much easier time with spreading dense logic into smaller segments. Its not about just packing in as much logic as you can per line. You show the high level interaction between functions and abstract away the gory details of the implementation. f x = write x =<< mutate =<< read x where mutatate list = do ...
One of the reasons we have inner functions in D now.
Jun 11 2008
prev sibling parent Georg Wrede <georg nospam.org> writes:
Robert Fraser wrote:
 Walter Bright wrote:
 
 An oldie, but some very thought provoking observations on what
 makes a language productive:
 
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt
 
Concise does not always mean readable, and reducing lines of code should *never* be a design goal.
Correct!
 For example, if I removed many temporary variables and used long
 expressions (as is the style in many functional languages), I could
 probably chop off 1/5-1/4 of the LOC of my program, but
 debugging/fixing it would get much harder. Additionally, redundancy 
 (as stated in the ";" topic) is not necessarily a bad thing as it
 helps reinforce meaning to readers.
Too concise and non-redundant, and it becomes inintelligible. As an example, I looked up the Idiom Library by the Finnish APL-Association, (ISBN 951-95886-0-4), Helsinki 1984, in my bookshelf. Here's a routine that removes duplicate entries from an array: (1 1Q<\Xo.=X)/X And this is from the easy side. Of course, having a language where you can write a 20 page D program in 25 lines is nice and all. But debugging this stuff is way harder than debugging old Perl programs. The word Nightmare doesn't even begin to describe it. Anything you've written more than two days ago, you simply can't debug. You have to rewrite it. But what if it took ten days to write in the first place? The other option would be to splash comments all over the place, but then the stuff becomes just as long as D, and we all know how up-to-date the comments will be in reality. (And yes, I was impressed with the language for a month, but then using it for real started to turn my stomach.)
Jun 11 2008
prev sibling next sibling parent reply Neal Alexander <WQEQWEUQY HOTMAIL.COM> writes:
Walter Bright wrote:
 An oldie, but some very thought provoking observations on what makes a 
 language productive:
 
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt 
 
It'll be interesting to see where D goes with the functional stuff. Some nice things i think you should steal from Haskell: - One of the interesting things about programming/reading haskell code is how a function's definition is structured. Each "where" clause is like zooming in on a microscope or whatever. Most of the time you can just look at the top levels and understand what the function does without even looking at the inner definitions. This gives a lot of locality to the code. - Thinking in terms of map/fold/zip/recursion is really a lot nicer than manually looping. Once you write code that can deal with 1 instance, it pretty much automatically can be applied to multiple sequences without any real changes. - Function composition: (process . reverse . sort) list vs process(reverse(sort(list))) - Partially applied functions - Good type inference - The "Maybe" monad provides a clear transport for possible failure. One of the nice things about it is how you can force different error handling behaviors. Short circuit, Pattern Match exception etc. - Restricting mutability to the absolute bare minimum helps reason about behavior. D already has the groundwork for the large majority of these features, but unfortunately has to rely on template hacks. In my opinion, one of the worst problems with D is going through the template system for alot of the advanced features (currying, tuples etc). Its not as bad as Boost but still.
May 17 2008
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Neal Alexander" <WQEQWEUQY HOTMAIL.COM> wrote in message 
news:g0nha0$1s9l$1 digitalmars.com...
 - Function composition: (process . reverse . sort) list
 vs
 process(reverse(sort(list)))
Did you mean: (sort . reverse . process) list vs process(reverse(sort(list))) Or does Haskell put them in order of (last . first)? FWIW, I really like the style I've seen in some languages that's basically: list.sort().reverse().process() vs process(reverse(sort(list))) Which, I'm assuming is what you're talking about, but not certain.
May 17 2008
next sibling parent reply Neal Alexander <WQEQWEUQY HOTMAIL.COM> writes:
Nick Sabalausky wrote:
 "Neal Alexander" <WQEQWEUQY HOTMAIL.COM> wrote in message 
 news:g0nha0$1s9l$1 digitalmars.com...
 - Function composition: (process . reverse . sort) list
 vs
 process(reverse(sort(list)))
Did you mean: (sort . reverse . process) list vs process(reverse(sort(list))) Or does Haskell put them in order of (last . first)? FWIW, I really like the style I've seen in some languages that's basically: list.sort().reverse().process() vs process(reverse(sort(list))) Which, I'm assuming is what you're talking about, but not certain.
Nah its read right to left. "(f . g) x" is the same as "f (g x)" http://en.wikipedia.org/wiki/Function_composition_(computer_science) Anyway, its similar to list.sort().reverse().process() in that you can create pipelines like that. But its different in that it joins two functions to create a new one - without having to apply any arguments to it right away. list.sort().reverse().process() can be looked at as a Monad too i guess. "process =<< reverse =<< sort =<< return list" (right to left again - with sort, reverse, and process allowing side effects)
May 17 2008
parent Dee Girl <deegirl noreply.com> writes:
Neal Alexander Wrote:

 Nick Sabalausky wrote:
 "Neal Alexander" <WQEQWEUQY HOTMAIL.COM> wrote in message 
 news:g0nha0$1s9l$1 digitalmars.com...
 - Function composition: (process . reverse . sort) list
 vs
 process(reverse(sort(list)))
Did you mean: (sort . reverse . process) list vs process(reverse(sort(list))) Or does Haskell put them in order of (last . first)? FWIW, I really like the style I've seen in some languages that's basically: list.sort().reverse().process() vs process(reverse(sort(list))) Which, I'm assuming is what you're talking about, but not certain.
Nah its read right to left. "(f . g) x" is the same as "f (g x)" http://en.wikipedia.org/wiki/Function_composition_(computer_science) Anyway, its similar to list.sort().reverse().process() in that you can create pipelines like that. But its different in that it joins two functions to create a new one - without having to apply any arguments to it right away. list.sort().reverse().process() can be looked at as a Monad too i guess. "process =<< reverse =<< sort =<< return list" (right to left again - with sort, reverse, and process allowing side effects)
This is so beautiful in new pipe in std.functional. Because you can group intuitive left to right. And does good work as compose! I look at definition it is this: template pipe(fun...) { alias compose!(Reverse!(fun)) pipe; } I am not 100% sure but think there is no new function, just rename of compose. So no runtime work. Very nice. Dee Girl
May 17 2008
prev sibling parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Sat, 17 May 2008 23:45:40 +0200, Nick Sabalausky <a a.a> wrote:

 "Neal Alexander" <WQEQWEUQY HOTMAIL.COM> wrote in message
 news:g0nha0$1s9l$1 digitalmars.com...
 - Function composition: (process . reverse . sort) list
 vs
 process(reverse(sort(list)))
Did you mean: (sort . reverse . process) list vs process(reverse(sort(list))) Or does Haskell put them in order of (last . first)? FWIW, I really like the style I've seen in some languages that's basically: list.sort().reverse().process() vs process(reverse(sort(list))) Which, I'm assuming is what you're talking about, but not certain.
In D, you can* use list.sort.reverse.process or list.sort().reverse().process(), if you like parentheses. * "If the first parameter to a function is an array, the function can be called as if it were a property of the array" (http://www.digitalmars.com/d/2.0/arrays.html) -- Simen
May 18 2008
parent reply bearophile <bearophileHUGS lycos.com> writes:
Simen Kjaeraas:
 In D, you can* use list.sort.reverse.process or  
 list.sort().reverse().process(), if you like parentheses.
You must use parentheses there :-) Bye, bearophile
May 18 2008
parent reply Simen Kjaeraas <simen.kjaras gmail.com> writes:
bearophile Wrote:

 Simen Kjaeraas:
 In D, you can* use list.sort.reverse.process or  
 list.sort().reverse().process(), if you like parentheses.
You must use parentheses there :-)
Not according to my programs. Well, for process, maybe. I just tested with sort and reverse, which works without parentheses. -- Simen
May 19 2008
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Simen Kjaeraas wrote:
 bearophile Wrote:
 
 Simen Kjaeraas:
 In D, you can* use list.sort.reverse.process or  
 list.sort().reverse().process(), if you like parentheses.
You must use parentheses there :-)
Not according to my programs. Well, for process, maybe. I just tested with sort and reverse, which works without parentheses.
And if list is a built-in array, you must *not* use parentheses on sort and reverse. --bb
May 19 2008
parent reply "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Mon, 19 May 2008 17:01:28 +0200, Bill Baxter  
<dnewsgroup billbaxter.com> wrote:

 Simen Kjaeraas wrote:
 bearophile Wrote:

 Simen Kjaeraas:
 In D, you can* use list.sort.reverse.process or   
 list.sort().reverse().process(), if you like parentheses.
You must use parentheses there :-)
Not according to my programs. Well, for process, maybe. I just tested with sort and reverse, which works without parentheses.
And if list is a built-in array, you must *not* use parentheses on sort and reverse. --bb
And if the moon is in senit, and it's cloudy and tuesday?
May 19 2008
next sibling parent reply Robert Fraser <fraserofthenight gmail.com> writes:
Simen Kjaeraas wrote:
 On Mon, 19 May 2008 17:01:28 +0200, Bill Baxter 
 <dnewsgroup billbaxter.com> wrote:
 
 Simen Kjaeraas wrote:
 bearophile Wrote:

 Simen Kjaeraas:
 In D, you can* use list.sort.reverse.process or  
 list.sort().reverse().process(), if you like parentheses.
You must use parentheses there :-)
Not according to my programs. Well, for process, maybe. I just tested with sort and reverse, which works without parentheses.
And if list is a built-in array, you must *not* use parentheses on sort and reverse. --bb
And if the moon is in senit, and it's cloudy and tuesday?
Indeed, it's indeed a bit confusing. Sort and reverse are built-in array properties (so cannot have parentheses), while user or library-defined array functions can be called as members only with trailing parentheses. In my onion, sort and reverse should not be built-ins, since libraries (other than the runtime) can devise better algorithms for these things.
May 19 2008
parent "Janice Caron" <caron800 googlemail.com> writes:
2008/5/20 Robert Fraser <fraserofthenight gmail.com>:
 In my onion, sort and reverse should not be built-ins, since libraries
 (other than the runtime) can
and have
 devise better algorithms for these things.
std.algorithm.sort is way better than the built-in sort, for example, at least in D2. It's way time built-in sort was dropped.
May 19 2008
prev sibling parent renoX <renosky free.fr> writes:
Simen Kjaeraas a écrit :
 On Mon, 19 May 2008 17:01:28 +0200, Bill Baxter 
 <dnewsgroup billbaxter.com> wrote:
 Simen Kjaeraas wrote:
 bearophile Wrote:
 Simen Kjaeraas:
 In D, you can* use list.sort.reverse.process or  
 list.sort().reverse().process(), if you like parentheses.
You must use parentheses there :-)
Not according to my programs. Well, for process, maybe. I just tested with sort and reverse, which works without parentheses.
And if list is a built-in array, you must *not* use parentheses on sort and reverse. --bb
And if the moon is in senit, and it's cloudy and tuesday?
Agreed, 'properties' are in my book (well in OOSC book actually) a way to hide the distinction between attributes and functions, to go further in hiding implementation details both normal functions and member functions should be callable without (). Of course this means that to get the address of a function, you need a prefix operator(&), but this is a not so frequent operation.. Regards, renoX
May 24 2008
prev sibling parent Georg Wrede <georg nospam.org> writes:
Neal Alexander wrote:
 Walter Bright wrote:
 
 An oldie, but some very thought provoking observations on what makes a 
 language productive:

 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt 
It'll be interesting to see where D goes with the functional stuff. Some nice things i think you should steal from Haskell: - One of the interesting things about programming/reading haskell code is how a function's definition is structured. Each "where" clause is like zooming in on a microscope or whatever. Most of the time you can just look at the top levels and understand what the function does without even looking at the inner definitions. This gives a lot of locality to the code. - Thinking in terms of map/fold/zip/recursion is really a lot nicer than manually looping. Once you write code that can deal with 1 instance, it pretty much automatically can be applied to multiple sequences without any real changes. - Function composition: (process . reverse . sort) list vs process(reverse(sort(list))) - Partially applied functions - Good type inference - The "Maybe" monad provides a clear transport for possible failure. One of the nice things about it is how you can force different error handling behaviors. Short circuit, Pattern Match exception etc. - Restricting mutability to the absolute bare minimum helps reason about behavior. D already has the groundwork for the large majority of these features, but unfortunately has to rely on template hacks. In my opinion, one of the worst problems with D is going through the template system for alot of the advanced features (currying, tuples etc). Its not as bad as Boost but still.
At least D /has/ templates. And I suspect that once some template idiom becomes standard usage, Walter or Andrei may just decide to incorporate it into the language proper. Thus, we have a seeding bed indoors, and the plants that really start to grow, get planted in the garden so they can grow into strong trees. (Heh, organic growth. D should get an Environment Sticker!)
Jun 11 2008
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
Walter Bright wrote:
 An oldie, but some very thought provoking observations on what makes a 
 language productive:
 
 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt 
Interestingly, this same analysis was posted by Josh Stern in 2006 on D.announce. You were even involved in the ensuing discussion quite a bit :-) Sean
May 18 2008
parent Sean Kelly <sean invisibleduck.org> writes:
Sean Kelly wrote:
 Walter Bright wrote:
 An oldie, but some very thought provoking observations on what makes a 
 language productive:

 http://faculty.cs.byu.edu/~irenelg/courses/330/CTM/Resources/C++-vs-Lisp.txt 
Interestingly, this same analysis was posted by Josh Stern in 2006 on D.announce. You were even involved in the ensuing discussion quite a bit :-)
Oops! Seems you even created a webpage for it at the time. May be worth referencing: http://www.digitalmars.com/d/2.0/lisp-java-d.html Sean
May 18 2008