March 19, 2015
On Wednesday, 18 March 2015 at 12:59:17 UTC, bearophile wrote:
> High level constructs in D are often slower than low-level code, so in some cases you don't want to use them.

I actually found that LDC does an _amazing_ job of optimizing high level constructs and converting "low level" code to higher level functional code resulted in minor speedups in a lot of cases.


(Other performance benefits include the algorithm primitives being extensively optimized in phobos.)
March 19, 2015
On 3/18/2015 5:34 PM, cym13 wrote:
> Maybe there should be a "part 2" to the C-to-D little tutorial, one that shows
> how to code at a higher level introducing gently functional structures instead
> of just teaching how to write C in D. To stop thinking about steps to think
> about transformations isn't an easy thing.

Andrei and I talked about this, how we are failing to point out how to idiomatically use D to advantage. We need to do a lot better at this.
March 19, 2015
On Friday, 13 March 2015 at 15:03:37 UTC, bearophile wrote:
> Andrei Alexandrescu:
>
>> That's a rather random collection - "strict" seems to be "D without the stuff bearophile dislikes". -- Andrei
>
> I am OK with that definition. Is that your best critique to those suggestions? :-)
>
> Bye,
> bearophile

:) I'd use that.
March 19, 2015
On Wed, 2015-03-18 at 13:27 +0000, CraigDillabaugh via Digitalmars-d wrote:
> 
[…]
> There is quite possibly something too that, and as I imagine with more functional experience it will come easier to me.
> 
> However, I still think imperative code is generally easier to
> reason about because (usually) each line of code is performing
> a single task, whereas with functional coding the goal seems
> to be to cram as many operations as possible into a single line
> (I know that isn't the real reason, it just seems that way at
> times).  Trying to 'unroll' everything in your head can be a
> challenge.  Throw in a lambda function or two with
> the mess of braces/symbols and then you have a real puzzler.

Each imperative statement may (or may not) be easier to understand, but the problem is putting them together in combination. The issue here is creating chunks on which you put a label for reasoning with. Everything is about the abstractions you reason with. A person who is familiar only with C-style programming (as per OPs code fragment) has built up various abstractions, but they are nonetheless at a very low level and so many have to be combined.

Someone who has learned the internal iteration abstraction and higher- order functions is actually working at a higher level of abstraction and generally needs to combine fewer things to achieve the overall goal. Cramming operations on a line is nothing to do with the abstractions, that is to do with some people playing code golf.

If you find yourself reading declarative style code and having to unroll to imperative equivalent to understand, it just means you have not yet internalized the declarative abstraction yet into your mental model and personal programming language.

There is a lot of work on all this sort of stuff in the psychology of programming research literature. We can speculate all we like here based on personal experience and anecdotal evidence, they do experiments and have real data. Of course if you see any experimenting on first and second year undergraduates of computer science, ignore the results. I am talking about those who experiment with practicing programmers, people with real experience and expertise.

-- 
Russel. ============================================================================= Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder@ekiga.net 41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel@winder.org.uk London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder


March 19, 2015
On 3/18/2015 4:41 PM, Walter Bright wrote:
> #include <stdbool.h>
> #include <stdio.h>
>
> typedef long T;
> bool find(T *array, size_t dim, T t) {
>   int i;
>   for (i = 0; i <= dim; i++);
>   {
>      int v = array[i];
>      if (v == t)
>          return true;
>   }
> }

Bugs:

1. i should be size_t
2. <= should be <
3. extraneous ;
4. v should be type T
5. missing return

