Pregunta

Tengo una función que toma una variable y una matriz asociativa, pero parece que no puedo hacer que pasen bien. Creo que esto tiene algo que ver con las declaraciones de funciones, sin embargo, no puedo entender cómo funcionan en Perl. ¿Hay una buena referencia para esto y cómo logro lo que necesito?

Debo agregar que se debe pasar por referencia.

sub PrintAA
{
    my $test = shift;
    my %aa   = shift;
    print $test . "\n";
    foreach (keys %aa)
    {
        print 

Tengo una función que toma una variable y una matriz asociativa, pero parece que no puedo hacer que pasen bien. Creo que esto tiene algo que ver con las declaraciones de funciones, sin embargo, no puedo entender cómo funcionan en Perl. ¿Hay una buena referencia para esto y cómo logro lo que necesito?

Debo agregar que se debe pasar por referencia.

<*> . " : " . $aa{

Tengo una función que toma una variable y una matriz asociativa, pero parece que no puedo hacer que pasen bien. Creo que esto tiene algo que ver con las declaraciones de funciones, sin embargo, no puedo entender cómo funcionan en Perl. ¿Hay una buena referencia para esto y cómo logro lo que necesito?

Debo agregar que se debe pasar por referencia.

<*>} . "\n"; $aa{

Tengo una función que toma una variable y una matriz asociativa, pero parece que no puedo hacer que pasen bien. Creo que esto tiene algo que ver con las declaraciones de funciones, sin embargo, no puedo entender cómo funcionan en Perl. ¿Hay una buena referencia para esto y cómo logro lo que necesito?

Debo agregar que se debe pasar por referencia.

<*>} = $aa{

Tengo una función que toma una variable y una matriz asociativa, pero parece que no puedo hacer que pasen bien. Creo que esto tiene algo que ver con las declaraciones de funciones, sin embargo, no puedo entender cómo funcionan en Perl. ¿Hay una buena referencia para esto y cómo logro lo que necesito?

Debo agregar que se debe pasar por referencia.

<*>} . "+"; } }
¿Fue útil?

Solución

Pase la referencia en lugar del hash mismo. Como en

PrintAA("abc", \%fooHash);

sub PrintAA
{
  my $test = shift;
  my $aaRef = shift;

  print $test, "\n";
  foreach (keys %{$aaRef})
  {
    print 

Pase la referencia en lugar del hash mismo. Como en

<*>

Véase también perlfaq7: ¿Cómo puedo pasar / devolver un {Function, FileHandle, Array, Hash, Method, Regex}?

, " : ", $aaRef->{

Pase la referencia en lugar del hash mismo. Como en

<*>

Véase también perlfaq7: ¿Cómo puedo pasar / devolver un {Function, FileHandle, Array, Hash, Method, Regex}?

}, "\n"; } }

Véase también perlfaq7: ¿Cómo puedo pasar / devolver un {Function, FileHandle, Array, Hash, Method, Regex}?

Otros consejos

Este código funciona:

#!/bin/perl -w

use strict;

