On Monday, 6 August 2012 at 16:40:02 UTC, deadalnix wrote:
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.
...

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.
}

This comes from the 'real' function type is 'void f()' whose usage is deprecated in D except for any function-/method-declaration: Imagine a C-style declaration of the fuction type and you'll come to the conclusion it's the way one defines functions in C/C++/D. But this type has a big quirk: it's variable length because different fuctions with the same signature can have a different amount of machine instuctions. Therefore this can't be stored, passed or returned. You can't have array of them. The only exception is when you define a constant, then it's a funciton definition. Now because of this there is a need for another type equivalent to the function itself: its address. It's written 'void (*f)()' in C. This type is mostly reffered to as function even though it's only its address. Now D wants to go away from C declarations so the 'void function()' syntax was invented. Regardless of its name it's only the pointer to the actual functions even though D allows you to call it without dereferencing.


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

This is because the former a function pointer and the latter are actual funtions.

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.

Because any usage of a function except a call or address-taking are complete non-sense, the functions is implicitly called if it hasn't got any parameters.

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

Even though it's written like that, the function is not called with the member calling convention. You can't create a transperent delegate of it because the function does not expect to get 'a' as a 'this'-parameter.

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.

Maybe it is. But it comes from the fact that ufcs is an afterthought.

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 don't like authorative formal specs. It means most things are set in stone and you have to write a new spec every once in a while which slows down development of awesome language features.

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.

Mafi


Reply via email to