Mit welcher Programmier-Sprache anfangen?

Wenn du so sehr auf den PC eingehen willst dann lass ihn doch direkt Assembly lernen. NASM, GAS, MASN welches auch immer (wobei man GAS einzig und allein in C per inlineAssembly einbinden kann), oder direkt puren Maschinen Code.

Schöner Link zu StackOverflow dazu
 
Autokiller677 schrieb:
Nein, aber ich habe eine grundsätzliche Vorstellung davon, wie "teuer" eine Operation ungefähr ist, wenn ich es eben mal selber machen musste statt irgendeine Lib zu verwenden.

Von was für Operationen redest du denn so? Um hier sinnvoll weiter zu kommen, wären doch ein paar Beispiele gut.

Autokiller677 schrieb:
Mir ist bewusst, dass Python hier einen anderen Ansatz verfolgt. Nervig finde ich es aber trotzdem, weil ich das C++ Konzept komplett einleuchtend und sehr einfach finde, allein schon, weil ich durch das "&" einfach nochmal drauf gestoßen werde, was ich gerade mache. Dagegen ist das Python Konzept einfach nervig imho.

Der "andere Ansatz", den Python verfolgt, ist quasi der, den alle anderen Sprachen außer den Lowlevel-Sprachen verfolgen. Es gibt nicht mehrere undurchsichtige Fälle bei der Parameterübergabe, sondern mehr oder weniger nur genau einen Fall, dessen Ausprägungen man einfach verstehen würde, hätte man direkt Python gelernt und würde nicht versuchen, sein Wissen aus einer Lowlevel-Sprache darauf abzuleiten. C# ist die einzige populäre nicht-Lowlevel-Sprache, die bei der Übergabe mit ref/out etwas Variation zulässt. Alles andere (inkl. Python) ist Schema F.
 
crvn075 schrieb:
Von was für Operationen redest du denn so? Um hier sinnvoll weiter zu kommen, wären doch ein paar Beispiele gut.
Das fängt (meiner Erfahrung nach) schon bei so simplen Sachen wie Manipulationen von Strings an, weil viele, die eben direkt z.B. Python gelernt haben, nie mit char* arrays, Listen von Arrays etc. rumgehampelt haben und daher nicht wissen, dass das im Hintergrund schon eher aufwändig ist, wenn man massiv mit strings durch die Gegend schmeißt und schnipselt. Andere Ecke wären eben Arrays vs. Listen - wenn man es in einem strukturierten Kurs lernt, lernt man da vielleicht auch noch die Unterschiede im Hintergrund, in Online Tutorials etc. fehlt das oft - Lib eingeführt und fertig (BTW - wie würde ich in Python eine verkettete Liste selber implementieren? Ohne Pointer / Referenzen stehe ich da gerade etwas im Regen).

Der "andere Ansatz", den Python verfolgt, ist quasi der, den alle anderen Sprachen außer den Lowlevel-Sprachen verfolgen. Es gibt nicht mehrere undurchsichtige Fälle bei der Parameterübergabe, sondern mehr oder weniger nur genau einen Fall, dessen Ausprägungen man einfach verstehen würde, hätte man direkt Python gelernt und würde nicht versuchen, sein Wissen aus einer Lowlevel-Sprache darauf abzuleiten. C# ist die einzige populäre nicht-Lowlevel-Sprache, die bei der Übergabe mit ref/out etwas Variation zulässt. Alles andere (inkl. Python) ist Schema F.

Hast du einen guten Link, der das Konzept einfach und verständlich erklärt? Ich habe in gut 2 Jahren Python sowas nicht gefunden und stehe daher in Rand- / Ausnahmefällen meistens doch mit Try-and-Error da, weil ich es eben absolut nicht Schema-F empfinde was da abgeht. Letztlich lassen sich die Probleme dann meistens darauf zurückführen, dass eben im Code nicht direkt klar ersichtlich ist, was jetzt Referenz und was Objekt ist und man daher mal wieder im falschen Scope rumgeändert hat.
 
Zuletzt bearbeitet:
Autokiller677 schrieb:
Das fängt (meiner Erfahrung nach) schon bei so simplen Sachen wie Manipulationen von Strings an, weil viele, die eben direkt z.B. Python gelernt haben, nie mit char* arrays, Listen von Arrays etc. rumgehampelt haben und daher nicht wissen, dass das im Hintergrund schon eher aufwändig ist, wenn man massiv mit strings durch die Gegend schmeißt und schnipselt.

