Zum Inhalt springen

OpenSCAD Benutzerhandbuch/OpenSCAD-Sprachreferenz

Aus Wikibooks

OpenSCAD-Sprache

[Bearbeiten]

OpenSCAD ist ein 2D-/3D- und Solid Modeling-Programm, das auf einer funktionalen Programmiersprache basiert. Mit ihr erstellst du Modelle, die auf dem Bildschirm vorgezeigt und in ein 3D-Polygonnetz (Mesh) gerendert werden, das in einer Vielzahl von 2D/3D-Dateiformaten exportiert werden kann.

Einführung in die Syntax

[Bearbeiten]

Ein Skript in der OpenSCAD-Sprache wird verwendet, um 2D- oder 3D-Modelle zu erstellen. Dieses Skript ist eine freiformartige Liste von Anweisungen, z. B.:

 variable = value;
 object();
 operator() object();
 operator() {
     variable = value;
     object();
 }
 operator() operator() {
     object();
     object();
 }
 operator() {
     operator() object();
     operator() {
         object();
         object();
     }
 }


Zuweisungen (Assignments)

[Bearbeiten]
Zuweisungsanweisungen verknüpfen einen Wert mit einem Namen.

Objekte

[Bearbeiten]
Objekte sind die Bausteine für Modelle, erstellt durch 2D- und 3D-Primitive und benutzerdefinierte Module. Objekte enden mit einem Semikolon ";".
Beispiele sind: "cube()", "sphere()", "polygon()", "circle()", etc.

Operatoren (Transformationen)

[Bearbeiten]
Operatoren, oder Transformationen, modifizieren die Lage, Farbe und andere Eigenschaften von Objekten. Operatoren verwenden geschweifte Klammern "{}", wenn ihr Gültigkeitsbereich mehr als eine Aktion umfasst. Mehr als ein Operator kann für dasselbe Objekt oder dieselbe Gruppe von Objekten verwendet werden. Mehrere Operatoren werden von rechts nach links verarbeitet, d.h. der dem Objekt am nächsten stehende Operator wird zuerst verarbeitet.

Beispiele:

   cube(5);
   x = 4+y;
   rotate(40) square(5,10);
   translate([10,5]) {
       circle(5);
       square(4);
   }
   rotate(60) color("red") {
       circle(5);
       square(4);
   }
   color("blue") {
       translate([5,3,0]) sphere(5);
       rotate([45,0,45]) {
           cylinder(10);
           cube([5,6,7]);
       }
   }


Kommentare

[Bearbeiten]

Kommentare sind Notizen innerhalb des Skripts (entweder für dich selbst oder für zukünftige Programmierer), die beschreiben, wie der Code funktioniert oder was er tut. Kommentare werden vom Compiler nicht ausgewertet und sollten nicht verwendet werden, um selbsterklärenden Code zu beschreiben.

OpenSCAD verwendet C++-artige Kommentare:

// Dies ist ein Kommentar
myvar = 10; // Der Rest der Zeile ist ein Kommentar
/*
   Mehrzeilige Kommentare
   können sich über mehrere Zeilen erstrecken.
*/


Werte und Datentypen

[Bearbeiten]

Ein Wert in OpenSCAD ist entweder eine Zahl (wie 42), ein Boolean (wie "true"), ein String (wie ""foo""), ein Range (wie "[0: 1: 10]"), ein Vektor (wie "[1,2,3]") oder der undefinierte Wert ("undef"). Werte können in Variablen gespeichert, als Funktionsargumente übergeben und als Funktionsergebnisse zurückgegeben werden.

OpenSCAD ist eine dynamisch typisierte Sprache mit einem festen Satz von Datentypen. Es gibt keine Typnamen und keine benutzerdefinierten Typen.

Zahlen

[Bearbeiten]

Zahlen sind der wichtigste Werttyp in OpenSCAD und werden in der vertrauten Dezimalschreibweise notiert, z. B. "-1", "42", "0.5", "2.99792458e+8".

Vorlage:Requires Hexadezimale Konstanten sind im C-Stil erlaubt, "0x" gefolgt von hexadezimalen Ziffern. [OpenSCAD unterstützt keine Oktalschreibweise für Zahlen.]

