# Das ist ein Kommentar# Alles ist ein Objektnil.class# => Nil100.class# => Int32true.class# => Bool# Falschwerte sind: nil, false und Nullpointer!nil# => true : Bool!false# => true : Bool!0# => false : Bool# Integer1.class# => Int32# Fünf vorzeichenbehaftete Ganzzahlen1_i8.class# => Int81_i16.class# => Int161_i32.class# => Int321_i64.class# => Int641_i128.class# => Int128# Fünf vorzeichenlose Ganzzahlen1_u8.class# => UInt81_u16.class# => UInt161_u32.class# => UInt321_u64.class# => UInt641_u128.class# => UInt1282147483648.class# => Int649223372036854775808.class# => UInt64# Binäre Zahlen0b1101# => 13 : Int32# Oktalzahlen0o123# => 83 : Int32# Hexadezimalzahlen0xFE012D# => 16646445 : Int320xfe012d# => 16646445 : Int32# Gleitkommazahlen (floats)1.0.class# => Float64# Es gibt zwei Typen von Gleitkommazahlen1.0_f32.class# => Float321_f32.class# => Float321e10.class# => Float641.5e10.class# => Float641.5e-7.class# => Float64# Chars (einzelne Zeichen)'a'.class# => Char# Oktale Schreibweise'\101'# => 'A' : Char# Unicode Schreibweise'\u0041'# => 'A' : Char# Strings (Zeichenketten)"s".class# => String# Strings sind unveränderlichs="hello, "# => "hello, " : Strings.object_id# => 1234667712 : UInt64s+="Crystal"# => "hello, Crystal" : Strings.object_id# => 142528472 : UInt64# Interpolation wird unterstützt"sum = #{1+2}"# => "sum = 3" : String# Mehrzeilige Strings" Dies ist ein
mehrzeiliger String."# String mit doppeltem Anführungszeichen%(hello "world")# => "hello \"world\""# Symbole# Unveränderbare, wiederverwendbare Konstanten, welche intern als Int32 Integer# Werte repräsentiert werden.# Symbole werden oft anstelle von Strings verwendet, um bestimmte Werte zu bestimmen.:symbol.class# => Symbolsentence=:question?# :"question?" : Symbolsentence=:question?# => true : Boolsentence=:exclamation!# => false : Boolsentence="question?"# => false : Bool# Arrays[1,2,3].class# => Array(Int32)[1,"hello",'x'].class# => Array(Int32 | String | Char)# Leere Arrays sollten einen Typen definieren[]# => Syntaxfehler: für leere Arrays,# verwende `[] of ElementType`[]ofInt32# => [] : Array(Int32)Array(Int32).new# => [] : Array(Int32)# Arrays können indiziert werdenarray=[1,2,3,4,5]# => [1, 2, 3, 4, 5] : Array(Int32)array[0]# => 1 : Int32array[10]# führt zu einem IndexErrorarray[-6]# führt zu einem IndexErrorarray[10]?# => nil : (Int32 | Nil)array[-6]?# => nil : (Int32 | Nil)# Starte am Ende des Arraysarray[-1]# => 5# Mit einem Startindex und einer Längearray[2,4]# => [3, 4, 5]# oder mit einem Bereicharray[1..3]# => [2, 3, 4]# Füge etwas zu einem Array hinzuarray<<6# => [1, 2, 3, 4, 5, 6]# Entferne Einträge am Ende des Arraysarray.pop# => 6array# => [1, 2, 3, 4, 5]# Entferne ersten Eintrag im Arrayarray.shift# => 1array# => [2, 3, 4, 5]# Überprüfe, ob ein Element in einem Array existiertarray.includes?3# => true# Spezielle Syntax für String-Arrays und Symbol-Arrays%w(one two three)# => ["one", "two", "three"] : Array(String)%i(one two three)# 0> [:one, :two, :three] : Array(Symbol)# Es gibt auch für andere Arrays eine spezielle Syntax, wenn die Methoden# `.new` und `#<<` definiert werden.set=Set{1,2,3}# => [1, 2, 3]set.class# => Set(Int32)# Das obere ist äquivalent zu:set=Set(typeof(1,2,3)).newset<<1set<<2set<<3# Hashes{1=>2,3=>4}.class# => Hash(Int32, Int32){1=>2,'a'=>3}.class# => Hash (Int32 | Char, Int32)# Leere Hashes sollten einen Typen spezifizieren{}# Syntaxfehler{}ofInt32=>Int32# {}Hash(Int32,Int32).new# {}# Hashes können schnell mit dem Key nachgeschaut werdenhash={"color"=>"green","number"=>5}hash["color"]# => "green"hash["no_such_key"]# => Fehlender hash key: "no_such_key" (KeyError)hash["no_such_key"]?# => nil# Überprüfe die Existenz eines Hashkeyshash.has_key?"color"# => true# Spezielle Schreibweise für Symbol- und Stringkeys{key1:'a',key2:'b'}# {:key1 => 'a', :key2 => 'b'} {"key1":'a',"key2":'b'}# {"key1" => 'a', "key2" => 'b'}# Die spezielle Syntax für Hash-Literale gibt es auch für andere Typen, sofern# diese die Methoden `.new` und `#[]=` Methoden definieren.classMyTypedef[]=(key,value)puts"do stuff"endendMyType{"foo"=>"bar"}# Das obere ist äquivalent zu:tmp=MyType.newtmp["foo"]="bar"tmp# Ranges (Bereiche)1..10# => Range(Int32, Int32)Range.new(1,10).class# => Range(Int32, Int32)# Ranges können inklusiv oder exklusiv sein.(3..5).to_a# => [3, 4, 5](3...5).to_a# => [3, 4]# Überprüfe, ob ein Range einen Wert enthält oder nicht.(1..8).includes?2# => true# Tupel sind unveränderliche, Stack-zugewiese Folgen von Werten mit fester # Größe und möglicherweise unterschiedlichen Typen{1,"hello",'x'}.class# => Tuple(Int32, String, Char)# Erhalte den Wert eines Tupels über den Indextuple={:key1,:key2}tuple[1]# => :key2tuple[2]# syntax error: Index out of bound# Können auf mehrere Variablen erweitert werdena,b,c={:a,'b',"c"}a# => :ab# => 'b'c# => "c"# Procs repräsentieren ein Funktionspointer mit einem optionalen Kontext.# Normalerweise wird ein Proc mit einem proc-Literal erstellt.proc=->(x:Int32){x.to_s}proc.class# => Print(Int32, String)# Außerdem kann man auch mit der Methode `new` ein Proc erstellen.Proc(Int32,String).new{|x|x.to_s}# Rufe ein Proc auf mit der Methode `call`proc.call10# => "10"# Kontrollstatementsiftrue"if statement"elsiffalse"else-f, optional"else"else, auch optional"endputs"if as a suffix"iftrue# => if as a suffix# If als Ausdrucka=if2>13else4enda# => 3# Bedingter ternärer Ausdrucka=1>2?3:4# => 4# Case-Statementcmd="move"action=casecmdwhen"create""Creating..."when"copy""Copying..."when"move""Moving..."when"delete""Deleting..."endaction# => "Moving..."# Schleifenindex=0whileindex<=3puts"Index: #{index}"index+=1end# Index: 0# Index: 1# Index: 2# Index: 3index=0untilindex>3puts"Index: #{index}"index+=1end# Index: 0# Index: 1# Index: 2# Index: 3# Der bevorzugte Weg, ist `each` zu verwenden.(1..3).eachdo|index|puts"Index: #{index}"end# Index: 1# Index: 2# Index: 3# Der Typ der Variablen hängt vom Typen innerhalb der Kontrollanweisung abifa<3a="hello"elsea=trueendtypeofa# => (Bool | String)ifa&&b# Hier wird garantiert, dass weder a noch b vom Typ Nil sindendifa.is_a?Stringa.class# => Stringend# Funktionendefdouble(x)x*2end# Funktionen geben implizit den Wert der letzten Anweisung zurück# Dies ist auch bei anderen Blöcken der Fall.double(2)# => 4# Klammern müssen nicht gesetzt werden, wenn der Aufruf eindeutig istdouble3# => 6doubledouble3# => 12defsum(x,y)x+yend# Funktionsargumente werden mit einem Komma separiert.sum3,4# => 7sumsum(3,4),5# => 12# yield# Alle Methoden haben einen impliziten, optionalen Blockparameter.# Dieser kann mit dem Schlüsselwort `yield` aufgerufen werden.defsurroundputs'{'yieldputs'}'endsurround{puts"Hallo Welt"}# {# Hallo Welt # }# Du kannst ein Block einer Funktion übergeben.# "&" kennzeichnet eine Referenz zu einem übergebenen Blockdefguests(&block)block.call"some_argument"end# Du kannst eine Liste von Argumenten mitgeben, welche zu einem Array# umgewandelt werden.# Hierfür ist der Splat-Operator ("*")defguests(*array)array.each{|guest|putsguest}end# Wenn eine Methode ein Array zurückgibt, kann destrukturiende Zuordnung# verwendet werden.deffoods["pancake","sandwich","quesadilla"]endbreakfast,lunch,dinner=foodsbreakfast# => "pancake"dinner# => "quesadilla"# Gemäß der Konvention enden alle Methoden, welchen einen Boolean zurückgeben# mit einem Fragezeichen.5.even?# false5.odd?# true# Und wenn eine Methode mit einem Ausrufezeichen endet, macht sie etwas# destruktives. Zum Beispiel wird der Aufrufer verändert. Einige Methoden haben# eine !-Version, um eine Änderung zu machen und eine Nicht-!-Version, welche# lediglich eine neue veränderte Version zurückgibt.company_name="Dunder Mifflin"company_name.gsub"Dunder","Donald"# => "Donald Mifflin"company_name# => "Dunder Mifflin"company_name.gsub!"Dunder","Donald"company_name# => "Donald Mifflin"# definiere eine Klasse mit dem Schlüsselwort `class`.classHuman# eine Klassenvariable. Diese wird mit allen Instanzen dieser Klasse geteilt.@@species="H. sapiens"# type of name is String@name:String# Grundlegender Intialisierer# Weise das Argument der Instanz-Variable "name" zu# Wenn kein Alter angegeben wird, wird der Default (hier 0) genommen.definitialize(@name,@age=0)end# Einfache Setter-Methodedefname=(name)@name=nameend# einfache Getter-Methodedefname@nameend# Die obere Funktionalität kann mit der property-Methode gekapselt werden:property:name# Getter/Setter-Methoden können auch individuell erstellt werden:getter:namesetter:name# eine Klassenmethode verwendet `self` um sich von Instanzmethoden zu # unterscheiden. Diese kann lediglich von einer Klasse aufgerufen werden,# nicht von einer Instanz.defself.say(msg)putsmsgenddefspecies@@speciesendend# Eine Klasse instanziierenjim=Human.new("Jim Halpert")dwight=Human.new("Dwight K. Schrute")# Lass uns ein paar Methoden aufrufenjim.species# => "H. sapiens"jim.name# => "Jim Halpert"jim.name="Jim Halpert II"# => "Jim Halpert II"jim.name# => "Jim Halpert II"dwight.species# => "H. sapiens"dwight.name# => "Dwight K. Schrute"# Rufe die Klassenmethode aufHuman.say("Hi")# => gibt Hi aus und gibt `nil` zurück# Variablen, welche mit @ starten, sind im Scope der InstanzclassTestClass@var="Ich bin eine Instanzvariable"end# Variablen, welche mit @@ starten, sind im Scope der KlasseclassTestClass@@var="Ich bin eine Klassenvariable"end# Variablen, welche mit einem Großbuchstaben starten, sind Konstanten.Var="Ich bin eine Konstante"Var="Ich kann nicht aktualisiert werden."# Die Konstante Var wurde bereits# initialisiert.# In Crystal ist Class auch ein Objekt. Dadurch können Klassen Instanzvariablen# haben. Klassenvariablen werden mit der Klasse und allen Subklassen geteilt.# BasisklasseclassHuman@@foo=0defself.foo@@fooenddefself.foo=(value)@@foo=valueendend# abgeleitete KlasseclassWorker<HumanendHuman.foo# => 0Worker.foo# => 0Human.foo=2# => 2Worker.foo# => 0Worker.foo=3# => 3Human.foo# => 2Worker.foo# => 3moduleModuleExampledeffoo"foo"endend# Wenn ein Modul mit include eingeschlossen wird, so werden die Methoden an die# Instanzen gebunden.# Wenn eine Klasse mit einem Modul erweitert wird, so werden die Methoden an die# Klasse selbst gebunden.classPersonincludeModuleExampleendclassBookextendModuleExampleendPerson.foo# => undefinierte Methode 'foo' für Person:ClassPerson.new.foo# => 'foo'Book.foo# => 'foo'Book.new.foo# => undefinierte Methode für Book# Ausnahmebehandlung# Definiere eine neue AusnahmeclassMyException<Exceptionend# Definiere eine weitere AusnahmeclassMyAnotherException<Exception;endex=beginraiseMyException.newrescueex1:IndexError"ex1"rescueex2:MyException|MyAnotherException"ex2"rescueex3:Exception"ex3"rescueex4# fange alle Ausnahmen ab"ex4"endex# => "ex2"