Sprache gesucht!
-
naja, schau mal:
ruby-progger ~ $ irb irb(main):001:0> class Test irb(main):002:1> def foo() irb(main):003:2> puts "In foo()." irb(main):004:2> end irb(main):005:1> end => nil irb(main):006:0> t = Test.new => #<Test:0xb7c053fc> irb(main):007:0> t.foo In foo(). => nil irb(main):008:0> class Test irb(main):009:1> def bar() irb(main):010:2> puts "In bar()." irb(main):011:2> end irb(main):012:1> end => nil irb(main):013:0> t.bar In bar(). => nil irb(main):014:0> def t.bar irb(main):015:1> puts "t's own bar()" irb(main):016:1> end => nil irb(main):017:0> t.bar t's own bar() => nil irb(main):018:0> another_t = Test.new => #<Test:0xb7bd8870> irb(main):019:0> antother_t.bar NameError: undefined local variable or method `antother_t' for main:Object from (irb):19 from :0 irb(main):020:0> another_t.bar In bar(). => nil irb(main):021:0>
-
pumuckl schrieb:
Wenn ich mir das so durchlese scheints das einfach nicht zu geben, und es scheint auch keiner meine Motivation einzusehen.
Weil du denkst dass dynamisch typisierte Sprachen nicht typsicher sind. Aber das ist falsch.
Was du willst ist einfach nur Sinnlos.
Gerade wenn ich dynamisch Code austausche besteht doch die Gefahr dass ich höllisch aufpassen muss um nicht beispielsweise Aufrufe von nicht vorhandenen Methoden zu haben. Oder Zugriffe auf nichtmehr vorhandene Member.
Das ist ein triviales Problem.
Im Grunde will ich doch nur das Beste aus beiden Welten - die Flexibilität durch dynamisch änderbaren Code und die Sicherheit und Konsistenz die mir der Compiler durch statische Typüberprüfung gewährleisten kann.
Nur dann kannst du eben den Typen nicht on the fly ändern. Dann musst du alles neukompilieren und das bedeutet du kannst nicht so einfach Teile austauschen.
Du gehst von so falschen voraussetzungen aus. Dynamische Typisierung ist eine gute typisierung und kann auch sehr strikt sein (je nach Sprache). Es ist nicht das beste beider Welten wenn du statische Typisierung in ein dynamisches Umfeld mitnimmst, es ist einfach eine Krücke.
Mir ist klar dass ich die Vielfalt der möglichen Änderungen dadurch einschränke, weil damit der Code nur von einem konsistenten Zustand in den nächsten übergehen kann ohne irgendwelche losen Enden, aber gerade das will ich ja erreichen.
nur ist das mit dynamischer typisierung total simpel zu erreichen. und simpel ist besser.
Wäre für einen solchen Zweck evtl folgendes sinnvoll?:
- Ich erweitere eine dynamisch typisierte Sprache um Typbezeichner und alles weitere was ich für statische Typisierung/die Konsistenzchekcs brauche.
- Ein Präprozessor (im Grunde schon ein halbes Compilerfrontend) übernimmt die Typüberprüfungen und weitere Konsistenzchecks, übersetzt den ganzen Mist in die eigentliche Sprache und macht den Codeupdate.Nein. Das was du willst ist serialisierung.
Wenn du ein statisches System willst, dann mach folgendes:Bevor das System upgedatet wird, wird die Verarbeitung auf eine backup DLL ausgelagert die zB nur Anfragen queued und sonst nichts macht. Sobald die backup DLL online gegangen ist, fährst du das ganze System herunter und serialisierst alle Daten. Danach kopierst du das neue System drüber und startest es. Es liest die serialisierten Daten ein und schickt die backup DLL wieder schlafen und übernimmt die Verarbeitung der gequeued Elemente. Danach ist die backup DLL ebenfalls austauschbar.
Das ist ein statisches System. Das funktioniert, ist aber umständlich.
Ein dynamisches System wäre viel cooler - du tauscht einfach eine komponente aus und fertig. ohne das system abzudrehen.
es macht einfach keinen sinn sich selbst mit statischer typisierung so zu verkrüppeln. statische typisierung bietet einem nichts was so toll ist. es gibt nur sehr wenige situationen wo statische typisierung mehr fehler abfängt als dynamische. und die sind dann idr in branches die fast nie ausgeführt werden. aber statische typisierung ermöglicht dafür auch eine reihe an konvertierungsfehlern die man in dynamisch typisierten system nicht hat.
du gehst davon aus dass statische typisierung sicherer ist als dynamische - das ist aber falsch. und deshalb macht es keinen sinn was du hier willst.
-
in Anlehnung an die Beispiele weiter oben, und nur damit ich alles richtig verstehe:
Montag:
class Test def foo() puts "foo()" end end class Doit def do() t = Test.new t.foo end end Doit d
Dienstag:
d.do
sollte ok sein oder?
Mittwoch:
class Test def bar() puts "bar()" end end
a)
läuft noch oder wird hier schon gemeckert dass der Aufruf von foo in Doit.do Mist ist?Donnerstag:
d.do
b)
oder krachts jetzt erst weil der interpreter plötzlich merkt dass es kein foo mehr gibt?Wann krachts, Mittwoch oder Donnerstag? Ich hätts gern dass die Eingabe am Mittwoch nicht akzeptiert wird weil das Programm inkonsistent ist, da der Aufruf von t.foo in Doit.do bullshit ist nach der neudefinition von Test
Zugegeben, ich habe nicht so viel Erfahrung mit dynamisch typisierten Sprachen (ein wenig PhP und Perl) wie mit statisch typisierten. Wenn mir jetzt jemand glaubhaft machen kann dass der Fehler bei dynamisch typisierten Sprachen schon dann bemerkt und abgelehnt wird wenn er in den Code kommt und nicht erst wenn der Interpreter beim Abarbeiten drüber stolpert und auf die Nase fällt, dann werd ich mich gern auf Ruby, Groovy oder andere Dynamisch typisierte Sprachen verlassen.
Ansonsten danke Shade, die Methode mit den DLLs entspricht in etwa dem was ich im Hinterkopf hatte. Ein Programm zu schreiben das den Switch von Alt nach Neu mit Serialisierung, umkopieren der DLLs und Deserialisierung überwacht sollte ja nicht allzu schwer sein oder?
-
Was heißt "es kracht". Es wird eben idr eine Exception geworfen, auf die du entsprechend reagieren kannst. Aber es gibt ja auch entsprechende Refactoring-Tools, zB rope für Python, die bei solchen Problemen helfen können. (und natürlich in dem du den Code vorher testest).
btw. vielleicht solltest du dir mal Haskell anschauen. Haskell ist statisch typisierend und der Code ist hotswapable. Und es gibt wohl auch OOP-Erweiterungen für Haskell.