"eigenes" printf
am 04.05.2006 19:35:59 von Carsten Broschek
Hallo NG!
Ich würde gerne Values aus einem Array mit einer selbstdefinierten
Formatierung ausgeben. In der Art:
printMe "Hier %xyz %s kommt %nmx ein Kart", $values;
Als Perl-Neuling würden mich Ideen interessieren, wie ich am einfachsten
durch den Formatstring iterieren kann und die %xyz durch die $values[x]
ersetzen kann.
Dankbar für Hinweise,
CARSTEN
Re: "eigenes" printf
am 04.05.2006 21:09:33 von Slaven Rezic
Carsten Broschek writes:
> Hallo NG!
>
> Ich würde gerne Values aus einem Array mit einer selbstdefinierten
> Formatierung ausgeben. In der Art:
>
> printMe "Hier %xyz %s kommt %nmx ein Kart", $values;
>
> Als Perl-Neuling würden mich Ideen interessieren, wie ich am einfachsten
> durch den Formatstring iterieren kann und die %xyz durch die $values[x]
> ersetzen kann.
>
Versuch mal:
$fmtstring =~ s{%([a-z]+)}{$values->{$1}}g;
--
Slaven Rezic - slaven rezic de
Berlin Perl Mongers - http://berlin.pm.org
Re: "eigenes" printf
am 04.05.2006 22:02:21 von Mirco Wahab
Hallo Carsten
> Ich würde gerne Values aus einem Array mit einer selbstdefinierten
> Formatierung ausgeben. In der Art:
> printMe "Hier %xyz %s kommt %nmx ein Kart", $values;
>
> Als Perl-Neuling würden mich Ideen interessieren, wie ich am einfachsten
> durch den Formatstring iterieren kann und die %xyz durch die $values[x]
> ersetzen kann.
Die direkte Übersetzung deiner Idee hat Slaven
bereits auf den Punkt gebracht.
Nun kann es aber sein, dass bei unterschiedlichen
'xyz' oder 'abc' jeweils etwas gänzlich anderes
gemacht werden soll (wissen wir ja nicht ;-).
Dann würde mann vielleicht einen Hash 'Xfmt' mit
den Formatzeichen als 'key' und Closures für die
Formatierung als 'value' nehmen, vielleicht sowas:
# - - - - - - - - - - - - - - - - - - - - - - #
my %Xfmt = (
xyz => sub { 'xyz<' . $_[0] . '>'; }, # hier formatierung
nmx => sub { 'nmx<' . $_[0] . '>'; }, # durchfuehren
);
sub disptch
{
my ($f, $v) = @_;
return exists $Xfmt{$f} ? &{$Xfmt{$f}}($v) : sprintf "%$f", $v;
}
sub printMe
{
my ($fmt, @a) = @_;
my $cnt=0;
$fmt =~ s/%(\w+)/disptch($1,$a[$cnt++])/eg;
print $fmt;
}
my @values = (2, 'Ha', 9);
printMe "Hier %xyz %s kommt %nmx ein Kart", @values;
# - - - - - - - - - - - - - - - - - - - - - - #
Oder sowas. Ein Dispatcher 'disptch' wird im Regex mit /e
pro %irgendwas aufgerufen und prüft, ob es sich um eine
'eigene' Formatierung handelt oder nicht - sonst wird eben
'sprintf' involviert. Nur so eine Idee ;-)
Viele Grüße
M.
"perlish"-Version
am 04.05.2006 23:14:31 von Mirco Wahab
Hallo
> Dann würde mann vielleicht ...
Ich hab noch mal drüber nachgedacht
und denke, dass das (unten) eine
'more perlish'-Variante ist.
Vielleicht kann mal jemand was dazu
sagen, ob das der Holzweg ist oder nicht.
Allerdings hab ich's nicht geschafft, ohne
einen Closure-Dispatcher auszukommen, da man
ja nicht:
{
undef => sub fallback { ... },
...
}
in den Hash schreiben kann.
Hmmm.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - #
my %XF = ( _fb => sub { sprintf "%$_[0]", $_[1]; }, # Fallback
xyz => sub { 'xyz<' . $_[1] . '>'; },
nmx => sub { 'nmx<' . $_[1] . '>'; } );
sub disptch
{
exists $XF{$_[0]} ? goto &{$XF{$_[0]}} : goto &{$XF{_fb}};
}
sub printMe
{
my ($f, @a) = @_;
$f =~ s/%(\w+)/disptch $1, shift @a/eg;
print $f;
}
printMe "Hier %xyz %s kommt %nmx ein Kart", 2, 'Ha', 9;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - #
Viele Grüße
M.
Re: "eigenes" printf
am 04.05.2006 23:25:10 von Christian Lackas
* Mirco Wahab [2006-05-04]:
Hallo Mirco,
> Dann würde mann vielleicht einen Hash 'Xfmt' mit
> den Formatzeichen als 'key' und Closures für die
> Formatierung als 'value' nehmen, vielleicht sowas:
> my %Xfmt = (
> xyz => sub { 'xyz<' . $_[0] . '>'; }, # hier formatierung
> nmx => sub { 'nmx<' . $_[0] . '>'; }, # durchfuehren
> );
die Idee ist hier sehr vielversprechend, allerdings sind benutzt du
dafür normale anonyme Subroutinen, kein Closures (dafür fehlt die Refenz
auf eine lexikalische Variable außerhalb des Scopes der Subroutine).
Eine gute Erklärung zum Begriff 'closure' gibt es hier:
perldoc -q closure
Gruß
Christian
--
Murphys Law 7: Je einfacher eine Änderung zu sein scheint, um so größere
Kreise zieht sie und um so mehr Pläne müssen neu erstellt werden.
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker
Re: "eigenes" printf
am 05.05.2006 00:11:50 von Mirco Wahab
Hallo Christian
> ... allerdings benutzt du dafür normale anonyme Subroutinen,
> kein Closures (dafür fehlt die Refenz auf eine lexikalische
> Variable außerhalb des Scopes der Subroutine).
> Eine gute Erklärung zum Begriff 'closure' gibt es hier:
>
> perldoc -q closure
>
Danke für die Präzisierung. Ich wusste bisher
tatsächlich nicht, anhand welcher Merkmale man
die Begriffe
- anonymous subroutine
- closure
verwenden muss, um sich richtig ausdrücken zu
können.
Aber jetzt! ;-))
Viele Grüße & Dank
Mirco
Re: "perlish"-Version
am 05.05.2006 00:34:32 von Mirco Wahab
Mirco Wahab wrote:
> Allerdings hab ich's nicht geschafft, ohne
> einen Closure-Dispatcher auszukommen, da man
> ja nicht ...
Sorry, das musste jetzt sein ;-) ==>
my %XF = ( _fb => sub { sprintf "%$_[0]", $_[1]; }, # Fallback
xyz => sub { 'xyz<' . $_[1] . '>'; },
nmx => sub { 'nmx<' . $_[1] . '>'; } );
sub printMe
{
my ($f, @a) = @_;
$f =~ s/%(\w+)/&{$XF{exists $XF{$1} ? $1 : _fb}}($1, shift @a)/eg;
print $f;
}
printMe "Hier %xyz %s kommt %nmx ein Kart", 2, 'Ha', 9;
(es hat mir keine Ruhe gelassen).
Zwar nicht besonders schön, aber
zumindest 'funktional'.
Viele Grüße
M.
Re: "perlish"-Version
am 05.05.2006 10:28:14 von Christian Lackas
* Mirco Wahab [2006-05-04]:
Hallo Mirco,
> Sorry, das musste jetzt sein ;-) ==>
> my %XF = ( _fb => sub { sprintf "%$_[0]", $_[1]; }, # Fallback
> xyz => sub { 'xyz<' . $_[1] . '>'; },
> nmx => sub { 'nmx<' . $_[1] . '>'; } );
ich würde hier noch ein
'%' => sub { '%' }
hinzufügen, damit man auch '%' wie üblich ausgeben kann.
> sub printMe
> {
> my ($f, @a) = @_;
> $f =~ s/%(\w+)/&{$XF{exists $XF{$1} ? $1 : _fb}}($1, shift @a)/eg;
Die Notation mit dem &{} ist so perl4. Nimm doch lieber den -> Operator
(wie auch bei anderen Refernzen):
$XF{_fb}->($1, shift @a);
Außerdem kann man das exists-Konstrukt noch etwas kompakter schreiben:
$f =~ s/%(%|\w+)/($XF{$1}||$XF{_fb})->($1, shift @a)/eg;
(habe hier auch den Fall '%%' hinzugefügt).
> print $f;
> }
> printMe "Hier %xyz %s kommt %nmx ein Kart", 2, 'Ha', 9;
printMe "Hier %xyz %s kommt %nmx ein Kart (%%f)", 2, 'Ha', 9;
Liefert dann:
Hier xyz<2> Ha kommt nmx<9> ein Kart (%f)
> Zwar nicht besonders schön, aber zumindest 'funktional'.
Wo mangelt es dir denn hier an Schönheit?
Gruß
Christian
--
Gebildet sein heißt:
Sich nicht merken zu lassen, wie schlecht man ist.
(Friedrich Nietzsche, dt. Philosoph, 1844-1900)
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker
Re: "perlish"-Version
am 05.05.2006 10:31:07 von Christian Lackas
* Christian Lackas [2006-05-05]:
Hallo Mirco,
> > Sorry, das musste jetzt sein ;-) ==>
> > my %XF = ( _fb => sub { sprintf "%$_[0]", $_[1]; }, # Fallback
> > xyz => sub { 'xyz<' . $_[1] . '>'; },
> > nmx => sub { 'nmx<' . $_[1] . '>'; } );
> ich würde hier noch ein
> '%' => sub { '%' }
wobei man das auch weglassen kann, da das ja auch so vom fallback
behandelt wird, reicht also diesen Fall unten in die RegExp zu
berücksichtigen (wobei eine eigene sub effizienter ist).
> $f =~ s/%(%|\w+)/($XF{$1}||$XF{_fb})->($1, shift @a)/eg;
Gruß
Christian
--
Die Schwerkraft ist ein Mythos: Die Erde saugt!
http://www.lackas.net/ Perl Delphi Linux MP3 Searchengines Domainchecker
Re: "perlish"-Version
am 05.05.2006 16:51:58 von Mirco Wahab
Hallo Christian
>> ich würde hier noch ein
>> '%' => sub { '%' }
>
> wobei man das auch weglassen kann, da das ja auch so vom fallback
> behandelt wird, reicht also diesen Fall unten in die RegExp zu
> berücksichtigen (wobei eine eigene sub effizienter ist).
>
>> $f =~ s/%(%|\w+)/($XF{$1}||$XF{_fb})->($1, shift @a)/eg;
danke für Deine Tipps, die einzige Schwierigkeit,
die ich sehe, ist die, dass %%f kein Argument von
der Liste shiften darf.
Hier meine dahingehend korrigierte Version. Vielleicht
kannst Du noch einige Ecken rausbügeln ;-)
my %XF = (
_fb => sub { sprintf "%$_[0]", $_[1]; }, # Fallback
lines => sub { '|||' . $_[1] . '|||'; },
brick => sub { '#' . $_[1] . '#'; },
vOwEl => sub { $_[1] =~ tr/aeiou/AEIOU/, $_[1]; }
);
sub printMe
{
my ($f, @a) = @_;
$f =~ s/ (.)%(\w+) /
$1 . ($1 ne '%' ? ($XF{$2} || $XF{_fb})->($2, shift @a) : $2)
/egx;
print $f;
}
my @values = (2, 'Ha', 9, 'abrakadabra');
printMe "Hier %lines %s kommt %brick ein (%%f) %vOwEl kart ", @values;
(Resultat: Hier |||2||| Ha kommt #9# ein (%f) AbrAkAdAbrA kart)
Viele Grüße & Dank
M.