strawberry logo lane historia ejemplos perl

logo - ¿Deberíamos contratar a alguien que escriba C en Perl?



perl vs python (23)

Uno de mis colegas entrevistó recientemente a algunos candidatos para un trabajo y uno dijo que tenían muy buena experiencia con Perl.

Si esta persona piensa que tiene muy buena experiencia con Perl y escribe Perl de esta manera, probablemente sea víctima del efecto Dunning-Kruger .

Entonces, eso es un no contratar.

Uno de mis colegas entrevistó recientemente a algunos candidatos para un trabajo y uno dijo que tenían muy buena experiencia con Perl.

Como mi colega no conocía a Perl, me pidió una crítica de algún código escrito (fuera del sitio) por ese potencial empleado, así que eché un vistazo y le conté mis preocupaciones (la principal era que originalmente no tenía comentarios). y no es como si les diésemos suficiente tiempo).

Sin embargo, el código funciona, por lo que detestaba decir no-go sin más información. Otra preocupación es que este código básicamente se ve exactamente cómo lo codificaría en C. Ha pasado un tiempo desde que hice Perl (y no hice mucho, soy más un Python para guiones rápidos) pero me parece recordar que era un lenguaje mucho más expresivo que lo que este tipo usó.

Estoy buscando aportes de los verdaderos programadores de Perl, y sugerencias sobre cómo se podría mejorar (y por qué un programador de Perl debería conocer ese método de mejora).

También puede hablar mucho sobre si las personas que escriben un idioma en un idioma totalmente diferente deben (o no deben ser contratados). Me interesan tus argumentos, pero esta pregunta es principalmente para criticar el código.

La especificación era procesar con éxito un archivo CSV de la siguiente manera y generar los campos individuales:

User ID,Name , Level,Numeric ID pax, Pax Morgan ,admin,0 gt," Turner, George" rubbish,user,1 ms,"Mark /"X-Men/" Spencer","guest user",2 ab,, "user","3"

El resultado sería algo como esto (el código del empleado potencial realmente muestra esto):

User ID,Name , Level,Numeric ID: [User ID] [Name] [Level] [Numeric ID] pax, Pax Morgan ,admin,0: [pax] [Pax Morgan] [admin] [0] gt," Turner, George " rubbish,user,1: [gt] [ Turner, George ] [user] [1] ms,"Mark /"X-Men/" Spencer","guest user",2: [ms] [Mark "X-Men" Spencer] [guest user] [2] ab,, "user","3": [ab] [] [user] [3]

Aquí está el código que enviaron:

#!/usr/bin/perl # Open file. open (IN, "qq.in") || die "Cannot open qq.in"; # Process every line. while (<IN>) { chomp; $line = $_; print "$line:/n"; # Process every field in line. while ($line ne "") { # Skip spaces and start with empty field. if (substr ($line,0,1) eq " ") { $line = substr ($line,1); next; } $field = ""; $minlen = 0; # Detect quoted field or otherwise. if (substr ($line,0,1) eq "/"") { $line = substr ($line,1); $pastquote = 0; while ($line ne "") { # Special handling for quotes (// and /"). if (length ($line) >= 2) { if (substr ($line,0,2) eq "///"") { $field = $field . "/""; $line = substr ($line,2); next; } if (substr ($line,0,2) eq "////") { $field = $field . "//"; $line = substr ($line,2); next; } } # Detect closing quote. if (($pastquote == 0) && (substr ($line,0,1) eq "/"")) { $pastquote = 1; $line = substr ($line,1); $minlen = length ($field); next; } # Only worry about comma if past closing quote. if (($pastquote == 1) && (substr ($line,0,1) eq ",")) { $line = substr ($line,1); last; } $field = $field . substr ($line,0,1); $line = substr ($line,1); } } else { while ($line ne "") { if (substr ($line,0,1) eq ",") { $line = substr ($line,1); last; } if ($pastquote == 0) { $field = $field . substr ($line,0,1); } $line = substr ($line,1); } } # Strip trailing space. while ($field ne "") { if (length ($field) == $minlen) { last; } if (substr ($field,length ($field)-1,1) eq " ") { $field = substr ($field,0, length ($field)-1); next; } last; } print " [$field]/n"; } } close (IN);


¿Funciona? ¿Lo escribió en un tiempo aceptable? ¿Crees que es mantenible?

Si pueden responderme estas tres preguntas, pueden pasar el puente de la muerte ( * ).


