Forum: PC-Programmierung Rust oder Nimrod als neue Hobbyprogrammiersprache?


von Yalu X. (yalu) (Moderator)


Lesenswert?

Vorbemerkung:

Hier geht es im zwei relativ junge und noch nicht zu Ende entwickelte
Pogrammierpsrachen, die

- nicht morgen schon C++, Java & Co komplett ersetzen sollen,

- nicht für Softwarefirmen, die bereits einen riesigen Pool von
  Softwaremodulen in einer anderen Sprache aufgebaut haben, geeignet
  sind und

- nicht auf 8-Bit-Mikrocontroller lauffähig sind,

also derzeit eher den ambitionierten und neophilen Freizeitprogrammierer
auf PCs oder nicht allzu mickrig ausgestatteten Embedded-Systemen
ansprechen.

Unter diesem Gesichtspunkt würde ich gerne die Diskussion hier sehen.

————————————————————————————————————————————————————————————————————————

Ich bin schon länger auf der Suche nach einer Programmiersprache, die
die Geschwindigkeit von C mit der Ausdrucksstärke von Python verbindet
oder zumindest einen guten Kompromiss zwischen beiden darstellt.

Die heißesten Kandidaten in dieser Richtung waren für mich bisher
Haskell und Lisp, die beide den zusätzlichen Vorteil haben, dass die
Arbeit mit ihnen auf Grund ihrer Andersartigkeit unglaublich viel Spaß
macht.

Da ich sie aber nur hobbymäßig einsetze, bin ich nicht wirklich geübt
darin, so dass ich für das Zusammenklopfen von Programmen, die ich
schnell mal brauche, meist doch auf Python zurückfalle (oder C, wenn die
Laufzeit eine Rolle spielt).

In diesen beiden Threads

  Beitrag "go or nogo ;)"
  Beitrag "Scriptsprache lernen"

wurden nun weitere Alternativen genannt, u.a. Rust und Nimrod. Weil mich
Stefan noch einmal daran erinnert hat

  Beitrag "Re: Was ist eine Instanz?"

gestern schlechtes Wetter war und von Rust kürzlich ein neues Release
herauskam, habe ich die beiden Compiler installiert, die Tutorials
durchgearbeitet und angefangen, damit herumzuspielen. Hier sind meine
vorläufigen Eindrücke und Erkenntnisse:

So richtig aus den Socken gehauen (so seinerzeit bei Pascal, C, Python,
Lisp und Haskell) hat es mich bei keiner der beiden Sprachen, aber man
ist ja mittlerweile auch ziemlich verwöhnt ;-)

Ich habe hier die für mich persönlich wichtigen High- und Lowlights
zusammengestellt:

Beide:

- Multiparadigma (prozedural, objektorientiert und ein Bisschen
  funktional)

- statische Typisierung, strenge Typprüfung, Typinferenz (mit
  Einschränkungen)

- durch Kompilierung, statische Typisiering und andere
  Spracheigenschaften schnell (habe allerdings keine Benchmarks gemacht)

- recht hohes Abstraktionsniveau

- keine Speicherlecks, Array-Überläufe und invalide Pointer

- mächtiges Makrosystem, gute Unterstützung von Metaprogrammierung

- Operaturüberladung, Closures, Generics

- ziemlich stabil, aber noch im Aufbau und Wandel begriffen

- Angebot an Bibliotheken ist da, aber noch bei weitem nicht so 
umfangreich
  wie bspw. für Python

- Foreign-Function-Interface zur Einbindung von bestehendem Code
  vorhanden

- keine Anfängersprachen, aber für jemanden, der bereits eine der
  Mainstream-Sprachen beherrscht, relativ leicht und schnell zu lernen


Rust:

- Kompromiss zwischen Ressourcenkontrolle und Abstraktionsniveau ist in
  weiten Grenzen wählbar

- Syntax: Blockstruktur ähnlich wie C, Deklarationen ähnlich wie Pascal

- algebraische Datentypen mit Pattern-Matching

- etwas mehr funktionales Feeling als bei Nimrod, aber ohne rigorose
  Einschränkungen wie bspw. bei Haskell

- eine Art Typklassensystem durch Traits nachgebildet

- Schwerpunkt auf sicherer multithreaded Programmierung

- Speicherprobleme, Race-Conditions u.ä. werden vielfach bereits zur
  Compilezeit erkannt oder bereits durch das Sprachdesign ausgeschlossen

- verschiedene Speichermöglichkeiten für Variablen: Static, Stack,
  Boxed, Reference-Counting, Garbage-Collection.

- relativ lange Kompilierzeiten

- kein interaktiver Modus


Nimrod:

- Syntax: Blockstruktur ähnlich wie Python, Deklarationen ähnlich wie
  Pascal

- benutzerdefinierte Operatoren

- named Arguments und Defaultwerte für Argumente

- Iteratoren/Generatoren ähnlich wie Python

- Subranges von Integer- und Enum-Typen als neuer Typ

- Makrosystem wohl noch mächtiger als in Rust

- Interpreter für interaktive Benutzung vorhanden, aber noch ziemlich
  buggy


Jede der beiden Sprachen hat ein paar coole Features, die die jeweils
andere nicht hat, weswegen ich bei keiner von beiden klar "Die isses!"
sagen kann.

Tendenziell sagt mir aber Rust ein klein wenig mehr zu, weil es – so
mein Eindruck – mehr Möglichkeiten bietet, den Programmstil je nach Art
der Anwendung (und aktueller Laune ;-)) aus den folgenden Alternativen
auszuwählen:

- C-Stil: geschwindgkeitsoptimiert, Variablen primär auf dem Stack oder
  statisch, feste Variablengrößen, ...

- C++-Stil: Objekte, Traits, dynamische Container-Typen, Smart-Pointers,
  ...

- Python-Stil: dynamische Container-Typen, Garbage-Collection, nicht
  mehr viel nachdenken müssen, ...

- Haskell-Stil (naja, wenigstens ansatzweise): immutable Variablen,
  Algebraische Datentypen, Pattern-Matching, logische Fehler führen mit
  recht hoher Wahrscheinlichkeit zu Compilezeit-Fehlern, ...

Gerade bei größeren Programmen, die oft aus High- und Low-Level-,
rechenzeitkritischen und -unkritischen Teile bestehen, hat man somit für
jeden Teil die richtigen Werkzeuge, ohne dafür die Sprache wechseln zu
müssen.

Wesentlich besser würde mir Rust aber gefallen, wenn es wie in Nimrod
einen interaktiven Interpreter, benutzerdefinierte Operatoren und
Generatoren gäbe. Außerdem habe ich eine wachsende Abneigung gegen
geschweifte Klammern, die nicht nur hässlich aussehen, sondern auch auf
deutschen Tastaturen schwer zu tippen sind. Leider braucht man sie in
Rust noch öfter als in C(++).

Trotzdem werde ich in der nächsten Zeit wohl noch etwas tiefer in Rust
eindringen, auch in der Hoffnung, dass vielleicht das eine oder andere
fehlende Feature noch nachgereicht wird.


Wenn jemand von euch ebenfalls schon Erfahrungen mit diesen Sprachen
gesammelt hat, würde mich eure Meinung dazu interessieren.

von Fritz (Gast)


Lesenswert?

Rust ist auch deshalb cool, weil die Entwickler schwer darauf acht 
geben, daß es (für kleine eingebettete Systeme) auch ohne 
Standardbibliothek sinnvoll nutzbar ist.

von Paul B. (paul_baumann)


Lesenswert?

Warum wird der Kram immer, immer komplizierter??

Was nützt es, die Auswahl zwischen X Programmiersprachen zu haben, wenn
man 5 Minuten für den Algorithmus des Programmes braucht, aber 5 Wochen,
um sich mit mistiger Syntax herumzuzanken?

Das mußte ich mal sagen, auch wenn es nicht zum Thema passt und wohl
auch niemanden anhebt.

MfG Paul

von Fritz (Gast)


Lesenswert?

Paul Baumann schrieb:
> Was nützt es, die Auswahl zwischen X Programmiersprachen zu haben, wenn
> man 5 Minuten für den Algorithmus des Programmes braucht, aber 5 Wochen,
> um sich mit mistiger Syntax herumzuzanken?

Es geht ja eben darum, die mistige Syntax von C und C++ zu verbessern, 
so daß der Programmierer leichter und klarer ausdrücken kann, was er 
will.

von Hello World ;) (Gast)


Lesenswert?

Paul Baumann (paul_baumann) schrieb:

> Warum wird der Kram immer, immer komplizierter??

Wahrscheinlich liegt's ein wenig hieran:

http://www.linux-magazin.de/Ausgaben/2012/10/Rust/%28offset%29/8

" Rust soll sich offenbar zu einer eierlegenden Wollmilchsau entwickeln: 
Der Code will die Geschwindigkeit von C++ erreichen, eine 
Speicherverwaltung verhindert nervende Abstürze, die funktionale 
Programmierung vereinfacht nebenläufige Aufgaben. Um das alles zu 
erreichen, übernehmen die Entwickler die ihrer Meinung nach besten 
Konzepte aus anderen Sprachen. Einfluss genommen haben laut 
Sprachreferenz so illustre Gestalten wie NIL, Hermes, Erlang, Sather, 
Newsqueak, Napier, Go, SML, C#, C++, Haskell, Python und Ruby. Die 
erstgenannten Exoten stammen durchweg aus den 80er Jahren.

Das Ergebnis ist ein Programmiersprachen-Cocktail "

Außerdem wäre für Windows die Frage, wie leicht lassen sich solche 
Sprachen zu GUI Programmem übersetzen. Daran hapert's dann oft, weil 
sich solche Exoten in erster Linie für sich selbst interessieren.

von Dussel (Gast)


Lesenswert?

Solange nicht so eine labernde Syntax wie die von Delphi übernommen 
wird, denke ich, kann man gespannt sein, ob da was Brauchbares 
rauskommt. Warum sollte man es von vornherein verurteilen?

von DingsDa (Gast)


Lesenswert?

Yalu X. schrieb:
> Außerdem habe ich eine wachsende Abneigung gegen
> geschweifte Klammern, die nicht nur hässlich aussehen, sondern auch auf
> deutschen Tastaturen schwer zu tippen sind.

Deshalb arbeite ich mit einer amerikanischen Tastatur, wenn es um das 
Programieren geht.

Ich finde es interessant, welche Klimmzüge veranstaltet werden um eine 
neue Sprache zu etablieren bzw. zu greieren.
Ein Frage die mich beschäftigt ist die, warum soll ich eine neue Sprache 
lernen (hätte kein Problem damit), wenn das OS auf dem ich diese Sprache 
einsetze in purem C und ein bisschen Assembler geschrieben ist?
Macht aus meiner Sicht keinen Sinn. Denn wenn das OS in der neuen 
Sprache geschrieben wäre, dann sollte doch das Gesamte in sich stabiler 
sein? Oder sehe ich etwas falsch?
Vor einigen Jahren gab es einmal einen Ansatz zur Sprache D, sehr C 
lastig.
Davon habe ich nichts mehr gehört / gelesen.

Habe in meinem Umfeld noch kein OS gesehen, das mit einer anderen 
Sprache als C/Assembler geschrieben war/ist.
Wenn hierzu jemand eine Info hätte, würde mich das sehr interessieren.

von TriHexagon (Gast)


Lesenswert?

Hello World ;) schrieb:
> Außerdem wäre für Windows die Frage, wie leicht lassen sich solche
> Sprachen zu GUI Programmem übersetzen. Daran hapert's dann oft, weil
> sich solche Exoten in erster Linie für sich selbst interessieren.

Erstens ist Rust kein Exot, es vereint etablierte moderne Konzepte und 
macht dir keine Vorschriften welches Paradigma du zu nutzen hast. Exoten 
sind Sprachen wie Haskell und Lisp.

Zweitens warum sollte es Probleme mit der GUI geben? Rust kann ohne 
Probleme C Code aufrufen und damit auch die WinAPI und GTK. Wrapper und 
Bindings gibt es schon.

DingsDa schrieb:
> Ein Frage die mich beschäftigt ist die, warum soll ich eine neue Sprache
> lernen (hätte kein Problem damit), wenn das OS auf dem ich diese Sprache
> einsetze in purem C und ein bisschen Assembler geschrieben ist?
> Macht aus meiner Sicht keinen Sinn. Denn wenn das OS in der neuen
> Sprache geschrieben wäre, dann sollte doch das Gesamte in sich stabiler
> sein? Oder sehe ich etwas falsch?

Klar mit C und Assembler kannst du alles schreiben was du willst. Aber 
mal im Ernst willst du immer noch so programmieren wie in den 70er/80er? 
Es gibt gute Gründe weshalb sich neue Sprachen und Konzepte entwickelt 
haben, nämlich um die Produktivität, Wiederverwendbarkeit und Sicherheit 
zu steigern. Vor allem die Sicherheit wird in Zukunft immer wichtiger 
werden und bei den Prozessoren die es heute gibt, kann man auf ein paar 
Nanosekunden verzichten und eine Sprache einsetzen die automatische 
Rangechecks etc. vornehmen. Gerade C hat ein paar Eigenschaften die 
Exploits begünstigen, dass sieht man immer wieder in Bugfixes im Linux 
Kernel.

Und dann gibt es da noch etwas, dass erst vor ein paar Jahren ein Thema 
(auf Heimrechnern) geworden ist: Parallität. Die Prozessoren haben immer 
mehr Kerne und Gesamtleistung. Das Problem ist nur, dass von der 
Gesamtleistung teils nur wenig übrig bleibt, dank Raceconditions und 
Co.. Es werden dann Sprachen entwickelt die das verbessern sollen, wie 
z.B. Go und Rust. C willst du da nicht verwenden und C++ muss/musste 
dafür noch nachrüsten.

DingsDa schrieb:
> Habe in meinem Umfeld noch kein OS gesehen, das mit einer anderen
> Sprache als C/Assembler geschrieben war/ist.
> Wenn hierzu jemand eine Info hätte, würde mich das sehr interessieren.

Das ist natürlich klar. Die etablierten und für den produktiven Gebrauch 
entwickelten Betriebsysteme (Linux/Windows/MacOS...) sind das Resultat 
mehrerer Jahre/Jahrzehnte, da stecken mehrere millionen Codezeilen drin. 
Sowas schreibt man nicht einfach so mal neu. Damals gabs nur C und 
Assembler.

von Hello World ;) (Gast)


Lesenswert?

TriHexagon (Gast) schrieb:

Hello World ;) schrieb:
>> Außerdem wäre für Windows die Frage, wie leicht lassen sich solche
>> Sprachen zu GUI Programmem übersetzen. Daran hapert's dann oft, weil
>> sich solche Exoten in erster Linie für sich selbst interessieren.

> Erstens ist Rust kein Exot, es vereint etablierte moderne Konzepte und
> macht dir keine Vorschriften welches Paradigma du zu nutzen hast. Exoten
> sind Sprachen wie Haskell und Lisp.

