Die folgenden Appetithappen sollen einen Eindruck davon vermitteln, wie sich Ruby-Code "`anfühlt"'. Im Anschluss (Abschnitt 1.3) fassen wir die wichtigsten Codekonventionen und Syntaxregeln für das Arbeiten mit Ruby zusammen.
Auch wenn die Anweisungen erst später
im Buch erklärt werden, kann man beim Durchlesen oft schon erraten,
was mit dem Code bezweckt wird.
Noch mehr wird man allerdings von unseren Häppchen haben, wenn
man die Beispiele auf einem Rechner ausprobiert, was wir im nächsten
Kapitel beschreiben. Zusätzlich zu den lokalen
Testmöglichkeiten gibt es noch Clemens' RubyCHannel
,
eine Website, auf der ein Ruby-Interpreter zur Verfügung steht,
mit dem viele Codebeispiele getestet werden können.
ruby -e 'puts "Hallo zukuenftiger Rubyist!"'
x, y = 2, 3 # x == 2 und y == 3 x, y = y, x # x == 3 und y == 2
finden; der Algorithmus
ist langsam, aber kurz.
for i in 2..100 do
puts i unless (2..i-1).find{|j| i % j == 0}
end
#-> 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
53 59 61 67 71 73 79 83 89 97
große ganze Zahlen sind eingebaut und werden
automatisch verwendet.
def fak(n)
f = 1
(2..n).each { |i| f *= i }
f
end
puts fak(gets.to_i)
# Eingabe: 100
#-> 93326215443944152681699238856...
einige nützliche Einzeiler zusammengestellt, die in der gezeigten
Schreibweise auf einem Unix-Rechner funktionieren. In einer DOS-Konsole
müssen die dort gültigen Syntaxregeln beachtet werden.
# Zeilen zählen ruby -e 'print readlines.length' # ersetze foo durch bar in C-Dateien # Sicherungskopie in .bak-Dateien ruby -i.bak -pe 'gsub "foo", "bar"' *.[ch] # Zeilen `in place' nummerieren ruby -pi -e 'printf "%d\t", $.;' thgttg.txt
haben in
Ruby dynamische Größen und können Elemente verschiedener Typen aufnehmen.
array = [1, 'Alligator', 643.001]
pcSpeedHash = {
'Duck2'=>750, 'Rockaplan'=>25, 'ZX81'=>0.6 }
pcSpeedHash['Ananke']=1700
# Bereiche
(5..10).each { |z| puts z**3 }
#-> 125 216 343 512 729 1000
# Hashtabellen
pcSpeedHash.sort.map{ |key, val|
"#{key}: #{val} MHz"
} #-> ['Ananke: 1700 Mhz', 'Duck2: 750 MHz',
'Rockaplan: 25 MHz', 'ZX81: 0.6 MHz']
freq = Hash.new(0)
open("dings.rb").read.scan(/\w+/){ |wort|
freq[wort] += 1
}
freq.sort.each { |wort, zahl|
puts "#{wort} - #{zahl}"
}
in ganzer Pracht.
Wir hatten eine Liste von Zitaten in der Form "`Autor: Zitat"' und erzeugen
daraus die LATEX-Anweisungen, die wir für dieses Buch verwenden.
readlines.each{ | line |
puts line.gsub('(.*?): (.*)',
'\\begin{rquote}{\1}\2\\end{rquote}')
}
![[*]](footnote.png)
"".methods.grep(/case/) #-> ["upcase!", "upcase", "swapcase!", ...]
..."`und wie hieß gleich noch mal die Error-Klasse?"'
ObjectSpace.each_object(Class) { |c|
puts c if c.to_s[/error/i]
} #-> SystemStackError, LocalJumpError,
EOFError, IOError, RegexpError, ...
Methoden und Variablen können während der Laufzeit
hinzugefügt und geändert werden, sogar für einzelne Objekte:
class A
def method_missing(methId)
print methId.id2name, " gibt es nicht.\n"
end
end
a=A.new
a.hello #-> hello gibt es nicht.
# diese Singleton-Methode gibt es nur für a
def a.hello
p "hier schon"
end
a.hello #-> hier schon
A.new.hello #-> hello gibt es nicht.
def quicksort( xs )
return xs if xs.size <= 1
m = xs[0] # Split-Element
quicksort(xs.select { |i| i < m } ) +
xs.select { |i| i == m } +
quicksort(xs.select { |i| i > m } )
end
quicksort([13, 11, 74, 69, 0])
#-> [0, 11, 13, 69, 74]
über Standardprotokolle, z.B. per ftp:
require 'net/ftp'
ftp = Net::FTP.open('ftp.netlab.co.jp')
ftp.login
ftp.chdir('pub/lang/ruby')
puts ftp.dir
ftp.quit
stehen ebenfalls zur
Verfügung, um Aufgaben parallel zu erledigen. Dieses Beispiel holt zwei
Webseiten gleichzeitig:
require 'net/http'
url1="www.approximity.com"
url2="www.ruby.ch"
def getPage(url)
h = Net::HTTP.new(url, 80)
puts "Hole: #{url}"
resp, data = h.get('/', nil )
puts "Habe #{url}: #{resp.message}"
end
thread1=Thread.new { getPage(url1) }
thread2=Thread.new { getPage(url2) }
thread1.join
thread2.join
können in Ruby
fast alle Objekte in Binärstreams/Strings transformiert werden.
Diese werden dann in Instanzen der Klasse String gespeichert.
include Marshal
a = 25.6;
pt = Struct.new('Point', :x,:y);
x = pt.new(10, 10)
y = pt.new(20, 20)
rt = Struct.new('Rectangle', :origin,:corner);
z = rt.new(x, y)
c = Object.new
thing = [a, x, z, c, c, "fff"];
representation = dump(thing);
p thing
p representation
p load(representation)
# ruby.rb
(n=$*[0].to_i).times{|i|s=(n/2-i).abs;puts" "*s+"#"*(n-2*s)}
# Konsole:
> ruby ruby.rb 10
ist mit
Distributed Ruby kein Problem.
Ein einfacher Server ist schnell geschrieben:
# server.rb require 'drb' class TestServer def doit; "Hallo, verteilte Welt"; end end ts = TestServer.new DRb.start_service( 'druby://approximity.com:9000', ts) DRb.thread.join # client.rb require 'drb' DRb.start_service cl = DRbObject.new(nil, 'druby://approximity.com:9000') p cl.doit
Wir haben den TestServer auf approximity.com eingerichtet, so dass nach dem Start des Clients der Text "`Hallo, verteilte Welt"' erscheinen sollte.
binden die Umgebung,
in der ihre Definition ausgeführt wird.
def addierer(incr); proc { |n| n + incr }; end
ad = addierer(3)
p ad.call(5) # => 8
99.downto(0) { |x|
u = "#{x > 0 ? (x) : 'No more'}" +
" bottle#{x != 1 ? 's' : "'} of beer"
w = u + " on the wall, "
puts w + u +
". Take one down, pass it around. " + w
}
Man kann die Flaschen auch objektorientiert leeren:
![[*]](footnote.png)
class Wall
def initialize num; @beers = num; end
def beer?; @beers > 0; end
def takeBottle; @beers -= 1; end
def bottles
@beers == 1 ? "bottle" : "bottles"
end
def count
@beers > 0 ? @beers.to_s : "No more"
end
def bob
"#{count} #{bottles} of beer"
end
end
wall = Wall.new 99
while wall.beer?
print "#{wall.bob} on the wall, " +
"#{wall.bob}. Take one down, "
wall.takeBottle
puts "pass it around. " +
"#{wall.bob} on the wall."
end