Domanda

Sto cercando di ridurre il numero di linee di codice che sto usando, ma sto finendo con un abbastanza semplice problema (anche se mi ha stumping poiché sto appena iniziando ad avvolgere la mia testa intorno riferimenti)

Sto cercando di concatenare i diversi valori in un ordine particolare .. Il mio codice simile a questo ..

my $separator = ":";
my @vals = qw(name last-name first-name phone);
my $return_name;
$return_name = map { 
    $return_name = $return_name . $query->param($_) . $separator 
} @vals;

Quello che sto ottenendo è "4", invece di concantenating tutto in una stringa.

Quello che sto cercando di realizzare è una versione più breve di ...

$return_name = $query->param('name') . 
    $separator . $query->param('last-name') . 
    $separator . $query->param('first_name') . 
    $separator . $query->param('phone');

(In realtà sto cercando di stringa insieme circa 25 $query->params. Ho solo dato quattro per brevità)

È stato utile?

Soluzione

Parte del problema è confusione su come funziona map.

map prende una lista di argomenti, esegue un'operazione sugli elementi della lista e crea un nuovo elenco dai risultati. In un contesto scalare restituisce il numero dei componenti nel nuovo elenco.

Nella maggior parte dei casi non si vuole fare un incarico nel funzionamento map.

# no assignment needed to set @foo
my @foo = map $_+2, 1,2,3; 
# @foo = (3,4,5);

L'unico luogo in cui assegnazione ha senso è che se è necessario utilizzare un'operazione che normalmente modificare il valore di $_, ma è necessario per preservare gli argomenti per mappare invariata.

Questa spiegazione non è molto chiaro. Scopri questi esempi, essi dovrebbero contribuire a chiarire quello che sto dicendo. La prima mostra si mappa può alterare i valori che essa processi:

my @foo = qw( fee fie foe fum );
my @bar = map { s/e/-/g } @foo;
# @foo = ( 'f--', 'fi-', 'fo-', 'fum' ); 
# @bar = ( 2, 1, 1, '' );

Per non alterare @pippo si può fare:

my @foo = qw( fee fie foe fum );
my @bar = map { my $val = $_; $val =~ s/e/-/g } @foo;
# @foo = ( 'fee', 'fie', 'foe', 'fum' ); 
# @bar = ( 'f--', 'fi-', 'fo-', 'fum' ); 

Oppure si può fare:

usare List :: moreutils QW (a pagamento);

my @foo = qw( fee fie foe fum );
my @bar = apply { s/e/-/g } @foo;
# @foo = ( 'fee', 'fie', 'foe', 'fum' ); 
# @bar = ( 'f--', 'fi-', 'fo-', 'fum' );

Al suo map più elementare funziona come una forma specializzata di un ciclo for. I due pezzi di codice producono lo stesso risultato esatto:

my @foo = map {$_ * 2} 1..5;

my @bar;
for (1..5) {
     my $val = $_ * 2;
     push @bar, $val;
}

Spero che questo vi ho dato qualche aiuto per imparare a pensare map. Una volta che hai imparato ad usarlo (e costrutti correlati come grep e apply) si sarà in grado di esprimere in modo conciso idee che possono incredibilmente verbose quando costruito utilizzando il normale codice di looping.

Altri suggerimenti

$return_name = map { $return_name = $return_name . $query->param($_) . $separator } @vals;

Questo è un incarico scalare, che dà il contesto mappa operazione scalare. mappa in contesto scalare restituisce un conteggio degli elementi che sarebbero state prodotte.

Mentre quella particolare linea di codice grida per l'uso di join () , se si proviene da un background di programmazione funzionale, si può essere più a suo agio con il ridurre:

use List::Util 'reduce';
$return_name = reduce { $a . $query->param($b) . $separator } "", @vals;

map restituisce una lista, non una stringa. Prova questo:

$return_name = join $separator, map { $query->param($_) } @vals;

Se si vuole veramente ridurre il numero di linee, provate questo:

my $return_name = join ':', 
    map { $query->param($_) } 
    qw(name last-name first-name phone);

(La versione di una sola riga è stata ispirata dalla risposta di DSM.)

Prova questo:

join $separator, 
     map { $query->param($_) } 
     ("name", "last-name", "first-name", "phone");

Per rispondere alla ragione si ottiene '4', è perché si sta assegnando cardinalità le matrici risultanti ad uno scalare.

In aggiunta a tutte le buone risposte che hai ricevuto, si noti che

$return_name = $return_name . $query->param($_) . $separator;

può essere scritta come

$return_name .= $query->param($_) . $separator;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top