www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why I'm Excited about D

reply "Adam Hawkins" <adam hawkins.io> writes:
Hello everyone, this is my first post on the forum. I've been 
investigating the language for the past few weeks. I was able to 
complete my first useful program thanks to very helpful people in 
#d on IRC . The experience made me very interested in the 
language and improving the community around it.

I'm primarily Ruby developer (been so about the last 7-8 years) 
doing web stuff with significant JavaScript work as well. I wrote 
a blog post on why I'm excited about D. You can read it here: 
http://hawkins.io/2015/04/excited-about-d/.

I've been reading the forums here so I can see that there is a 
focus on improving the marketing for the language and growing the 
community. I see most of the effort is geared towards C++ 
programmers, but have you considered looking at us dynamic 
languages folk? I see a big upside for us. Moving from Ruby to D 
(my case) gives me power & performance. I still have OOP 
techniques but I still have functional things like closures and 
all that good stuff. Only trade off in the Ruby case is 
metaprogramming. All in all I think there is a significant value 
promise for those of us doing backend services for folks like me.

Regardless, I figured it might be interesting to hear about some 
experience coming to the language from a different perspective. 
Cheers!
Apr 06 2015
next sibling parent reply "w0rp" <devw0rp gmail.com> writes:
On Monday, 6 April 2015 at 23:51:17 UTC, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been 
 investigating the language for the past few weeks. I was able 
 to complete my first useful program thanks to very helpful 
 people in #d on IRC . The experience made me very interested in 
 the language and improving the community around it.

 I'm primarily Ruby developer (been so about the last 7-8 years) 
 doing web stuff with significant JavaScript work as well. I 
 wrote a blog post on why I'm excited about D. You can read it 
 here: http://hawkins.io/2015/04/excited-about-d/.

 I've been reading the forums here so I can see that there is a 
 focus on improving the marketing for the language and growing 
 the community. I see most of the effort is geared towards C++ 
 programmers, but have you considered looking at us dynamic 
 languages folk? I see a big upside for us. Moving from Ruby to 
 D (my case) gives me power & performance. I still have OOP 
 techniques but I still have functional things like closures and 
 all that good stuff. Only trade off in the Ruby case is 
 metaprogramming. All in all I think there is a significant 
 value promise for those of us doing backend services for folks 
 like me.

 Regardless, I figured it might be interesting to hear about 
 some experience coming to the language from a different 
 perspective. Cheers!
I'm glad you like the language and felt enthusiatic enough to write an article about it. That's pretty much how D makes me feel. I think for pulling in Ruby people, it might be mostly the same as pulling in web people. I think the way I see it, I'd take vibe.d, an ORM with migrations, and runtime templates. The last two haven't been written yet. Then I'd be happy as far as replacing my web language of choice goes. At the moment I use Python and Django myself because of how little code I have to write to do a lot of things.
Apr 06 2015
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 7 April 2015 at 00:15:51 UTC, w0rp wrote:
 [...]and runtime templates. The last two haven't been written 
 yet.
Really? Runtime templates aren't even hard to implement.... What I do with my web libs is use a minimal templating system based on dom.d. Basic things are inserted with placeholders (which can also pipe variables through various transformation things, like myvar|capitalize), then advanced things are done with the dom api - you can easily define custom tags and such to do what you need to do. I like it. Of course, I'm perhaps a bit weird in that I like having plain html templates for the most part and find little value in the weird things other languages do. Ruby on Rails with its stupid erb and form "helpers" are far more cumbersome to use than straight html if you ask me - especially if you have a server side dom to help do convenience transformations. And stuff like haml, wtf is even the point of that nonsense. .... but still, stuff like erb or haml isn't that hard to implement, it is strange to me that vibe wouldn't have them.
Apr 06 2015
parent reply Jacob Carlborg <doob me.com> writes:
On 2015-04-07 02:29, Adam D. Ruppe wrote:
 On Tuesday, 7 April 2015 at 00:15:51 UTC, w0rp wrote:
 [...]and runtime templates. The last two haven't been written yet.
Really? Runtime templates aren't even hard to implement....
vibe.d has a template system. It's based on Jade, which seems to be based on Haml. -- /Jacob Carlborg
Apr 06 2015
next sibling parent Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 04/07/2015 08:28 AM, Jacob Carlborg wrote:

 
 vibe.d has a template system. It's based on Jade, which seems to be
 based on Haml.
There is also a runtime template system, http://code.dlang.org/packages/mustache-d. See https://github.com/D-Programming-GDC/gdcproject for an example.
Apr 07 2015
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 7 April 2015 at 06:28:49 UTC, Jacob Carlborg wrote:
 vibe.d has a template system. It's based on Jade, which seems 
 to be based on Haml.
Aye, though it is compile time rather than runtime which hurts the edit/run cycle - you have to recompile, redeploy (maybe), and restart just to see a quick text change. In my web projects. I used compile time stuff sometimes too, but the runtime loading ultimately won out for the ease of editing by me and by the frontend team - they can edit html too without needing to worry about rerunning a compiler.
Apr 07 2015
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2015-04-07 18:06, Adam D. Ruppe wrote:

 Aye, though it is compile time rather than runtime which hurts the
 edit/run cycle - you have to recompile, redeploy (maybe), and restart
 just to see a quick text change.
Oh, right, that was what he meant with "runtime" :) -- /Jacob Carlborg
Apr 07 2015
prev sibling parent reply Martin Nowak <code+news.digitalmars dawg.eu> writes:
On 04/07/2015 06:06 PM, Adam D. Ruppe wrote:
 In my web projects. I used compile time stuff sometimes too, but the
 runtime loading ultimately won out for the ease of editing by me and by
 the frontend team - they can edit html too without needing to worry
 about rerunning a compiler.
That's why I spent quite some time reducing that cycle and worked on a dub watch command. https://github.com/D-Programming-Language/dub/pull/388 https://code.dawg.eu/reducing-vibed-turnaround-time-part-2-less-compiling.html https://github.com/D-Programming-Language/dub/pull/446 What's still missing is a faster AST interpreter for CTFE though.
Apr 07 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 11:42 AM, Martin Nowak wrote:
 What's still missing is a faster AST interpreter for CTFE though.
A JIT would be nice. -- Andrei
Apr 07 2015
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 7 April 2015 at 22:22:35 UTC, Andrei Alexandrescu 
wrote:
 On 4/7/15 11:42 AM, Martin Nowak wrote:
 What's still missing is a faster AST interpreter for CTFE 
 though.
A JIT would be nice. -- Andrei
I'm not so sure CTFE would ever get out of the warmup debt JITs incur, ctfe bits usually don't live very long.
Apr 07 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 3:29 PM, Adam D. Ruppe wrote:
 On Tuesday, 7 April 2015 at 22:22:35 UTC, Andrei Alexandrescu wrote:
 On 4/7/15 11:42 AM, Martin Nowak wrote:
 What's still missing is a faster AST interpreter for CTFE though.
A JIT would be nice. -- Andrei
I'm not so sure CTFE would ever get out of the warmup debt JITs incur, ctfe bits usually don't live very long.
A JIT would pay off where it matters - intensive use of CTFE leading to long compilations. -- Andrei
Apr 07 2015
next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 7 April 2015 at 22:30:17 UTC, Andrei Alexandrescu 
wrote:
 On 4/7/15 3:29 PM, Adam D. Ruppe wrote:
 On Tuesday, 7 April 2015 at 22:22:35 UTC, Andrei Alexandrescu 
 wrote:
 On 4/7/15 11:42 AM, Martin Nowak wrote:
 What's still missing is a faster AST interpreter for CTFE 
 though.
A JIT would be nice. -- Andrei
I'm not so sure CTFE would ever get out of the warmup debt JITs incur, ctfe bits usually don't live very long.
A JIT would pay off where it matters - intensive use of CTFE leading to long compilations. -- Andrei
I can talk from first hand experience here, as SDC uses ONLY JIT for CTFE. It turns out that it is slower in the general case where you some small computation, but way faster as soon as you run something non trivial. I don't think it would be a good move to integrate it as this, but coupled with some heuristic, it would be great.
Apr 07 2015
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/7/2015 3:30 PM, Andrei Alexandrescu wrote:
 A JIT would pay off where it matters - intensive use of CTFE leading to long
 compilations. -- Andrei
A decent interpreter would fix most of CTFE's performance problems, no need to go as far as a JIT.
Apr 07 2015
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 7 April 2015 at 22:59:00 UTC, Walter Bright wrote:
 On 4/7/2015 3:30 PM, Andrei Alexandrescu wrote:
 A JIT would pay off where it matters - intensive use of CTFE 
 leading to long
 compilations. -- Andrei
A decent interpreter would fix most of CTFE's performance problems, no need to go as far as a JIT.
What is a JIT if not an interpreter with hardware support ?
Apr 07 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 4:54 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 22:59:00 UTC, Walter Bright wrote:
 On 4/7/2015 3:30 PM, Andrei Alexandrescu wrote:
 A JIT would pay off where it matters - intensive use of CTFE leading
 to long
 compilations. -- Andrei
A decent interpreter would fix most of CTFE's performance problems, no need to go as far as a JIT.
What is a JIT if not an interpreter with hardware support ?
Nah. It's a fundamentally different approach to the same problem. -- Andrei
Apr 07 2015
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 8 April 2015 at 00:28:50 UTC, Andrei Alexandrescu 
wrote:
 On 4/7/15 4:54 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 22:59:00 UTC, Walter Bright wrote:
 On 4/7/2015 3:30 PM, Andrei Alexandrescu wrote:
 A JIT would pay off where it matters - intensive use of CTFE 
 leading
 to long
 compilations. -- Andrei
A decent interpreter would fix most of CTFE's performance problems, no need to go as far as a JIT.
What is a JIT if not an interpreter with hardware support ?
Nah. It's a fundamentally different approach to the same problem. -- Andrei
Not really when you think about it. CPU instruction is a bytecode like another, with provided hardware interpreter for it. It is becoming common to have VM not going through the interpreter step (ie software interpreter) to go directly to low quality but fast codegen. V8 is doing this for instance.
Apr 07 2015
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/7/2015 5:59 PM, deadalnix wrote:
 Not really when you think about it. CPU instruction is a bytecode like another,
 with provided hardware interpreter for it.
Oh, I have thought about it. There's at least a couple orders of magnitude difference in complexity, even for the dumbest code generator.
 It is becoming common to have VM not going through the interpreter step (ie
 software interpreter) to go directly to low quality but fast codegen. V8 is
 doing this for instance.
