D Programmierung
-
Reyx schrieb:
Brutus schrieb:
Was hast du gegen std::for_each()?
Dass es kein Sprachkonstrukt ist ...
diese foreach fixiertheit hab ich noch nie verstanden.
produziert der compiler was besseres als output wenn es ein sprachkonstruckt ist?
-
Brutus schrieb:
Was hast du gegen std::for_each()?
- Ich kann nicht schreiben
std::for_each(vec.begin(), vec.end()){ }Ohne irgendeine Art vernünftiger Lambda Ausdrücken die die Übersetzungszeit nicht verdreifachen ist dies nicht möglich.
- Ich kann nicht schreiben
std::for_each(vec, &output);Sondern muss schreiben
std::for_each(vec.begin(), vec.end(), &output);Dies ist jetzt aber ein Problem der STL und nicht der Sprache. Der Fall wo ich den ganzen Verktor ausgeben will ist nun einmal viel häufiger als der wo ich nur einen Teil ausgeben will. Besser würde ich also finden:
for_each(vec, &output); for_each(make_range(vec.begin(), vec.end()-3), &output);
-
daHa schrieb:
Reyx schrieb:
Brutus schrieb:
Was hast du gegen std::for_each()?
Dass es kein Sprachkonstrukt ist ...
diese foreach fixiertheit hab ich noch nie verstanden.
produziert der compiler was besseres als output wenn es ein sprachkonstruckt ist?
Nicht zwangsläufig... ein foreach braucht man halt einfach verdammt oft und selbst mit auto wird das Durchiterieren immer noch nicht genauso schön wie mit foreach. Überleg mal wie lesbar es den Code macht, wenn da steht "für jedes ding in myList { ... }"
-
Wers unbedingt braucht macht halt nen Makro, aber ne Sprache danach zu bewerten ob es "foreach" gibt...
C und C++ haben nicht umsonst viel weniger Schlüsselwörter als andere Sprachen, sie sind dadurch zwar komplexer, aber die Möglichkeiten schier unbegrenzt.
-
C++ und viel weniger Schlüsselwörter als andere Sprachen? Seit wann dass denn?
-
Makros schrieb:
Wers unbedingt braucht macht halt nen Makro, aber ne Sprache danach zu bewerten ob es "foreach" gibt...
C und C++ haben nicht umsonst viel weniger Schlüsselwörter als andere Sprachen, sie sind dadurch zwar komplexer, aber die Möglichkeiten schier unbegrenzt.Warum sind Sprachen durch weniger Schlüsselworte komplexer? Ob ich nun
virtual void foobar()=0;schreibe, oder
abstract void foobar();macht eine Sprache nicht komplexer, sondern nur unleserlicher.
C++ hat nur aus einem Grund teilweise mit "neuen" Schlüsselwörtern gegeizt: Man wollte soviel C Code wie möglich kompatibel halten.
Aber D sieht wirklich mal sehr interessant aus. Mich wunderts nur, dass man darüber bisher sowenig gehört hat.
-
D ist eben zur zeit version 0.144 und damit noch nicht wirklich produktionsqualitaet. funktionieren tuts wunderbar; es kommen eigentlich nur immer features dazu und minimale bugfixes.
-
D hat keine Daseinsberechtigung.
-
Makros schrieb:
Wers unbedingt braucht macht halt nen Makro, aber ne Sprache danach zu bewerten ob es "foreach" gibt...
Dann mach mal. Wenn du es fertig bringst ein foreach Makro zu bauen dann geb ich einen aus.
-
Optimizer schrieb:
daHa schrieb:
Reyx schrieb:
Brutus schrieb:
Was hast du gegen std::for_each()?
Dass es kein Sprachkonstrukt ist ...
diese foreach fixiertheit hab ich noch nie verstanden.
produziert der compiler was besseres als output wenn es ein sprachkonstruckt ist?
Nicht zwangsläufig... ein foreach braucht man halt einfach verdammt oft und selbst mit auto wird das Durchiterieren immer noch nicht genauso schön wie mit foreach. Überleg mal wie lesbar es den Code macht, wenn da steht "für jedes ding in myList { ... }"
lesbarkeit ist von for schleifen mindestens genauso gut, wenn nicht besser
ausserdem kann ich in for schleifen recht gemuetlich den iteratortype bestimmen, const , reverse, usw.., was bei den gewuneschten foreach so nicht geht, bzw dann nicht mehr so leicht lesbar ist.
diese foreach fixiertheit ist reines marketinggeplapper fuer/von sprachen die das implementiert haben.
und das halt als grossartiges feature (und ueberlegenheit (der eleganz)) der sprache verkaufen.ich persoenlich finde es eleganter, und ueberlegen, wenn ich mir ohne probleme eigene foreach (bzw aehnlich benamst um keine verwirrung zu stiften) erstellen kann, die dann in combi von praeprozessor und compiler optimalen code fabrizieren, eine tatsache die die foreachmarketingplapperer gern uebersehen bzw gar nicht wissen.
-
daHa schrieb:
lesbarkeit ist von for schleifen mindestens genauso gut, wenn nicht besser
typedef std::map<MyKey, MyValue*>::const_iterator Iterator; for( Iterator i = myMap.begin(); i != myMap.end(); ++i ) { cout << (*i)->getMember(); }foreach( MyValue v in myMap ) { Console.Out.WriteLine(v.getMember()); }q.e.d.
ausserdem kann ich in for schleifen recht gemuetlich den iteratortype bestimmen, const , reverse, usw.., was bei den gewuneschten foreach so nicht geht, bzw dann nicht mehr so leicht lesbar ist.
Super Vorteil, der mir aber nichts bringt, wenn ich einfach die Elemente aufzählen will. Kommt bei mir wesentlich öfters vor, als irgendwas spezielleres. foreach soll ja gar nicht alles abdecken, sondern nur elegant aufzählen. Ich verstehe auch gar nicht, was daran "gemütlich" sein soll, wenn ich immer nen Iterator-typedef machen muss. Ich glaub die C++ - Community freut sich nicht ohne Grund auf das verbesserte auto.
diese foreach fixiertheit ist reines marketinggeplapper fuer/von sprachen die das implementiert haben.
und das halt als grossartiges feature (und ueberlegenheit (der eleganz)) der sprache verkaufen.Nö, ich mag's. Und ich bin kein Wirtschaftler.
ich persoenlich finde es eleganter, und ueberlegen, wenn ich mir ohne probleme eigene foreach (bzw aehnlich benamst um keine verwirrung zu stiften) erstellen kann, die dann in combi von praeprozessor und compiler optimalen code fabrizieren, eine tatsache die die foreachmarketingplapperer gern uebersehen bzw gar nicht wissen.
Du kannst kein gescheites foreach basteln, ganz einfach, wenn du es irgendwann mal versuchst, wirst du es selber merken. Man kann der Sache zugegebenermaßen einigermaßen nahe kommen, aber supertoll ist es nicht. Und wenn irgendwas nicht klappt steht dann nicht da, "Map<K, V> does not implement IEnuermable<V>, sondern es steht 2 Seiten Fehlermeldung. Aber das bist du ja vielleicht gewohnt.

