Go rant

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Dec 21 11:51:08 PST 2009


retard wrote:
> Mon, 21 Dec 2009 12:13:48 -0600, Andrei Alexandrescu wrote:
> 
>> Daniel de Kok wrote:
>>> On 2009-12-19 21:04:32 +0100, Andrei Alexandrescu
>>> <SeeWebsiteForEmail at erdani.org> said:
>>>> "This code is shown for its elegance rather than its efficiency. Using
>>>> ++ in this way is not generally considered good programming practice."
>>>>
>>>> So if the code is inefficient and in poor programming practice, how in
>>>> this blessed world could it count as elegant?
>>> Well, it is elegant in that it is very readable, and as such provides
>>> educational value.
>> I disagree. We don't want to educate people to write patently
>> inefficient code and in poor programming practice.
>>
>> When I was doing Windows programming, I noticed that many example in the
>> documentation were written in terrible style. I also noticed that much
>> of the production code I was working with was often stitched from
>> documentation examples.
>>
>>> There are very many examples in programming text books that may not be
>>> efficient, but do show the solution to a problem elegantly.
>> Yeah, exponential-time Fibonacci and bubble sort come to mind.
>>
>> In my mind "elegant" and "at a polynomial blowup in complexity" can't be
>> reconciled anywhere outside a Turing machine introduction where
>> everything is equivalent within a polynomial difference in time and
>> space.
>>
>>> E.g. consider list reversal in a recursive function or predicate. It is
>>> easy to see that to reverse a list, you append the head to the reversed
>>> tail. E.g.:
>>>
>>> reverse([],[]).
>>> reverse([H|T],R) :-
>>>  reverse(T,RT),
>>>  append(RT,[H],R).
>>>
>>> Of course, this is very inefficient, since the program is doing (slow)
>>> appends all the time, and is not tail-recursive. You can do it a lot
>>> faster with an accumulator, but it makes the solution also less
>>> understandable, and not something you'd want to present
>>> students/readers immediately:
>>>
>>> reverse(List,Reverse) :-
>>>  reverse_aux(List,Reverse,[]).
>>>
>>> reverse_aux([],List,List).
>>> reverse_aux([H|T],List,List0) :-
>>>  reverse_aux(T,List,[H|List0]).
>> Yah, I understand. But what you're really saying is that reverse offers
>> either a simple implementation or an efficient implementation, but not
>> both. That's hardly furthering my belief that FP has a crushing
>> advantage over pretty much anything else.
>>
>> In another thread, "retard" wrote in response to the comparison of the
>> real quicksort in C and Haskell:
>>
>> "What is so brilliant? Referential transparency is broken unless single-
>> threadedness is forced through monadic computation or by some other
>> means (uniqueness types comes to mind)."
>>
>> I think that's a roundabout way of saying that functional programming is
>> unable to express certain algorithms easily or at all.
> 
> I think one of the things that make good programming languages good is 
> that they allow hiding the complexity behind abstractions. This is 
> something I remember from the SICP lectures. This is the ideology behind 
> pure functional and pure object oriented programming. Reliability is 
> transitive - if the building blocks are good, you can't screw /those/ 
> things on higher level. Things like referential transparency also give 
> you truly modular isolation in this way. You can always find a loop hole 
> in languages like D.

That all sounds nice and I agree with it, but friction is also 
transitive. Inefficiencies add when you build higher-level abstractions, 
and may force you at some point to choose between good abstraction and 
working program.

The beauty of D is that it has low or often zero friction in the way of 
creating abstractions. That is very difficult to achieve.

As far as loop holes go, D's answer is SafeD. We managed to pull it in 
an extremely short time, and it's in some ways a gambit, but I am 
confident we have made the right decision. Until somebody provides a 
soundness proof a la Featherweight Java, there is no ultimate proof that 
SafeD is in fact safe, but I have reasons to believe there are no 
principle reasons we can't, and if you do find loopholes please let us 
know. Java has had for years safety holes, and naysayers enjoyed 
claiming it will always have. Now it's common knowledge that Java is safe.

> I think I've already read what you think about abstractions. After all, 
> it's not really surprising why in "systems programming languages" like D 
> one can more or less easily convert any high level expression into 
> machine code in their head. On relatively low level it's benefical to 
> always think in terms of machine code instructions, stack layouts, 
> pointers etc.
> 
> But on higher level, performance is in many domains only a secondary 
> goal. Reliability is the main goal. If there's an abstract data type such 
> as a queue or a stack, you simply can't produce traditional stack 
> overflows because the abstraction protects against that. The container 
> code can be really ugly spaghetti internally - the abstraction works as a 
> public interface.

I fail to see how in D you'd be hard pressed to think in terms of lower 
level abstractions.


Andrei



More information about the Digitalmars-d mailing list