Zusätzlich zu Dezimalzahlen ist der folgende Name für eine spezielle Zahl definiert:

  • "PI"

OpenSCAD hat nur eine einzige Art von Zahl: eine 64-Bit-IEEE-Gleitkommazahl. OpenSCAD unterscheidet nicht zwischen ganzen Zahlen und Gleitkommazahlen als zwei verschiedene Typen und unterstützt auch keine komplexen Zahlen. Da OpenSCAD den IEEE-Gleitkommastandard verwendet, gibt es einige Abweichungen vom Verhalten von Zahlen in der Mathematik:

  • Wir verwenden binäre Gleitkommazahlen. Eine Bruchzahl wird nicht exakt dargestellt, es sei denn, der Nenner ist eine Zweierpotenz. Zum Beispiel hat 0.2 (2/10) keine exakte interne Darstellung, aber 0.25 (1/4) und 0.375 (3/8) werden exakt dargestellt.
  • Die größte darstellbare Zahl ist etwa 1e308. Wenn ein numerisches Ergebnis zu groß ist, kann das Ergebnis unendlich sein (wird von "echo" als "inf" ausgegeben).
  • Die kleinste darstellbare Zahl ist etwa -1e308. Wenn ein numerisches Ergebnis zu klein ist, kann das Ergebnis -unendlich sein (wird von "echo" als "-inf" ausgegeben).
  • Werte sind auf etwa 16 Dezimalstellen genau.
  • Wenn ein numerisches Ergebnis ungültig ist, kann das Ergebnis "Not A Number" sein (wird von "echo" als "nan" ausgegeben).
  • Wenn ein von Null verschiedenes numerisches Ergebnis zu nahe an Null liegt, um dargestellt zu werden, ist das Ergebnis "-0", wenn das Ergebnis negativ ist, andernfalls "0". Null ("0") und negative Null ("-0") werden von einigen mathematischen Operationen als zwei verschiedene Zahlen behandelt und von "echo" unterschiedlich ausgegeben, obwohl sie als gleich verglichen werden.

Die Konstanten "inf" und "nan" werden von OpenSCAD nicht als numerische Konstanten unterstützt, obwohl du Zahlen berechnen kannst, die von "echo" so ausgegeben werden. Du kannst Variablen mit diesen Werten definieren, indem du Folgendes verwendest: """

inf = 1e200 * 1e200;
nan = 0 / 0;
echo(inf,nan);

""" Der Wert "nan" ist der einzige OpenSCAD-Wert, der nicht gleich einem anderen Wert ist, auch nicht mit sich selbst. Obwohl du testen kannst, ob eine Variable "x" den undefinierten Wert hat, indem du "x == undef" verwendest, kannst du nicht "x == 0/0" verwenden, um zu testen, ob "x" "Not A Number" ist. Stattdessen musst du "x != x" verwenden, um zu testen, ob "x" "nan" ist.

Boolesche-Werte

[Bearbeiten]

