Leser: 26
sub f {return (1,2,3)}
sub f {return LIST(1,2,3)}
my $ret = machwas();
my @ret=machwas();
2009-06-03T16:42:22 topegAuch im Arraykontext ändert sich nicht viel:
Code (perl): (dl )my @ret=machwas();
Was das nun für eine Referenz ist kann man nach der Abfrage klären.
Quote@ret ist jetzt ein einelementiges Array, ist das wirklich gewollt?
my $data = read($file);
if(is_array($data)) #...
return wantarray ? \@list : @list;
return wantarray ? @list : \@list;
2009-06-04T16:47:48 Linuxer
2009-06-04T16:07:54 sid burnam ende finde ich jetzt auch nicht so aufwendig.
1 2 3 4 5 6 7 8 9 10
use Carp; sub test { croak q{Wrong Context} unless wantarray ; return qw/a b c/; } print test(); print scalar test(); # Fehler test(); # Fehler
return-a
return !wantarray ? croak('Wrong Context'):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
package ExtReturn; use Filter::Util::Call; use strict; use warnings; sub import { my $type = shift; my $self={}; $self->{quote}=''; $self->{regtyp}=0; $self->{croak}=0; filter_add(bless $self); } sub replace { my $data=shift; $data=~s/return-a/return !wantarray ? croak('Wrong Context'): /gs; return $data } sub special { my $key=shift; return '}' if($key eq '{'); return ')' if($key eq '('); return ']' if($key eq '['); return $key; } sub filter { my $self = shift; my $status; if(($status = filter_read()) >0 ) { my $data=$_; #Modul Carp einfügen... $data="use Carp;\n" if(!$self->{croak}); $self->{croak}=1; #print "IN : $data"; my $out=''; my $block=''; my ($vor,$q); # alles nicht beachten, # was innerhalb von einem String oder Regexp ist my $reg=$self->{regtyp}? '|'.$self->{quote}: ''; while($data=~m/^(.+?)(['"]|=~|q[wxrq]?$reg)(.+)$/s) { #print "QUOTE is [$self->{quote}] REGTYP=$self->{regtyp}\n"; ($vor,$q,$data)=($1,$2,$3); #print "FOUND: $q\n"; # regexp ignorieren # String finden und ignorieren if($self->{quote} ne '') { #print "INSIDE QUOTE\n"; if($self->{quote} eq $q) { #print "MATCH : $q\n"; if($vor=~m!(\\+)$! && length($1)%2>0) { $block.=$vor.$q; } else { if($self->{regtyp}>0) { #print "REDUCE REGEXP\n"; $self->{regtyp}--; $block.=$vor.$q; if($self->{regtyp}==0) { #print "LEAVE QUOTE\n"; $self->{quote}=''; $out.=$block; $block=''; } } else { #print "LEAVE QUOTE\n"; $self->{quote}=''; $out.=$block.$vor.$q; $block=''; } } } else { $block.=$vor.$q; } } else { # außerhalb von String/Regexp $out.=replace($block.$vor).$q; $block=''; # Regexp gesondert behandeln # aber auch qw,qx,qr,qq,q if($q eq '=~') { # was für eine regexp? if($data=~/^(\s*([msy]|tr)(.))(.+)$/s) { $out.=$1; $data=$4; if($2 eq 'm') { # suchen $self->{quote}=special($3); $self->{regtyp}=1; } else { # suchen/ersetzen $self->{quote}=special($3); $self->{regtyp}=2; } } elsif($data=~m!^(\s*/)(.+)$!) { $out.=$1; $data=$2; # suchen $self->{quote}='/'; $self->{regtyp}=1; } else { # wasn das??? # Fehler im Programm?? # ignorieren... $self->{quote}=''; $self->{regtyp}=0; } } elsif($q eq 'qw' || $q eq 'qx' || $q eq 'qr' || $q eq 'qq' || $q eq 'q') { if($data=~/^(.)(.+)$/s) { $out.=$1; $data=$2; $self->{quote}=special($3); $self->{regtyp}=1; } else { # wasn das??? # Fehler im Programm?? # ignorieren... $self->{quote}=''; $self->{regtyp}=0; } } else { $self->{quote}=$q; } } $reg=$self->{regtyp}? '|'.$self->{quote}: ''; } $block=replace($block) if($self->{quote} eq ''); $data =replace($data) if($self->{quote} eq ''); $out.=$block.$data; #print "OUT: $out"; $_=$out; } return $status; } 1;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
package CheckContext; use strict; use warnings; use Attribute::Handlers; sub VOID : ATTR(CODE) { my ($pkg,$sym,$code) = @_; my $name = *{$sym}{NAME}; no warnings 'redefine'; *{ $sym } = sub { my $context = wantarray; if( defined $context ) { die "sub have to be called in void context"; } $code->( @_ ); } } sub SCALAR : ATTR(CODE) { my ($pkg,$sym,$code) = @_; my $name = *{$sym}{NAME}; no warnings 'redefine'; *{ $sym } = sub { my $context = wantarray; unless( defined $context and not $context ) { die "sub have to be called in scalar context"; } $code->( @_ ); } } sub LIST : ATTR(CODE) { my ($pkg,$sym,$code) = @_; my $name = *{$sym}{NAME}; no warnings 'redefine'; *{ $sym } = sub { my $context = wantarray; unless( defined $context and $context ) { die "sub have to be called in list context"; } $code->( @_ ); } } 1;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
package CheckTest; use strict; use warnings; use base 'CheckContext'; sub test : VOID { print 'hallo'; } sub zwo : SCALAR { return 'hallo'; } sub drei : LIST { return (1,2,3); } 1;
1
2
3
4
5
6
7
8
CheckTest::test(); # 'hallo'
my $test = CheckTest::test(); # sub have to be called in void context at CheckContext.pm line 17.
my @test = CheckTest::test(); # sub have to be called in void context at CheckContext.pm line 17.
my $zwo = CheckTest::zwo();
my @zwo = CheckTest::zwo(); # sub have to be called in scalar context at CheckContext.pm line 33.
CheckTest::zwo(); # sub have to be called in scalar context at CheckContext.pm line 33.
2009-06-05T06:43:35 reneemit caller könnte man die Fehlermeldung noch besser gestalten...
2009-06-05T08:03:12 LanX-Hi Renee,
Attribute::Handlers war ja eine meiner Alternativen, und ich denke es wär der beste Ansatz.
(Wobei meine Frage war obs zuverlässig wäre!)
2009-06-05T08:03:12 LanX-Ab Perl 5.10.0 kann man eigene Pragmas schreiben...Die weitergehende Frage ist, könnte ich am Kopf einer Datei/Blocks festlegen (wie beim strict pragma), das alle folgenden Subs z.B. nur Scalarkontext haben sollen?
2009-06-05T08:03:12 LanX-Das "die" habe ich hier für das Beispiel genommen. Ob Du jetzt "croak", "die" oder "warn" nimmst, bleibt Dir dann überlassen ;-)2009-06-05T06:43:35 reneemit caller könnte man die Fehlermeldung noch besser gestalten...
Klar, aber warum nicht croak statt die benutzen?
2009-06-05T01:04:20 topegSicher ein Sourcefilter ist nicht gut, aber ich wüsste keine andere Möglichkeit deine Wünsche zu erfüllen...
2009-06-05T01:04:20 topegSicher ein Sourcefilter ist nicht gut, aber ich wüsste keine andere Möglichkeit deine Wünsche zu erfüllen...
1 2 3 4 5 6 7 8
sub test { return LIST(@dummy); } sub LIST{ carp ("wrong context") unless wantarray; return @_; }
1 2 3 4 5 6 7 8
sub test { goto RETURN-LIST(@dummy); } sub RETURN-LIST{ carp ("wrong context") unless wantarray; return @_; }
2009-06-05T01:04:20 topegNunja der Code ist nicht sehr hübsch (Qualität Holzhammer) sollte aber funktionieren.
1
2
3
4
5
6
7
8
use autodie::hints;
autodie::hints->set_hints_for(
'Some::Package::some_sub' => {
scalar => sub { 1 },
list => sub { @_ == 2 and not defined $_[0] },
},
);