Functional programming in D and some reflexion on the () optionality.

deadalnix deadalnix at gmail.com
Mon Aug 6 09:40:01 PDT 2012


It is known that some part of D are very dmd's implementation defined. 
One of the part is manipulation function as first class objects and 
implicitly calling them.

Some digressions about functional programing first.

Functional programming emphasis function purity, function as first class 
objects and immutability (among other things). Now, function is data 
(and can be passed as first class object to other function for instance) 
but no difference exists anymore between data and function.

A function which is pure, with no parameters, will always return the 
same value. The difference between what is a function without argument 
and what is a constant is up to the compiler.

The same way, the difference between a delegate and an expression don't 
exist anymore.

This allow functional style to remove explicit call of functions. In 
fact, when does the function get called is irrelevant, because they are 
pure. This is for instance THE thing is haskell.

The difference between a function call and a delegate creation is 
blurred, don't exists anymore and don't matter anymore regarding program 
result.

D intend to implement functional, and get an mix of all the feature 
cited above, but in a way that don't work properly and is mostly dmd's 
implementation defined.

Let's put aside the @property phenomena, this isn't that important here.

To me, the first big failure of D to implement functional style is to 
not have first class functions. You get a function using & operator. But 
does it really make sense ? See code below :

void foo(){}
void bar(void function() buzz) {}

void main() { bar(foo); } // This will execute foo, and so fail. 
Functions are not first class objects.

void main() {
     auto bar = &foo;
     foo(); // Do something.
     bar(); // Do the same thing.
     auto buzz = &bar;
     (*buzz)(); // Do the same thing.
}

Functions don't behave the same way is they are variables or declared in 
the source code.

Worse, foo was before a function call. Now it isn't anymore. foo, as a 
expression have a different meaning depending on what is done on it. It 
would become very confusing if foo return a reference, so it is an 
lvalue and & is a valid operation on the function call.

As D don't enforce purity like functional programing does, it can't be 
up to the compiler to decide when does the function get executed.

Then come UFCS. UFCS allow for function calls with parameters. It is 
still inconsistent.

void foo(T)(T t) {}

a.foo; // foo is called with a as argument.
&a.foo; // error : not an lvalue

Now let imagine that foo is a member function of a, &a.foo become a 
delegate. a.foo is still a function call. This is still quite inconsistent.

Implementing all this is almost impossible when you add @property into 
the already messy situation. Additionally, the current implement fails 
to provide the basics of functional programing, and break several 
abstraction provided by other languages features. C++ has proven that 
bad association of good language features lead to serious problems.

This require to be formalized in some way and not based on dmd's 
implementation. Inevitably, the process will lead to code breakage 
(adding or removing some ()/&).

Reading the @property thread, it seems that most people want to keep 
dmd's current behavior. Because code rely on it. This make sense, but if 
dmd's implement is the only goal, it means that other compiler are only 
to be reverse engineering dmd's behavior, and are guaranteed to lag 
behind. Considering this, I seriously wonder if it make sense to even 
try to follow dmd's behavior and decide whatever seems the right one 
when writing a D compiler, which will result in community split, or no 
alternative compiler produced for D.

I also have some proposal to fix thing, even some that would allow 
a.map!(...).array() to still be available. But inevitably, some other 
construct will broke. At this point, what matter isn't really what 
solution is adopted, but do we still want to be dependent on dmd 
implementation for D features.


More information about the Digitalmars-d mailing list