www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A few comments about D

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/

Andrei
Aug 22 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/
What that person says about closures vs classes is silly. I don't fully understand what that person says about D arrays/strings, but I think it is not meaningful. On the other hand what that person says about "compile app.d" is right, the D compiler needs this feature. Bye, bearophile
Aug 22 2011
prev sibling next sibling parent reply "Marco Leise" <Marco.Leise gmx.de> writes:
Am 23.08.2011, 05:11 Uhr, schrieb Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org>:

 http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/

 Andrei
So I figure you want to collect some opinions. - Garbage collection: I do miss the purity of C here and wish it was really straight forward to switch between GC and manual memory management. The argument that "the program stops randomly" will die hard. - Delegates: They feel modern and can be put to good use. - One clear way to do things: Actually that is what I like about Java. But I understand that as soon as you mix programming paradigms the way D does there are multiple approaches. As an OO programmer I prefer interchangeable container classes and for operations on "ranges" there is your neat library implementation, which I find innovative. Now it just doesn't feel quite natural to bring them together. See also the talk about the use of reference type ranges. Practically all containers should work with the range API. - string built-in: What the heck is he talking about? I couldn't imagine a more light-weight string implementation. "the same thing with arrays" - he probably doesn't understand that they are the same. Anyway after all nothing would stop him from implementing an array wrapper class either working on built-in arrays or pointers, if he prefers. D's strings are the best that could have happened. (And I know Delphi has a similar approach.) - unit tests & ddoc: :D - only I'd like to see some more hierarchy in the documentation. The symbol list on top looks like a crime to me. - compile app.d: Nice to have. - Marco
Aug 23 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Marco Leise" <Marco.Leise gmx.de> wrote in message 
news:op.v0noz1q09y6py2 dslb-088-070-152-209.pools.arcor-ip.net...
 Am 23.08.2011, 05:11 Uhr, schrieb Andrei Alexandrescu 
 <SeeWebsiteForEmail erdani.org>:

 http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/

 Andrei
So I figure you want to collect some opinions. - Garbage collection: I do miss the purity of C here and wish it was really straight forward to switch between GC and manual memory management. The argument that "the program stops randomly" will die hard.
YES! I like the built-in GC, but a *systems language* needs to be good for games and embedded. And to be universally good at those, and *really* compete with C/C++ in those domains, it needs to be easy to guarantee no GC allocations. Can't do that right now without a world of pain. This is something I've been hoping for for a loooong time.
 - One clear way to do things:
Ugh. More and more I'm starting to find the Church of Python Zen to be a load of puritanical hogwash.
 - string built-in: What the heck is he talking about? I couldn't imagine a 
 more light-weight string implementation. "the same thing with arrays" - he 
 probably doesn't understand that they are the same. Anyway after all 
 nothing would stop him from implementing an array wrapper class either 
 working on built-in arrays or pointers, if he prefers. D's strings are the 
 best that could have happened. (And I know Delphi has a similar approach.)
Yea, the other thing he said about it that really raised my eyebrow was that "an array carries around no bounds information". Where the hell did he get that? And the whole "all of the functions that work with [strings] are just sitting around in the global namespace"...Uhh...what global namespace?
 - compile app.d: Nice to have.
Yup, that would be nice. That's why we already have it: rdmd --build-only -ofmyapp myapp.d Or if you *really* need it to be just one switch:
type dmdc.bat
echo off rdmd --build-only "-of%1" "%1.d"
Aug 23 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Maybe this idea is still up in the air:

"Walter Bright is considering adding a compile-time flag that would
banish all constructs that make implicit use of the GC, in which case
you'll know at compile time where the culprits are, and you can change
your code accordingly."

from http://www.informit.com/articles/article.aspx?p=1622265
Aug 23 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.2481.1314119920.14074.digitalmars-d puremagic.com...
 Maybe this idea is still up in the air:

 "Walter Bright is considering adding a compile-time flag that would
 banish all constructs that make implicit use of the GC, in which case
 you'll know at compile time where the culprits are, and you can change
 your code accordingly."

 from http://www.informit.com/articles/article.aspx?p=1622265
I certainly hope so. That's desperately needed for certain domains.
Aug 23 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 8/23/11, Nick Sabalausky <a a.a> wrote:
 I certainly hope so. That's desperately needed for certain domains.
It would be super-useful for audio programming. If someone were to write a VST audio plugin for use in some music sequencer (Ableton Live, Steinberg Cubase, etc), they would have to guarantee there are *zero* pauses while the plugin is processing audio. It /might/ be ok to do any collections when the plugin is idling, and there's a way to check that in the VST SDK. But the biggest concern to me are implicit calls to GC due to e.g. array concatenation. I was planning on making a D wrapper library for the VST protocol, but until this is sorted out I think I'll just stay away from it for now. I don't want to have fingers pointed at me when someone writes a VST plug that ends up crashing some user's sequencer due to a GC collection (and more likely than not the companies who make sequencers would get fingers pointed at, which is bad).
Aug 23 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.2482.1314125320.14074.digitalmars-d puremagic.com...
 On 8/23/11, Nick Sabalausky <a a.a> wrote:
 I certainly hope so. That's desperately needed for certain domains.
