Functional programming in D and some reflexion on the () optionality.
David Piepgrass
qwertie256 at gmail.com
Mon Aug 6 11:05:49 PDT 2012
> 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.
I'm not sure if I understand your point perfectly, but I
definitely feel that the way D handles optional parens is awful.
The other day I noticed that the following is a syntax error (DMD
2.059):
class A { void B() {} }
auto a = new A().B();
// ^ semicolon expected following auto declaration, not '.'
Even without silly errors like this, optional parenthesis create
ambiguities, and ambiguities are bad. Maybe there is a sane way
for parenthesis to be optional, but the way I've seen D behaving
is *bizarre*.
The compiler should *expect* parenthesis, and only assume that
the parenthesis are missing if it's the only way to compile
without an immediate error. So for example,
- if foo is a non- at property function that returns another
function, foo() must invoke foo itself and never the function
that foo returns.
- if I say "&foo" where foo is a non- at property function, it
should always take the address of the function, never take the
address of the return value.
- The rules shouldn't change if you replace "foo" with a complex
expression like "x.y[z]" or "new Module.ClassName".
More information about the Digitalmars-d
mailing list