Sou (realmente) novato em programação funcional (na verdade, só tive contato com ele usando python), mas parece ser uma boa abordagem para algumas tarefas que exigem muita lista em um ambiente shell.
Eu adoraria fazer algo assim:
$ [ git clone $host/$repo for repo in repo1 repo2 repo3 ]
Existe algum shell Unix com esse tipo de recurso? Ou talvez algum recurso para permitir acesso fácil ao shell (comandos, env / vars, readline, etc ...) de dentro do python (a idéia é usar o interpretador interativo do python como um substituto para o bash).
EDITAR:
Talvez um exemplo comparativo esclareça. Digamos que eu tenho uma lista composta de dir / file :
$ FILES=( build/project.rpm build/project.src.rpm )
E eu quero fazer uma tarefa muito simples: copiar todos os arquivos para dist / AND instalá-lo no sistema (faz parte de um processo de compilação):
Usando o bash:
$ cp $ {files [*]} dist / $ cd dist && rpm -Uvh $ (para f em $ {files [*]}; faça o nome da base $ f; done))
Usando uma abordagem de "casca pitônica" (cuidado: este é um código imaginário):
$ cp [os.path.join ('dist', os.path.basename (file)) para o arquivo em FILES] 'dist'
Você consegue ver a diferença? É disso que estou falando. Como ainda não é possível sair de um shell com esse tipo de material? É uma verdadeira dor lidar com listas no shell, mesmo sendo uma tarefa tão comum: lista de arquivos, lista de PIDs, lista de tudo.
E um ponto muito, muito importante: usando sintaxe / ferramentas / recursos que todo mundo já conhece: sh e python.
O IPython parece estar em uma boa direção, mas está inchado: se o nome do var começar com '$', ele fará isso, se '$$' fizer isso. Sua sintaxe não é "natural", existem muitas regras e "soluções alternativas" ( [ ln.upper() for ln in !ls ]
-> erro de sintaxe)
Respostas:
Há um Shell de esquema que provavelmente está muito próximo do que você está procurando. Eu não usei eu mesmo.
ATUALIZAÇÃO:
Acabei de instalar e tentei eu mesmo. Parece que o scsh é mais um interpretador de esquema interativo e uma linguagem de script do que um shell interativo realmente útil. Você não pode simplesmente digitar
a sintaxe parece ser
e levou vários minutos pesquisando no Google apenas para descobrir isso. O primeiro exemplo aqui é:
que se traduz em:
mas isso não mostra como executar um simples comando shell.
Esta entrada da FAQ diz:
Então talvez essa seja a resposta real.
fonte
Na categoria de responder diretamente à pergunta, existe o shell ES, que se destina a substituir funcional o Bash e o Zsh, etc.
Em segundo lugar, na categoria de ajudá-lo a escrever shell padrão mais funcional, considere aprender a técnica de pipemill:
O primeiro loop while é funcional
keep
(transmite apenas os valores não nulos que saem do loop) e o segundo é umeach
(mapa apenas para efeitos colaterais).Este é um tremendo impulso ao FP nas conchas.
É possível expressar muitas coisas em um estilo mais fp em um shell, simplesmente não é tão fácil quanto pode ser. Parece que não há muito interesse em fazer conchas melhores, embora todos nós as usemos tanto.
fonte
As conchas Bourne de estilo padrão (
sh
,bash
,ksh
, etc.) já permitem que você faça:(Observe a necessidade de ponto
do
e vírgula antes edone
.) Além disso, embash
e outros shells, se$repo
aparecer apenas uma vez no comando, você pode escrever:fonte
git clone $host/{repo1,repo2,repo3}
não faz a mesma coisa que ofor
loop; invocagit clone
uma vez com três argumentos. O fato de fazer essencialmente a mesma coisa é um artefato de comogit clone
funciona; não se aplica necessariamente a outros comandos. (Compareecho foo bar baz
aecho foo; echo bar; echo baz
, por exemplo.)FUN=eval 'git clone '"$host"'$0
para definir um lambda para uso comofor repo in repo{1,2,3} ; do $FUN $repo ; done
Esquema Shell, scsh, é realmente bom.
Como observa Keith Thompson, não é útil como um shell interativo (embora o Commander S pareça um experimento interessante). Em vez disso, é uma excelente linguagem de programação para contextos em que é útil ter todas as ligações POSIX - isso inclui casos em que você deseja chamar outros aplicativos unix. Um script de shell com mais de algumas dezenas de linhas sempre parecerá um hack, não importa o quão bem você escreva
sh
; em contraste, não há nada que o impeça de escrever programas significativos usando o scsh.O scsh não é muito compacto (a brevidade é a força e a fraqueza das linguagens da família sh), mas é poderoso.
Por ser útil e prático para tarefas pequenas e grandes, o scsh é, aliás, uma boa maneira de se familiarizar com um esquema (embora, se esse fosse o seu objetivo, você também poderia ir direto para o Racket hoje em dia).
As vantagens das linguagens funcionais não são apenas para tarefas com muitas listas (embora, devido ao seu histórico, elas tendam a favorecer as listas como uma estrutura de dados) - é uma maneira realmente robusta de escrever programas, depois de beber o kool certo. ajuda.
Não há um sentido significativo no qual os shells do estilo sh sejam funcionais, e o Python é funcional apenas no sentido marginal de que ele possui uma função lambda.
fonte
Os reservatórios são necessariamente extremamente expressivos, o que significa que você obtém lotes com menos linhas, tokens etc.
Geralmente, tornamos as linguagens expressivas projetando-as para uma finalidade especial, como shells ou DSLs como R, maple, etc. E você encontra relativamente pouca expressividade na maioria das linguagens de uso geral, como C, C ++, Java, etc.
Python, Perl, Ruby etc. são linguagens de uso geral que são mais expressivas de maneira semelhante a shells, digitando ala duck. Então as DSLs são soldadas, ala Sage para matemática. Porém, não é tão bom para comandos reais de shell .
O esquema não é tão expressivo, mesmo depois de criar um DLS, devido a todos os parênteses.
No entanto, existem linguagens funcionais como Haskell com enorme expressividade e uma grande capacidade para criar DSLs. Esforço interessante para construir um escudo em Haskell são tartaruga e Shelly .
Na prática, há uma curva de aprendizado com ferramentas de esforços devido ao sistema de tipo Haskell poderoso, porém restritivo, mas elas mostram uma promessa considerável.
fonte
Primeiro, você deve usar em
"${files[@]}"
qualquer lugar que tenha${files[*]}
. Caso contrário, os espaços vão atrapalhar você.O shell já é bastante funcional; se você pensa em termos de saída de texto como listas de linhas, então
grep
éfilter
,xargs
émap
etc. Os tubos são muito funcionais.É certo que o shell não é o ambiente de programação mais amigável, mas é muito mais adequado para uso interativo que o Python. E tem o recurso muito bom de que a API e a interface do usuário são idênticas - aprenda as duas ao mesmo tempo.
Não entendo por que você acha
cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'
preferívelcp "${FILES[@]}" dist
. Este último é muito menos digitado.fonte
Não sei se é "funcional", mas também há rc , que o artigo scsh menciona. É um predecessor para es.
No Linux Mint (e provavelmente Debian, Ubuntu ...), você pode experimentá-lo com
fonte