It would be super-useful for audio programming. If someone were to write a VST audio plugin for use in some music sequencer (Ableton Live, Steinberg Cubase, etc), they would have to guarantee there are *zero* pauses while the plugin is processing audio. It /might/ be ok to do any collections when the plugin is idling, and there's a way to check that in the VST SDK. But the biggest concern to me are implicit calls to GC due to e.g. array concatenation. I was planning on making a D wrapper library for the VST protocol, but until this is sorted out I think I'll just stay away from it for now. I don't want to have fingers pointed at me when someone writes a VST plug that ends up crashing some user's sequencer due to a GC collection (and more likely than not the companies who make sequencers would get fingers pointed at, which is bad).
Yea. Basically anything real-time. That and many low-memory situations (since it's a copying collector).
Aug 23 2011
parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
Hi,


languages
with GC.

You just need to provide a systems module that allows you to control memory 
allocations
when time is needed. Or to know where the memory allocations are happening.

--
Paulo

"Nick Sabalausky" <a a.a> wrote in message 
news:j30thv$14qo$1 digitalmars.com...
 "Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
 news:mailman.2482.1314125320.14074.digitalmars-d puremagic.com...
 On 8/23/11, Nick Sabalausky <a a.a> wrote:
 I certainly hope so. That's desperately needed for certain domains.
It would be super-useful for audio programming. If someone were to write a VST audio plugin for use in some music sequencer (Ableton Live, Steinberg Cubase, etc), they would have to guarantee there are *zero* pauses while the plugin is processing audio. It /might/ be ok to do any collections when the plugin is idling, and there's a way to check that in the VST SDK. But the biggest concern to me are implicit calls to GC due to e.g. array concatenation. I was planning on making a D wrapper library for the VST protocol, but until this is sorted out I think I'll just stay away from it for now. I don't want to have fingers pointed at me when someone writes a VST plug that ends up crashing some user's sequencer due to a GC collection (and more likely than not the companies who make sequencers would get fingers pointed at, which is bad).
Yea. Basically anything real-time. That and many low-memory situations (since it's a copying collector).
Aug 23 2011
next sibling parent foo <foo bar.com> writes:
== Quote from Paulo Pinto (pjmlp progtools.org)'s article
 Hi,

 languages
 with GC.
 You just need to provide a systems module that allows you to control memory
 allocations
 when time is needed. Or to know where the memory allocations are happening.
Or, you know, just use one of those common languages like Java. There is nothing special required from a language to support real-time. It's just a matter of providing a collector that supports real-time guaranties, e.g. like those Sun (now Oracle) sells.
Aug 23 2011
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/23/2011 09:17 PM, Paulo Pinto wrote:
 Hi,


 languages
 with GC.

 You just need to provide a systems module that allows you to control memory
 allocations
 when time is needed. Or to know where the memory allocations are happening.

 --
 Paulo
There is an interface like this in core.memory .
Aug 23 2011
prev sibling parent reply Rainer Schuetze <r.sagitario gmx.de> writes:
On 23.08.2011 20:48, Andrej Mitrovic wrote:
 On 8/23/11, Nick Sabalausky<a a.a>  wrote:
 I certainly hope so. That's desperately needed for certain domains.
It would be super-useful for audio programming. If someone were to write a VST audio plugin for use in some music sequencer (Ableton Live, Steinberg Cubase, etc), they would have to guarantee there are *zero* pauses while the plugin is processing audio. It /might/ be ok to do any collections when the plugin is idling, and there's a way to check that in the VST SDK. But the biggest concern to me are implicit calls to GC due to e.g. array concatenation. I was planning on making a D wrapper library for the VST protocol, but until this is sorted out I think I'll just stay away from it for now. I don't want to have fingers pointed at me when someone writes a VST plug that ends up crashing some user's sequencer due to a GC collection (and more likely than not the companies who make sequencers would get fingers pointed at, which is bad).
A way to deal with this could be done in the runtime library, allowing to set a flag for the real time thread, that excludes it from being suspended in a garbage collection. It is then the responsiblity of the developer to ensure that any GC data used in the realtime thread is also referenced elsewhere. Another flag might cause any (possibly blocking) GC calls to bail out if it is called from within this thread. This is no perfect compiler guarantee, but at least a runtime check for the thread not depending on a GC lock.
Aug 23 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 12:24 AM, Rainer Schuetze wrote:
 On 23.08.2011 20:48, Andrej Mitrovic wrote:
 On 8/23/11, Nick Sabalausky<a a.a> wrote:
 I certainly hope so. That's desperately needed for certain domains.
It would be super-useful for audio programming. If someone were to write a VST audio plugin for use in some music sequencer (Ableton Live, Steinberg Cubase, etc), they would have to guarantee there are *zero* pauses while the plugin is processing audio. It /might/ be ok to do any collections when the plugin is idling, and there's a way to check that in the VST SDK. But the biggest concern to me are implicit calls to GC due to e.g. array concatenation. I was planning on making a D wrapper library for the VST protocol, but until this is sorted out I think I'll just stay away from it for now. I don't want to have fingers pointed at me when someone writes a VST plug that ends up crashing some user's sequencer due to a GC collection (and more likely than not the companies who make sequencers would get fingers pointed at, which is bad).
A way to deal with this could be done in the runtime library, allowing to set a flag for the real time thread, that excludes it from being suspended in a garbage collection. It is then the responsiblity of the developer to ensure that any GC data used in the realtime thread is also referenced elsewhere.
Basically, afaik you can already get that now. It suffices not to register the new thread with the GC. (I don't know if core does provide an interface for this) The thread then has to use manual memory management.
 Another flag might cause any (possibly blocking) GC calls to bail out if
 it is called from within this thread. This is no perfect compiler
 guarantee, but at least a runtime check for the thread not depending on
 a GC lock.
Aug 23 2011
parent Rainer Schuetze <r.sagitario gmx.de> writes:
On 24.08.2011 01:19, Timon Gehr wrote:
 On 08/24/2011 12:24 AM, Rainer Schuetze wrote:
 A way to deal with this could be done in the runtime library, allowing
 to set a flag for the real time thread, that excludes it from being
 suspended in a garbage collection. It is then the responsiblity of the
 developer to ensure that any GC data used in the realtime thread is also
 referenced elsewhere.
Basically, afaik you can already get that now. It suffices not to register the new thread with the GC. (I don't know if core does provide an interface for this) The thread then has to use manual memory management.
I know there is the suggestion to use the C thread creation functions instead if you don't want to interact with the GC, but I don't think it works well: - you need more thread initialization than just GC, e.g. TLS. - you might want to setup the thread with GC, then disable it for any further processing - a VST plugin is a DLL, and you are usually not the creator of the threads. The DLL initialization code attaches to all threads and adds them to the thread pool. You'll probably need control over which threads to suspend in a collection, and which threads are not allowed to use the GC.
Aug 23 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

"Walter Bright is considering adding a compile-time flag that would banish all
constructs that make implicit use of the GC, in which case you'll know at
compile time where the culprits are, and you can change your code accordingly."<
I think producing an error for each GC allocation in the current compilation unit is a bit harsh. To face this kind of problems I (with ideas from other people) have suggested (both are in Bugzilla with more explanations): 1) A transitive attribute like noheap (or maybe nogcheap) that statically disallows GC allocations inside a function (and the functions it calls), so they become errors. (Don doesn't like this idea much, I don't know why). Even better is to give the library programmer the tools to create a noheap by herself. This means introducing user-defined attributes in D2 and adding more static introspection, to allow the implementation & running of this recursive testing code at compile time (maybe Don appreciates this idea more). 2) A compiler switch that produces a warning for each line of code where there is a closure allocation on the heap. A variant of this idea is to produce a warning for each line of code that causes a GC allocation. Bye, bearophile
Aug 23 2011
parent dsimcha <dsimcha yahoo.com> writes:
On 8/23/2011 8:20 PM, bearophile wrote:
 1) A transitive attribute like  noheap (or maybe  nogcheap) that statically
disallows GC allocations inside a function (and the functions it calls), so
they become errors.
The main problem I see with this is that realistically library writers aren't going to bother to mark every function that doesn't heap allocate noheap. Therefore, in practice something like this would be extremely conservative.
Aug 23 2011
prev sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Nick Sabalausky Wrote:

 Yea, the other thing he said about it that really raised my eyebrow was that 
 "an array carries around no bounds information". Where the hell did he get 
 that?
This one threw me for a bit. What he is saying is that D tried to improve on the "an array carries no bounds information" by including bounds for arrays. He thinks it is better to wrap it in the class/struct to handle it. As he said he likes C/C++ and just wants the syntax cleaned up, not additions to the language... I don't agree... He misses the point that then everyone must provide a proper wrapper around their array operations.
 And the whole "all of the functions that work with [strings] are just 
 sitting around in the global namespace"...Uhh...what global namespace?
As I implied he wants all operations bundled up in a String class. But yeah, there isn't a global namespace.
Aug 23 2011
prev sibling next sibling parent reply "Paulo Pinto" <pjmlp progtools.org> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message
news:j2v5oc$12i1$1 digitalmars.com...
 http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/

 Andrei
Hi, I also don't use D, being more of a lurker in Go and D forums, wondering when a better systems language will eventual replace C and C++. I am also language agnostic, I use C, C++, JVM languages, .Net languages, whatever is required/requested by the current project. Regarding the forum question and using a format similar to Marco's answer: - Garbage collection: Since the late 90's there are research operating systems written with system programming languages that are 100% GC enabled. No issue here for me, except to say that it needs to be improved and the way D enables pointers, leaves out many GC optimization algorithms. - Delegates: The only problem I see is that D provides two ways of specifing delegates.one being D only and the other one for C/C++ interfacing. This might confuse people. - unit tests/ddoc - There are plus and minus for having in the compiler, personally I prefer to have such type of features in tools or libraries. - compile app.d - I see this as a very nice feature. I was spoiled by Turbo Pascal which did already something similar in the MS-DOS days. - the language is still not mature - Andrei's book still does not fully replace the language and when one browses the mailing lists there are still quite a few features being discussed, not clear enough what the direction ought to be. For me as a language geek, it is understandable that these things take time, but they cause a bad impression for people considering to use D. even Haskell on a new project than D, because there are quite a few big companies/projects using them. With lots of war stories how these languages helped their companies become more sucessfull, in all major developer conferences. Marketing pays off. -- Paulo
Aug 23 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Paulo Pinto:

 - the language is still not mature - Andrei's book still does not fully 
 replace the language and
 when one browses the mailing lists there are still quite a few features 
 being discussed, not clear
 enough what the direction ought to be.
It's the other way round. Those discussions are a sign of good health for any language, they are necessary. Every language actively used has similar discussions, even Fortran and Ada. See as example: http://mail.python.org/pipermail/python-ideas/


 even Haskell on a new project than D, because there are quite a few big 
 companies/projects using them.
Haskell was created as "laboratory language", and today it has more design discussions than D still :-) Bye, bearophile
Aug 23 2011
next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:j300i9$2io2$1 digitalmars.com...
 Paulo Pinto:

 - the language is still not mature - Andrei's book still does not fully
 replace the language and
 when one browses the mailing lists there are still quite a few features
 being discussed, not clear
 enough what the direction ought to be.