-
typedef std::map<MyKey, MyValue*>::const_iterator Iterator; for( Iterator i = myMap.begin(); i != myMap.end(); ++i ) { cout << (*i)->getMember(); }Haste jetzt extra nen Pointer in die Map gepackt, damit du quasi 2mal dereferenzieren musst und es so "schlimmer" aussieht?
for(auto iter = map.begin(); iter != map.end(); ++iter) { cout << (*i)->get(); }Finde ich nicht unbedingt hässlicher als das foreach in C#. Das begin() und end() sagt meiner Meinung nach genauso viel aus wie ein foreach.
Ok, funktioniert noch nicht aber kommt..Und wenn irgendwas nicht klappt steht dann nicht da, "Map<K, V> does not implement IEnuermable<V>, sondern es steht 2 Seiten Fehlermeldung. Aber das bist du ja vielleicht gewohnt.

Naja, das liegt halt an den Templates. Hast du nen Vorschlag wie man das besser regeln könnte?

-
struct Int { Int( int i ) : i( i ) { } bool display() { cout << i << "\t"; return true; } int i; }; int main() { list< Int > li; li.push_back( 1 ); li.push_back( 2 ); li.push_back( 3 ); for_each( li.begin(), li.end(), mem_fun_ref( &Int::display ) ); }Wenn man einfach nur irgendwas machen will auf allen Objekten, ist for_each optimal. Sobald man mehr machen will, ist der Kopf der for-Schleife nicht mehr unnötig viel Standardbalast im Vergleich zum Rumpf.
Aber gut jeder wie er will, ich werde eine Sprache nicht wegen einem fehlenden foreach bemängeln. Ich mag C++ und kann damit leben mal ne Zeile mehr zu tippen.
-
Any schrieb:
Wenn man einfach nur irgendwas machen will auf allen Objekten, ist for_each optimal.
Der Kritikpunkt ist der, dass der "Rumpf" in nem Functor liegt und der irgendwo anders gespeichert ist. Ist halt nicht soo leserlich..
Naja, ich hab da eigentlich auch kein Problem mit..
-
Konrad schrieb:
Any schrieb:
Wenn man einfach nur irgendwas machen will auf allen Objekten, ist for_each optimal.
Der Kritikpunkt ist der, dass der "Rumpf" in nem Functor liegt und der irgendwo anders gespeichert ist. Ist halt nicht soo leserlich..
Naja, ich hab da eigentlich auch kein Problem mit..
Dann ist es natürlich umständlicher, aber ich bezog das hier nur auf einen Funktionsaufruf, den man für alle Objekte durchführen möchte.
In den meisten Fällen braucht man so etwas doch nur, wenn man für alle Objekte eine Funktion aufrufen will, oder wenn man sie ausgeben will, für beides ist in C++ std::for_each ne kurze und einfache Lösung.
Für größere/komplexere Sachen nimmt man halt die for-Schleife. Ich kann mich nicht daran erinnern jemals so schnell und viel getippt zu haben (in nem sauberen projekt), dass so ne Zeile oder zwei zu viel Zeit gekostet hätten.
-
Konrad schrieb:
typedef std::map<MyKey, MyValue*>::const_iterator Iterator; for( Iterator i = myMap.begin(); i != myMap.end(); ++i ) { cout << (*i)->getMember(); }Haste jetzt extra nen Pointer in die Map gepackt, damit du quasi 2mal dereferenzieren musst und es so "schlimmer" aussieht?
In dem C#-Beispiel kann das Ding auch ein Pointer sein. Der Pointer tut auch in C++ mit seinem Pfeil nicht weh. Was weh tut ist, dass man den Iterator nochmal zusätzlich dereferenzieren muss.

