MyLang ist eine einfache pädagogische Programmiersprache, die von Python
, JavaScript
und C
inspiriert ist und als persönliche Herausforderung in kurzer Zeit geschrieben wurde, vor allem, um Spaß am Schreiben eines Parsers mit rekursiver Abstammung zu haben und die Welt der Interpreter zu erkunden. Erwarten Sie keine vollständige Skriptsprache mit Bibliotheken und Frameworks, die für den Produktionseinsatz bereit sind. Allerdings verfügt MyLang
nur über einen minimalen Satz integrierter Funktionen und könnte auch für praktische Zwecke verwendet werden.
MyLang ist in portablem C++17 geschrieben: Derzeit weist das Projekt keine anderen Abhängigkeiten als die Standard-C++-Bibliothek auf. Um es zu erstellen, führen Sie einfach Folgendes aus, wenn Sie GNU make
installiert haben:
$ make -j
Andernfalls übergeben Sie einfach alle .cpp-Dateien an Ihren Compiler und fügen Sie das Verzeichnis src/
zum Include-Suchpfad hinzu. Eines der schönsten Dinge daran, keine Abhängigkeiten zu haben, ist, dass für einmalige Builds kein Build-System erforderlich ist.
Übergeben Sie einfach die Option BUILD_DIR
um make
:
$ make -j BUILD_DIR=other_build_directory
Wenn Sie auch die Tests von MyLang ausführen möchten, müssen Sie für ein besseres Debugging-Erlebnis einfach mit TESTS=1 kompilieren und die Optimierungen mit OPT=0 deaktivieren:
$ make -j TESTS=1 OPT=0
Führen Sie dann alle Tests aus mit:
$ ./build/mylang -rt
Es ist erwähnenswert, dass Test-Frameworks wie GoogleTest und Boost.Test zwar unendlich viel leistungsfähiger und flexibler sind als die triviale Test-Engine, die wir in src/tests.cpp
haben, es sich jedoch um externe Abhängigkeiten handelt. Je weniger Abhängigkeiten, desto besser, oder? :-)
Der kürzeste Weg, MyLang
zu beschreiben, ist: eine C-ähnliche dynamische Python-Sprache . Der wahrscheinlich schnellste Weg, diese Sprache zu lernen, besteht darin, sich die Skripte im Verzeichnis samples/
anzusehen und gleichzeitig einen Blick auf die kurze Dokumentation unten zu werfen.
MyLang
ist eine dynamische Ententypisierungssprache wie Python
. Wenn Sie Python
kennen und bereit sind, { }
-Klammern zu verwenden, können Sie es automatisch verwenden. Keine Überraschungen. Zeichenfolgen sind wie in Python
unveränderlich, Arrays können wie in Python
mit [ ]
definiert werden und Wörterbücher können ebenfalls mit { }
definiert werden. Die Sprache unterstützt auch Array-Slices mit derselben [start:end]
-Syntax, die von Python
verwendet wird.
Allerdings unterscheidet sich MyLang
in mehreren Aspekten von Python
und anderen Skriptsprachen:
Es gibt Unterstützung für Analysezeitkonstanten, die mit const
deklariert werden.
Alle Variablen müssen mit var
deklariert werden.
Variablen haben einen Gültigkeitsbereich wie in C
Shadowing wird unterstützt, wenn eine Variable explizit mit var
in einem verschachtelten Block neu deklariert wird.
Alle Ausdrucksanweisungen müssen mit ;
wie in C
, C++
und Java
.
Es gibt die Schlüsselwörter true
und false
, aber keinen boolean
Typ. Wie in C ist 0
falsch, alles andere ist true
. Allerdings haben Strings, Arrays und Wörterbücher einen booleschen Wert, genau wie in Python
(z. B. wird ein leeres Array false
betrachtet). Das true
Builtin ist nur ein Alias für die Ganzzahl 1
.
Der Zuweisungsoperator =
kann wie in C
innerhalb von Ausdrücken verwendet werden, aber aufgrund der Array-Erweiterungsfunktion gibt es keinen Kommaoperator.
MyLang unterstützt sowohl die klassische for
Schleife als auch eine explizite foreach
Schleife.
MyLang unterstützt derzeit keine benutzerdefinierten Typen. Allerdings unterstützen Wörterbücher einen schönen syntaktischen Zucker: Zusätzlich zur Hauptsyntax d["key"]
wird für String-Schlüssel auch die Syntax d.key
unterstützt.
Variablen werden immer mit var
deklariert und leben in dem Bereich, in dem sie deklariert wurden (während sie in verschachtelten Bereichen sichtbar sind). Zum Beispiel:
# Variable declared in the global scope
var a = 42 ;
{
var b = 12 ;
# Here we can see both `a` and `b`
print ( a , b ) ;
}
# But here we cannot see `b` .
Es ist möglich, mehrere Variablen mit der folgenden bekannten Syntax zu deklarieren:
var a , b , c ;
Aber es gibt eine Einschränkung, wahrscheinlich die einzige „überraschende“ Funktion von MyLang
: Das Initialisieren von Variablen funktioniert nicht wie in C. Betrachten Sie die folgende Aussage:
var a , b , c = 42 ;
Anstatt nur a
und b
zu deklarieren und mit c
auf 42 zu initialisieren, initialisieren wir in diesem Fall alle drei Variablen mit dem Wert 42. Um jede Variable mit einem anderen Wert zu initialisieren, verwenden Sie die Array-Erweiterungssyntax:
var a , b , c = [ 1 , 2 , 3 ] ;
Konstanten werden auf ähnliche Weise wie Variablen deklariert, können jedoch nicht in verschachtelten Bereichen gespiegelt werden. Zum Beispiel:
const c = 42 ;
{
# That's not allowed
const c = 1 ;
# That's not allowed as well
var c = 99 ;
}
In MyLang
werden Konstanten zur Parse-Zeit ausgewertet, ähnlich wie die constexpr- Deklarationen von C++
(dort sprechen wir jedoch über die Kompilierungszeit ). Beim Initialisieren eines const
kann zusätzlich zum gesamten Satz von const- Builts jede Art von Literal verwendet werden. Zum Beispiel:
const val = sum ( [ 1 , 2 , 3 ] ) ;
const x = " hello " + " world " + " " + join ( [ " a " , " b " , " c " ] , " , " ) ;
Um zu verstehen, wie genau eine Konstante ausgewertet wurde, führen Sie den Interpreter mit der Option -s
aus, um den abstrakten Syntaxbaum vor der Ausführung des Skripts zu sichern. Für das obige Beispiel:
$ cat > t
const val = sum([1,2,3]);
const x = "hello" + " world" + " " + join(["a","b","c"], ",");
$ ./build/mylang t
$ ./build/mylang -s t
Syntax tree
--------------------------
Block(
)
--------------------------
Überrascht? Nun, andere Konstanten als Arrays und Wörterbücher werden nicht einmal als Variablen instanziiert. Sie existieren zur Laufzeit einfach nicht. Fügen wir eine Anweisung mit x
hinzu:
$ cat >> t
print(x);
$ cat t
const val = sum([1,2,3]);
const x = "hello" + " world" + " " + join(["a","b","c"], ",");
print(x);
$ ./build/mylang -s t
Syntax tree
--------------------------
Block(
CallExpr(
Id("print")
ExprList(
"hello world a,b,c"
)
)
)
--------------------------
hello world a,b,c
Jetzt sollte alles einen Sinn ergeben. Fast das Gleiche passiert mit Arrays und Wörterbüchern, mit der Ausnahme, dass letztere ebenfalls zur Laufzeit instanziiert werden, um zu vermeiden, dass es überall potenziell große Literale gibt. Betrachten Sie das folgende Beispiel:
$ ./build/mylang -s -e 'const ar=range(4); const s=ar[2:]; print(ar, s, s[0]);'
Syntax tree
--------------------------
Block(
ConstDecl(
Id("ar")
Op '='
LiteralArray(
Int(0)
Int(1)
Int(2)
Int(3)
)
)
ConstDecl(
Id("s")
Op '='
LiteralArray(
Int(2)
Int(3)
)
)
CallExpr(
Id("print")
ExprList(
Id("ar")
Id("s")
Int(2)
)
)
)
--------------------------
[0, 1, 2, 3] [2, 3] 2
Wie Sie sehen können, wurde die Slice- Operation zur Analysezeit ausgewertet, während die Konstante s
initialisiert wurde, aber beide Arrays sind auch zur Laufzeit vorhanden. Stattdessen werden die Indexoperationen für konstante Ausdrücke in Literale konvertiert. Das scheint ein guter Kompromiss für die Leistung zu sein: Kleine Werte wie Ganzzahlen, Gleitkommazahlen und Zeichenfolgen werden während der const-Auswertung in Literale konvertiert, während Arrays und Wörterbücher (möglicherweise groß) zur Laufzeit als schreibgeschützte Symbole belassen werden, dies aber weiterhin zulassen Einige Operationen auf ihnen (wie [index]
und len(arr)
) müssen konstant ausgewertet werden.
MyLang
unterstützt derzeit nur die folgenden (eingebauten) Typen:
None Der Typ von none
, das Äquivalent von Pythons None
. Variablen, die gerade deklariert wurden, ohne dass ihnen ein Wert zugewiesen wurde, haben den Wert none
(z. B. var x;
). Das Gleiche gilt für Funktionen, die keinen Rückgabewert haben. Außerdem wird es im Fehlerfall von integrierten Funktionen wie find()
als Sonderwert verwendet.
Ganzzahl Eine Ganzzahl mit Zeigergröße und Vorzeichen (z. B. 3
).
Float Eine Gleitkommazahl (z. B. 1.23
). Intern ist es ein langes Double.
String Ein String wie „Hallo“. Strings sind unveränderlich und unterstützen Slices (z. B. s[3:5]
oder s[3:]
oder s[-2:]
mit derselben Bedeutung wie in Python
).
Array Ein veränderlicher Typ für Arrays und Tupel (z. B. [1,2,3]
). Es kann Elemente unterschiedlichen Typs enthalten und unterstützt beschreibbare Slices. Array-Slices verhalten sich wie Kopien, nutzen aber unter der Haube Copy-on-Write-Techniken.
Wörterbuchwörterbücher sind Hash-Maps, die mit der Python
-Syntax definiert werden: {"a": 3, "b": 4}
. Auf Elemente wird mit der bekannten Syntax d["key-string"]
oder d[23]
zugegriffen, sie können mit find()
gesucht und mit erase()
gelöscht werden. Derzeit können nur Zeichenfolgen, Ganzzahlen und Gleitkommazahlen als Schlüssel eines Wörterbuchs verwendet werden. Vorteile : Auf bezeichnerähnliche Zeichenfolgenschlüssel kann auch mit der Syntax „member of“ zugegriffen werden: d.key
.
Funktion Sowohl eigenständige Funktionen als auch Lambdas haben denselben Objekttyp und können wie jedes andere Objekt weitergegeben werden (siehe unten). Aber nur Lambdas können eine Capture-Liste haben. Reguläre Funktionen können während der Konstantenauswertung nicht ausgeführt werden, pure
Funktionen hingegen schon. Reine Funktionen können nur Konstanten und ihre Argumente sehen.
Ausnahme Der einzige Objekttyp, der geworfen werden kann. Um sie zu erstellen, verwenden Sie die integrierte exception()
oder deren Verknüpfung ex()
.
Bedingte Anweisungen funktionieren genau wie in C
Die Syntax lautet:
if ( conditionExpr ) {
# Then block
} else {
# Else block
}
Und die { }
-Klammern können wie in C
im Fall von Einzelanweisungsblöcken weggelassen werden. conditionExpr
kann ein beliebiger Ausdruck sein, zum Beispiel: (a=3)+b >= c && !d
.
Wenn conditionExpr
ein Ausdruck ist, der als Konstante ausgewertet werden kann, wird die gesamte if-Anweisung durch den True-Zweig ersetzt, während der False-Zweig verworfen wird. Betrachten Sie beispielsweise das folgende Skript:
const a = 3 ;
const b = 4 ;
if ( a < b ) {
print ( " yes " ) ;
} else {
print ( " no " ) ;
}
Es gibt nicht nur immer „Ja“ aus, sondern es muss vorher auch nichts überprüft werden. Überprüfen Sie den abstrakten Syntaxbaum:
$ ./build/mylang -s t
Syntax tree
--------------------------
Block(
Block(
CallExpr(
Id("print")
ExprList(
"yes"
)
)
)
)
--------------------------
yes
MyLang
unterstützt die klassischen while
und for
Schleifen.
while ( condition ) {
# body
if ( something )
break ;
if ( something_else )
continue ;
}
for ( var i = 0 ; i < 10 ; i += 1 ) {
# body
if ( something )
break ;
if ( something_else )
continue ;
}
Hier können die geschweiften Klammern { }
wie im obigen Fall weggelassen werden. Es gibt nur wenige Unterschiede zu C
die es wert sind, erwähnt zu werden:
Die Operatoren ++
und --
existieren in MyLang
derzeit nicht.
Um mehrere Variablen zu deklarieren, verwenden Sie die folgende Syntax: var a, b = [3,4];
oder einfach var a,b,c,d = 0;
wenn Sie möchten, dass alle Variablen denselben Anfangswert haben.
Um den Wert mehrerer Variablen zu erhöhen, verwenden Sie die Syntax: a, b += [1, 2]
. In den äußerst seltenen und komplexen Fällen, in denen wir in der Inkrementanweisung der for-Schleife jeder Variablen eine neue Variable mit unterschiedlichen Ausdrücken zuweisen müssen, nutzen Sie die Erweiterungssyntax bei der Zuweisung: i, j = [i+2, my_next(i, j*3)]
.
MyLang
unterstützt foreach
Schleifen mit einer ziemlich vertrauten Syntax:
var arr = [ 1 , 2 , 3 ] ;
foreach ( var e in arr ) {
print ( " elem: " , e ) ;
}
Foreach-Schleifen können für Arrays, Strings und Wörterbücher verwendet werden. Das Durchlaufen jedes <key, value>
-Paares in einem Wörterbuch ist beispielsweise so einfach:
var d = { " a " : 3 , " b " : 10 , " c " : 42 } ;
foreach ( var k , v in d ) {
print ( k + " => " + str ( v ) ) ;
}
Um nur jeden Schlüssel zu durchlaufen, verwenden Sie stattdessen einfach var k in d
.
MyLang
unterstützt auch die Aufzählung in foreach-Schleifen. Sehen Sie sich das folgende Beispiel an:
var arr = [ " a " , " b " , " c " ] ;
foreach ( var i , elem in indexed arr ) {
print ( " elem[ " + str ( i ) + " ] = " + elem ) ;
}
Mit anderen Worten: Wenn vor dem Namen des Containers das Schlüsselwort indexed
steht, wird der ersten Variablen bei jeder Iteration eine fortlaufende Nummer zugewiesen.
Beim Durchlaufen eines Arrays kleiner Arrays fester Größe (denken Sie an Tupel) ist es möglich, diese „Tupel“ direkt in der foreach-Schleife zu erweitern:
var arr = [
[ " hello " , 42 ] ,
[ " world " , 11 ]
] ;
foreach ( var name , value in arr ) {
print ( name , value ) ;
}
# This is a shortcut for :
foreach ( var elem in arr ) {
# regular array expansion
var name , value = elem ;
print ( name , value ) ;
}
# Which is a shortcut for :
foreach ( var elem in arr ) {
var name = elem [ 0 ] ;
var value = elem [ 1 ] ;
print ( name , value ) ;
}
Das Deklarieren einer Funktion ist einfach wie folgt:
func add ( x , y ) {
return x + y ;
}
Es werden aber auch mehrere Verknüpfungen unterstützt. Im Fall von Single-Statement-Funktionen wie der oben genannten kann beispielsweise die folgende Syntax verwendet werden:
func add ( x , y ) => x + y ;
Auch wenn es eine gute Praxis ist, immer ()
für Funktionen ohne Parameter zu schreiben, sind sie in dieser Sprache eigentlich optional:
func do_something { print ( " hello " ) ; }
Funktionen werden in MyLang
als reguläre Symbole behandelt und es gibt in dieser Sprache keine wesentlichen Unterschiede zwischen eigenständigen Funktionen und Lambdas. Beispielsweise können wir die add
-Funktion (oben) folgendermaßen als Lambda deklarieren:
var add = func ( x , y ) => x + y ;
Hinweis: Beim Erstellen von Funktionsobjekten in Ausdrücken dürfen wir ihnen keinen Namen zuweisen.
Lambdas unterstützen auch eine Erfassungsliste, implizite Erfassungen werden jedoch aus Gründen der Klarheit nicht unterstützt. Natürlich können Lambdas wie jedes andere Objekt zurückgegeben werden. Zum Beispiel:
func create_adder_func ( val ) =>
func [ val ] ( x ) => x + val ;
var f = create_adder_func ( 5 ) ;
print ( f ( 1 ) ) ; # Will print 6
print ( f ( 10 ) ) ; # Will print 15
Lambdas mit Captures haben einen state , wie jeder erwarten würde. Betrachten Sie das folgende Skript:
func gen_counter ( val ) => func [ val ] {
val += 1 ;
return val ;
} ;
var c1 = gen_counter ( 5 ) ;
for ( var i = 0 ; i < 3 ; i += 1 )
print ( " c1: " , c1 ( ) ) ;
# Clone the `c1` lambda object as `c2` : now it will have
# its own state , indipendent from `c1` .
var c2 = clone ( c1 ) ;
print ( ) ;
for ( var i = 0 ; i < 3 ; i += 1 )
print ( " c2: " , c2 ( ) ) ;
print ( ) ;
for ( var i = 0 ; i < 3 ; i += 1 )
print ( " c1: " , c1 ( ) ) ;
Es generiert die Ausgabe:
c1: 6
c1: 7
c1: 8
c2: 9
c2: 10
c2: 11
c1: 9
c1: 10
c1: 11
Reguläre benutzerdefinierte Funktionsobjekte (einschließlich Lambdas) gelten nicht const
und können daher während der const-Auswertung nicht ausgeführt werden. Das ist eine ziemlich starke Einschränkung. Betrachten Sie das folgende Beispiel:
const people = [
[ " jack " , 3 ] ,
[ " alice " , 11 ] ,
[ " mario " , 42 ] ,
[ " bob " , 38 ]
] ;
const sorted_people = sort ( people , func ( a , y ) => a [ 0 ] < b [ 0 ] ) ;
In diesem Fall kann das Skript das const-Array sorted_people
nicht erstellen. Da wir ein Funktionsobjekt an die integrierte Funktion const sort()
übergeben haben, erhalten wir einen ExpressionIsNotConstEx
Fehler. Sicher, wenn sorted_people
als var
deklariert würde, würde das Skript ausgeführt, aber das Array wäre nicht mehr const und wir könnten von keiner Analysezeitoptimierung profitieren. Daher kann die eingebaute Funktion sort()
zwar während der Const-Auswertung aufgerufen werden, wenn sie jedoch über einen benutzerdefinierten Parameter compare func
verfügt, ist dies nicht mehr möglich.
Um die gerade beschriebene Einschränkung zu überwinden, verfügt MyLang
über eine spezielle Syntax für reine Funktionen. Wenn eine Funktion mit dem Schlüsselwort pure
vor func
deklariert wird, behandelt der Interpreter sie auf besondere Weise: Sie kann jederzeit aufgerufen werden, sowohl während der Const-Auswertung als auch zur Laufzeit , aber die Funktion kann keine globalen Variablen sehen oder etwas erfassen: Sie kann nur verwenden Konstanten und der Wert ihrer Parameter: Genau das brauchen wir bei der const-Auswertung. Um beispielsweise sorted_people
während der const-Auswertung zu generieren, reicht es aus, Folgendes zu schreiben:
const sorted_people = sort ( people , pure func ( a , b ) => a [ 0 ] < b [ 0 ] ) ;
Reine Funktionen können als eigenständige Funktionen definiert und auch mit nicht konstanten Parametern verwendet werden . Wenn eine Funktion als pure
deklariert werden kann, sollte sie daher immer so deklariert werden. Betrachten Sie beispielsweise das folgende Skript:
pure func add2 ( x ) => x + 2 ;
var non_const = 25 ;
print ( add2 ( non_const ) ) ;
print ( add2 ( 5 ) ) ;
Der abstrakte Syntaxbaum, den die Sprach-Engine zur Laufzeit verwendet, lautet:
$ ./build/mylang -s t
Syntax tree
--------------------------
Block(
FuncDeclStmt(
Id("add2")
<NoCaptures>
IdList(
Id("x")
)
Expr04(
Id("x")
Op '+'
Int(2)
)
)
VarDecl(
Id("non_const")
Op '='
Int(25)
)
CallExpr(
Id("print")
ExprList(
CallExpr(
Id("add2")
ExprList(
Id("non_const")
)
)
)
)
CallExpr(
Id("print")
ExprList(
Int(7)
)
)
)
--------------------------
27
7
Wie Sie sehen können, erfolgt im ersten Fall ein tatsächlicher Funktionsaufruf, da non_const
keine Konstante ist, während es im zweiten Fall AS IF ist, haben wir eine literale Ganzzahl an print()
übergeben.
Wie bei anderen Konstrukten verfügt MyLang
über eine Ausnahmebehandlung ähnlich der von Python
, verwendet jedoch eine ähnliche Syntax wie C++
. Das Grundkonstrukt ist die try-catch
-Anweisung. Sehen wir uns ein Beispiel an:
try {
var input_str = " blah " ;
var a = int ( input_str ) ;
} catch ( TypeErrorEx ) {
print ( " Cannot convert the string to integer " ) ;
}
Hinweis: Wenn durch konstante Ausdrücke (z. B. int("blah")
) eine Ausnahme generiert wird, wird der Fehler während der const-Auswertung direkt gemeldet, wobei jegliche Ausnahmebehandlungslogik umgangen wird. Der Grund dafür ist die Durchsetzung eines frühzeitigen Scheiterns .
Es sind auch mehrere catch
-Anweisungen zulässig:
try {
# body
} catch ( TypeErrorEx ) {
# error handling
} catch ( DivisionByZeroEx ) {
# error handling
}
Und falls mehrere Ausnahmen mit demselben Code behandelt werden können, kann auch eine kürzere Syntax verwendet werden:
try {
# body
} catch ( TypeErrorEx , DivisionByZeroEx as e ) {
# error handling
print ( e ) ;
} catch ( OutOfBoundsEx ) {
# error handling
}
Ausnahmen können Daten enthalten, aber derzeit enthält keine der integrierten Ausnahmen Daten. Die Liste der integrierten Laufzeitausnahmen , die mit try-catch
-Blöcken abgefangen werden können, ist:
Andere Ausnahmen wie SyntaxErrorEx
können stattdessen nicht abgefangen werden. In MyLang
ist es auch möglich, JEDE Ausnahme mithilfe eines Catch-Anything-Blocks abzufangen:
try {
# body
} catch {
# Something went wrong .
}
Diese Sprache unterstützt derzeit keine benutzerdefinierten Typen. Daher ist es nicht möglich, beliebige Objekte wie in einigen anderen Sprachen zu werfen . Um eine Ausnahme auszulösen, ist es notwendig, die spezielle integrierte Funktion exception()
oder deren Verknüpfung ex()
zu verwenden. Betrachten Sie das folgende Beispiel:
try {
throw ex ( " MyError " , 1234 ) ;
} catch ( MyError as e ) {
print ( " Got MyError, data: " , exdata ( e ) ) ;
}
Wie die Intuition vermuten lässt, haben wir mit ex()
ein Ausnahmeobjekt namens MyError
erstellt und später ausgelöst, dessen Nutzdaten 1234
sind. Später haben wir im catch
-Block die Ausnahme abgefangen und die Nutzdaten mithilfe der integrierten Funktion exdata()
extrahiert.
Falls eine bestimmte Ausnahme keine Payload benötigt, ist es möglich, das Ergebnis von ex()
einfach in einer Variablen zu speichern und es später mit einer wahrscheinlich angenehmeren Syntax auszulösen:
var MyError = ex ( " MyError " ) ;
throw MyError ;
MyLang
unterstützt das erneute Auslösen einer Ausnahme im Hauptteil von Catch-Anweisungen mithilfe des dedizierten Schlüsselworts rethrow
:
try {
do_something ( ) ;
} catch {
print ( " Something went wrong!! " ) ;
rethrow ;
}
In einigen Fällen kann es erforderlich sein, nach der Ausführung eines Codeblocks, der möglicherweise eine Ausnahme auslöst, eine Bereinigung durchzuführen. Für diese Fälle unterstützt MyLang
die bekannte finally
Klausel, die genau wie in C#
funktioniert:
try {
step1_might_throw ( ) ;
step2_might_throw ( ) ;
step3_might_throw ( ) ;
step4_might_throw ( ) ;
} catch ( TypeErrorEx ) {
# some error handling
} finally {
# clean - up
}
Es ist erwähnenswert, dass auch try-finally
Konstrukte (ohne catch
Klausel) zulässig sind.
Die folgenden integrierten Funktionen werden während der Analysezeit ausgewertet, wenn ihnen konstante Argumente übergeben werden.
defined(symbol)
Überprüfen Sie, ob symbol
definiert ist. Gibt 1 zurück, wenn das Symbol definiert ist, andernfalls 0.
len(container)
Gibt die Anzahl der Elemente im angegebenen Container zurück.
str(value, [decimal_digits])
Konvertieren Sie den angegebenen Wert in eine Zeichenfolge. Wenn value
eine Gleitkommazahl ist, gibt der 2. Parameter die gewünschte Anzahl von Dezimalstellen in der Ausgabezeichenfolge an.
int(value)
Konvertieren Sie die angegebene Zeichenfolge in eine Ganzzahl. Wenn der Wert ein Float-Wert ist, wird er verkürzt. Wenn der Wert eine Zeichenfolge ist, wird er analysiert und nach Möglichkeit in eine Ganzzahl konvertiert. Wenn der Wert bereits eine Ganzzahl ist, wird er unverändert zurückgegeben.
float(value)
Konvertieren Sie den angegebenen Wert in Float. Wenn der Wert eine Ganzzahl ist, wird er in eine Gleitkommazahl umgewandelt. Wenn es sich bei dem Wert um eine Zeichenfolge handelt, wird er analysiert und nach Möglichkeit in eine Gleitkommazahl konvertiert. Wenn der Wert bereits ein Float-Wert ist, wird er unverändert zurückgegeben.
clone(obj)
Klonen Sie das angegebene Objekt. Nützlich für nicht triviale Objekte wie Arrays, Wörterbücher und Lambda mit Captures.
type(value)
Gibt den Namen des Typs des angegebenen Werts in String-Form zurück. Nützlich zum Debuggen.
hash(value)
Gibt den Hash-Wert zurück, der von Wörterbüchern intern verwendet wird, wenn value
als Schlüssel verwendet wird. Derzeit unterstützen nur Ganzzahlen, Gleitkommazahlen und Zeichenfolgen hash()
.
array(N)
Gibt ein Array mit none
zurück