Ich habe im vorherigen Post noch überlegt, ob ich Strings als Gegenbeispiel anführen soll. Wenn du direkt Java lernst (nur als Beispiel, man könnte auch andere Sprachen heranführen), dann weißt du, dass Java-Strings immer immutable sind und jede Änderung an einem String ein neues Objekt erzeugt, was eben teuer ist. Das steht so in jedem brauchbaren Buch, spätestens dann, wenn der StringBuilder erörtert wird (was er in jedem Buch wird). Des Weiteren sind Strings hier Referenztypen, das heißt, dass sie irgendwo im Heap stehen und meine Variable nur als "Zeiger" fungiert - weise ich ihr einen neuen String zu, dann wird der alte String nicht überschrieben, die Variable zeigt jetzt plötzlich nur an eine andere Stelle im Heap auf ein neues String-Objekt*. Und so weiter und so fort. Ich wüsste hier überhaupt nicht, wie mich Vorwissen in C/++ mit meinem Verständnis für Strings in Java schneller ans Ziel bringen würde als es einfach direkt zu lernen.

* so funktioniert btw. quasi alles in Python, evt. rührt deine Verwirrung bzgl. Parameter daher.

Autokiller677 schrieb:
(BTW - wie würde ich in Python eine verkettete Liste selber implementieren? Ohne Pointer / Referenzen stehe ich da gerade etwas im Regen).

Ich denke erneut, dass dich hier C/++ eher verwirrt. Es geht wieder um den Begriff Referenz in Python, Java, C# etc., der in C++ eher einem Pointer entsprechen würde als einer Referenz (siehe hierzu aber ganz unten).
Du hättest jedenfalls eine Art Container-Klasse (bestenfalls generisch), deren Instanz a) genau ein Element des generischen Typs aufnimmt und b) über eine Referenz auf den nächsten Container verweiset, der wiederum ein Element hat und auf den nächsten Container verweist usw. Das ganze wäre in einem eigenen Typ gekapselt, der Methoden bereitstellt, mit denen man neue Elemente hinzufügen kann (aka an den letzten Container der Liste per Referenz einen neuen Container dranhängen und das einzufügende Element im neuen Container ablegen). Eine andere Operation könnte das x-te Element auslesen, in dem sie x mal von Container zu Container springt und beim Zielcontainer das Element herauszieht.

Die vorgefertigten Collections dieser Sprachen sind aber i.d.R. nativ implementiert.

Autokiller677 schrieb:
Hast du einen guten Link, der das Konzept einfach und verständlich erklärt? Ich habe in gut 2 Jahren Python sowas nicht gefunden und stehe daher in Rand- / Ausnahmefällen meistens doch mit Try-and-Error da, weil ich es eben absolut nicht Schema-F empfinde was da abgeht. Letztlich lassen sich die Probleme dann meistens darauf zurückführen, dass eben im Code nicht direkt klar ersichtlich ist, was jetzt Referenz und was Objekt ist und man daher mal wieder im falschen Scope rumgeändert hat.

Du hast quasi immer Referenzen (nämlich deine ganz normalen Variablen) auf Objekte, die irgendwo im Heap rumliegen. Übergibst du jetzt ein Objekt an eine Funktion/Methode, dann übergibst du eigentlich nicht das Objekt selbst, sondern die Referenz auf das Objekt - diese Referenz wird bei diesem Vorgang auch noch kopiert. Auch wenn die Referenz jetzt im Body der Methode eine andere ist wie die außerhalb (wie gesagt, wurde kopiert), so zeigen dennoch beide Referenzen auf das selbe Objekt. Änderst du in der Methode jetzt etwas am Objekt über die Referenz in der Methode, so sind diese Änderungen auch über die Referenz außerhalb der Methode sichtbar, denn beide zeigen ja auf das selbe Objekt. Du kannst jedoch NICHT die äußere Referenz selbst ändern, indem du beispielsweise der Referenz in der Methode etwas neues zuweist. Das würde nur dazu führen, dass die Referenz in der Methode auf etwas neues zeigt, die Referenz außerhalb jedoch nach wie vor auf das alte Objekt.

Das ist quasi erstmal die ganze Geschichte. Jetzt kann es sein, dass das übergebene Objekt (bzw. das Objekt hinter der übergebenen Referenz) Immutable ist. Das heißt, du kannst das Objekt gar nicht verändern. Und wenn du es in der Methode nicht verändern kannst, dann sind auch keine Änderungen über die Referenz außerhalb der Methode sichtbar. Das ist aber kein anderer Fall der Übergabe, sondern nur eine Eigenschaft des übergebenen Datentyps.
 