Käse. Natürlich ist Rust ein Exot. Alle neuen Programmierdialekte die 
sich noch nicht durchgesetzt haben führen ihr Dasein als Exot unter den 
Eteblierten. Lisp ist alles andere als ein Exot. Lisp hat seine 
Tauglichkeit längst bei AutoCAD unter Beweis gestellt. Haskell ist für 
mich dagegen ebenso eine recht exotische Programmiersprache. Was wurde 
damit bisher groß entwickelt? Im Gegensatz zu Rust ist Haskell aber 
zumindest schon länger in der Entwicklung.

ICh hab außerdem gar nichts gegen neue Dialekte. Die Frage die sich mir 
stellt ist eher, wer braucht die eignetlich? Wo ist der Mehrwert? 
Außerdem gilt generell für alles was entwickelt wird, neue 
Programmiersprache, neue Probleme. Und den zeitlichen Aufwand den man 
dort investiert muss man an anderer Stelle einsparen wie immer im Leben.

von TriHexagon (Gast)


Lesenswert?

Hello World ;) schrieb:
> Käse. Natürlich ist Rust ein Exot. Alle neuen Programmierdialekte die
> sich noch nicht durchgesetzt haben führen ihr Dasein als Exot unter den
> Eteblierten. Lisp ist alles andere als ein Exot. Lisp hat seine
> Tauglichkeit längst bei AutoCAD unter Beweis gestellt. Haskell ist für
> mich dagegen ebenso eine recht exotische Programmiersprache. Was wurde
> damit bisher groß entwickelt? Im Gegensatz zu Rust ist Haskell aber
> zumindest schon länger in der Entwicklung.

Du schaust nur auf die Verbreitung und die ist bei Rust natürlich noch 
verhalten. Rust ist noch nicht fertig, es können immer noch große und 
starke Designänderungen kommen. Vielen Gefällt der Gedanke, dass jede 
Zeile Code mit der Zeit unbrauchbar werden kann, da sich noch viel 
ändern kann, einfach nicht. In Sachen Design ist Rust relativ 
konservativ und streut noch Puderzucker drauf.

Hello World ;) schrieb:
> ICh hab außerdem gar nichts gegen neue Dialekte. Die Frage die sich mir
> stellt ist eher, wer braucht die eignetlich? Wo ist der Mehrwert?
> Außerdem gilt generell für alles was entwickelt wird, neue
> Programmiersprache, neue Probleme. Und den zeitlichen Aufwand den man
> dort investiert muss man an anderer Stelle einsparen wie immer im Leben.

Da geb ich dir Recht, aber die alten Programmiersprachen wie C und C++ 
zu der es noch keine richtige Alternativen gibt, sind alles andere als 
Perfekt. C ist voller Designfehler und ohne Erfahrung gefährlich. C++ 
hat davon noch so einiges geerbt (dank C Subset) und ist mit der Zeit zu 
einem unüberschaubaren und komplexen Ungeheuer mutiert. Die 
fundamentalen Probleme der beiden Sprachen werden nicht mehr 
ausgebügelt, da sonst Unmengen von Code ungültig werden würde und sich 
das Standardkomitee nicht traut einen harten Schnitt zu machen. Also 
gibt es nur eine Lösung: eine neue bessere Sprache muss her, die von der 
Erfahrung der letzten Jahrzehnte profitiert. Das ist jedenfalls meine 
Meinung bei den Systemsprachen, wo sich nichts mehr getan hat bis vor 
kurzem. Vielleicht kann Rust/Go/Nimrod endlich mal eine moderne 
Alternative bieten.

von Stefan Salewski (Gast)


Lesenswert?

Yalu X. schrieb:
> gestern schlechtes Wetter war und von Rust kürzlich ein neues Release
> herauskam, habe ich die beiden Compiler installiert, die Tutorials
> durchgearbeitet und angefangen, damit herumzuspielen.

Hallo Yalu!

Du bist ja echt fix! Ich hatte Nimrod vor ca. 3 Monaten entdeckt, als 
ich nach Neuigkeiten zu Rust gesucht hatte. Seit dem habe ich mich im 
Wesentlichen auf Nimrod konzentriert -- Rust beobachte ich aber weiter, 
habe es aber bisher nicht installiert. Momentan benutze ich vorwiegend 
Ruby -- ich hatte damit vor einigen Jahren angefangen. Ist auch eine 
schöne, elegante Sprache, gefällt mir ein wenig besser als Python. Aber 
manchmal hätte man eben gerne Geschwindigkeit vergleichbar zu C, und 
wenn Projekte etwas größer werden, erscheint mir statische Typisierung 
zusammen mit all den Überprüfungen, die ein Kompiler machen kann, doch 
vorteilhaft.

Von den modernen schnellen, universellen Sprachen, die auch für 
Systemprogrammierung nutzbar sind, erscheinen mir derzeit Nimrod und 
Rust am interessantesten, jedenfalls in der freien Welt. Kürzlich kam ja 
Swift heraus, als überfälliger Nachfolger von Objective-C. Interessiert 
mich nicht wirklich. Für Matlab ähnliche Anwendungen ist natürlich Julia 
sehr interessant. Und Go und nun Dart sollte man auch nicht vergessen, 
Go soll ja recht einfach sein, und wäre damit vielleicht gerade für 
Hobbyprogrammierer interessant. Und Dart eben als Java-Script 
Alternative. Haskell ist natürlich vom Konzept sehr interessant, bei 
einigen Benchmarks aber doch recht langsam. Python und  Ruby -- ich 
denke dass deren große Zeit etwas zu Ende geht, auch wenn mit PyPy und 
Cython für Python das Geschwindigkeitsproblem nicht mehr so groß ist. 
Aber heute würde ich statt der beiden wohl eher Go oder Julia lernen -- 
nun gibt es für die letztgenannten auch gute GTK wrapper, was mir 
wichtig ist.

Aber nun zurück zu Rust und Nimrod:
Ein wesentlicher Aspekt ist, dass Rust von einem größeren Team 
entwickelt wird, einige davon wohl bezahlte Ganztagsprogrammierer. Bei 
Nimrod ist es wohl ein Hauptentwickler mit einigen Unterstützern -- wohl 
eher unbezahlt, aber sehr helle Köpfe. Und bei Nimrod steckt wohl eher 
ein Plan hinter der Entwicklung, bei Rust geht es noch etwas chaotisch 
zu. Etwa zu der Speicherverwaltung bei Rust -- Garbage-Collector mag man 
nicht so recht, daher gibt es diese "sicheren" (owned) Pointer -- habe 
ich noch nicht so richtig verstanden, ich hatte dazu auch manchmal 
widersprüchliches gelesen. Nimrod hat einen Garbage-Collector, der 
weitgehend echtzeitfähig sein soll, und zusätzlich einfache Pointer die 
manuell verwaltet werden. Beeindruckt hat mich an Nimrod die Eleganz und 
Kompaktheit -- der Compiler hat wohl nur einige 10k Zeilen Code und 
übersetzt sich selbst in wenigen Sekunden. Grundsätzlich ist Nimrod wohl 
wirklich als universelle Sprache konzipiert, Systemprogrammierung (ein 
minimaler bootfähiger Kernel existiert!), Scripting bis zu großen 
Anwendungen. Rust ist wohl auch universell, aber Hauptziel war wohl ein 
multitaskingfähiger Browser und Betriebssystemprogrammierung. Als ein 
Beispiel hatte ich mir mal deren GTK2-Editor Aporia angesehen, ein gedit 
Equivalent, in wenigen Sekunden installiert, läuft gut, und der 
Quellcode sieht recht gut aus, ähnlich wie bei Python oder Ruby. 
Übrigens was mich sehr an Rust stört, sind die von C übernommenen 
geschweiften Klammern. Irgendwie habe ich da den Eindruck, dass man 
unbedingt ein vertrautes Erscheinungsbild haben wollte, damit sich C und 
Java Programmierer gleich zuhause fühlen. Und sonst: Nimrod generiert ja 
gewöhnlich C Zwischencode, so dass man Nimrod grundsätzlich auch für 
8-Bit Mikroprozessoren einsetzen könnte -- jedenfall wurde irgendwo auch 
ein AVR erwähnt, Das Problem sind wohl eher die angepassten 
Bibliotheken, war früher für GCC ja auch das Problem. (Ich persöhnlich 
denke allerdings, dass C für 8-bit gut genug ist.). Bindings zu 
C-Bibliotheken lassen sich für Nimrod übrigens recht einfach mit einen 
Tool und ein wenig Handarbeit erstellen -- ich hatte kürzlich einfache 
GTK3 Bindings aus den C-Headern erzeugt. Ja das wäre es dann erstmal -- 
ich werde mir die übrigen Beiträge dann auch noch mal ansehen...

Gruß

Stefan

von Fritz (Gast)


Lesenswert?

DingsDa schrieb:
> Ein Frage die mich beschäftigt ist die, warum soll ich eine neue Sprache
> lernen (hätte kein Problem damit), wenn das OS auf dem ich diese Sprache
> einsetze in purem C und ein bisschen Assembler geschrieben ist?

Rust kann man sehr gut und einfach mit C zusammen einsetzen.

Warum man nicht einfach rasch das OS auch in Rustz schreibt? Mach mal. 
Und berichte nächste Woche von deinen Erfahrungen. g

von Fritz (Gast)


Lesenswert?

Stefan Salewski schrieb:
> bei Rust geht es noch etwas chaotisch
> zu. Etwa zu der Speicherverwaltung bei Rust -- Garbage-Collector mag man
> nicht so recht,

Rust hat sehr wohl einen Garbage Collector, sowohl einen echten, als 
auch Reference Counting.

Die Unterstützung ist nur vor geraumer Zeit aus dem Sprachkern entfernt 
worden und in die Standardbibliothek gewandert.

Und das ist ein sehr gutes Zeichen für stimmiges Sprachdesign: 
offensichtlich kann man bei Rust derart grundlegende Funktionalität und 
Semantik in Bibliotheken auslagern.

Alte Lisper kennen das natürlcih schon, aber für etwas mainstreamigere 
Sprachen ist das schon etwas ganz besonderes.

von Dr. Sommer (Gast)


Lesenswert?

Fritz schrieb:
> Alte Lisper kennen das natürlcih schon, aber für etwas mainstreamigere
> Sprachen ist das schon etwas ganz besonderes.
In C++ wird das seit Jahr und Tag ebenfalls als Library gemacht, dank 
Templates ("smart pointer"). Seit 3 Jahren ist der refcounting-basierte 
auch im Standard:
http://de.cppreference.com/w/cpp/memory/shared_ptr

von TriHexagon (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Ein wesentlicher Aspekt ist, dass Rust von einem größeren Team
> entwickelt wird, einige davon wohl bezahlte Ganztagsprogrammierer. Bei
> Nimrod ist es wohl ein Hauptentwickler mit einigen Unterstützern -- wohl
> eher unbezahlt, aber sehr helle Köpfe. Und bei Nimrod steckt wohl eher
> ein Plan hinter der Entwicklung, bei Rust geht es noch etwas chaotisch
> zu.

Ja am Anfang war es etwas chaotisch, das hat sich aber gebessert. Die 
Entwickler wissen was sie wollen, waren sich am Anfang aber unsicher wie 
die Inhalte im Detail aussehen sollen. Das sieht man gut an den GC und 
RefCount Zeiger die zuerst in der Syntax etabliert waren und dann in die 
Standardbibliothek gewandert sind (richtige Entscheidung!). Mir gefällt 
vor allem die communitynahe Entwicklung. Jeder kann sich auf Github 
beteiligen und Vorschläge machen. Die Entwicklungszeit ist zwar länger, 
aber die Qualität der Sprache ist (theoretisch) besser, wenn es externe 
Leute gibt, die einen Blick auf das Sprachdesign werfen.

Stefan Salewski schrieb:
> Nimrod generiert ja
> gewöhnlich C Zwischencode, so dass man Nimrod grundsätzlich auch für
> 8-Bit Mikroprozessoren einsetzen könnte -- jedenfall wurde irgendwo auch
> ein AVR erwähnt, Das Problem sind wohl eher die angepassten
> Bibliotheken, war früher für GCC ja auch das Problem. (Ich persöhnlich
> denke allerdings, dass C für 8-bit gut genug ist.).

Nur weil Nimrod C Code erzeugt bedeutet das nicht, dass Nimrod auf einem 
8-Bit µC sinnvoll oder möglich ist. C wird auf einem µC benutzt weil C 
nichts verschleiert und extrem performant ist. In einem Lowlevel Feld wo 
sich selbst C++ nicht durchsetzen kann, wird es für Nimrod noch 
schwieriger haben. Und dann noch der aufgezwungene GC. Für 8-Bit µC ein 
absolutes NoGo.

Zum Glück ist der GC Hype am Abflachen und jeder müsste nun wissen, dass 
ein GC keine Allheilslösung ist, also warum einen GC erzwingen? Schon 
deshalb ist Rust für mich der absolute Favorit über Nimrod und Go. Wobei 
Go natürlich eher für Serveranwendungen konzipiert ist.

von TriHexagon (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Übrigens was mich sehr an Rust stört, sind die von C übernommenen
> geschweiften Klammern. Irgendwie habe ich da den Eindruck, dass man
> unbedingt ein vertrautes Erscheinungsbild haben wollte, damit sich C und
> Java Programmierer gleich zuhause fühlen.

Das kommt wohl daher, dass die Rust Entwickler (Mozilla) sonst 
hauptsächlich mit C++ arbeiten. Aber ehrlich gesagt gefallen mir die 
Klammern lieber als irgendwelche Schlüsselwörter wie "end". Zugegeben 
auf der deutschen Tastatur nicht optimal, aber das macht den Code 
luftiger, die Klammern fallen beim Lesen kaum auf damit bleibt der Fokus 
auf den wichtigen Teilen des Quellcodes. Basic finde ich deshalb so 
häßlich, der Code besteht dann immer aus riesigen zusammenhängenden 
Blöcken.

von Stefan Salewski (Gast)


Lesenswert?

TriHexagon schrieb:
> Nur weil Nimrod C Code erzeugt bedeutet das nicht, dass Nimrod auf einem
> 8-Bit µC sinnvoll oder möglich ist. C wird auf einem µC benutzt weil C
> nichts verschleiert und extrem performant ist. In einem Lowlevel Feld wo
> sich selbst C++ nicht durchsetzen kann, wird es für Nimrod noch
> schwieriger haben. Und dann noch der aufgezwungene GC. Für 8-Bit µC ein
> absolutes NoGo.
>
> Zum Glück ist der GC Hype am Abflachen und jeder müsste nun wissen, dass
> ein GC keine Allheilslösung ist, also warum einen GC erzwingen?

Ich bin mir eigentlich ziemlich sicher, dass Nimrod keinesfalls einen 
Garbage-Collector "erzwingt". Das wäre in der Tat schlecht. Der Nimrod 
GC arbeitet mit Pointern die mit dem Schlüselwort ref gekennzeichgnet 
sind, Pointer gekennzeichnet mit ptr werden manuell verwaltet. Wenn also 
das Schlüsselwort ref nirgends auftaucht, bekommt man ein Programm ohne 
GC. Klar darf man dann keine Bibliotheken verwenden, die den GC 
benötigen. Nimrod hat den GC zwar in der Sprache integriert, aber bieted 
durchaus verschiedene GC Varianten. Ob es jetzt besser ist, den GC nicht 
in die Sprache zu integrieren, sondern nur als Bibliothek anzubieten? 
Glaube ich eher nicht. Bei Rust war der GC ja anfangs sehr unbeliebt, da 
er für systemnahe Programmierung eh nicht verwendet wird, und 
insbesondere da Garbage-Collection den Rechner für einige Zeit zum 
Stehen bringen kann. Das ist für viele Anwendungen ein großen Problem, 
etwa für Systemprogrammierung oder auch Spiele. Bei Nimrods GC sollen 
diese erzwungenen Pausen aber sehr klein sein, ms oder so.

Und zu den geschweiften Klammern: Dass man } lieber mag als das 
Schlüsselwort end kann ich verstehen, in Ruby verwende ich auch oft das 
Paar {} statt etwa do end. Aber für jeden Block nach if, else, while 
usw. ein {} Paar wie in C und Java üblich? Da gefällt mir etwa Ruby's 
Syntax doch besser. Mit den erzwungenen Einrückungen vom Python hatte 
ich anfangs auch meine Probleme, da ich manchmal einfach drauf lostippe 
ohne mich um Formatierung zu kümmern. Aber damit kommen die Leute wohl 
doch gut zurecht, sonst wäre Python ja nicht so populär geworden. Und 
die Strukturierung durch Einrückungen in Python, Haskell und Nimrod 
ergibt eben kompakten, gut lesbaren Code und wird daher in Lehrbüchern 
und Pseudo-Code ja auch oft verwendet.

von Arc N. (arc)


Lesenswert?

TriHexagon schrieb:
> Nur weil Nimrod C Code erzeugt bedeutet das nicht, dass Nimrod auf einem
> 8-Bit µC sinnvoll oder möglich ist. C wird auf einem µC benutzt weil C
> nichts verschleiert und extrem performant ist. In einem Lowlevel Feld wo
> sich selbst C++ nicht durchsetzen kann, wird es für Nimrod noch
> schwieriger haben. Und dann noch der aufgezwungene GC. Für 8-Bit µC ein
> absolutes NoGo.

Von aufgezwungen lese ich auf der Nimrod-Seite nichts...
"System programming features: Ability to manage your own memory and 
access the hardware directly. Pointers to garbage collected memory are 
distinguished from pointers to manually managed memory."
Kenne die Sprache aber zu wenig, um da genaueres sagen zu können.

DingsDa schrieb:
> Habe in meinem Umfeld noch kein OS gesehen, das mit einer anderen
> Sprache als C/Assembler geschrieben war/ist.
> Wenn hierzu jemand eine Info hätte, würde mich das sehr interessieren.

Es gibt einige Betriebssysteme die nicht C als Hauptsprache verwenden 
u.a.:
Oberon: Bluebottle, AOS, Native Oberon
Java: JX
Lisp: Interlisp, Symbolics Genera
BitC: Coyotos (sollte das erste formal verifizierte OS werden, was aber 
seL4 wurde)
Sing# (C#-Ableger): Singularity
C#, TAL, Boogie/Z3: Verve
Zu den beiden letztgenannten: http://singularity.codeplex.com/
http://research.microsoft.com/apps/pubs/?id=122884
http://research.microsoft.com/en-us/projects/singularity/

Yalu X. schrieb:
> Wesentlich besser würde mir Rust aber gefallen, wenn es wie in Nimrod
> einen interaktiven Interpreter, benutzerdefinierte Operatoren und
> Generatoren gäbe.

REPL (rusti) wird es (wieder) geben, zwischenzeitlich kann man 
https://github.com/tarcieri/irust ausprobieren.

von Stefan Salewski (Gast)


Lesenswert?

TriHexagon schrieb:
> Nur weil Nimrod C Code erzeugt bedeutet das nicht, dass Nimrod auf einem
> 8-Bit µC sinnvoll oder möglich ist.

Ich habe gerade Google noch mal nachlesen lassen...

http://nimrod-lang.org/nimrodc.html#nimrod-for-embedded-systems

Da wird vom 16 bit uC ohne OS geschrieben und AVR erwähnt -- wobei GCC 
die AVR's ja als 16 bittig betrachtet, weil eben der Adressbereich 
größer als 8 Bit sein kann. Gut, ich selbst würde für die AVR's C 
nehmen, ich kann mir nicht vorstellen, dass man da mit Rust oder Nimrod 
viel gewinnt. Eher schon für einen kleinen ARM...

von Yalu X. (yalu) (Moderator)


Lesenswert?

Es freut mich, dass da schon eine rege Diskussion im Gange ist, wie ich
sie fast nicht erwartet hätte :)

