Seite 1 von 2
Dynamische und statische Typisierung
Verfasst: 14.04.2018, 10:34
von Alexander Kornrumpf
[abgespalten aus Lustiges und so]
Krishty hat geschrieben:
Off-Topic:
I call bullshit. In python musst du den Typ nicht dazusagen. Nach meinem Verständnis ist das genau das, was
auto zu C++ hinzufügt. Und es ist insbesondere das was in natürlichen Sprachen der Fall ist. Siehe: "The nimbish gibbler cranookled the frazobe". Du weißt nicht was 80% der Wörter bedeuten, aber du weißt genau was Adjektiv und was Verb, "Subjekt" und "Objekt" von dem Satz ist. Es ist genau das Gegenteil von dem richtig was in dem Bild behauptet wird: Würde natürliche Sprache wie das pre-moderne C++ funktionieren wäre das Schild nicht lustig. Das Gehirn hätte keine Möglichkeit zu erkennen was falsch läuft, weil der Typ nicht dransteht. [Sondern, in der Analogie, "nur" der Variablenname. Und da haben wir noch nicht davon gesprochen, dass ich in der Praxis noch niemanden habe Integer für "Anzahl" "Höhe" und "Jahr" wrappen sehen, aber das ist nicht der Punkt].
Unstreitig ist, dass man für Python gerne statische Analysetools hätte, die so mächtig sind wie ein C-Compiler. Genauso wie man für C selbst gerne statische Analysetools hätte die mächtiger sind als der Compiler. Daraus können wir aber nur lernen, dass es _immer_ einen Bedarf für noch mächtigere statische Analyse gibt. Das hat nichts mit dem Typsystem zu tun.
Re: Lustiges und so
Verfasst: 14.04.2018, 15:56
von dot
Alexander Kornrumpf hat geschrieben:I call bullshit. In python musst du den Typ nicht dazusagen. Nach meinem Verständnis ist das genau das, was auto zu C++ hinzufügt.
nope
noch Fragen?
Re: Lustiges und so
Verfasst: 15.04.2018, 20:26
von Jonathan
Der Vorteil liegt ja auch gar nicht so sehr im Ersteller der Variablen sondern im Benutzen. Funktionsaufrufe machen eben nur mit bestimmten Typen von Variablen sind, der Python-Way ist, dass das Programm bei der Ausführung crasht (am besten nachdem man 10 Minuten was gerechnet hat), der C++-Way ist, dass es beim Kompilieren crasht (und zwar mit einer sinnvollen Fehlermeldung, weil das Übergeben schon nicht klappt und nicht erst irgendetwas, was intern mit der Variable gemacht wird). Das C++ Typsystem ist auch nicht toll und C++ Templates können richtig pervers werden, aber rein vom Prinzip halte ich statische Typsysteme für absolut überlegen (vermutlich will man irgendetwas modernes mit type-traits und so, ich muss mir unbedingt nochmal Rust anschauen, da sah das interessant aus).
Keinen Typ dran schreiben zu müssen ist nett für Skripte die auf eine Seite passen. Für alles andere braucht man zwingend Robustheit des Codes wenn man damit effektiv arbeiten will. Bei Python steht (wenn man Glück hat) in der Dokumentation recht ausführlich, was für eine Art von Typ übergeben werden darf. Was letztendlich eine informelle und inkonsistente Art ist, einfach einen verdammten Typen direkt in den Code zu schreiben.
Re: Lustiges und so
Verfasst: 15.04.2018, 20:38
von Krishty
Jonathan hat geschrieben:rein vom Prinzip halte ich statische Typsysteme für absolut überlegen
Chromanoid hatte hier mal eine Studie gepostet, dass statische Typisierung gegenüber dynamischer keine messbare Verkürzung der Entwicklungszeit bewirkt. Vielleicht ist er so lieb, sie nochmal zu posten …
Re: Lustiges und so
Verfasst: 15.04.2018, 22:52
von Chromanoid
Krishty hat geschrieben:Jonathan hat geschrieben:rein vom Prinzip halte ich statische Typsysteme für absolut überlegen
Chromanoid hatte hier mal eine Studie gepostet, dass statische Typisierung gegenüber dynamischer keine messbare Verkürzung der Entwicklungszeit bewirkt. Vielleicht ist er so lieb, sie nochmal zu posten …
Puh, ich erinnere mich nur dunkel daran. Ich finde das Ding leider nicht mehr auf die Schnelle. Ich selbst hasse "dynamische" Sprachen und habe schon ganz viele "tolle" Sachen erlebt. Sowas wie "aus Versehen tippen" und beim Committen nicht aufpassen. Aus
if( a ) { ... } wurde versehentlich
i f( a ) { ... }... Hab ich dann erst ziemlich viel später gemerkt. Die Fehlermeldung war auch klasse. "Methode i nicht gefunden" WTF, dachte ich nur... Das war so ein Moment. Wenn man dann auch noch rauskriegt, dass man das selbst war, weil man wahrscheinlich das falsche Fenster im Fokus hatte, will man solche Sprachen nie wieder anfassen. Da muss man Unittests allein schon deshalb schreiben, um sicher zu gehen, dass der Code gültig ist...
Re: Lustiges und so
Verfasst: 17.04.2018, 23:44
von Jonathan
Krishty hat geschrieben:Jonathan hat geschrieben:rein vom Prinzip halte ich statische Typsysteme für absolut überlegen
Chromanoid hatte hier mal eine Studie gepostet, dass statische Typisierung gegenüber dynamischer keine messbare Verkürzung der Entwicklungszeit bewirkt. Vielleicht ist er so lieb, sie nochmal zu posten …
Da ich weder derartige Publikationen gelesen habe (aber ja, wäre sicher mal interessant), noch selber empirische Untersuchungen angestellt habe, will ich da erstmal nicht widersprechen, aber da wir hier im Internet, sag ich einfach mal bloß meine (nicht wert-evaluierte) Meinung: Selbst wenn ich in einer statisch typisierten Sprache 10% länger brauchen würde, würde ich es bevorzugen, einfach weil es sich besser anfühlt. Ich hasse es Code zu haben, der einfach nur aus Versehen funktioniert. Dieses Gefühl, gewisse Garantien zu haben, hat einfach etwas sehr wohltuendes an sich. Es ist vermutlich der selbe Grund, weshalb ich für alle möglichen Dinge lieber eine Stunde investiere um ein automatisiertes Skript zu entwickeln, dass ich dann letztendlich genau einmal ausführe, als eine halbe Stunde lang 500 mal das selbe zu tun. Es macht einfach mehr Freude und hinterher weiß man auch, dass es richtig ist.
Um zum eigentlichen Thema zurück zu kommen:
Re: Lustiges und so
Verfasst: 18.04.2018, 13:37
von antisteo
Jonathan hat geschrieben:Ich hasse es Code zu haben, der einfach nur aus Versehen funktioniert. Dieses Gefühl, gewisse Garantien zu haben, hat einfach etwas sehr wohltuendes an sich.
Falsch. Dynamisch getypte Sprachen sind genau so deterministisch und geben dir genau dieselben Garantien wie jede stark getypte Sprache mit dem einzigen Unterschied, dass die dynamisch getypte Sprache
nur einen Typen besitzt und der ein entsprechend komplexeres Verhalten aufzeigt. Die Komplexität ist aber beherrschbar, was dir tausende Entwickler beweisen, die firm in dynamisch getypten Sprachen sind.
Re: Lustiges und so
Verfasst: 18.04.2018, 14:40
von Chromanoid
antisteo hat geschrieben:Jonathan hat geschrieben:Ich hasse es Code zu haben, der einfach nur aus Versehen funktioniert. Dieses Gefühl, gewisse Garantien zu haben, hat einfach etwas sehr wohltuendes an sich.
Falsch. Dynamisch getypte Sprachen sind genau so deterministisch und geben dir genau dieselben Garantien wie jede stark getypte Sprache mit dem einzigen Unterschied, dass die dynamisch getypte Sprache
nur einen Typen besitzt und der ein entsprechend komplexeres Verhalten aufzeigt. Die Komplexität ist aber beherrschbar, was dir tausende Entwickler beweisen, die firm in dynamisch getypten Sprachen sind.
Mmh, aber was ist denn mit meinem Beispiel? Größerer Code-Block in Groovy, durch ein Versehen gerät ein Leerzeichen in den Code. Dies ist bei ganz ganz vielen Stellen bei typsicheren Sprachen gleich ein Syntaxfehler. Bei dynamischen Sprachen könnte es ja alles mögliche sein. Bei Groovy z.B. kann man Methoden statt mit
m(x) auch mit
m x aufrufen (BTW Groovy kann man auch typsicher einstellen, das war in diesem Kontext aber nicht so einfach möglich). Aus
if( x ) wurde
i f(x) also
i(f(x)). Das ist dann also vom Compiler geschluckt worden und erst zur Laufzeit kam die Meldung, dass die Methode
i nicht gefunden wurde. Dynamische Sprachen machen es viel einfacher genau solche dummen Fehler zu machen. Da gibt es ja bei typsicheren Sprachen schon viel zu viele Tretminen.
Übrigens eine interessante aus der Praxis getriebene Entwicklung ist hier die Programmiersprache Dart von Google. Die war erst dynamisch typisiert und mit der neuen Version gibt's nur noch statische Typisierung. Die Motivation dahinter:
https://github.com/dart-lang/sdk/blob/m ... NG_MODE.md
Re: Lustiges und so
Verfasst: 19.04.2018, 11:05
von Jonathan
antisteo hat geschrieben:Jonathan hat geschrieben:Ich hasse es Code zu haben, der einfach nur aus Versehen funktioniert. Dieses Gefühl, gewisse Garantien zu haben, hat einfach etwas sehr wohltuendes an sich.
Falsch. Dynamisch getypte Sprachen sind genau so deterministisch und geben dir genau dieselben Garantien wie jede stark getypte Sprache mit dem einzigen Unterschied, dass die dynamisch getypte Sprache
nur einen Typen besitzt und der ein entsprechend komplexeres Verhalten aufzeigt. Die Komplexität ist aber beherrschbar, was dir tausende Entwickler beweisen, die firm in dynamisch getypten Sprachen sind.
Pff, das ist so als würde man sagen, sie seien deterministisch, weil Prozessoren (Assemblercode) nunmal deterministisch ist. Das ändert nichts an der Tatsache, dass es so undurchsichtig wird, dass ein Mensch nicht mehr verstehen kann, was passiert und es damit aus menschlicher Sicht nicht mehr deterministisch ist.
Ein Beispiel: In Python ist es unmöglich, eine IDE zu schreiben, die dir beim Code-Schreiben schon sagt, ob er funktionieren wird oder nicht. Weil sich die Semantik des Codes buchstäblich erst zur Laufzeit entscheidet, und alles Prinzipiell alles sein kann. Du kannst eine Funktion schreiben, die aussieht, wie Quicksort, aber deine Festplatte formatiert. Natürlich ist das ein bisschen konstruiert, aber es zeigt das zugrundeliegende Problem. In C++ weißt du, dass wenn du eine Funktion schreibst, du sie auch ausführen kannst. Natürlich kannst du immer noch SegFaults bekommen oder Endlosschleifen, aber mit etwas Erfahrung ist das halbwegs selten. Das sind konzeptionelle Fehler, die in irgendeiner Form das Design des Algorithmus betreffen. Daneben gibt es aber noch all die vielen kleinen Flüchtigkeitsfehler (Funktionsname falsch geschrieben, etc.). Solche Fehler passieren, weil man nicht immer alle (größtenteils unwichtigen) Details des Programmes im Kopf hat, und ich mag es einfach, wenn mir der Compiler oder die IDE hilft, sie schnell zu finden und zu heben. In Python aber könnte so ziemlich alles sinnvoller Code sein und das ist einfach nervig.
Re: Lustiges und so
Verfasst: 19.04.2018, 19:42
von Krishty
Wenn ich vergleiche, wie wenig Zeilen Python ich brauche, um das gleiche zu tun wie in vielen Zeilen C (jetzt mal in
richtigen Projekten mit Dateiverarbeitung und UI; nicht in
Hello World oder
Primzahlen bis 100 ausgeben), dann erscheint mir das eher als Entropieproblem.
Für jedes Programm gibt es eine Mindestlänge, in der es sich formulieren lässt – unabhängig der Sprache. (Das dürfte der
Herr Kolmogorov formalisiert haben.) Dynamic Typing verdichtet das Programm stark – ich brauche Typen nicht deklarieren oder konvertieren, denn sie werden aus der sonst redundanten Zuweisung abgeleitet. (Ich kann auch Variablen und Funktionsparameter deklarieren, ohne dabei Typen angeben zu müssen; was allein das ausmacht!) Je dichter ein Signal ist, desto mehr geht kaputt, wenn ich ein Zeichen darin lösche. Auch das ist grundsätzlich klar.
Hausaufgabe: Verdichtet Garbage Collection das Programm? Wenn mein Programm mit Garbage Collection nur noch halb so lang ist, geht da auch mehr kaputt, wenn ich ein zufälliges Zeichen lösche?
Re: Lustiges und so
Verfasst: 19.04.2018, 21:46
von Chromanoid
Mich würde mal interessieren wie sich der programmiertechnische Unterscheid zwischen Typinferenz und dynamischer Bindung so niederschlägt. Weniger Nachdenken muss man ja in beiden Fällen, weniger Code ist es auch. Dynamische Typbindung ist halt nett, wenn man hübsche DSLs bauen will, aber das führt zu gruseligen Konstrukten, die man nur versteht, wenn man die Sprache wirklich kennt. So richtig toll finde ich dynamische Typbindung eigentlich nur dann, wenn man "programmfremde Konstrukte" wie XML oder JSON konstruieren möchte. Da ist es schon nett, wenn man
xml.tag1.tag2.content="test" schreiben kann. Auf der anderen Seite könnte man das mit gutem Willen auch bei typsicheren Sprachen über Metaprogrammierung und Operatoren hinbekommen - das ist aber auch nicht besonders durchschaubar. Im Grunde spart man sich bei dynamischen Sprachen doch eigentlich nur das Casten und die Definition von Interfaces - aus meiner Sicht ein gefährlicher Verzicht, der das "Entropiepotential" eher erhöht als verringert.
Kotlin ist schon ziemlich nah an einer dynamisch typisierten Sprache und trotzdem typsicher. Mit "
Function Literals with Receiver" lässt sich schon viel schicker Schabernack treiben.
Re: Lustiges und so
Verfasst: 20.04.2018, 09:53
von antisteo
Krishty hat geschrieben:Für jedes Programm gibt es eine Mindestlänge, in der es sich formulieren lässt – unabhängig der Sprache.
Gegenbeispiel: Ich erfinde eine Sprache, die mit einem einzigen ASCII-Zeichen einen Quicksort auslöst. (Geht noch krasser: mit einem Bit; dann ist aber der Code mit ASCII-basierten Editoren nicht mehr lesbar; oder mit leerer Datei)
[edit]der Wiki-Artikel behauptet auch, dass sich die Mindestlänge immer auf eine Sprache bezieht[/edit]
Bei Programmiersprachen-Design spielt schon Shannons Kodierungs-Theorie stark mit rein. Wir bauen momentan zum Beispiel an einer Programmiersprache, die gar keine Ausdrucksmöglichkeit für Algorithmen, Datenstrukturen, Variablen und Schleifen mehr hat. Es werden nur noch Software-Architektur-Pattern deklariert. Damit lässt sich z.B. eine Business-Anwendung (z.B. Reklamations-Management mit Dashboard) in wenigen hundert Zeilen darstellen, was mit konventionellen Programmiersprachen tausende Zeilen Code wären.
Re: Dynamische und statische Typisierung
Verfasst: 20.04.2018, 16:31
von antisteo
Generell zu dem Thema fällt mir noch eine sehr starke Pointe ein:
Als C-Programmierer muss man ja einen Algorithmus jedes mal neu schreiben, wenn man ihn für andere Datentypen verwenden will. Beispiel Quicksort mit array von integer geht anders als Quicksort mit Array von struct, wobei nach Feld x im Struct sortiert werden soll.
Macht man jetzt das ganze in JavaScript, entwickelt man den Algorithmus nur ein mal. Dank der dynamischen Typung ist der Code sowohl für Datentyp A als auch Datentyp B gültig. Sogar das Sortierkriterium ist dann völlig dynamisch: Gibt man keines an, wird der Wert direkt verglichen (Strings untereinander; Numbers untereinander), gibt man einen Callback an, kann man diesen zwei beliebig getypte Werte vergleichen lassen - am Ende müssen nur die eingegebenen Daten mit der Sortierfunktion harmonieren. (Quelle: Array.prototype.sort)
Re: Lustiges und so
Verfasst: 20.04.2018, 16:53
von Krishty
antisteo hat geschrieben:Krishty hat geschrieben:Für jedes Programm gibt es eine Mindestlänge, in der es sich formulieren lässt – unabhängig der Sprache.
[edit]der Wiki-Artikel behauptet auch, dass sich die Mindestlänge immer auf eine Sprache bezieht[/edit]
Ja, da hast du recht. (Abgesehen vom selten dämlichen Beispiel.)
Trotzdem verfehlt das mein Argument. Das zerreiße ich hier mal selber: Kolmogorov hat gezeigt, dass es
vernachlässigbar für die Minimallänge ist, welche Sprache ich nutze. Wenn z.B. der Linux-Kernel in JavaScript am kürzesten ist, nehme ich den JavaScript-Quelltext, lege einen JavaScript-zu-Python-Compiler bei, und nun habe ich theoretisch eine Version des Linux-Kernels in Python, die nur ein winziges kleines Bisschen größer ist als in JavaScript (nämlich die Größe des JavaScript-zu-Python-Compilers).
Und das bringt uns überhaupt nichts, denn es ist zur praktischen Programmierung nicht nutzbar.
Denn wir diskutieren hier nicht die
Minimallänge, sondern die minimale
praktisch nutzbare Länge. Und da wird es schon diffus.
Aber abgesehen von Kolmogorov steht mein Argument. Je höher ich ein Programm komprimiere, desto mehr geht kaputt, wenn ich einen Buchstaben ändere. Packt eure Quelltexte mit 7-Zip PPmD, ändert einen Buchstaben in den gepackten Daten, und extrahiert wieder …
@Chromanoid: In vielen Sicherheitsrelevanten Bereichen muss man identisch spezifizierte Programme in zwei verschiedenen Programmiersprachen implementieren (um Fehler auszuschließen). Daraus könnten doch interessante Paper entstanden sein!
Re: Dynamische und statische Typisierung
Verfasst: 20.04.2018, 17:15
von Chromanoid
Habe eben noch mal kurz geschaut und das hier gefunden:
http://danluu.com/empirical-pl/ so richtig überzeugend ist da keine Studie, wenn ich das richtig sehe.
Was mich am meisten irritiert, ist wie wenig man über die Lesbarkeit von Programmen bei dynamischer bzw. statischer Typisierung zu forschen scheint. Bei größeren Projekten liest man ja mehr Code als dass man ihn schreibt. Ich wüsste überhaupt nicht wie ich mich in einer dynamischen Sprache in eine Open Source Bibliothek einarbeiten sollte.
Bei typisierten Sprachen ist das mit der richtigen IDE für mich wie als ob ich ein gut gegliedertes Handbuch im Schnelldurchlauf lese. Bei dynamischen Sprachen kann ich oft nicht mal ebenso auf die Methode klicken, Ausführungspfaden folgen und zu den richtigen Stellen springen. Bei Groovy sind die ja soweit gegangen "Domain Specific Language Descriptoren" zu entwickeln, damit man programmieren kann, was die IDE bei entsprechenden Konstrukten für Typen zu erwarten hat (siehe
https://spring.io/blog/2011/05/09/bette ... vy-eclipse). Und JavaScript gibt es sicher auch deshalb in zig "typ-sicheren" Geschmacksrichtungen. Das muss einfach Usability-Gründe haben... :)
Re: Dynamische und statische Typisierung
Verfasst: 20.04.2018, 18:40
von Alexander Kornrumpf
Für das Protokoll möchte ich kurz anmerken, dass keiner der weiteren Diskussionsbeiträge besonders viel mit der intendierten Aussage meines Postings, das jetzt Eingangsbeitrag ist, zu tun hat. Vermutlich habe ich mich nicht sehr gut erklärt. Das nachzuholen erscheint mir recht viel Aufwand für potentiell wenig nutzen daher nur zwei Punkte:
1) Unabhängig davon ob statische oder dynamische Typisierung nach welcher Metrik auch immer "besser" sind, ist das _Argument_ mit der natürlichen Sprache, wie in dem Bild vorgebracht jedenfalls falsch. Im Sinne von: Es ist ein falsches Argument für eine ansonsten möglicherweise richtige These. Darauf ist, wenn ich es nicht überlese, im weiteren niemand mehr eingegangen.
2) Wie ich dachte schon geschrieben zu haben, aber vielleicht blöd formuliert habe, ist der Vorteil, schon durch statische Analyse erkennen zu können, ob es irgendwo im Programm eine Typinkompatibilität gibt, völlig unbestritten. Die interessantere Frage ist, was man glaubt, das aus dieser Erkenntnis folgt.
Wo ich jetzt eh schon dabei bin möchte ich einen Punkt rausgreifen:
Ein Beispiel: In Python ist es unmöglich, eine IDE zu schreiben, die dir beim Code-Schreiben schon sagt, ob er funktionieren wird oder nicht. Weil sich die Semantik des Codes buchstäblich erst zur Laufzeit entscheidet, und alles Prinzipiell alles sein kann. Du kannst eine Funktion schreiben, die aussieht, wie Quicksort, aber deine Festplatte formatiert. Natürlich ist das ein bisschen konstruiert, aber es zeigt das zugrundeliegende Problem.
Ich glaube nicht, dass das ("unmöglich") so stimmt. Ich verstehe dich so, dass du "ob er [der Code] funktionieren wird" relativ zu C++ meinst, denn als absoluter Anspruch geht das natürlich in keiner Sprache. Im Lichte von Polymorphie (Semantik zur Laufzeit) und undefined Behaviour (es kann prinzipiell alles passieren, wenn man nicht aufpasst) glaube ich, dass der Anspruch von einem C++-Compiler oder einer C++-IDE real nur in einem Maße erfüllt wird, das man mit python und sehr viel Geduld auch erreichen könnte. Ob das ein sinnvolles Unterfangen wäre ist dann wieder eine andere Frage. Einschränkend muss ich sagen, dass ich nicht weiß, ob Python Input zur Laufzeit auswerten kann ("eval"). JavaScript kann das soviel ich weiß.
Re: Dynamische und statische Typisierung
Verfasst: 20.04.2018, 18:42
von Psycho
ich bin für statisch. fail-fast und bessere autovervollständigung. lesbarkeit ist durch typinferenz wie schon geschrieben trotzdem gut.
Re: Dynamische und statische Typisierung
Verfasst: 20.04.2018, 19:11
von Chromanoid
@Alexander ich würde sagen, dass die Erwähnung des Schildes einfach nur aufzeigen soll, dass Menschen in Typen/Kategorien denken. Ich stimme dir aber zu, dass natürliche Sprache eher dynamischen Sprachen ähnelt. Der Typ ergibt sich meist aus dem Kontext und Satzbau nicht aus den Wörtern selbst, insbesondere in Sprachen ohne Groß- und Kleinschreibung.
Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
Der Satz zeigt zugleich wie nett Typinformationen manchmal auch für natürliche Sprache wären.
Re: Dynamische und statische Typisierung
Verfasst: 20.04.2018, 20:14
von Krishty
Chromanoid hat geschrieben:Habe eben noch mal kurz geschaut und das hier gefunden:
http://danluu.com/empirical-pl/ so richtig überzeugend ist da keine Studie, wenn ich das richtig sehe.
Danke, das ist Gold!
Re: Lustiges und so
Verfasst: 22.04.2018, 08:06
von antisteo
Krishty hat geschrieben:
Aber abgesehen von Kolmogorov steht mein Argument. Je höher ich ein Programm komprimiere, desto mehr geht kaputt, wenn ich einen Buchstaben ändere. Packt eure Quelltexte mit 7-Zip PPmD, ändert einen Buchstaben in den gepackten Daten, und extrahiert wieder …
Das kann ich nicht so unterstreichen, dazu mehrere Gegenbeispiele:
- Ändere ich in C einen Datentypen, geht gleich "alles" kaputt - es compilt nicht mehr
- Ändere ich in JS einen Identifier, läuft das Programm stattdessen weiter, aber der gewollte Identifier hat den Wert "undefined" - spielt der Wert eine untergeordnete Rolle oder wird meist mit false oder null belegt, geht sogar vorläufig gar nix kaputt
- Bei unserer neuen FOP-Programmiersprache ist es z.B. so, dass man durch das Löschen einer Zeile ein Feature nahtlos entfernt. Hier müsste man "kaputt" noch mal anders definieren.
Wenn du mir natürlich jetzt eine Definition für "kaputt" lieferst, die deine vorherige Aussage wahr macht, ist alles wieder in Ordnung ;)
antisteos fiktiver Krishty hat geschrieben:
kaputt meint nicht mehr die Softwarespezifikation zu 100% zu erfüllen
In dem Fall wäre aber dann das C-Programm "stärker" kaputt als das JS- oder FOP-Programm.
Re: Dynamische und statische Typisierung
Verfasst: 22.04.2018, 08:49
von Alexander Kornrumpf
Man könnte argumentieren, dass ein C-Programm was gar nicht erst kompiliert (und folglich auch keinen Schaden anrichten kann) weniger kaputt ist, als ein python-Programm, das etwas subtil anderes tut als es sollte. Vielleicht meinte Krishty das.
Re: Dynamische und statische Typisierung
Verfasst: 22.04.2018, 12:26
von xq
Da ich die Diskussion auch spannend finde, möchte ich mal noch eine Sache in den Raum werfen, die bisher vermischt wurde:
(Statische und dynamische Typisierung) vs. (Statisches und dynamisches Scope)
Zweiteres ist der teil mit: "Ich benenne eine Variable um und es compiliert/führt immer noch aus, die Variable ist dann halt undefined"
Man kann auch dynamische Typisierung mit statischen Scope haben (sprich: Variablen müssen deklariert werden, haben aber dynamischen Typ)
Ein gutes Beispiel hierfür ist C#:
Code: Alles auswählen
using System;
public class Test
{
static dynamic thingy;
public static void Main()
{
thingy = 10;
Console.WriteLine("Thingy = {0}", thingy); // Thingy = 10
thingy = new { Prop = "Name" };
Console.WriteLine("Thingy = {0}", thingy); // Thingy = { Prop = Name }
Console.WriteLine("Thingy.Prop = {0}", thingy.Prop); // Thingy.Prop = Name
otherThingy = "doof"; // prog.cs(16,3): error CS0103: The name `otherThingy' does not exist in the current context
}
}
Der Typ der Variable
thingy ist dynamisch (darum kann man den auch beliebig subscripten), aber ist deklariert.
otherThingy hingegen ist nicht deklariert -> Compilerfehler
Re: Dynamische und statische Typisierung
Verfasst: 23.04.2018, 12:19
von Jonathan
antisteo hat geschrieben:Generell zu dem Thema fällt mir noch eine sehr starke Pointe ein:
Als C-Programmierer muss man ja einen Algorithmus jedes mal neu schreiben, wenn man ihn für andere Datentypen verwenden will. Beispiel Quicksort mit array von integer geht anders als Quicksort mit Array von struct, wobei nach Feld x im Struct sortiert werden soll.
Macht man jetzt das ganze in JavaScript, entwickelt man den Algorithmus nur ein mal. Dank der dynamischen Typung ist der Code sowohl für Datentyp A als auch Datentyp B gültig. Sogar das Sortierkriterium ist dann völlig dynamisch: Gibt man keines an, wird der Wert direkt verglichen (Strings untereinander; Numbers untereinander), gibt man einen Callback an, kann man diesen zwei beliebig getypte Werte vergleichen lassen - am Ende müssen nur die eingegebenen Daten mit der Sortierfunktion harmonieren. (Quelle: Array.prototype.sort)
Prinzipiell richtig, aber zumindest mir geht es nicht um C vs. Python, sondern um die generelle Idee Statisch- vs. Dynamisch Typisiert. Sprich: Natürlich ist C eine grausame Sprache und ich glaube nicht, dass irgendjemand sie noch benutzen sollte (andere Sprachen sind nicht so viel langsamer, und wenn ich mir anschaue, wie viele gravierende Sicherheitsmängel auf das Verwenden antiquierter Programmiersprachen zurückgehen, rechtfertigt das für mich diesen minimalen Gewinn einfach nicht). Mit C++ hast du zumindest schonmal Templates und damit hast du quais alles was Java hat. Aber C++-Templates sind auch nicht toll, zum Beispiel, weil Fehlermeldungen nicht mehr menschenlesbar sind. Templates sind ein gewisser Fortschritt, aber einer der vor zig Jahren passierte und heutzutage ist man nun einmal weiter.
Mir geht es eher darum, dass man mit modernen Konzepten ohne weiteres eine Sprache entwickeln kann, die im Vergleich zu dynamischen Sprachen nicht länger oder komplizierter zu schreiben ist, aber sehr viel robuster. Dank Typinterferenz & Co, muss man gar nicht so viel mehr tippen, und an den Stellen wo man es muss, dient es zur Dokumentation des Codes und ist damit hilfreich und nicht hinderlich. Chromanoids Einwand des 'mehr Lesens' ist ja im Prinzip genau das, weswegen ich ihn an dieser Stelle nochmal hervorheben möchte. Ich habe noch keine einzige Python-Bibliothek mit benutzbarer Dokumentation gefunden. Ich muss absolut jeden kleinen Scheiß jedes mal in Google eintippen. Und das nervt, insbesondere weil es unnötig ist.
Re: Dynamische und statische Typisierung
Verfasst: 23.04.2018, 19:14
von Alexander Kornrumpf
Jonathan hat geschrieben:Ich habe noch keine einzige Python-Bibliothek mit benutzbarer Dokumentation gefunden. Ich muss absolut jeden kleinen Scheiß jedes mal in Google eintippen. Und das nervt, insbesondere weil es unnötig ist.
Wait, what?
Re: Dynamische und statische Typisierung
Verfasst: 25.04.2018, 10:18
von Jonathan
Darüber rante ich mal in einer ruhigen Minute, es wird aber sicherlich noch etwas subjektiver als der Rest meiner Kritik.
Re: Dynamische und statische Typisierung
Verfasst: 28.04.2018, 00:09
von Krishty
Jonathan hat geschrieben:Natürlich ist C eine grausame Sprache und ich glaube nicht, dass irgendjemand sie noch benutzen sollte (andere Sprachen sind nicht so viel langsamer, und wenn ich mir anschaue, wie viele gravierende Sicherheitsmängel auf das Verwenden antiquierter Programmiersprachen zurückgehen, rechtfertigt das für mich diesen minimalen Gewinn einfach nicht).
Wow. Nicht-antiquierte Sprachen wie Java oder JavaScript sind für ihre überragende Sicherheit bekannt? Oder sollen wir jetzt alles in Rust machen?
Alexander Kornrumpf hat geschrieben:Man könnte argumentieren, dass ein C-Programm was gar nicht erst kompiliert (und folglich auch keinen Schaden anrichten kann) weniger kaputt ist, als ein python-Programm, das etwas subtil anderes tut als es sollte. Vielleicht meinte Krishty das.
Ja, genau – denn so war ja auch das ursprüngliche Argument. In C definierst du die Randbedingungen eines Funktionsaufrufes dreifach: Durch die Definition, durch eine quasi-identische optionale Deklaration und nochmal implizit durch die Typen der Operanden beim eigentlichen Aufruf. Sobald die drei nicht mehr deckungsgleich sind, kommt es gar nicht zur Ausführung. Da „zufällig“ was kaputt zu machen ist auf jeden Fall schwerer als bei Python, wo der Vertipper …
alles tun könnte.
Chromanoid hat geschrieben:Bei typisierten Sprachen ist das mit der richtigen IDE für mich wie als ob ich ein gut gegliedertes Handbuch im Schnelldurchlauf lese. Bei dynamischen Sprachen kann ich oft nicht mal ebenso auf die Methode klicken, Ausführungspfaden folgen und zu den richtigen Stellen springen.
Ich habe diesbezüglich mal nachgefragt, und mein JavaScript-Kollege meinte, dass das dort alles kein Problem sei (PHPStorm könne das so gut wie eine C-IDE). Könnte heißen, dass schwer entscheidbare Fälle viel seltener sind, als wir denken. Überprüft hab ich’s nicht.
Re: Dynamische und statische Typisierung
Verfasst: 28.04.2018, 08:28
von Chromanoid
Mmh vielleicht. Ich kenn's vor allem von Groovy und Eclipse. Das Problem sind sicher nicht die Stellen, wo man die dynamischen Aspekte der Sprache nicht ausnutzt. Wie gesagt wurde bei Groovy für diesen Zweck eine eigene Beschreibungssprache gebastelt, damit man auch die dynamischen Stellen mit Auto-Completion usw. versehen kann.
Ein sehr beliebtes Pattern sind zumindest bei Groovy für Gradle die dynamische Deklaration von vermeintlichen Member-Variablen bzw. Methoden. Das ganze funktioniert über "catch-all" Methoden. Bei PHP geht das auch irgendwie bei JavaScript gibt's dafür wohl mittlerweile auch was.
Da das schick für DSLs ist, wird's wohl benutzt aber für die Verständlichkeit ist es halt pures Gift. AOP und Proxy-Objekte gibt's ja auch für Java, aber zumindest sind da die Zugriffe typisiert, man kann halt nur nicht so einfach verstehen, was theoretisch durch den Methodenaufruf alles ausgelöst wird.
Ansonsten gibt's bei dynamischen Sprachen ja sowieso das Problem, dass Objekte praktisch einfach nur Key-Value-Maps sind. Da kann man eben nur begrenzt wissen, wer da wann was reingetan hat...
Aus o.g. Gründen haben sich die Gradle Leute übrigens für das typsichere Kotlin als neue Buildscript-Sprache entschieden. Ohne vernünftige Code-Completion und Co. ist das einfach zu unkomfortabel und fehleranfällig:
https://blog.gradle.org/kotlin-meets-gradle
You’ll find that, suddenly, the things you usually expect from your IDE just work, including:
* auto-completion and content assist
* quick documentation
* navigation to source
* refactoring and more
The effect is dramatic, and we think it’ll make a big difference for Gradle users.
Re: Dynamische und statische Typisierung
Verfasst: 28.04.2018, 11:00
von Alexander Kornrumpf
Krishty hat geschrieben:
Alexander Kornrumpf hat geschrieben:Man könnte argumentieren, dass ein C-Programm was gar nicht erst kompiliert (und folglich auch keinen Schaden anrichten kann) weniger kaputt ist, als ein python-Programm, das etwas subtil anderes tut als es sollte. Vielleicht meinte Krishty das.
Ja, genau – denn so war ja auch das ursprüngliche Argument. In C definierst du die Randbedingungen eines Funktionsaufrufes dreifach: Durch die Definition, durch eine quasi-identische optionale Deklaration und nochmal implizit durch die Typen der Operanden beim eigentlichen Aufruf. Sobald die drei nicht mehr deckungsgleich sind, kommt es gar nicht zur Ausführung. Da „zufällig“ was kaputt zu machen ist auf jeden Fall schwerer als bei Python, wo der Vertipper …
alles tun könnte.
Mögliche Gegenargumente:
1) Aus sich eines unerfahrenen Programmierer kann auch kompilierender C-Code "
alles" (tm) tun. Da undefined behaviour ja keine Kompilerfehler wirft, sogar wortwörtlich. Subjektiv tut python-Code viel öfter das was man dachte dass er tun würde, als C-Code. Das stellt sich für dich oder dot oder einige andere hier sicher anders da, aber Robert C. Martin erzählt ja in jedem Talk dass die Hälfte aller Programmierer weniger als 5 Jahre Erfahrung hat.
2) Es gibt genug Business Cases in denen ein Programm was "ein bisschen kaputt" ist das Unternehmen weniger Geld kostet als eins das gar nicht läuft. Egal wie sehr der Ingenieur die Hände darüber ringen mag.
Ich merke gerade, dass ich nur das paraphrasiert habe was in unserem Alter eh die Antwort auf jede Frage nach den Vorzügen einzelner Sprachen sein sollte: Es hängt von der Erfahrung des Teams und der Eignung für die konkrete Aufgabe ab.
Re: Dynamische und statische Typisierung
Verfasst: 28.04.2018, 11:07
von NytroX
Naja, ich finde die Grenzen verschwimmen da mittlerweile relativ stark.
In PHP haben die Variablen auch feste Typen, aber man kann ihnen trotzdem alles zuweisen.
Die Frage ist, ob man sowas immer will.
Beispiel in C++:
Code: Alles auswählen
auto myFun(bool x){
if (x) return "Hi"; else return 2.0f;
}
Geht nicht. Warum? Weil mans nicht will!
Gedankenexperiment: Durch was müsste ich "auto" ersetzen, damit das in C++ funktioniert? Ist es dann nicht dynamsich?
Die Frage ist für mich meistens: Warum sollte ich sowas schreiben?
Das gilt vor allem auch in dynamsichen Sprachen:
Sowas macht man einfach nicht, wenn man den Code später noch warten will. Das gehört (meistens) einfach in 2 verschiedene Variablen, weil die Inhalte gar nichts miteinander zu tun haben.
Und da finde ichs gut, wenn die Sprache/das Typesystem sowas einfach nicht zulässt.
Wie wärs mit:
Code: Alles auswählen
immutable titleForWindow = "1";
immutable acceleration = 2.0f;
=> sinnvolle Namen helfen, klare Unterscheidung des Zwecks, und nur Variablen verwenden, wo es sein muss (ansonsten immutable oder const oder was auch immer die Sprache her gibt).
Habe oft bemerkt, dass man dann gar keine dynamische Typisierung braucht, oder überhaupt will.
Java ist auch eigentlich statisch typisiert, aber mir passiert es oft, dass ich von einem Objekt "toString()" aufrufe, und dann einen Wert wie "0x52325325" in der Ausgabe landet. Offensichtlich nicht Sinn der Sache.
Das ist mir auch schon zu "dynamsich", ein Compilerfehler wäre mir lieber (obwohl es mit der Typisierung nichts zu tun hat).
Bei manchen Konstrukten kann ich schon garnicht mehr sagen, ob ich es unter "statisch" oder "dynamisch" einordnen soll. In C# kann ich den statischen Typ "dynamic" vergeben...
Ich denke, was man eigentlich will, ist ein "fail early" (am besten sogar noch vor der compile time in der IDE!). Egal, wie man das erreicht. (Wobei ein Typensystem da mMn durchaus helfen kann)
Für eine schnelle Entwicklungszeit ist mir ein "fail early" wichtig, damit ich nicht so oft debuggen muss, und die AutoCompletion. Da hängts auch oft, sogar in Java kriegen die meisten IDEs das bei Lambdas nicht mehr hin, wenn man den Argument-Typ nicht mit angibt.
Ich glaube, jeder, der schonmal mit VS in C# entwickelt hat, weiß, dass andere Sprache/IDE-Kombinationen da oft unterlegen sind.
Außerdem kann es gut sein, dass bei der Entwicklung selbst der Unterschied von verschiedenen Sprachen nicht so groß ist, was die Entwicklungszeit angeht... aber versuch das mal über Jahre hinweg zu warten! :D
Re: Dynamische und statische Typisierung
Verfasst: 28.04.2018, 11:49
von xq
NytroX hat geschrieben:In C# kann ich den statischen Typ "dynamic" vergeben...
Vorsicht!
dynamic ist tatsächlich "dynamisch typisiert" wie in Lua oder JavaScript! Da wird nichts zur Compilezeit überprüft, alle Auswertung erfolgt zur Runtime und verhält sich dann eben auch wie dynamisch typisierte Programmiersprachen (sprich: Es knallt, wenn was ungültiges angestellt wird).
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/dynamic hat geschrieben:Type
dynamic behaves like type
object in most circumstances. However, operations that contain expressions of type
dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. As part of the process, variables of type
dynamic are compiled into variables of type
object. Therefore, type
dynamic exists only at compile time, not at run time.