Standard Library
Mit Ruby mitgeliefert wird eine große und nützliche Bibliothek mit
Modulen und Klassen. Dieses Kapitel enthält einige Beispiele der eher
nützlichen.
Interessanterweise und anders als der Code aus den späteren Kapiteln wurden
alle diese Bibliotheken in Ruby geschrieben. Man findet die Quellen im
lib
-Unterverzeichnis der Standard-Ruby-Distribution.
class Complex
|
Parent:
|
Numeric
|
Version:
|
1.6
|
|
Index:
new Arithmetische Operationen <=> == abs abs2 arg conjugate image polar real to_f to_i to_r to_s
require "complex" |
|
v1 = Complex(2,3) |
» |
Complex(2, 3) |
v2 = 2.im |
» |
Complex(0, 2) |
v1 + v2 |
» |
Complex(2, 5) |
v1 * v2 |
» |
Complex(-6, 4) |
v2**2 |
» |
Complex(-4, 0) |
Math.sin(v1) |
» |
Complex(9.154499147, -4.16890696) |
v1 < v2 |
» |
false |
v2**2 == -4 |
» |
true |
class methods
|
new
|
Complex.new( a, b )
-> aComplex |
|
Liefert a + bi.
|
Zusätzlich zum Complex.new
-Konstruktor gibt es in der
Complex
-Bibliothek die Methode
Numeric.im
,
mit
aNumeric.im
liefert sie 0 + aNumerici zurück.
Außerdem werden komplexe Zahlen mit der globalen Methode
Complex
erzeugt, die ein oder zwei Argumente entgegen nimmt. Ihr Rückgabewert
hängt vom Typ ihrer Argumente ab:
a |
b |
Ergebnis |
Number |
Number |
a + bi |
Complex |
0 |
a |
Complex |
Complex |
Complex( a.real - b.image,
a.image + b.real ) |
Number |
Complex |
Complex( a - b.image,
b.real ) |
 |
instance methods
|
Arithmetische Operationen
|
|
|
Führt verschiedene arithmetrische Operationen mit ref aus.
ref |
+ |
aNumeric-> aComplex |
Addition |
ref |
- |
aNumeric-> aComplex |
Subtraktion |
ref |
* |
aNumeric-> aComplex |
Multiplikation |
ref |
/ |
aNumeric-> aComplex |
Division |
ref |
% |
aNumeric-> aComplex |
Rest |
ref |
** |
aNumeric-> aComplex |
Exponentiation (reelle und
komplexe Hochzahl) |
|
<=>
|
ref <=> other-> -1, 0, +1 |
|
Liefert ref.abs <=> other.abs.
(An dieser Stelle muss der Übersetzer jedoch anmerken, dass mathematisch gesehen
ein Vergleich von zwei komplexen Zahlen Unsinn ist. Es ist doch sehr verwirrend,
wenn für zwei Zahlen
ref <= other sowie
ref >= other gilt und sie dann trotzdem nicht gleich sind.
Ich bin der Meinung, wenn man
ref.abs < other.abs haben will, dann soll man auch
ref.abs < other.abs schreiben.)
|
==
|
ref == anObject-> true or false |
|
Liefert true ,
wenn anObject eine komplexe Zahl ist und Real- und Imaginärteil denen bei
ref entsprechen. Liefert auch true , wenn anObject
eine einfache Zahl ist und ref.real ist gleich
anObject und ref.image ist null.
Andernfalls wird versucht, anObject in eine komplexe Zahl
umzuwandeln, und das Ergebnis verglichen.
|
abs
|
ref.abs -> aFloat |
|
Absolut-Wert.
|
abs2
|
ref.abs2 -> aFloat |
|
Quadrat des Absolut-Werts.
|
arg
|
ref.arg -> aFloat |
|
Argument (Winkel von (1,0) aus).
|
conjugate
|
ref.conjugate
-> aComplex |
|
Komplex-Konjugiert.
|
image
|
ref.image -> aNumeric |
|
Imaginärteil von ref.
|
polar
|
ref.polar -> anArray |
|
Liefert ein zwei-elementiges Array: [c.abs, c.arg].
|
real
|
ref.real -> aNumeric |
|
Realteil von ref.
|
to_f
|
ref.to_f -> aComplex |
|
Liefert Complex(real.to_f, image.to_f) .
|
to_i
|
ref.to_i -> aComplex |
|
Liefert Complex(real.to_i, image.to_i) .
|
to_r
|
ref.to_r -> aComplex |
|
Liefert Complex(real.to_r, image.to_r) , wobei beide Teile der
komplexen Zahl in eine rationale Zahl konvertiert werden.
|
to_s
|
ref.to_s -> aString |
|
String-Repräsentation von ref.
|
Zusätzlich werden die Math
-Funktionen sqrt
,
exp
, cos
,
sin
, tan
, log
, log10
und atan2
erweitert, um ein Argument der Klasse Complex
aufnehmen zu können.
class Date
|
Parent:
|
Object
|
Version:
|
1.6
|
|
Index:
exist2? exist? existw? gregorian_leap? julian_leap? leap? new new1 new2 new3 neww today Accessors + -- << <=> === >> downto england gregorian italy jd julian leap? mjd newsg next ns? os? sg step succ to_s upto
require 'date' |
|
d = Date.new(2000, 3, 31) |
» |
#<Date: 2451635,2299161> |
[d.year, d.yday, d.wday] |
» |
[2000, 91, 5] |
[d.month, d.mday] |
» |
[3, 31] |
[d.cwyear, d.cweek, d.cwday] |
» |
[2000, 13, 5] |
[d.jd, d.mjd] |
» |
[2451635, 51634.5] |
(d << 1).to_s |
» |
"2000-02-29" |
d.succ.to_s |
» |
"2000-04-01" |
(d + 100).to_s |
» |
"2000-07-09" |
d.leap? |
» |
true |
Date.new(2000, 3, -10).to_s |
» |
"2000-03-22" |
d1 = Date.neww(2000, 13, 7) |
» |
#<Date: 2451637,2299161> |
d1.to_s |
» |
"2000-04-02" |
[d1.cwday, d1.wday] |
» |
[7, 0] |
Die date
-Bibliothek implementiert die Klasse Date
,
die einen übersichtlichen Satz an Mitteln zur Verfügung stellt, um Datums zu speichern,
zu manipulieren und zu konvertieren. Um die ganzen Optionen darzustellen, müssen wir aber
erst einen kurzen historischen Umweg nehmen, damit einiege Begriffe klar werden.
Intern wird ein Datum als die Zahl eines julianischen Tages gespeichert, das ist die
Anzahl der Tage seit Mittag des 1. Januar 4713 v.Chr. [Im Code findet man oft die
Referenz auf das Jahr -4712. Weil es im astronomischen Kalender
das Jahr Null gibt,
ist das dasselbe wie 4713 v.Chr.] [Der Übersetzer:
Julianisch heißt der Tag
nach dem Namen des Vaters des Erfinders dieser Zählweise, das hat nichts mit Julius
Cäsar und dem Julianischen Kalender zu tun. Weil der Erfinder diese Datumsnotierung für
astronomische Beobachtungen ersonnen hat, geht ein Julianischer Tag auch von Mittag zu
Mittag, damit nachts zur Beobachtungszeit für Astronomen kein Datumswechsel stört.]
Die Regeln für die Konvertierung von Julianischer
Tag in ein Kalenderdatum sind kompliziert, weil die Römer die Länge eines Jahres nicht
ganz richtig abgeschätzt haben. Im Julianischen Kalender (auch Old Style oder O.S. genannt)
ist jedes vierte Jahr ein Schaltjahr. In der Klasse Date
gibt es
Optionen, um Datums unter dieser Voraussetung zu konvertieren.
Im sechzehnten Jahrhundert waren die Ungenauigkeiten dieser Zählweise offensichtlich
geworden. 1582 wurde mit einem Edikt von Papst Gregor XIII der New Style (N.S.)
oder Gregorianische Kalender eingeführt, bei dem Jahre, die durch 100 teilbar waren,
keine Schaltjahre mehr waren, außer sie waren auch durch 400 teilbar. Dieses System
wurde von den meisten katholischen Ländern sofort übernommen, aber religiöse
Differenzen verhinderten eine weitere Verbreitung. England (und mehrere andere Staaten)
stellten erst 1752 um, andere Länder noch später. [Der Übersetzer: Deshalb fand
die russische Oktoberrevolution für den Rest der Welt im November statt.]
In der Klasse Date
kann man den Stichtag auf 1582 einstellen (die Date::ITALY
-Option), 1752
(Date::ENGLAND
) oder ein anderes frei wählbares Datum.
Die Klasse Date
unterstützt außerdem die Konvertierung
zum modifizierten julianischen Tag (MJD).
Die MJD-Zählung beginnt am 17. November 1858 um Mitternacht. Weil diese Werte ab
Mitternacht und nicht ab Mittags gezählt werden, wird zum Konvertierungsfaktor noch ein
halber Tag dazu gezählt.
Die folgende Beschreibung benutzt die Abkürzungen aus Tabelle Table 24.1
auf Seite 445.
Abkürzungen zum Beschreiben der Datums
Feld |
Bedeutung |
cwday |
Ein ISO 8601 Kalender-Wochentag. 1 ist Montag, 7 ist Sonntag. |
cweek |
Eine ISO 8601 Kalender-Woche. Woche 1 ist diejenige mit dem ersten Mittwoch (oder
äquivalent dazu diejenige mit dem 4. Januar). |
cwyear |
Ein ISO 8601 kalender-wochen-basiertes Jahr. Das kann vom year
abweichen, weil es erst am ersten Montag anfängt. |
jd |
Die Nummer des julianischen Tags --- die Anzahl der Tage seit dem
1. Januar, 4713 v.Chr. (mittags). |
mday |
Der Tag des Monats (1..31). |
mjd |
Die Nummer des modifizierten julianischen Tages. |
mon |
Der Monat des Jahres (1..12). |
sg |
Der Beginn der gregorianischen Korrektur: Date::ITALY (Default)
für 1582, Date::ENGLAND für 1752 oder
JULIAN , d.h. keine Korrektur. Man kann auch einen beliebigen
julianischen Tag für diesen Parameter angeben, dann fängt die Korrektur an diesem
Datum an. |
wday |
Der Tag der Woche (0 ist Sonntag). |
week |
Die Wochennummer des Jahres (1..53). |
yday |
Der Tag des Jahres (1..366). |
year |
Ein Jahr (1966, 2001 und so was). |
 |