March 19, 2015
On Thursday, 19 March 2015 at 08:17:42 UTC, Russel Winder wrote:
> On Wed, 2015-03-18 at 13:27 +0000, CraigDillabaugh via Digitalmars-d wrote:
>> 
> […]
>> There is quite possibly something too that, and as I imagine
>> with more functional experience it will come easier to me.
>> 
>> However, I still think imperative code is generally easier to
>> reason about because (usually) each line of code is performing
>> a single task, whereas with functional coding the goal seems
>> to be to cram as many operations as possible into a single line
>> (I know that isn't the real reason, it just seems that way at
>> times).  Trying to 'unroll' everything in your head can be a
>> challenge.  Throw in a lambda function or two with
>> the mess of braces/symbols and then you have a real puzzler.
>
> Each imperative statement may (or may not) be easier to understand,
> but the problem is putting them together in combination. The issue
> here is creating chunks on which you put a label for reasoning with.
> Everything is about the abstractions you reason with. A person who is
> familiar only with C-style programming (as per OPs code fragment) has
> built up various abstractions, but they are nonetheless at a very low
> level and so many have to be combined.
>
> Someone who has learned the internal iteration abstraction and higher-
> order functions is actually working at a higher level of abstraction
> and generally needs to combine fewer things to achieve the overall
> goal. Cramming operations on a line is nothing to do with the
> abstractions, that is to do with some people playing code golf.
>
> If you find yourself reading declarative style code and having to
> unroll to imperative equivalent to understand, it just means you have
> not yet internalized the declarative abstraction yet into your mental
> model and personal programming language.
>
> There is a lot of work on all this sort of stuff in the psychology of
> programming research literature. We can speculate all we like here
> based on personal experience and anecdotal evidence, they do
> experiments and have real data. Of course if you see any experimenting
> on first and second year undergraduates of computer science, ignore
> the results. I am talking about those who experiment with practicing
> programmers, people with real experience and expertise.

I just saw a talk of one of those studies.

One of the points was that curly braces languages lead to more bugs than languages that follow the Algol more verbose style.

CodeMesh 2014 - Andreas Stefik - The Programming Language Wars

https://www.youtube.com/watch?v=mDZ-QSLQIB8

Quite interesting when one mixes psychology research with language features, backed by validated research data.

--
Paulo
March 19, 2015
On Tuesday, 17 March 2015 at 18:29:20 UTC, Almighty Bob wrote:
> On Tuesday, 17 March 2015 at 11:48:15 UTC, Nick Treleaven wrote:
>> On 17/03/2015 10:31, Almighty Bob wrote:
>>> It's far more useful for csvReader to return a type I know and
>>> can use than it is to obscure the return type for the sake of
>>> some philosophical ideal of increasing encapsulation.
>>
>> Part of the art of API design is to hide implementation where it's not necessarily needed. Designers might err on the side of hiding things, because how you expose something is important as it has to be maintained indefinitely. If they expose everything then the internals can never be redesigned for better performance, etc.
>
> They don't increase encapsulation. The public members of a voldomort type are still public, you still have to code to the API of the return type whether it's a regular or voldomort type. You can keep as much private or public in either case as you like.
>
> All they do take the typename out of circulation, they make life harder for the user. There's no benefit. None.
>
> But at least the library author can stroke his chin a feel smug that there's one less type in the modules' namespace.

Totally missing the point. The crux of the matter is this: changing a voldemort type (assuming the public semantics are the same) is not a breaking API change, because no-one else's code ever names it.

Admittedly this is sort-of true for any function that returns auto and doesn't document its return type, but that is by convention (the type is always readable in the relevant .d or .di file) whereas using a voldemort type enforces it.

Note that if you really want a name to use in your code:
alias IotaFloat = typeof(iota(0f, 2f, 1f));
March 19, 2015
On Wednesday, 18 March 2015 at 01:52:00 UTC, Laeeth Isharc wrote:
> On Tuesday, 17 March 2015 at 21:00:11 UTC, bachmeier wrote:
>> On Tuesday, 17 March 2015 at 19:00:06 UTC, jmh530 wrote:
>>> In addition, further development of the ability to call D from R or Python* or Julia (or vice-versa) would also be a positive.
>>
>> What do you have in mind? I no longer work much with Python so my knowledge is limited, but calling D from R or Julia should be no different from calling C from those languages, as you normally compile your C code into a shared library anyway.
>>
>> I've done the R->D thing many times and in the process have worked with a big chunk of the R API. Things like allocating R data structures from a D function, adding assertions to your D code to allow for an easy exit when things don't work out, and calling functions in the R math library, among other things, are not difficult.
>
> (I wonder how well cython works with interfacing with D via the C++ interface, because that way you could extend python with D classes and have them be faster than going through PyD).