It's the other way round. Those discussions are a sign of good health for any language, they are necessary. Every language actively used has similar discussions, even Fortran and Ada. See as example: http://mail.python.org/pipermail/python-ideas/
In Python's case ideas which end up in PEPs.

 approval

 even Haskell on a new project than D, because there are quite a few big
 companies/projects using them.
Haskell was created as "laboratory language", and today it has more design discussions than D still :-) Bye, bearophile
True, but if I mention Haskell-98 or Haskell-2010, I am sure that there are compilers on the wild that support such standard. While D has a semi-official standard, Andrei's book, that does not map to any existing compiler. You don't need to convice me, I know the benefits of D. You need however to convince people that come to D forums and leave conviced that the language is not mature enough for what they want to use it. -- Paulo
Aug 23 2011
prev sibling parent reply Caligo <iteronvexor gmail.com> writes:
On Tue, Aug 23, 2011 at 5:48 AM, bearophile <bearophileHUGS lycos.com>wrote:

 Paulo Pinto:

 - the language is still not mature - Andrei's book still does not fully
 replace the language and
 when one browses the mailing lists there are still quite a few features
 being discussed, not clear
 enough what the direction ought to be.
It's the other way round. Those discussions are a sign of good health for any language, they are necessary. Every language actively used has similar discussions, even Fortran and Ada. See as example: http://mail.python.org/pipermail/python-ideas/

approval

 even Haskell on a new project than D, because there are quite a few big
 companies/projects using them.
Haskell was created as "laboratory language", and today it has more design discussions than D still :-) Bye, bearophile
Haskell is one of the most beautiful languages. I wish I had discovered it sooner.
Aug 23 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Caligo:

 Haskell is one of the most beautiful languages. I wish I had discovered it