VielenDank schon jetzt an alle Teilnehmer.

Ich fange hier mal an, ein paar Dinge zu kommentieren:

Fritz schrieb:
> Rust ist auch deshalb cool, weil die Entwickler schwer darauf acht
> geben, daß es (für kleine eingebettete Systeme) auch ohne
> Standardbibliothek sinnvoll nutzbar ist.

So wirklich klein sind die Executables aber auch nicht: Ein leeres main
ist bei mir schon 812024 Bytes lang (gestrippt). Dazu kommen noch
folgend Shared Objects, die allerdings auf einem normale Linux-System
sowieso ständig geladen sind und damit nicht ins Gewicht fallen:
1
  linux-vdso.so.1
2
  libdl.so.2
3
  libpthread.so.0
4
  libgcc_s.so.1
5
  libc.so.6
6
  ld-linux-x86-64.so.2
7
  libm.so.6


Stefan Salewski schrieb:
> Garbage-Collector mag man nicht so recht, daher gibt es diese
> "sicheren" (owned) Pointer -- habe ich noch nicht so richtig
> verstanden, ich hatte dazu auch manchmal widersprüchliches gelesen.

Owned Objects sind Objekte, die manuell alloziert (mit dem box-Operator)
und automatisch, wenn ihr Scope verallsen wird, wieder freigegeben
werden. Bis dahin hat das Ähnlichkeit mit RAII. Zusätzlich können aber
solche Objekte in einen anderen Scope gemovet werden. Das geschieht
durch eine Zuweisung, Argumentübergabe oder Funktionswertrückgabe.
Wichtig dabei ist, dass immer nur ein einziger Pointer auf das Objekt
zeigt, weil man dann ohne Reference-Counting o.ä. auskommt. Wird also
ein Pointer einer anderen Variablen zugewiesn, wird dir ursprünglich
Pointervariable ungültig, und jeder weitere Zugriff darauf ist ein
Fehler, der bereits beim Kompilieren aufgedeckt wird.

Ein typisches Anwendungsfeld für solche Pointer sind Funktionen, die
dynamisch erzeugte Daten an den Aufrufer zurückgeben. In solchen Fällen
ist der Aufrufer für die Freigabe des belegten Speichers verantwortlich.
In Rust geschieht das automatisch. Beispiel:
1
fn erzeuge_daten() -> Box<int> {
2
  let p = box 123;
3
  p
4
}
5
6
fn aufrufer() {
7
  let p = erzeuge_daten();
8
  println!("{}", *p);
9
}

Hier wird der in erzeuge_daten reservierte Speicher am Ende von
aufrufer automatisch zurückgegeben. Der Rechenaufwand ist der eines
malloc/free-Kombination und damit geringer als bei Smart-Pointern, die
man in C++ für solche Dinge benutzen würde.

Stefan Salewski schrieb:
> Nimrod hat einen Garbage-Collector, der weitgehend echtzeitfähig sein
> soll, und zusätzlich einfache Pointer die manuell verwaltet werden.

Es gibt in Nimrod auch allocate() und deallocate() für die manuelle
Speicherverwaltung. Die wird man aber nicht gerne nutzen, weil man damit
die in C gefürchteten Speicherlecks heraufbeschwört. Wenn man also
dynamisch Objekte anlegen will, gibt es nur unsicher oder GC, aber
nichts dazwischen. In Rust gibt es eben zusätzlich noch die
Owned-Objekte und Reference-Counting als effizienetere Alternativen.
Wobei die GCs mittlerweile so gut sind, dass sie ein Programm im Mittel
kaum verlangsamen. Schlimm ist nur, wenn der GC zu einem ungünstigen
Zeitpunkt zuschlägt und dann gleich den kompletten Speicher auf einmal
aufräumt, was entsprechend dauern kann. In Nimrod kann deswegen die GC
lokal beschränkt werden, so dass sie immer nur kleinere Häppchen am
Stück bearbeiten muss.


Fritz schrieb:
> Und das ist ein sehr gutes Zeichen für stimmiges Sprachdesign:
> offensichtlich kann man bei Rust derart grundlegende Funktionalität und
> Semantik in Bibliotheken auslagern.

Dazu gibt es in der mitgelieferten Regex-Bibliothek auch ein schönes
Beispiel:
1
#![feature(phase)]
2
#[phase(plugin)]
3
extern crate regex_macros;
4
extern crate regex;
5
6
fn main() {
7
    let re = regex!(r"^\d{4}-\d{2}-\d{2}$");
8
    assert_eq!(re.is_match("2014-01-01"), true);
9
}

Die Zeile "let re = ..." kompiliert den als String übergebenen regulären
Ausdruck. Das passiert aber nicht wie in anderen Sprachen zur Laufzeit,
sondern zu Compile-Zeit. Entsprechend werden auch Syntaxfehler bereits
beim Kompilieren angezeigt. Lässt man bspw. die letzte geschweifte
Klammer weg, meckert der Compiler:
1
regex.rs:7:14: 7:44 error: Regex syntax error near position 15: No closing brace for counted repetition starting at position 15.
2
regex.rs:7     let re = regex!(r"^\d{4}-\d{2}-\d{2$");
3
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
error: aborting due to previous error

Nicht nur, dass eine Fehlermeldung angezeigt wird, sie ist sogar sofort
verständlich. Man denkt hier, die Regexe seien fester Sprachbestandteil
von Rust. Tatsächlich sind sie aber ein geniales (fast an Lisp
erinnerndes) Beispiel von Metaprogrammierung, die man auch selber nutzen
kann. In C++ ist etwas Ähnliches nur möglich, wenn man die Regex-Syntax
so abändert, dass sie nicht als String, sondern als Ausdruck mit
Operatoren zwischen den einzelnen Primitiven dargestellt werden kann (s.
Boost:Xpressive), da ein String zur Compile-Zeit nur schwerlich
analysiert werden kann.

Das ist übrigens etwas, wo es mich beim Lesen und anschließendem
Ausprobieren dann doch etwas aus den Socken gehauen hat ;-)

In Nimrod sollten solche Dinge aber ebenfalls problemlos gehen.


Arc Net schrieb:
> REPL (rusti) wird es (wieder) geben, zwischenzeitlich kann man
> https://github.com/tarcieri/irust ausprobieren.

Klasse, werde ich bei nächster Gelegenheit ausprobieren :)

von Stefan Salewski (Gast)


Lesenswert?

Yalu X. schrieb:
> So wirklich klein sind die Executables aber auch nicht: Ein leeres main
> ist bei mir schon 812024 Bytes lang (gestrippt).

Wenn dem so ist, wird sich das hoffentlich noch stark verbessern -- 
womöglich ist aber viel Debugging-Code enthalten?

Ich hatte zuletzt den Convex-Hull Algorithmus von Wikibooks mit Nimrod 
probiert, executable size mit Linux AMD64 sind 75946 Bytes. Kompiliert 
mit "nimrod c -d:release convex_hull.nim" (mit gcc version 4.8.3 und gcc 
Option O3). Soweit ich mich errinnere schaltet -d:release Debugging und 
Dinge wie Stack-Check ab -- es gibt aber noch eine Option für noch 
kleinere Executables, die finde ich aber gerade nicht. Ist wohl dann gcc 
mit -Os.

stefan@AMD64X2 ~ $ ldd convex_hull
  linux-vdso.so.1 (0x00007fff3c3ff000)
  libdl.so.2 => /lib64/libdl.so.2 (0x00007f25acb2b000)
  libc.so.6 => /lib64/libc.so.6 (0x00007f25ac784000)
  /lib64/ld-linux-x86-64.so.2 (0x00007f25acd2f000)

Der Code ist hier -- für Rust leider noch nicht.

http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain

http://forum.nimrod-lang.org/t/483

Demnächst werde ich es mal mit zwei Threads probieren, jeweils für die 
untere und obere Hülle.

von Yalu X. (yalu) (Moderator)


Angehängte Dateien:

Lesenswert?

Stefan Salewski schrieb:
> Ich habe gerade Google noch mal nachlesen lassen...
>
> http://nimrod-lang.org/nimrodc.html#nimrod-for-embedded-systems
>
> Da wird vom 16 bit uC ohne OS geschrieben und AVR erwähnt

Ich habe das mal anhand eines ganz einfachen Beispiels versucht:
1
# avrtest.nim
2
proc arithReihe(n: int8): int8 =
3
  for i in countup(1, n):
4
    result += i
5
6
var a = arithReihe(10)

Erst einmal gab es vom Nimrod-Compiler Gemecker, weil in einem
mitgelieferten System-File (system.nim) irgendwelche Array-Typen
deklariert werden, deren Elementzahl gößer als 65535 ist. Hab's
hingefrickelt, indem ich die Werte durch kleinere ersetzt habe und dann
mit folgendem Kommando das Programm kompiliert:
1
nimrod c --cpu:avr --os:standalone --deadCodeElim:on --genScript -x:off --opt:size avrtest.nim

Mit -x:off werden sämtlich Laufzeitüberprüfungen abgeschaltet, was den
erzeugten Code deutlich kompakter macht.

Das Ganze brach vor der Generierung des Binärcodes mit Fehlermeldungen
ab, weil die generierten C-Dateien vom C-Compiler nicht gefunden wurden.
Zudem wurde der falsche Compiler gestartet (gcc statt avr-gcc). Ich
schätze, das man das alles durch weitere Optionen oder irgenwelche
Konfigurationsdateien in den Griff bekommen kann.

Immerhin wurden aber zwei C-Files generiert, die ich dann manuell vom
AVR-GCC 4.7.2 übersetzen ließ.

Hui, und das Ergebnis kann sich sehen lassen:
1
$ avr-size avrtest
2
   text    data     bss     dec     hex filename
3
    126       0      15     141      8d avrtest

Das Disassembly habe ich angehängt.

Damit ist Nimrod entgegen meiner ursprünglichen Vermutung sogar ein
Kandidat für die AVR-Programmierung. Allerdings müsste sich noch jemand
hinsetzen und Makros für die Zugriffe auf die I/O-Register schreiben.
Oder gibt es so etwas vielleicht sogar schon?

Stefan Salewski schrieb:
> Gut, ich selbst würde für die AVR's C nehmen, ich kann mir nicht
> vorstellen, dass man da mit Rust oder Nimrod viel gewinnt.

Ja, so sehe ich das auch. Die Programme, die man typischerweise für
einen AVR schreibt, sind so klein, dass man sich um höherlevelige
Programmierung nicht viele Gedanken machen muss. Trotzdem finde ich es
toll, mit wie wenig Ressourcen Nimrod auskommt. Damit wird es auf jeden
Fall interessant für komplexere Mikrocontrollerprogramme, die dann bspw.
auf kleinen bis mittelgroßen ARMs laufen.