When you've got unlimited resources, you can do that.
Apr 07 2015
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 6:26 PM, Walter Bright wrote:
 On 4/7/2015 5:59 PM, deadalnix wrote:
 Not really when you think about it. CPU instruction is a bytecode like
 another,
 with provided hardware interpreter for it.
Oh, I have thought about it. There's at least a couple orders of magnitude difference in complexity, even for the dumbest code generator.
That's about the case for hhvm. -- Andrei
Apr 07 2015
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 5:59 PM, deadalnix wrote:
 On Wednesday, 8 April 2015 at 00:28:50 UTC, Andrei Alexandrescu wrote:
 On 4/7/15 4:54 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 22:59:00 UTC, Walter Bright wrote:
 On 4/7/2015 3:30 PM, Andrei Alexandrescu wrote:
 A JIT would pay off where it matters - intensive use of CTFE leading
 to long
 compilations. -- Andrei
A decent interpreter would fix most of CTFE's performance problems, no need to go as far as a JIT.
What is a JIT if not an interpreter with hardware support ?
Nah. It's a fundamentally different approach to the same problem. -- Andrei
Not really when you think about it. CPU instruction is a bytecode like another, with provided hardware interpreter for it.
Classical interpretation via tree walking does not use a bytecode. -- Andrei
Apr 07 2015
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/7/2015 6:30 PM, Andrei Alexandrescu wrote:
 Classical interpretation via tree walking does not use a bytecode. -- Andrei
And this is proven to work by CTFE. (CTFE walks the AST.) Note that walking the AST, instead of generating bytecode, is not at all why CTFE is slow. CTFE is slow because it allocates memory for every step in the computation.
Apr 07 2015
parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Tue, Apr 07, 2015 at 06:48:58PM -0700, Walter Bright via Digitalmars-d wrote:
 On 4/7/2015 6:30 PM, Andrei Alexandrescu wrote:
Classical interpretation via tree walking does not use a bytecode. --
Andrei
And this is proven to work by CTFE. (CTFE walks the AST.) Note that walking the AST, instead of generating bytecode, is not at all why CTFE is slow. CTFE is slow because it allocates memory for every step in the computation.
Is this fixable within reasonable effort, or does it require what essentially amounts to rewriting CTFE from scratch? T -- MACINTOSH: Most Applications Crash, If Not, The Operating System Hangs
Apr 07 2015
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 8 April 2015 at 01:30:02 UTC, Andrei Alexandrescu 
wrote:
 Not really when you think about it. CPU instruction is a 
 bytecode like
 another, with provided hardware interpreter for it.
Classical interpretation via tree walking does not use a bytecode. -- Andrei
Yes, but this is pretty much what is done right now, so that wouldn't be an improvement.
Apr 07 2015
next sibling parent "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"deadalnix"  wrote in message news:qranzmdfsbaxpxlwikmj forum.dlang.org...

 Classical interpretation via tree walking does not use a bytecode. --  
 Andrei
Yes, but this is pretty much what is done right now, so that wouldn't be an improvement.
The allocation problems are not caused by the tree walking, and they can be fixed without changing to a bytecode interpreter or a JIT.
Apr 07 2015
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 7:33 PM, deadalnix wrote:
 On Wednesday, 8 April 2015 at 01:30:02 UTC, Andrei Alexandrescu wrote:
 Not really when you think about it. CPU instruction is a bytecode like
 another, with provided hardware interpreter for it.
Classical interpretation via tree walking does not use a bytecode. -- Andrei
Yes, but this is pretty much what is done right now, so that wouldn't be an improvement.
You went ouroboros. This means your point has been destroyed so thoroughly, you lost the thread of the dialog. Own the destruction and move on. -- Andrei
Apr 07 2015
parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 8 April 2015 at 05:03:03 UTC, Andrei Alexandrescu 
wrote:
 On 4/7/15 7:33 PM, deadalnix wrote:
 On Wednesday, 8 April 2015 at 01:30:02 UTC, Andrei 
 Alexandrescu wrote:
 Not really when you think about it. CPU instruction is a 
 bytecode like
 another, with provided hardware interpreter for it.
Classical interpretation via tree walking does not use a bytecode. -- Andrei
Yes, but this is pretty much what is done right now, so that wouldn't be an improvement.
You went ouroboros. This means your point has been destroyed so thoroughly, you lost the thread of the dialog. Own the destruction and move on. -- Andrei
You are the one making about winning.
Apr 08 2015
prev sibling parent "Martin Nowak" <code dawg.eu> writes:
On Tuesday, 7 April 2015 at 22:22:35 UTC, Andrei Alexandrescu 
wrote:
 On 4/7/15 11:42 AM, Martin Nowak wrote:
 What's still missing is a faster AST interpreter for CTFE 
 though.
A JIT would be nice. -- Andrei
Maxine understood the point, see http://dconf.org/2013/talks/chevalier_boisvert.pdf p. 61 ff, an AST interpreter is something you can write over a long weekend, a JIT is rather unlikely to happen any time soon. Even a bytecode interpreter might hardly be worth the effort.
Apr 08 2015
prev sibling next sibling parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 7/04/2015 11:51 a.m., Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been
 investigating the language for the past few weeks. I was able to
 complete my first useful program thanks to very helpful people in #d on
 IRC . The experience made me very interested in the language and
 improving the community around it.

 I'm primarily Ruby developer (been so about the last 7-8 years) doing
 web stuff with significant JavaScript work as well. I wrote a blog post
 on why I'm excited about D. You can read it here:
 http://hawkins.io/2015/04/excited-about-d/.

 I've been reading the forums here so I can see that there is a focus on
 improving the marketing for the language and growing the community. I
 see most of the effort is geared towards C++ programmers, but have you
 considered looking at us dynamic languages folk? I see a big upside for
 us. Moving from Ruby to D (my case) gives me power & performance. I
 still have OOP techniques but I still have functional things like
 closures and all that good stuff. Only trade off in the Ruby case is
 metaprogramming. All in all I think there is a significant value promise
 for those of us doing backend services for folks like me.

 Regardless, I figured it might be interesting to hear about some
 experience coming to the language from a different perspective. Cheers!
I was slightly surprised that you didn't mention CTFE in there as it is one of D's unique and powerful features. But only because I'm a little invested https://leanpub.com/ctfe in it. I am very interested in feedback on https://github.com/DNetDev from you. I do have a web service framework also being written. But it really needs the web server first.
Apr 06 2015
parent reply "Jens Bauer" <doctor who.no> writes:
On Tuesday, 7 April 2015 at 00:28:11 UTC, Rikki Cattermole wrote:
 I was slightly surprised that you didn't mention CTFE in there 
 as it is one of D's unique and powerful features.
 But only because I'm a little invested https://leanpub.com/ctfe 
 in it.
It is very cool, that you can generate tables without the need for writing a perl-script or some "additional" C/C++ program. Having table-generation at compile-time is an excellent feature. -Yes, that's only one of the features, but it's a feature I'll be using more than once! :)
Apr 06 2015
parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 7/04/2015 12:52 p.m., Jens Bauer wrote:
 On Tuesday, 7 April 2015 at 00:28:11 UTC, Rikki Cattermole wrote:
 I was slightly surprised that you didn't mention CTFE in there as it
 is one of D's unique and powerful features.
 But only because I'm a little invested https://leanpub.com/ctfe in it.
It is very cool, that you can generate tables without the need for writing a perl-script or some "additional" C/C++ program. Having table-generation at compile-time is an excellent feature. -Yes, that's only one of the features, but it's a feature I'll be using more than once! :)
CTFE could have some pretty awesome applications for embedded I suspect. After all, you can pregenerate data structures ext. For faster execution. I don't think anybody has toyed with this yet.
Apr 06 2015
parent reply "Jens Bauer" <doctor who.no> writes:
On Tuesday, 7 April 2015 at 00:57:09 UTC, Rikki Cattermole wrote:
 CTFE could have some pretty awesome applications for embedded I 
 suspect. After all, you can pregenerate data structures ext. 
 For faster execution.
Yes, they're particularly useful for embedded devices. I've often used tables in assembly language in this regard. -Things that seem to be impossible, because the normal approach is to "write optimized code" suddenly becomes possible, when optimizing (rearranging) the data to fit the hardware.
 I don't think anybody has toyed with this yet.
With D, advanced table-generation will become much easier. I bet I'm one of those people, who will have a lot of fun using this feature. ;)
Apr 06 2015
parent reply Rikki Cattermole <alphaglosined gmail.com> writes:
On 7/04/2015 1:02 p.m., Jens Bauer wrote:
 On Tuesday, 7 April 2015 at 00:57:09 UTC, Rikki Cattermole wrote:
 CTFE could have some pretty awesome applications for embedded I
 suspect. After all, you can pregenerate data structures ext. For
 faster execution.
Yes, they're particularly useful for embedded devices. I've often used tables in assembly language in this regard. -Things that seem to be impossible, because the normal approach is to "write optimized code" suddenly becomes possible, when optimizing (rearranging) the data to fit the hardware.
 I don't think anybody has toyed with this yet.
With D, advanced table-generation will become much easier. I bet I'm one of those people, who will have a lot of fun using this feature. ;)
I'm watching your progress closely. I think we are ready to get D properly on micro controllers and you are really testing, exploring it even. I would be very surprised in the next year or so, if you don't make atleast one breakthrough!
Apr 06 2015
parent "Jens Bauer" <doctor who.no> writes:
On Tuesday, 7 April 2015 at 01:28:03 UTC, Rikki Cattermole wrote:
 I'm watching your progress closely. I think we are ready to get 
 D properly on micro controllers and you are really testing, 
 exploring it even.
Johannes made some very important additions for regarding this. It might already be possible for me to write a complete startup file entirely in D, because of these additions.
 I would be very surprised in the next year or so, if you don't 
 make atleast one breakthrough!
I'm looking forward to the first one; it's just around the corner: The file "startup.d". :) -I'll be sure to create a thread about it, when it's complete (it's at something like 98% already). One thing I'd like to add to why I like D, is that it feels "limitless". I don't feel like I'm restricted by the language or the compiler; in other words, I feel a lot of 'freedom'.
Apr 07 2015
prev sibling next sibling parent "Jens Bauer" <doctor who.no> writes:
On Monday, 6 April 2015 at 23:51:17 UTC, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum.
Then as a fellow newcomer to D, let me be the first to welcome you. :)
 I wrote a blog post on why I'm excited about D. You can read it 
 here: http://hawkins.io/2015/04/excited-about-d/.
