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 

 

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 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 
 

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.

"(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.

"(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.


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.


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 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.


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
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.


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 next sibling 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 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