|
Die Klasse Date
liefert auch die konstanten Arrays
Date::MONTHNAMES
und Date::DAYNAMES
, die man mit mon und
wday indizieren kann, um die dazugehörenden englischen Namen zu bekommen.
Desweiteren liefert Date
auch noch low-level Konvertierungs-Methoden:
* civil_to_jd |
* jd_to_civil |
* commercial_to_jd |
* jd_to_commercial |
* ordinal_to_jd |
* jd_to_ordinal |
* jd_to_mjd |
* mjd_to_jd |
Diese Methoden führen eine begrenzte Fehlerprüfung ihrer Parameter durch und werden
hier nicht dokumentiert. Die etwas unglücklich benannten exist..?
führen eine Konvertierung aus einem anderen Format in das Format julianischer Tag inklusive
Fehlerprüfung durch. Diese Methoden normalisieren außerdem ihre Parameter.
mixins
|
Comparable:
|
<, <=, ==, >=, >, between? |
class methods
|
exist2?
|
Date.exist2?(
year, yday, sg=Date::ITALY ) -> jd |
|
Konvertiert ein year und yday in einen julianischen Tag,
liefert nil im Fehlerfall.
|
exist?
|
Date.exist?( year, mon,
mday, sg=Date::ITALY ) -> jd |
|
Konvertiert ein year, mon und mday in einen julianischen
Tag, bzw. nil falls die Parameter nicht stimmen.
|
existw?
|
Date.existw?(
cyear, cweek, cwday, sg=Date::ITALY )
-> jd |
|
Konvertiert ein cyear,
cweek und cwday in einen julianischen Tag.
|
gregorian_leap?
|
Date.gregorian_leap?( year
) -> true or false |
|
Gregorianisches Schaltjahr: true falls year durch 4
teilbar, außer falls year durch 100 und nicht durch 400 teilbar.
|
julian_leap?
|
Date.julian_leap?( year )
-> true or false |
|
true falls year durch 4 teilbar.
|
leap?
|
Date.leap?( year ) -> true or false |
|
Synonym für Date.gregorian_leap? .
|
new
|
Date.new( year=-4712, mon=1, mday=1,
sg=Date::ITALY ) -> aNewDate |
|
Liefert ein Date für das angegebene year, mon und
mday. Falls mon negativ ist, wird vom Ende des Jahres rückwärts gezählt.
Falls mday negativ ist, wird vom Ende des Monats rückwärts gezählt.
|
new1
|
Date.new1( jd, sg=Date::ITALY )
-> aNewDate |
|
Erzeugt ein Date zum übergebenen julianischen Tag.
|
new2
|
Date.new2( year=-4712, yday=1,
sg=Date::ITALY ) -> aNewDate |
|
Erzeugt ein Date zum übergebenen year und
yday. Falls yday negativ ist, wird vom Ende des Jahres rückwärts
gezählt.
|
new3
|
Date.new3( year=-4712, mon=1, mday=1,
sg=Date::ITALY ) -> aNewDate |
|
Synonym für Date.new .
|
neww
|
Date.neww( cyear=1582, cweek=41,
cwday=5, sg=Date::ITALY ) -> aNewDate |
|
Erzeugt ein Date zum übergebenen cyear, cweek
und
cwday. Falls cweek negativ ist, wird vom Ende des Jahres rückwärts gezählt.
Falls cwday negativ ist, wird vom Ende der Woche rückwärts gezählt.
|
today
|
Date.today( sg=Date::ITALY )
-> aNewDate |
|
Liefert ein Date für Heute.
|
instance methods
|
Accessors
|
ref.year -> year ref.yday -> yday ref.mjd -> mjd ref.mon -> mon ref.month -> mon ref.mday -> mday ref.day -> mday ref.cwyear -> cwyear ref.cweek -> cweek ref.cwday -> cwday ref.wday -> wday |
|
Gibt die angegebenen Komponente von ref als Zahl zurück.
|
+
|
ref + anInteger-> aNewDate |
|
Erzeugt ein neues Date anInteger Tage von ref.
|
--
|
ref- anInteger-> aNewDate ref- anOtherDate-> anInteger |
|
Die erste Form liefert ein neues Date anInteger Tage vor
ref.
Die zweite Form liefert die Anzahl der Tage zwischen ref
und anOtherDate.
|
<<
|
ref << anInteger-> aNewDate |
|
Liefert ein neues Date , gebildet durch Subtraktion von
anInteger Monaten von ref, dabei wird der Wert mday
heruntergesetzt, falls die Monatsgrenze sonst überschritten wird.
|
<=>
|
ref <=> anOther-> -1, 0, +1 |
|
anOther muss ein Numeric sein (dann gilt es als Nummer
des julianischen Tags) oder ein Date .
Liefert -1, 0, +1 falls ref kleiner als, gleich oder größer als
anOther ist. Siehe Modul Comparable auf Seite 406.
|
===
|
ref === anOther-> true or false |
|
anOther muss ein Numeric sein (dann gilt es als Nummer
des julianischen Tags) oder ein Date .
liefert true , falls die Nummer des julianischen Tages von
anOther dieselbe ist wie die von ref.
|
>>
|
ref >> anInteger-> aNewDate |
|
Liefert ein neues Date gebildet durch Addition von
anInteger Monaten zu ref,
der Wert von mday wird dabei falls nötig auf den letzen gültigen Tag des
Monats zurück gesetzt.
|
downto
|
ref.downto( aDateMin )
{| date | block }-> ref |
|
Ruft den Block auf mit Datums von ref runter bis aDateMin.
|
england
|
ref.england -> aDate |
|
Äquivalent zu ref.newsg(Date::ENGLAND) .
|
gregorian
|
ref.gregorian
-> aDate |
|
Äquivalent zu ref.newsg(Date::GREGORIAN) .
|
italy
|
ref.italy -> aDate |
|
Äquivalent zu ref.newsg(Date::ITALY) .
|
jd
|
ref.jd -> jd |
|
Liefert die Nummer des julianischen Tags für ref.
|
julian
|
ref.julian -> aDate |
|
Äquivalent zu ref.newsg(Date::JULIAN) .
|
leap?
|
ref.leap? -> true or false |
|
Liefert true falls ref in einem Schaltjahr ist.
|
mjd
|
ref.mjd -> mjd |
|
Liefert die Nummer des modifizierten julianischen Tags für ref.
|
newsg
|
ref.newsg( sg=Date::ITALY )
-> aNewDate |
|
Liefert ein neues Date .
|
next
|
ref.next -> aNewDate |
|
Synonym für ref.succ.
|
ns?
|
ref.ns? -> true or false |
|
Liefert true falls ref nach der gregorianischen Korrektur
liegt.
|
os?
|
ref.os? -> true or false |
|
Liefert true falls ref vor der gregorianischen Korrektur
liegt.
|
sg
|
ref.sg -> anInteger |
|
Liefert die Nummer des julianischen Tages vom ersten Tag nach der gregorianischen
Korrektur für das Objekt ref.
|
step
|
ref.step( aDateLimit, step )
{| date | block }-> ref |
|
Ruft den Block auf mit Datums, die anfangen bei ref,
jeweils erhöht werden um step Tage und enden bevor das Datum
größer als aDateLimit ist (bzw. kleiner bei negativer Schrittweite).
|
succ
|
ref.succ -> aNewDate |
|
Liefert das Datum von ref plus einen Tag.
|
to_s
|
ref.to_s -> aString |
|
Liefert self als ``year-mon-mday.''
|
upto
|
ref.upto( aDateMax )
{| date | block }-> ref |
|
Ruft den Block auf mit Datums von ref bis aDateMax.
|
require "English"
$OUTPUT_FIELD_SEPARATOR = ' -- '
"waterbuffalo" =~ /buff/
print $LOADED_FEATURES, $POSTMATCH, $PID, "\n"
print $", $', $$, "\n"
|
erzeugt:
English.rb -- alo -- 14806 --
English.rb -- alo -- 14806 --
|
Wenn man die Bibliotheks-Datei English in ein Ruby-Script einbindet, kann man
globale Variablen wie $_
mit etwas weiniger kryptischen Namen ansprechen,
wie sie in folgender Tabelle stehen.
 |
