Eine Sprache, die sich für Programmierer gut anfühlt
Ausführen: Datei hallo.rb speichern und mit ruby hallo.rb starten, interaktiv mit irb.
puts, print, p; #{...} für String-Interpolation? und ! haben Konventionenirb zum Ausprobieren, gem für Paketeruby hallo.rb # Datei ausführen
ruby -e 'puts 1 + 2' # eine Zeile
irb # interaktive Konsole
gem install rails # Paket (Gem) installierensnake_case, Konstanten GROSS, @instanz, $global7 / 2 = 3; Ganzzahlen sind beliebig groß"...":name sind eindeutige Bezeichnernil und false sind falschInteger("x") wirft Fehler, "x".to_i liefert 0name = "Mia" # lokale Variable
alter = 17
PI = 3.14159 # Konstante (Großbuchstaben)
$global = "selten sinnvoll" # globale Variable
@instanz = "in Objekten" # Instanzvariable
a, b = 1, 2
a, b = b, a # tauschen
erst, *rest = [1, 2, 3, 4]
puts "#{a} #{b} #{erst} #{rest}"
x = y = 5
puts x + y
puts defined?(name)
puts defined?(nirgendwo).inspectif/elsif/else, unless, Modifikator ... if bedingungcase/when vergleicht mit === (Bereiche, Klassen, Regex, Lambdas)times, upto, each, while, until, loop mit break und nextif und casepunkte = 78
if punkte >= 90
puts "sehr gut"
elsif punkte >= 75
puts "gut"
else
puts "weiter üben"
end
puts "bestanden" if punkte >= 50 # Modifikator-Form
puts "nicht ganz" unless punkte >= 80 # unless = if not
ergebnis = punkte >= 50 ? "ja" : "nein" # ternär
puts ergebnis
status = if punkte > 70 then "stark" else "schwach" end # if ist ein Ausdruck
puts status<<, push, pop, sort, uniq, zip, flatten; Zugriff a[0], a[1..2]map, select, reject, reduce, group_by, tally, sum, each_with_object{ name: "Mia" }, fetch, dig, Hash.new(0), transform_values, merge(1..5) und (1...5), auch endlos und lazySet für Mengena = [5, 3, 9, 1]
a << 7 # anhängen
a.push(2)
a.unshift(0) # vorne einfügen
p a
p a.pop, a.shift
p a, a.length, a.first, a.last, a[1], a[-1], a[1..2], a[1, 2], a.first(2), a.last(2)
a.delete(9)
a.insert(1, 99)
p a
p a.include?(99), a.index(99), a.sort, a.sort.reverse, a.sort { |x, y| y <=> x }
p a.min, a.max, a.sum, a.minmax, a.take(2), a.drop(2)
p [1, 2, 2, 3, 3, 3].uniq, [1, [2, [3]]].flatten, [3, 1, 2].reverse, [1, 2, 3].rotate
p [1, 2, 3] + [4], [1, 2, 3, 4] - [2, 3], [1, 2] * 2, [1, 2, 3] & [2, 3, 4], [1, 2] | [2, 3]
p [1, 2, 3].zip(%w[a b c]), [[1, :a], [2, :b]].to_h, [1, 2, 3].each_slice(2).to_a
p [1, 2, 3, 4].each_cons(2).to_a, [3, 1, 2].sort_by { |x| -x }, %w[bb a ccc].sort_by(&:length)
p Array.new(3, 0), Array.new(3) { |i| i * i }, [nil, 1, nil].compact
p [1, 2, 3].sample.class, [1, 2, 3].shuffle.length
x, y, *rest = [1, 2, 3, 4]
p x, y, rest*args, **opts, Schlüsselwort-Argumente{ |x| ... } und yield; block_given?->(x) { } (Lambda) und Proc.new: Code als Objekt, call, curry, >>def gruss(name = "Welt", anrede: "Hallo")
"#{anrede}, #{name}!"
end
def summe(*zahlen) # beliebig viele Argumente
zahlen.sum
end
def optionen(name, **opts) # Schlüsselwort-Argumente
"#{name} #{opts}"
end
def minmax(liste)
[liste.min, liste.max] # mehrere Werte als Array
end
def quadrat(x) = x * x # Einzeiler (Endless Method, Ruby 3)
puts gruss
puts gruss("Mia", anrede: "Hi")
puts summe(1, 2, 3, 4)
puts summe(*[5, 6]) # Array entpacken
puts optionen("x", farbe: "rot", groesse: 3)
klein, gross = minmax([4, 9, 1])
puts "#{klein} #{gross}"
puts quadrat(7)
puts method(:gruss).arityclass Name ... end, initialize als Konstruktor, @variablenattr_reader/writer/accessor erzeugen Zugriffsmethodenprivate/protected, Klassenmethoden self.nameclass B < A, super; Comparable für VergleicheStruct und Data für kleine Datenobjekteclass Konto
attr_reader :inhaber, :stand # Getter
attr_accessor :notiz # Getter + Setter
@@anzahl = 0 # Klassenvariable
ZINS = 0.02 # Konstante
def initialize(inhaber, stand = 0) # Konstruktor
@inhaber = inhaber # Instanzvariablen beginnen mit @
@stand = stand
@@anzahl += 1
end
def einzahlen(betrag)
raise ArgumentError, "Betrag muss positiv sein" unless betrag.positive?
@stand += betrag
self # für Verkettung
end
def reich? = @stand > 1000
def to_s = "#{@inhaber}: #{format('%.2f', @stand)}"
def self.anzahl = @@anzahl # Klassenmethode
private
def geheim = "intern"
end
k = Konto.new("Mia", 100)
k.einzahlen(50).einzahlen(25.5)
puts k
puts k.reich?
k.notiz = "VIP"
puts k.notiz
puts Konto.anzahl
puts Konto::ZINS
begin
k.einzahlen(-5)
rescue ArgumentError => e
puts "Fehler: #{e.message}"
end
begin
k.geheim
rescue NoMethodError => e
puts "NoMethodError: #{e.message[0, 40]}"
end
puts k.inspect.sub(/0x[0-9a-f]+/, "0x...")
puts k.instance_variables.inspect
puts k.respond_to?(:einzahlen), k.is_a?(Konto), Konto.instance_methods(false).sort.first(3).inspectinclude, extend, prependancestorsComparable (mit <=>) und Enumerable (mit each) liefern viele Methoden gratisEnumerator und lazy für unendliche Folgenmodule Geometrie
PI = 3.14159
def self.kreisflaeche(r) = PI * r * r
class Kreis
def initialize(r) = @r = r
def flaeche = Geometrie.kreisflaeche(@r)
end
end
puts Geometrie.kreisflaeche(2)
puts Geometrie::Kreis.new(1).flaeche
puts Geometrie::PIbegin / rescue / else / ensure / end, raise, retry; eigene Fehlerklassen von StandardErrorFile.read/write/open/foreach, Block schließt automatischjson, csv, yaml gehören zur Standardbibliothek=~, match, scan, gsub mit benannten GruppenTime und Date für Zeitrechnungdef teile(a, b)
raise ZeroDivisionError, "Division durch null" if b.zero?
a / b
end
begin
puts teile(10, 2)
puts teile(1, 0)
rescue ZeroDivisionError => e
puts "Fehler: #{e.message}"
else
puts "kein Fehler"
ensure
puts "ensure läuft immer"
end
def versuche
yield
rescue TypeError, ArgumentError => e
puts "#{e.class}: #{e.message}"
end
versuche { Integer("x") }
versuche { 1 + nil }
versuche { [1, 2].fetch(9) } rescue puts "IndexError (Modifikator-rescue)"
puts (Integer("zzz") rescue -1)
versuche = 0
begin
versuche += 1
raise "kaputt" if versuche < 3
puts "klappte im Versuch #{versuche}"
rescue
retry # erneut versuchen
endsend, define_method, method_missing, instance_variable_get/set verändern Verhalten zur Laufzeitrespond_to_missing? mit method_missing kombinierencase/in) zerlegt Strukturenclass Roboter
def sage_hallo = "Hallo"
end
r = Roboter.new
puts r.send(:sage_hallo) # Methode per Namen aufrufen
puts r.public_send(:sage_hallo)
puts r.respond_to?(:fliegen)
Roboter.class_eval do # Klasse nachträglich erweitern
define_method(:fliegen) { |ziel = "Mond"| "fliege zum #{ziel}" }
end
puts r.fliegen, r.fliegen("Mars")
%w[rot gruen blau].each do |farbe| # Methoden in einer Schleife erzeugen
Roboter.define_method("#{farbe}?") { @farbe == farbe }
end
r.instance_variable_set(:@farbe, "gruen")
puts r.gruen?, r.rot?
puts r.instance_variable_get(:@farbe)
p Roboter.instance_methods(false).sortassert_equal, assert_raisesGemfile, Gemfile.lock, bundle exec)lib/, test/, Rakefilebinding.irb zum Debuggenrequire "minitest/autorun"
class Rechner
def addiere(a, b) = a + b
def teile(a, b)
raise ZeroDivisionError, "durch null" if b.zero?
a / b
end
end
class RechnerTest < Minitest::Test
def setup
@r = Rechner.new
end
def test_addition
assert_equal 5, @r.addiere(2, 3)
end
def test_teilen
assert_in_delta 2.5, @r.teile(5, 2.0), 0.001
end
def test_fehler
assert_raises(ZeroDivisionError) { @r.teile(1, 0) }
end
def test_enthaelt
assert_includes [1, 2, 3], 2
refute_nil @r
end
endrails new, generate, db:migrate, server, console, testincludes vermeidenrequire "sinatra"
require "json"
get "/" do
"Hallo Welt"
end
get "/gruss/:name" do
"Hallo, #{params[:name]}!"
end
post "/api/echo" do
content_type :json
daten = JSON.parse(request.body.read)
{ empfangen: daten }.to_json
endEnumerable und Hash decken den Großteil des Alltags abname = "Mia" # Variable
NAME = 1 # Konstante
@feld, @@klassenfeld, $global
puts "Hallo #{name}"
if x then .. elsif .. else .. end puts "ja" if x unless x ..
case v when 1 then .. when 2..5 .. else .. end
while c .. end until c .. end loop do .. end 3.times { |i| .. }
def methode(a, b = 1, *rest, key: 0, **opts, &block) .. end
class A < B; include M; attr_accessor :x; def initialize(x) = @x = x; end
module M; def hallo = "hi"; end
begin .. rescue Fehler => e .. ensure .. end