2010-08-22 6 views
11

Ich arbeite jetzt seit ungefähr zwei Monaten mit Perl; Mir ist gerade in den Sinn gekommen, dass ich nicht weiß, wie man Standardargumente für Unterprogramme setzt. Hier ist, was ich in Betracht gezogen:Standard-Argumentwerte in Subroutinen

sub hello { 
    print @_ || "Hello world"; 
} 

Und das funktioniert für in Ordnung, wenn alles, was Sie brauchten, war ein Argument. Wie würden Sie Standardwerte für mehrere Argumente festlegen? Ich wollte das tun:

sub hello { 
    my $say = $_[0] || "Hello"; 
    my $to = $_[1] || "World!"; 
    print "$say $to"; 
} 

Aber das ist eine Menge Arbeit ... Es muss einen einfacheren Weg geben; möglicherweise eine Best Practice? Vielen Dank!

Antwort

2

Es gibt das Attribute::Default Modul auf CPAN. Wahrscheinlich sauberer als dies, und vermeidet ein paar Komplexitäten (wie, was, wenn Sie false an Ihre Unterroutine übergeben wollen?).

Ich habe auch gesehen Leute verwenden my $var = exists @_[0] ? shift : "Default_Value";, aber Perls Dokumentation stellt fest, dass calling exists on arrays is deprecated, so würde ich es nicht wirklich empfehlen.

Snippet von Attribute::Default aus der doc Seite:

sub vitals : Default({age => 14, sex => 'male'}) { 
    my %vitals = @_; 
    print "I'm $vitals{'sex'}, $vitals{'age'} years old, and am from $vitals{'location'}\n"; 
    } 

    # Prints "I'm male, 14 years old, and am from Schenectady" 
    vitals(location => 'Schenectady'); 
11

ich in der Regel so etwas wie:

sub hello { 
    my ($say,$to) = @_; 
    $say ||= "Hello"; 
    $to ||= "World!"; 
    print "$say $to\n"; 
} 

Beachten Sie, dass von Perl 5.10 starten, können Sie den "//=" Operator verwenden, um zu testen, ob Die Variable ist definiert und nicht nur ungleich Null. (Stellen Sie sich den Anruf hello("0","friend") vor, der unter Verwendung des oben genannten würde "Hello friend" ergeben, was möglicherweise nicht das war, was Sie wollten. Unter Verwendung des //= Operators würde es "0 friend" ergeben).

+0

Ja ich versucht, 'Druck @_ // "Hallo Welt",' aber ich habe '0' ... – David

+3

@Davidmoreen: Testen eines Arrays für die Definition ist nicht sinnvoll – ysth

+3

@Davidmoreen, der richtige Weg, um zu sagen, das ist 'print $ _ [0] //" Hallo Welt ";'. Wie schon gesagt, kann man 'defined' nicht auf einem Array verwenden (was' // 'bedeutet), weil ein Array im skalaren Kontext seine Länge zurückgibt, die immer definiert ist. – cjm

4

Da Perls Mechanismus zum Übergeben von Argumenten an Subroutinen eine einzige Liste ist, sind Argumente positionsabhängig. Dies erschwert die Bereitstellung von Standardwerten. Einige eingebaute (z. B. substr) handhaben dies, indem sie Argumente entsprechend ihrer Wahrscheinlichkeit sortieren, die verwendet werden sollen - weniger häufig verwendete Argumente erscheinen am Ende und haben nützliche Standardwerte.

Ein sauberer Weg, dies zu tun ist durch die benannten Argumente verwenden. Perl unterstützt keine benannten Argumente per se, aber man kann sie mit Hashes emulieren:

use 5.010; # for // 

sub hello { 
    my %arg = @_; 
    my $say = delete $arg{say} // 'Hello'; 
    my $to = delete $arg{to} // 'World!'; 
    print "$say $to\n"; 
} 

hello(say => 'Hi', to => 'everyone'); # Hi everyone 
hello(say => 'Hi');     # Hi world! 
hello(to => 'neighbor Bob');   # Hello neighbor Bob 
hello();        # Hello world! 

Hinweis: Die Defined oder Betreiber // in Perl v5.10 hinzugefügt wurde. Es ist robuster als ein logische Verwendung oder (||), da es nicht auf den logisch falschen Werten '' und 0 nicht erfüllt.

14

Ich tue es mit benannten Argumenten wie so:

sub hello { 
    my (%arg) = (
     'foo' => 'default_foo', 
     'bar' => 'default_bar', 
     @_ 
    ); 

} 

Ich glaube Params::Validate Standardwerte unterstützt, aber das ist mehr Mühe, als ich nehmen möchte.

3

Wenn Sie die Dokumentation von Perl Best Practices sehen: Standard Argument Werte von Damian Conway dann werden Sie einige wichtige Punkte, wie finden:

  • lösen jedes Standardargument sobald Werte als @_ ist entpackt.
  • Es schlägt vor, dass, wenn Sie viele Standardwerte einzurichten haben, der sauberste Weg wäre, die Standardwerte in Tabellen, dh, einen Hash Factoring und dann die Argument Hash mit dieser Tabelle vorinitialisieren.

Beispiel:

#!/usr/bin/perl 
    use strict; 
    use warning; 
    my %myhash = (say => "Hello", to => "Stack Overflow"); 
    sub hello { 
    my ($say, $to) = @_; 
    $say = $say ? $say : $myhash{say}; 
    $to = $to ? $to : $myhash{to}; 
    print "$say $to\n"; 
    } 
    hello('Perl');  # output :Perl Stack Overflow 
    hello('','SO');  # output :Hello SO 
    hello('Perl','SO'); # output :Perl SO 
    hello();   # output :Hello Stack Overflow 

Weitere Einzelheiten und vollständiges Beispiel finden Perl Best Practices.

4

Schauen Sie sich auch Method::Signatures. Dies verwendet Devel::Declare, um einige zusätzliche (benötigt!) Zucker mit den Schlüsselwörtern method und func bereitzustellen.

Im Folgenden finden Sie Ihr Beispiel mit den neuen func:

use Method::Signatures; 

func hello ($say='Hello', $to='World!') { 
    say "$say $to"; 
} 

hello('Hello', 'you!'); # => "Hello you!" 
hello('Yo');    # => "Yo World!" 
hello();      # => "Hello World!" 

/I3az/

1

Der beste Weg, um Ihr Problem zu lösen wurde in den anderen Antworten diskutiert. obwohl schlägt
Eine Sache, die mich ist, dass Sie feststellen, dass:

sub hello { 
    print @_ || "Hello world"; 
} 

Und das funktioniert gut für, wenn alles, was Sie benötigt ein Argument war.

Haben Sie diesen Code tatsächlich ausprobiert? Es wird die Anzahl der Argumente ausgegeben, oder, wenn keine angegeben ist, Hello World!
Der Grund dafür ist, dass der Operator || Vorrang hat und die linke Seite im Skalarkontext erzwingt, wodurch @_ auf die Anzahl der von Ihnen angegebenen Argumente reduziert wird, NICHT die Argumente selbst!
werfen Sie einen Blick auf perlop für weitere Informationen über Operatoren in Perl.

HTH,
Paul

0

Für mehr Zucker, siehe auch Method::Signatures:

func add($this = 23, $that = 42) { 
    return $this + $that; 
} 
+0

Sorry, habe nicht bemerkt, dass es bereits vorgeschlagen wurde – pwes

Verwandte Themen