¿Quizás le pidas que escriba más versiones del mismo código? En caso de duda sobre la contratación, haga más preguntas al candidato.


Aconsejo a las personas que nunca contraten programadores de Perl, programadores de C, programadores de Java, etc. Solo contrata buenas personas. Los programadores que contraté para escribir Perl también eran expertos en otros idiomas. Los contraté porque eran buenos programadores, y los buenos programadores pueden manejar múltiples idiomas.

Ahora, ese código se parece mucho a C, pero creo que también está bien Perl. Si contratas a un buen programador, con un poco de práctica de Perl en su haber, se pondrá al día perfectamente. La gente se queja de la falta de expresiones regulares, lo que simplificaría las cosas en las áreas auxiliares, pero no desearía a nadie una solución de expresiones regulares para analizar esos datos sucios de CSV. No me gustaría leerlo o mantenerlo.

A menudo encuentro que el problema inverso es más problemático: contratar a un buen programador que escriba un buen código Perl, pero el resto del equipo solo conoce los conceptos básicos de Perl y no puede mantener el ritmo. Esto no tiene nada que ver con un formato deficiente o una mala estructura, solo un nivel de habilidad con temas avanzados (por ejemplo, cierres).

Las cosas se calientan un poco en este debate, por lo que creo que debería explicar más sobre cómo lidiar con este tipo de cosas. No veo esto como un problema de expresión regular / no-regex. No habría escrito el código como lo hizo el candidato, pero eso realmente no importa.

Escribo un poco de código horrible también. En el primer paso, normalmente estoy pensando más en la estructura y el proceso que en la sintaxis. Vuelvo más tarde para apretarlo. Eso no significa que el código del candidato sea bueno, pero para un primer pase hecho en una entrevista no lo juzgo demasiado duramente. No sé cuánto tiempo tuvo para escribirlo, y así sucesivamente, así que no lo juzgo en base a algo en lo que habría tenido mucho tiempo para trabajar. Las preguntas de la entrevista siempre son raras porque no puedes hacer lo que realmente harías para el trabajo real. Probablemente también fallaría una pregunta sobre escribir un analizador CSV si tuviera que empezar de cero y hacerlo en 15 minutos. De hecho, perdí más que eso hoy siendo un completo idiota con algún código.

Fui a ver el código de Text::CSV_PP , el primo de Pure Perl a Text::CSV_XS . Utiliza expresiones regulares, pero una gran cantidad de expresiones regulares que manejan casos especiales, y en la estructura no es tan diferente del código presentado aquí. Es un montón de código, y es un código complicado que espero no tener que volver a mirar nunca más.

Lo que tiendo a desaprobar son las respuestas a las entrevistas que solo abordan la información dada. Eso es casi siempre lo incorrecto en el mundo real, donde debe manejar casos que aún no ha descubierto y necesita flexibilidad para enfrentar problemas futuros. También me parece que faltan muchas respuestas en . El proceso de pensamiento de la solución es más revelador para mí. Las personas se vuelven expertas en un idioma más fácilmente que cambian la manera en que piensan sobre las cosas. Puedo enseñar a la gente cómo escribir mejor Perl, pero no puedo cambiar sus wetware en su mayor parte. Eso proviene de cicatrices y experiencia.

Como no estaba allí para ver al candidato codificar la solución o hacerle preguntas de seguimiento, no voy a especular sobre por qué lo escribió de la manera en que lo hizo. Para algunas de las otras soluciones que he visto aquí, podría ser igualmente duro en una entrevista.

Una carrera es un viaje. No espero que todos sean gurú o que tengan las mismas experiencias. Si cancelo personas porque no conocen algún truco o modismo, no les estoy dando la oportunidad de continuar su viaje. El código del candidato no ganará ningún premio, pero aparentemente fue suficiente para llevarlo a los últimos tres para considerar una oferta. El tipo se levantó e intentó, lo hizo mucho mejor que un montón de código que he visto en mi vida, y eso es suficiente para mí.


Argumentaría que escribir C en Perl es una situación mucho mejor que escribir Perl en C. Como suele mencionarse en el podcast SO, entender C es una virtud que no todos los desarrolladores (incluso algunos buenos) tienen hoy en día. Contrate y compre una copia de las mejores prácticas de Perl para ellos y se lo establecerá. Después de las mejores prácticas, una copia de Perl intermedio y podrían funcionar.


Como no programador de Perl (? Programador?), Tengo que decir que ese es probablemente el Perl más legible que he leído en mi vida. :)

