2010-08-30 13 views
6

In tutto il luogo, soprattutto in DBI, vedo che questo messaggio si presenta sempre. È confuso, perché la prima cosa che viene in mente è che gli argomenti che sto passando alla funzione sono impostati su undef (o qualcosa di simile), ma chiaramente non è il caso.

Dato un modulo e un corrispondente script ...

Modulo: ./lib/My/Module.pm

package My::Module; 

use strict; 
use warnings; 

sub trim { 
    my $str = shift; 
    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

Script: ./test.pl

#!/usr/bin/perl 

use strict; 
use warnings; 
use My::Module qw(trim); 

print $My::Module->trim(" \t hello world\t \t"); 

torno il messaggio di errore

Circa Non chiamare il metodo "tagliare" su un valore indefinito in linea ./text.pl 7.

Infatti, se chiamo $My::Module->notamethod("hello world"); dà un errore simile.

Cosa c'è di sbagliato nello script/modulo sopra?

Che cos'è davvero l'errore Can't call method “X” on an undefined value at ${SOMEFILE} line ${SOMELINE}? Si riferisce al contesto della chiamata al metodo (passato qui per stampare) o al contesto degli argomenti?

risposta

6

Questa sintassi cerca un oggetto o un nome di classe nella variabile $My::Module e chiama il suo metodo di assetto, ma quella variabile non è definita.

Invece, si desidera semplicemente pronunciare print My::Module::trim(" \t hello world\t \t"); per chiamare la funzione My :: Module :: trim().

Dalla linea di utilizzo, sembra che si sta tentando di importare assetto() nel pacchetto locale in modo si può chiamare senza la qualificazione My::Module::, ma il modulo non sembra come esso è impostato per supportare l'esportazione .

Nelle espressioni regex, i flag/s e/m non hanno alcun effetto - cambiano solo i parametri., ^, E $ e non ne usano nessuno.

+0

tendo a mettere quelle di quando si scrive regex del perché mi piace mettere i commenti :) linea. Ho appena dimenticato di portarli fuori a titolo di esempio. – heymatthew

+1

@The Demoni Advocate,/s e/m non hanno nulla a che fare con commenti in linea. Quello è/x. – cjm

-1

È proprio come Perl fa OO. La differenza è nel modo in cui definisci i metodi.

Questo semplicemente chiama il sub-trim nel mio pacchetto :: Modulo:

My::Module::trim('foo') 

D'altra parte,

My::Module->trim('foo) 

diventa automaticamente una chiamata al sub-trim nella mia :: Pacchetto del modulo con la stringa "My :: Module" come primo argomento. oggetti funzionano allo stesso modo:

my $m = My::Module->new; # Corrected. Thanks for pointing this out. 
$m->trim('foo'); 

trasforma in una chiamata alla stessa sotto, ma questa volta con un riferimento all'oggetto $ m come primo argomento.

cosa si sta cercando di fare è:

$My::Module->trim('foo'); 

che si traduce in un dereference della variabile $ :: Modulo (che non esiste), così il messaggio di errore "Impossibile chiamare il metodo X su un valore indefinito ". Se $ My :: Module fosse un riferimento effettivo a un oggetto, ciò comporterebbe una chiamata a trim() su quell'oggetto, con il riferimento come primo argomento implicito.

Edit: Entrambi i commentatori sono corrette. Questa risposta era originariamente intesa come un commento alla risposta accettata. (C'è un modo per risolvere questo?)

Ci scusiamo per la confusione. Ho aggiunto un po 'più di dettagli qui, quindi spero che diventi più chiaro come si riferisce alla domanda originale (dereferenziare una variabile non definita).

+1

Non si dovrebbe usare la sintassi del metodo indiretto per la riga 'new'. Vedi qui per il motivo: http://stackoverflow.com/questions/429657/what-is-the-difference-between-new-someclass-and-someclass-new-in-perl/429798#429798 – friedo

+0

Le informazioni contenute in questo post è vero, ma in realtà non ha nulla a che fare con la domanda. – jrockway

13

Stai confondendo diversi modi per gestire i moduli e gli oggetti - e finendo con uno che non funziona.

Qui ci sono quattro approcci che funzionano:

1/:: Modulo è una libreria. il taglio non viene esportato.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

sub trim { 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

# Note: No $ and :: not -> 
print My::Module::trim(" \t hello world\t \t"); 

2/My :: Modulo è una libreria. il trim viene esportato.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

use Exporter; 
our @ISA = qw(Exporter); 
our @EXPORT = qw(trim); 

sub trim { 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

print trim(" \t hello world\t \t"); 

3/MyModule è una classe. assetto è un metodo di classe.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

sub trim { 
    # Note class name passed as first argument 
    my $class = shift; 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

# Note: Not $ and -> not :: 
print My::Module->trim(" \t hello world\t \t"); 

4/MyModule è una classe, trim è un metodo di oggetto.

$ cat My/Module.pm 
package My::Module; 

use strict; 
use warnings; 

# Need a constructor (but this one does nothing useful) 
sub new { 
    my $class = shift; 

    return bless {}, $class; 
} 

sub trim { 
    # Note: Object method is passed an object (which is ignored here) 
    my $self = shift; 
    my $str = shift; 

    $str =~ s{ \A \s+ }{}xms; # remove space from front of string 
    $str =~ s{ \s+ \z }{}xms; # remove space from end of string 
    return $str; 
} 

1; 
$ cat test 
#!/usr/bin/perl 

use strict; 
use warnings; 

use My::Module; 

my $trimmer = My::Module->new; 

print $trimmer->trim(" \t hello world\t \t"); 

Penso che si stava tentando per l'opzione 1. In questo caso, penso che io consiglierei l'opzione 2.

E per rispondere alla tua domanda finale. Stai ricevendo quell'errore perché stai provando a chiamare un metodo su una variabile ($ My :: Module) che non è definita.

Problemi correlati