This is a good idea. dtoh could speed up this workflow, see https://github.com/adamdruppe/dtoh/blob/master/dtoh.d and http://forum.dlang.org/post/uyuwdptkpukshxzygqpn@forum.dlang.org
March 19, 2015
On Thursday, 19 March 2015 at 00:42:51 UTC, weaselcat wrote:
> On Wednesday, 18 March 2015 at 12:59:17 UTC, bearophile wrote:
>> High level constructs in D are often slower than low-level code, so in some cases you don't want to use them.
>
> I actually found that LDC does an _amazing_ job of optimizing high level constructs and converting "low level" code to higher level functional code resulted in minor speedups in a lot of cases.
>
>
> (Other performance benefits include the algorithm primitives being extensively optimized in phobos.)

If the code/compiler generates suboptimal code in the first place then improvements can be somewhat random. But if you write code with good cache locality, filling the pipeline properly then  there is no alternative to going low level.

Btw, take a look at this:
http://stackoverflow.com/questions/28922323/improving-line-wise-i-o-operations-in-d

That's really bad marketing...
March 19, 2015
On Thursday, 19 March 2015 at 16:59:36 UTC, Ola Fosheim Grøstad wrote:
> On Thursday, 19 March 2015 at 00:42:51 UTC, weaselcat wrote:
>> On Wednesday, 18 March 2015 at 12:59:17 UTC, bearophile wrote:
>>> High level constructs in D are often slower than low-level code, so in some cases you don't want to use them.
>>
>> I actually found that LDC does an _amazing_ job of optimizing high level constructs and converting "low level" code to higher level functional code resulted in minor speedups in a lot of cases.
>>
>>
>> (Other performance benefits include the algorithm primitives being extensively optimized in phobos.)
>
> If the code/compiler generates suboptimal code in the first place then improvements can be somewhat random. But if you write code with good cache locality, filling the pipeline properly then  there is no alternative to going low level.
>
> Btw, take a look at this:
> http://stackoverflow.com/questions/28922323/improving-line-wise-i-o-operations-in-d
>
> That's really bad marketing...

python:
time python2 wc.py enwiki-latest-pages-articles1.xml-p000000010p000010000
There are 1245473 lines
python2 wc.py enwiki-latest-pages-articles1.xml-p000000010p000010000  0.21s user 0.08s system 99% cpu 0.294 total

wc -l:
time wc -l enwiki-latest-pages-articles1.xml-p000000010p000010000
1245472 enwiki-latest-pages-articles1.xml-p000000010p000010000
wc -l enwiki-latest-pages-articles1.xml-p000000010p000010000  0.05s user 0.02s system 96% cpu 0.072 total


iterative version:
ldc -O5 -inline -release -boundscheck=off wc.d
time ./wc
There are 1245473 lines.
./wc enwiki-latest-pages-articles1.xml-p000000010p000010000  0.59s user 0.07s system 99% cpu 0.661 total

functional version:
writeln("There are ", (cast(string)read(args[1])).splitter('\n').array.length, " lines.");

ldc -O5 -inline -release -boundscheck=off wc.d
time ./wc enwiki-latest-pages-articles1.xml-p000000010p000010000
There are 1245473 lines.
./wc enwiki-latest-pages-articles1.xml-p000000010p000010000  0.04s user 0.08s system 98% cpu 0.125 total


ahem
>> I actually found that LDC does an _amazing_ job of optimizing high level constructs and converting "low level" code to higher level functional code resulted in minor speedups in a lot of cases.