Contratar a alguien sobre algo como un lenguaje de scripting que se puede aprender en días o semanas (¡si es un lenguaje de scripting que vale la pena!) Parece altamente defectuoso desde el principio.

Personalmente, probablemente contrataría a esta persona por diferentes motivos. El código está bien estructurado y razonablemente bien comentado. Los detalles del idioma se pueden enseñar fácilmente más tarde.


Creo que el mayor problema es que él o ella no mostraron ningún conocimiento de la expresión regular. Y esa es la clave en Perl.

La pregunta es, ¿pueden aprender? Hay tanto que buscar en un candidato más allá de este fragmento de código.


El código no solo sugiere que el candidato realmente no conoce Perl, sino que todas las líneas que dicen $line = substr ($line,1) son terribles en cualquier idioma. Trate de analizar una línea larga (digamos unos miles de campos) usando ese tipo de enfoque y verá por qué. Simplemente muestra el tipo de problema que Joel Spolsky discutió en esta publicación .


El código se ve limpio y legible. Para ese tamaño, no requiere tantos comentarios (quizás ninguno). No se trata solo de buenos comentarios, sino también de un buen código, y el último es más importante que el anterior.

Si estuviéramos mirando un fragmento de código más complejo / más grande, diría que se necesitan comentarios. Pero para that (especialmente la forma en que fue escrito, bien escrito), no lo creo.

Creo que es injusto y vano poner dudas sobre el solicitante, dado que la pieza de código presentada por él / ella es bastante aceptable e hizo el trabajo.


El hecho de que no haya usado una sola pieza de expresión regular en el código debería hacer que le hagas muchas preguntas sobre por qué escribió así.

Tal vez él es Jamie Zawinski o un fan y él no quería tener más problemas?

No estoy necesariamente diciendo que todo el análisis debe ser una gran cantidad de expresiones regulares de lectura de CSV ilegibles como ("([^"]*|"{2})*"(,|$))|"[^"]*"(,|$)|[^,]+(,|$)|(,) o una de las muchas expresiones regulares similares alrededor, pero al menos para recorrer las líneas o en lugar de utilizar la substring() .


El punto crucial aquí es, naturalmente, después de asegurar que funciona como se espera, si el código es mantenible .

  • ¿Lo entendiste?
  • ¿Te sentirías cómodo arreglando un error?

Los programas Perl tienen una tendencia a parecerse a lo que un gato escribe por accidente cuando camina sobre el teclado. Si esta persona sabe cómo escribir un código legible de Perl que se ajuste al equipo, esto es realmente algo bueno.

Por otra parte, es posible que desee enseñarle sobre expresiones regulares, pero solo con cuidado :-)


Este es un caso en el que necesita hacer un seguimiento con el programador. Pregúntele por qué lo escribió de esta manera.

Puede haber una muy buena razón ... quizás esto tenía que seguir el mismo comportamiento que el código existente y, por lo tanto, hizo una traducción línea por línea a propósito para una compatibilidad total. Si es así, dele puntos por una explicación decente.

O quizás él no conoce a Perl, así que lo aprendió esa tarde para responder la pregunta. Si es así, dele puntos por habilidades de aprendizaje rápidas y ágiles.

El único comentario descalificante puede ser "Yo siempre programo Perl de esta manera. No entiendo eso de expresiones regulares".


Hmm, no veo nada en la solicitud que las citas se eliminen, y las palabras se deben eliminar. El archivo de entrada tenía la palabra "basura", y no está en la salida.

He visto archivos CSV, exportados con comillas, que esperan esas mismas citas. Si su especificación ha sido eliminar citas y palabras extrañas entre comillas, tal vez este trabajo sea necesario.

Yo miraría eso, y la verbosidad. Busca a alguien más holgazán (cumplido en Perl).

open (IN, "csv.csv"); while (<IN>) { #print $_; chomp; @array = split(/,/,$_); print "[User Id] = $array[0] [Name] = $array[1] [Level] = $array[2] [Numeric ID] = $array[3]/n"; }


No aceptaría al candidato. No se siente cómodo con los modismos de Perl, lo que dará como resultado un código subóptimo, menos eficiencia en el trabajo (¡todas esas líneas innecesarias deben escribirse!) Y una incapacidad para leer el código escrito por un programador experimentado de Perl (quien por supuesto usa expresiones regulares) etc. en general).

Pero funciona...


