Je suis (vraiment) novice en programmation fonctionnelle (en fait, je n'ai eu de contact qu'avec elle en utilisant python), mais semble être une bonne approche pour certaines tâches gourmandes en listes dans un environnement shell.
J'adorerais faire quelque chose comme ça:
$ [ git clone $host/$repo for repo in repo1 repo2 repo3 ]
Existe-t-il un shell Unix avec ce genre de fonctionnalité? Ou peut-être une fonctionnalité permettant un accès facile au shell (commandes, env / vars, readline, etc ...) depuis python (l'idée est d'utiliser l'interpréteur interactif de python en remplacement de bash).
ÉDITER:
Peut-être qu'un exemple comparatif clarifierait. Disons que j'ai une liste composée de dir / fichier :
$ FILES=( build/project.rpm build/project.src.rpm )
Et je veux faire une tâche vraiment simple: copier tous les fichiers dans dist / ET l'installer dans le système (cela fait partie d'un processus de construction):
Utilisation de bash:
$ cp $ {files [*]} dist / $ cd dist && rpm -Uvh $ (pour f dans $ {files [*]}; do basename $ f; done))
Utilisation d'une approche "shell pythonique" (attention: c'est du code imaginaire):
$ cp [os.path.join ('dist', os.path.basename (file)) pour le fichier dans FILES] 'dist'
Pouvez-vous voir la différence ? C’est de cela que je parle. Comment ne peut-on pas encore sortir d'un shell avec ce genre de trucs intégrés? C'est une vraie douleur de gérer des listes en shell, même si c'est une tâche si courante: liste de fichiers, liste de PID, liste de tout.
Et un point vraiment, vraiment important: utiliser la syntaxe / outils / fonctionnalités que tout le monde connaît déjà: sh et python.
IPython semble être dans la bonne direction, mais il est gonflé: si le nom var commence par '$', il fait ceci, si '$$' il fait cela. Sa syntaxe n'est pas "naturelle", donc de nombreuses règles et "contournements" ( [ ln.upper() for ln in !ls ]
-> erreur de syntaxe)
Réponses:
Il existe un Scheme Shell qui est probablement très proche de ce que vous recherchez. Je ne l'ai pas utilisé moi-même.
MISE À JOUR :
Je viens de l'installer et de l'essayer moi-même. Il semble que scsh soit plus un interpréteur de schéma interactif et un langage de script qu'un shell interactif vraiment utile. Vous ne pouvez pas simplement taper
la syntaxe semble être
et il a fallu plusieurs minutes de recherche sur Google juste pour trouver cela. Le premier exemple ici est:
ce qui se traduit par:
mais cela ne vous dit pas comment exécuter une simple commande shell.
Cette entrée de la FAQ dit:
C'est peut-être la vraie réponse.
la source
Dans la catégorie des réponses directes à la question, il y a le shell ES qui se veut un remplacement fonctionnel pour Bash et Zsh etc.
Deuxièmement, dans la catégorie de vous aider à écrire un shell standard plus fonctionnel, envisagez d'apprendre la technique du pipetier:
La première boucle while est une fonction
keep
(ne transmettez que les valeurs non nulles qui sortent de la boucle) et la seconde est uneeach
(mappage des effets secondaires uniquement).Il s'agit d'un formidable coup de pouce au fp dans les coquilles.
Il est possible d'exprimer beaucoup de choses dans un style plus fp dans un shell, ce n'est tout simplement pas aussi facile qu'il pourrait l'être. Il semble qu'il n'y ait pas beaucoup d'intérêt à fabriquer de meilleures coquilles, même si nous les utilisons tous beaucoup.
la source
Les coquilles standards de type Bourne (
sh
,bash
,ksh
, etc.) vous permettent déjà faire:(Notez la nécessité de points-virgules avant
do
etdone
.) De plus, dansbash
et dans d' autres shells, si une$repo
seule fois apparaît dans la commande, vous pouvez écrire:la source
git clone $host/{repo1,repo2,repo3}
ne fait pas la même chose que lafor
boucle; il invoquegit clone
une fois avec trois arguments. Le fait que cela fasse essentiellement la même chose est un artefact de la façon dontgit clone
fonctionne; il ne s'applique pas nécessairement aux autres commandes. (Comparezecho foo bar baz
àecho foo; echo bar; echo baz
, par exemple.)FUN=eval 'git clone '"$host"'$0
pour définir un lambda à utiliser commefor repo in repo{1,2,3} ; do $FUN $repo ; done
Scheme Shell, scsh, est vraiment bon.
Comme le note Keith Thompson, il n'est pas utile en tant que shell interactif (bien que le commandant S ressemble à une expérience intéressante). Au lieu de cela, c'est un excellent langage de programmation pour les contextes où toutes les liaisons POSIX sont utiles - cela inclut les cas où vous souhaitez appeler d'autres applications Unix. Un script shell de plus de quelques dizaines de lignes se sentira toujours comme un hack, quelle que soit la façon dont vous écrivez
sh
; en revanche, rien ne vous empêche d'écrire des programmes importants en utilisant scsh.scsh n'est pas très compact (la brièveté est à la fois la force et la faiblesse des langages de la famille sh), mais il est puissant.
Parce qu'il est utile et pratique pour les petites et grandes tâches, scsh est d'ailleurs un bon moyen de se familiariser avec un schéma (bien que, si cela était votre objectif, vous feriez aussi bien d'aller directement à Racket, ces jours-ci).
Les avantages des langages fonctionnels ne sont pas seulement pour les tâches gourmandes en listes (bien qu'en raison de leur historique, ils ont tendance à privilégier les listes en tant que structure de données) - c'est un moyen très robuste pour écrire des programmes, une fois que vous buvez le bon kool- aide.
Il n'y a pas de sens significatif dans lequel les shells de style sh sont fonctionnels, et Python n'est fonctionnel que dans le sens marginal où il a une fonction lambda.
la source
Les coquilles sont nécessairement extrêmement expressives, ce qui signifie que vous réalisez des lots avec moins de lignes, de jetons, etc.
Nous rendons généralement les langages expressifs en les concevant à des fins spéciales, comme les shells ou les DSL comme R, érable, etc. Et vous trouvez relativement peu d'expressivité dans la plupart des langages à usage général comme C, C ++, Java, etc.
Python, Perl, Ruby, etc. sont des langages à usage général qui sont plus expressifs de manière similaire aux shells, ala duck typing. Les DSL sont donc soudés dessus, ala Sage pour les mathématiques. Ce n'est pas si bon pour les commandes shell réelles .
Le schéma n'est pas à mon humble avis, même une fois que vous avez créé un DLS, à cause de toutes les parenthèses.
Il existe cependant des langages fonctionnels comme Haskell avec une expressivité énorme et une grande capacité de construction de DSL. Les efforts intéressants pour construire une coquille sur Haskell sont la tortue et la coquille .
Dans la pratique, il existe une courbe d'apprentissage avec des outils d'efforts en raison du système de type Haskell puissant mais restrictif, mais ils sont très prometteurs.
la source
Tout d'abord, vous devez utiliser
"${files[@]}"
partout où vous avez${files[*]}
. Sinon, les espaces vous gâcheront.Le shell est déjà assez fonctionnel; si vous pensez que la sortie de texte est une liste de lignes, alors
grep
estfilter
,xargs
estmap
, etc. Les tuyaux sont très fonctionnels.Le shell n'est certes pas l'environnement de programmation le plus convivial, mais il est beaucoup plus adapté à une utilisation interactive que Python. Et il a la très belle fonctionnalité que l'API et l'interface utilisateur sont identiques - apprenez les deux à la fois.
Je ne comprends pas pourquoi vous trouvez
cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'
préférablecp "${FILES[@]}" dist
. Ce dernier est beaucoup moins typant.la source
Je ne sais pas si c'est "fonctionnel", mais il y a aussi rc , que le papier scsh mentionne. C'est un prédécesseur d'es.
Sur Linux Mint (et probablement Debian, Ubuntu ...) vous pouvez l'essayer avec
la source