sooner.
I am now able to write small Haskell programs. It has some features and parts that I like significantly (and I'd like some of them in D too!), but so far I am not appreciating it much on the whole. It feels almost like a "puzzle language", as Forth (almost, but not really). Those operators are not easy to find in the documentation, the purpose of all those little functions is not easy to remember, and its obsession with purity sometimes turns easy things into very complex things (I like purity and immutability, but not much inside functions, so I prefer D). It's good for some kinds of tasks (Euler Puzzles, certain math tasks, certain experiments about types), acceptable for other tasks (some generic algorithms, some string processing, etc), and bad for many other purposes, so it doesn't feel like a general purpose language. I am sometimes able to write very short programs with it, but often they are slow. It's not easy for me to tell how much efficient a program will be, once compiled with GHC. Keep in mind that I am a newbie of Haskell, so don't take my comments too much seriously :-) Bye, bearophile
Aug 24 2011
next sibling parent "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:j32mti$15tp$1 digitalmars.com...
 Caligo:

 Haskell is one of the most beautiful languages. I wish I had discovered 
 it sooner.
I am now able to write small Haskell programs. It has some features and parts that I like significantly (and I'd like some of them in D too!), but so far I am not appreciating it much on the whole. It feels almost like a "puzzle language", as Forth (almost, but not really). Those operators are not easy to find in the documentation, the purpose of all those little functions is not easy to remember, and its obsession with purity sometimes turns easy things into very complex things (I like purity and immutability, but not much inside functions, so I prefer D). It's good for some kinds of tasks (Euler Puzzles, certain math tasks, certain experiments about types), acceptable for other tasks (some generic algorithms, some string processing, etc), and bad for many other purposes, so it doesn't feel like a general purpose language. I am sometimes able to write very short programs with it, but often they are slow. It's not easy for me to tell how much efficient a program will be, once compiled with GHC. Keep in mind that I am a newbie of Haskell, so don't take my comments too much seriously :-)
Totally agree (and I like your comparion to Forth and the description "puzzle language"). Haskell is what proved to me that functional programming should be a feature of an imperative language, but not the fundamental nature of a language. (FWIW, Smalltalk (and to a much lesser extent, Java) proved the same to me about OO...and LISP with lists...JS with minimalism...ok, I'll stop now...Basically I just don't like pure/"beautiful" languages. They're pretty, but not practical.)
Aug 24 2011
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, August 24, 2011 04:22 bearophile wrote:
 Caligo:
 Haskell is one of the most beautiful languages. I wish I had discovered
 it sooner.
I am now able to write small Haskell programs. It has some features and parts that I like significantly (and I'd like some of them in D too!), but so far I am not appreciating it much on the whole. It feels almost like a "puzzle language", as Forth (almost, but not really). Those operators are not easy to find in the documentation, the purpose of all those little functions is not easy to remember, and its obsession with purity sometimes turns easy things into very complex things (I like purity and immutability, but not much inside functions, so I prefer D). It's good for some kinds of tasks (Euler Puzzles, certain math tasks, certain experiments about types), acceptable for other tasks (some generic algorithms, some string processing, etc), and bad for many other purposes, so it doesn't feel like a general purpose language. I am sometimes able to write very short programs with it, but often they are slow. It's not easy for me to tell how much efficient a program will be, onc! e compiled with GHC. Keep in mind that I am a newbie of Haskell, so don't take my comments too much seriously :-)
I like Haskell and have used it a fair bit, but I don't use it a lot these days. I think that every serious programmer should study and learn at least one functional language. Learning to think functionally can have be very helpful even in imperative programming and will make you a better programmer. And on top of the kind of stuff that it normally helps with (like understanding recursion), in D it helps when dealing with ranges, since ranges can be processed like slists a lot of the time. However, as much as I like Haskell, I find it very hard to work with on anything large, and even smaller stuff can be difficult. It just requires too much brain-bending to figure out how to do something purely functionally for it to be easy, and Haskell's laziness makes debugging it very difficult. So, I definitely recommend learning a functional lanugage (and Haskell is a good one), but I wouldn't program in it as my primary language. The main reason that I've used it as much as I have is that it has a fantastic parsing library (Parsec). And actually, I've been working on trying to port it to D, though it'll probably be a while before I finish it, and the lack of laziness could actually be a performance impediment in this case, since you risk having to copy the parsing state too often. Hopefully I can get that sorted out though. I still have a ways to go with it regardless. - Jonathan M Davis
Aug 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 08:19 PM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 04:22 bearophile wrote:
 Caligo:
 Haskell is one of the most beautiful languages. I wish I had discovered
 it sooner.
I am now able to write small Haskell programs. It has some features and parts that I like significantly (and I'd like some of them in D too!), but so far I am not appreciating it much on the whole. It feels almost like a "puzzle language", as Forth (almost, but not really). Those operators are not easy to find in the documentation, the purpose of all those little functions is not easy to remember, and its obsession with purity sometimes turns easy things into very complex things (I like purity and immutability, but not much inside functions, so I prefer D). It's good for some kinds of tasks (Euler Puzzles, certain math tasks, certain experiments about types), acceptable for other tasks (some generic algorithms, some string processing, etc), and bad for many other purposes, so it doesn't feel like a general purpose language. I am sometimes able to write very short programs with it, but often they are slow. It's not easy for me to tell how much efficient a program will be, onc! e compiled with GHC. Keep in mind that I am a newbie of Haskell, so don't take my comments too much seriously :-)
I like Haskell and have used it a fair bit, but I don't use it a lot these days. I think that every serious programmer should study and learn at least one functional language. Learning to think functionally can have be very helpful even in imperative programming and will make you a better programmer. And on top of the kind of stuff that it normally helps with (like understanding recursion), in D it helps when dealing with ranges, since ranges can be processed like slists a lot of the time. However, as much as I like Haskell, I find it very hard to work with on anything large, and even smaller stuff can be difficult. It just requires too much brain-bending to figure out how to do something purely functionally for it to be easy, and Haskell's laziness makes debugging it very difficult. So, I definitely recommend learning a functional lanugage (and Haskell is a good one), but I wouldn't program in it as my primary language. The main reason that I've used it as much as I have is that it has a fantastic parsing library (Parsec). And actually, I've been working on trying to port it to D, though it'll probably be a while before I finish it, and the lack of laziness could actually be a performance impediment in this case, since you risk having to copy the parsing state too often. Hopefully I can get that sorted out though. I still have a ways to go with it regardless. - Jonathan M Davis
I have implemented runtime lazy lists on top of delegates as a toy project. I have also written some utility lazy functions, a purely functional lazy merge sort to sort the lists and a recursively defined fibonacci list that works in O(n). Unfortunately it is about 10 times slower than haskell. :) And the syntax sucks, much owed to http://d.puremagic.com/issues/show_bug.cgi?id=6260 If anyone is interested: http://pastebin.com/2rEdx0RD
Aug 24 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable". Are you able to use it to translate the Haskell version of this task? http://rosettacode.org/wiki/Hamming_numbers#Haskell Bye, bearophile
Aug 24 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:

 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
Aug 24 2011
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 Statement at line 40 is necessary to make 
 the /type inference/ work out, and such things are the reason I don't 
 usually turn warnings on.
I think this fools DMD, and removes the warning: return assert(0, "Tried to get tail of empty list!"), List.init; (Your coding style is really compact.)
  Another example where warnings are a pita:
 
 case "bla","blu","blo": // Warning: fallthrough
 case "xxx","yyy","zzz":
 
 What the code expresses is: There are two cases, one occurs if the input 
 is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those 
 cases should be handled the same way. (At least for now).
 goto case; is both unnecessary and ugly in that case.
Are you sure the DMD head gives a warning in that case? This program shows me no warnings: void main() { int c; switch (c) { case 1: case 2: break; default: break; } } Bye, bearophile
Aug 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 01:36 AM, bearophile wrote:
 Timon Gehr:

 Statement at line 40 is necessary to make
 the /type inference/ work out, and such things are the reason I don't
 usually turn warnings on.
I think this fools DMD, and removes the warning: return assert(0, "Tried to get tail of empty list!"), List.init;
Thank you, that works. But I generally don't want to be fighting with the D compiler, that is what C++ is for. x)
 (Your coding style is really compact.)
It is especially compact in that program, because it is almost purely functional code. But it is true that there are typically many inline delegates in my code, that is why I have asked for more concise ones.
   Another example where warnings are a pita:

 case "bla","blu","blo": // Warning: fallthrough
 case "xxx","yyy","zzz":

 What the code expresses is: There are two cases, one occurs if the input
 is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those
 cases should be handled the same way. (At least for now).
 goto case; is both unnecessary and ugly in that case.
Are you sure the DMD head gives a warning in that case?
I am always waiting for releases, because I am too lazy to install the compiler myself. :) (polluting my path is not an option)
 This program shows me no warnings:

 void main() {
      int c;
      switch (c) {
          case 1:
          case 2: break;
          default: break;
      }
 }
Same for me, but try this: void main() { int c; switch (c) { case 1,2: case 3,4: break; default: break; } } I am starting to think this is not as intended.
Aug 24 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 It is especially compact in that program,
The coding style of that program is an unreadable mess, example: LList!T hamming(T)(){ LList!T merge(LList!T xs, LList!T ys){ return lz({ auto x=xs.head, y=ys.head; if(x()<y()) return cons(x,merge(xs.tail,ys))(); else if(x()>y()) return cons(y,merge(xs,ys.tail))(); else return cons(x,merge(xs.tail,ys.tail))(); }); } return lz({ LList!T r; r=cons(st(1),lz({return merge(merge(map((Lazy!T a){return lz({return 2*a();});},r),map((Lazy!T a){return lz({return 3*a();});},r)),map((Lazy!T a){return lz({return 5*a();});},r))();})); return r(); }); } This is a bit better: LList!T hamming(T)() { static LList!T merge(LList!T xs, LList!T ys) { return lz({ auto x = xs.head; auto y = ys.head; if (x() < y()) return cons(x, merge(xs.tail, ys))(); else if (x() > y()) return cons(y, merge(xs, ys.tail))(); else return cons(x, merge(xs.tail, ys.tail))(); }); } return lz({ LList!T r; r = cons(st(BigInt(1)), lz({ return merge(merge(map((Lazy!T a){ return lz({ return 2 * a(); }); }, r), map((Lazy!T a){ return lz({ return 3 * a(); }); }, r)), map((Lazy!T a){ return lz({ return 5 * a(); }); }, r))(); })); return r(); }); }
 I am starting to think this is not as intended.
I think it's a DMD bug. Fit for Bugzilla.
 I cannot seem to find it, but I'd like to vote on it. Do you have a link?
I have updated this: http://d.puremagic.com/issues/show_bug.cgi?id=5970 Bye, bearophile
Aug 24 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 04:08 AM, bearophile wrote:
 Timon Gehr:

 It is especially compact in that program,
The coding style of that program is an unreadable mess, example: LList!T hamming(T)(){ LList!T merge(LList!T xs, LList!T ys){ return lz({ auto x=xs.head, y=ys.head; if(x()<y()) return cons(x,merge(xs.tail,ys))(); else if(x()>y()) return cons(y,merge(xs,ys.tail))(); else return cons(x,merge(xs.tail,ys.tail))(); }); } return lz({ LList!T r; r=cons(st(1),lz({return merge(merge(map((Lazy!T a){return lz({return 2*a();});},r),map((Lazy!T a){return lz({return 3*a();});},r)),map((Lazy!T a){return lz({return 5*a();});},r))();})); return r(); }); } This is a bit better: LList!T hamming(T)() { static LList!T merge(LList!T xs, LList!T ys) { return lz({ auto x = xs.head; auto y = ys.head; if (x()< y()) return cons(x, merge(xs.tail, ys))(); else if (x()> y()) return cons(y, merge(xs, ys.tail))(); else return cons(x, merge(xs.tail, ys.tail))(); }); } return lz({ LList!T r; r = cons(st(BigInt(1)), lz({ return merge(merge(map((Lazy!T a){ return lz({ return 2 * a(); }); }, r), map((Lazy!T a){ return lz({ return 3 * a(); }); }, r)), map((Lazy!T a){ return lz({ return 5 * a(); }); }, r))(); })); return r(); }); }
Well, the main reason it is an unreadable mess is the bug with lazy and closures I reported, and I think inserting whitespace does not necessarily make the code better readable. (I like especially the first half of the code snippet better in the format I provided) I usually do not spend much time to format my code, especially if like here the end result is not significantly better readable. Maybe code formatting should be automated completely via a dedicated tool.
 I am starting to think this is not as intended.
I think it's a DMD bug. Fit for Bugzilla.
See http://d.puremagic.com/issues/show_bug.cgi?id=6552
 I cannot seem to find it, but I'd like to vote on it. Do you have a link?
I have updated this: http://d.puremagic.com/issues/show_bug.cgi?id=5970
Thanks.
Aug 24 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 01:15 AM, Timon Gehr wrote:
 On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:

 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
ASDF. I got it working quite fast, and then I started a fight with std.bigint.BigInt.toString until I accidentally cp'd over my source code. That will be reported soon, it makes BigInt UNUSABLE. I am going to code it again...
Aug 24 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, August 24, 2011 17:17 Timon Gehr wrote:
 On 08/25/2011 01:15 AM, Timon Gehr wrote:
 On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:
 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
ASDF. I got it working quite fast, and then I started a fight with std.bigint.BigInt.toString until I accidentally cp'd over my source code. That will be reported soon, it makes BigInt UNUSABLE. I am going to code it again...
Don refuses to implement it, because it always creates a new string. He wants something like the DIP for writeFrom (or whatever the exact function name was) which allows for writing to a pre-existing buffer. I think that there's already a bug on the issue, but I'd have to search for it. - Jonathan M Davis
Aug 24 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 02:34 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:17 Timon Gehr wrote:
 On 08/25/2011 01:15 AM, Timon Gehr wrote:
 On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:
 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
ASDF. I got it working quite fast, and then I started a fight with std.bigint.BigInt.toString until I accidentally cp'd over my source code. That will be reported soon, it makes BigInt UNUSABLE. I am going to code it again...
Don refuses to implement it, because it always creates a new string. He wants something like the DIP for writeFrom (or whatever the exact function name was) which allows for writing to a pre-existing buffer. I think that there's already a bug on the issue, but I'd have to search for it. - Jonathan M Davis
We must just add _*RVO for arrays*_ to the compiler and then users can use the built-in array concatenation syntax for the efficient thing. Everything else would just waste the precious grammar rules. How it is now is just painful and it does not fit well into the rest of Phobos. Not even std.conv.to can convert a BigInt to a string. This is a trivial issue that renders std.bigint unusable for these kinds of little scripts, where they actually would be of use. I don't care if I get a newly allocated string, because I only convert it once to output it. The current design just hurts me everywhere, and wasted a lot of my time. Premature optimization is the root of all evil.
Aug 24 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, August 24, 2011 17:52 Timon Gehr wrote:
 On 08/25/2011 02:34 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:17 Timon Gehr wrote:
 On 08/25/2011 01:15 AM, Timon Gehr wrote:
 On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:
 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
ASDF. I got it working quite fast, and then I started a fight with std.bigint.BigInt.toString until I accidentally cp'd over my source code. That will be reported soon, it makes BigInt UNUSABLE. I am going to code it again...
Don refuses to implement it, because it always creates a new string. He wants something like the DIP for writeFrom (or whatever the exact function name was) which allows for writing to a pre-existing buffer. I think that there's already a bug on the issue, but I'd have to search for it. - Jonathan M Davis
We must just add _*RVO for arrays*_ to the compiler and then users can use the built-in array concatenation syntax for the efficient thing. Everything else would just waste the precious grammar rules. How it is now is just painful and it does not fit well into the rest of Phobos. Not even std.conv.to can convert a BigInt to a string. This is a trivial issue that renders std.bigint unusable for these kinds of little scripts, where they actually would be of use. I don't care if I get a newly allocated string, because I only convert it once to output it. The current design just hurts me everywhere, and wasted a lot of my time. Premature optimization is the root of all evil.
The DIP actually solves the problem quite well, but it hasn't gone anywhere yet. I'd argue that BigInt should have a toString in the interim, but Don is against it (and std.conv.to requires toString, alias this to a string, or a cast to a string for a struct or class to work with it, and BigInt has none of those). - Jonathan M Davis
Aug 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 03:07 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:52 Timon Gehr wrote:
 On 08/25/2011 02:34 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:17 Timon Gehr wrote:
 On 08/25/2011 01:15 AM, Timon Gehr wrote:
 On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:
 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
ASDF. I got it working quite fast, and then I started a fight with std.bigint.BigInt.toString until I accidentally cp'd over my source code. That will be reported soon, it makes BigInt UNUSABLE. I am going to code it again...
Don refuses to implement it, because it always creates a new string. He wants something like the DIP for writeFrom (or whatever the exact function name was) which allows for writing to a pre-existing buffer. I think that there's already a bug on the issue, but I'd have to search for it. - Jonathan M Davis
We must just add _*RVO for arrays*_ to the compiler and then users can use the built-in array concatenation syntax for the efficient thing. Everything else would just waste the precious grammar rules. How it is now is just painful and it does not fit well into the rest of Phobos. Not even std.conv.to can convert a BigInt to a string. This is a trivial issue that renders std.bigint unusable for these kinds of little scripts, where they actually would be of use. I don't care if I get a newly allocated string, because I only convert it once to output it. The current design just hurts me everywhere, and wasted a lot of my time. Premature optimization is the root of all evil.
The DIP actually solves the problem quite well, but it hasn't gone anywhere yet. I'd argue that BigInt should have a toString in the interim, but Don is against it (and std.conv.to requires toString, alias this to a string, or a cast to a string for a struct or class to work with it, and BigInt has none of those).
It could have a special case for BigInt. The DIP does not solve the whole issue imho. This _cries_ for a more general solution. The DIP says, 'composing strings is inefficient and puts too much pressure on the heap, that is why we have to replace a simple API with a more complex one'. Wrong. That is why we have to make the compiler generate good code for composing strings, if necessary through an ABI change. writeTo looks like a neat solution if you want to Eg. output the thing without heap activity. But toString means: Convert this Object to string, and allocate a new string. I do not get why anyone would think that a hermaphrodite method with the name toString and the functionality of writeTo has any reason to exist. How do you simply convert a BigInt to a string using that tool? (I haven't found out, I always get "0") It really hurts generic code too, because it deviates from how things work for other types. Don should seriously reconsider.
Aug 24 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, August 25, 2011 03:35:05 Timon Gehr wrote:
 On 08/25/2011 03:07 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:52 Timon Gehr wrote:
 On 08/25/2011 02:34 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:17 Timon Gehr wrote:
 On 08/25/2011 01:15 AM, Timon Gehr wrote:
 On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:
 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of
 this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
ASDF. I got it working quite fast, and then I started a fight with std.bigint.BigInt.toString until I accidentally cp'd over my source code. That will be reported soon, it makes BigInt UNUSABLE. I am going to code it again...
Don refuses to implement it, because it always creates a new string. He wants something like the DIP for writeFrom (or whatever the exact function name was) which allows for writing to a pre-existing buffer. I think that there's already a bug on the issue, but I'd have to search for it. - Jonathan M Davis
We must just add _*RVO for arrays*_ to the compiler and then users can use the built-in array concatenation syntax for the efficient thing. Everything else would just waste the precious grammar rules. How it is now is just painful and it does not fit well into the rest of Phobos. Not even std.conv.to can convert a BigInt to a string. This is a trivial issue that renders std.bigint unusable for these kinds of little scripts, where they actually would be of use. I don't care if I get a newly allocated string, because I only convert it once to output it. The current design just hurts me everywhere, and wasted a lot of my time. Premature optimization is the root of all evil.
The DIP actually solves the problem quite well, but it hasn't gone anywhere yet. I'd argue that BigInt should have a toString in the interim, but Don is against it (and std.conv.to requires toString, alias this to a string, or a cast to a string for a struct or class to work with it, and BigInt has none of those).
It could have a special case for BigInt. The DIP does not solve the whole issue imho. This _cries_ for a more general solution. The DIP says, 'composing strings is inefficient and puts too much pressure on the heap, that is why we have to replace a simple API with a more complex one'. Wrong. That is why we have to make the compiler generate good code for composing strings, if necessary through an ABI change. writeTo looks like a neat solution if you want to Eg. output the thing without heap activity. But toString means: Convert this Object to string, and allocate a new string. I do not get why anyone would think that a hermaphrodite method with the name toString and the functionality of writeTo has any reason to exist. How do you simply convert a BigInt to a string using that tool? (I haven't found out, I always get "0") It really hurts generic code too, because it deviates from how things work for other types. Don should seriously reconsider.
The DIP works great if it's fully implemented. It complicates the implementations for classes and structs somewhat, but the code which uses them isn't generally affected much. It just uses to!string(a) instead of a.toString(). The problem is that the DIP hasn't been fully implemented. And in the meantime, the lack of a toString on BigInt is crippling. - Jonathan M Davis
Aug 24 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 04:05 AM, Jonathan M Davis wrote:
 On Thursday, August 25, 2011 03:35:05 Timon Gehr wrote:
 On 08/25/2011 03:07 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:52 Timon Gehr wrote:
 On 08/25/2011 02:34 AM, Jonathan M Davis wrote:
 On Wednesday, August 24, 2011 17:17 Timon Gehr wrote:
 On 08/25/2011 01:15 AM, Timon Gehr wrote:
 On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:
 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable".
There is only one missing override, but it is reported for every instantiation of the template. Statement at line 40 is necessary to make the /type inference/ work out, and such things are the reason I don't usually turn warnings on. Another example where warnings are a pita: case "bla","blu","blo": // Warning: fallthrough case "xxx","yyy","zzz": What the code expresses is: There are two cases, one occurs if the input is bla blu or blo, and the other one if it is xxx or yyy or zzz. Those cases should be handled the same way. (At least for now). goto case; is both unnecessary and ugly in that case. So basically, for me there are too many false positives to make the -w switch really practical, which is a pity, as they would have catched the missing override in this case.
 Are you able to use it to translate the Haskell version of
 this task?
 http://rosettacode.org/wiki/Hamming_numbers#Haskell
Challenge accepted.
ASDF. I got it working quite fast, and then I started a fight with std.bigint.BigInt.toString until I accidentally cp'd over my source code. That will be reported soon, it makes BigInt UNUSABLE. I am going to code it again...
Don refuses to implement it, because it always creates a new string. He wants something like the DIP for writeFrom (or whatever the exact function name was) which allows for writing to a pre-existing buffer. I think that there's already a bug on the issue, but I'd have to search for it. - Jonathan M Davis
We must just add _*RVO for arrays*_ to the compiler and then users can use the built-in array concatenation syntax for the efficient thing. Everything else would just waste the precious grammar rules. How it is now is just painful and it does not fit well into the rest of Phobos. Not even std.conv.to can convert a BigInt to a string. This is a trivial issue that renders std.bigint unusable for these kinds of little scripts, where they actually would be of use. I don't care if I get a newly allocated string, because I only convert it once to output it. The current design just hurts me everywhere, and wasted a lot of my time. Premature optimization is the root of all evil.
The DIP actually solves the problem quite well, but it hasn't gone anywhere yet. I'd argue that BigInt should have a toString in the interim, but Don is against it (and std.conv.to requires toString, alias this to a string, or a cast to a string for a struct or class to work with it, and BigInt has none of those).
It could have a special case for BigInt. The DIP does not solve the whole issue imho. This _cries_ for a more general solution. The DIP says, 'composing strings is inefficient and puts too much pressure on the heap, that is why we have to replace a simple API with a more complex one'. Wrong. That is why we have to make the compiler generate good code for composing strings, if necessary through an ABI change. writeTo looks like a neat solution if you want to Eg. output the thing without heap activity. But toString means: Convert this Object to string, and allocate a new string. I do not get why anyone would think that a hermaphrodite method with the name toString and the functionality of writeTo has any reason to exist. How do you simply convert a BigInt to a string using that tool? (I haven't found out, I always get "0") It really hurts generic code too, because it deviates from how things work for other types. Don should seriously reconsider.
The DIP works great if it's fully implemented. It complicates the implementations for classes and structs somewhat, but the code which uses them isn't generally affected much. It just uses to!string(a) instead of a.toString(). The problem is that the DIP hasn't been fully implemented. And in the meantime, the lack of a toString on BigInt is crippling.
Yes I do think it is a good concept. However, what the dip achieves for construction of new full-blown strings on the heap memory should be doable in the compiler through some form of RVO and provide even superior efficiency. The clear advantage would be that it would not complicate the implementations for structs and classes. writeTo and toString should be complementary, and everyone should be able to implement what fits their needs best, except Phobos data structures, those should implement both. to!string should default to toString (and then writeTo if not available), and writeln should default to writeTo (and then toString).
Aug 24 2011
prev sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
Jonathan M Davis:

 Don refuses to implement it, because it always creates a new string. He wants 
 something like the DIP for writeFrom
99.9% of the times Don is right, but in this case he's wrong. You can't avoid putting a necessary feature (a correctly working toString) just because it's not efficient yet because of a not yet implemented language feature (writeFrom). Making BigInt partially unusable just because Santa Claws isn't here yet isn't an acceptable design decision for a respectable standard library. Basic functionality comes before perceived (or imaginary) efficiency issues.
I think that there's already a bug on the issue,<
Opened by me, I think. Bye, bearophile
Aug 24 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 03:23 AM, bearophile wrote:
 Jonathan M Davis:

 Don refuses to implement it, because it always creates a new string. He wants
 something like the DIP for writeFrom
99.9% of the times Don is right, but in this case he's wrong. You can't avoid putting a necessary feature (a correctly working toString) just because it's not efficient yet because of a not yet implemented language feature (writeFrom). Making BigInt partially unusable just because Santa Claws isn't here yet isn't an acceptable design decision for a respectable standard library. Basic functionality comes before perceived (or imaginary) efficiency issues.
I think until this is fixed, most effort that has gone into std.bigint can be considered wasted, which is a pity.
 I think that there's already a bug on the issue,<
Opened by me, I think.
I cannot seem to find it, but I'd like to vote on it. Do you have a link?
Aug 24 2011
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/24/2011 11:55 PM, bearophile wrote:
 Timon Gehr:

 If anyone is interested:
 http://pastebin.com/2rEdx0RD
I suggest you to usually compile your D code with -w, I see some missing overrides. At line 40 it gives me a "Warning: statement is not reachable". Are you able to use it to translate the Haskell version of this task? http://rosettacode.org/wiki/Hamming_numbers#Haskell Bye, bearophile
Done: http://pastebin.com/Vx4hXvaT Theoretically it could use std.bigint, but I have still not found out how to convert these to string without pain.
Aug 24 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Timon Geh:

 Done: http://pastebin.com/Vx4hXvaT
 
 Theoretically it could use std.bigint, but I have still not found out 
 how to convert these to string without pain.
To compute Hamming(1_000_000) this converts a BigInt to string: string bigIntRepr(BigInt i) { const(char)[] result; i.toString((const(char)[] s) { result = s; }, "d"); return to!string(result); } Bye, bearophile
Aug 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 04:11 AM, bearophile wrote:
 Timon Geh:

 Done: http://pastebin.com/Vx4hXvaT

 Theoretically it could use std.bigint, but I have still not found out
 how to convert these to string without pain.
To compute Hamming(1_000_000) this converts a BigInt to string: string bigIntRepr(BigInt i) { const(char)[] result; i.toString((const(char)[] s) { result = s; }, "d"); return to!string(result); } Bye, bearophile
Ah, it is the format string that is not standard as well, now I get it. I'll give it a try tomorrow, thanks!
Aug 24 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 04:24 AM, Timon Gehr wrote:
 On 08/25/2011 04:11 AM, bearophile wrote:
 Timon Geh:

 Done: http://pastebin.com/Vx4hXvaT

 Theoretically it could use std.bigint, but I have still not found out
 how to convert these to string without pain.
To compute Hamming(1_000_000) this converts a BigInt to string: string bigIntRepr(BigInt i) { const(char)[] result; i.toString((const(char)[] s) { result = s; }, "d"); return to!string(result); } Bye, bearophile
Ah, it is the format string that is not standard as well, now I get it. I'll give it a try tomorrow, thanks!
http://pastebin.com/C6vf9DQQ It delivers correct results, but it takes 20min to run. (probably mainly GC-related, I don't know)
Aug 25 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 http://pastebin.com/C6vf9DQQ
Very good.
 It delivers correct results, but it takes 20min to run. (probably mainly 
 GC-related, I don't know)
DMD is not inlining those delegates, it is not merging streams as GHC does, etc. But such missing optimizations aren't the main cause of that so low performance. I think following those chains is a kind of worst-case for a mark&sweep GC. If I disable the GC using this code: void main() { import core.memory, core.stdc.stdlib; auto h = hamming!BigInt(); GC.disable(); writeln(h()[1_000_000]); exit(0); } The code runs in less than 23 seconds, using about 1.5 GB RAM, on a slow 32 bit PC (timings on a 64 CPU are welcome). Later I'll profile the code. Bye, bearophile
Aug 25 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/25/2011 07:40 PM, bearophile wrote:
 Timon Gehr:

 http://pastebin.com/C6vf9DQQ
Very good.
 It delivers correct results, but it takes 20min to run. (probably mainly
 GC-related, I don't know)
DMD is not inlining those delegates, it is not merging streams as GHC does, etc. But such missing optimizations aren't the main cause of that so low performance. I think following those chains is a kind of worst-case for a mark&sweep GC. If I disable the GC using this code: void main() { import core.memory, core.stdc.stdlib; auto h = hamming!BigInt(); GC.disable(); writeln(h()[1_000_000]); exit(0); } The code runs in less than 23 seconds, using about 1.5 GB RAM, on a slow 32 bit PC (timings on a 64 CPU are welcome). Later I'll profile the code. Bye, bearophile
I have already tried that, but my machine starts swapping and therefore I don't get the speedup. What kind of GC would be fastest for that use case? Is the current GC repeatedly looping over all allocated memory blocks to find the next link to follow?
Aug 25 2011
parent bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 I have already tried that, but my machine starts swapping and therefore 
 I don't get the speedup.
I have "only 2" GB of RAM. I suggest you to just reduce the number, so instead of 1_000_000, to use a smaller number, like 500_000, or smaller.
 What kind of GC would be fastest for that use case?
I am not an expert of GC, but there are tens of different kinds of GCs. I presume a GC that doesn't need to follow the chains is more efficient in this case (Time ago two persons were searching for D GC benchmarks. I suggest them to add this little program to their set of benchmarks). But sometimes it's not bad to give hints n some way to the GC, and change its working strategy for a small piece of code where the programmer knows a large data structure will be built in a focused way.
 Is the current GC 
 repeatedly looping over all allocated memory blocks to find the next 
 link to follow?
I think it is doing something like that. Bye, bearophile
Aug 25 2011
prev sibling next sibling parent reply Trass3r <un known.com> writes:
 http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/
Oh how I hate that. They always post general questions about D or ask what people think about it in places where nobody knows D at all. Of course this provokes damn stupid answers like "D is irrelevant now that
Aug 23 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 08/23/2011 02:21 PM, Trass3r wrote:
 http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/
Oh how I hate that. They always post general questions about D or ask what people think about it in places where nobody knows D at all.
I have corrected that by signing up and posting an answer myself.
 Of course this provokes damn stupid answers like "D is irrelevant now

Well, I LOL'd.
Aug 23 2011
next sibling parent reply =?UTF-8?B?QWxleCBSw7hubmUgUGV0ZXJzZW4=?= <xtzgzorex gmail.com> writes:
On 23-08-2011 15:03, Timon Gehr wrote:
 On 08/23/2011 02:21 PM, Trass3r wrote:
 http://www.linuxquestions.org/questions/programming-9/d-is-d-programming-language-just-too-much-898862/
Oh how I hate that. They always post general questions about D or ask what people think about it in places where nobody knows D at all.
I have corrected that by signing up and posting an answer myself.
 Of course this provokes damn stupid answers like "D is irrelevant now

Well, I LOL'd.
replace D? - Alex
Aug 23 2011
parent "Vladimir Panteleev" <vladimir thecybershadow.net> writes:
On Tue, 23 Aug 2011 16:40:40 +0300, Alex Rønne Petersen  
<xtzgzorex gmail.com> wrote:



 replace D?
By being further down the alphabet, perhaps? ;) (I'm wonder if paulsm4 was only kidding there) -- Best regards, Vladimir mailto:vladimir thecybershadow.net
Aug 23 2011
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 I have corrected that by signing up and posting an answer myself.
From that thread:
 str0.dup;     str1.dup;      // Some basic methods
 str0.sort;    str1.sort;     // are built into the
 str0.reverse; str1.reverse;  // base "string" class
Aren't sort and reverse going to be deprecated? (I like reverse as built-in). Bye, bearophile
Aug 23 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
Ugh, yet another POS that blocks mailinator. If anybody does bother to jump 
through their draconian registration hoops, be sure to tell them:

rdmd --build-only -ofmyapp myapp.d
Aug 23 2011
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
Nick Sabalausky Wrote:

 Ugh, yet another POS that blocks mailinator. If anybody does bother to jump 
 through their draconian registration hoops, be sure to tell them:
 
 rdmd --build-only -ofmyapp myapp.d
 
 
While not condoning their choice, LinuxQuestions.org is actually a great place to ask questions. It isn't as active as some places, but generally if you get an answer it's pretty good quality, or helpful in some way.
Aug 23 2011
parent "Nick Sabalausky" <a a.a> writes:
"Jesse Phillips" <jessekphillips+D gmail.com> wrote in message 
news:j31ide$258j$1 digitalmars.com...
 Nick Sabalausky Wrote:

 Ugh, yet another POS that blocks mailinator. If anybody does bother to 
 jump
 through their draconian registration hoops, be sure to tell them:

 rdmd --build-only -ofmyapp myapp.d
While not condoning their choice, LinuxQuestions.org is actually a great place to ask questions. It isn't as active as some places, but generally if you get an answer it's pretty good quality, or helpful in some way.
Yea, I ended up joining with one of the throwaway addresses I have on my server. One I already need to abandon anyway.
Aug 23 2011