$* |
$ARGV |
$" |
$LOADED_FEATURES |
$? |
$CHILD_STATUS |
$& |
$MATCH |
$< |
$DEFAULT_INPUT |
$. |
$NR |
$> |
$DEFAULT_OUTPUT |
$, |
$OFS |
$! |
$ERROR_INFO |
$\ |
$ORS |
$@ |
$ERROR_POSITION |
$\ |
$OUTPUT_RECORD_SEPARATOR |
$; |
$FIELD_SEPARATOR |
$, |
$OUTPUT_FIELD_SEPARATOR |
$; |
$FS |
$$ |
$PID |
$= |
$IGNORECASE |
$' |
$POSTMATCH |
$. |
$INPUT_LINE_NUMBER |
$` |
$PREMATCH |
$/ |
$INPUT_RECORD_SEPARATOR |
$$ |
$PROCESS_ID |
$~ |
$LAST_MATCH_INFO |
$0 |
$PROGRAM_NAME |
$+ |
$LAST_PAREN_MATCH |
$/ |
$RS |
$_ |
$LAST_READ_LINE |
 |
Index:
find prune
require "find"
Find.find("/etc/passwd", "/var/spool/lp1", ".") do |f|
Find.prune if f == "."
puts f
end
|
erzeugt:
/etc/passwd
/var/spool/lp1
/var/spool/lp1/status
/var/spool/lp1/lock
/var/spool/lp1/.seq
|
Das Find
-Modul unterstützt die top-down Traversierung für
eine Menge aus Datei-Pfaden.
class methods
|
find
|
ref.find( [aName]* ) {| aFileName | block }
|
|
Ruft den dazugehörenden Block auf, jeweils mit dem Namen von jeder
Datei und jedem Verzeichnis, die in der Parameterliste aufgeführt sind,
dann rekursiv in deren Unterverzeichnissen und so weiter.
|
prune
|
ref.prune
|
|
Bricht die Bearbeitung der aktuellen Datei oder des aktuellen
Verzeichnisses ab und beginnt die Schleife wieder bei dem
nächsten Eintrag. Falls der aktuelle Eintrag ein Verzeichnis ist,
wird nicht in diesem Verzeichnis weitergemacht. Sinnvoll ist das natürlich nur
in einem mit Find::find verbundenen Block.
|
Index:
cmp compare copy cp install makedirs mkpath move mv rm_f safe_unlink syscopy
require 'ftools' |
|
File.copy 'testfile', 'testfile1' |
» |
true |
File.compare 'testfile', 'testfile1' |
» |
true |
Die FTools
-Bibliothek stellt mehrere Methoden für die eingebaute Klasse
File
zur Verfügung. Diese Methoden sind ganz nützlich bei
Programmen, die Dateien verschieben oder kopieren, etwa Installations-Programme.
class methods
|
cmp
|
ref.cmp( name1, name2,
verbose=false )
-> true or false |
|
Synonym für File.compare .
|
compare
|
ref.compare( name1, name2,
verbose=false )
-> true or false |
|
Liefert true nur dann, wenn der Inhalt der Dateien name1
und name2 identisch ist.
|
copy
|
ref.copy( fromName, toName,
verbose=false )
-> true or false |
|
Äquivalent mit dem Aufruf von File.syscopy ,
außer dass der Versuch auf
$stderr protokolliert wird, falls verbose nicht false ist.
|
cp
|
ref.cp( fromName, toName,
verbose=false )
-> true or false |
|
Synonym für File.copy .
|
install
|
ref.install( fromName, toName,
aMode=nil , verbose=false )
|
|
Kopiert die Datei fromName nach toName und benutzt dabei
File.syscopy ,
außer toName gibt es schon und es hat den selben Inhalt wie
fromName. Setzt den Modus der Ziel-Datei auf
aMode, außer aMode ist nil .
|
makedirs
|
ref.makedirs(
[dirName]*[, aBoolean] )
|
|
Erzeugt die angegebenen Verzeichnisse, protokolliert jeden Versuch auf
$stderr falls der letze Parameter
true ist. Erzeugt auch übergeordnete Verzeichnisse, falls nötig.
|
mkpath
|
ref.mkpath(
[dirName]*[, aBoolean] )
|
|
Synonym für File.makedirs .
|
move
|
ref.move( fromName, toName,
verbose=false )
-> true or false |
|
Ändert den Namen von fromName nach toName, protokolliert
auf $stderr falls verbose nicht false ist.
|
mv
|
ref.mv( fromName, toName,
verbose=false )
-> true or false |
|
Synonym für File.move .
|
rm_f
|
ref.rm_f(
[fileName]*[, aBoolean] )
-> anInteger |
|
Synonym für File.safe_unlink
(der Name weist auf das Unix-Kommando rm -f hin).
|
safe_unlink
|
ref.safe_unlink(
[fileName]*[, aBoolean] )
-> anInteger or nil |
|
Entkoppelt (vernichtet) die angegebenen Dateien, protokolliert auf
$stderr falls der letzte Parameter true ist.
Die Methode versucht, alle Dateien vorher beschreibbar zu machen, damit kein Fehler
durch das Vernichten von nur-lesbaren Dateien auftritt. Gibt die Anzahl der vernichteten
Dateien zurück, oder nil im Fehlerfall.
|
syscopy
|
ref.syscopy( fromName, toName )
-> true or false |
|
Kopiert die Datei namens fromName nach
toName. Falls toName ein Verzeichnis bezeichnet, so ist das Ziel
eine Datei in diesem Verzeichnis mit demselben Dateinamen wie
fromName. Nach dem Kopieren ist der Modus von toName
der selbe wie der von fromName. Gibt im Erfolgsfall true
zurück.
|
 |
class GetoptLong
|
Parent:
|
Object
|
Version:
|
1.6
|
|
Index:
new each error? error_message get get_option ordering ordering= quiet quiet= quiet? set_options terminate terminated?
# Call using "ruby example.rb --size 10k -v -q a.txt b.doc"
require 'getoptlong'
# specify the options we accept and initialize
# the option parser
opts = GetoptLong.new(
[ "--size", "-s", GetoptLong::REQUIRED_ARGUMENT ],
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
[ "--query", "-q", GetoptLong::NO_ARGUMENT ],
[ "--check", "--valid", "-c", GetoptLong::NO_ARGUMENT ]
)
# process the parsed options
opts.each do |opt, arg|
puts "Option: #{opt}, arg #{arg.inspect}"
end
puts "Remaining args: #{ARGV.join(', ')}"
|
erzeugt:
Option: --size, arg "10k"
Option: --verbose, arg ""
Option: --query, arg ""
Remaining args: a.txt, b.doc
|
Die Klasse GetoptLong
liefert eine Auflösung der Kommandozeilen-Optionen
im GNU-Stil. Optionen dürfen sein: ein Minuszeichen (`-') gefolgt von einem Zeichen oder zwei
Minuszeichen (`--') gefolgt von einem Namen (die lange Option). Lange Optionen dürfen gekürzt
werden solange sie noch eindeutig bleiben.
Eine spezielle interne Option kann mehrere externe Repräsentationen besitzen. Zum Beispiel sieht
die Option für den ausführlichen Output so aus:
-v
, --verbose
oder --details
. Einige Optionen nehmen auch
einen dazugehörenden Wert entgegen.
Jede interne Option wird an GetoptLong
als Array weitergegeben, das
Strings enthält, die die externen Formen der Option bezeichnen, sowie ein Flag.
Das Flag (NO_ARGUMENT
, REQUIRED_ARGUMENT
oder
OPTIONAL_ARGUMENT
) gibt an, wie GetoptLong
mit einem
dazugehörenden Argument umgehen soll.
Falls die Umgebungs-Variable
POSIXLY_CORRECT
gesetzt ist, müssen alle Optionen in der Kommandozeile vor
Nicht-Optionen kommen. Andernfalls und als Default-Einstellung wird
GetoptLong
die Kommandozeile sortieren und die Optionen an den Anfang
setzen. Diese Verhalten kann man ändern, indem man
GetoptLong#ordering=
setzt, und zwar auf eine der Konstanten
PERMUTE
, REQUIRE_ORDER
oder RETURN_IN_ORDER
.
POSIXLY_CORRECT
darf nicht überschrieben werden.
Konstanten für Optionen |
NO_ARGUMENT |
|
Eine Option, die keine Argumente erwartet. |
OPTIONAL_ARGUMENT |
|
Eine Nicht-Option, die nach dieser Option kommt, wird als Argument dieser
Option genutzt. |
REQUIRED_ARGUMENT |
|
Nach dieser Option muss ein Argument kommen. |
 |
Konstanten für alles |
PERMUTE |
|
Optionen und ihre Argumente werden an den Anfang der Komanndozeile geschoben.
|
REQUIRE_ORDER |
|
Optionen und ihre Argumente müssen am Anfagn der Kommandozeile
stehen. Nach der ersten Nicht-Option werden keine Optionen mehr
akzeptiert. |
RETURN_IN_ORDER |
|
Liefert die Optionen in der Reihenfolge zurück, in der sie in der
Kommandozeile stehen. |
 |
class methods
|
new
|
GetoptLong.new( [options]* ) -> ref |
|
Liefert einen neuen Options-Parser. Alle options werden an
ref.set_options weitergegeben.
|
instance methods
|
each
|
ref.each {| anOption, anArgument | block }
|
|
Durchläuft eine Schleife und ruft dabei GetoptLong#get auf,
übergibt die zurückgegebene Option und das Argument an den angeschlossenen Block. Die Schleife
endet, falls get für anOption nil zurückliefert.
|
error?
|
ref.error?
-> anException |
|
Liefert ein Exception -Objekt, das jeden aufgetretenen Felhler
dokumentiert, oder nil falls es keinen Fehler gab.
|
error_message
|
ref.error_message
-> aString |
|
Liefert den Text der letzten Fehlermeldung.
|
get
|
ref.get -> [ anOption,
anArgument ] |
|
Liefert die nächste Option, zusammen mit einem dazu gehörenden Argument. Wenn es kein
Argument gibt, wird nil für
anArgument zurück gegeben. Wenn keine nicht abgehandelten Optionen mehr übrig
sind oder wenn ein Fehler bei der Abarbeitung der Optionen aufgetreten ist, so wird, falls
quiet gesetzt ist, nil für anOption zurückgegeben.
Andernfalls, wenn ein Fehler auftrat, wird eine Meldung an $stderr geschickt und
eine Exception (eine Unterklasse von StandardError ) wird ausgelöst.
Der zurückgegebene Options-String ist die erste Option, die im dazugehörenden
an set_options übergebenen Array stand.
|
get_option
|
ref.get_option -> [ anOption,
anArgument ] |
|
Synonym für GetoptLong#get .
|
ordering
|
ref.ordering -> aFixnum |
|
Liefert die aktuelle Ordnung.
|
ordering=
|
ref.ordering = aFixnum |
|
Bestimmt die Ordnung, das ist eine von PERMUTE , REQUIRE_ORDER
oder RETURN_IN_ORDER . Wird stillschweigend ignoriert, falls die
Umgebungsvariable POSIXLY_CORRECT gesetzt ist. Die Ordnung darf nicht mehr
verändert werden, wenn die Options-Abarbeitung schon angefangen hat.
|
quiet
|
ref.quiet -> true or false |
|
Liefert den aktuellen Werte des quiet -Attributs.
|
quiet=
|
ref.quiet = true or false |
|
Setzt den aktuellen Wert des quiet -Attributs. Wenn auf false
gesetzt, werden alle aurtretenden Fehler nach
$stderr geschickt.
|
quiet?
|
ref.quiet? -> true or false |
|
Synonym für GetoptLong#quiet .
|
set_options
|
ref.set_options(
[anOptArray]* ) -> ref |
|
Jeder Parameter ist ein Array, das eine einzelne interne Option bezeichnet.
Das Array enthält einen oder mehrere Strings, die die externe(n) Form(en) der
Option bezeichnen, und eines der Flags NO_ARGUMENT ,
OPTIONAL_ARGUMENT oder REQUIRED_ARGUMENT . Für Anwendungsbeispiele
siehe den Beispiel-Code
auf Seite 452.
|
terminate
|
ref.terminate -> ref |
|
Beendet die Options-Abarbeitung. Alle noch übrigen Argumente werden zurück
nach ARGV geschrieben. Das kann innerhalb von
GetoptLong#each aufgerufen werden oder
auch alleinstehend.
Wenn wir zum Beipiel das folgende Programm mit ``ruby example.rb --size 10k -v
-term -q a.txt b.doc '' aufrufen, bleibt -q und die Dateinamen in
ARGV stehen.
require 'getoptlong'
opts = GetoptLong.new(
[ "--size", "-s", GetoptLong::REQUIRED_ARGUMENT ],
[ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
[ "--term", "-t", GetoptLong::NO_ARGUMENT ],
[ "--query", "-q", GetoptLong::NO_ARGUMENT ],
[ "--check", "--valid", "-c", GetoptLong::NO_ARGUMENT ]
)
opts.each do |opt, arg|
puts "Option: #{opt}, arg #{arg.inspect}"
opts.terminate if (opt == '--term')
end
puts "Remaining args: #{ARGV.join(', ')}"
|
erzeugt:
Option: --size, arg "10k"
Option: --verbose, arg ""
Option: --term, arg ""
Remaining args: -q, a.txt, b.doc
|
|
terminated?
|
ref.terminated?
-> true or false |
|
Liefert true , wenn die Options-Abarbeitung beendet ist.
|
 |
Index:
create_makefile dir_config find_library have_func have_header have_library
Die mkmf
-Bibliothek wird von Ruby-Erweiterungs-Modulen benutzt,
um Makefiles
zu erzeugen. Wenn man eine Erweiterung schreibt, erzeugt man ein Programm
namens ``extconf.rb
''. Das kann ganz einfach aussehen, etwa:
require 'mkmf'
create_makefile("Test")
|
Nach dem Starten erzeugt dieses Script ein Makefile
passend auf die Ziel-Plattform.
mkmf
enthält verschiedene Methoden zum Auffinden von Bibliotheken
und Einbinden von Dateien und um Compiler-Flags zu setzen.
Mehr Informationen über das Erzeugen von Erweiterungs-Modulen gibt es im
Kapitel 17 ab Seite 171.
|
PLATFORM |
unterschiedlich |
Ein konstanter String, der die Plattform beschreibt, auf der Ruby läuft, etwa
``mswin32'' oder
``i686-linux.'' |
$CFLAGS |
|
Globale Variable für Compiler-Flags. |
$LDFLAGS |
|
Globale Variable für Linker-Flags. |
instance methods
|
create_makefile
|
create_makefile( target )
|
|
Erzeugt ein Makefile für eine Erweiterung namens target.
Wenn diese Methode nicht aufgerufen wird, dann wird auch kein Makefile erzeugt.
|
dir_config
|
dir_config( name )
|
|
Sucht nach den Optionen der Verzeichnis-Konfiguration für name, die als
Argumente zu diesem Programm oder bei der ursprünglichen Erstellung von Ruby angegeben
waren. Diese Argumente können so aussehen:
--with- name-dir =directory |
--with- name-include =directory |
--with- name-lib =directory |
Die angegebenen Verzeichnisse werden zum passenden Such-Pfad (include oder link)
im Makefile hinzugefügt.
|
find_library
|
find_library( name,
function, [path]+ )
-> true oder false |
|
Das selbe wie have_library , sucht zusätzlich in den angegebenen
Verzeichnissen.
|
have_func
|
have_func( function )
-> true oder false |
|
Wenn die genannte Funktion in der Standard-Compile-Umgebung existiert, so wird die
Direktive -DHAVE_FUNCTION zum Compile-Kommando im Makefile
hinzugefügt und true zurück gegeben.
|
have_header
|
have_header( header )
-> true oder false |
|
Wenn die angegebene Header-Datei im Standard-Such-Pfad gefunden werden kann, so wird
die Direktive -DHAVE_HEADER zum Compile-Kommando im Makefile hinzugefügt und true zurück gegeben.
|
have_library
|
have_library( library,
function ) -> true or false |
|
Wenn die agegebene Funktion in der genannten Bibliothek, die im Standard-Such-Pfad oder
in einem mit dir_config hinzugefügten Verzeichnis liegen muss, existiert, so wird
die Bibliothek zum Link-Kommando im Makefile hinzugefügt und true zurück
gegeben.
|
 |
Index:
parsedate
Im ParseDate
-Modul wird nur eine einzige Methode definiert,
ParseDate::parsedate
, die einen Datums- und/oder
Zeit-String in seine Bestandteile auflöst. Dabei benutzt sie Methoden, die eine große Vielfalt an
Datums- und Zeit-Formaten behandelt, inclusive einer Untermenge von ISO 8601,
Unix-ctime
und die meisten gebräuchlichen geschriebenen Varianten.
Die folgende Tabelle gibt einige Beispiele.
StringGuess? |
yy |
mm |
dd |
hh |
min |
sec |
zone |
wd |
1999-09-05 23:55:21+0900 |
F |
1999 |
9 |
5 |
23 |
55 |
21 |
+0900 |
-- |
1983-12-25 |
F |
1983 |
12 |
25 |
-- |
-- |
-- |
-- |
-- |
1965-11-10 T13:45 |
F |
1965 |
11 |
10 |
13 |
45 |
-- |
-- |
-- |
10/9/75 1:30pm |
F |
75 |
10 |
9 |
13 |
30 |
-- |
-- |
-- |
10/9/75 1:30pm |
T |
1975 |
10 |
9 |
13 |
30 |
-- |
-- |
-- |
Mon Feb 28 17:15:49 CST 2000 |
F |
2000 |
2 |
28 |
17 |
15 |
49 |
CST |
1 |
Tue, 02-Mar-99 11:20:32 GMT |
F |
99 |
3 |
2 |
11 |
20 |
32 |
GMT |
2 |
Tue, 02-Mar-99 11:20:32 GMT |
T |
1999 |
3 |
2 |
11 |
20 |
32 |
GMT |
2 |
12-January-1990, 04:00 WET |
F |
1990 |
1 |
12 |
4 |
0 |
-- |
WET |
-- |
4/3/99 |
F |
99 |
4 |
3 |
-- |
-- |
-- |
-- |
-- |
4/3/99 |
T |
1999 |
4 |
3 |
-- |
-- |
-- |
-- |
-- |
10th February, 1976 |
F |
1976 |
2 |
10 |
-- |
-- |
-- |
-- |
-- |
March 1st, 84 |
T |
1984 |
3 |
1 |
-- |
-- |
-- |
-- |
-- |
Friday |
F |
-- |
-- |
-- |
-- |
-- |
-- |
-- |
5 |
 |
class methods
|
parsedate
|
ref.parsedate( aString, guessYear=false ) -> [ year, mon, mday,
hour, min, sec, zone, wday
] |
|
Parst einen String, der ein Datum und/oder eine Zeit enthält. Liefert ein Array von
Fixnum -Objekten, das die verschiedenen Komponenten enthält.
nil wird für Felder zurückgegeben, die nicht aufgelöst werden können.
Falls das Ergebnis ein Jahr enthält, das kleiner als 100 ist und guessYear ist true,
dann liefert parsedate als Jahr den Wert year plus 2000 falls year
kleiner als 69 ist, andernfalls year plus 1900.
|
Die profile
-Bibliothek schreibt nach $stderr
eine
Übersicht mit der Anzahl der Aufrufe von und der verbrachten Dauer in jeder Methode eines
Ruby-Programms. Der Output wird nach der Gesamtdauer der Methoden sortiert. Dieses
Profiling kann von der Kommandozeile aus angeschaltet werden mit der
-r
profile
-Option oder von innerhalb des Programms
durch Angabe von require für das profile
-Modul.
require 'profile'
def ackerman(m, n)
if m == 0 then n+1
elsif n == 0 and m > 0 then ackerman(m-1, 1)
else ackerman(m-1, ackerman(m, n-1))
end
end
ackerman(3,3)
|
erzeugt:
time seconds seconds calls ms/call ms/call name
70.77 2.30 2.30 2432 0.95 41.42 Object#ackerman
14.46 2.77 0.47 3676 0.13 0.13 Fixnum#==
9.54 3.08 0.31 2431 0.13 0.13 Fixnum#-
4.92 3.24 0.16 1188 0.13 0.13 Fixnum#+
0.31 3.25 0.01 57 0.18 0.18 Fixnum#>
0.00 3.25 0.00 1 0.00 0.00 Module#method_added
0.00 3.25 0.00 1 0.00 3250.00 #toplevel
|
class PStore
|
Parent:
|
Object
|
Version:
|
1.6
|
|
Index:
new [ ] [ ]= abort commit path root? roots transaction
Die Klasse PStore
stellt transaktionsgesicherte, datei-basierte
Speicherung von Ruby-Objekten zur Verfügung. Das folgende Beispiel speichert zwei
Hierarchien in einem PStore. Das erste, mit dem Schlüssel ``names
'', ist ein
Array aus Strings. Das zweite, mit dem Schlüssel
``tree
'', ist ein einfacher binärer Baum.
require "pstore"
class T
def initialize(val, left=nil, right=nil)
@val, @left, @right = val, left, right
end
def to_a
[ @val, @left.to_a, @right.to_a ]
end
end
store = PStore.new("/tmp/store")
store.transaction do
store['names'] = [ 'Douglas', 'Barenberg', 'Meyer' ]
store['tree'] = T.new('top',
T.new('A', T.new('B')),
T.new('C', T.new('D', nil, T.new('E'))))
end
# now read it back in
store.transaction do
puts "Roots: #{store.roots.join(', ')}"
puts store['names'].join(', ')
puts store['tree'].to_a.inspect
end
|
erzeugt:
Roots: names, tree
Douglas, Barenberg, Meyer
["top", ["A", ["B", [], []], []], ["C", ["D", [], ["E", [], []]], []]]
|
Jedes PStore
kann mehrere Objekt-Hierarchien speichern.
Jede Hierarchie besitzt eine Wurzel, die durch einen Schlüssel (oftmals ein String)
gekennzeichnet wird. Am Anfang einer PStore
-Transaction
werden diese Hierarchien aus einer Datei gelesen und dem Ruby-Programm zur
Verfügung gestellt. Am Ende der Transaction werden die Hierarchien wieder zurück
in die Datei geschrieben. Alle Änderungen an den Objekten dieser Hierarchien werden daher
auf Platte gespeichert, um bei der nächsten Transaction, die diese Datei benutzt, wieder
gelesen zu werden.
Im Normalfall wird ein PStore
-Objekt erzeugt und dann ein- oder
mehrmals benutzt, um eine Transaction zu kontrollieren. Innerhalb des Rumpfes einer
Transaction werden alle Objekt-Hierarchien, die vorher gesichert waren, wieder zugänglich
gemacht, und alle Änderungen an Objekt-Hierarchien und alle neuen Hierarchien werden
zum Schluss zurück auf Platte geschrieben.
class methods
|
new
|
PStore.new( aFilename )
-> aPStore |
|
Liefert ein neues PStore -Objekt, das zur angegebenen
Datei gehört. Wenn die Datei schon existiert, muss sie vorher schon mit
PStore geschrieben worden sein.
|
instance methods
|
[ ]
|
ref[ anObject ] -> anOtherObject |
|
Zugriff auf die Wurzel --- Liefert die Wurzel einer Objekt-Hierarchie zum Objekt
anObject. Eine Exception wird ausgelöst, wenn für anObject kein
Wurzelobjekt existiert.
|
[ ]=
|
ref[ anObject ] =
anOtherObject-> anOtherObject |
|
Wurzel-Erzeugung --- Setzt anOtherObject als Wurzel der Objekt-Hierarchie, die
durch anObject angesprochen wird.
|
abort
|
ref.abort
|
|
Beendet diese Transaction, alle Änderungen an der Objekt-Hierarchie gehen verloren.
|
commit
|
ref.commit
|
|
Beendet die aktuelle Transaction, sichert die Obejkt-Hierarchien in der dazugehörenden Datei.
|
path
|
ref.path -> aString |
|
Liefert den Namen der mit dieser Transaction verbundenen Datei.
|
root?
|
ref.root?( anObject )
-> true or false |
|
Liefert true falls anObject der Schlüssel einer Wurzel in diesem
Speicherbereich ist.
|
roots
|
ref.roots -> anArray |
|
Liefert die Schlüssel zu den Wurzel-Objekten, die zu diesem Speicherbereich gehören.
|
transaction
|
ref.transaction {| ref | block }-> anObject |
|
Wenn die zu ref gehörende Datei existiert, wird aus ihr in der Objekt-Hierarchie
gelesen. Dann wird der zugehörige Block ausgeführt, wobei ref übergeben wird.
Der Block kann dann über diesen Parameter auf die Wurzeln der Hierarchien zugreifen und so
die geschützten Objekte erreichen. Falls der Block PStore#abort
aufruft oder eine Exception auslöst, werden keine Daten zurück in die Datei geschrieben.
Anderenfalls, wenn er PStore#commit aufruft oder
normal beendet wird, werden die Objekt-Hierarchien in die Datei zurück geschrieben. Der
Rückgabewert ist der Rückgabewert des Blocks.
|
 |
class Tempfile
|
Parent:
|
[IO]
|
Version:
|
1.6
|
|
Index:
new open close open path
require "tempfile" |
|
tf = Tempfile.new("afile") |
tf.path |
» |
"/tmp/afile14822.0" |
tf.puts("Cosi Fan Tutte") |
» |
nil |
tf.close |
» |
nil |
tf.open |
» |
#<File:0x4016e3c0> |
tf.gets |
» |
"Cosi Fan Tutte\n" |
tf.close(true) |
» |
#<File:0x4016e3c0>\n0x40187c30 |
Die Klasse Tempfile
erzeugt verwaltete temporäre Dateien. Obwohl sie sich
genauso wie andere IO
.Objekte auch verhalten, werden temporäre Dateien
automatisch vernichtet, wenn ein Ruby-Programm beendet wird. Wenn man erstmal ein
Tempfile
-Objekt erzeugt hat, kann man die darunter liegende Datei
immer wieder öffnen und schließen.
Die Klasse Tempfile
wird nicht direkt von der Klasse IO
abgeleitet. Stattdessen gibt sie die Aufrufe an ein File
-Objekt weiter.
Aus Sicht des Programmieres verhält es sich, mit Ausnahme der unüblichen new
,
open,
und
close
Ausdrücke, als wäre es ein IO
-Objekt.
class methods
|
new
|
Tempfile.new( basename,
tmpdir=<see below> )
-> ref |
|
Erzeugt eine temporäre Datei im angegebenen Verzeichnis. Der Dateiname wird gebildet aus
dem basename, der aktuellen Prozess-Id und (als Extension) einer eindeutigen
laufenden Nummer. Wenn kein tmpdir-Parameter angegeben ist, wird
defaultmäßig eine der Umgebungsvariablen TMPDIR , TMP ,
oder TEMP genommen, oder das Verzeichnis /tmp .
Die Datei wird dann im Modus ``w+'' geöffnet, das ermöglicht Lesen und
Schreiben und zerstört eventuell vorher schon vorhandenen Inhalt (siehe Tabelle
22.5 auf Seite 331).
|
open
|
Tempfile.open( basename,
tmpdir )
-> ref |
|
Synonym für Tempfile.new .
|
instance methods
|
close
|
ref.close( final=false )
|
|
Schließt ref. Falls final true ist, wird die
zu Grunde liegende Datei zerstört. Falls final false ist,
darf man ref später wieder öffnen. Auf jeden Fall wird die zu Grunde
liegende Datei bei Programmende zerstört.
|
open
|
ref.open
|
|
Öffnet ref wieder im Modus ``r+'', welcher Lesen und Schreiben ermöglicht,
aber keinen schon vorhandenen Inhalt löscht.
|
path
|
ref.path -> aString |
|
Liefert den vollständigen Pfad für die zu Grunde liegende Datei.
|
class Mutex
|
Parent:
|
Object
|
Version:
|
1.6
|
|
Index:
lock locked? synchronize try_lock unlock
require 'thread'
sema4 = Mutex.new
a = Thread.new {
sema4.synchronize {
# access shared resource
}
}
b = Thread.new {
sema4.synchronize {
# access shared resource
}
}
|
Mutex
implementiert ein einfaches Semaphore, das man zur
Koordinierung des Zugriffs auf gemeinsame Daten bei mehreren gleichzeitigen Threads
nehmen kann.
instance methods
|
lock
|
ref.lock
-> ref |
|
Versucht die Blockierung zu ergattern und wartet, wenn sie noch nicht verfügbar ist.
|
locked?
|
ref.locked?
-> true or false |
|
Liefert true , falls diese Blockierung momentan schon von einem
Thread gehalten wird.
|
synchronize
|
ref.synchronize { block }-> ref |
|
Greift sich eine Blockierung (mit Mutex#lock ),
lässt den Block laufen und gibt die Blockierung wieder frei, wenn der Block fertig ist.
|
try_lock
|
ref.try_lock -> true or false |
|
Versucht sich eine Blockierung zu greifen und kehrt sofort zurück.
Liefert true , falls die Blockierung erhalten wurde.
|
unlock
|
ref.unlock
-> ref or nil |
|
Gibt eine Blockierung wieder frei. Lieert nil falls ref
nicht blockiert war.
|
class ConditionVariable
|
Parent:
|
Object
|
Version:
|
1.6
|
|
Index:
broadcast signal wait
require 'thread'
mutex = Mutex.new
resource = ConditionVariable.new
a = Thread.new {
mutex.synchronize {
# Thread 'a' braucht jetzt resource
resource.wait(mutex)
# 'a' kann nun resource haben
}
}
b = Thread.new {
mutex.synchronize {
# Thread 'b' ist fertig mit resource
resource.signal
}
}
|
ConditionVariable
-Objekte erweitern die Klasse Mutex
.
Mit Condition-Variablen kann man innerhalb von kritischen Bereichen einfach abwarten,
bis eine Resource zur Verfügung steht (siehe die Abhandlung auf Seite 119).
instance methods
|
broadcast
|
ref.broadcast
|
|
Weckt alle Threads auf, die auf diese Blockierung warten.
|
signal
|
ref.signal
|
|
Weckt den ersten Thread auf, der auf diese Blockierung wartet.
|
wait
|
ref.wait( aMutex )
-> aMutex |
|
Gibt die über aMutex gehaltene Blockierung auf und wartet dann;
beim Aufwachen wird die Blockierung wieder geholt.
|
require "timeout"
for snooze in 1..2
puts "About to sleep for #{snooze}"
timeout(1.5) do
sleep(snooze)
end
puts "That was refreshing"
end
|
erzeugt:
About to sleep for 1
That was refreshing
About to sleep for 2
/tc/usr/lib/ruby/1.6/timeout.rb:37: execution expired (TimeoutError)
from prog.rb:5:in `timeout'
from prog.rb:5
from prog.rb:3:in `each'
from prog.rb:3
|
Die timeout
-Methode nimmt als einzelnen Parameter die Timeout-Periode entgegen,
sowie einen Block. Der Block wird ausgeführt während der Timer gleichzeitig läuft. Falls
der Block vor dem Timeout fertig ist, liefert timeout
true
.
Andernfalls wird eine TimeoutError
-Exception ausgelöst.
class WeakRef
|
Parent:
|
Delegator
|
Version:
|
1.6
|
|
Index:
new weakref_alive?
require "weakref"
ref = "fol de rol"
puts "Initial object is #{ref}"
ref = WeakRef.new(ref)
puts "Weak reference is #{ref}"
ObjectSpace.garbage_collect
puts "But then it is #{ref}"
|
erzeugt:
Initial object is fol de rol
Weak reference is fol de rol
n finals=>1
0x40188a7c
n finals=>0
prog.rb:8: Illegal Reference - probably recycled (WeakRef::RefError)
|
In Ruby werden Objekte nicht für die Garbage-Collection freigegeben, wenn es
immer noch Referenzen auf sie gibt. Normalerweise ist das eine gute Sache --- es wäre
äußerst unschön, wenn Objekte sich einfach in Luft auflösen, während man sie
noch benutzt. Andererseits braucht man manchmal etwas mehr Flexibilität. Man will
zum Beispiel den Inhalt von oft benutzten Dateien als Cache im Speicher halten. Je mehr
Dateien man einliest, desto größer wird dann der Cache. Irgendwann wird dann der Speicher
knapp, der Garbage-Collecter wird aufgerufen, aber die Objekte im Cache werden alle
von der Cache-Verwaltung referenziert und können deshalb nicht vernichtet werden.
Eine Weak-Reference (schwache Referenz) verhält sich ganz genau wie ein
normales Objekt mit einer wichtigen Ausnahme --- das referenzierte Objekt kann Opfer
der Garbage-Collection werden, selbst wenn noch eine Referenz darauf existiert.
Wenn man in dem Cache-Beispiel die gecacheten Dateien über Weak-References anspricht,
so können sie durch den Garbage-Colletor vernichtet werden, wenn der Speicherplatz
knapp wird, und der Rest der Applikation hat wieder genug davon.
Natürlich sind Weak-References nicht ganz so einfach zu behandeln. Da das
referenzierte Objekt jederzeit vom Garbage-Collector vernichtet werden kann, muss der Code,
der darauf zugreift, erst sicherstellen, dass die Referenzen auch noch gültig sind. Dafür
gibt es zwei Techniken. Zunächst kann man das Objekt ganz normal ansprechen. Jeder Versuch,
ein vom Garbage-Collector vernichtetes Objekt zu referenzieren, löst eine
WeakRef::RefError
-Exception aus, die man dann behandeln kann.
Ein anderer Zugang liegt in der Benutzung der
WeakRef#weakref_alive?
-Methode, um die Gültigkeit
einer Referenz vor ihrer Benutzung zu prüfen. Die Garbage-Collection muss natürlich
währenddessen und während darauf folgender Zugriffe auf das Objekt ausgeschaltet
bleiben. In einem Programm mit nur einem Thread kann man das etwa wie folgt
machen:
ref = WeakRef.new(someObject)
#
# .. some time later
#
gcWasDisabled = GC.disable
if ref.weakref_alive?
# do stuff with 'ref'
end
GC.enable unless gcWasDisabled
|
class methods
|
new
|
WeakRef.new( anObject )
-> ref |
|
Erzeugt eine Weak-Reference auf anObject und liefert diese zurück. Alle weiteren
Referenzen auf anObject sollten dann über ref laufen.
|
instance methods
|
weakref_alive?
|
ref.weakref_alive?
-> true or false |
|
Liefert false , wenn das über ref referenzierte Objekt
schon vom Garbage-Collector vernichtet wurde.
|
Extracted from the book "Programming Ruby -
The Pragmatic Programmer's Guide"
Übersetzung: Jürgen Katins
Für das englische Original:
©
2000 Addison Wesley Longman, Inc. Released under the terms of the
Open Publication License V1.0.
That reference is available for
download.
Diese Lizenz sowie das Original vom Herbst 2001 bilden die Grundlage der
Übersetzung
Es wird darauf hingewiesen, dass sich die Lizenz des englischen Originals
inzwischen geändert hat.
Für die deutsche Übersetzung:
© 2002 Jürgen Katins
Der Copyright-Eigner stellt folgende Lizenzen zur Verfügung:
Nicht-freie Lizenz:
This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/).
Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.
Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.
Freie Lizenz:
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
or any later version published by the Free Software Foundation;
with no Invariant Sections, with no
Front-Cover Texts, and with no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".