Ethan Jarrell „egy kérdést tett fel” a felosztott eredmények listás hozzárendelésével kapcsolatban a hármas operátoron keresztül. A Perl effajta felfedezése, bár szórakoztató és rendkívül tanulságos, egyben része annak is, hogy a Perl az egyszer írható, vonalzajról híres. Ez azonban soha nem mentség arra, hogy ne osszam meg tapasztalataimat.

Ethan megkérdezte: "Ha valakinek van rálátása, azt megköszönném." és biztosan tudok válaszolni, hogy mi a probléma.

Három problémával találkozik. Az egyik a Perl listakiegyenlítő viselkedése, a másik kettő pedig a Perl vesszőoperátora és az osztott függvény működésének félreértése. Nézzük először a lista lapítását. Tudod, hogy ez működik:

my ($var1, $var2) = (100, 200);

és a következőket szeretné elérni:

my (@var3, @var4) = ( (something), (something) );

A Perl listasimító viselkedése azonban azt jelenti, hogy függetlenül attól, hogy mi van a jobb oldalon, minden egy nagy listába kerül, és mindez a @var3-hoz lesz hozzárendelve, és semmi sem kerül a @var4-be. A Perl nagyon szívesen ad üres tömböket, így nincs figyelmeztetés erre a viselkedésre.

Hivatkozásokat kell használnunk, hogy ez a bit működjön:

my ($var3, $var4) = ( [something], [something] )

Hivatkozások hozzáadása szinte azonnal megoldaná a problémát, de részben csak jó szerencsével, így a többi hibára is kitérek.

Először is a vessző operátor. Az esetek többségében az ember hibázik a vesszőoperátorok működésével kapcsolatban, és valamilyen figyelmeztetést kap, például: „A konstans („sáv”) haszontalan használata üres kontextusban a foo.pl 19. sorában. Ezt kapnád, ha valami ostobaságot csinálnál, például:

use warnings;
print("foo"), "bar";

Az emberek általában azt feltételezik, hogy a vessző operátor az idő nagy részében „egy is”-ként működik. A felosztások nélküli hármasban ezt próbálja elérni:

my ($arr3, $arr4) = (index($str2, '-') != -1)
    ?
      ["partial 1", "partial 2"], ["partial 3", "partial 4"]
    : ["partial 1a", "partial 2a"], ["partial 3a", "partial 4a"];

Ez nem fordítható le, és az if és akkor opciók körüli zárójelek hiánya kényelmetlenül érzi magát, mert nem egyezik a sablonunkkal:

my ($var1, $var2) = (100, 200);

Tehát ezeket hozzá kell adnunk:

my ($arr3, $arr4) = (index($str2, '-') != -1)
    ?
      ( ["partial 1", "partial 2"],   ["partial 3", "partial 4"]  )
    : ( ["partial 1a", "partial 2a"], ["partial 3a", "partial 4a"]);
print "array ref 3[0] is: $arr3->[0]\n";
print "array ref 3[1] is: $arr3->[1]\n";
print "array ref 4[0] is: $arr4->[0]\n";
print "array ref 4[1] is: $arr4->[1]\n";

Ez most működik.

Ha csak a fentiek szerint járna el, kijavítaná a kódot, és boldog lenne, de szeretnék egy utolsó, könnyen kihagyható hibára felhívni a figyelmet… A kód a következőket tartalmazza:

split /-/,$str2, split /;/, $str4

A Perl split függvénye 3 argumentumot vehet fel, így biztos vagyok benne, hogy a Perl ezt így olvassa:

split(/-/, $str2, (split /;/, $str4))

Nem tudom, miért nem kapja meg az „Érv… nem numerikus felosztásban” figyelmeztetést, amit általában kap, de nem kap hasznos eredményt sem.

A kód félreértelmezésének ismerete megkönnyíti a fennmaradó javítást. További zárójelek hozzáadása:

(split /-/,$str2), (split /;/, $str4)

Tehát ezt a két javítást kombinálva (és felismerve, hogy most már elhagyhatjuk az extra belső zárójeleket), az egyszerű kezdeti hozzárendelési verzió a következő lesz:

my ($arr3, $arr4) = ( [split /-/,$str2], [split /;/, $str4] )

és ennek megfelelően a hármas megoldás a következő lesz:

my ($arr3, $arr4) = (index($str2, '-') != -1)
    ? 
      ([split /-/,$str2], [split /;/, $str4])
    : ([split /:/,$str2], [split /;/, $str4]);

a teljes megoldással:

use strict;
use warnings;
my $str2 = 'This string has two sentences -  A dash separates them';
my $str4 = 'This string has different punctuation; a semicolon';
my ($arr3, $arr4) = (index($str2, '-') != -1)
    ? 
      ([split /-/,$str2], [split /;/, $str4])
    : ([split /:/,$str2], [split /;/, $str4]);
print "array ref 3[0] is: $arr3->[0]\n";
print "array ref 3[1] is: $arr3->[1]\n";
print "array ref 4[0] is: $arr4->[0]\n";
print "array ref 4[1] is: $arr4->[1]\n";

Mindezek után biztosíthatom, hogy ez egy csúnya megoldás.

Az eredeti feltételes kijelentésed (@arr5 és @arr6 esetén) sokkal karbantarthatóbb megoldás (ami azt jelenti, hogy kedvesebb azokhoz, akik 5 év múlva hajnali 2-kor keresik a kódodat, és megpróbálják kijavítani, hogy elmenhessenek. vissza az ágyba…), ha több karakterlánc felosztása egy adott karaktert tartalmazó karakterlánctól függ. Alternatív megoldásként, mivel jelenleg ugyanazt csináljuk a $str4-el, ezt is megtehetjük:

my @arr3;
my @arr4 = split /;/, $str4;
if( ( @arr3 = split /-/, $str2 ) < 2 ) {
        @arr3 = split /;/, $str2;
}
print "array 3[0] is:  $arr3[0]\n";
print "array 3[1] is:  $arr3[1]\n";
print "array 4[0] is:  $arr4[0]\n";
print "array 4[1] is:  $arr4[1]\n";

A fenti kód legnagyobb előnye, hogy nem kell indexet hívnunk. Megpróbálhatjuk a felosztást, és ha csak 1 sort kapunk vissza, tudjuk, hogy a felosztás sikertelen volt. :)

Boldog perlinget!