Ich bin (wirklich) Neuling in der funktionalen Programmierung (tatsächlich hatte ich nur mit Python Kontakt), aber es scheint ein guter Ansatz für einige listenintensive Aufgaben in einer Shell-Umgebung zu sein.
Ich würde gerne so etwas machen:
$ [ git clone $host/$repo for repo in repo1 repo2 repo3 ]
Gibt es eine Unix-Shell mit solchen Funktionen? Oder vielleicht eine Funktion, die einen einfachen Shell-Zugriff (Befehle, env / vars, readline usw.) aus Python heraus ermöglicht (die Idee ist, den interaktiven Interpreter von Python als Ersatz für bash zu verwenden).
BEARBEITEN:
Vielleicht würde ein Vergleichsbeispiel klarstellen. Nehmen wir an, ich habe eine Liste bestehend aus dir / file :
$ FILES=( build/project.rpm build/project.src.rpm )
Und ich möchte eine wirklich einfache Aufgabe erledigen: Kopieren Sie alle Dateien nach dist / UND installieren Sie sie im System (es ist Teil eines Build-Prozesses):
Bash benutzen:
$ cp $ {files [*]} dist / $ cd dist && rpm -Uvh $ (für f in $ {files [*]}; mache den Basisnamen $ f; fertig)
Verwenden eines "Pythonic Shell" -Ansatzes (Vorsicht: Dies ist imaginärer Code):
$ cp [os.path.join ('dist', os.path.basename (file)) für file in FILES] 'dist'
Kannst du den Unterschied sehen? DAS ist es, wovon ich rede. Wie kann man eine Shell mit solchen eingebauten Sachen noch nicht verlassen? Es ist ein echtes Problem, mit Listen in der Shell umzugehen, auch wenn es eine so häufige Aufgabe ist: Liste der Dateien, Liste der PIDs, Liste von allem.
Und ein wirklich, wirklich wichtiger Punkt: Verwenden von Syntax / Tools / Features, die jeder bereits kennt: sh und Python.
IPython scheint auf einem guten Weg zu sein, aber es ist aufgebläht: Wenn der Variablenname mit '$' beginnt, tut es dies, wenn '$$', tut es das. Die Syntax ist nicht "natürlich", so viele Regeln und "Problemumgehungen" ( [ ln.upper() for ln in !ls ]
-> Syntaxfehler)
Antworten:
Es gibt eine Schema-Shell , die wahrscheinlich sehr nah an dem ist, wonach Sie suchen. Ich habe es selbst nicht benutzt.
UPDATE:
Ich habe es gerade selbst installiert und ausprobiert. Es scheint, dass scsh eher ein interaktiver Scheme-Interpreter und eine Skriptsprache ist als eine wirklich nützliche interaktive Shell. Sie können nicht einfach tippen
Die Syntax scheint zu sein
und es dauerte einige Minuten von Googeln, nur um das zu finden. Das erste Beispiel ist hier :
was übersetzt zu:
Aber das sagt Ihnen nicht, wie man einen einfachen Shell-Befehl ausführt.
Dieser FAQ-Eintrag lautet:
Vielleicht ist das die richtige Antwort.
quelle
In der Kategorie der direkten Beantwortung der Frage gibt es die ES-Shell, die als funktionaler Ersatz für Bash und Zsh usw. gedacht ist.
Zweitens sollten Sie in der Kategorie Hilfe beim Schreiben einer funktionaleren Standard-Shell das Erlernen der Pipemill-Technik in Betracht ziehen:
Die erste while-Schleife ist eine Funktion
keep
(nur die Nicht-Null-Werte weitergeben, die aus der Schleife kommen) und die zweite ist eineeach
(Karte nur für Nebenwirkungen).Dies ist ein enormer Schub für Fp in Shells.
Es ist möglich, viele Dinge in einer Shell in einem fp-Stil auszudrücken, es ist einfach nicht so einfach, wie es sein mag. Es scheint, dass es nicht viel Interesse gibt, bessere Muscheln herzustellen, obwohl wir sie alle so oft verwenden.
quelle
Die Standard - Bourne-style Schalen (
sh
,bash
,ksh
, etc.) schon können Sie tun:(Beachten Sie die Notwendigkeit von Semikolons vor
do
unddone
.) Außerdem können Sie inbash
und in anderen Shells$repo
schreiben , wenn sie nur einmal im Befehl enthalten sind:quelle
git clone $host/{repo1,repo2,repo3}
macht nicht das Gleiche wie diefor
Schleife; es ruftgit clone
einmal mit drei Argumenten auf. Die Tatsache, dass sie im Wesentlichen dasselbe tut, ist ein Artefakt der Funktionsweisegit clone
. Dies gilt nicht unbedingt für andere Befehle. (Vergleicheecho foo bar baz
zumecho foo; echo bar; echo baz
Beispiel.)FUN=eval 'git clone '"$host"'$0
, um ein Lambda zu definieren, das alsfor repo in repo{1,2,3} ; do $FUN $repo ; done
Schema Shell, scsh, ist wirklich gut.
Wie Keith Thompson bemerkt, ist es als interaktive Shell nicht nützlich (obwohl Commander S wie ein interessantes Experiment aussieht). Stattdessen ist es eine ausgezeichnete Programmiersprache für Kontexte, in denen alle POSIX-Bindungen nützlich sind - dies schließt Fälle ein, in denen Sie andere Unix-Anwendungen aufrufen möchten. Ein Shell-Skript mit mehr als ein paar Dutzend Zeilen fühlt sich immer wie ein Hack an, egal wie ordentlich Sie schreiben
sh
. im gegensatz dazu hindert nichts sie daran, wichtige programme mit scsh zu schreiben.scsh ist nicht sehr kompakt (Kürze ist sowohl die Stärke als auch die Schwäche von Sprachen der sh-Familie), aber es ist mächtig.
Da scsh für kleine und große Aufgaben nützlich und praktisch ist, ist es im Übrigen eine gute Möglichkeit, ein Schema in den Griff zu bekommen (obwohl Sie heutzutage auch gleich zu Racket wechseln könnten, wenn dies Ihr Ziel wäre).
Die Vorteile von funktionalen Sprachen gelten nicht nur für listenintensive Aufgaben (obwohl sie aufgrund ihrer Vergangenheit Listen als Datenstruktur bevorzugen) - es ist eine sehr robuste Methode, um Programme zu schreiben, wenn Sie die richtige Lernsoftware trinken. Hilfe.
Es gibt keinen sinnvollen Sinn, in dem die Sh-Shells funktionieren, und Python ist nur in dem marginalen Sinn funktionsfähig, in dem es eine Lambda-Funktion hat.
quelle
Muscheln sind notwendigerweise extrem ausdrucksstark, was bedeutet, dass Sie viel mit weniger Linien, Token usw. erreichen.
Wir machen Sprachen in der Regel ausdrucksstark, indem wir sie für einen bestimmten Zweck entwerfen, z. B. für Muscheln oder DSLs wie R, Ahorn usw. In den meisten Mehrzwecksprachen wie C, C ++, Java usw. ist die Ausdruckskraft relativ gering.
Python, Perl, Ruby usw. sind Mehrzwecksprachen, die in ähnlicher Weise wie Muscheln ausdrucksstark sind. Also werden DSLs angeschweißt, ala Sage für Mathe. Ist aber nicht so toll für aktuelle Shell-Befehle .
Das Schema ist nicht so aussagekräftig, auch wenn Sie erst einmal ein DLS erstellt haben, da alle Klammern gesetzt sind.
Es gibt jedoch funktionale Sprachen wie Haskell mit enormer Ausdruckskraft und einer großen Kapazität zum Aufbau von DSLs. Interessante Bemühungen, eine Muschel auf Haskell zu bauen, sind Schildkröten und Muscheln .
In der Praxis gibt es aufgrund des leistungsfähigen, aber restriktiven Schriftsystems von Haskell eine Lernkurve mit Aufwandsinstrumenten, die jedoch beträchtliche Aussichten eröffnen.
quelle
Erstens sollten Sie
"${files[@]}"
überall verwenden, wo Sie haben${files[*]}
. Andernfalls werden Leerzeichen Sie durcheinander bringen.Die Shell ist schon ziemlich funktionell; Wenn Sie denken, dass die Textausgabe Listen von Zeilen ist, dann
grep
istfilter
,xargs
istmap
usw. Pipes sind sehr funktional.Die Shell ist zwar nicht die freundlichste Programmierumgebung, eignet sich jedoch viel besser für die interaktive Verwendung als Python. Und es hat die sehr nette Eigenschaft, dass die API und die Benutzeroberfläche identisch sind - lernen Sie beide auf einmal.
Ich verstehe nicht, warum Sie es
cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'
vorziehencp "${FILES[@]}" dist
. Letzteres ist viel weniger tippen.quelle
Ich weiß nicht, ob es "funktionstüchtig" ist, aber es gibt auch rc , was im scsh-Artikel erwähnt wird. Es ist ein Vorläufer von es.
Auf Linux Mint (und wahrscheinlich Debian, Ubuntu ...) können Sie es mit versuchen
quelle