Soy (realmente) novato en la programación funcional (de hecho, solo tuve contacto con él usando python) pero parece ser un buen enfoque para algunas tareas intensivas en listas en un entorno de shell.
Me encantaría hacer algo como esto:
$ [ git clone $host/$repo for repo in repo1 repo2 repo3 ]
¿Hay algún shell de Unix con este tipo de características? O tal vez alguna característica para permitir un fácil acceso de shell (comandos, env / vars, readline, etc.) desde Python (la idea es utilizar el intérprete interactivo de Python como reemplazo de bash).
EDITAR:
Quizás un ejemplo comparativo aclararía. Digamos que tengo una lista compuesta de dir / archivo :
$ FILES=( build/project.rpm build/project.src.rpm )
Y quiero hacer una tarea realmente simple: copiar todos los archivos para dist / AND instalarlo en el sistema (es parte de un proceso de compilación):
Usando bash:
$ cp $ {archivos [*]} dist / $ cd dist && rpm -Uvh $ (para f en $ {archivos [*]}; nombre base $ f; hecho))
Usando un enfoque de "capa pitónica" (precaución: este es un código imaginario):
$ cp [os.path.join ('dist', os.path.basename (file)) para el archivo en ARCHIVOS] 'dist'
Puedes ver la diferencia ? ESO es de lo que estoy hablando. ¿Cómo no se puede salir de un shell con este tipo de cosas incorporadas todavía? Es realmente difícil manejar listas en shell, incluso si es una tarea tan común: lista de archivos, lista de PID, lista de todo.
Y un punto muy, muy importante: usar la sintaxis / herramientas / características que todos ya conocen: sh y python.
IPython parece estar en una buena dirección, pero está hinchado: si el nombre var comienza con '$', lo hace, si '$$' lo hace. Su sintaxis no es "natural", hay muchas reglas y "soluciones" ( [ ln.upper() for ln in !ls ]
-> error de sintaxis)
Respuestas:
Hay un Shell de esquema que probablemente esté muy cerca de lo que estás buscando. No lo he usado yo mismo.
ACTUALIZACIÓN
Acabo de instalarlo y lo probé yo mismo. Parece que scsh es más un intérprete de esquemas interactivo y un lenguaje de script que un shell interactivo realmente útil. No puedes simplemente escribir
la sintaxis parece ser
y me tomó varios minutos buscar en Google solo para encontrar eso. El primer ejemplo aquí es:
que se traduce en:
pero eso no te dice cómo ejecutar un simple comando de shell.
Esta entrada de preguntas frecuentes dice:
Entonces tal vez esa sea la respuesta real.
fuente
En la categoría de responder directamente a la pregunta, está el shell ES que está destinado a ser un reemplazo funcional para Bash y Zsh, etc.
En segundo lugar, en la categoría de ayudarlo a escribir un shell estándar más funcional, considere aprender la técnica de pipemill:
El primer bucle while es funcional
keep
(transmite solo los valores no nulos que salen del bucle) y el segundo es uneach
(mapa solo para efectos secundarios).Este es un tremendo impulso para fp en los depósitos.
Es posible expresar muchas cosas en un estilo más fp en un shell, simplemente no es tan fácil como podría ser. Parece que no hay mucho interés en hacer mejores conchas, a pesar de que todos las usamos mucho.
fuente
Las conchas de estilo Bourne estándar (
sh
,bash
,ksh
, etc.) ya le permiten hacer:(Tenga en cuenta la necesidad de punto
do
y coma antes ydone
.) Además, enbash
y otros shells, si$repo
solo aparece una vez en el comando, puede escribir:fuente
git clone $host/{repo1,repo2,repo3}
no hace lo mismo que elfor
bucle; Invocagit clone
una vez con tres argumentos. El hecho de que esencialmente haga lo mismo es un artefacto de cómogit clone
funciona; no necesariamente se aplica a otros comandos. (Compáreseecho foo bar baz
conecho foo; echo bar; echo baz
, por ejemplo.)FUN=eval 'git clone '"$host"'$0
para definir una lambda para usar comofor repo in repo{1,2,3} ; do $FUN $repo ; done
Scheme Shell, scsh, es realmente bueno.
Como señala Keith Thompson, no es útil como un shell interactivo (aunque el Comandante S parece un experimento interesante). En cambio, es un excelente lenguaje de programación para contextos donde es útil tener todos los enlaces POSIX, lo que incluye casos en los que desea llamar a otras aplicaciones de Unix. Un script de shell de más de unas pocas docenas de líneas siempre se sentirá como un truco, sin importar cuán prolijamente escriba
sh
; en contraste, no hay nada que te detenga escribiendo importantes programas usando scsh.scsh no es muy compacto (la brevedad es tanto la fortaleza como la debilidad de los lenguajes sh-family), pero es potente.
Debido a que es útil y práctico para tareas pequeñas y grandes, scsh es, por cierto, una buena manera de familiarizarse con un Esquema (aunque, si ese fuera su objetivo, también podría ir directamente a Racket, en estos días).
Las ventajas de los lenguajes funcionales no son solo para las tareas intensivas en listas (aunque debido a su historial, tienden a favorecer las listas como una estructura de datos), es una forma realmente sólida de escribir programas, una vez que bebe el kool- correcto ayuda.
No hay un sentido significativo en el que los shells de estilo sh sean funcionales, y Python solo es funcional en el sentido marginal de que tiene una función lambda.
fuente
Los proyectiles son necesariamente extremadamente expresivos, lo que significa que logra lotes con menos líneas, tokens, etc.
Por lo general, hacemos que los lenguajes sean expresivos al diseñarlos para un propósito especial, como shells o DSL como R, maple, etc. Y encuentra relativamente poca expresividad en la mayoría de los lenguajes de propósito general como C, C ++, Java, etc.
Python, Perl, Ruby, etc. son lenguajes de uso general que son más expresivos en formas similares a las conchas, la escritura del pato ala. Entonces, las DSL se sueldan sobre ellas, como Sage para las matemáticas. Sin embargo, no es tan bueno para los comandos de shell reales .
El esquema no es tan expresivo, incluso una vez que construyes un DLS, debido a todos los paréntesis.
Sin embargo, existen lenguajes funcionales como Haskell con una enorme expresividad y una gran capacidad para construir DSL. Esfuerzo interesante para construir un caparazón en Haskell son las tortugas y las conchas .
En la práctica, hay una curva de aprendizaje con herramientas de esfuerzo debido al sistema de tipo potente pero restrictivo de Haskell, pero muestran una promesa considerable.
fuente
Primero, deberías usarlo en
"${files[@]}"
todas partes${files[*]}
. De lo contrario, los espacios te arruinarán.El shell ya es bastante funcional; si piensa que en términos de salida de texto son listas de líneas, entonces
grep
isfilter
,xargs
ismap
, etc. Las tuberías son muy funcionales.El shell no es el entorno de programación más amigable, pero es mucho más adecuado para el uso interactivo que Python. Y tiene la característica muy buena de que la API y la interfaz de usuario son idénticas: aprenda ambas cosas a la vez.
No entiendo por qué te parece
cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'
preferiblecp "${FILES[@]}" dist
. Este último es mucho menos tipeado.fuente
No sé si es "funcional", pero también hay rc , que el documento scsh menciona. Es un antecesor de es.
En Linux Mint (y probablemente Debian, Ubuntu ...) puedes probarlo con
fuente