On 09/21/2011 10:20 PM, Andrei Alexandrescu wrote:
On 9/21/11 2:29 PM, Timon Gehr wrote:
On 09/21/2011 06:55 PM, Andrei Alexandrescu wrote:
I'm back from the Strange Loop conference. It's been an interesting
experience. The audience was very diverse, with interest in everything
functional (you'd only need to say "Haskell" or "monad" to get positive
aahs), Web/cloud/tablet stuff, concurrent and distributed systems.
Mentioning C++ non-mockingly was all but a faux pas; languages like
Scala, Haskell, Clojure, and Erlang got attention. The quality of talks
has been very variable, and unfortunately the
over-confident-but-clueless-speaker stereotype was well represented.

I gave a talk there
(https://thestrangeloop.com/sessions/generic-programming-galore-using-d)
which has enjoyed moderate audience and success. I uploaded the slides
at http://erdani.com/d/generic-programming-galore.pdf and the video may
be available soon.

I am looking forward to it!


There was a very strong interest in D's CTFE abilities, which we should
consider a strategic direction going forward.

One milestone would be to make DMD GC enabled. CTFE string manipulation
sucks up too much memory.

Also finalizing D's
concurrency language and library infrastructure is essential. These two
features are key differentiators. Also, capitalizing on D's functional
features (which are e.g. better than Scala's but less known) would add
good value.


Where D still loses when compared to Scala is functional code syntax:

val newcol = collection filter {x=>x<5} map {x=>2*x}

Yoda this wrote.

Actually it is the order in which it will (conceptually at least) be executed =). D can do similar things on arrays with UFCS.


or maybe

val newcol = for(x<-collection if(x<5)) yield 2*x

Too baroque.

vs

auto newrange = filter!((x){return x<5;})(map!((x){return 2*x;})(range));

auto newrange = filter!"a<5"(map!"2*a"(range));

At first some people get the heebiejeebies when seeing string-based
lambda and the implicit naming convention for unary and binary
functions.

Yes, I have seen it happen multiple times. There are even people who consider strings-as-code an evil concept entirely :o). How are CTFE and string mixins best introduced to people who think they might be too lazy to bother about learning more about the language?

More importantly, there's the disadvantage you can't access
local functions inside a string lambda.

I often want to do that. We could replace the 5 and 2 constants by stack variables, and then the point would be made.

We should probably add a
specialized lambda syntax.

It would probably be a simple addition as it is restricted mostly to the parser.

Like this? Or is there a better lambda syntax around?

int u,v;
auto newrange=map!(x=>u*x)(filter!(x=>v<x)(range));

auto newrange = range.filter!(x=>v<x).map!(x=>u*x);



I believe that is part of the reason why it is less known. If I write
functional style code in D I unfortunately usually get feedback that it
is "extremely hard to read". Furthermore, Scala has built-in tuples, and
eg delimited continuations, which enable some more functional
programming idioms. std.algorithm/std.range are also considerably (and
as I understand, deliberately) underpowered for FP when compared to eg
Haskell's standard set of libraries, and writing a good range from
scratch is usually a serious undertaking.

I wonder what Scala/Haskell idioms we should borrow for D.

In my opinion these are worth looking into:

Haskell: This might not happen, but having a tiny little function with a literate name for most common tasks is very convenient. I think other Haskell idioms not already in D are hard to translate because the type system and execution model of the two languages are so different. I have managed to use D for haskell-lookalike toy examples nonetheless. (it leads to extremely obfuscated code because of many nested lambdas and a bug in the lazy storage class that needs to be worked around)

Both: (Concise expression-based lambdas.) Pattern matching, if it can be incorporated in a good way. (dynamic) lazy evaluation. Scala has lazy val. It would play very nicely with Ds purity, but maybe suboptimally with immutable (for immutable structures, the lazy fields would have to be computed eagerly)

Generators? (those are implicit in Haskell) Something like this example would automatically create a compile-time lazy range to compute a power set efficiently.

auto powerset(T)(T[] x) {
    foreach(i;0..1<<x.length) {
        yield (size_t i){
            while(i){
                yield x[bsf(i)];
                i &= i-1;
            }
        }(i);
    }
}

Equivalent code that spells out the nested structs with all the front/popFront/empty etc contains considerable boilerplate. I am not sure how powerful it could be, but it should be possible to automatically let the following example propagate random access iff fun is pure, based on the observation that it does not have state:

auto map(alias fun, R)(R m){
    foreach(x; m) yield unaryFun!fun(x);
}

The range concept is very important in D code, some syntactic sugar like this would help a lot.


Another big advantage that Scala has is that it supports pattern
matching. It is usually about the first feature functional programmers
care about.

What do you think is the biggest advantage that Ds functional
programming has in comparison to Scala's?

1. True immutability

2. True purity

Compiler-enforced immutability and purity.


3. Pass by alias


It is extremely nice how templates are automatically instantiated in the correct scope. The fact that delegates are constrained to one context pointer and that static function literals don't decay to delegates tends to be annoying though. (also, that there is no inference if a context pointer is needed)

For a language that has so firmly branded itself as functional, Scala
has a surprisingly poor handling of immutability and referential
transparency aka purity. My understanding is that Scala's immutability
merely consists of final values and a web of conventions. (Please
correct me if I'm wrong.)


I think you are right. But in Scala, much of the language semantics are actually implemented in the library. The immutable collections could be considered truly immutable by some.

Reply via email to