Booleans sind Variablen mit zwei Zuständen, in OpenSCAD typischerweise als "true" und "false" bezeichnet. Boolean-Variablen werden typischerweise durch bedingte Tests erzeugt und von der bedingten Anweisung "if()", dem bedingten Operator "? :" und den logischen Operatoren "!" (nicht), "&&" (und) und "||" (oder) verwendet. Anweisungen wie "if()" akzeptieren tatsächlich nicht-boole'sche Variablen, aber die meisten Werte werden in einem Boolean-Kontext in "true" umgewandelt. Die Werte, die als "false" zählen, sind:

  • "false"
  • "0" und "-0"
  • """"
  • "[]"
  • "undef"

Beachte, dass ""false"" (der String), "[0]" (ein numerischer Vektor), "[ [] ]" (ein Vektor, der einen leeren Vektor enthält), "[false]" (ein Vektor, der den Boolean-Wert false enthält) und "0/0" (not a number) alle als "true" zählen.

Strings

[Bearbeiten]

Ein String ist eine Folge von null oder mehr Unicode-Zeichen. String-Werte werden verwendet, um Dateinamen beim Importieren einer Datei anzugeben und um Text zu Debugging-Zwecken mit "echo()" anzuzeigen. Strings können auch mit dem Primitiv "text()" verwendet werden, das in Version 2015.03 hinzugefügt wurde.

Ein String-Literal wird als Folge von Zeichen geschrieben, die in Anführungszeichen """ eingeschlossen sind, wie z.B.: """" (ein leerer String) oder ""this is a string"".

Um ein """-Zeichen in ein String-Literal einzufügen, verwende "\"". Um ein "\"-Zeichen in ein String-Literal einzufügen, verwende "\\". Die folgenden mit "\" beginnenden Escape-Sequenzen können innerhalb von String-Literalen verwendet werden:

  • "\"" → """
  • "\\" → "\"
  • "\t" → Tabulator
  • "\n" → Zeilenumbruch (newline)
  • "\r" → Wagenrücklauf (carriage return)
  • "\x21" → "!" - nur gültig im Bereich von "\x01" bis "\x7f", "\x00" erzeugt ein Leerzeichen
  • "\u03a9" → "Ω" - 4-stelliger Unicode-Codepoint, siehe text() für weitere Informationen zu Unicode-Zeichen
  • "\U01f600" → "😀" - 6-stelliger Unicode-Codepoint

Dieses Verhalten ist neu seit OpenSCAD-2011.04. Du kannst alte Dateien mit dem folgenden sed-Befehl upgraden: "sed 's/\\/\\\\/g' non-escaped.scad > escaped.scad"

Beispiel: """

 echo("The quick brown fox \tjumps \"over\" the lazy dog.\rThe quick brown fox.\nThe \\lazy\\ dog.");

""" Ergebnis
"""

   ECHO: "The quick brown fox     jumps "over" the lazy dog.
   The quick brown fox.
   The \lazy\ dog."

""" Altes Ergebnis """

   ECHO: "The quick brown fox \tjumps \"over\" the lazy dog.
   The quick brown fox.\nThe \\lazy\\ dog."

"""

Ranges (Bereiche)

[Bearbeiten]

Ranges werden von for()-Schleifen und children() verwendet. Sie haben 2 Varianten:

  • "[<start>:<end>]"
  • "[<start>:<increment>:<end>]"

Ein fehlendes "<increment>" standardmäßig auf 1.

Obwohl sie in eckige Klammern "[]" eingeschlossen sind, sind sie keine Vektoren. Sie verwenden Doppelpunkte ":" als Trennzeichen, nicht Kommas. """

r1 = [0:10];
r2 = [0.5:2.5:20];
echo(r1); // ECHO: [0: 1: 10]
echo(r2); // ECHO: [0.5: 2.5: 20]