Very nice article. I think I came across a minor error (please correct me if I'm wrong)... In your runTests 'in' part - shouldn't "results" be "tests" ? ... As for myself, I sense a lot of power in the D language; but curently I'm only in the process of starting the engine. My goal is to work with D for microcontrollers like ARM Cortex-M and ARM Cortex-A later. D is *very* suitable for this; perhaps the most suitable language I've ever come across. To me, D is appealing because: 1: I am crazy about optimizing my code. Assembly language and optimization is one of my greatest hobbies. 2: I would like my code to be easy and simple. 3: I would like an object-oriented programming language which does not bloat everything out of proportions. ;) 4: I like 'universal', 'general' and 'generic' very much. I think D covers those points very well. From what I've seen and read so far, the produced binary is short and quite fast; the source code for a program does not need to be huge and ugly, but can be small and easy to overview. Furthermore, I hate "C++ string classes". In D, a string is a native type; pretty cool. Just start typing your code and run it. And for a long time, I've wanted something as easy as Javascript, but just able to generate executable code, which works outside the Web-browser. D is clearly a language designed by experienced developers. It shows the best side of open source. (My favorites: Redis, GCC and D - and yes, I've already noticed Tiny Redis, and i'm going to use try it out sometime, perhaps even on a microcontroller).
Apr 06 2015
prev sibling next sibling parent reply "bachmeier" <no spam.net> writes:
On Monday, 6 April 2015 at 23:51:17 UTC, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been 
 investigating the language for the past few weeks. I was able 
 to complete my first useful program thanks to very helpful 
 people in #d on IRC . The experience made me very interested in 
 the language and improving the community around it.

 I'm primarily Ruby developer (been so about the last 7-8 years) 
 doing web stuff with significant JavaScript work as well. I 
 wrote a blog post on why I'm excited about D. You can read it 
 here: http://hawkins.io/2015/04/excited-about-d/.

 I've been reading the forums here so I can see that there is a 
 focus on improving the marketing for the language and growing 
 the community. I see most of the effort is geared towards C++ 
 programmers, but have you considered looking at us dynamic 
 languages folk? I see a big upside for us. Moving from Ruby to 
 D (my case) gives me power & performance. I still have OOP 
 techniques but I still have functional things like closures and 
 all that good stuff. Only trade off in the Ruby case is 
 metaprogramming. All in all I think there is a significant 
 value promise for those of us doing backend services for folks 
 like me.

 Regardless, I figured it might be interesting to hear about 
 some experience coming to the language from a different 
 perspective. Cheers!
The thing I liked, coming from languages like R and Ruby, was that I could write D code in the most convenient, least efficient manner possible and still get good enough performance that it wouldn't matter. I find D to be easier to write than any scripting language. When I write D I always have to remind myself that I can just write, without concern for efficiency. And in the few cases that performance is critical I know I can do as well as C.
Apr 06 2015
parent reply "cym13" <cpicard openmailbox.org> writes:
On Tuesday, 7 April 2015 at 01:12:20 UTC, bachmeier wrote:
 The thing I liked, coming from languages like R and Ruby, was 
 that I could write D code in the most convenient, least 
 efficient manner possible and still get good enough performance 
 that it wouldn't matter. I find D to be easier to write than 
 any scripting language. When I write D I always have to remind 
 myself that I can just write, without concern for efficiency. 
 And in the few cases that performance is critical I know I can 
 do as well as C.
This! This is really the thing I like about D overall! I used to prototype in python and either rewrite part of it in C (process involving lots of latent rage for missing common features) or give up on performance (which, honestly, was most of the time a good answer). In D I feel like I don't have this tradeoff. I start prototyping in D putting auto everywhere and not anotating anything and when the prototype works I just start cleaning the code, annotating it, etc.... The fact that where I used two languages I can now use only one is what convinced me (even if, to be fair, the prototyping part is way much easier in python... But that may be due to the gab of experience).
Apr 07 2015
parent reply "Laeeth Isharc" <laeeth nospamlaeeth.com> writes:
even if,
 to be fair, the prototyping part is way much easier in 
 python... But that may be due to the gab of experience).
what - beyond a richer choice of libraries (and documentation, including examples) would make D comparable to python in terms of prototyping ease?
Apr 07 2015
parent "Laeeth Isharc" <laeeth nospamlaeeth.com> writes:
We are clearly blessed here with an abundance of expertise in 
Ruby in the forum.

If anyone would like to share some of their knowledge, this page 
could use some filling out:

http://wiki.dlang.org/Coming_From/Ruby

Concrete examples and links to personal stories are helpful - as 
well as more theoretical explorations of language concepts.

It's better to make a start than worry about it not being perfect.
Apr 07 2015
prev sibling next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Monday, 6 April 2015 at 23:51:17 UTC, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been 
 investigating the language for the past few weeks. I was able 
 to complete my first useful program thanks to very helpful 
 people in #d on IRC . The experience made me very interested in 
 the language and improving the community around it.

 I'm primarily Ruby developer (been so about the last 7-8 years) 
 doing web stuff with significant JavaScript work as well. I 
 wrote a blog post on why I'm excited about D. You can read it 
 here: http://hawkins.io/2015/04/excited-about-d/.

 I've been reading the forums here so I can see that there is a 
 focus on improving the marketing for the language and growing 
 the community. I see most of the effort is geared towards C++ 
 programmers, but have you considered looking at us dynamic 
 languages folk? I see a big upside for us. Moving from Ruby to 
 D (my case) gives me power & performance. I still have OOP 
 techniques but I still have functional things like closures and 
 all that good stuff. Only trade off in the Ruby case is 
 metaprogramming. All in all I think there is a significant 
 value promise for those of us doing backend services for folks 
 like me.

 Regardless, I figured it might be interesting to hear about 
 some experience coming to the language from a different 
 perspective. Cheers!
Very nice article. I have two suggestions: import std.stdio, std.parallelism; auto names = [ "Adam Hawkins", "Peter Esselius" ]; foreach(name; taskPool.parallel(names)) { writeln(name); } There is a convenience function in std.parallelism that allows you to write the following instead for your foreach loop: foreach (name; names.parallel) { writeln(name); } Also, system, trusted, safe don't really have much to do with optimization or access levels, but safety. Theoretically, if all of your code is safe, then it is impossible for your program to corrupt memory. Also, have you considered posting this article to Hacker News/Reddit?
Apr 06 2015
parent reply "ixid" <adamsibson hotmail.com> writes:
 import std.stdio, std.parallelism;

 auto names = [ "Adam Hawkins", "Peter Esselius" ];

 foreach(name; taskPool.parallel(names)) {
     writeln(name);
 }

 There is a convenience function in std.parallelism that allows 
 you to write the following instead for your foreach loop:

 foreach (name; names.parallel) {
     writeln(name);
 }

 Also,  system,  trusted,  safe don't really have much to do 
 with optimization or access levels, but safety. Theoretically, 
 if all of your code is  safe, then it is impossible for your 
 program to corrupt memory.

 Also, have you considered posting this article to Hacker 
 News/Reddit?
Or to be more consistent with UFCS: foreach (name; names.parallel) { name.writeln; }
Apr 07 2015
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
     name.writeln;
 }
no.please
Apr 07 2015
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
     name.writeln;
 }
no.please
wat
Apr 07 2015
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
    name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
Apr 07 2015
next sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 4/7/15 3:34 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
    name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
Yes, I don't like "writeln" being used with UFCS, it's an abuse. My point is that every language has WATs :-)
Apr 07 2015
next sibling parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Tue, Apr 07, 2015 at 04:46:07PM -0300, Ary Borenszweig via Digitalmars-d
wrote:
 On 4/7/15 3:34 PM, deadalnix wrote:
On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig wrote:
On 4/7/15 2:16 PM, deadalnix wrote:
On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
Or to be more consistent with UFCS:

foreach (name; names.parallel) {
   name.writeln;
}
no.please
wat
unreadable.is.ufcs.using.over
Yes, I don't like "writeln" being used with UFCS, it's an abuse. My point is that every language has WATs :-)
My current favorite WAT in D is: import std.stdio; void fun(string text) { import std.conv; writeln(text); } void main() { fun("Hello world"); } This program outputs a blank line. :-) T -- A mathematician is a device for turning coffee into theorems. -- P. Erdos
Apr 07 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 1:11 PM, H. S. Teoh via Digitalmars-d wrote:
 On Tue, Apr 07, 2015 at 04:46:07PM -0300, Ary Borenszweig via Digitalmars-d
wrote:
 On 4/7/15 3:34 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
    name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
Yes, I don't like "writeln" being used with UFCS, it's an abuse. My point is that every language has WATs :-)
My current favorite WAT in D is: import std.stdio; void fun(string text) { import std.conv; writeln(text); } void main() { fun("Hello world"); } This program outputs a blank line. :-)
Yeah, I think it's urgent we fix that. -- Andrei
Apr 07 2015
parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 7 April 2015 at 22:24:21 UTC, Andrei Alexandrescu 
wrote:
 My current favorite WAT in D is:

 	import std.stdio;
 	void fun(string text) {
 		import std.conv;
 		writeln(text);
 	}
 	void main() {
 		fun("Hello world");
 	}

 This program outputs a blank line. :-)
Yeah, I think it's urgent we fix that. -- Andrei
My favorite next: void function() f; static assert(is(f == function)); // OK void delegate() dg; static assert(is(f == delegate)); // Nope... Note that even phobos can get confused with that one in some cases.
Apr 07 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/7/15 3:27 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 22:24:21 UTC, Andrei Alexandrescu wrote:
 My current favorite WAT in D is:

     import std.stdio;
     void fun(string text) {
         import std.conv;
         writeln(text);
     }
     void main() {
         fun("Hello world");
     }

 This program outputs a blank line. :-)
Yeah, I think it's urgent we fix that. -- Andrei
My favorite next: void function() f; static assert(is(f == function)); // OK void delegate() dg; static assert(is(f == delegate)); // Nope...
(I assume you meant "dg" here.) This doesn't strike me as big, but it is weird.
 Note that even phobos can get confused with that one in some cases.
Are there bugzillas for these two matters? Andrei
Apr 07 2015
parent "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Tue, Apr 07, 2015 at 03:29:26PM -0700, Andrei Alexandrescu via Digitalmars-d
wrote:
 On 4/7/15 3:27 PM, deadalnix wrote:
On Tuesday, 7 April 2015 at 22:24:21 UTC, Andrei Alexandrescu wrote:
My current favorite WAT in D is:

    import std.stdio;
    void fun(string text) {
        import std.conv;
        writeln(text);
    }
    void main() {
        fun("Hello world");
    }
[...]
 Are there bugzillas for these two matters?
