2014-11-20 3 views
8

Mit Prototypen können Sie ein Unterprogramm erstellen, die einen Codeblock als erster Parameter akzeptiert:Wie kann ich eine Perl-Subroutine erstellen, die mehr als einen Block akzeptiert?

sub example (&) { 
    my $code_ref = shift; 
    $code_ref->(); 
} 
example { print "Hello\n" }; 

Wie kann ich das gleiche tun, aber mit mehr als einem Code-Block? Ich möchte Blöcke von Codes, nicht Variablen oder sub { ... } verwenden.

funktioniert das nicht: hier

Not enough arguments for main::example2 
+0

Sie brauchen nicht wirklich Prototypen verwenden Sie Codereferenzen, Sie können sie einfach als benannte oder unbenannte U-Boote übergeben. – TLP

+1

Was Sie "Blöcke des Codes" nennen, ist genau das, was 'sub {...}' ist, nur geben Sie nicht das 'sub' Schlüsselwort ein – TLP

+1

@TLP: Sie meinen so? 'example2 sub {...}, sub {...};' Ich weiß, dass ich nur auf das Schlüsselwort oder die Variablen 'sub' verzichten möchte. Ich schätze, das kann nicht gemacht werden. – Flimm

Antwort

9

Ich hoffe, Sie erkennen, dass dies nur Code Gewürz ist, und alles, was Sie zu erreichen sind, ist ein aufgeräumter Syntax auf Kosten der Klarheit?

Perl lässt nicht zu, dass Sie mehr als einen freien Block an ein Unterprogramm übergeben, aber der zweite tatsächliche Parameter könnte ein Aufruf eines Unterprogramms sein, das auch einen einzelnen Block akzeptiert und einfach die Codereferenz zurückgibt.

Dieses Programm demonstriert. Beachten Sie, dass ich please und also als Namen für die Subroutinen gewählt habe. Aber Sie müssen etwas verwenden, das sowohl für die Funktionalität Ihres eigenen Codes geeignet ist, als auch sehr unwahrscheinlich ist, dass es mit bevorstehenden Erweiterungen der Kernsprache kollidiert.

use strict; 
use warnings; 

sub please(&$) { 
    my ($code1, $code2) = @_; 
    $code1->(); 
    $code2->(); 
} 

sub also(&) { 
    $_[0]; 
} 

please { print "aaa\n" } also { print "bbb\n" }; 

Ausgang

aaa 
bbb 
+0

Akzeptiert, weil die Antwort lautet: "Perl erlaubt Ihnen nicht, mehr als einen freien Block an ein Unterprogramm zu übergeben". Das '' '' - Ding ist schlau, aber es verhält sich in diesem Fall genau wie 'sub', also kann ich auch 'sub' verwenden. – Flimm

1

Arbeiten für mich ...

sub example2 { 
    my $code_ref = shift; 
    my $code_ref2 = shift; 
    $code_ref->(); 
    $code_ref2->(); 
} 
example2 (sub { print "One\n" }, sub { print "Hello\n" }); 

Nur für die Zwecke der TMTOWTDI a:

sub example2 (&&) { 
    my $code_ref = shift; 
    my $code_ref2 = shift; 
    $code_ref->(); 
    $code_ref2->(); 
} 
example2 { print "One\n" } { print "Hello\n" }; 

Es gibt diesen Fehler Methode, die in gewisser Weise funktioniert, wie das OP angefordert

zunächst eine Quellenfilter

package poop; 

use Filter::Util::Call; 

sub import { 
    my ($type) = @_; 
    my ($ref) = []; 
    filter_add(bless $ref); 
} 

