Re: wie expandiere ich hashvalues in einem string
Pit Capitain <[email protected]> Thu, 24 Feb 2005 21:04:47 +0100
| Newsgroups | gmane.comp.lang.ruby.german |
|---|---|
| Message-ID | <[email protected]> |
robert kuzelj schrieb:
> das ist schon wesentlich besser. hab aber ein paar fragen.
Gerne. Der Code ist leider nicht so leicht zu verstehen.
> 010 def expand(template, values)
> 020 b =3D binding
> 030 v =3D nil
> 040 values.each do |name, value|
> 050 v =3D value
> 060 eval("#{name} =3D v", b)
> 070 end
> 080 eval(%Q{"#{template}"})
> 090 end
> 100
> 110 s =3D expand('Eins: #{eins}, Zwei: #{zwei}', {"eins" =3D> 111, "zwe=
i" =3D>
> 222})
> 120 puts s # =3D> Eins: 111, Zwei: 222
Zun=C3=A4chst mal nutze ich eval, um die Variablen zu erzeugen. Hierbei i=
st zu=20
beachten, dass man mit eval zwar neue lokale Variablen erzeugen kann, die=
se aber=20
au=C3=9Ferhalb von eval nicht sichtbar sind:
eval("a =3D 1")
puts a # =3D> undefined local variable or method `a'
Man kann allerdings auf diese Variablen auch sp=C3=A4ter noch mit eval zu=
greifen:
puts(eval("a")) # =3D> 1
Da das Template am Ende sowieso mit eval ausgewertet werden sollte, hat m=
ir=20
dieses Verhalten gereicht.
Ich habe den Code erst mal ohne Binding und ohne die Variable v ausprobie=
rt.=20
Dabei hat sich gezeigt, dass ich innerhalb des each Blocks zwar auf die n=
euen=20
Variablen zugreifen konnte, diese aber au=C3=9Ferhalb des Blocks nicht me=
hr sichtbar=20
waren. Also gilt auch f=C3=BCr die mit eval angelegten lokalen Variablen =
dasselbe wie=20
bei normalen lokalen Variablen: wenn sie erst in einem Block neu angelegt=
=20
werden, sind sie au=C3=9Ferhalb des Blocks nicht mehr sichtbar:
1.times do
a =3D 1
end
puts a # =3D> undefined local variable or method `a'
Daher habe ich dann den zweiten Parameter von eval benutzt, um die Variab=
len im=20
Kontext des =C3=A4u=C3=9Feren Codes zu erzeugen. Daf=C3=BCr brauchte ich =
dann wiederum die=20
Variable v aus dem =C3=A4u=C3=9Feren Kontext, um die Werte setzen zu k=C3=
=B6nnen. So ist dann=20
letztlich dieser Code entstanden.
> soweit ich aus der doku verstanden habe holt sich Kernel::binding
> die variablen bindings zum zeitpunkt des aufrufs um es zb. spaeter
> in einem aufruf von eval nutzen zu koennen. nun ist aber zb. v,
> welches du in eval nutzt noch gar nicht definiert. warum gibt das
> keinen fehler?
Mit binding bekommt man keinen Snapshot der aktuellen Variablen-Bindungen=
,=20
sondern eben nur den Kontext f=C3=BCr die Variablen. Sp=C3=A4tere =C3=84n=
derungen in diesem=20
Kontext sind dann nach wie vor =C3=BCber das vorher erzeugte Binding-Obje=
kt sichtbar.
> und schliesslich was um gottes willen macht %Q ?
Ich wollte das Template ja mit eval auswerten und brauchte daf=C3=BCr ein=
en String,=20
der einen String-Ausdruck enth=C3=A4lt. Ich brauchte also Anf=C3=BChrungs=
zeichen vor und=20
hinter dem Template. Das h=C3=A4tte ich mit
'"' + template + '"'
machen k=C3=B6nnen, aber normalerweise verwende ich die "...#{wert}..." S=
chreibweise,=20
um Strings zusammenzubauen:
"\"#{template}\""
Hier haben mich aber die \ vor den Anf=C3=BChrungszeichen etwas gest=C3=B6=
rt, und um ein=20
Konstrukt zu =C3=BCben, das ich bisher nur selten verwendet habe, habe ic=
h den=20
speziellen Quoting-Mechanismus von Ruby verwendet. Siehe hierzu z.B.
http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_stdtypes.html#S2
Gru=C3=9F,
Pit