"""

In Version 2021.01 und früher erzeugt ein Range in der Form "[<start>:<end>]" mit "<start>" größer als "<end>" eine Warnung und ist äquivalent zu "[<end>: 1: <start>]".

Ein Range in der Form "[<start>:1:<end>]" mit "<start>" größer als "<end>" erzeugt keine Warnung und ist äquivalent zu "[]". Vorlage:Requires Dies gilt auch, wenn das Inkrement weggelassen wird.

Das "<increment>" in einem Range kann negativ sein (für Versionen nach 2014). Ein Startwert kleiner als der Endwert mit einem negativen Inkrement erzeugt keine Warnung und ist äquivalent zu "[]".

Du solltest vorsichtig sein mit Schrittwerten, die nicht exakt als binäre Gleitkommazahlen dargestellt werden können. Ganzzahlen sind in Ordnung, ebenso wie Bruchwerte, deren Nenner eine Zweierpotenz ist. Zum Beispiel sind 0.25 (1/4) und 0.375 (3/8) sicher, aber 0.2 (2/10) kann Probleme verursachen. Das Problem mit diesen Schrittwerten ist, dass dein Range aufgrund ungenauer Arithmetik mehr oder weniger Elemente haben kann als erwartet.

Der undefinierte Wert

[Bearbeiten]

Der undefinierte Wert ist ein spezieller Wert, geschrieben als "undef". Er ist der Anfangswert einer Variable, der noch kein Wert zugewiesen wurde, und er wird oft als Ergebnis von Funktionen oder Operationen zurückgegeben, denen illegale Argumente übergeben wurden. Schließlich kann "undef" als Nullwert verwendet werden, ähnlich wie "null" oder "NULL" in anderen Programmiersprachen.

Alle arithmetischen Ausdrücke, die "undef"-Werte enthalten, ergeben "undef". In logischen Ausdrücken ist "undef" äquivalent zu "false". Vergleichende Operatorausdrücke mit "undef" ergeben "false", außer "undef==undef", was "true" ergibt.

Beachte, dass numerische Operationen auch "'nan'" (not-a-number) zurückgeben können, um ein illegales Argument anzuzeigen. Zum Beispiel ist "0/false" "undef", aber "0/0" ist "'nan'". Vergleichende Operatoren wie "<" und ">" geben "false" zurück, wenn sie illegale Argumente erhalten. Obwohl "undef" ein Sprachwert ist, ist "'nan'" das nicht.

Variablen

[Bearbeiten]

OpenSCAD-Variablen werden durch eine Anweisung mit einem Namen oder Identifier, einer Zuweisung über einen Ausdruck und einem Semikolon erstellt. Die Rolle von Arrays, die in vielen imperativen Sprachen vorkommen, wird in OpenSCAD durch Vektoren übernommen. Gültige Identifier bestehen aus einfachen Zeichen und Unterstrichen "[a-zA-Z0-9_]". High-ASCII- und Unicode-Zeichen sind nicht erlaubt.

Vor Development snapshot konnten Variablennamen mit Ziffern beginnen. In Development snapshot stellen Namen, die mit "0x" beginnen und von hexadezimalen Ziffern gefolgt werden, eine hexadezimale Konstante dar, und andere Variablennamen, die mit Ziffern beginnen, lösen eine Warnung aus. """

var = 25;
xx = 1.25 * cos(50);
y = 2*xx+var;
logic = true;
MyString = "This is a string";
a_vector = [1,2,3];
rr = a_vector[2];      // Element eines Vektors
range1 = [-1.5:0.5:3]; // for()-Schleifen-Range
xx = [0:5];            // alternativer for()-Schleifen-Range

"""

OpenSCAD ist eine funktionale Programmiersprache, daher sind solche Variablen an Ausdrücke gebunden und behalten aufgrund der Anforderungen der referenziellen Transparenz während ihrer gesamten Lebensdauer einen einzigen Wert. In imperativen Sprachen wie C wird dasselbe Verhalten bei Konstanten beobachtet, die typischerweise normalen Variablen gegenübergestellt werden.

Mit anderen Worten, OpenSCAD-Variablen sind eher wie Konstanten, aber mit einem wichtigen Unterschied: Wenn Variablen mehrfach ein Wert zugewiesen wird, wird nur der letzte zugewiesene Wert an allen Stellen im Code verwendet. Siehe weitere Diskussion unter #Variables cannot be changed. Dieses Verhalten ist notwendig, um variable Eingaben über die Befehlszeile über die Option "-D variable=value" bereitzustellen. OpenSCAD platziert diese Zuweisung derzeit am Ende des Quellcodes und muss daher erlauben, dass der Wert einer Variable zu diesem Zweck geändert wird.

Werte können nicht zur Laufzeit geändert werden; alle Variablen sind effektiv Konstanten, die sich nicht ändern, sobald sie erstellt wurden. Jede Variable behält ihren zuletzt zugewiesenen Wert, in Übereinstimmung mit funktionalen Programmiersprachen. Im Gegensatz zu imperativen Sprachen wie C ist OpenSCAD keine iterative Sprache, daher ist das Konzept von "x = x + 1" nicht gültig. Der einzige Weg, wie ein Ausdruck wie dieser in OpenSCAD funktioniert, ist, wenn das "x" auf der rechten Seite aus einem übergeordneten Gültigkeitsbereich stammt, z.B. einer Argumentenliste, und der Zuweisungsvorgang ein neues "x" im aktuellen Gültigkeitsbereich erzeugt. Dieses Konzept zu verstehen, führt zum Verständnis der Schönheit von OpenSCAD.

Vor Version 2015.03 war es nicht möglich, Zuweisungen an einer anderen Stelle als auf Dateiebene und Modulebene vorzunehmen. Innerhalb einer "if/else"- oder "for"-Schleife war "assign()" erforderlich.

Seit Version 2015.03 können Variablen nun in jedem Gültigkeitsbereich zugewiesen werden. Beachte, dass Zuweisungen nur innerhalb des Gültigkeitsbereichs gültig sind, in dem sie definiert wurden – es ist immer noch nicht möglich, Werte in einen äußeren Gültigkeitsbereich "auslaufen" zu lassen. Siehe #Scope of variables für weitere Details. """