No es terriblemente idiomático Perl, pero tampoco es completamente terrible Perl (aunque podría ser mucho más compacto).

Dos campanas de advertencia: la línea shebang no incluye '' -w '' y no hay '' use strict; ''ni'' use warnings; ''. Esto es Perl muy antiguo; un buen código de Perl usa ambas advertencias y es estricto.

El uso de manejadores de archivos antiguos ya no se recomienda, pero no es automáticamente incorrecto (podría ser un código escrito hace más de 10 años, tal vez).

La no utilización de expresiones regulares es un poco más sorprendente. Por ejemplo:

# Process every field in line. while ($line ne "") { # Skip spaces and start with empty field. if (substr ($line,0,1) eq " ") { $line = substr ($line,1); next; }

Eso podría escribirse:

while ($line ne "") { $line =~ s/^/s+//;

Esto corta todos los espacios iniciales usando una expresión regular, sin hacer que el código itere alrededor del bucle. Una buena parte del resto del código se beneficiaría de expresiones regulares cuidadosamente escritas también. Estas son una expresión característicamente Perl; es sorprendente ver que no están siendo utilizados.

Si la eficiencia era la preocupación proclamada (razón para no usar expresiones regulares), entonces las preguntas deberían ser "¿lo midieron?" Y "¿qué tipo de eficiencia están discutiendo: máquina o programador?

El código de trabajo cuenta. Más o menos código idiomático es mejor.

Además, por supuesto, hay módulos Text :: CSV y Text :: CSV_XS que podrían usarse para manejar el análisis CSV. Sería interesante preguntar si conocen los módulos Perl.

También hay varias anotaciones para manejar citas dentro de campos cotizados. El código parece suponer que la comilla inversa es apropiada; Creo que Excel usa comillas dobles:

"He said, ""Don''t do it"", but they didn''t listen"

Esto podría ser igualado por:

$line =~ /^"([^"]|"")*"/;

Con un poco de cuidado, podría capturar solo el texto entre las citas adjuntas. De todos modos, deberá postprocesar el texto capturado para eliminar las comillas dobles incorporadas.

Un campo no citado se correspondería con:

$line =~ /^([^,]*)(?:,|$)/;

Esto es enormemente más corto que el bucle y la subcadena mostrada.

Aquí hay una versión del código, que usa el mecanismo de escape de comillas invertidas y comillas dobles utilizado en el código de la pregunta, que hace el mismo trabajo.

#!/usr/bin/perl -w use strict; open (IN, "qq.in") || die "Cannot open qq.in"; while (my $line = <IN>) { chomp $line; print "$line/n"; while ($line ne "") { $line =~ s/^/s+//; my $field = ""; if ($line =~ m/^"((?:[^"]|//.)*)"([^,]*)(?:,|$)/) { # Quoted field $field = "$1$2"; $line = substr($line, length($field)+2); $field =~ s/""/"/g; } elsif ($line =~ m/^([^,]*)(?:,|$)/) { # Unquoted field $field = "$1"; $line = substr($line, length($field)); } else { print "WTF?? ($line)/n"; } $line =~ s/^,//; print " [$field]/n"; } } close (IN);

Tiene menos de 30 líneas no en blanco, sin comentarios, en comparación con aproximadamente 70 en el original. La versión original es más grande de lo que necesita con algún margen. Y no me he salido de mi camino para reducir este código al mínimo posible.


No me importa si usó expresiones regulares o no. Tampoco me importa si su Perl se ve como C o no. La pregunta que realmente importa es: ¿es esto bueno Perl? Y yo diría que no:

  1. Él no usó el use strict
  2. Él no habilitó las advertencias.
  3. Está usando la versión anticuada de dos argumentos de open.
  4. El comentario de "abrir archivo" duele y me da la impresión de que el código que generalmente escribe no contiene ningún comentario.
  5. El código es difícil de mantener
  6. ¿Se le permitió usar módulos de CPAN? Un buen programador de Perl miraría esa opción primero.

Perdona a este tipo. No me hubiera atrevido a analizar CSV con una expresión regular aunque se pueda hacer.

El DFA en el código estructurado es más obvio que la expresión regular aquí y la traducción de DFA -> regex no es trivial y es propensa a errores estúpidos.


Sin uso de advertencias estrictas / de uso, uso sistemático de substr en lugar de regexp, sin uso de módulos. Definitivamente no es alguien que tenga " muy buena experiencia Perl ". Al menos no para proyectos reales de Perl. Al igual que usted, sospecho que probablemente sea un programador de C con conocimientos básicos de Perl.