[...] The blank output one has been known for a while now (since June 2013), under various guises: https://issues.dlang.org/show_bug.cgi?id=10378 The above test case, though, strikes me as a particularly compelling example of why this bug is so nasty. T -- Why waste time learning, when ignorance is instantaneous? -- Hobbes, from Calvin & Hobbes
Apr 07 2015
prev sibling parent reply "ixid" <adamsibson hotmail.com> writes:
On Tuesday, 7 April 2015 at 19:46:07 UTC, Ary Borenszweig wrote:
 On 4/7/15 3:34 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig 
 wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
   name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
Yes, I don't like "writeln" being used with UFCS, it's an abuse. My point is that every language has WATs :-)
Why is it 'an abuse'? Do you special case any other functions or is names.parallel unacceptable as well? Are longer chains ending in writeln acceptable or do you insist in putting the whole chain inside a parens writeln? name.reverse.writeln or writeln(name.reverse) or surely that would break your dislike of single UFCS arguments so you should stick to: writeln(reverse(name)) Which is proper yoda speak.
Apr 08 2015
next sibling parent reply "Idan Arye" <GenericNPC gmail.com> writes:
On Wednesday, 8 April 2015 at 08:35:52 UTC, ixid wrote:
 On Tuesday, 7 April 2015 at 19:46:07 UTC, Ary Borenszweig wrote:
 On 4/7/15 3:34 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig 
 wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
  name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
Yes, I don't like "writeln" being used with UFCS, it's an abuse. My point is that every language has WATs :-)
Why is it 'an abuse'? Do you special case any other functions or is names.parallel unacceptable as well? Are longer chains ending in writeln acceptable or do you insist in putting the whole chain inside a parens writeln? name.reverse.writeln or writeln(name.reverse) or surely that would break your dislike of single UFCS arguments so you should stick to: writeln(reverse(name)) Which is proper yoda speak.
At the very least, put () after the writelne: name.reverse.writeln(); Using the property getter style for a function used solely for it's side-effects kind of conceals what you are trying to do here... At any rate, since UFCS allows you to choose the order your code will be read in, you should try give as much information as soon as possible: `writeln(name.reverse);` - the first word is `writeln`, so I know it's a statement that's going to write something to stdout. `name.reverse.writeln();` - the first word is `name`, so I know it has something to do with the name. Decide which one to use based on the first impression you want people to get from that statement.
Apr 08 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Apr 08 2015
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei Alexandrescu 
wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Yes.
Apr 08 2015
next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 8 April 2015 at 16:49:27 UTC, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei Alexandrescu
 No. -- Andrei
Yes.
FILE_NOT_FOUND
Apr 08 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 16:49:27 UTC, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei Alexandrescu 
 wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Yes.
And, by the way, this is not a just personal taste thing. This stupid style has costed me many wasted debugging ours during project maintenance. Considering I am far from the only person having problems with it in our team and such style is extremely common because of being easy - this can easily be one of most damaging language features in D in terms of wasted developer time.
Apr 08 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 9:53 AM, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:49:27 UTC, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei Alexandrescu wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Yes.
And, by the way, this is not a just personal taste thing.
It is.
 This stupid
 style has costed me many wasted debugging ours during project
 maintenance.
Not buying it.
 Considering I am far from the only person having problems
 with it in our team and such style is extremely common because of being
 easy - this can easily be one of most damaging language features in D in
 terms of wasted developer time.
Again trying with ad populum. Not buying it. Andrei
Apr 08 2015
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 16:56:12 UTC, Andrei Alexandrescu 
wrote:
 Considering I am far from the only person having problems
 with it in our team and such style is extremely common because 
 of being
 easy - this can easily be one of most damaging language 
 features in D in
 terms of wasted developer time.
Again trying with ad populum. Not buying it.
I don't even slightly care about your opinion here. It is just another annoying custom style rule I have to deal with. Casual necessity for actually getting work done with D. And if "not buying it" is all you can say about actual experience report (however opinionated it is) this tells quite a lot about how justified _your_ preference is.
Apr 08 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 10:04 AM, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:56:12 UTC, Andrei Alexandrescu wrote:
 Considering I am far from the only person having problems
 with it in our team and such style is extremely common because of being
 easy - this can easily be one of most damaging language features in D in
 terms of wasted developer time.
Again trying with ad populum. Not buying it.
I don't even slightly care about your opinion here. It is just another annoying custom style rule I have to deal with. Casual necessity for actually getting work done with D.
I guess I deserve this for making my point as a jerk. I shouldn't engage in brief bickering when I don't have time. My point was: you'd need some detail to back up your claim about those wasted hours because I also work on a large D project at work with others and that hasn't been an issue, like, ever. We ended up just not adding the pesky "()"s simply because sitting down and deciding which deserves and which doesn't was a waste of time. E.g. front and empty shouldn't, but popFront should. Really no reason for it.
 And if "not buying it" is all you can say about actual experience report
 (however opinionated it is) this tells quite a lot about how justified
 _your_ preference is.
Yah, I do think it's a matter of preference. Andrei
Apr 08 2015
next sibling parent reply "Dmitri Makarov" <dmakarv gmail.com> writes:
On Wednesday, 8 April 2015 at 18:08:36 UTC, Andrei Alexandrescu 
wrote:
 ... I also work on a large D project at work ...
Which compiler do you use?
Apr 08 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 11:50 AM, Dmitri Makarov wrote:
 On Wednesday, 8 April 2015 at 18:08:36 UTC, Andrei Alexandrescu wrote:
 ... I also work on a large D project at work ...
Which compiler do you use?
dmd -- Andrei
Apr 08 2015
parent reply "weaselcat" <weaselcat gmail.com> writes:
On Wednesday, 8 April 2015 at 22:19:11 UTC, Andrei Alexandrescu 
wrote:
 On 4/8/15 11:50 AM, Dmitri Makarov wrote:
 On Wednesday, 8 April 2015 at 18:08:36 UTC, Andrei 
 Alexandrescu wrote:
 ... I also work on a large D project at work ...
Which compiler do you use?
dmd -- Andrei
Is this for both production and development?
Apr 08 2015
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 3:28 PM, weaselcat wrote:
 On Wednesday, 8 April 2015 at 22:19:11 UTC, Andrei Alexandrescu wrote:
 On 4/8/15 11:50 AM, Dmitri Makarov wrote:
 On Wednesday, 8 April 2015 at 18:08:36 UTC, Andrei Alexandrescu wrote:
 ... I also work on a large D project at work ...
Which compiler do you use?
dmd -- Andrei
Is this for both production and development?
Both. -- Andrei
Apr 08 2015
prev sibling parent reply ketmar <ketmar ketmar.no-ip.org> writes:
On Wed, 08 Apr 2015 22:28:58 +0000, weaselcat wrote:

 On Wednesday, 8 April 2015 at 22:19:11 UTC, Andrei Alexandrescu wrote:
 On 4/8/15 11:50 AM, Dmitri Makarov wrote:
 On Wednesday, 8 April 2015 at 18:08:36 UTC, Andrei Alexandrescu wrote:
 ... I also work on a large D project at work ...
Which compiler do you use?
dmd -- Andrei
=20 Is this for both production and development?
i'm using DMD for production code too. most of the time code waits for i/o (being that disk, network or user interaction). ah, even my 2d game=20 engine is ok with -release.=
Apr 08 2015
parent ketmar <ketmar ketmar.no-ip.org> writes:
On Wed, 08 Apr 2015 23:14:23 +0000, ketmar wrote:

 On Wed, 08 Apr 2015 22:28:58 +0000, weaselcat wrote:
=20
 On Wednesday, 8 April 2015 at 22:19:11 UTC, Andrei Alexandrescu wrote:
 On 4/8/15 11:50 AM, Dmitri Makarov wrote:
 On Wednesday, 8 April 2015 at 18:08:36 UTC, Andrei Alexandrescu
 wrote:
 ... I also work on a large D project at work ...
Which compiler do you use?
dmd -- Andrei
=20 Is this for both production and development?
=20 i'm using DMD for production code too. most of the time code waits for i/o (being that disk, network or user interaction). ah, even my 2d game engine is ok with -release.
to be honest, "-release" doesn't make much difference, as i'm already=20 using `.ptr` to avoid range checking where it isn't appropriate.=
Apr 08 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 18:08:36 UTC, Andrei Alexandrescu 
wrote:
 On 4/8/15 10:04 AM, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:56:12 UTC, Andrei 
 Alexandrescu wrote:
 Considering I am far from the only person having problems
 with it in our team and such style is extremely common 
 because of being
 easy - this can easily be one of most damaging language 
 features in D in
 terms of wasted developer time.
