Sprache gesucht!



  • Zeus schrieb:

    Groovy, Ruby und Phyton haben eine dynamische Typisierung sind aber Type-Safe. Ledenfalls lt. http://de.wikipedia.org/wiki/Dynamische_Typisierung
    In Groovy wird eine Exception geschmissen, wenn du versucht eine Integer-Variable einen StringLiteral zu geben.

    Wobei bei Ruby nicht die Variable getypt wird, sondern das referenzierte Objekt. Bei Python wird jedoch die Variable getypt.
    Das heißt bei Ruby kann eine Variable einmal einen String enthalten, dann eine Zahl und dann wieder einen String.
    Bei Pyhton bedeutet einmal String immer String.

    Und das finde ich imo besser und auch sehr schade, dass es Ruby nicht so macht.



  • Tippgeber schrieb:

    Wobei bei Ruby nicht die Variable getypt wird, sondern das referenzierte Objekt. Bei Python wird jedoch die Variable getypt.
    Das heißt bei Ruby kann eine Variable einmal einen String enthalten, dann eine Zahl und dann wieder einen String.
    Bei Pyhton bedeutet einmal String immer String.

    Und das finde ich imo besser und auch sehr schade, dass es Ruby nicht so macht.

    Das ist komplett falsch. Variablen in Python können immer beliebige Objekte aufnehmen - auch von wechselnden Typen, ganz genau wie in Ruby.



  • tfa schrieb:

    Tippgeber schrieb:

    Wobei bei Ruby nicht die Variable getypt wird, sondern das referenzierte Objekt. Bei Python wird jedoch die Variable getypt.
    Das heißt bei Ruby kann eine Variable einmal einen String enthalten, dann eine Zahl und dann wieder einen String.
    Bei Pyhton bedeutet einmal String immer String.

    Und das finde ich imo besser und auch sehr schade, dass es Ruby nicht so macht.

    Das ist komplett falsch. Variablen in Python können immer beliebige Objekte aufnehmen - auch von wechselnden Typen, ganz genau wie in Ruby.

    Seit wann das? Aber ich habe gerade nachgesehen und du hast recht. Ich bin mir so sicher, dass ich das damals in Dive into Python gelesen habe. Und habe es seither auch nie mehr ausprobiert.



  • Keine Ahnung. War das je anders?



  • Ich bin bei Python seit dem 20.01.06 und damals wars auch schon so. 😉



  • Shade Of Mine schrieb:

    statisch typisiert und zur laufzeit klassen ändern beisst sich.

    wenn ich

    obj.meth();

    mache und das statisch auswerten will, dann kann ich nicht garantieren dass obj zu diesem zeitpunkt meth als member haben wird.

    Doch, kann ich und will ich. Wenn ich obj.meth() aufrufen will, muss zu dem Zeitpunkt meth() ein member von obj sein. Wenn ich auf der anderen Seite die Klasse von obj später so ändern will, dass meth() aus der Klasse entfernt wird, darf gleichzeitig im restlichen Code kein Aufruf von meth() mehr vorhanden sein. Dass dadurch neuer Code erstmal umfangreich auf Konsistenz gecheckt werden muss nehme ich in Kauf, wenn ich dadurch verhindere dass mein System mir um die Ohren fliegt weil ich in einer dynamisch typisierten Sprache irgendwo ein meth() im Code gelassen hab obwohl obj neuerdings diese Methode garnicht mehr hat. Wenn ich auf der anderen Seite die Sicherheit haben will dass mir der Code nicht um die Ohren fliegt, muss ich eine Möglichkeit haben, ihn beim "einchecken" zu prüfen, und das geht nur mit statischer Typisierung.



  • Also stell dir mal vor du kapselst die Anweisungen, die die Struktur eine beliebigen Klassen ändert. Dies kann dann vom Benutzer aktiviert werden. Wie soll der Compiler jetzt auf die Typen nachprüfen, wenn die Compilezeit schon längst um ist?



  • pumuckl schrieb:

    Doch, kann ich und will ich.

    Kannst du aber nicht mit statisch typisierten Sprachen.

    Dass ist der Sinn von statisch typisierten Systemen dass ich garantieren kann dass obj die methode meth hat oder nicht.
    Was du willst ist ein dynamisch typisiertes System wo du zur zeit des code erstellens nicht weisst ob obj jetzt die methode meth hat oder nicht.

    Wenn ich obj.meth() aufrufen will, muss zu dem Zeitpunkt meth() ein member von obj sein. Wenn ich auf der anderen Seite die Klasse von obj später so ändern will, dass meth() aus der Klasse entfernt wird, darf gleichzeitig im restlichen Code kein Aufruf von meth() mehr vorhanden sein. Dass dadurch neuer Code erstmal umfangreich auf Konsistenz gecheckt werden muss nehme ich in Kauf, wenn ich dadurch verhindere dass mein System mir um die Ohren fliegt weil ich in einer dynamisch typisierten Sprache irgendwo ein meth() im Code gelassen hab obwohl obj neuerdings diese Methode garnicht mehr hat.

    Klingt ziemlich doof. Du sagst nämlich effektiv: du willst kein dynamisches system sondern du willst immer alles komplett neu kompilieren. Wenn du meth raus nimmst muss der code ja umgeschrieben werden.

    Wenn ich auf der anderen Seite die Sicherheit haben will dass mir der Code nicht um die Ohren fliegt, muss ich eine Möglichkeit haben, ihn beim "einchecken" zu prüfen, und das geht nur mit statischer Typisierung.

    Du hast dynamische typisierung nicht verstanden.
    der code fliegt dir so oder so um die ohren wenn er falsch ist.

    die frage: was willst du wirklich. aktuell beschreibst du ein system dass kein bisschen dynamisch ist. das kannst du ohne aufwand in c++ implementieren. du kompilierst bei jeder änderung alles neu und ersetzt dann auf einen schlag alle binaries.



  • Shade Of Mine schrieb:

    die frage: was willst du wirklich. aktuell beschreibst du ein system dass kein bisschen dynamisch ist. das kannst du ohne aufwand in c++ implementieren. du kompilierst bei jeder änderung alles neu und ersetzt dann auf einen schlag alle binaries.

    Nur dass ich dabei die Laufzeitumgebung inklusive aller bereits bestehenden Objekte verliere, was eben genau das ist was ich nicht will.

    Im Grunde könnte mans auch so beschreiben, dass ich das neue Programm kompiliere und sofort starte, und zwar mit der alten Laufzeit als Initialisierung. Das neue Programm transformiert dann die alten Objekte entsprechend der Vorgaben und arbeitet dann mit den neuen Objekten wie gehabt weiter.



  • pumuckl schrieb:

    Im Grunde könnte mans auch so beschreiben, dass ich das neue Programm kompiliere und sofort starte, und zwar mit der alten Laufzeit als Initialisierung. Das neue Programm transformiert dann die alten Objekte entsprechend der Vorgaben und arbeitet dann mit den neuen Objekten wie gehabt weiter.

    Denk mal nochmal nach.



  • Was du willst macht keinen Sinn. Genau für soetwas gibt es dynamische typisierung.

    Man könnte jetzt natürlich hergehen und einfach immer konverter schreiben um den aktuellen status zu behalten wenn man das system mit dem neuen code neustartet. mit serialisierungs-frameworks sollte das kein allzugroßes problem sein.

    aber du stößt an allen ecken und enden auf probleme die du nicht haben würdest wenn du zB python oder ruby verwenden würdest. dynamische typisierung ermöglicht ja genau das was du willst - code zur laufzeit zu ändern.

    zB hatte volkard als bot in #cpp eine lange zeit Marvin. Marvin war in Perl geschrieben und man konnte zur laufzeit allen möglichen code austauschen. Marvin hat sich nie vom server trennen müssen nur weil er upgedatet wurde.

    das ganze in statischen sprachen ist schon deutlich schwerer.
    wozu willst du statische typisierung haben?

    denn eigentlich sollte man das richtige tool für den richtigen job verwenden. aber gerade wenn du dynamisch code austauschen willst, dann stören statische typchecks nur. und es ist ja nicht so dass dynamische typisierung schwach wäre oder fehler provozieren würde. viele leute sehen dynamische typisierung als fehlerunfanfälliger an - wobei das immer eine endlose debatte ist bei der keiner gewinnen kann...



  • Wenn ich mir das so durchlese scheints das einfach nicht zu geben, und es scheint auch keiner meine Motivation einzusehen.

    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. 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.

    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.

    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.



  • pumuckl schrieb:

    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. 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.

    Du solltest dir erstmal die dynamischen Sprachen ansehen, bevor du irgendwas in dem Mund nehmst.

    class Auto
      def fahren()
        puts "Jetzt fahrt das Auto"
      end
    end
    
    class Flugzeug
      def fliegen()
        puts "Jetzt fliegt das Flugzeug"
      end
    end
    
    x = Auto.new
    x.fliegen;
    

    D:\workspace\RubyApplication2\lib\main.rb:18: undefined method `fliegen' for #Auto:0x1554d32 (NoMethodError)

    Ist übrigends kein Compilerfehlermeldung, sonder vom Interpreter.



  • 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.


Anmelden zum Antworten