Eso no significa que no puedan aprender, especialmente porque hay otras personas Perl alrededor. Sin embargo, parece significar que exageraron su calificación para el trabajo. Algunas preguntas más sobre cómo exactamente adquirieron esa muy buena experiencia de Perl estarían en orden.


Solo el bloque inicial indica que ha perdido los fundamentos sobre Perl.

while ($line ne "") { # Skip spaces and start with empty field. if (substr ($line,0,1) eq " ") { $line = substr ($line,1); next; }

Eso debería al menos escribirse usando una expresión regular para eliminar el espacio en blanco inicial. Me gusta la respuesta de jrockway best , modules rock. Aunque hubiera usado expresiones regulares para hacerlo, algo así como.

#!/usr/bin/perl -w # # $Id$ # use strict; open(FD, "< qq.in") || die "Failed to open file."; while (my $line = <FD>) { # Don''t like chomp. $line =~ s/(/r|/n)//g; # ".*?[^////]" = Match everything between quotations that doesn''t end with # an escaped quotation, match lazy so we will match the shortest possible. # [^",]*? = Match strings that doesn''t have any quotations. # If we combine the two above we can match strings that contains quotations # anywhere in the string (or doesn''t contain quotations at all). # Put them together and match lazy again so we can match white-spaces # and don''t include them in the result. my $match_field = ''/s*((".*?[^////]"|[^",]*?)*)/s*''; if (not $line =~ /^$match_field,$match_field,$match_field,$match_field$/) { die "Invalid line: $line"; } # Put values in nice variables so we don''t have to deal with cryptic $N # (and can use $1 in replace). my ($user_id, $name, $level, $numeric_id) = ($1, $3, $5, $7); print "$line/n"; for my $field ($user_id, $name, $level, $numeric_id) { # If the field starts with a quotation, # strip everything after the first unescaped quotation. $field =~ s/^"(.*?[^////])".*/$1/g; # Now fix all escaped variables (not only quotations). $field =~ s///(.)/$1/g; print " [$field]/n"; } } close FD;


Su código es un poco detallado. Perl tiene que ver con módulos, y evitarlos te hace la vida difícil. Aquí hay un equivalente a lo que publicaste que escribí en unos dos minutos:

#!/usr/bin/env perl use strict; use warnings; use Text::CSV; my $parser = Text::CSV->new({ allow_whitespace => 1, escape_char => ''//', allow_loose_quotes => 1, }); while(my $line = <>){ $parser->parse($line) or die "Parse error: ". $parser->error_diag; my @row = $parser->fields; print $line; print "/t[$_]/n" for @row; }


Tengo que (algo así) estar en desacuerdo con la mayoría de los puntos de vista expresados ​​aquí.

Dado que el código en cuestión podría expresarse de forma mucho más compacta y fácil de mantener en idiomático Perl, realmente debe plantearse la cuestión de cuánto tiempo el candidato pasó desarrollando esta solución y cuánto tiempo habría pasado alguien medianamente competente utilizando Perl idiomático.

Creo que encontrará que este estilo de codificación puede ser una gran pérdida de tiempo (y, por lo tanto, el dinero de la empresa).

No discuto que cada programador de Perl necesita grok el lenguaje -que, desafortunadamente, sería descabellado-, pero debería saber lo suficiente como para no pasar siglos reaplicando las funciones del lenguaje central en su código una y otra vez.

EDITAR Mirando nuevamente el código, tengo que ser más drástico: aunque el código se ve muy limpio, en realidad es horrible . Lo siento. Esto no es Perl. ¿Conoces el dicho "puedes programar Fortran en cualquier idioma"? Sí tu puedes. Pero no deberías.


Una pregunta obvia podría ser, si no usa Perl en su empresa en primer lugar, ¿qué importancia tiene su código Perl?

No estoy seguro de que la elegancia de su código Perl diga mucho sobre sus habilidades en cualquier idioma que estés usando.


Yo diría que su código es una solución adecuada. Funciona, ¿no? Y hay una ventaja para la capacidad de mantenimiento al escribir "a mano" en lugar de en el menor número de caracteres posible.

El lema de Perl es " Hay más de una forma de hacerlo ". Perl realmente no entiende tu estilo de codificación, como hacen algunos idiomas (también me gusta Python, pero debes admitir que la gente puede ser bastante esnob cuando evalúa si el código es "pitónico" o no).