sub PrintAA
{
    my($test, %aa) = @_;
    print $test . "\n";
    foreach (keys %aa)
    {
        print 

Este código funciona:

my $test = shift;
my(%aa) = @_;

El punto clave es el uso del contexto de matriz en la 'declaración' my () en la función.


  

¿Qué hace realmente el negocio de contexto de matriz?

De manera sucinta, hace que funcione correctamente.

Significa que el primer valor en el conjunto de argumentos @_ se asigna a $ test , y los elementos restantes se asignan al hash % aa . Dada la forma en que lo llamé, hay un número impar de elementos en @_ , por lo que una vez que el primer elemento se asigna a $ test , hay un número par de elementos disponibles para asignar a % aa , siendo el primer elemento de cada par la clave ('aaa', 'bbb', 'ccc' en mi ejemplo), y el segundo es el valor correspondiente.

Sería posible reemplazar % aa con @aa , en cuyo caso, la matriz tendría 6 elementos. También sería posible reemplazar % aa con $ aa , y en ese caso, la variable $ aa contendría el valor 'aaa' , y los valores restantes en @_ serían ignorados por la asignación.

Si omite los paréntesis alrededor de la lista de variables, Perl se niega a compilar el código. Una de las respuestas alternativas mostró la notación:

Reference found where even-sized list expected at xx.pl line 18.
...
Use of uninitialized value in concatenation (.) or string at xx.pl line 13.

Esto es más o menos equivalente a lo que escribí; la diferencia es que después de las dos declaraciones my , @_ solo contiene 6 elementos en esta variación, mientras que en la única versión my , todavía contiene 7 elementos.

Definitivamente hay otras preguntas en SO sobre el contexto de matriz.


  

En realidad, no estaba preguntando sobre el my ($ test,% aa) = @_; estaba preguntando sobre my (% hash) = ('aaa' = > ; 1, 'bbb' = > 'bolas', 'ccc' = > \ & amp; PrintAA); versus my% hash = {'aaa' = > 1, ...};

La diferencia es que la notación {...} genera un hash ref y la notación (...) genera una lista, que se asigna a un hash (en oposición a hash ref). Del mismo modo, [...] genera una referencia de matriz y no una matriz.

De hecho, cambie el código 'principal' para que se lea: my (% hash) = {...}; y obtiene un error de tiempo de ejecución (pero no de compilación): trate los números de línea con precaución ya que he agregado codificaciones alternativas a mi archivo:

<*> . " : " . $aa{

Este código funciona:

<*>

El punto clave es el uso del contexto de matriz en la 'declaración' my () en la función.


  

¿Qué hace realmente el negocio de contexto de matriz?

De manera sucinta, hace que funcione correctamente.

Significa que el primer valor en el conjunto de argumentos @_ se asigna a $ test , y los elementos restantes se asignan al hash % aa . Dada la forma en que lo llamé, hay un número impar de elementos en @_ , por lo que una vez que el primer elemento se asigna a $ test , hay un número par de elementos disponibles para asignar a % aa , siendo el primer elemento de cada par la clave ('aaa', 'bbb', 'ccc' en mi ejemplo), y el segundo es el valor correspondiente.

Sería posible reemplazar % aa con @aa , en cuyo caso, la matriz tendría 6 elementos. También sería posible reemplazar % aa con $ aa , y en ese caso, la variable $ aa contendría el valor 'aaa' , y los valores restantes en @_ serían ignorados por la asignación.

Si omite los paréntesis alrededor de la lista de variables, Perl se niega a compilar el código. Una de las respuestas alternativas mostró la notación:

<*>

Esto es más o menos equivalente a lo que escribí; la diferencia es que después de las dos declaraciones my , @_ solo contiene 6 elementos en esta variación, mientras que en la única versión my , todavía contiene 7 elementos.

Definitivamente hay otras preguntas en SO sobre el contexto de matriz.


  

En realidad, no estaba preguntando sobre el my ($ test,% aa) = @_; estaba preguntando sobre my (% hash) = ('aaa' = > ; 1, 'bbb' = > 'bolas', 'ccc' = > \ & amp; PrintAA); versus my% hash = {'aaa' = > 1, ...};

La diferencia es que la notación {...} genera un hash ref y la notación (...) genera una lista, que se asigna a un hash (en oposición a hash ref). Del mismo modo, [...] genera una referencia de matriz y no una matriz.

De hecho, cambie el código 'principal' para que se lea: my (% hash) = {...}; y obtiene un error de tiempo de ejecución (pero no de compilación): trate los números de línea con precaución ya que he agregado codificaciones alternativas a mi archivo:

<*>} . "\n"; } } my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA ); PrintAA("test", %hash);

El punto clave es el uso del contexto de matriz en la 'declaración' my () en la función.


  

¿Qué hace realmente el negocio de contexto de matriz?

De manera sucinta, hace que funcione correctamente.

Significa que el primer valor en el conjunto de argumentos @_ se asigna a $ test , y los elementos restantes se asignan al hash % aa . Dada la forma en que lo llamé, hay un número impar de elementos en @_ , por lo que una vez que el primer elemento se asigna a $ test , hay un número par de elementos disponibles para asignar a % aa , siendo el primer elemento de cada par la clave ('aaa', 'bbb', 'ccc' en mi ejemplo), y el segundo es el valor correspondiente.

Sería posible reemplazar % aa con @aa , en cuyo caso, la matriz tendría 6 elementos. También sería posible reemplazar % aa con $ aa , y en ese caso, la variable $ aa contendría el valor 'aaa' , y los valores restantes en @_ serían ignorados por la asignación.

Si omite los paréntesis alrededor de la lista de variables, Perl se niega a compilar el código. Una de las respuestas alternativas mostró la notación:

<*>

Esto es más o menos equivalente a lo que escribí; la diferencia es que después de las dos declaraciones my , @_ solo contiene 6 elementos en esta variación, mientras que en la única versión my , todavía contiene 7 elementos.

Definitivamente hay otras preguntas en SO sobre el contexto de matriz.


  

En realidad, no estaba preguntando sobre el my ($ test,% aa) = @_; estaba preguntando sobre my (% hash) = ('aaa' = > ; 1, 'bbb' = > 'bolas', 'ccc' = > \ & amp; PrintAA); versus my% hash = {'aaa' = > 1, ...};