a=0;
if (a==0)
  {
 a=1; // Vor 2015.03 würde diese Zeile einen Compile Error erzeugen.
      // Seit 2015.03 kein Fehler mehr, aber der Wert a=1 ist auf den Bereich innerhalb der geschweiften Klammern {} beschränkt.
  }

"""

Nicht definierte Variable

[Bearbeiten]

Der Verweis auf eine Variable, der noch kein Wert zugewiesen wurde, löst eine Warnung aus und liefert den speziellen Wert "undef".

Es ist möglich, eine undefinierte Variable mit "is_undef(var)" zu erkennen. (Beachte, dass das einfachere "var == undef" eine Warnung auslöst.) """

 echo("Variable a is ", a);                // Variable a is undef, triggers a warning
 if (is_undef(a)) {                        // does not trigger a warning
   echo("Variable a is tested undefined"); // Variable a is tested undefined
 }

"""

Gültigkeitsbereich von Variablen

[Bearbeiten]

Wenn Operatoren wie "translate()" und "color()" mehr als eine Aktion umfassen müssen (Aktionen enden mit ";"), sind geschweifte Klammern "{}" erforderlich, um die Aktionen zu gruppieren und einen neuen, inneren Gültigkeitsbereich zu schaffen. Wenn es nur ein Semikolon gibt, sind Klammern normalerweise optional.

Jedes Paar geschweifter Klammern, das die "Kinder" eines Operators gruppiert, erzeugt einen neuen Gültigkeitsbereich innerhalb des Bereichs, in dem sie verwendet wurden. Seit 2015.03 können in diesem neuen Bereich neue Variablen erstellt werden. Variablen, die in einem äußeren Bereich erstellt wurden, können neue Werte erhalten. Diese Variablen und ihre Werte sind auch für weitere innere Bereiche verfügbar, die innerhalb dieses Bereichs erstellt werden, sind aber nicht verfügbar für alles außerhalb dieses Bereichs. Variablen haben immer noch nur den letzten Wert, der innerhalb eines Bereichs zugewiesen wurde. """

                       // scope 1
 a = 6;                // create a
 echo(a,b);            //                6, undef
 translate([5,0,0]){   // scope 1.1
   a= 10;
   b= 16;              // create b
   echo(a,b);          //              100, 16   a=10; was overridden by later a=100;
   color("blue") {     // scope 1.1.1
     echo(a,b);        //              100, 20
     cube();
     b=20;
   }                   // back to 1.1
   echo(a,b);          //              100, 16
   a=100;              // override a in 1.1
 }                     // back to 1
 echo(a,b);            //                6, undef
 color("red"){         // scope 1.2
   cube();
   echo(a,b);          //                6, undef
 }                     // back to 1
 echo(a,b);            //                6, undef
 //In diesem Beispiel sind die Bereiche 1 und 1.1 äußere Bereiche für 1.1.1, aber 1.2 ist es nicht.

""" Anonyme Bereiche werden nicht als Gültigkeitsbereiche betrachtet: """

 {
   angle = 45;
 }
 rotate(angle) square(10);