sub filter { 
    my ($self) = @_; 
    my ($status); 
if (($status = filter_read()) > 0) { 
     if(!/sub/ && /example2/) { 
      s/\{/sub \{/g; 
      } 
     } 

    $status; 
} 
1; 

Zweitens muss der Filter

use poop; 

sub example2 { 
    my $code_ref = shift; 
    my $code_ref2 = shift; 
    $code_ref->(); 
    $code_ref2->(); 
} 
example2 ({ print "One\n" }, { print "Hello\n" }); 

ps verwendet werden. Das ist entsetzlich und niemand würde dies in der Produktion sehen wollen.

1

Haben Sie versucht, ein Komma zwischen den beiden Blöcken zu setzen?

You have:   example { print "One\n" } { print "Hello\n" }; 
You probably want: example { print "One\n" }, { print "Hello\n" }; 

ich war falsch ...

Aber das funktioniert für mich:

 example { print "One\n" } sub { print "Hello\n" }; 
+0

Haben Sie es versucht und sehen, ob es funktioniert? Es ist nicht für mich. – TLP

+2

Ich habe meine Antwort aktualisiert ... Vielleicht könnten Sie uns sagen, warum es wichtig ist, Blöcke anstelle von anonymen Subs zu übergeben. Es ist Ruby, oder? –

+0

Die Frage ist nicht über Ruby - es geht um Perl (im Titel und Tags angegeben). –

0

Sie könnten nur eval die Blöcke

use experimental 'signatures'; 
use feature 'say'; 

sub doublethecode ($block1, $block2) { eval { $block1; }; eval { $block2;} } ; 
doublethecode \&{ print "OH " }, \&{ say for qw/HAI YOU LOLCAT :-P/ }; 

Ausgang:

OH, HAI 
YOU 
LOLCAT 
:-P 

Dann ignorieren Sie einfach die \& und Sie sind da.

Ab v5.20 Sie können Signaturen und :prototype Attribute zusammen verwenden. Die Funktion signatures bietet eine "häufigere" Syntax und eine minimalistische Art der Argumentprüfung. Vielleicht wird eines der Zukunftsperls ein "eingebautes" (optionales, hochflexibles) System irgendeiner Art dazu haben, aber Prototypen sind so etwas nicht. So etwas wie:

sub doublethecode :prototype(\&\&) ($cr1, $cr2) { $cr1 ; $cr2 ; } 

ist nicht, was es scheint. Da Prototypen, signatures und Signaturen mit :prototype(&&) du nicht sein kann geben, was denken Sie bekommen, könnte dies gut genug sein:

sub doublethecode { eval { shift }; eval{ shift } } ; 
doublethecode &{ print "perl" }, &{ print "6" } 

Ausgang:

perl6 

Um sicherzustellen, dass Perl doesn‘ t denken {} ist ein Hash, der & ist notwendig. Aber eigentlich ... was ist falsch mit anonymen Subroutinen sub { } hier verwenden?

+0

Was meinst du' sub doublethecode ($ block1, $ block2) '? – Borodin

+1

@borodin oops Ich denke, wir haben zur gleichen Zeit bearbeitet sorry ... Ich denke 'sub doublethecode ($ block1, $ block2) {...}' ist nur eine neue Art der Zuweisung '@ _', mit ihm zu verwenden Attribute ': prototype (&&)' scheint diese Übung nicht besser zu machen :-) –

+1

Bitte schauen Sie in die [Dokumentation zum 'experimentellen' Pragma] (https://metacpan.org/module/experimental). Es ist äquivalent zu "keine Warnungen" experimentell "; Verwenden Sie die Funktion 'Signaturen'; '. Und selbst dann wird Ihr Code mit Nachrichten wie "Unbekannte Warnungen Kategorie 'Experimental'" oder "Feature" Signaturen "wird nicht unterstützt, es sei denn, Sie haben eine vorangehende" 5.020 verwenden ". Ja, um Ihre Lösung zu verwenden, müssen Sie die neueste Version von Perl verwenden, die erst im Mai dieses Jahres veröffentlicht wurde. Es wird an der Spitze geritten und alle Warnungen vor neuen Anlagen werden zur Schau gestellt. Du weißt wo du bist. – Borodin

Verwandte Themen