La diferencia es que la notación {...} genera un hash ref y la notación (...) genera una lista, que se asigna a un hash (en oposición a hash ref). Del mismo modo, [...] genera una referencia de matriz y no una matriz.

De hecho, cambie el código 'principal' para que se lea: my (% hash) = {...}; y obtiene un error de tiempo de ejecución (pero no de compilación): trate los números de línea con precaución ya que he agregado codificaciones alternativas a mi archivo:

<*>

Alternativamente:

sub PrintAA
{
    my $test       = shift;
    my %aa         = @_;
        print $test . "\n";
        foreach (keys %aa)
        {
                print 

Alternativamente:

<*>

Lo que fundamentalmente falta es que una matriz asociativa no es un argumento único (aunque sí lo es una referencia de matriz asociativa, como en la respuesta de Paul Tomblin).

. " : " . $aa{

Alternativamente:

<*>

Lo que fundamentalmente falta es que una matriz asociativa no es un argumento único (aunque sí lo es una referencia de matriz asociativa, como en la respuesta de Paul Tomblin).

} . "\n"; $aa{

Alternativamente:

<*>

Lo que fundamentalmente falta es que una matriz asociativa no es un argumento único (aunque sí lo es una referencia de matriz asociativa, como en la respuesta de Paul Tomblin).

} = $aa{

Alternativamente:

<*>

Lo que fundamentalmente falta es que una matriz asociativa no es un argumento único (aunque sí lo es una referencia de matriz asociativa, como en la respuesta de Paul Tomblin).

} . "+"; } }

Lo que fundamentalmente falta es que una matriz asociativa no es un argumento único (aunque sí lo es una referencia de matriz asociativa, como en la respuesta de Paul Tomblin).

Parece que debería pasar una referencia a un hash.

sub PrintAA
{
   my $test = shift;
   my $aa = shift;
   if (ref($aa) != "HASH") { die "bad arg!" }
   ....
}

PrintAA($foo, \%bar);

La razón por la que no puedes hacer un

my %aa = shift;

se debe a que Perl aplana todos los argumentos de una subrutina en una lista, @_. Cada elemento se copia, por lo que pasar por referencia también evita esas copias.

Como de costumbre, hay varias formas. Esto es lo que Mejores prácticas de Perl , el más reverenciado de punteros de estilo, tiene que decir sobre pasar parámetros a funciones:

Use un hash de argumentos con nombre para cualquier subrutina que tenga más de tres parámetros

Pero como solo tienes dos, puedes escapar;) pasándolos directamente de esta manera:

my $scalar = 5;
my %hash = (a => 1, b => 2, c => 3);

func($scalar, %hash)

Y la función se define así:

sub func {
    my $scalar_var = shift;
    my %hash_var = @_;

    ... Do something ...
}

Podría ser más útil si pudiera mostrar algún código.

Todos los métodos anteriores funcionan, pero esta era siempre la forma en que prefería hacer cosas como esta:

sub PrintAA ($\%)
{
    my $test       = shift;
    my %aa         = ${shift()};
    print "$test\n";
    foreach (keys %aa)
    {
        print "

Todos los métodos anteriores funcionan, pero esta era siempre la forma en que prefería hacer cosas como esta:

PrintAA("test", %hash);

Nota: También cambié un poco su código. Las cadenas entre comillas dobles de Perl interpretarán " $ test " como el valor de $ test en lugar de la cadena real '$ test' , así que no necesitas tantos . s.

Además, me equivoqué acerca de cómo funcionan los prototipos. Para pasar un hash, usa esto:

PrintAA("test", %$ref_to_hash);

Para imprimir una referencia hash, use esto:

<*>

Por supuesto, ahora no puede modificar el hash al que hace referencia $ ref_to_hash porque está enviando una copia, pero puede modificar un % hash sin procesar porque lo pasa como referencia.

: $aa{

Todos los métodos anteriores funcionan, pero esta era siempre la forma en que prefería hacer cosas como esta:

<*>

Nota: También cambié un poco su código. Las cadenas entre comillas dobles de Perl interpretarán " $ test " como el valor de $ test en lugar de la cadena real '$ test' , así que no necesitas tantos . s.

Además, me equivoqué acerca de cómo funcionan los prototipos. Para pasar un hash, usa esto:

<*>

Para imprimir una referencia hash, use esto:

<*>

Por supuesto, ahora no puede modificar el hash al que hace referencia $ ref_to_hash porque está enviando una copia, pero puede modificar un % hash sin procesar porque lo pasa como referencia.

}\n"; $aa{

Todos los métodos anteriores funcionan, pero esta era siempre la forma en que prefería hacer cosas como esta:

<*>

Nota: También cambié un poco su código. Las cadenas entre comillas dobles de Perl interpretarán " $ test " como el valor de $ test en lugar de la cadena real '$ test' , así que no necesitas tantos . s.

Además, me equivoqué acerca de cómo funcionan los prototipos. Para pasar un hash, usa esto:

<*>

Para imprimir una referencia hash, use esto:

<*>

Por supuesto, ahora no puede modificar el hash al que hace referencia $ ref_to_hash porque está enviando una copia, pero puede modificar un % hash sin procesar porque lo pasa como referencia.

} = "$aa{

Todos los métodos anteriores funcionan, pero esta era siempre la forma en que prefería hacer cosas como esta:

<*>

Nota: También cambié un poco su código. Las cadenas entre comillas dobles de Perl interpretarán " $ test " como el valor de $ test en lugar de la cadena real '$ test' , así que no necesitas tantos . s.

Además, me equivoqué acerca de cómo funcionan los prototipos. Para pasar un hash, usa esto:

<*>

Para imprimir una referencia hash, use esto:

<*>

Por supuesto, ahora no puede modificar el hash al que hace referencia $ ref_to_hash porque está enviando una copia, pero puede modificar un % hash sin procesar porque lo pasa como referencia.

}+"; } }

