En Perl, cualquier función puede determinar en qué contexto se llama: escalar, de lista o void. El operador wantarray se utiliza para determinar el contexto.
Ejemplo:
sub foo { if (wantarray) { return (1, 2, 3); # Contexto de lista } else { return 42; # Contexto escalar } } my @a = foo(); # (1, 2, 3) my $b = foo(); # 42 foo(); # Contexto void
Características: si no se usa wantarray correctamente, se pueden devolver valores inesperados.
¿Qué devolverá la función si, dependiendo del contexto, devuelve un arreglo y un escalar, y se llama en contexto void?
Respuesta: En contexto void, el valor devuelto se ignora, sin embargo, el código de ejecución de la ramificación según wantarray permanece. Por lo tanto, se debe prever un manejo separado si la función realiza efectos secundarios. Por ejemplo:
sub noisy { if (wantarray) { print "Llamado en contexto de lista"; return (1,2,3); } elsif (defined wantarray) { print "Llamado en escalar"; return 42; } else { print "¡Void!"; return; } }
Historia 1
En un proyecto, un ingeniero olvidaba las diferencias de contexto. La función que devolvía una lista de nombres de archivos a veces "daba" solo la cantidad de archivos (contexto escalar) en lugar de los propios nombres; esto llevaba a la pérdida de datos al concatenarse con otros resultados.
Historia 2
Al desarrollar una API para analizar encabezados, las funciones devolvían una lista solo si había un arreglo explícito a la izquierda (
my @headers = parse_headers()), y si se llamaban comoif (parse_headers()), solo se devolvía el primer encabezado. El error no se encontró de inmediato, ya que el procesamiento parecía lógico, pero el comportamiento era diferente en distintas partes del proyecto.
Historia 3
Una función para buscar coincidencias en un archivo devolvía diferentes cantidades de resultados dependiendo del contexto. Como resultado, al pasarse a map o grep, ocurrían errores inesperados: map esperaba una lista, pero obtenía undef; en contexto escalar solo se contaba el número de coincidencias encontradas. El problema se detectó solo después de varios lanzamientos.