Zuletzt bearbeitet:
D.h. also simpel Python ist einfach immer Call by Reference? Zumindest liest es sich so.

Ok, d.h. ich baue meine Liste genauso wie in C++ und schreibe dann halt statt ListElem *next = new ListElem() sowas wie self.next = ListElem() ?

Naja, mag wirklich an der C++ Denkweise liegen, aber schön finde ich es nicht. Irgendwie wird mir da schon zu viel versteckt, aber jetzt verstehe ich immerhin weshalb viele Objekte den copy-constructor so explizit mit .copy() implementieren. Anders gehts dann ja nicht.
 
Autokiller677 schrieb:
D.h. also simpel Python ist einfach immer Call by Reference? Zumindest liest es sich so.

Also vorweg: Variablen sind immer Referenzen, das ist der Standardfall. Übertragen auf C/++ wäre das passende Wort aber eher Pointer als Referenz.

Bei Call-by-Reference könntest du einer Referenz außerhalb einer Methode einen komplett neuen Wert zuweisen, indem du der Referenz nach Übergabe an eine Methode in der Methode einen neuen Wert zuweist. Das geht aber nicht. Weist du der übergebenen Referenz in der Methode mit "=" etwas neues zu, dann zeigt die Referenz eben auf etwas neues, die Referenz außerhalb aber immer noch auf das alte Objekt, was übergeben wurde. Also kann es ja eigentlich kein Call-by-Reference sein.

Wäre es klassisches Call-By-Value, dann hättest du in der Methode eine Kopie des Parameters. Ist scheinbar aber auch nicht so, denn falls das Objekt Mutable ist, dann siehst du Änderungen am Objekt ja auch außerhalb der Methode.

Man sagt dennoch, dass es Call-by-Value ist: Das, was bei der Übergabe kopiert wird, ist die Referenz auf das übergebene Objekt, nicht das Objekt selbst. Dann ist auch klar, warum du der Referenz außerhalb der Methode nichts neues zuweisen kannst wenn du in der Methode bist (schließlich ist die in der Methode verwendete Referenz eine Kopie, also nicht die identische). Es ist aber auch klar, warum du Änderungen am bestehenden Objekt in der Methode auch über die Referenz außerhalb erkennst: beide Referenzen zeigen ja auf das gleiche Objekt.

Da hier Call-by-Value aber etwas irreführend ist im Vergleich zu C/++ nennt man es auch manchmal Call-by-Object-Reference oder Call-by-Assignment.

Du hast ja schon C# benutzt. Schau dir mal an, was passiert, wenn du ein Objekt (muss ein Referenztyp sein, für Wertetypen gilt es nicht) an eine Methode übergibst, ohne dabei ref/out zu benutzen (quasi der Standardfall). Du wirst dann Änderungen am Objekt auch außerhalb sehen können (falls das Objekt mutable ist), kannst der Referenz außerhalb aber nichts komplett neues zuweisen, wenn du in der Methode bist. Ganz genau das gleiche Schema.

Autokiller677 schrieb:
Ok, d.h. ich baue meine Liste genauso wie in C++ und schreibe dann halt statt ListElem *next = new ListElem() sowas wie self.next = ListElem() ?

Ganz genau.


Autokiller677 schrieb:
Naja, mag wirklich an der C++ Denkweise liegen, aber schön finde ich es nicht. Irgendwie wird mir da schon zu viel versteckt, aber jetzt verstehe ich immerhin weshalb viele Objekte den copy-constructor so explizit mit .copy() implementieren. Anders gehts dann ja nicht.

Das ist reine Gewohnheit. Wie gesagt gibt es eigentlich nur einen einzigen Fall. In Java und C# gibt es 2 Fälle, weil man zwischen Werte- und Referenztypen unterscheidet (und in C# auch noch ref/out benutzen kann). Der Normalfall für Referenztypen ist aber in allen drei Sprachen der gleiche und unterscheidet sich hier zu C++.

Das mit dem copy kann man so sagen, stimmt.
 
Zuletzt bearbeitet:
Man sagt dennoch, dass es Call-by-Value ist: Das, was bei der Übergabe kopiert wird, ist die Referenz auf das übergebene Objekt, nicht das Objekt selbst.
Dafür gibt es auch Bezeichnungen wie call-by-object-reference.

In Python nervt das Fehlen von echtem Call-by-Reference aber nicht so sehr wie z.B. in Java, weil man ja Tupel zurückgeben kann. Größter Nachteil ist das Problem mit dem Kopieren.
 
Zurück
Oben