Gibt es eine Möglichkeit, eine "Konstante" als Hash-Schlüssel in Perl zu verwenden?

Gibt es eine Möglichkeit, eine Konstante als Hash-Schlüssel zu verwenden?

Beispielsweise:

use constant X => 1;

my %x = (X => 'X');

Der obige Code erzeugt einen Hash mit "X" als Schlüssel und nicht mit 1 als Schlüssel. Dagegen möchte ich den Wert der Konstante X als Schlüssel verwenden.

0
hinzugefügt bearbeitet
Ansichten: 2

9 Antworten

=> operator interprets its left side as a "string", the way qw() does.

Versuchen Sie es mit

my %x = ( X, 'X');
0
hinzugefügt

Kommentar @shelfoo (der Ruf ist nicht hoch genug, um einen Kommentar direkt dort hinzuzufügen!)

Stimme voll und ganz zu Perl Best Practices von Damian Conway ... zu seiner sehr empfehlenswerten Lektüre.

Bitte lesen Sie jedoch PBP-Modul-Empfehlung Kommentar , das ein nützliches "Errata" ist, wenn Sie planen, PBP für einen internen Style Guide zu verwenden.

0
hinzugefügt
Danke dafür, gut zu wissen. Ich bin von meinem Perl Gig weggegangen, also werde ich ihn wahrscheinlich nicht zu Hause verwenden, aber ich habe diesen Link an einen der Leute weitergeleitet, mit denen ich gearbeitet habe.
hinzugefügt der Autor shelfoo, Quelle

Your problem is that => is a magic comma that automatically quotes the word in front of it. So what you wrote is equivalent to ('X', 'X').

Der einfachste Weg ist, einfach ein Komma zu verwenden:

my %x = (X, 'X');

Or, you can add various punctuation so that you no longer have a simple word in front of the =>:

my %x = ( X() => 'X' );
my %x = ( &X => 'X' );
0
hinzugefügt

Das Pragma use constant erstellt einen Subroutinenprototyp, der keine Argumente annimmt. Während wie eine Konstante im C-Stil aussieht, ist es wirklich eine Subroutine, die einen konstanten Wert zurückgibt.

The => (fat comma) automatically quotes left operand if its a bareword, as does the $hash{key} notation.

Wenn Ihre Verwendung des konstanten Namens wie ein Bareword aussieht, treten die Quotierungsmechanismen in Kraft und Sie erhalten ihren Namen als Schlüssel statt als Wert. Um dies zu verhindern, ändern Sie die Verwendung, so dass es kein Barwort ist. Beispielsweise:

use constant X => 1;
%hash = (X() => 1);
%hash = (+X => 1);
$hash{X()} = 1;
$hash{+X} = 1;

In Initialisatoren können Sie stattdessen auch das einfache Komma verwenden:

%hash = (X, 1);
0
hinzugefügt

Verwenden Sie $ hash {CONSTANT ()} oder $ hash {+ CONSTANT} , um zu verhindern, dass der Bareword-Quotierungsmechanismus eingesetzt wird.

From: http://perldoc.perl.org/constant.html

0
hinzugefügt

use constant actually makes constant subroutines.

Um zu tun, was Sie wollen, müssen Sie das Subjekt explizit aufrufen:

use constant X => 1;

my %x = ( &X => 'X');

oder

use constant X => 1;

my %x = ( X() => 'X');
0
hinzugefügt

Eine Möglichkeit besteht darin, X als (X) zu kapseln:

my %x ( (X) => 1 );

Another option is to do away with '=>' and use ',' instead:

my %x ( X, 1 );
0
hinzugefügt

Eine weitere Option besteht darin, das Konstante-Pragma nicht zu verwenden und nach den Empfehlungen in den Best Practices von Damian Conway zu Readonly zu wechseln.

Ich habe eine Weile zurückgeschaltet, nachdem ich realisiert habe, dass konstante Hash-Refs nur eine konstante Referenz auf den Hash sind, aber nichts über die Daten im Hash tun.

Die readonly-Syntax erstellt "normal aussehende" Variablen, aber wird die Konstanten oder Readonlyness tatsächlich erzwingen. Sie können es wie jede andere Variable als Schlüssel verwenden.


use Readonly;

Readonly my $CONSTANT => 'Some value';

$hash{$CONSTANT} = 1;

0
hinzugefügt
Es ist kein Kernmodul.
hinzugefügt der Autor ceving, Quelle

Die meisten anderen Leute haben Ihre Frage gut beantwortet. Zusammen ergeben diese eine vollständige Erklärung des Problems und empfohlene Umgehungslösungen. Das Problem ist, dass das Perl-Pragma "use constant" wirklich eine Subroutine in Ihrem aktuellen Paket erstellt, deren Name das erste Argument des Pragmas ist und dessen Wert der letzte ist.

Wenn in Perl eine Subroutine deklariert ist, kann sie ohne Parens aufgerufen werden.

Understanding that "constants" are simply subroutines, you can see why they are not interpolated in strings and why the "fat comma" operator "=>" which quotes the left-hand argument thinks you've handed it a string (try other built-in functions like time() and keys() sometime with the fat comma for extra fun).

Zum Glück können Sie die Konstante mit expliziten Satzzeichen wie Parens oder dem kaufmännischen Und-Zeichen aufrufen.

Ich habe jedoch eine Frage an Sie: Warum verwenden Sie überhaupt Konstanten für Hash-Schlüssel?

Ich kann mir ein paar Szenarien vorstellen, die Sie in diese Richtung führen könnten:

  1. Sie möchten steuern, welche Schlüssel im Hash enthalten sein können.

  2. Sie möchten den Namen der Schlüssel abstrahieren, falls sich diese später ändern sollten

Im Fall von Nummer 1 speichern Konstanten wahrscheinlich Ihren Hash nicht. Erwägen Sie stattdessen, eine Klasse zu erstellen, die öffentliche Setter und Getter enthält, die einen nur für das Objekt sichtbaren Hashwert auffüllen. Dies ist eine sehr un-Perl ähnliche Lösung, aber sehr einfach zu tun.

Im Fall der Nummer 2 würde ich immer noch stark für eine Klasse eintreten. Wenn der Zugriff auf den Hash über eine wohldefinierte Schnittstelle geregelt wird, ist nur der Implementierer der Klasse dafür verantwortlich, die Hash-Schlüsselnamen richtig zu machen. In diesem Fall würde ich nicht vorschlagen, überhaupt Konstanten zu verwenden.

Hoffe das hilft und danke für deine Zeit.

0
hinzugefügt