: Bearbeitet durch Moderator
von Stefan Salewski (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Wenn dem so ist, wird sich das hoffentlich noch stark verbessern --
> womöglich ist aber viel Debugging-Code enthalten?

Man kann mit Rust wohl doch recht kleine Executables bekommen, mit `-C 
prefer-dynamic`.

Siehe

http://comments.gmane.org/gmane.comp.lang.rust.devel/8692

von Dr. Sommer (Gast)


Lesenswert?

Yalu X. schrieb:
> Der Rechenaufwand ist der eines
> malloc/free-Kombination und damit geringer als bei Smart-Pointern, die
> man in C++ für solche Dinge benutzen würde
Nicht seit C++11, unique_ptr und move semantics. Bei Verwendung davon 
passiert exakt das selbe...

von Stefan Salewski (Gast)


Lesenswert?

Yalu X. schrieb:
> Immerhin wurden aber zwei C-Files generiert, die ich dann manuell vom
> AVR-GCC 4.7.2 übersetzen ließ.
>
> Hui, und das Ergebnis kann sich sehen lassen:
> $ avr-size avrtest
>    text    data     bss     dec     hex filename
>     126       0      15     141      8d avrtest
>
> Das Disassembly habe ich angehängt.
>
> Damit ist Nimrod entgegen meiner ursprünglichen Vermutung sogar ein
> Kandidat für die AVR-Programmierung.

Das ist wirklich interessant!
Schön dass Du Dir die Mühe gemacht hast das mal auszuprobieren.

> Allerdings müsste sich noch jemand
> hinsetzen und Makros für die Zugriffe auf die I/O-Register schreiben.
> Oder gibt es so etwas vielleicht sogar schon?

Denke ich nicht. Aber vielleicht wäre das gar nicht so extrem aufwändig, 
zu Nimrod gibt es das Tool c2nim das C-Header und zum Teil auch C-Code 
nach Nimrod wandeln kann. Na ja, das wäre dann eine Alternative für die 
Leute, die eine starke Abneigung gegen C haben und für die AVR's BASIC 
oder ähnliches benutzen...

Nicht dass ich das jetzt für wirklich sinnvoll halte, ich würde für AVR 
bei C bleiben, wahrscheinlich würde ich heute gar nicht mehr mit AVR 
anfangen sondern gleich mit ARM beginnen. Aber dass es mit Nimrod 
grundsätzlich möglich wäre gefällt mir schon.

von TriHexagon (Gast)


Lesenswert?

Mhm das weckt nun doch mein Interesse, werde ich mal ausprobieren. Wäre 
mal interessant wie sich das anfühlt. Ich hab mir vor ein paar Monaten 
einen kleinen Überblick über Nimrod beschaft. Solange ich den Heap nicht 
benutze, wird der GC also nicht einmal angerührt?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dr. Sommer schrieb:
> Yalu X. schrieb:
>> Der Rechenaufwand ist der eines
>> malloc/free-Kombination und damit geringer als bei Smart-Pointern, die
>> man in C++ für solche Dinge benutzen würde
> Nicht seit C++11, unique_ptr und move semantics. Bei Verwendung davon
> passiert exakt das selbe...

Ja, stimmt, die unique_ptr gibt es ja auch noch. Die haben tatsächlich
die gleiche Funktion wie die Owned Boxes in Rust, unterscheiden sich von
diesen aber in zwei Punkten, von denen der erste von entscheidender
Bedeutung ist:

1. Die Dereferenzierung eines leeren unique_ptr in C++ führt zu
   undefiniertem Verhalten (üblicherweise ein Segfault), während der
   entsprechende Fehler in Rust bereits beim Kompilieren erkannt wird.
   Damit sind die Owned Boxes im Gegensatz zu den unique_ptr absolut
   idiotensicher.

2. Die unique_ptr sind geringfügig ineffizienter, weil beim Move der
   alte Pointer explizit auf null gesetzt werden muss und beim Verlassen
   des Scopes der Pointer auf null geprüft werden muss, um zu
   entscheiden, ob ein Objekt gelöscht muss kann oder nicht. Da in Rust
   diese Entscheidung bereits zur Compile-Zeit erfolgt, ist die
   Verwendung von Owned Boxes genauso effizient wie die manuelle
   Speicherverwaltung mit new und delete.

von MCUA (Gast)


Lesenswert?

>Und
>die Strukturierung durch Einrückungen in Python, Haskell und Nimrod
>ergibt eben kompakten, gut lesbaren Code
Ab ein paar Ebenen sieht man überhaupt nichts mehr!
Ausserdem, eine Stufe zuweit eingerückt (was schnell passieren kann), 
und alles ist Mist.
Bei mit end.. oder } (oder ähnlichem) lässt sich eindeutig 
nachvollziehen, wo's hingehört. Alles andere ist für grössere Progr. 
völlig unbrauchbar!

von Dussel (Gast)


Lesenswert?

Das Blocken durch Einrücken halte ich auch für keine gute Idee. Bei 
Python als Anfängersprache ist das vielleicht sinnvoll, aber wenn es 
größere Programme werden, kann man das nicht mehr gebrauchen. Nicht 
umsonst gibt es in guten IDE die Möglichkeit zur automatischen 
Einrückung. Man benötigt eine neue Ebene oder hat eine Ebene zu viel und 
schon darf man ewig viel Code neu einrücken.

Stützräder sind für Fahranfänger sicher eine gute Idee, aber trotzdem 
habe ich noch keinen Rennradfahrer mit Stützrädern gesehen…

von Michael (Gast)


Lesenswert?

Dussel schrieb:
> Python als Anfängersprache

Und mal wieder wenig Ahnung, aber viel Meinung.

von Micha L. (milu)


Lesenswert?

Yalu X. schrieb:
> Außerdem habe ich eine wachsende Abneigung gegen
> geschweifte Klammern, die nicht nur hässlich aussehen, sondern auch auf
> deutschen Tastaturen schwer zu tippen sind.

Wenn du mit Windows arbeitest: Mit MSKLC (Microsoft Keyboard Layout 
Creator) kannst du supereinfach dein Tastaturlayout anpassen. Da fällt 
ein kleiner Installer für x86/amd64/ia64 raus, den du auf deinen 
Rechnern installierst und dann als Standardtastatur setzt.

Ich hab mir die wichtigsten Zeichen auf AltGr = rechter Daumen plus 
linke Hand gelegt, also:

 qwert = @\/^`
 asdf  = {[]}

Seitdem mach ich sehr gerne ein paar Schweife oder Array Indexe. Für 
Linux gibt es sowas bestimmt auch. Auf dem Mac, gut, da gibt es ein 
Problem, weil der leider kein AltGr hat.

von Salewski (Gast)


Lesenswert?

MCUA schrieb:
> Ab ein paar Ebenen sieht man überhaupt nichts mehr!

Das ist doch stets das Problem, sofern man nicht einen Editor verwendet, 
der die Ebenen irgendwie besonders kenntlich macht. Was nützt einem ein 
{}-Paar, wenn nur eine der Klammern sichtbar ist? Man braucht also 
Editor-Support, im einfasten Fall das Hin- und Herspringen zwischen den 
Klammern.

Und generell gilt es ja eher als schlechter Stil, wenn man extrem lange 
Funktionen mit unzähligen Einrückungsebenen hat.

Bei Ruby hat man ja das Schlüsselwort end -- der Stil gefällt mir 
eigentlich am besten, nur verbraucht man durch jedes end eine Zeile.

Bei Python, Haskell, Nimrod ist wohl das größte (und einzige) Problem 
das Umkopieren von Programmtext, aber auch dafür ist Editorunterstützung 
möglich.

Und natürlich ist es recht einfach möglich, alternativ zu der 
Einrückungssyntax etwa geschweifte Klammern anzubieten -- {} ist für den 
Parser ja trivial.

von MCUA (Gast)


Lesenswert?

>Das ist doch stets das Problem, sofern man nicht einen Editor verwendet,
>der die Ebenen irgendwie besonders kenntlich macht.
Problem nur, wenn eine Ebene (auch wenns nur 2 sind) mit space endet. 
Man sieht nichts! Diese Syntax ist beschi??en. Es macht einfach keinen 
Sinn, Blöcke/Ebenen bloss mit Einrücktiefe zu kennzeichen, ohne dass man 
es dem Text selbst ansieht. (Und wehe, es wurde versehentlich mal falsch 
eingerückt (was schnell passieren kann). Da sucht man ewig. Wogegen im 
anderen Fall dadurch überhaupt kein Fehler entstehen kann, und man es 
ggfs sogar autom einrücken lassen kann).

von Salewski (Gast)


Lesenswert?

Soweit ich weiß gab es für Python mal die Option, nach einer 
Einrückungsebene ein endif einzufügen, also ähnlich wie bei Ruby. Wollte 
wohl aber keiner verwenden. Und natürlich kann man einfach 
End-Kommentare verwenden, etwa "# end". Oder "# {" und "# }"

Aber das Thema hat sich durch die Popularität vom Python wohl eh 
erledigt, die meisten Leute kommen mit den Einrückungen scheinbar gut 
klar. Ich selbst muss mich noch etwas daran gewöhnen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Micha Lu schrieb:
> Ich hab mir die wichtigsten Zeichen auf AltGr = rechter Daumen plus
> linke Hand gelegt, also:
>
>  qwert = @\/^`
>  asdf  = {[]}

So etwas ist sicher ganz praktisch. Ich habe dabei nur die Befürchtung,
dass, wenn ich auf einem fremden Rechner arbeite, ständig irgendwelche
fremdartigen Zeichen auf dem Bildschirm erscheinen ;-)

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

DingsDa schrieb:
> Habe in meinem Umfeld noch kein OS gesehen, das mit einer anderen
> Sprache als C/Assembler geschrieben war/ist.
> Wenn hierzu jemand eine Info hätte, würde mich das sehr interessieren.

AmigaOS ist teilweise in C und teilweise in BCPL geschrieben worden. 
Diese Mischung ist auch für Anwendungsentwickler relevant, da man bei 
jedem API schauen muss, in welcher Sprache es entwickelt wurde. Will man 
also eine in BCPL implementierte Funktion aufrufen, sollte man tunlichst 
keine nullterminierten Strings übergeben, sondern solche mit Längenfeld. 
Zeiger sind um zwei Bit nach rechts verschoben, da BCPL mit 
Langwortadressierung statt Byteadressierung arbeitet.

NeXTSTEP, Apple OS X und iOS sind größtenteils in Objective-C 
entwickelt.

von Dr. Sommer (Gast)


Lesenswert?

Yalu X. schrieb:
>    Damit sind die Owned Boxes im Gegensatz zu den unique_ptr absolut
>    idiotensicher.
Aber unflexibler, denn man kann sie wohl nicht aus Member-Variablen 
herausmoven ohne die Instanz zu zerstören.
> 2. Die unique_ptr sind geringfügig ineffizienter, weil beim Move der
>    alte Pointer explizit auf null gesetzt werden muss...
Dafür kann man in C++ einen moved-from unique_ptr auch wieder zuweisen; 
Allerdings sollten halbwegs schlaue Compiler in den meisten Fällen 
erkennen dass die Extra-Operationen sinnlos sind und weggelassen werden 
können.

von MCUA (Gast)


Lesenswert?

>Aber das Thema hat sich durch die Popularität vom Python...
Popularität? Im uC-Bereich eigentl. unbekannt.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Hello World ;) schrieb:
> Lisp ist alles andere als ein Exot. Lisp hat seine
> Tauglichkeit längst bei AutoCAD unter Beweis gestellt.

Und natürlich bei EMACS!

Früher gab es auch spezielle auf die Ausführung von LISP optimierte 
Mikroprozessoren (Texas Instruments Explorer) bzw. Computer (Symbolics 
36xx), und zwar zu Zeiten des großen KI-Hypes.

Sun verfolgte in der Anfangszeit von Java einen ähnlichen Ansatz mit dem 
picoJava-Mikroprozessor, der direkt Java-Bytecode ausführte. Ich kann 
mich noch dunkel an eine "Embedded Systems" (heute: "Embedded World") 
erinnern, auf der Sun einige verschlossene Glasvitrinen mit picoJavas 
und zugehörige Entwicklungsboards präsentierte. Angeblich sollten die 
Prozessoren kurz vor der Auslieferung gestanden haben, aber dafür gab es 
noch erstaunlich spärliche Informationen...

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

MCUA schrieb:
>>Aber das Thema hat sich durch die Popularität vom Python...
> Popularität? Im uC-Bereich eigentl. unbekannt.

Im uC-Bereich eigentlich extrem verbreitet, jedoch weniger zur 
Ausführung auf dem Microcontroller, sondern für Tools und Testskripte.

von MCUA (Gast)


Lesenswert?

>Sun verfolgte in der Anfangszeit von Java einen ähnlichen Ansatz mit dem
>picoJava-Mikroprozessor, der direkt Java-Bytecode ausführte.
..den keiner haben wollte.
Das pardoxe bei Java ist, dass es keiner dafür benutzt, wofür es urspr. 
gedacht war.

>Im uC-Bereich eigentlich extrem verbreitet, jedoch weniger zur
>Ausführung auf dem Microcontroller,
das widerspricht sich

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

MCUA schrieb:
>>Im uC-Bereich eigentlich extrem verbreitet, jedoch weniger zur
>>Ausführung auf dem Microcontroller,
> das widerspricht sich

Zitiere gefälligst vollständig.

Lötkolben sind im uC-Bereich auch extrem verbreitet, auch wenn sie nur 
sehr kurzzeitig mit einem uC in Kontakt kommen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dr. Sommer schrieb:
> Yalu X. schrieb:
>>    Damit sind die Owned Boxes im Gegensatz zu den unique_ptr absolut
>>    idiotensicher.
> Aber unflexibler, denn man kann sie wohl nicht aus Member-Variablen
> herausmoven ohne die Instanz zu zerstören.

Nur die gemovete Member-Variable wird ungültig, auf den Rest der
Struktur kannst du nach wie vor zugreifen.

>> 2. Die unique_ptr sind geringfügig ineffizienter, weil beim Move der
>>    alte Pointer explizit auf null gesetzt werden muss...
> Dafür kann man in C++ einen moved-from unique_ptr auch wieder zuweisen;

Das geht in Rust auch, sofern die Pointer-Variable mutual ist.

Edit: Es muss natürlich "mutable" und nicht "mutual" heißen (immer diese 
neumodischen Ausdrücke, hätte vielleicht, wenn ich schon keine Ahnung 
habe, einfach "veränderlich" schreiben sollen ;-))

: Bearbeitet durch Moderator
von Hello World ;) (Gast)


Lesenswert?

Yalu X. (yalu) (Moderator) schrieb:

> Das geht in Rust auch, sofern die Pointer-Variable mutual ist.

Apropos "gemovete Member-Variable" und co. Täuscht mich der Eindruck, 
dass auch Rust, go, Nimrod ähnlich wie D vielleicht wunderbare, 
interessante "Kommandozeilendialekte" sind, aber man spätestens in 
Sachen GUI-Anbindung auf eine Mauer trifft?

