"Mogens Hansen" <mogens_h@dk-online.dk> wrote
> "Bjarke Dahl Ebert" <bebert@worldonline.dk> wrote
>
[snip]
> > Min egen anti-C++-farvede holdning er at metoden med at bruge "<<" er at
> > grimt hack. Man forsøger næsten at putte en ny konstruktion ind i
sproget
> > (man må indrømme at
> >
> > cout << "Hello: " << i << ", " << j << endl;
> >
> > ser ud som om sproget har en form for print-statement), men dog uden at
> > ændre sproget, kun standard-biblioteket.
>
> Sådan kan man se så forskelligt på det.
> For mig er det en af de fundament sunde tanker i C++, at lægge så meget
> funktionalitet i biblioteker, og at dem der skriver Standard Library ikke
> har adgang til særlige egenskaber. Alle kan skrive biblioteker
> * som passer til et givent domæne
> * som ligner sprogudvidelser, hvis det er passende
> * kan have samme performance som indbygget funktionalitet
> Jeg skal nok uddybe det synspunkt lidt senere - jeg har ikke mere tid lige
> nu.
>
Jeg syntes udsagnet "Biblioteks design _er_ sprog design" er vældigt
fornuftigt.
Jeg anser det for at være en stor styrke at man ikke behøves at være
compiler konstruktør, og man ikke behøves at få godkendelse fra ISO C++
standard komiteen, for at kunne tilføje nyttige abstraktioner, som opfører
sig lige så godt som hvis de var bygget direkte ind i sproget.
Det er nyttigt fordi det giver mig som programmør stor frihed til at vælge
og eksperimentere, og dermed opbygge erfaring.
Det er nyttigt fordi der findes mange flere dygtige folk, der har nyttige
ideer, end der findes compiler konstruktører. Derfor giver designet i C++
alle disse dygtige folk mulighed for at ytre sig.
Det er nyttigt fordi bibliotekerne, hvis de baserer sig på ISO C++, typisk
umiddelbart vil være tilgængelige for et bredt publikum.
For mig aftvinger det dyb respekt, at de utvivlsomt meget dygtige folk, der
har været involveret i designet af C++, har erkendt at de ikke ved hvad der
er bedst for alle mennesker, og derfor har lagt meget vægt på at løse
generelle problemer og derved understøtte muligheden for at lave nye
konstruktioner, som de ikke havde tænkt på.
Prøv at se det konkrete eksempel, streaming.
Det er ikke forbeholdt nogen, at definere et lukket set af typer som kan
streames. Jeg kan til enhver tid definere "my_class" og definere hvordan den
skal skrives ud, på en effektiv og typesikker måde. Det er fundamentalt
anderledes end "printf" i C.
Der er mange eksempler på biblioteker, der nærmest putter nye konstruktioner
ind i sproget, til stor glæde mange.
Hvis ikke C++ havde været designet på den måde havde STL ikke eksisteret.
Så vidt jeg har forstået, valgte Alex Stephanov (hoved designeren af STL)
ikke C++ til at implementere STL fordi han var dybt involveret i C++.
Han havde først prøvet at implementere det i Ada, men kunne ikke. Alex
Stephanov var dybt involveret i generisk programmering, og C++'s template
mekanisme var et redskab der var tilstrækkeligt til at udtrykke det han
ønskede.
Andre _eksempler_ på biblioteker, der nærmest putter nye konstruktioner ind
i sproget er
* BLL - Lambda biblioteket i Boost
(
http://www.boost.org/libs/lambda/doc/index.html).
* Spririt - et parser bibliotek (
http://spirit.sourceforge.net/)
* MTL - et matrix template library
(
http://www.osl.iu.edu/research/mtl/intro.php3)
BLL gør det muligt at skrive, sådan noget som
for_each(a.begin(), a.end(), std::cout << _1 << ' ');
Spirit gør det muligt nærmest at skrive EBNF (Extended Backus Normal Form) i
ren C++, når man beskriver en parser.
F.eks. er
rule<> expr;
rule<> integer = lexeme[ (!(ch_p('+') | '-') >> +digit)[&doInt] ];
rule<> group = '(' >> expr >> ')';
rule<> expr1 = integer | group;
rule<> expr2 = expr1 >> *(('*' >> expr1)[&doMult] | ('/' >>
expr1)[&doDiv]);
expr = expr2 >> *(('+' >> expr2)[&doAdd] | ('-' >> expr2)[&doSubt]);
en komplet beskrivelse af en parser til regnestykker som f.eks. "1 + ((6 *
200) - 20) / 6".
"doInt", "doAdd", "doMult" og "doDiv" er simple funktioner, der behandler de
enkelte del udtryk:
void doInt(char const* str, char const* end)
{
string s(str, end);
cout << s << endl;
}
void doAdd(char const*, char const*) { cout << "ADD\n"; }
void doSubt(char const*, char const*) { cout << "SUBT\n"; }
void doMult(char const*, char const*) { cout << "MULT\n"; }
void doDiv(char const*, char const*) { cout << "DIV\n"; }
Konsekvensen af at vælge at lægge meget funktionalitet i biblioteker i
stedet for direkte i sproget (core language), gør det muligt at understøtte
mange flere specielle domainer (f.eks. parsere, matricer), på måder der er
naturlige for domainet.
Venlig hilsen
Mogens Hansen