"""

For()-Schleifen sind keine Ausnahme von der Regel, dass Variablen nur einen Wert innerhalb eines Gültigkeitsbereichs haben. Für jeden Durchlauf wird eine Kopie des Schleifeninhalts erstellt. Jeder Durchlauf erhält seinen eigenen Gültigkeitsbereich, sodass alle Variablen für diesen Durchlauf eindeutige Werte haben können. Nein, du kannst immer noch nicht "a = a + 1" machen.

Variablen können nicht geändert werden

[Bearbeiten]

Die einfachste Beschreibung von OpenSCAD-Variablen ist, dass eine Zuweisung eine neue Variable im aktuellen Gültigkeitsbereich erzeugt und dass es nicht erlaubt ist, eine Variable festzulegen, die bereits im aktuellen Gültigkeitsbereich gesetzt wurde. In vielerlei Hinsicht ist es am besten, sie sich als benannte Konstanten vorzustellen, die beim Eintritt in den Bereich berechnet werden, aber es gibt einen Haken: Wenn du eine Variable zweimal im selben Bereich setzt, löst die zweite Zuweisung eine Warnung aus (die das Programm je nach Einstellung abbrechen kann). Sie ersetzt nicht den Wert der Variable – sondern sie ersetzt die ursprüngliche Zuweisung an ihrer Position in der Liste der Zuweisungen. Die ursprüngliche Zuweisung wird niemals ausgeführt.

a = 1;   // never executed
echo(a); // 2
a = 2;   // executed at the position of the original assignment
echo(a); // 2


Das ist noch nicht die ganze Geschichte. Es gibt zwei Sonderfälle, die keine Warnungen auslösen:

  • wenn die erste Zuweisung auf oberster Ebene einer "include"-Datei steht und die zweite Zuweisung in der einbindenden Datei.
  • wenn die erste Zuweisung auf oberster Ebene des Programmquellcodes steht und die zweite Zuweisung von einer "-D"-Option oder vom Customizer kommt.

Obwohl dies kontraintuitiv erscheint, erlaubt es dir, interessante Dinge zu tun: Wenn du zum Beispiel deine gemeinsamen Bibliotheksdateien so einrichtest, dass sie Standardwerte als Variablen auf ihrer obersten Ebene definieren, kannst du diese Konstanten beim Einbinden dieser Datei in deinen eigenen Code einfach "neu definieren" oder überschreiben, indem du ihnen einen neuen Wert zuweist – und andere Variablen, die auf dieser Variable basieren, basieren dann auf dem Wert aus dem Hauptprogramm.

// main.scad
include <lib.scad>
a = 2;
echo(b);
// lib.scad
a = 1;
b = a + 1;

ergibt 3.

Spezielle Variablen

[Bearbeiten]

Spezielle Variablen bieten eine alternative Möglichkeit, Argumente an Module und Funktionen zu übergeben. Alle Variablen, die mit einem "$" beginnen, sind spezielle Variablen, ähnlich wie spezielle Variablen in Lisp. Daher sind sie dynamischer als reguläre Variablen. (Weitere Details siehe Andere Sprachmerkmale)

Vektoren

[Bearbeiten]

Ein Vektor oder eine Liste ist eine Folge von null oder mehr OpenSCAD-Werten. Vektoren sind Sammlungen von numerischen oder Boolean-Werten, Variablen, Vektoren, Strings oder beliebigen Kombinationen davon. Sie können auch Ausdrücke sein, die zu einem davon ausgewertet werden. Vektoren übernehmen die Rolle von Arrays, die in vielen imperativen Sprachen vorkommen.

Ein Vektor hat eckige Klammern "[]", die null oder mehr Elemente (Elemente oder Mitglieder) umschließen, getrennt durch Kommas. Ein Vektor kann Vektoren enthalten, die wiederum Vektoren enthalten können, usw.

Beispiele """

   [1,2,3]
   [a,5,b]
   []
   [5.643]
   ["a","b","string"]
   [[1,r],[x,y,z,4,5]]
   [3, 5, [6,7], [[8,9],[10,[11,12],13], c, "string"]
   [4/3, 6*1.5, cos(60)]

""" Verwendung in OpenSCAD: """

  cube( [width,depth,height] );           // optionale Leerzeichen zur Verdeutlichung
  translate( [x,y,z] )
  polygon( [ [x0,y0],  [x1,y1],  [x2,y2] ] );

"""

Erstellung

[Bearbeiten]

Vektoren werden erstellt, indem die Liste der Elemente, getrennt durch Kommas, in eckige Klammern geschrieben wird. Variablen werden durch ihre Werte ersetzt. """

  cube([10,15,20]);
  a1 = [1,2,3];
  a2 = [4,5];
  a3 = [6,7,8,9];
  b  = [a1,a2,a3];    // [ [1,2,3], [4,5], [6,7,8,9] ]  beachte die erhöhte Verschachtelungstiefe

""" Vektoren können mithilfe einer in eckige Klammern eingeschlossenen for-Schleife initialisiert werden.

Das folgende Beispiel initialisiert den Vektor "result" mit einer Länge "n" von 10 Werten auf den Wert von "a". """ n = 10; a = 0;

result = [ for (i=[0:n-1]) a ]; echo(result); //ECHO: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] """ Das folgende Beispiel zeigt einen Vektor "result" mit einer Länge "n" von 10, der mit Werten initialisiert ist, die abwechselnd "a" oder "b" sind, je nachdem, ob die Indexposition "i" eine gerade oder ungerade Zahl ist. """ n = 10; a = 0; b = 1; result = [ for (i=[0:n-1]) (i % 2 == 0) ? a : b ]; echo(result); //ECHO: [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] """

Indizierung von Elementen innerhalb von Vektoren

[Bearbeiten]

Elemente innerhalb von Vektoren sind von 0 bis n-1 nummeriert, wobei n die von len() zurückgegebene Länge ist. Adressiere Elemente innerhalb von Vektoren mit der folgenden Notation: """

e[5]           // Element Nr. 5 (das sechste) auf der 1. Verschachtelungsebene
e[5][2]        // Element 2 von Element 5 auf der 2. Verschachtelungsebene
e[5][2][0]     // Element 0 von 2 von 5 auf der 3. Verschachtelungsebene
e[5][2][0][1]  // Element 1 von 0 von 2 von 5 auf der 4. Verschachtelungsebene

""" Beispielelemente mit Längen von len() """

e = [ [1], [], [3,4,5], "string", "x", [[10,11],[12,13,14],[[15,16],[17]]] ];  // Länge 6
Adresse        Länge  Element
e[0]          1       [1]
e[1]          0       []
e[5]          3       [ [10,11], [12,13,14], [[15,16],[17]] ]
e[5][1]       3       [ 12, 13, 14 ]
e[5][2]       2       [ [15,16], [17] ]
e[5][2][0]    2       [ 15, 16 ]
e[5][2][0][1] undef   16
e[3]          6       "string"
e[3 ][2]      1       "r"
s = [2,0,5]; a = 2;
s[a]          undef   5
e[s[a]]       3       [ [10,11], [12,13,14], [[15,16],[17]] ]

"""

String-Indizierung

[Bearbeiten]

Die Elemente (Zeichen) eines Strings können abgerufen werden: """

"string"[2]    // ergibt "r"

"""

Punktnotation-Indizierung

[Bearbeiten]

Die ersten drei Elemente eines Vektors können mit einer alternativen Punktnotation abgerufen werden: """

e.x    // äquivalent zu e[0]
e.y    // äquivalent zu e[1]
e.z    // äquivalent zu e[2]

"""

Vektor-Operatoren

[Bearbeiten]

concat

[Bearbeiten]

Vorlage:Requires

"concat()" kombiniert die Elemente von 2 oder mehr Vektoren zu einem einzigen Vektor. Die Verschachtelungsebene ändert sich nicht. """

 vector1 = [1,2,3]; vector2 = [4]; vector3 = [5,6];
 new_vector = concat(vector1, vector2, vector3); // [1,2,3,4,5,6]
 string_vector = concat("abc","def");                 // ["abc", "def"]
 one_string = str(string_vector[0],string_vector[1]); // "abcdef"

"""

"len()" ist eine Funktion, die die Länge von Vektoren oder Strings zurückgibt. Indizes von Elementen gehen von [0] bis [Länge-1].

  • Vektor
 * Gibt die Anzahl der Elemente auf dieser Ebene zurück.
 * Einzelwerte, die keine Vektoren sind, lösen einen Fehler aus.
  • String
 * Gibt die Anzahl der Zeichen in einem String zurück.

"""

 a = [1,2,3]; echo(len(a));   //  3

"""

Siehe Beispielelemente mit Längen

Matrix

[Bearbeiten]

Eine Matrix ist ein Vektor von Vektoren.

Beispiel, das eine 2D-Rotationsmatrix definiert: """

mr = [
     [cos(angle), -sin(angle)],
     [sin(angle),  cos(angle)]
    ];

"""

Objekte

[Bearbeiten]

Vorlage:Requires

Objekte speichern Sammlungen von Daten, ähnlich wie Vektoren, aber die einzelnen Mitglieder werden über String-Namen und nicht über numerische Indizes abgerufen. Sie sind analog zu JavaScript-Objekten oder Python-Dictionaries.

Erstellen eines Objekts

[Bearbeiten]

Die Funktion "object()" kann verwendet werden, um Objekte zu erstellen. "object()" verarbeitet seine Argumente von links nach rechts und fügt sie dem im Aufbau befindlichen Objekt hinzu. Sie akzeptiert drei verschiedene Stile von Argumenten, die beliebig gemischt werden können:

Die erste Form ist diese: """

   <name>=<value>

""" Diese Form ist praktisch für Fälle, in denen der Name konstant und als Identifier geeignet ist.

Die zweite Form ist diese: """

   [
       [ <name-string>, <value> ],
       ...
   ]

""" Diese Form ermöglicht berechnete Namen und Namen, die nicht als Identifier geeignet sind. Sie ermöglicht auch Listen von Mitgliedern, die aus anderen Verarbeitungen abgeleitet sind – vielleicht aus einer List Comprehension.

Die dritte Form ist diese: """

   <object>

""" Wenn ein Argument selbst ein Objekt ist, werden seine Mitglieder zum im Aufbau befindlichen Objekt hinzugefügt.

Wenn ein Mitglied mehr als einmal erwähnt wird, gewinnt die letzte Erwähnung. So kannst du ein Objekt kopieren und ein Mitglied ersetzen, indem du "object(obj, name=newvalue)" verwendest.

Du kannst ein Mitglied aus dem im Aufbau befindlichen Objekt entfernen, indem du die Listenform verwendest und nur einen Namen, aber keinen Wert angibst – z.B. "object(obj, [ [ "unwanted" ] ])".

Abrufen eines Werts aus einem Objekt

[Bearbeiten]

"""

   obj.name

""" Ruft den benannten Wert aus dem Objekt ab, für einen Namen, der konstant und syntaktisch als Identifier geeignet ist. """

   obj["name"]

""" Ruft den benannten Wert aus dem Objekt ab, für einen Namen, der ein beliebiger String-Ausdruck ist.

Beachte, dass Mitglieder mit identifier-ähnlichen Namen mit beiden Mechanismen abgerufen werden können. Die Wahl hängt vom jeweiligen Anwendungsfall ab.

Wenn das angegebene Mitglied nicht im Objekt vorhanden ist, ergibt es "undef".

Iterieren über Objekt-Mitglieder

[Bearbeiten]

"""

  for (name = obj) { ... }

""" Iteriert über die Mitglieder des Objekts in einer nicht spezifizierten Reihenfolge und setzt "name" auf den Namen jedes Mitglieds. Dann ist es typischerweise wünschenswert, auf den Wert mit "obj[name]" zuzugreifen.

Dieses Konstrukt funktioniert für flussgesteuertes "for", intersection_for() und List-Comprehension "for".

Beispiele

[Bearbeiten]

"""

   // Erstelle ein Objekt mit einigen Mitgliedern.
   o1 = object(a = 1, b = "hello", c = true);
   // Hole ein Mitglied mit einem konstanten Namen ab.
   echo(o1.b);      // "hello"
   // Hole Mitglieder mit einem vari