Again trying with ad populum. Not buying it.
I don't even slightly care about your opinion here. It is just another annoying custom style rule I have to deal with. Casual necessity for actually getting work done with D.
I guess I deserve this for making my point as a jerk. I shouldn't engage in brief bickering when I don't have time. My point was: you'd need some detail to back up your claim about those wasted hours because I also work on a large D project at work with others and that hasn't been an issue, like, ever. We ended up just not adding the pesky "()"s simply because sitting down and deciding which deserves and which doesn't was a waste of time. E.g. front and empty shouldn't, but popFront should. Really no reason for it.
So, to be more specific, here is one of cases where it actually caused trouble in practice. Someone has originally written code that looked roughly like this: while (something) { // ... auto str = format("%s", parser.node); } Long time later I have been adding trace logs to that module and this has become akin to while (something) { log(parser.node); // ... auto str = format("%s", parser.node); } Which resulted in broken application. It took almost an hour to bisect all changed to trace the failure to this specifc line and realize that `parser.node` wasn't just trivial getter but method which actually advanced internal iterator to next node while returning current one. Yes, this does seem to bother only some people and others actually enjoy omitting parens everywhere. But it comes up often enough to cause actual damage which makes aesthetical point much less convincing. I don't have any good statistics for how often it strikes or what kind of workflow is more likely to clash with such style - all I know that such cases happen, and happen often enough to not be dismissed as purely accidental. Considering that following more permissive coding style does not actually give you any benefits than saving at most one pair of () per line, choice feels obvious. We don't currently have any strict style rules about this but general direction seems to be "mandatory () for last call in a call chain" with an exception for side-effect free trivial getters. tl; dr: I can commonly be wrong in identifying the problem, evalutating its importance or proposing solutions but it feels offending when you suggest I don't actually have a problem at all. "Those are not the droids you are looking for" style ;)
Apr 08 2015
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 11:45 PM, Dicebot wrote:
 It took almost an hour to bisect all changed to trace the failure to
 this specifc line and realize that `parser.node` wasn't just trivial
 getter but method which actually advanced internal iterator to next node
 while returning current one.
Thanks. The matter seems like a C++ false friend. -- Andrei
Apr 09 2015
parent reply "Dicebot" <public dicebot.lv> writes:
On Thursday, 9 April 2015 at 07:00:56 UTC, Andrei Alexandrescu 
wrote:
 On 4/8/15 11:45 PM, Dicebot wrote:
 It took almost an hour to bisect all changed to trace the 
 failure to
 this specifc line and realize that `parser.node` wasn't just 
 trivial
 getter but method which actually advanced internal iterator to 
 next node
 while returning current one.
Thanks. The matter seems like a C++ false friend. -- Andrei
Actually, C++ had the very same issue, just the other way around. Stuff like length() was still called like method even if trivial and I remember resorting to naming convention to avoid wasting time on following all symbol references. It was roughly the same rule - no side effects or costly computations in methods named `getXXX`, simply attached to naming convention as opposed to calling convention. And it was even more unpleasant than current D state of affairs. I had much more pleasant experience of maintaining code in plain C where separation between data and code is more forced by language simplicity. It is much better in languages that do support dedicated properties because language rules can be used to express the same notion without resorting to any conventions. And properly naming things is unreasonably time consuming so this "by convention" approach hardly works anyway. The way I see situation in D is that it had an opportunity to actually get things better than in C/C++ with property but that was killed in favor of seemingly "nice" syntax. Which feels completely disproportional approach to me because saving one pair of () per line of code is hardly comparable to being able to better reason about the code without resorting to IDE. Everyone who has pointed out that naming in original snippet sucks is completely right. However, this is not really helping - bad names will inevitably slip through here and there. Which naturally makes me annoyed about language features that make the issue worse instead of largely diminishing it. Mandatory () are probably not that important on their own - but thet at least add something to to the language, while alternative is simply syntax sugar with no practical value.
Apr 12 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/12/15 10:43 AM, Dicebot wrote:
 It is much better in languages that do support dedicated properties
 because language rules can be used to express the same notion without
 resorting to any conventions.
behavior? -- Andrei
Apr 12 2015
next sibling parent "Idan Arye" <GenericNPC gmail.com> writes:
On Sunday, 12 April 2015 at 18:42:01 UTC, Andrei Alexandrescu 
wrote:
 On 4/12/15 10:43 AM, Dicebot wrote:
 It is much better in languages that do support dedicated 
 properties
 because language rules can be used to express the same notion 
 without
 resorting to any conventions.
avoid surprising behavior? -- Andrei
I'd be surprised if there is any language that prevents you from causing side-effects in getters(beside functional languages that prevent you from causing side-effects anywhere) or non-setting-related side-effects in setters. These kind of limitations prevent many useful patterns, like calculating-and-caching a value the first time a getter is called, or updating a visual component on the screen when it's setters are called. I don't think relying-purely-on-conventions-with-no-language-support and the-language-strictly-forbids-stuff are the only choices. With a grain (syntactic) salt a language can promote the right way by turning the wrong way into code smell. getter declaration syntax or with D's doesn't-actually-do-anything property attribute or whatever used in that language) that causes side-effects other than the ones pragmatically needed for getting the value, you can immediately see that something is wrong. But if you look at such a function at the call site you can't guess that it's doing that stuff. getter-setter syntax for actual getters and setters, then that is probably the least of your worries... In D, you don't need to not rely on other developers to do that, because EVERY method without arguments and EVERY function with a single argument are getters, and there is nothing you can do about it(unless you use the seems-to-be-abandoned -property flag). BTW - the exact definition of getters and setters may vary(can querying a webservice be considered a getter?), but under no sane definition is writeln a getter!
Apr 12 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Sunday, 12 April 2015 at 18:42:01 UTC, Andrei Alexandrescu 
wrote:
 On 4/12/15 10:43 AM, Dicebot wrote:
 It is much better in languages that do support dedicated 
 properties
 because language rules can be used to express the same notion 
 without
 resorting to any conventions.
avoid surprising behavior? -- Andrei
This is totally reasonable way to put it but in practice there are enough differences to keep it maintainable. With dedicated getters decision (and reviewer attention) is focused on definition of getter and done there once and for all. Some tough decisions are inevitable but it is at least possible to ensure that all such decisions are deliberate. In D such decision is done at call site which makes it very hard to review as changes are distributed everywhere. Though DScanner can possibly help here and I am really looking forward trying to it in our code control. That said, I think the main reason why this notion didn't work well for D when property was introduces is because of extremely vague range semantics. I find it important that you have mentioned exactly `front` and `popFront` as examples for unclear parens placement - problem with those is that there isn't. `front` may or may not be trivial getter depending on (sometimes arbitrary) decision by range implementor, there is no uniformity between those. Which makes impossible to enforce consistent calling style and makes "drop everything" approach much more tempting.
Apr 12 2015
next sibling parent "Dominikus Dittes Scherkl" writes:
On Monday, 13 April 2015 at 05:46:32 UTC, Dicebot wrote:
 [...]
 That said, I think the main reason why this notion didn't work 
 well for D when  property was introduces is because of 
 extremely vague range semantics. I find it important that you 
 have mentioned exactly `front` and `popFront` as examples for 
 unclear parens placement - problem with those is that there 
 isn't. `front` may or may not be trivial getter depending on 
 (sometimes arbitrary) decision by range implementor, there is 
 no uniformity between those. Which makes impossible to enforce 
 consistent calling style and makes "drop everything" approach 
 much more tempting.
At work we use a tool that uses a kind of attribute "no side effects". I would love it if the D could do just that - the compiler is already able to check if a function has side effects or not (if it has none it can warns about simple function call statements), than only functions with no side effects should be callable without parantheses. That would be straight and a clear visible for the reader of some code. And than the attribute property could be used to allow even a function WITH side effects to be called without parantheses - the developer has to ensure that what ever is done in such a function does something sensible (e.g. calculate something at first call and then only works as getter afterwards), but the reader of the code is warned: the attribute proberty was used, so he better take a look what this function really does. Maybe also a new attribute nonprop could be introduced, to force that a function must be called with parantheses even if it has no side effects, but I'm not sure where this would be useful.
Apr 13 2015
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Monday, 13 April 2015 at 05:46:32 UTC, Dicebot wrote:
 On Sunday, 12 April 2015 at 18:42:01 UTC, Andrei Alexandrescu 
 wrote:
 On 4/12/15 10:43 AM, Dicebot wrote:
 It is much better in languages that do support dedicated 
 properties
 because language rules can be used to express the same notion 
 without
 resorting to any conventions.
avoid surprising behavior? -- Andrei
This is totally reasonable way to put it but in practice there are enough differences to keep it maintainable. With dedicated getters decision (and reviewer attention) is focused on definition of getter and done there once and for all. Some tough decisions are inevitable but it is at least possible to ensure that all such decisions are deliberate. In D such decision is done at call site which makes it very hard to review as changes are distributed everywhere. Though DScanner can possibly help here and I am really looking forward trying to it in our code control. That said, I think the main reason why this notion didn't work well for D when property was introduces is because of extremely vague range semantics. I find it important that you have mentioned exactly `front` and `popFront` as examples for unclear parens placement - problem with those is that there isn't. `front` may or may not be trivial getter depending on (sometimes arbitrary) decision by range implementor, there is no uniformity between those. Which makes impossible to enforce consistent calling style and makes "drop everything" approach much more tempting.
Very good point. I've been bitten by range semantic many times, especially map, which is lazy and does the work on front call, rather than popFront as I would have expected. Thinking about it, this is probably the right thing to do, but the range interface makes it non obvious and confusing.
Apr 13 2015
parent "Abdulhaq" <alynch4047 gmail.com> writes:
On Monday, 13 April 2015 at 16:43:00 UTC, deadalnix wrote:
 Thinking about it, this is probably the right thing to do, but 
 the range interface makes it non obvious and confusing.
Some time ago there was a long thread about formalising the interface for ranges, i.e. a clear and precise definition of what each method should do. Was a consensus reached and documented?
Apr 13 2015
prev sibling parent reply "Araq" <rumpf_a web.de> writes:
 So, to be more specific, here is one of cases where it actually 
 caused trouble in practice. Someone has originally written code 
 that looked roughly like this:

 while (something)
 {
     // ...
     auto str = format("%s", parser.node);
 }

 Long time later I have been adding trace logs to that module 
 and this has become akin to

 while (something)
 {
     log(parser.node);
     // ...
     auto str = format("%s", parser.node);
 }

 Which resulted in broken application. It took almost an hour to 
 bisect all changed to trace the failure to this specifc line 
 and realize that `parser.node` wasn't just trivial getter but 
 method which actually advanced internal iterator to next node 
 while returning current one.
In Java many people would have done this instead: while (something) { log(parser.getNode()); // ... String str = format("%s", parser.getNode()); } Because trivial accessors are everywhere in Java one usually has to assume it has no side-effects. I fail to see the relevance of the missing () in your example; () doesn't scream side-effect in simply poorly named suggesting it has no side-effects. 'nextNode' for instance doesn't have this problem.
Apr 09 2015
next sibling parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Thursday, 9 April 2015 at 16:12:17 UTC, Araq wrote:

 'node' or 'getNode' is simply poorly named suggesting it has no 
 side-effects. 'nextNode' for instance doesn't have this problem.
"next" is a common name for next-pointers. You need to pick a verb that cannot be mistaken for an adjective. E.g. "moveToNextNode". Anyway, being explicit is important for maintainability. Some language designers are very much against even overloading for this reason. There's a convenience-maintenance trade off between weakly typed implicit languages and statically/strictly/strongly typed explicit code (suitable for large vocabulary, large source base, long running). Here's the semiotics I tend to go by: - Dot-notation indicates an accessor/interface provided by the object, e.g. penetrating an encapsulation. - A parametric accessor ("()" is empty) indicates work being done using reference semantics. - Free form functions indicates value-semantics with results derived from values/objects. Consistent mapping from syntax to semantics makes for more readable and, more importantly, more easily maintainable code.
Apr 09 2015
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/9/2015 9:12 AM, Araq wrote:
 Because trivial accessors are everywhere in Java one usually has to assume it
 has no side-effects. I fail to see the relevance of the missing () in your

 that 'node' or 'getNode' is simply poorly named suggesting it has no
 side-effects. 'nextNode' for instance doesn't have this problem.
I agree, it seems the method is poorly named as a simple noun that implies a static computation, rather than as a verb that implies some sort of action.
Apr 09 2015
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 8 April 2015 at 16:56:12 UTC, Andrei Alexandrescu 
wrote:
 On 4/8/15 9:53 AM, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:49:27 UTC, Dicebot wrote:
 On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei 
 Alexandrescu wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Yes.
And, by the way, this is not a just personal taste thing.
It is.
He is coming with actual feedback from people using D. This is not opinion, this is fact (considering he can be trusted, but then request more precise data instead of stating it is opinion).
 Considering I am far from the only person having problems
 with it in our team and such style is extremely common because 
 of being
 easy - this can easily be one of most damaging language 
 features in D in
 terms of wasted developer time.
Again trying with ad populum. Not buying it.
It is not ad populum, it is actual feedback from people using D having wasted time.
Apr 08 2015
prev sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
Also, I've noted the general trend lately were you seems value 
more "winning" the debate than actually coming to some conclusion.

I'm not sure what's up with that, but nothing good can come out 
of this on the long run.
Apr 08 2015
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 1:21 PM, deadalnix wrote:
 Also, I've noted the general trend lately were you seems value more
 "winning" the debate than actually coming to some conclusion.

 I'm not sure what's up with that, but nothing good can come out of this
 on the long run.
Hmmm... Could you please give a few examples. You seem to be disproportionately sore over this specious claim of yours:
 What is a JIT if not an interpreter with hardware support ?
which I found worth spending time to refute (in hindsight, not really worth the drama). For that distraction I'm sorry. If you want to chat about improving my manners, let's talk over a coffee. I guess I'll have a little list as well :o). Andrei
Apr 08 2015
prev sibling parent reply "Idan Arye" <GenericNPC gmail.com> writes:
On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei Alexandrescu 
wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Why not? The property syntax's purpose is to create... well... properties. Give you the illusion that you are reading and writing member fields when you are actually calling functions. `names.reverse` is OK, because you can imagine that `names` has a member field called `reverse` that holds it reversed(this is not really true because `names.reverse` is mutating the original array, but the point is that we are not calling `reverse` for it's side - we are only interested in it's return value). `names.reverse.writeln;` - not so much. We are not treating `writeln` as a property - we don't really care what it returns - we treat it as a method, and therefore it should use the method call syntax. In matter of fact - if `writeln` was a member field - the very same thing the combination of UFCS and property syntax is trying to emulate - this code wouldn't compile: struct Foo { string writeln; } struct Bar { Foo reverse; } void main() { Bar names; names.reverse.writeln; } source/app.d(10): Error: dotvar has no effect in expression (names.reverse.writeln)
Apr 08 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 4:15 PM, Idan Arye wrote:
 On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei Alexandrescu wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Why not? The property syntax's purpose is to create... well... properties. Give you the illusion that you are reading and writing member fields when you are actually calling functions.
It seems to be a difference without a distinction. One day I got tired of writing r.empty and r.front but r.popFront(). Furthermore I got tired to spend time thinking where I should insert parens vs. where I shouldn't. So I dropped parens from that. And then from other places. Apparently I didn't get struck by lightning where I stood. Andrei
Apr 08 2015
parent reply "Idan Arye" <GenericNPC gmail.com> writes:
On Thursday, 9 April 2015 at 01:28:05 UTC, Andrei Alexandrescu 
wrote:
 On 4/8/15 4:15 PM, Idan Arye wrote:
 On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei 
 Alexandrescu wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Why not? The property syntax's purpose is to create... well... properties. Give you the illusion that you are reading and writing member fields when you are actually calling functions.
It seems to be a difference without a distinction. One day I got tired of writing r.empty and r.front but r.popFront(). Furthermore I got tired to spend time thinking where I should insert parens vs. where I shouldn't. So I dropped parens from that. And then from other places. Apparently I didn't get struck by lightning where I stood. Andrei
This is not about being struck by lightning. This is about being struck by the next developer who has to read your code.
Apr 09 2015
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/9/15 10:31 AM, Idan Arye wrote:
 On Thursday, 9 April 2015 at 01:28:05 UTC, Andrei Alexandrescu wrote:
 On 4/8/15 4:15 PM, Idan Arye wrote:
 On Wednesday, 8 April 2015 at 16:47:10 UTC, Andrei Alexandrescu wrote:
 On 4/8/15 2:24 AM, Idan Arye wrote:
 At the very least, put () after the writelne:
No. -- Andrei
Why not? The property syntax's purpose is to create... well... properties. Give you the illusion that you are reading and writing member fields when you are actually calling functions.
It seems to be a difference without a distinction. One day I got tired of writing r.empty and r.front but r.popFront(). Furthermore I got tired to spend time thinking where I should insert parens vs. where I shouldn't. So I dropped parens from that. And then from other places. Apparently I didn't get struck by lightning where I stood. Andrei
This is not about being struck by lightning. This is about being struck by the next developer who has to read your code.
Apparently they didn't either. -- Andrei
Apr 09 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 08:35:52 UTC, ixid wrote:
 On Tuesday, 7 April 2015 at 19:46:07 UTC, Ary Borenszweig wrote:
 On 4/7/15 3:34 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig 
 wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
  name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
Yes, I don't like "writeln" being used with UFCS, it's an abuse. My point is that every language has WATs :-)
Why is it 'an abuse'? Do you special case any other functions or is names.parallel unacceptable as well? Are longer chains ending in writeln acceptable or do you insist in putting the whole chain inside a parens writeln?
There are two main use cases for UFCS: use UFCS syntax for cases where you would consider actually having method like this in used data type. 2) more readable syntax for functional style processing pipeline There is no way anyone would ever add method called "writeln" to user data type and it is clearly not pipeline function. This is plain and disgusting abuse of the syntax, I am fully with deadalnix here. For parallel it may be feasible if data set is actually intended for parallelization by design but I would personally consider that fishy too. Omitting parens from function calls with side effects is another horrible sin but that is more of a personal taste thing.
Apr 08 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 6:42 AM, Dicebot wrote:
 There is no way anyone would ever add method called "writeln" to user
 data type