Zum Vergleich mal ein Blick auf D in Sachen GUI

http://qznc.github.io/d-tut/gui.html

Also für Windows Programme stelle ich mir Werbung dann doch ein wenig 
anders vor, als diese drei kläglichen Verweise. Das reicht nicht mal zum 
anmotivieren.

Jetzt könnte man Rust und Nimrod noch zugute halten, diese Sprachen sind 
ja noch recht neu (wird also vielleicht noch werden). Aber D ist jetzt 
wie viele Jahre auf dem Radar? Laut Bugliste minimum 7 Jahre seit v2.0, 
eher 10 Jahre (also lange genug für umfangreiche Frameworkbeispiele, die 
es jedochbis heute kaum oder gar nicht gibt).

Eine "Hobbyprogrammiersprache" wird's mit den Neuen wenn überhaupt wohl 
eher nur für Nicht-Windows-GUI-Programme bzw. für Dialog orientierte 
GUI-Programme und Progrämmchen wird der geneigte Hobbyist nach einem 
kurzen Kontakt mehr auf Frust wohl schnell lieber auf sein gewohntes 
Lazarus (samt IDE), sein C# (samt Visual) oder sein QT-Framework mit 
zahlreichen Beispielen zurückgreifen. Denn dort wird ihm geholfen.

Die Überschrift hätte folglich vielleicht eher lauten sollen

"Rust oder Nimrod als neue Spezialistenprogrammiersprache?"

von Micha L. (milu)


Lesenswert?

