Gebt doch endlich mal richtige Gründe gegen die Sprache D an!



  • Super in D. 👍
    Auch ne Demonstration welchen Vorteil es bietet anstatt std::string/vector builtin Typen zu haben.



  • Und total automatisches constexpr vor allem, ich hab ja nix sagen müssen. Das kommt meinem "hypothetischen" Compiler schon recht nahe, außer dass man halt selber die "variablen" strings zusammensetzen muss.
    Ich bin mega begeistert von den paar Sachen, die ich hier nebenbei so in der Doku überflogen habe, während ich mir das nötige anlas für das Problem hier.



  • Gibts fuer D ueberhaupt ne brauchbare IDE? Das Eclipse Plugin scheint mit aktuellen Versionen nicht zu funktionieren, bei "D-IDE" (offenbar eine schlechte Kopie von MSVC, und das ist schon mies) konnte ich nicht mal ein Projekt erstellen (Create-Button ausgegraut, keine Fehlermeldung). Visual Studio Plugins funktionieren soweit ich weiss nicht mit Express.

    Edit: Cross-Plattform waere uebrigens nett. (Windows, Mac OS 😵



  • Ich sehe in der DDT-Gruppe kein Rumgeschreie, dass es nicht funzen würde. Überrascht mich jetzt, dass das nicht funktioniert, vor allem wäre das auch die einzige Variante, die Deinen Ansprüchen genügen würde. Wobei der Debugger-support mit gdb wohl hakelig sein soll. Ich hab hier VS benutzt und das scheint gut zu funktionieren, mindestens mal gut genug, um die Sprache besser kennen zu lernen und damit kleine Konsolentools zu schreiben.



  • decimad schrieb:

    (0,1)
    (2,3)
    (0,2)(1,3)(1,2)(0,1)
    (4,5)
    (6,7)
    (4,6)(5,7)(5,6)(4,5)
    (0,4)(2,6)(2,4)(0,2)(1,5)(3,7)(3,5)(1,3)(1,2)(0,1)(3,4)(0,1)(5,6)(0,1)
    

    Also (ich zerteile so in Zeilen, daß keine zwei Zeilen auf das selbe Element zugreifen müssen):

    (0,1)(2,3) //beide gehen noch parallel
    (0,2)(1,3) //auch
    (1,2) //leider zugriff auf die 1, ganz ungeschickt
    (0,1) //und nochmal
    (4,5)(6,7)
    (4,6)(5,7)
    (5,6)
    (4,5)
    (0,4)
    (2,6)
    (2,4)
    (0,2)
    (1,5)(3,7)
    (3,5)
    (1,3)
    (1,2)
    (0,1)
    (3,4)(0,1)(5,6)
    (0,1)
    

    macht 19 Zeilen. 😢

    decimad schrieb:

    Wenn das nicht die Reihenfolge ist, die Du möchtest, dann müssen wir einen anderen Algorithmus wählen 😉

    Jo. Aber woher nehmen? Alternativ erstmal die Zugriffe sammeln und dann geeignet umsortieren. Greedy die Zeilen vollmachen, würde ich mal versuchen, wobei halt kein Zugriff einen anderen Zugriff aufs selbe Element überholen darf.
    Uih, und das Nachsortieren geht in D ganz einfach. In C++ würde ich mir einen abbrechen.



  • @Decimad: Wow. Nun will ich auch mixins :).



  • So, nach einer Neuinstallation klappt das Eclipse Plugin endlich. Aber die Code-Completion finde ich mehr als enttaeuschend. Bei Konstruktoren kann der mir nicht mal die Parameter aller verschiedenen Overloads anzeigen. Ausserdem ist Code-Completion case-sensitive.



  • Ich hab lieber keine tolle Code-Completion bis Du sie uns programmiert hast, als das in C++-Template-Form hinzuschreiben ;). Kannst ja mal auf der DDT-Liste stänkern, vielleicht fühlt sich dann jemand motiviert!



  • Nun, meine Loesung http://ideone.com/gOIzqH , und die Probleme mit VS 2013 http://www.c-plusplus.net/forum/320689 . Insgesamt gefaellt mir das noch nicht ganz, da "parallele" swap_if's wie in der ersten Ebene nicht direkt hintereinander stehen (es stehen die 8 parallelen Operationen nicht hintereinander). Gleiches gilt fuer den rosa Rattenschwanz. Funktioniert mit VS 2010, g++ und clang++. bitonic_sort-Template sollte C++03 entsprechen, d.h. ueberall benutzbar sein.

    Im Nachhinein betrachtet, war es doch gar nicht so schwer. Zwar noch recht lang, aber vielleicht kannmit den Moeglichkeiten von C++11 das Template klarer gestalltet werden. Mal schauen.

    Einige Verstaendnisfragen zur Loesung in 😨

    mixin(GenerateOddEven("myarray", myarray.length));
    

    Mit GenerateOddEven werden Strings generiert, die dann durch mixin an besagter Stelle als Code eingefuegt werden?



  • Ja, genau.



  • Ich fühle mich aber gerade ziemlich dumm, weil mir keine Breadth-First-Umsetzung zu dem Algorithmus einfällt, die es hinbekommt, CAS aus gleicher Stufe zusammenzuhalten. Die einzige Option wäre, die Stufe in den Funktionen mitzureichen und in den CAS-Anweisungen zu vermerken und hinterher nach der Stufe zu sortieren. Aber das muss doch irgendwie klüger gehen. 😮



  • Ich arbeite dran ... also bei meinem Ansatz, bei Batcher odd even weiss ich noch nicht recht.



  • Hab mal versucht, n kleines Programm zu schreiben. Funktionieren tuts zumindest bei mir, keine Ahnung was da bei ideone nicht passt.
    http://ideone.com/JZLdok

    1. Ist das idiomatisches D? Wenn nicht, was wuerde man anders machen?
    2. Wird hier alles korrekt aufgeraeumt? Wenn nicht, was muss ich dafuer tun?
    3. Wie schreib ich das Programm ohne GC?


  • Kellerautomat schrieb:

    Hab mal versucht, n kleines Programm zu schreiben. Funktionieren tuts zumindest bei mir, keine Ahnung was da bei ideone nicht passt.
    http://ideone.com/JZLdok

    1. Ist das idiomatisches D? Wenn nicht, was wuerde man anders machen?
    2. Wird hier alles korrekt aufgeraeumt? Wenn nicht, was muss ich dafuer tun?
    3. Wie schreib ich das Programm ohne GC?
    1. Nein. Siehe Beispiele. Exception handling wird in D anders gemacht. enum > immutable > const. Für Compiletime-Konstante immer enum, sonst immutable. const bedeutet "hier read-only, andere Programmteile dürfen aber den Status verändern". Man kann das Problem auch mit Ranges arbeiten, aber das ist fürs erste zu viel.
    2. Ja.
    3. http://forum.dlang.org/thread/kjo7id$22jk$1@digitalmars.com?page=1 Den GC umgeht man in der Praxis dadurch, dass man das Memory Management selber in die Hand nimmt. Und soo schlecht ist ein GC auch nicht.
    4. Die typischen D-IDEs sind Emacs, Vim und MicroEmacs.


  • Alles klar, mein Gedankenproblem war, dass ich irgendwie mehrere Rekursionen parallel machen wollte, was so recht natürlich nicht funktioniert. Jetzt gehe ich anders an die Sache ran... Erstmal baue ich eine Liste aus Odd-Even-Merges, die sequentiell abgearbetet werden muss, und für jede dieser Listen implementiere ich die parallele Rekursion dadurch, dass Ich einen Rekursionsschritt mache und die Ergebnisse der einzelnen Merges "interleave". Da die Teilbäume ja gleich aussehen im Falle von 2^N, sind die Bäume ja exakt gleichartig.

    module main;
    
    import std.stdio;
    import std.algorithm;
    import std.conv;
    
    struct merge_args {
    	int low;
    	int high;
    };
    
    struct cas_args {
    	int arg0;
    	int arg1;
    };
    
    cas_args[] GenerateCasList( int lo, int hi, int r )
    {
    	int step = r*2;
    	if( step < hi-lo ) {
    		cas_args[] list1 = GenerateCasList( lo, hi, step );
    		cas_args[] list2 = GenerateCasList( lo+r, hi, step );
    		cas_args[] interleaved;
    
    		for( int i=0; i<list1.length; ++i ) {
    			interleaved ~= list1[i];
    			interleaved ~= list2[i];
    		}
    
    		for( int i=lo+r; i<hi-r; i += step ) {
    			interleaved ~= cas_args( i, i+r );
    		}
    
    		return interleaved;
    	} else {
    		return [ cas_args( lo, lo+r ) ];
    	}
    }
    
    cas_args[] GenerateCasListFromMergeSet( ref merge_args[] merge_set )
    {
    	cas_args[] result;
    
    	cas_args[][] merge_cas_lists;
    	for( int i=0; i<merge_set.length; ++i ) {
    		merge_cas_lists ~= GenerateCasList( merge_set[i].low, merge_set[i].high, 1 );
    	}
    
    	for( int i=0; i<merge_cas_lists[0].length; ++i ) {
    		for( int j=0; j<merge_cas_lists.length; ++j ) {
    			result ~= merge_cas_lists[j][i];
    		}
    	}
    
    	return result;
    }
    
    cas_args[] GenerateCasListFromMergeSets( ref merge_args[][] merge_sets )
    {
    	cas_args[] result;
    	for( int i=0; i<merge_sets.length; ++i ) {
    		result ~= GenerateCasListFromMergeSet( merge_sets[i] );
    	}
    	return result;
    }
    
    merge_args[][] GenerateMergeSets( int array_size )
    {
    	merge_args[][] merge_sets;
    
    	for( int stride = array_size; stride > 1; stride /= 2 ) {
    		merge_args[] current_set;
    
    		for( int i=0; i<array_size; i += stride ) {
    			current_set ~= merge_args( i, i+stride-1 );
    		}
    		merge_sets = current_set ~ merge_sets;
    	}
    
    	return merge_sets;
    }
    
    string GenerateNetworkMixin( string arr, string op, int size )
    {
    	merge_args[][] merge_sets = GenerateMergeSets( size );
    	cas_args[] cas_list = GenerateCasListFromMergeSets( merge_sets  );
    
    	string result;
    	for( int i=0; i<cas_list.length; ++i ) {
    		string arg0 = arr~"["~to!string(cas_list[i].arg0)~"]";
    		string arg1 = arr~"["~to!string(cas_list[i].arg1)~"]";
    		result ~= "if("~arg0~op~arg1~") swap("~arg0~","~arg1~");\n";
    	}
    
    	return result;
    }
    
    int main(string[] argv)
    {
    	int array[8] = [ 4,6,1,8,3,1,6,5 ];
    	mixin( GenerateNetworkMixin( "array", ">", array.length ) );
    	write( GenerateNetworkMixin( "array", ">", array.length ) );
    	for( int i=0; i<array.length; ++i ) write( array[i], "," );
    	stdout.flush();
    	return 0;
    }
    

    Mit der Ausgabe:

    if(array[0]>array[1]) swap(array[0],array[1]);
    if(array[2]>array[3]) swap(array[2],array[3]);
    if(array[4]>array[5]) swap(array[4],array[5]);
    if(array[6]>array[7]) swap(array[6],array[7]);
    if(array[0]>array[2]) swap(array[0],array[2]);
    if(array[4]>array[6]) swap(array[4],array[6]);
    if(array[1]>array[3]) swap(array[1],array[3]);
    if(array[5]>array[7]) swap(array[5],array[7]);
    if(array[1]>array[2]) swap(array[1],array[2]);
    if(array[5]>array[6]) swap(array[5],array[6]);
    if(array[0]>array[4]) swap(array[0],array[4]);
    if(array[1]>array[5]) swap(array[1],array[5]);
    if(array[2]>array[6]) swap(array[2],array[6]);
    if(array[3]>array[7]) swap(array[3],array[7]);
    if(array[2]>array[4]) swap(array[2],array[4]);
    if(array[3]>array[5]) swap(array[3],array[5]);
    if(array[1]>array[2]) swap(array[1],array[2]);
    if(array[3]>array[4]) swap(array[3],array[4]);
    if(array[5]>array[6]) swap(array[5],array[6]);
    1,1,3,4,5,6,6,8,
    


  • hreadv schrieb:

    Exception handling wird in D anders gemacht.

    Ich hab dazu nicht viel gefunden. Koenntest du etwas konkreter werden?

    hreadv schrieb:

    enum > immutable > const. Für Compiletime-Konstante immer enum, sonst immutable. const bedeutet "hier read-only, andere Programmteile dürfen aber den Status verändern".

    Wenn man das also in C++ uebrsetzen wuerde, stimmt das so in etwa?
    enum = constexpr
    immutable = const daten
    const = const view

    hreadv schrieb:

    Man kann das Problem auch mit Ranges arbeiten, aber das ist fürs erste zu viel.

    Wuerde mich schon interessieren. 😉

    hreadv schrieb:

    1. http://forum.dlang.org/thread/kjo7id$22jk$1@digitalmars.com?page=1 Den GC umgeht man in der Praxis dadurch, dass man das Memory Management selber in die Hand nimmt. Und soo schlecht ist ein GC auch nicht.

    Mit anderen Worten: Ohne GC ist D quasi nutzlos, weil man sich Stdlib-Ersatz schreiben muss.

    Ich hab das Programm mal ueberarbeitet: http://ideone.com/hYLa7k
    Besser?



  • Die Sprache ist darauf ausgelegt, einen GC zu verwenden. Dir ist es aber freigestellt, für gewisse Instanzen keinen zu verwenden, nur dann musst Du halt selber auf die Lebenszeiten achten und auf ein paar weitere kleine Details, damit der GC auf seinem Working-Set zurande kommt. Alles nötige für die Custom-Allokatoren Deiner Klassen kannst wahrscheinlich per Template-Mixin reinmixen, sodass das nur einmal-Aufwand ist. Wenn Du aber gar keinen GC verwenden willst und die Stdlib das gefälligst auch nicht tun soll, dann ist es wohl nicht die richtige Sprache.
    Aber selbst in C++ verwendet man Pools um Allokationen zu vermeiden, wenn's wirklich um die Wurst geht, also sehe ich da den Nachteil noch nicht so stark. Wenn man jetzt aber die Sprache auseinander nimmt wegen des GCs, dann kann man auch gleich sagen: Ich will niemals GC, basta, D ist nix für mich, dafür wurstel ich lieber mit ekligen Templates und anderer Grütze rum.



  • Wobei wahrscheinlich für SIMD-Befehle der Odd-Even-Transposition-Algorithmus besser geeignet ist? Ersteinmal ist der im Aufbau viel einfacher und zweitens kann man ja bei SIMD keine Hardware-Einheiten sparen, dadurch dass auf einer Stufe weniger los ist - während man aber im Falle von 8 Elementen mehr sequenzielle Stufen abarbeiten muss.



  • Ja nun, es ist schon peinlich, in wievielen Arten und Weisen ich den Algorithmus missverstanden habe, als ich ihn aus dem Python-Code reverse-engineeren wollte und mir das Bild auf Wikipedia angeschaut habe. Jetzt habe ich mich mal mit dem Algorithmus eingehender beschäftigt und siehe da, es lässt sich doch effizienter veranstalten, das ganze. Vielleicht interessiert sich ja volkard noch dafür?

    http://pastebin.com/txwS2cBZ

    Ansonsten ignorieren & weitergehen 😉



  • Grumpf, Zeile 122 sollte da nicht sein... -> http://pastebin.com/vZzu8x6s


Anmelden zum Antworten