File defines it.
 and it is clearly not pipeline function.
Oh but it is.
 This is plain and
 disgusting abuse of the syntax, I am fully with deadalnix here.
No. Andrei
Apr 08 2015
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 8 April 2015 at 16:51:53 UTC, Andrei Alexandrescu 
wrote:
 File defines it.
Last time this came up on reddit, I explained that *this* was exactly why I think "string".writeln is mistaken. writeln does NOT operate on its string, it doesn't tell the string to do something, it doesn't transform the string. It tells a *File* to do something.
Apr 08 2015
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/8/2015 9:58 AM, Adam D. Ruppe wrote:
 On Wednesday, 8 April 2015 at 16:51:53 UTC, Andrei Alexandrescu wrote:
 File defines it.
Last time this came up on reddit, I explained that *this* was exactly why I think "string".writeln is mistaken. writeln does NOT operate on its string, it doesn't tell the string to do something, it doesn't transform the string. It tells a *File* to do something.
writeln is an OutputRange. It takes its input from the pipeline and places it in a container (the screen).
Apr 08 2015
next sibling parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 17:17:21 UTC, Walter Bright wrote:
 On 4/8/2015 9:58 AM, Adam D. Ruppe wrote:
 On Wednesday, 8 April 2015 at 16:51:53 UTC, Andrei 
 Alexandrescu wrote:
 File defines it.
Last time this came up on reddit, I explained that *this* was exactly why I think "string".writeln is mistaken. writeln does NOT operate on its string, it doesn't tell the string to do something, it doesn't transform the string. It tells a *File* to do something.
writeln is an OutputRange. It takes its input from the pipeline and places it in a container (the screen).
But it is actually a method of stdout file, which was what Adam has pointed out. Hiding it behind free function and abusing that fact for UFCS is just mixing semantics and, well, abuse.
Apr 08 2015
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 8 April 2015 at 17:17:21 UTC, Walter Bright wrote:
 writeln is an OutputRange.
No, it isn't. It isn't even remotely close to one - an OutputRange is a type, writeln is a function. isOutputRange doesn't even return false for it, it outright fails to compile! File isn't an output range either btw. An output range is defined by the presence of a put method, which File doesn't have. b.d(4): Error: static assert (isOutputRange!(File, char)) is false Even putting aside the formal definition of output range, output is NOT part of the pipeline! Pipelines can be composed and they keep pumping data through them. writeln does not transform its input nor does it forward it to the next item in the pipe. It just eats it. That's totally different than everything else in the sequence. And that's not even bringing in writeln's sister function, writefln, whose first argument isn't what is to be printed at all! (it can show something to print but passing arbitrary strings to writef as the first argument is a major program bug, you should never do it)
Apr 08 2015
next sibling parent reply "ixid" <adamsibson hotmail.com> writes:
 Even putting aside the formal definition of output range, 
 output is NOT part of the pipeline! Pipelines can be composed 
 and they keep pumping data through them. writeln does not 
 transform its input nor does it forward it to the next item in 
 the pipe. It just eats it.
"nor does it forward it to the next item in the pipe" This is something I think writeln should do and have suggested before. It would be useful for debugging pipelines to be able to drop in writeln in the middle of the pipeline and pass on the data unchanged.
Apr 08 2015
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 17:41:01 UTC, ixid wrote:
 Even putting aside the formal definition of output range, 
 output is NOT part of the pipeline! Pipelines can be composed 
 and they keep pumping data through them. writeln does not 
 transform its input nor does it forward it to the next item in 
 the pipe. It just eats it.
"nor does it forward it to the next item in the pipe" This is something I think writeln should do and have suggested before. It would be useful for debugging pipelines to be able to drop in writeln in the middle of the pipeline and pass on the data unchanged.
http://dlang.org/library/std/range/tee.html ?
Apr 08 2015
parent "ixid" <adamsibson hotmail.com> writes:
On Wednesday, 8 April 2015 at 17:43:27 UTC, Dicebot wrote:
 On Wednesday, 8 April 2015 at 17:41:01 UTC, ixid wrote:
 Even putting aside the formal definition of output range, 
 output is NOT part of the pipeline! Pipelines can be composed 
 and they keep pumping data through them. writeln does not 
 transform its input nor does it forward it to the next item 
 in the pipe. It just eats it.
"nor does it forward it to the next item in the pipe" This is something I think writeln should do and have suggested before. It would be useful for debugging pipelines to be able to drop in writeln in the middle of the pipeline and pass on the data unchanged.
http://dlang.org/library/std/range/tee.html ?
Thanks, I wasn't aware of that function. Will use that.
Apr 08 2015
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 8 April 2015 at 17:41:01 UTC, ixid wrote:
 It would be useful for debugging pipelines to be able to drop 
 in writeln in the middle of the pipeline and pass on the data 
 unchanged.