for(auto iter = map.begin(); iter != map.end(); ++iter) { cout << (*i)->get(); }Das auto ist nur eine Erfindung der Wirtschaftler. SCNR

Natürlich ist es - wie bereits von mir erwähnt - mit auto dann schöner. Trotzdem ist die Anzahl der möglichen Fehler in diesem Stück Code immer noch höher als mit foreach. Wenn du zwei Schleifen mit i und j schachtelst (is ja nicht unüblich, z.B. kann man ne Sparse Matrix speichersparend mit geschachtelten Hashmaps darstellen) kann es passieren, dass du das ++ am Ende an der falschen Variable hast. Oder den Vergleich in der Mitte beim copy & paste verhunzt.
Nicht zuletzt sagt diese Schleife, wenn sie mir in's Gesicht springt, immer noch nicht schneller "für alle...", als wie wenn ich nen Iterator-typedef verwende. In diesem Punkt hast du also sogar noch gar nichts dazugewonnen.Naja, das liegt halt an den Templates. Hast du nen Vorschlag wie man das besser regeln könnte?

Ja, als Sprachmittel. Dann weiß der Compiler nämlich, dass ich ein foreach will und kann das richtige bemängeln. Wenn der Compiler nicht weiß, was ich vorhabe und durch Makros und Templates erstmal was völlig anderes zu sehen kriegt als ich, dann ist natürlich klar, dass er nichts mehr sinnvolles meckern kann. Das ist ja auch einer der Hauptpunkte, warum viele Leute glauben, dass sowas in eine Sprache muss.
-
* religion?
* "d programmierung" oder "vorzuege von foreach"?
-
ich persoenlich finde es eleganter, und ueberlegen, wenn ich mir ohne probleme eigene foreach (bzw aehnlich benamst um keine verwirrung zu stiften) erstellen kann, die dann in combi von praeprozessor und compiler optimalen code fabrizieren, eine tatsache die die foreachmarketingplapperer gern uebersehen bzw gar nicht wissen.
Nur ist das Problem, dass C++ nicht so elegant ist und es auch nicht mit auto oder typeof sein wird.
#define foreach(i, begin, end) for(auto i=(begin), __end = (end); i!=__end; ++i) foreach(i, Foo<int, char>::vec.begin(), Foo<int, char>::vec.end()){ (*i) = 4; }Siehst du Problem Nummer 1? Dises Makro nimmt 4 Parameter. Ob dieses Problem mit C++0x behoben wird weiß ich nicht allerdings wäre eine solche Änderung nicht mehr strikt rückwärtskompatibel.
So nun kommt Problem Nummer 2 : i ist ein Iterator und nicht eine Referenz. Nichts im Kopf der foreach Schleife lässt darauf vermuten, dass i ein Iterator ist. Ganz im Gegenteil ist eine Reference die Norm in einer foreach Schleife. Das Ziel der besseren Lesbarkeit wurde also verfehlt.
Ein D oder C# foreach ist in C++ gar nicht möglich und bis jetzt auch nicht in C++0x.
Eine Implementirung als Makro bringt auch die üblichen Scopeprobleme mit sich die für alles anderes als Keywords schlecht sind. Ich sehe es jetzt schon:
SDL_FOREACH, wxFOREACH, CFOREACH, TFOREACH, ALFOREACH, ...
und jedes ein wenig anders.Desweiteren erlaubt ein foreach als Buildinschleife es dem Compiler eine Reihe von Optimirungen wesentlich einfacher durch zu führen.
Fazit entweder eine ordentliche foreach Schleife oder gar keine. Ein verkrüppeltes #define foreach oder std::for_each ist jedenfals keine Lösung.
-
Da hat sich aber jemand mit seinem Posting ordentlich ins Aus katapultiert.
-
Ben04 schrieb:
Siehst du Problem Nummer 1? Dises Makro nimmt 4 Parameter.
Bin ich blind oder sind das nur 3?

Diesen 3 Parametern im Gegensatz zu 2 Parametern in C# könnte man mit nem Interface entgegen treten. Dabei meine ich kein "richtiges" Interface wie in Java oder C#, welches die jeweiligen Klassen für foreach implementieren müssen, sondern eher ein Konzept wie es bei den Stl-Container auch ist.
Man verlangt einfach das der zu iterierende Typ eine begin() und end() Methode hat und das es außerdem ein ::iterator bzw. ::const_iterator gibt. (Ob const oder nicht, da müsste man diskutieren ob foreach den Container verändern können soll..)Edit: Also gemeint hatte ich damit, dass anstelle von 3 Parametern i, begin, end es nur 2 Parameter gibt. i, container und dabei wird vorausgesetzt das container eine begin und eine end Methode besitzt.