Nota: También cambié un poco su código. Las cadenas entre comillas dobles de Perl interpretarán " $ test " como el valor de $ test en lugar de la cadena real '$ test' , así que no necesitas tantos . s.

Además, me equivoqué acerca de cómo funcionan los prototipos. Para pasar un hash, usa esto:

<*>

Para imprimir una referencia hash, use esto:

<*>

Por supuesto, ahora no puede modificar el hash al que hace referencia $ ref_to_hash porque está enviando una copia, pero puede modificar un % hash sin procesar porque lo pasa como referencia.

Los argumentos de las funciones se aplanan en una sola matriz (@_). Por lo tanto, generalmente es más fácil pasar hashes para que funcionen por referencia.

Para crear un HASH:

my %myhash = ( key1 => "val1", key2 => "val2" );

Para crear una referencia a ese HASH:

my $href = \%myhash

Para acceder a ese hash por referencia;

%$href

Entonces en tu sub:

my $myhref = shift;

keys %$myhref;

Todas las otras respuestas aquí hasta ahora me parecen bastante complicadas. Cuando escribo la función Perl, generalmente " expandir " todos los argumentos pasados ??en la primera línea de la función.

sub someFunction {
    my ( $arg1, $arg2, $arg3 ) = @_;

Esto es similar a otros idiomas, donde declaras funciones como

... someFunction ( arg1, arg2, arg3 )

Y si lo haces de esa manera y pasas el hash como último argumento, estarás bien sin ningún truco o magia especial. Por ejemplo:

sub testFunc {
    my ( $string, %hash ) = @_;
    print "$string $hash{'abc'} $hash{'efg'} $string\n";
}

my %testHash = (
    'abc' => "Hello",
    'efg' => "World"
);
testFunc('!!!', %testHash);

El resultado es el esperado:

!!! Hello World !!!

Esto funciona porque en Perl los argumentos siempre se pasan como una matriz de valores escalares y si pasa un hash, su valor clave / pares se agregan a esa matriz. En el ejemplo anterior, los argumentos pasados ??a la función como matriz ( @_ ) son, de hecho:

'!!!', 'abc', 'Hello', 'efg', 'World'

y '!!!' es simple asignado a % string , mientras que % hash " swallows " todos los demás argumentos, siempre interpretando uno como una clave y el siguiente como valor (hasta que se agoten todos los elementos).

No puede pasar varios hashes de esa manera y el hash no puede ser el primer argumento, ya que de lo contrario se tragaría todo y dejaría todos los demás argumentos sin asignar.

Por supuesto, exactamente lo mismo funciona para la matriz como último argumento. La única diferencia aquí es que las matrices no distinguen entre claves y valores, para ellos todos los argumentos sobrantes son valores y simplemente son empujados a la matriz.

Utilice el siguiente sub para obtener hash o hashref, lo que sea que haya pasado :)

sub get_args { ref( 

Utilice el siguiente sub para obtener hash o hashref, lo que sea que haya pasado :)

printAA($firstarg,somearg=>1, anotherarg=>2)

Llama a tu función de esta manera:

printAA($firstarg,{somearg=>1, anotherarg=>2})

O como este (no importa):

my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \PrintAA );

PrintAA("test", %hash);

O incluso así (no importa):

<*>

¡Salud!

[0] ) ? shift() : ( @_ % 2 ) ? {} : {@_}; } sub PrintAA { my $test = shift; my $aa = get_args(@_);; #then $aa->{somearg} #do something $aa->{anotherearg} #do something }

Llama a tu función de esta manera:

<*>

O como este (no importa):

<*>

O incluso así (no importa):

<*>

¡Salud!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top