That might be useful for debugging but I'd also be annoyed if someone used that in production code too because then your pipeline would have global side effects!
Apr 08 2015
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 4/8/2015 10:33 AM, Adam D. Ruppe wrote:
 On Wednesday, 8 April 2015 at 17:17:21 UTC, Walter Bright wrote:
 writeln is an OutputRange.
No, it isn't. It isn't even remotely close to one - an OutputRange is a type,
I meant an instance of a type, as in: i is an int meaning i has type int.
 writeln is a function. isOutputRange doesn't even return false for it, it
 outright fails to compile!
I understand that a true OutputRange would require one to write: arg.copy(writeln); and that a common idiom is to write it so the copy() can be implicit. I haven't made up my mind as to the right style here.
 File isn't an output range either btw. An output range is defined by the
 presence of a put method, which File doesn't have.

 b.d(4): Error: static assert  (isOutputRange!(File, char)) is false


 Even putting aside the formal definition of output range, output is NOT part of
 the pipeline! Pipelines can be composed and they keep pumping data through
them.
An output range is the caboose of a pipeline (to mix metaphors).
 writeln does not transform its input nor does it forward it to the next item in
 the pipe. It just eats it.
It places its input into a container.
 That's totally different than everything else in the sequence. And that's not
 even bringing in writeln's sister function, writefln, whose first argument
isn't
 what is to be printed at all!
It's true that a lot of Phobos code was designed pre-ranges, and the parameters aren't set up ideally for it. I've been doing some work to fix that.
Apr 08 2015
prev sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 16:51:53 UTC, Andrei Alexandrescu 
wrote:
 and it is clearly not pipeline function.
Oh but it is.
Oh really? And what does it transform the input data to? Just to be clear - I wouldn't allow range.copy(stdout) in my projects either, requiring any consumer to be written as dedicated expression.
Apr 08 2015
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 8 April 2015 at 16:59:27 UTC, Dicebot wrote:
 Just to be clear - I wouldn't allow range.copy(stdout) in my 
 projects either, requiring any consumer to be written as 
 dedicated expression.
Worth noting that std.range.put's documentation also says use the freestanding syntax. (This is surely to avoid ambiguity with member puts on output ranges, but still.)
Apr 08 2015
prev sibling next sibling parent "ixid" <adamsibson hotmail.com> writes:
On Tuesday, 7 April 2015 at 18:34:01 UTC, deadalnix wrote:
 On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
   name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
UFCS doesn't give you yoda speak. It's more consistent to use it for single as well as multiple function chains and it's cleaner. Some users' distaste for UFCS cramps D's developing its own consistent idiomatic approach. Do you have any argument for your dislike that isn't just personal preference? You're fine with names.parallel but for some reason balk at name.writeln?
Apr 08 2015
prev sibling parent "Atila Neves" <atila.neves gmail.com> writes:
On Tuesday, 7 April 2015 at 18:34:01 UTC, deadalnix wrote:
 On Tuesday, 7 April 2015 at 18:01:53 UTC, Ary Borenszweig wrote:
 On 4/7/15 2:16 PM, deadalnix wrote:
 On Tuesday, 7 April 2015 at 08:58:57 UTC, ixid wrote:
 Or to be more consistent with UFCS:

 foreach (name; names.parallel) {
   name.writeln;
 }
no.please
wat
unreadable.is.ufcs.using.over
I love UFCS. I'd definitely write names.parallel myself. Atila
Apr 08 2015
prev sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
deadalnix:

 foreach (name; names.parallel) {
    name.writeln;
 }
no.please
I think "foo.writeln;" is acceptable. You just need to get a bit used to it. Bye, bearophile
Apr 08 2015
next sibling parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 13:52:22 UTC, bearophile wrote:
 deadalnix:

 foreach (name; names.parallel) {
   name.writeln;
 }
no.please
I think "foo.writeln;" is acceptable. You just need to get a bit used to it. Bye, bearophile
No.
Apr 08 2015
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/8/15 7:00 AM, Dicebot wrote:
 On Wednesday, 8 April 2015 at 13:52:22 UTC, bearophile wrote:
 deadalnix:

 foreach (name; names.parallel) {
   name.writeln;
 }
no.please
I think "foo.writeln;" is acceptable. You just need to get a bit used to it. Bye, bearophile
No.
Ja, ja, ja. -- Andrei
Apr 08 2015
prev sibling parent reply "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Wednesday, 8 April 2015 at 13:52:22 UTC, bearophile wrote:
 I think "foo.writeln;" is acceptable. You just need to get a 
 bit used to it.
The whole dot-notation for pipelining is semantically flawed en relies on knowing what names stand for rather than more universal symbols with known interpretations. It has been (ab)used quite a bit in OO-libraries for other languages, for chaining, which can be rather confusing when you use many libraries. Dedicated pipeline operators look much better ("input->process->output"). Add dataflow with multiple paths and high level optimization, then you have something.
Apr 08 2015
parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 8 April 2015 at 14:57:15 UTC, Ola Fosheim Grøstad 
wrote:
 On Wednesday, 8 April 2015 at 13:52:22 UTC, bearophile wrote:
 I think "foo.writeln;" is acceptable. You just need to get a 
 bit used to it.
The whole dot-notation for pipelining is semantically flawed en relies on knowing what names stand for rather than more universal symbols with known interpretations. It has been (ab)used quite a bit in OO-libraries for other languages, for chaining, which can be rather confusing when you use many libraries. Dedicated pipeline operators look much better ("input->process->output"). Add dataflow with multiple paths and high level optimization, then you have something.
I kind of agree with this one. Range based pipeline has established rather late as core D idiom but in general it is distinct enough to warrant own syntax.
Apr 08 2015
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2015-04-07 01:51, Adam Hawkins wrote:

 Only trade off in the Ruby case is metaprogramming.
You can do metaprogramming in D, it's just a bit different compared to Ruby. -- /Jacob Carlborg
Apr 06 2015
prev sibling next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Mon, 06 Apr 2015 23:51:16 +0000, Adam Hawkins wrote:

 I've been reading the forums here so I can see that there is a focus on
 improving the marketing for the language and growing the community. I
 see most of the effort is geared towards C++ programmers, but have you
 considered looking at us dynamic languages folk?
it seems that there are not so many people that comes from some dynamic=20 we know bits and pieces about dynamic land, we generally not using it for=20 something "serious" (unless we are forced to do so ;-).
 Regardless, I figured it might be interesting to hear about some
 experience coming to the language from a different perspective.
sure. you're welcome, it's always good to have more opinions, both=20 positive (yay!) and negative (heh... so what we can do with that?).=
Apr 07 2015
prev sibling next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Monday, 6 April 2015 at 23:51:17 UTC, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been 
 investigating the language for the past few weeks. I was able 
 to complete my first useful program thanks to very helpful 
 people in #d on IRC . The experience made me very interested in 
 the language and improving the community around it.

 I'm primarily Ruby developer (been so about the last 7-8 years) 
 doing web stuff with significant JavaScript work as well. I 
 wrote a blog post on why I'm excited about D. You can read it 
 here: http://hawkins.io/2015/04/excited-about-d/.

 I've been reading the forums here so I can see that there is a 
 focus on improving the marketing for the language and growing 
 the community. I see most of the effort is geared towards C++ 
 programmers, but have you considered looking at us dynamic 
 languages folk? I see a big upside for us. Moving from Ruby to 
 D (my case) gives me power & performance. I still have OOP 
 techniques but I still have functional things like closures and 
 all that good stuff. Only trade off in the Ruby case is 
 metaprogramming. All in all I think there is a significant 
 value promise for those of us doing backend services for folks 
 like me.

 Regardless, I figured it might be interesting to hear about 
 some experience coming to the language from a different 
 perspective. Cheers!
This is awesome :) A few notes on the blog: "peaked my interest" should be "piqued my interest" You can have as many unittest blocks as you want in a file/module. property isn't really about parentheses-less calls (parentheses are optional for all function calls), it's more for this sort of thing: struct S { private int a_; enum flagMask = 1u << 31; property void val(int v) { a_ = (a_ & flagMask) & (v & ~flagMask); } property int val() { return a_ & ~flagMask; } property void flag(bool b) { a_ = ((cast(uint)b) << 31) & (a_ & ~mask); } property bool flag() { return a_ & flagMask; } } unittest { S s; s.flag = true; s.val = 75; assert(s.flag); assert(s.val == 75); } Note that the assignments are calling the property functions.
Apr 07 2015
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-04-07 10:33, John Colvin wrote:

 (parentheses are optional for all function calls),
Optional for all function calls taking no arguments. Note that in Ruby parentheses are optional for function calls taking arguments as well. -- /Jacob Carlborg
Apr 07 2015
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 7 April 2015 at 11:16:56 UTC, Jacob Carlborg wrote:
 On 2015-04-07 10:33, John Colvin wrote:

 (parentheses are optional for all function calls),
Optional for all function calls taking no arguments. Note that in Ruby parentheses are optional for function calls taking arguments as well.
Sorry, yes my mistake
Apr 07 2015
prev sibling parent reply "Jens Bauer" <doctor who.no> writes:
On Tuesday, 7 April 2015 at 08:33:58 UTC, John Colvin wrote:
  property isn't really about parentheses-less calls 
 (parentheses are optional for all function calls), it's more 
 for this sort of thing:
 [snip]
      property void val(int v)
     {
         a_ = (a_ & flagMask) & (v & ~flagMask);
     }
This is *really* cool and very useful on microcontrollers and is superior to C's bit-fields. Imagine that your microcontroller has 24 GPIO pins. Such pins are usually grouped in 'ports', for instance Port A and Port B. Each port could for instance support up to 32 pins: PA0 ... PA31 and PB0 ... PB31. But there's a problem here: Our microcontroller has only 24 pins, and our microcontroller vendor chose to make the following pins available to us: PA1 ... PA5, PA7, PA13, PA17, PA18 .. PA19, PA23 ... PA28 PB0 ... PB3, PB8 ... PB12 Every developer will think this is annoying. We want to write a byte to a port, but it has to be converted first. If just incrementing a value, one could do as follows: PortB = (PortB | 0x00f0) + 1; ... oposite for decrementing: PortB = (PortB & 0xff0f) - 1; But the property can make all this transparent, so our sources become very easy to overview and understand.
Apr 07 2015
next sibling parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 7 April 2015 at 14:20:58 UTC, Jens Bauer wrote:
 On Tuesday, 7 April 2015 at 08:33:58 UTC, John Colvin wrote:
  property isn't really about parentheses-less calls 
 (parentheses are optional for all function calls), it's more 
 for this sort of thing:
 [snip]
     property void val(int v)
    {
        a_ = (a_ & flagMask) & (v & ~flagMask);
    }