Yalu X. schrieb:
>>  qwert = @\/^`
>>  asdf  = {[]}
>
> So etwas ist sicher ganz praktisch. Ich habe dabei nur die Befürchtung,
> dass, wenn ich auf einem fremden Rechner arbeite, ständig irgendwelche
> fremdartigen Zeichen auf dem Bildschirm erscheinen ;-)

Nicht ständig, nur einmal, dann schalten Gehirn und Finger in den alten 
Modus um. Ich hatte die gleiche Befürchtung wie du. Ist aber kein 
Problem, ich war selber erstaunt, wie leicht es geht,  macht alles das 
Kleinhirn für dich. :)

von MCUA (Gast)


Lesenswert?

>Zitiere gefälligst vollständig.
das ändert aber nichts dran.

von Dr. Sommer (Gast)


Lesenswert?

Yalu X. schrieb:
> Nur die gemovete Member-Variable wird ungültig, auf den Rest der
> Struktur kannst du nach wie vor zugreifen.
>
>>> 2. Die unique_ptr sind geringfügig ineffizienter, weil beim Move der
>>>    alte Pointer explizit auf null gesetzt werden muss...
>> Dafür kann man in C++ einen moved-from unique_ptr auch wieder zuweisen;
>
> Das geht in Rust auch, sofern die Pointer-Variable mutual ist.
Das würde aber bedeuten dass sie zwischen move-from und zuweisung "null" 
ist, man beim Zugriff einen Fehler erhält, und die Pointer-Variable 
immer auf != 0 geprüft wird. Also exakt genauso wie std::unique_ptr ?!?!

von Salewski (Gast)


Lesenswert?

Hello World ;) schrieb:
> Täuscht mich der Eindruck,
> dass auch Rust, go, Nimrod ähnlich wie D vielleicht wunderbare,
> interessante "Kommandozeilendialekte" sind, aber man spätestens in
> Sachen GUI-Anbindung auf eine Mauer trifft?

GTK2 und GTK3 (ungetestet) gibt es für Nimrod, für Rust gibt es auch ein 
GTK, das mir aber etwas verwaist erschien.

Bei GO und Haskell hat es ja auch gedauert, bis es GTK Bindings gab. Und 
QT Bindings zu machen ist schon schwieriger und mehr Arbeit.

Wann es native GUI Unterstützung für Windows und Apple geben wird weiß 
ich nicht, aber wahrscheinlich arbeiten Bill und Steve schon daran...

Aber Du hast schon recht, GUI ist wohl nicht der Schwerpunkt der 
Entwickler. Bei Nimrod ist sicher einer der Schwerpunkte 
Server_Anwendungen, da wo noch vorwiegend Python und ähnliches 
eingesetzt wird. Da gibt es großes finanzielles Einsparpotential

Und bei Apple werden sich jetzt eh alle auf Swift stürzen (müssen). Und 
für Windows kann man sicher mit C# leben. Zu Android weiß ich nichts...

Und zur Überschrift: Beides sind sicher keine Hobbysprachen -- ich wüßte 
jetzt auch keine richtige Hobbysprache, na ja vielleicht dieses AVR 
Basic? Einsetzen kann man beide sicherlich im Hobbybereich, aber da muss 
die Dokumentation noch etwas besser werden.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dr. Sommer schrieb:
> Das würde aber bedeuten dass sie zwischen move-from und zuweisung "null"
> ist, man beim Zugriff einen Fehler erhält, und die Pointer-Variable
> immer auf != 0 geprüft wird. Also exakt genauso wie std::unique_ptr ?!?!

Man erhält die Fehlermeldung nicht erst beim realen Zugriff (also zur
Laufzeit), sondern bereits beim Kompilieren. Deswegen muss der Pointer
zur Laufzeit weder genullt noch abgeprüft werden, da die Situation, wo
dies von Nutzen wäre, bei einem erfolgreich kompilierten Programm gar
nie einteten kann.

Hier ist ein kleines Beispiel:
1
fn main() {
2
  let mut p1 = box 123i; // zunächst ist p1 Owner
3
  println!("{}", p1);    // OK
4
5
  let p2 = p1;           // dann übernimmt p2 die Ownerschaft
6
  println!("{}", p1);    // Compiler meckert: "use of moved value: `p1`"
7
8
  p1 = p2;               // p1 wird erneut Owner
9
  println!("{}", p1);    // OK
10
}

Das Programm kompiliert nur dann, wenn man die zweite (fehlerhafte)
println-Anweisung weglässt. Das dritte println ist in Ordnung, obwohl p1
temporär die Ownerschaft an p2 abgegeben hat.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Yalu X. schrieb:
>
> Ich habe das mal anhand eines ganz einfachen Beispiels versucht:
>
>
1
> # avrtest.nim
2
> proc arithReihe(n: int8): int8 =
3
>   for i in countup(1, n):
4
>     result += i
5
> 
6
> var a = arithReihe(10)
7
>
>
> [...]
>
1
nimrod c --cpu:avr --os:standalone --deadCodeElim:on --genScript -x:off  --opt:size avrtest.nim
>
> [...]
>
> Immerhin wurden aber zwei C-Files generiert, die ich dann manuell vom
> AVR-GCC 4.7.2 übersetzen ließ.

Wobei sich bei einem Transpiler generell die Frage stellt, wie flauschig 
sich das debuggt.  Der Debugger sieht ja nicht mehr als generierten 
Code...

Bei dem einfachen Beispiel geht das noch, aber bei richtigen Programmen?

von Salewski, Stefan (Gast)


Lesenswert?

Johann L. schrieb:
> Wobei sich bei einem Transpiler generell die Frage stellt, wie flauschig
> sich das debuggt.  Der Debugger sieht ja nicht mehr als generierten
> Code...

Dich gibt es hier also doch noch -- hatte lange nichts mehr von dir 
gelesen!

Das mit dem Debuggen ist ein guter Einwand. Für den PC hat Nimrod wohl 
einen einfachen (langsamen) Debugger. Ich selbst habe (fast) nie einen 
Debugger verwenden mögen -- für einfache Dinge brauche ich ihn nicht, 
für komplizierten Code mit verschachtelten Datenstrukturen und Rekursion 
kann ich mir nicht vorstellen, dass ein Debugger mir viel hilft. Und in 
einer guten Sprache treten ja auch lange nicht so viele Fehler auf. Aber 
für Hobby-Kids mag so Zeug wie AVR-Studio schon hilfreich sein.

von Dr. Sommer (Gast)


Lesenswert?

Yalu X. schrieb:
> Das Programm kompiliert nur dann, wenn man die zweite (fehlerhafte)
> println-Anweisung weglässt. Das dritte println ist in Ordnung, obwohl p1
> temporär die Ownerschaft an p2 abgegeben hat.
Hm, interessant. Das kann C++ nicht. Und wie funktioniert das wenn die 
Referenz eine Member-Variable ist? Wenn man in einer Member-Funktion a() 
dann aus der Referenz heraus-movt, kann man dann in einer 
Member-Funktion b() noch drauf zugreifen?

Und was ist in so einem Fall, angenommen der Rückgabewert von getInput() 
ist erst zur Laufzeit bekannt (Tastatureingabe oder so) (modulo Syntax):
1
fn main() {
2
  let mut p1 = box 123i; // zunächst ist p1 Owner
3
  println!("{}", p1);    // OK
4
  
5
  if (getInput () == 27) {
6
    let p2 = p1;           // dann übernimmt p2 die Ownerschaft
7
  }
8
9
  p1 = box 456i;         // p1 wird erneut Owner
10
  println!("{}", p1);    // OK
11
}
Ob also "p1" am Ende etwas enthält oder nicht weiß der Compiler nicht, 
was macht er dann?

Funktioniert das in Rust dann nur mit solchen Referenzen oder kann man 
sich auch seine eigenen Typen mit move semantics bauen, bei denen man 
ebenfalls nicht auf eine moved-from Instanz zugreifen kann?

Salewski, Stefan schrieb:
> für komplizierten Code mit verschachtelten Datenstrukturen und Rekursion
> kann ich mir nicht vorstellen, dass ein Debugger mir viel hilft.
Wie findest du denn dann da Fehler? 10000x printf? Wenn es irgendwo 
abschmiert auf die letzte printf-Ausgabe gucken, die hoffentlich alle 
relevanten Variablen ausgibt?
Wie findest du Fehler dass in C(++) versehentlich eine Variable 
überschrieben wird (Speicherfehler) wenn nicht mit Watchpoints?
Was wenn die printf-Informationen so viele sind dass sie nicht einfach 
über UART an den PC übertragen werden können? Bei Verwendung eines 
Debuggers kann man zu beliebigem Zeitpunkt (ISR, ...) anhalten (lassen) 
und sich alles angucken, egal wie schnell der Code läuft...

von Salewski, Stefan (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Wie findest du denn dann da Fehler?

Ein paar Textausgaben (bei uC etwa über UART) und etwas Nachdenken. Gut, 
funktioniert nicht immer. Ich kann mich noch erinnern, bei meiner 
USB-Firmware hatte ich lange Zeit den Chip einfach nicht anbekommen, war 
einfach tot. Da habe ich wohl eine Woche herumprobiert -- Lösung war 
einfach, dass man drei Befehle aus dem Datenblatt in einer bestimmten 
Reihenfolge schreiben musste, eventuell noch mit einem Delay dazwischen. 
Das stand aber nicht im Datenblatt. Oder bei meinem PCB-Router, da habe 
ich schon mal ein paar Tage nach manch trivialem Fehler gesucht. Aber 
ich wüsste überhaupt nicht, wo ich da etwa einen Breakpoint setzen 
sollte...

Debugger kann ich mir eigentlich nur für fremde Software vorstellen, 
wenn die etwa mit segfault abricht und man nicht weiss wo. Das soll ja 
mit dem gcc gnu Debugger gehen, müßte ich vielleicht auch mal lernen...

von Dr. Sommer (Gast)


Lesenswert?

Salewski, Stefan schrieb:
> Debugger kann ich mir eigentlich nur für fremde Software vorstellen,
> wenn die etwa mit segfault abricht und man nicht weiss wo. Das soll ja
> mit dem gcc gnu Debugger gehen, müßte ich vielleicht auch mal lernen...
Klar geht das, dafür ist der da... Aber auch bei eigener Software, wenn 
die plötzlich abschmiert - wie willst du rausfinden wo das war?

Salewski, Stefan schrieb:
> Ein paar Textausgaben (bei uC etwa über UART)
Und was wenn der relevante Code 100000x pro Sekunde läuft, so viele 
Ausgaben inkl. der relevanten Variablen kriegste per UART nicht hin...

Ich würde mal sagen gerade bei komplexen Projekten ist ein richtiger 
Debugger extrem hilfreich...

von Salewski, Stefan (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Klar geht das, dafür ist der da... Aber auch bei eigener Software, wenn
> die plötzlich abschmiert - wie willst du rausfinden wo das war?
>

Na bei eigener Software weiß man ja, an welcher Stelle man zuletzt 
gearbeitet hat.

> Salewski, Stefan schrieb:
>> Ein paar Textausgaben (bei uC etwa über UART)
> Und was wenn der relevante Code 100000x pro Sekunde läuft, so viele
> Ausgaben inkl. der relevanten Variablen kriegste per UART nicht hin...
>

Und Deine Augen können 100000x pro Sekunde Ausgaben des Debuggers 
verarbeiten?

> Ich würde mal sagen gerade bei komplexen Projekten ist ein richtiger
> Debugger extrem hilfreich...

Beispiel: Ich habe ein ganz einfaches PCB Test-Layout generiert per 
Zufallsgenerator, mit vielleicht 20 Leiterbahnen, zweiseitiges Layout, 
der Rechner rechnet daran nur 0.03 Sekunden. 1000 mal ist alles perfekt, 
aber dann, für einen bestimmten Seed-Wert kreuzen sich irgendwo die 
Bahnen. In den 0.03 Sekunden hat der Rechner vielleicht eine Million 
Zeilen Code abgearbeitet. Und ich habe keine Idee. Was soll ich da mit 
dem Debugger anfangen? (Wenn ich eine Idee habe, dann ist das Problem eh 
schon fast gelöst.)Oder anderes Beispiel: In meiner Jugend hatte ich mal 
ein etwas dümmliches Schachprogramm gemacht -- das Stichwort 
alpha-beta-prunnung kannte ich da noch nicht -- ich habe also die Züge 
in voller Breite rekursiv durchgerechnet. Natürlich kamen da auch Feher 
vor, und ich hatte mir dann tatsächlich für 200 D-Mark den 
Oberon-Debugger gekauft. War auch ein nettes Spielzeug, Breakpoint 
setzen, Durchlaufen bis bestimmte Variablen bestimmte Werte haben, 
Speicherstellen modifizieren, alles schön grafisch dargestellt. Aber für 
das Schachprogramm war das alles keine Hilfe, da musste ich dann doch 
nachdenken. Auch ohne Rekursion, wenn ich also eine Zug-Baum im Speicher 
generiert hätte, wüsste ich nicht wirklich was mir der Debugger da 
helfen sollte.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Dr. Sommer schrieb:
> fn main() {
>   let mut p1 = box 123i; // zunächst ist p1 Owner
>   println!("{}", p1);    // OK
>
>   if (getInput () == 27) {
>     let p2 = p1;           // dann übernimmt p2 die Ownerschaft
>   }
>
>   p1 = box 456i;         // p1 wird erneut Owner
>   println!("{}", p1);    // OK
> }
>
> Ob also "p1" am Ende etwas enthält oder nicht weiß der Compiler nicht,
> was macht er dann?

In diesem konkreten Fall ist p1 beim letzten println auf jeden Fall
gültig, weil du ihm in der Zeile davor einen neuen Wert zugewiesen hast.

Aber lassen wir die Zeile "p1 = box 456i" mal weg. Jetzt gibt es zwei
Möglichkeiten:

1. Die If-Bedingung ist falsch, dann ist p1 bis zum Schluss gültig, und
   das Programm läuft fehlerfrei ab.

2. Die If-Bedingung ist wahr, dann wird p1 nach p2 gemovet und p1 somit
   ungültig. Damit kann der Zugriff auf p1 im letzten println nicht mehr
   ausgeführt werden.

Rust geht davon aus, dass bei Verzweigungen immer beide Alternativen
eintreten können. Wenn mindestens eine der beiden zum Fehler führt, gilt
das Programm als fehlerhaft und der Compiler gibt eine "use of moved
value"-Meldung in der Zeile mit dem println aus. Ein Zugriff auf eine
Owned Box ist nur dann zulässig, wenn alle Ablaufpfade, die zu
entsprechenden Stelle führen, zu einen gültigen Pointer führen. Das wird
vom Compiler durch eine entsprechende Datenflussanalyse überprüft.

> Und wie funktioniert das wenn die Referenz eine Member-Variable ist?
> Wenn man in einer Member-Funktion a() dann aus der Referenz
> heraus-movt, kann man dann in einer Member-Funktion b() noch drauf
> zugreifen?

So genau kann ich das im Moment noch nicht sagen (bin ja noch Anfänger).
Ein wenig Herumprobieren hat ergeben, dass es ziemlich schwierig, wenn
nicht sogar unmöglich ist, eine Box, die ein Member ist, mit Zustimmung
des Compilers per Methode aus einem Objekt nach außen zu moven. Die
Frage ist aber, ob man das überhaupt möchte, da man dadurch ja auf jeden
Fall ein "Loch" im Objekt hinterlässt. Die Alternativen wären:

- Man lässt sich eine Kopie des Inhalts der Box zurückgeben. Das geht
  immer, ist aber bei größeren Datenstrukturen evtl. zu ineffizient.

- Man lässt sich eine "geborgte" Referenz zurückgeben. Dabei bleibt die
  Ownership unangetastet. Allerdings ist dabei sicherzustellen, dass die
  geborgte Referenz nicht länger lebt als das Objekt, auf dessen Member
  sie zeigt. Ist sich der Compiler diesbezüglich nicht sicher, meckert
  er "cannot infer an appropriate lifetime for borrow expression due to
  conflicting requirements", gibt aber netterweise einen konstruktiven
  Hinweis: "consider using an explicit lifetime parameter as shown: fn
  getPtr<'a>(&'a self) -> &'a int".

Was es mit diesem Lifetime-Parameter auf sich hat, muss ich erst noch
nachlesen.

von Arc N. (arc)


Lesenswert?

Salewski, Stefan schrieb:
> Beispiel: Ich habe ein ganz einfaches PCB Test-Layout generiert per
> Zufallsgenerator, mit vielleicht 20 Leiterbahnen, zweiseitiges Layout,
> der Rechner rechnet daran nur 0.03 Sekunden. 1000 mal ist alles perfekt,
> aber dann, für einen bestimmten Seed-Wert kreuzen sich irgendwo die
> Bahnen. In den 0.03 Sekunden hat der Rechner vielleicht eine Million
> Zeilen Code abgearbeitet. Und ich habe keine Idee. Was soll ich da mit
> dem Debugger anfangen? (Wenn ich eine Idee habe, dann ist das Problem eh
> schon fast gelöst.)

Stichwort Reverse Debugging (erste Paper aus den 1970ern, aber je nach 
Verfahren erst heute praktikabel). Kurz gefasst: Es werden bspw. 
Programmzustände aufgezeichnet und es kann rückwärts durch den 
Programmablauf debuggt werden.
Gute Artikelserie dazu
Übersicht
http://jakob.engbloms.se/archives/1547
Forschung/Paper
http://jakob.engbloms.se/archives/1554
Produkte die das unterstützen
http://jakob.engbloms.se/archives/1564

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Salewski, Stefan schrieb:
> Dr. Sommer schrieb:
>> Klar geht das, dafür ist der da... Aber auch bei eigener Software, wenn
>> die plötzlich abschmiert - wie willst du rausfinden wo das war?
>>
>
> Na bei eigener Software weiß man ja, an welcher Stelle man zuletzt
> gearbeitet hat.
Und es stürzt bei dir immer nur da ab? Und du schreibst immer nur ein 
paar Zeilen auf einmal? Dann bist du ein Spezialfall...
>
>> Salewski, Stefan schrieb:
>>> Ein paar Textausgaben (bei uC etwa über UART)
>> Und was wenn der relevante Code 100000x pro Sekunde läuft, so viele
>> Ausgaben inkl. der relevanten Variablen kriegste per UART nicht hin...
>>
>
> Und Deine Augen können 100000x pro Sekunde Ausgaben des Debuggers
> verarbeiten?
Nein. Aber wenn der Code abschmiert, bleibt der Debugger stehen und ich 
kann alle Variablen analysieren.
> Und ich habe keine Idee. Was soll ich da mit
> dem Debugger anfangen?
Die Werte mit assert() überprüfen. Sind sie ungültig, bleibt der 
Debugger stehen und man kann alles analysieren.
> Auch ohne Rekursion, wenn ich also eine Zug-Baum im Speicher
> generiert hätte, wüsste ich nicht wirklich was mir der Debugger da
> helfen sollte.
Fehler, die sich nur in ungültigen Werten äußern die man nicht einfach 
per if() auf Gültigkeit/Konsistenz prüfen kann äußern, sind aber nur 
eine Klasse. Ja, bei denen muss man sich tatsächlich eine Menge 
debug-Informationen ausgeben lassen und die analysieren.

Gegenbeispiel: Du hast einen riesigen Code und irgendwo ganz tief 
versteckt ist ein Array aus Funktionspointern, die nacheinander 
aufgerufen werden. Leider ist die Größe verkehrt angegeben, und es wird 
ein undefinierter Wert aus dem Speicher geholt und dieser als 
Funktionspointer "aufgerufen" (klassischer Buffer-Overflow). Das 
Programm stürzt ab. Mit einem Debugger ist das Problem schnell gefunden, 
man macht einen Backtrace, findet den ungültigen Aufruf, stellt fest 
dass eine falsche Adresse geladen wird, stellt fest dass die Größe 
falsch war.

Durch pures Nachdenken hätte man den Fehler nicht gefunden. Und sich die 
(vermeintliche) Größe dieses Arrays per printf() auszugeben, darauf muss 
man auch erstmal kommen.


Salewski, Stefan schrieb:
> und ich hatte mir dann tatsächlich für 200 D-Mark den
> Oberon-Debugger gekauft.
der GDB ist heutzutage gratis... Bei Hardware-Entwicklung braucht man 
noch einen Adapter, aber den braucht man zB bei ARM sowieso.

Yalu X. schrieb:
> Das wird
> vom Compiler durch eine entsprechende Datenflussanalyse überprüft.
Das ist sehr interessant. Das kann C++ tatsächlich überhaupt nicht und 
wird es wohl auch so schnell nicht bekommen... Das ermöglicht dann 
natürlich einige interessante Dinge.

von Stefan Salewski (Gast)


Lesenswert?

Hallo Yalu (und Johann),

was ich noch nicht wirklich verstanden habe: Wann muss man eigentlich 
(bei PC-Programmierung) unbedingt auf einen Garbage-Collector 
verzichten? Ich habe dazu eben u.a. diesen Beitrag gefunden

http://stackoverflow.com/questions/19612801/how-do-i-do-realtime-programming-in-rust

aber so wirklich viel hilft der mir auch nicht. Es gibt ja jetzt wohl 
Algorithmen für Garbage-Collectoren, die nur Pausen von wenigen ms 
erzwingen, und eh allenfalls dann aufgerufen werden, wenn Speicher 
angefordert wird. So ist das ja wohl bei Nimrod (und die 
Oberon-Betriebssysteme der ETH Zürich etwa verwenden ja schon immer GC.)
Und viel Performance kosten die GC auch nicht. Grundsätzlich wird man GC 
ja wohl auch kurzzeitig blockieren können, so dass etwa ein 
zeitkritischer Interrupt nicht unterbrochen wird?

Klar, wenn man C-Bibliotheken verwendet, muss man deren interner 
Speicherverwantung folgen, GC geht also nicht so ohne weiteres, man 
müßte Wrapper schreiben. Kann man das mit den verschiedenen 
Rust-Pointern wirklich einfacher erschlagen.

Und sonst: Bei mehreren Threads oder Prozessen und geneinsam genutzten 
Datenstrukturen könnte ich mir Probleme verstellen.

Im Embedded-Bereich ist es mir schon klarer, da kann eine Pause von 1 ms 
womöglich schon zu lang sein, und insbesondere möchte man, dass der 
gesammte Code so klein wie möglich ist, also kein Platz für den GC.

von TriHexagon (Gast)


Lesenswert?

Von außen sieht es mal so aus als wäre Rust bald ready to roll.

https://github.com/rust-lang/rust/issues/milestones

Das könnte man jedenfalls wegen diesem Balken, der sich fast jeden Tag 
um 1% verschiebt, und der Tatsache, dass extra ein Mann abgestellt wurde 
um die Dokumentation/Tutorials zu vollenden, so interpretieren.

Dann bekommt Rust hoffentlich die Libs und Tools die es verdient. Ich 
bin ja schon mal sehr gespannt.

von Die Welt geht vor die Hunde (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Im Embedded-Bereich ist es mir schon klarer, da kann eine Pause von 1 ms
> womöglich schon zu lang sein, und insbesondere möchte man, dass der
> gesammte Code so klein wie möglich ist, also kein Platz für den GC.

luna (avr) hat ja einen GC, mich würde da tatsächlich mal interessieren 
wie das effizient funktionieren soll. Gut, er ist optional aber per 
default aktiv. Bei den kritischen Zeitzuständen im Controller frage ich 
mich ernsthaft wieviel Sinn das macht da eine dynamische 
Speicherverwaltung mit einem GC zu verwenden. Sind die notwendigen 
Verwaltungsdaten nicht sinnlose Speicherverschwendung, oder kommt das 
auf den Anwendungsfall an?

von Michael (Gast)


Lesenswert?

Die Welt geht vor die Hunde schrieb:
> Sind die notwendigen
> Verwaltungsdaten nicht sinnlose Speicherverschwendung

Noch jemand, der glaubt, malloc() käme ohne Verwaltungsdaten aus?

Tipp: woher weiß free() denn eigentlich, wieviele Bytes da freigegeben 
werden sollen? Kriegt doch schließlich nur einen simplen zeiger ohne 
weitere Längenangabe übergeben.

von Walter Tarpan (Gast)


Lesenswert?

Michael schrieb:
> Noch jemand, der glaubt, malloc() käme ohne Verwaltungsdaten aus?

OT: Gibt es irgendwo eine schöne Beschreibung, was dort überhaupt intern 
geschieht?

von Michael (Gast)


Lesenswert?

Naja, es gibt jede Menge verschiedene Implementierungsmöglichkeiten.

Einfache Beispiele:

Du kannst eine Bitmap haben, die pro Speicherblock fester Größe ein Bit 
an Verwaltungsdaten hat. Belegte Blöcke führen zu gesetztem Bit.
Schöner Effekt: Das Vereinigen freier benachbarter Blöcke geschieht 
automatisch und kostenlos.

Du kannst diese Speicherblöcke auch in Baumstrukturen verwalten.

Du kannst variable Speicherblockgrößen haben, und dann in das Wort vor 
dem Speicherblock eine Längenangabe packen (free() guckt dann an p-4 
nach der Länge).

Du kannst...


Wenns dich interessiert, gibts zwei Wege:

(a) Uniskripte haben oft grobe Überblicke über Strategien. Entweder im 
Betriebssystembereich, oder im Programmiersprachenbereich

(b) die mallocs der freien Betriebssysteme mal angucken. Die 
BSD-Varianten und Linux wären erste Einstiegspunkte. Sehr bekannt und 
oft verwendet ist auch jemalloc: http://www.canonware.com/jemalloc/

von Yalu X. (yalu) (Moderator)


Lesenswert?

Walter Tarpan schrieb:
> OT: Gibt es irgendwo eine schöne Beschreibung, was dort überhaupt intern
> geschieht?

Hier ist ausführlich die dynamische Speicherverwaltung der AVR-Libc
beschrieben:

  http://www.nongnu.org/avr-libc/user-manual/malloc.html

Falls du noch mehr Details brauchst, kannst du auch im gut kommentierten
Quellcode nachschauen:

  http://svn.savannah.nongnu.org/viewvc/*checkout*/trunk/avr-libc/libc/stdlib/malloc.c?root=avr-libc&content-type=text%2Fplain
  http://svn.savannah.nongnu.org/viewvc/*checkout*/trunk/avr-libc/libc/stdlib/stdlib_private.h?root=avr-libc&content-type=text%2Fplain

Jeder allozierte Speicherblock braucht also zusätzlich zur Größer der
Nutzdaten noch ein size_t (2 Bytes) für die Größeninformation des
Blocks. Darüberhinaus gibt es noch ein paar globale Variablen mit
zusammen 12 Bytes (wenn ich richtig gezählt habe). Zusammen sind dies

  (12 + 2 · nb) Bytes

an Verwaltungsdaten (nb ist die Anzahl der allozierte Blöcke).

Die ebenfalls Verwaltung benötigte Freispeicherliste ist in dieser Zahl
nicht enthalten, da sie im nichtallozierten Heap-Speicher liegt und
somit effektiv keinen Overhead darstellt.

von TriHexagon (Gast)


Lesenswert?

Michael schrieb:
> Die Welt geht vor die Hunde schrieb:
>> Sind die notwendigen
>> Verwaltungsdaten nicht sinnlose Speicherverschwendung
>
> Noch jemand, der glaubt, malloc() käme ohne Verwaltungsdaten aus?
>
> Tipp: woher weiß free() denn eigentlich, wieviele Bytes da freigegeben
> werden sollen? Kriegt doch schließlich nur einen simplen zeiger ohne
> weitere Längenangabe übergeben.

Wer nutzt denn malloc() auf einem AVR? Da macht man schön alles 
statisch. Das ist übersichtlich und reduziert den Speicherverbrauch auf 
ein Minimun. Es geht doch darum, dass dieser Speicherverbrauch bei 
LuaAVR per Default schon eingestellt ist und nicht darum wie sich das 
dynamische Speichersystem von zwei Sprachen unterscheidet. Weil es 
praktisch auf so einer Platform einfach nicht hin sinnvoll ist.

von Walter Tarpan (Gast)


Lesenswert?

TriHexagon schrieb:
> Wer nutzt denn malloc() auf einem AVR?

Ich.

Yalu X. schrieb:
> Hier ist ausführlich die dynamische Speicherverwaltung der AVR-Libc
> beschrieben:
>
>   http://www.nongnu.org/avr-libc/user-manual/malloc.html

Michael schrieb:
> Du kannst...

Danke für die Beschreibung! Insbesondere die AVR-Libs-Beschreibung ist 
ja schön zu lesen! Damit bin ich mit meinem Off-Topic-Thema glücklich.

von Mark B. (markbrandis)


Lesenswert?

Fritz schrieb:
> Es geht ja eben darum, die mistige Syntax von C und C++ zu verbessern,
> so daß der Programmierer leichter und klarer ausdrücken kann, was er
> will.

Dass die Syntax von C++ teilweise unnötig kompliziert ist, unterschreib 
ich gerne. Aber die von C? Echt jetzt? Was soll an der so komplex sein?

von Michael (Gast)


Lesenswert?

TriHexagon schrieb:
> Wer nutzt denn malloc() auf einem AVR?

Wenn du nur statischen Speicher verwendest, dann verwendest du eh keinen 
GC.

Da wir über GC diskutieren, gehts zwingend auch um malloc und Konsorten.

von Mandrosil (Gast)


Lesenswert?

TriHexagon schrieb:
> Es geht doch darum, dass dieser Speicherverbrauch bei
> LuaAVR per Default schon eingestellt ist und nicht darum wie sich das
> dynamische Speichersystem von zwei Sprachen unterscheidet. Weil es
> praktisch auf so einer Platform einfach nicht hin sinnvoll ist.

warum sollte das nicht sinnvoll sein? Das kommt doch schlussendlich auf 
die Implementierungsart an. Wenn bei malloc() und Co. Verwaltungsdaten 
nur dann anfallen, wenn man diese Befehle nutzt, hat man die Wahl und 
somit gibt es gar kein Problem.

http://www.nongnu.org/avr-libc/user-manual/malloc.html
wobei mir einfällt: kann bei knappem Speicher und haufenweisem free() 
von kleinen Speicherblöcken die Freelist in den Stack wachsen?

Bei luna-avr ist das laut Dokumentation ähnlich gelöst, wobei das hier 
augenscheinlich als verkettete Liste verwaltet wird, es existiert keine 
statische Tabelle (jedenfalls habe ich keinen Hinweis darauf gefunden).

http://avr.myluna.de/doku.php?id=de:speicherverwaltung

Jeder Speicherblock kann also auch mit einer intrinsischen Variable 
verknüpft sein, beim Aufräumen des GC werden dann die Zeiger automatisch 
angepasst. Da keine Liste existiert ist der heap hier komplett statisch 
nutzbar ohne Speicherblockanforderungen. Täuscht das, oder sind 5 bytes 
per Block dann aber schon etwas viel? Vor allem ist nicht beschrieben 
wann die GarbageCollection durchgeführt wird, beim Freigeben?

von Yalu X. (yalu) (Moderator)


Lesenswert?

Mandrosil schrieb:
> http://www.nongnu.org/avr-libc/user-manual/malloc.html
> wobei mir einfällt: kann bei knappem Speicher und haufenweisem free()
> von kleinen Speicherblöcken die Freelist in den Stack wachsen?

Deine Sorge ist unbegründet, denn die die Freelist-Knoten werden in den
freien Speicherblöcken selber gespeichert. Voraussetzung dafür ist
natürlich, dass die freien Speicherblöcke mindestens 4 Byte groß sind (2
Bytes für die Größe und 2 Bytes für den Zeiger auf den nächten freien
Block). Deswegen wird bereits in malloc() dafür gesorgt, dass die
allozierten Blöcke inkl. der Größenangabe mindestens 4 Bytes groß sind,
d.h. sie enthalten mindestens 2 Bytes Nutzdaten. Bei malloc(1) wird
demzufolge 1 Byte verschenkt. Wegen eines einzelnen Bytes wird aber auch
kaum jemand die dynamische Speichverwaltung bemühen.

: Bearbeitet durch Moderator
von Stefan S. (Gast)


Lesenswert?

Yalu X. schrieb:
> Wenn jemand von euch ebenfalls schon Erfahrungen mit diesen Sprachen
> gesammelt hat, würde mich eure Meinung dazu interessieren.

Nun ja, Dein Beitrag ist ja nun auch schon etwas älter...

Zu Nim gibt es jetzt auch ein Buch -- genauer gesagt die ersten Kapitel. 
Das erste ist wohl frei erhältlich, die ersten drei gegen Geld, der Rest 
dann im laufe des Jahres. Momentan gibt es einen Rabattcode, damit 
bekommt man die digitale Version für 20 Dollar. Das ist schon sehr fair 
für die viele Arbeit, und der Author hat schon etwas auf dem Kasten. Ich 
habe es mir gestern mal bestellt.

Neben Nim gibt es natürlich derzeit viele Interessante andere Sprachen, 
Rust und Haskell hatten wir ja diskutiert, Crystal ist wohl auch 
bekannt, der Hype hat aber in den letzten Monaten etwas nachgelassen. 
Und Swift ist ja nun auch mehr oder weniger frei.

Um mal etwas konkrete Erfahrung mit Nim zu sammels habe ich in den 
letzten Tagen mal "from Scratch" ein einfaches Schachspiel geschrieben, 
mit GTK3 GUI und Figuren als Unicode Fonts. Das ging wirklich alles sehr 
schnell und einfach, in Ruby hätte ich wohl länger gebraucht, in C erst 
recht. Fazit: Ich werde mich weiter auf Nim konzentrieren, die Sprache 
ist für mich der derzeit beste Kompromis. Rust und Haskell haben sicher 
ihre Berechtigung, die werde ich auch weiter beobachten. Und Crystal 
wohl auch, zumal es sehr stark Ruby ähnelt. Falls Du noch Nim 
installiert hast, hier findest Du mein  Schachspiel: 
https://github.com/StefanSalewski/nim-chess Und hier das Bildchen dazu: 
http://ssalewski.de/tmp/toychess.png

von Zwiebelrostbratenausgasung (Gast)


Lesenswert?

Hello World ;) schrieb:
> Lisp hat seine
> Tauglichkeit längst bei AutoCAD unter Beweis gestellt.
Ja damals als LISP noch schick war und man darin die Zukunft sah, zu der 
eit ist auch das erste AutoCAD entstanden, deshalb steckt heute noch der 
Zombie dort drinn, man kann aber längst in anderen Sprachen unter 
AutoCAD entwickeln.
LISP ist praktisch tot, der letze kommerzielle Lispcompilerhersteller 
ist schon seit Jahren dicht. LISP bzw. dessen verwandte akadmische 
Spielzeugsprachen wie Haskell und Co dienen nur noch als Material- und 
Ideenlager für andere Sprachen, siehe JavaScript in seinen aktuellen 
Versionen und Bastarden davon um mal eine relevante Sprache mit 
funktionalen Anteilen zu nennen. Nat. gibts immer wieder Versuche was 
möglichst LISPartiges zu etablieren wie die Missgeburt namens Scala, 
auch so eine Otterbrut aus dem Reich der Hochschulen, völlig verkorkst 
mit noch kaputteren Bibliotheken als das Sprachdesign, aber mit einer 
umso stärkeren Fanboitruppe. Ok der Hype von Scala ist inzwischen auch 
vorbei und die Leute sind in der Realität angekommen, wie schon 
dutzendfach beim xten Versuchen eine weitgehend funktionale Sprache zu 
etablieren, das Zeug will in der Praxis einfach niemand, wenn dann nur 
einzelne funktionale (damit ist das Programmierparadigma gemeint nicht 
im sinne von 'praktisch nützlich' o.ä.) Anteile. Und wenn ihre 
Funtkionalen Fanboischreihälse das Feature in der nächsten Release 
durchgeboxt haben wie z.B. in Python fliegt es später wieder mangels 
Verwendung still und leise bei der nächsten Relase wieder raus. LISP 
bzw. funktionale Sprachen sind wie der Schweinezyklus, kommen alle paar 
Jahre wieder in Form eines Hypes, weil eine neue Generation von Kindern 
an den Hochschulen die coolness wiederentdecken und die 
praxisuntauglichkeit nicht erfahren haben, eben mangels Praxis. Ausser 
den typischen Lehrbuchbeispielen kennen sie nix, die sehen nat. alle 
elegant und einfach aus.

von Uhu U. (uhu)


Lesenswert?

Du machst deinem Nick alle Ehre...

von Yalu X. (yalu) (Moderator)


Lesenswert?

Stefan S. schrieb:
> Um mal etwas konkrete Erfahrung mit Nim zu sammels habe ich in den
> letzten Tagen mal "from Scratch" ein einfaches Schachspiel geschrieben,
> mit GTK3 GUI und Figuren als Unicode Fonts.

Coole Sache! Hab's natürlich gleich mal ausprobiert :)

Leider hat das Programm nicht auf Anhieb gebaut, weil da wohl die
int()-Funktion aus GTK3 mit der gleichnamigen von Nim clasht. Ein
1
import gtk3 except int

in board.nim behebt das Problem aber.

Gemessen an der Quellcodegröße (engine.nim) und der ziemlich kurzen
Bedenkzeit spielt das Programm erstaunlich gut. Auch das GUI (board.nim)
ist knackig kurz. Was vielleicht noch ein Bisschen fehlt, ist eine
Erkennung, wann das Spiel zu Ende ist ;-)


Zwiebelrostbratenausgasung schrieb:
> LISP ist praktisch tot, der letze kommerzielle Lispcompilerhersteller
> ist schon seit Jahren dicht.

Falsch vermutet. Es gibt mindestens noch drei Lisp-Compiler für Geld,
die noch aktiv weiterentwickelt werden, davon zwei Klassiker und ein
Newcomer für Mobilgeräte:

Allegro Common Lisp:   http://franz.com/products/allegro-common-lisp/

LispWorks:             http://www.lispworks.com/products/lispworks.html

mocl:                  https://wukix.com/mocl

Dazu kommen noch ein paar Lisp-Compiler (z.B. von Scieneer und Corman),
die nicht mehr groß weiterentwickelt zu werden scheinen, aber nach wie
vor von deren Herstellern verkauft werden.

> LISP bzw. dessen verwandte akadmische Spielzeugsprachen wie Haskell
> und Co […]

> Nat. gibts immer wieder Versuche was möglichst LISPartiges zu
> etablieren wie die Missgeburt namens Scala […]

Für dich ist wohl jede Programmiersprache, die du nicht kennst,
Lisp-artig :)

> Ok der Hype von Scala ist inzwischen auch vorbei

> LISP bzw. funktionale Sprachen sind wie der Schweinezyklus, kommen
> alle paar Jahre wieder in Form eines Hypes

Von welchen Hypes sprichst du? Habe ich da etwas verpasst?

Nein, da gibt es (zum Glück) weder Hypes noch Schweinezyklen. Die
funktionale Programmierung entwickelt sich ganz leise und stetig weiter,
ähnlich wie das lange Zeit bei der objektorientierten Programmierung der
Fall war, nur noch langsamer. Irgendwann wird der Tag kommen, an dem die
ganze Welt funktional programmiert, ohne sich dessen bewusst zu sein :)

von Programmierer (Gast)


Lesenswert?

Meines Erachtens nach ist C (nicht C++) das einzige was wirklich etwas 
taugt, zumindest für performante und hardwarenahe Sachen. C# mag ja gut 
sein um Klicki-Bunti zu machen. Aber auch der Brocken wie Java etc. ist 
einfach nur ein versuch es allen recht zu machen. Klar Java ist 
plattformunabhängig, aber dafür auch in gewissen Sachen nicht wirklich 
performant, insbesondere dann, wenn ein Java-Programm geladen wird und 
vorher noch nichts mit Java zur Systemlaufzeit gestartet wurde. Da wird 
erstmal ein riesen Brocken an Software geladen noch bevor die 
eigentliche Anwendung loslegen kann. Plain C mit Winapi etc. ist 
schneller als alles andere (wenn man natürlich programmieren kann), 
dumme nutzen fertig C#/.net Libs und die verzeichen auch dummen, dass 
sie nicht programmieren können und bleiben nahezu gleich schnell.
Diese ganze Objektorientiuierung mag für den ein oder anderen - insb. 
für Softies, die von der Hardware, die den Code ausführt keine Ahnung 
haben - ein Segen sein, aber in Wirklichkeit ist es doch nur ein Mittel 
um Softies auch mal die Möglichkeit zu geben sich geistig austoben zu 
können.
Das einzig tolle an C++ finde ich die Polymorphie, alles andere ist 
unnötig und trägt nur zur Unübersichtlichkeit des Codes bei. Sicherlich 
ist sowas auch einer der Gründe warum selbst für popelige Software 1 GB 
Festplattenspeicher, 2 GB RAM und ein DualCore benötigt wird.

von Hauptsache schnell (Gast)


Lesenswert?

Wenn es nicht schneller als Assembler ist, lohnt sich  der Umstieg 
nicht.

Gruß,

von Stefan S. (Gast)


Lesenswert?

Yalu X. schrieb:
> Coole Sache! Hab's natürlich gleich mal ausprobiert :)
>
> Leider hat das Programm nicht auf Anhieb gebaut, weil da wohl die
> int()-Funktion aus GTK3 mit der gleichnamigen von Nim clasht.

Hallo Yalu,

das überascht mich etwas. In der Tat gibt es in gtk3.nim
1
proc int*(settings: PrintSettings; 
2
                                 key: cstring): gint {.
3
    importc: "gtk_print_settings_get_int", libgtk.}

aber das sollte ja kein Problem sein, auf Grund der Parameter.

Und einige andere Leute haben das Programm auch schon ausprobiert, 
soweit ich weiss ohne dieses Problem. Hast Du Nim 0.13 ? Aber gut, Du 
hast es ja beheben können. Ja, ein paar Erweiterungen werde ich wohl 
irgendwann mal einbauen. Ursprünglich hatte ich das Programm eigentlich 
nur für mich geschrieben, um etwas mehr praktische Übung mit Nim zu 
erlangen und um meine GTK3-Bindings etwas zu testen. Ich war wirklich 
überascht, wie schnell man mit Nim doch Software schreiben kann -- bei 
Programmen länger als einige hundert Zeilen wohl schneller als mit 
Python oder Ruby. Die statische Typisierung und die Compiler-Meldungen 
sind schon hilfreich.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Stefan S. schrieb:
> Hast Du Nim 0.13 ?

Es scheint so:

1
$ nim --version
2
Nim Compiler Version 0.13.0 (2016-01-22) [Linux: i386]
3
Copyright (c) 2006-2015 by Andreas Rumpf
4
5
git hash: a121c3f9eb2a348b9d6ae03ffd01aab26a238c30
6
active boot switches: -d:release

Hier ist die Fehlermeldung:

1
$ nim c -d:release board.nim
2
   :
3
<viele Hints>
4
   :
5
board.nim(65, 22) Error: type mismatch: got (gdouble)
6
but expected one of: 
7
gtk3.int(settings: PrintSettings, key: cstring)
8
gobject.int(value: GValue)

Das ist schon etwas komisch: Der Compiler erkennt zwar, dass gtk3.int
und gobject.int typmäßig nicht passen, aber auf die Idee, stattdessen
einfach die int-Funktion von Nim zu nehmen, kommt er scheinbar nicht.

von Stefan S. (Gast)


Lesenswert?

Falls doch noch jemand Interesse an Nim hat: Das Buch "Nim in Action" 
gibt es heute nochmals zum halben Preis, also die EPub und PDF-Version 
für ca. 20 Dollar. Der Rabatt-Code ist im Nim Forum angegeben. (Wobei, 
der Sinn dieser Rabatt-Aktionen erschliesst sich mir nicht, damit hatte 
sich doch schon ein Baumarkt ruiniert.)

von W.S. (Gast)


Lesenswert?

Nö.

Die Welt braucht nicht noch einen Vorbrenner für C - kurzum, das Ganze 
ist Murks. Weder effizient, noch elegant.

W.S.

von Stefan S. (Gast)


Lesenswert?

W.S. schrieb:
> Die Welt braucht nicht noch einen Vorbrenner für C - kurzum, das Ganze
> ist Murks. Weder effizient, noch elegant.

Nö. Der Bedarf ist schon da, und neben C gibt es ja auch JS und 
experimentell LLVM als Backend. Und C wurde schon mit Bedacht gewählt -- 
die Nachteile sind bekannt, die Vorteile überwiegen aber.

Aber es gibt natürlich auch noch einige andere interessante moderne 
Sprachen.

von W.S. (Gast)


Lesenswert?

Stefan S. schrieb:
> Der Bedarf ist schon da

Wo bitte?

Also mein finaler Komentar: igittigit. Wenn ich C schreiben will, dann 
kann ich das direkt tun, ohne solche finsteren Vorbrenner. Ich denke mit 
Schaudern an A.Dunkels Proto-Threads und Co.

Hätten diese Leute doch man bloß ihren Entwicklerschweiß in was 
handfesteres gesteckt, wie z.B. ein ordentlich optimierendes Pascal für 
den Cortex.

W.S.

von Yalu X. (yalu) (Moderator)


Lesenswert?

W.S. schrieb:
> Also mein finaler Komentar: igittigit. Wenn ich C schreiben will, dann
> kann ich das direkt tun, ohne solche finsteren Vorbrenner.

Was ist denn so schlecht daran, als Native-Code-Compiler einen bewährten
C-Compiler mit all seinen Optimierungsfähigkeiten zu nutzen, dass du
dich gleich in zwei Beiträgen darüber echauffieren musst? Man muss den
C-Zwischencode ja nicht anschauen.

von Stefan Salewski (Gast)


Lesenswert?

Ja, diese beiden Kommentare des Herrn W.S. sind schon sehr schwach...

Die Nachteile von C Zwischencode sind bekannt. So kann man die echten 
Low-Level Elemente der Hardware, die C nicht kennt, nicht wirklich gut 
ausnutzen. Dies betrifft etwa Exceptions oder das Erkennen von 
ganzahligen Überläufen bei unsigned int Arithmetik. Und für gute 
Effizienz muss es möglich sein, die Ausgangssprache gut in C abzubilden. 
Debugging ist durch den C Zwischencode wohl auch etwas erschwert -- 
wobei anderersets kann man sich so auch den C Code ansehen.

Vorteile: Es gibt auf fast jedem System einen C-Compiler, meist sogar 
hoch optimierende C-Compiler. Damit kann die Ausgangssprache dann 
prinzipiell dort eingesetzt werden. Weiter hat man sehr gute 
Kompatibilität zu all den C Bibliotheken, oder man kann Software 
wahlweise auch in Form des C Zwischencodes ausliefern, der Nutzer 
benötigt dann nur einen C Compiler.

LLVM ist wie erwähnt auch eine (spätere) Option.

Na ja, Yalu weiss das eh besser als ich, und den Herr WS wird es nicht 
wirklich interessieren. Wundert mich eigentlich etwas, denn Nim hat mit 
Pascal/Delphi doch einige Ähnlichkeiten.

von W.S. (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Wundert mich eigentlich etwas, denn Nim hat mit
> Pascal/Delphi doch einige Ähnlichkeiten.

Wie bitte?
Etwa so, wie KDE zu Windows?

OK, Basteln ist Hobbysache und niemand fragt einen, womit man seine 
Freizeit verbringt. Insofern ist das wurscht.



Yalu X. schrieb:
> Was ist denn so schlecht daran, als Native-Code-Compiler einen bewährten
> C-Compiler mit all seinen Optimierungsfähigkeiten zu nutzen

Ach Yalu, die Sage vom Sisyphus oder wie der Kerl mit dem Stein geheißen 
haben mag, kennst du ja wohl. Mich dauert es eben immer wieder, wenn 
Leute ihre Zeit und Kraft in solches Zeugs vergeuden. Es ist so 
unsäglich sinnlos, denn niemand wird damit irgend etwas wirklich 
Sinnvolles anstellen können/wollen.

Genau das ist der Punkt. Wir sollten uns auf "Hobby" einigen, denn da 
fragt keiner nach dem Sinn vom Bierkorkensammeln usw.

Aber eigentlich hab ich das ja bereits ganz explizit geschrieben - also 
warum fragst du da nochmal hinterher?

W.S.

von Psychoklemptner (Gast)


Lesenswert?

W.S. schrieb:

> Aber eigentlich hab ich das ja bereits ganz explizit geschrieben - also
> warum fragst du da nochmal hinterher?

Vermutlich hat er gelesen, dass Beschäftigungstherapie für Choleriker 
nur anzuraten ist.

von Yalu X. (yalu) (Moderator)


Lesenswert?

W.S. schrieb:
> Wir sollten uns auf "Hobby" einigen, denn da
> fragt keiner nach dem Sinn vom Bierkorkensammeln usw.

Wir brauchen uns darüber nicht zu einigen, siehe Thread-Titel.

> Aber eigentlich hab ich das ja bereits ganz explizit geschrieben - also
> warum fragst du da nochmal hinterher?

Ja, ich habe das schon gelesen: Dich stört, dass der "Vorbrenner"
"finster" ist. Nebenbei habe ich noch erfahren, dass du kein Freund von
A. Dunkels Protothreads bist (was auch immer das mit Nim zu tun haben
mag) ;-)

W.S. schrieb:
> Stefan Salewski schrieb:
>> Wundert mich eigentlich etwas, denn Nim hat mit
>> Pascal/Delphi doch einige Ähnlichkeiten.
>
> Wie bitte?

Um ehrlich zu sein, sehe ich auch nicht viele Ähnlichkeiten zwischen den
beiden Sprachen, weder syntaktisch noch semantisch.

Delphi hält halt auf Grund seiner Abstammung noch an der aus den 50er
Jahren stammenden Algol-Syntax fest. Das wäre nicht weiter schlimm, wenn
nicht auch der ganze Rest so altbacken daher käme. Das ist auch kein
Wunder, da Delphi im Wesentlichen aus dem Pascal-Sprachkern aus den 70er
Jahren besteht, der durch etwas Nineties-Style-OOP aufgepeppt wurde. Da
hat Nim, das ohne irgendwelche Altlasten völlig neu konzipiert wurde,
schon deutlich mehr zu bieten.

Aber ich schätze, du bist unter den Programmierern das, was unter den
Autofahrern der Morgan¹-Freak ist, der auch nicht in ein Auto neuerer
Bauart (d.h. ohne ein Gerippe aus Eschenholz) steigen würde :)

W.S. schrieb:
> Hätten diese Leute doch man bloß ihren Entwicklerschweiß in was
> handfesteres gesteckt, wie z.B. ein ordentlich optimierendes Pascal für
> den Cortex.

Ich meine, sowohl Delphi als auch Free Pascal gäbe es auch für Cortexe,
kenne allerdings ihren Reifegrad aber nicht.

————————————
¹) Wobei ein Morgan im Gegensatz zu Pascal/Delphi immerhin einen extrem
   hohen Coolness-Faktor hat.

von Stefan Salewski (Gast)


Lesenswert?

Yalu X. schrieb:
> Um ehrlich zu sein, sehe ich auch nicht viele Ähnlichkeiten zwischen den
> beiden Sprachen, weder syntaktisch noch semantisch.

Nim FAQ:

What have been the major influences in the language's design?
The language borrows heavily from (in order of impact): Modula 3, 
Delphi, Ada, C++, Python, Lisp, Oberon.

Nun ja, ich kann mich an Pascal nur dunkel errinnnern, eher schon an 
Modula3 und Oberon. Bei Delphi habe ich nur mal einigen Leuten über die 
Schulter geguckt.

Was mir so einfiel: keine {} für Blöcke, "var i: int", const und type 
sections, proc() und func(), ptr und ref statt dem * von C, and und or 
ausgeschrieben statt && und ||

von Stefan Salewski (Gast)


Lesenswert?

Stefan Salewski schrieb:
> Modula3

Ach Tippfehler. Modula-2 meinte ich, Modula-3 kenne ich nur vom Namen. 
Und sonst, inc() und dec() gibt es, oder etwa bei strings wird die Länge 
explizit gespeichert.

Aber sonst hat sich bei den modernen Sprachen natürlich viel getan, 
Iteratoren, Templates, hygenic Macros, Interfaces (derzeit eher Concepts 
bei Nim), Konstrukte für parallele Verarbeitung. Gut, einiges davon hat 
Delphi wohl auch mitlerweile.

von Mehmet K. (mkmk)


Lesenswert?

W.S. schrieb:
> Ich denke mit Schaudern an A.Dunkels Proto-Threads und Co.

Ja, ich erinnere mich an diesen Thread. Liegt glaube ich so 1 - 2 Jahre 
zurück. Dabei ging es um Sinn und Zweck von RTOS. Und Du hattest 
vehement die Ansicht vertreten, dass ein Main-Loop, in der man Flags 
abfraegt, voll ausreichend sei. Als ich dann noch Protothreads in die 
Diskussion einwarf ...

In all den Jahren habe ich in diesem Forum eines gelernt: wenn W.S. 
etwas ablehnt, herabsetzt oder gar ausrastet, dann lohnt es sich für 
mich, wenn ich mir dies etwas naeher anschaue. :)

von W.S. (Gast)


Lesenswert?

Yalu X. schrieb:
> Nebenbei habe ich noch erfahren, dass du kein Freund von
> A. Dunkels Protothreads bist (was auch immer das mit Nim zu tun haben
> mag) ;-)

Was es mit Nim zu tun hat?
Ich könnte jetzt schreiben: ist dasselbe.
Aber konkret: es ist beides Vorbrenner-Akrobatik.
Bei Dunkel eben Präprozessor-Akrobatik und bei Nim eben 
Prä-Umsetzer-Akrobatik oder wie man das nennen sollte.

Ich hätte da eigentlich einen nicht wirklich stubenreinen Ausdruck für 
beides. Aber es ist schon bemerkenswert, womit manche Leute ihre 
Freizeit ausfüllen.

W.S.

von Stefan Salewski (Gast)


Lesenswert?

W.S. schrieb:
> Prä-Umsetzer-Akrobatik oder wie man das nennen sollte.

Es gab da neulich im Nim Forum bzw. IRC einen Troll, der fest davon 
überzeugt war, Nim wäre kein wirklicher Compiler, weil er nicht direkt 
Maschiencode erzeugt. Wer mag kann das gerne so sehen.

von Mehmet K. (mkmk)


Lesenswert?

W.S. schrieb:
> Aber es ist schon bemerkenswert, womit manche Leute ihre Freizeit ausfüllen.

Also mit RTOS und Protothreads fülle ich nicht meine Freizeit aus, 
sondern meine Arbeitszeit; und somit meinen Geldbeutel.
Was die Freizeit anbelangt: Wegen Deinen negativen Aeusserungen zu Rust 
muss ich jetzt in meiner knappen Freizeit mich damit beschaeftigen :(

von Yalu X. (yalu) (Moderator)


Lesenswert?

Mehmet K. schrieb:
> In all den Jahren habe ich in diesem Forum eines gelernt: wenn W.S.
> etwas ablehnt, herabsetzt oder gar ausrastet, dann lohnt es sich für
> mich, wenn ich mir dies etwas naeher anschaue. :)

Mehmet K. schrieb:
> Was die Freizeit anbelangt: Wegen Deinen negativen Aeusserungen zu Rust
> muss ich jetzt in meiner knappen Freizeit mich damit beschaeftigen :(

So gesehen musst du dich mit allem beschäftigen, was nicht Delphi ist.
Oje, da hast du noch einiges vor dir ;-)

von Mehmet K. (mkmk)


Lesenswert?

Yalu X. schrieb:
> So gesehen musst du dich mit allem beschäftigen, was nicht Delphi ist.
> Oje, da hast du noch einiges vor dir ;-)

Ne, ne! Ich pick' mir nur die Rosinen raus :)

von W.S. (Gast)


Lesenswert?

Yalu X. schrieb:
> Oje, da hast du noch einiges vor dir

Naja, Assembler kann er also schon mal auslassen. Eigentlich C auch. Da 
bleibt aber ne Menge Firlefanz übrig.

Also los, ihr Beiden.

Die nächste interaktive GUI-App zum Flash-Programmieren für nen STM32 
programmiert einer von euch in Rust und der andere in Nim. Und dann 
präsentiert eure Ergebnisse hier bei Projekte&Code. Gelle?

W.S.

von Yalu X. (yalu) (Moderator)


Lesenswert?

W.S. schrieb:
> Die nächste interaktive GUI-App zum Flash-Programmieren für nen STM32
> programmiert einer von euch in Rust und der andere in Nim. Und dann
> präsentiert eure Ergebnisse hier bei Projekte&Code. Gelle?

GUI-Programmierung? Pfui-Deifel =8-o

Die Programmiersprache, in der mir GUI-Programmierung Spaß macht, die
muss leider erst noch erfunden werden ;-)

Und da man ein Flash-Tool typischerweise von Make oder einem anderen
Build-Tool aufruft, ist hier ein GUI sowieso eher ein Hindernis als eine
Hilfe.

Da stecke ich meinen Entwicklerschweiß lieber in etwas Handfesteres – um
es mit deinen Worten auszudrücken :)

von Stefan Salewski (Gast)


Lesenswert?

Yalu X. schrieb:
> Die Programmiersprache, in der mir GUI-Programmierung Spaß macht, die
> muss leider erst noch erfunden werden ;-)

Ja leider. Die GUI-Unterstützung ist für die meisten interessanten 
modernen Sprachen nicht gerade toll. Ausnahmen wären wohl Swift auf OSX 
oder Dart und Kotlin für Web bzw. Android -- habe ich mir aber alles 
noch nicht angesehen. In den letzten Wochen hatte ich mal einen kleinen 
Nim Editor mit GTK3 gemacht -- geht zwar ganz gut, aber die ware Freude 
ist das nicht.

http://ssalewski.de/tmp/NEd.png

https://github.com/ngtk3/NEd

von D. I. (Gast)


Lesenswert?

Also mit XAML lassen sich schon vernünftige GUIs schmerzfrei erstellen 
meiner Meinung nach.
Oder eben Web GUIs mit HTML und CSS, das geht auch ganz gut.

von Sinnlos (Gast)


Lesenswert?

Also jetzt ist eigentlich Rust der Klare Sieger

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.