This is *really* cool and very useful on microcontrollers and is superior to C's bit-fields. Imagine that your microcontroller has 24 GPIO pins. Such pins are usually grouped in 'ports', for instance Port A and Port B. Each port could for instance support up to 32 pins: PA0 ... PA31 and PB0 ... PB31. But there's a problem here: Our microcontroller has only 24 pins, and our microcontroller vendor chose to make the following pins available to us: PA1 ... PA5, PA7, PA13, PA17, PA18 .. PA19, PA23 ... PA28 PB0 ... PB3, PB8 ... PB12 Every developer will think this is annoying. We want to write a byte to a port, but it has to be converted first. If just incrementing a value, one could do as follows: PortB = (PortB | 0x00f0) + 1; ... oposite for decrementing: PortB = (PortB & 0xff0f) - 1; But the property can make all this transparent, so our sources become very easy to overview and understand.
and, for convenience there is
Apr 07 2015
prev sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Tue, 07 Apr 2015 14:20:57 +0000, Jens Bauer wrote:

 If just incrementing a value, one could do as follows:
 PortB =3D (PortB | 0x00f0) + 1;
 ... oposite for decrementing:
 PortB =3D (PortB & 0xff0f) - 1;
=20
 But the  property can make all this transparent, so our sources become
 very easy to overview and understand.
and gcc can optimise function calls away (especially with=20 ` attribute("forceinline")`), so it effectively compiles to the same code.=
Apr 07 2015
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/6/15 4:51 PM, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been
 investigating the language for the past few weeks. I was able to
 complete my first useful program thanks to very helpful people in #d on
 IRC . The experience made me very interested in the language and
 improving the community around it.
[snip] http://www.reddit.com/r/programming/comments/31rdp1/excited_about_d/ https://twitter.com/D_Programming/status/585472101349462020 https://www.facebook.com/dlang.org/posts/1046466315367049 Share away! Andrei
Apr 07 2015
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/6/2015 4:51 PM, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been investigating the
 language for the past few weeks. I was able to complete my first useful program
 thanks to very helpful people in #d on IRC . The experience made me very
 interested in the language and improving the community around it.

 I'm primarily Ruby developer (been so about the last 7-8 years) doing web stuff
 with significant JavaScript work as well. I wrote a blog post on why I'm
excited
 about D. You can read it here: http://hawkins.io/2015/04/excited-about-d/.

 I've been reading the forums here so I can see that there is a focus on
 improving the marketing for the language and growing the community. I see most
 of the effort is geared towards C++ programmers, but have you considered
looking
 at us dynamic languages folk? I see a big upside for us. Moving from Ruby to D
 (my case) gives me power & performance. I still have OOP techniques but I still
 have functional things like closures and all that good stuff. Only trade off in
 the Ruby case is metaprogramming. All in all I think there is a significant
 value promise for those of us doing backend services for folks like me.

 Regardless, I figured it might be interesting to hear about some experience
 coming to the language from a different perspective. Cheers!
This is a nice article, thanks! I noticed a bug in one of the examples: assert("Adam Hawkins" == myName()); should be: assert("Adam Hawkins" == myName());
Apr 07 2015
next sibling parent reply "Jens Bauer" <doctor who.no> writes:
On Tuesday, 7 April 2015 at 16:29:40 UTC, Walter Bright wrote:
 I noticed a bug in one of the examples:

   assert("Adam Hawkins" == myName());

 should be:

   assert("Adam Hawkins" == myName());
-It already is. :) By the way; the reason to switch from C to D can be put *very* simple: :C -> :D ... or if you prefer the longer version: :-C -> :-D
Apr 07 2015
parent "Jens Bauer" <doctor who.no> writes:
On Tuesday, 7 April 2015 at 16:39:39 UTC, Jens Bauer wrote:
  :C  ->  :D
Even better (includes the meaning of '=' in place of 'when'): =C -> =D
Apr 07 2015
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/7/2015 9:28 AM, Walter Bright wrote:
 I noticed a bug in one of the examples:

    assert("Adam Hawkins" == myName());
er, the example is: assert("Adam Hawkins" = myName());
 should be:

    assert("Adam Hawkins" == myName());
Apr 07 2015
parent reply "bachmeier" <no spam.com> writes:
On Tuesday, 7 April 2015 at 17:03:55 UTC, Walter Bright wrote:
 On 4/7/2015 9:28 AM, Walter Bright wrote:
 I noticed a bug in one of the examples:

   assert("Adam Hawkins" == myName());
er, the example is: assert("Adam Hawkins" = myName());
 should be:

   assert("Adam Hawkins" == myName());
You're such a good programmer that you can't write code with a bug in it even if you try.
Apr 07 2015
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/7/2015 10:33 AM, bachmeier wrote:
 You're such a good programmer that you can't write code with a bug in it even
if
 you try.
We're all susceptible to making certain types of errors. Over time, we learn to compensate for those errors, and don't make them any more. I can't remember the last time I made the = == mistake. It's probably why that error in the article glared out at me. If you really want to mess with my head, design a language with = and == reversed.
Apr 07 2015
parent reply "H. S. Teoh via Digitalmars-d" <digitalmars-d puremagic.com> writes:
On Tue, Apr 07, 2015 at 11:04:35AM -0700, Walter Bright via Digitalmars-d wrote:
 On 4/7/2015 10:33 AM, bachmeier wrote:
You're such a good programmer that you can't write code with a bug in
it even if you try.
We're all susceptible to making certain types of errors. Over time, we learn to compensate for those errors, and don't make them any more. I can't remember the last time I made the = == mistake. It's probably why that error in the article glared out at me. If you really want to mess with my head, design a language with = and == reversed.
Actually, I find the current use of = vs. == in programming languages rather counterintuitive, even though I myself have become accustomed to it as you have. If I were ever to invent my own programming language, I'd use = for equality and := for assignment. (I wouldn't include ==, though; I think it's an eyesore.) T -- It is the quality rather than the quantity that matters. -- Lucius Annaeus Seneca
Apr 07 2015
parent "Ola Fosheim =?UTF-8?B?R3LDuHN0YWQi?= writes:
On Tuesday, 7 April 2015 at 18:21:44 UTC, H. S. Teoh wrote:
 Actually, I find the current use of = vs. == in programming 
 languages
 rather counterintuitive, even though I myself have become 
 accustomed to
 it as you have. If I were ever to invent my own programming 
 language,
 I'd use = for equality and := for assignment. (I wouldn't 
 include ==,
 though; I think it's an eyesore.)
Simula uses =, <=, >=, <> for value comparison. For references comparison: ==, =/=. Value assignment is done with := and :- is used for reference assignment. I am not sure if I like the visual confusion of references and having to type *this in C++... With reference operators you bypass all the dereferencing clutter.
Apr 07 2015
prev sibling parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
On 4/6/15 8:51 PM, Adam Hawkins wrote:
 Hello everyone, this is my first post on the forum. I've been
 investigating the language for the past few weeks. I was able to
 complete my first useful program thanks to very helpful people in #d on
 IRC . The experience made me very interested in the language and
 improving the community around it.

 I'm primarily Ruby developer (been so about the last 7-8 years) doing
 web stuff with significant JavaScript work as well. I wrote a blog post
 on why I'm excited about D. You can read it here:
 http://hawkins.io/2015/04/excited-about-d/.

 I've been reading the forums here so I can see that there is a focus on
 improving the marketing for the language and growing the community. I
 see most of the effort is geared towards C++ programmers, but have you
 considered looking at us dynamic languages folk? I see a big upside for
 us. Moving from Ruby to D (my case) gives me power & performance. I
 still have OOP techniques but I still have functional things like
 closures and all that good stuff. Only trade off in the Ruby case is
 metaprogramming. All in all I think there is a significant value promise
 for those of us doing backend services for folks like me.

 Regardless, I figured it might be interesting to hear about some
 experience coming to the language from a different perspective. Cheers!
"Ruby was never intended to be correct" -> I think Ruby is the most correct language I've seen around. ~~~ a = [] a << a ~~~ This is just an example. Using Ruby and reading its source code I found so many things that they get right, like border-cases, that I'm surprised you say that. It's true that Ruby is slow, but only because their priority is correctness.
Apr 07 2015
next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Tuesday, 7 April 2015 at 17:46:45 UTC, Ary Borenszweig wrote:
 It's true that Ruby is slow, but only because their priority is 
 correctness.
https://www.destroyallsoftware.com/talks/wat
Apr 07 2015
parent Jacob Carlborg <doob me.com> writes:
On 2015-04-07 19:53, deadalnix wrote:

 https://www.destroyallsoftware.com/talks/wat
That is mostly for JavaScript. -- /Jacob Carlborg
Apr 08 2015
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2015-04-07 19:46, Ary Borenszweig wrote:

 It's true that Ruby is slow, but only because their priority is
 correctness.
I don't think it's so much about the correctness, it's rather the complicated features it supports, like metaprogramming. eval and bindings are causing problems, also promoting Fixnum to Bignum when it doesn't fit is a problem. I also read somewhere that since you can replace any method in Ruby, all calls to a method needs to check if the method has been replaced. Here's a blog that talks about the problems of optimizing Ruby [1] [1] http://blog.headius.com/2012/10/so-you-want-to-optimize-ruby.html -- /Jacob Carlborg
Apr 08 2015
parent Ary Borenszweig <ary esperanto.org.ar> writes:
On 4/8/15 4:59 AM, Jacob Carlborg wrote:
 On 2015-04-07 19:46, Ary Borenszweig wrote:

 It's true that Ruby is slow, but only because their priority is
 correctness.
I don't think it's so much about the correctness, it's rather the complicated features it supports, like metaprogramming. eval and bindings are causing problems, also promoting Fixnum to Bignum when it doesn't fit is a problem.
The autopromotion of Fixnum to Bignum is interesting. It always leads to correct code, although it's slow. Without this feature you start to realize how week are other languages. For example, take the simple problem of parsing a number out of a string. In Ruby it's: But this also works: 12398123091823091823091823091823091820318203123 In typed language one would be forced to make a decision for the return type of to_i. Maybe if it doesn't fit in an Int32 or Int64 raise an exception or signal an error somehow. In Ruby you just forget about these little problems, it will always work and give the correct result. That's one of the reasons I think it's bad to say that Ruby is not a "correct" language.
Apr 08 2015