我(真的)是函数式编程的新手(实际上只使用 python 接触过它)但对于 shell 环境中的一些列表密集型任务来说,它似乎是一种很好的方法。
我很想做这样的事:
$ [ git clone $host/$repo for repo in repo1 repo2 repo3 ]
是否有任何 Unix shell 具有此类功能?或者也许某些功能允许从 python 内部轻松访问 shell(命令、env/vars、readline 等...)(想法是使用 python 的交互式解释器来替代 bash)。
编辑:
也许一个比较的例子可以解释清楚。假设我有一个列表,由目录/文件:
$ FILES=( build/project.rpm build/project.src.rpm )
我想做一个非常简单的任务:将所有文件复制到分布/并将其安装在系统中(这是构建过程的一部分):
使用 bash:
$ cp ${文件[*]} dist/ $ cd dist && rpm -Uvh $(for f in ${files[*]}; do basename $f; done))
使用“pythonic shell”方法(注意:这是虚构的代码):
$ cp [ os.path.join('dist', os.path.basename(file)) for file in FILES ] 'dist'
你能看出区别吗?这就是我所说的。如何退出内置了这些东西的 shell?在 shell 中处理列表真的很麻烦,即使它是一项很常见的任务:文件列表、PID 列表、所有内容的列表。
还有一个非常非常重要的点:使用大家都知道的语法/工具/功能:sh 和 python。
IPython 似乎朝着好的方向发展,但它有些臃肿:如果变量名称以“$”开头,它会这样做,如果以“$$”开头,它会那样做。它的语法不“自然”,有太多规则和“变通方法”([ ln.upper() for ln in !ls ]
--> 语法错误)
答案1
有一个方案外壳这可能非常接近您想要的。我自己没有用过。
更新 :
我刚刚安装并亲自尝试了它。看来 scsh 更像是一个交互式 Scheme 解释器和脚本语言,而不是一个真正有用的交互式 shell。你不能只输入
echo hello
语法似乎是
(run (echo hello))
我花了好几分钟在 Google 上搜索才找到这个。第一个例子这里是:
gunzip < paper.tex.gz | detex | spell | lpr -Ppulp &
翻译过来就是:
(& (| (gunzip) (detex) (spell) (lpr -Ppulp)) (< paper.tex.gz))
但这并没有告诉你如何运行简单的shell 命令。
4.6 我可以使用 scsh 作为交互式 shell 吗?
嗯,从技术上讲,您可以:只需运行“scsh”命令,您就会进入一个 Scheme 48 会话,其中所有 scsh 功能都可用。但是,这绝对不适合交互式工作:没有命令行编辑、没有命令行历史记录、没有文件/函数名称完成、没有简洁的语法等。
为了缓解这些问题,Martin Gasbichler 和 Eric Knauel 编写了 Commander S,它运行在 scsh 之上,并提供舒适的交互式环境。它的一个新颖的功能是它可以理解许多 Unix 命令的输出,并允许用户以有用的方式浏览和操作它。有关 Commander S 的更多信息可以在描述它的论文中找到: http://www.deinprogramm.de/scheme-2005/05-knauel/05-knauel.pdf 有关如何获取和安装 Commander S 的说明可从 scsh 网站获得:http://www.scsh.net/resources/commander-s.html
所以这也许就是真正的答案。
答案2
在直接回答问题的类别中,有ES外壳其目的是作为 Bash 和 Zsh 等的功能替代品。
其次,在帮助您编写更具功能性的标准 shell 方面,可以考虑学习 pipemill 技术:
who | while read username
do
cat <<EOF | grep $username
nic
mark
norman
keith
EOF
done | while read username
do
echo "you have an answer on superuser.com" | mail -s "well done" $username
done
第一个 while 循环是函数式的keep
(仅传递循环中出来的非空值),第二个 while 循环是each
(仅用于副作用的映射)。
这对于 shell 中的 fp 来说是一个巨大的提升。
在 shell 中,可以以更 fp 的风格表达许多东西,但这并不像想象的那么容易。似乎人们对制作更好的 shell 兴趣不大,尽管我们都经常使用它们。
答案3
标准的 Bourne 风格 shell(sh
、、等)已经允许您执行以下操作bash
:ksh
for repo in repo1 repo2 repo3 ; do git clone $host/$repo ; done
do
(请注意和之前需要加分号done
。)此外,在bash
和其他 shell 中,如果$repo
在命令中只出现一次,则可以写:
git clone $host/{repo1,repo2,repo3}
答案4
Scheme Shell,scsh,确实很好用。
正如 Keith Thompson 所说,它作为交互式 shell 并不实用(尽管 Commander S 看起来像一个有趣的实验)。相反,它是一种出色的编程语言,适用于拥有所有 POSIX 绑定很有用的上下文——包括您想要调用其他 unix 应用程序的情况。超过几十行的 shell 脚本将总是感觉像个黑客,不管你写得多么整洁sh
;相反,没有什么可以阻止你使用 scsh 编写重要的程序。
scsh 不是很紧凑(简洁是 sh 系列语言的优点和缺点),但它的功能强大。
因为它对于小型和大型任务来说都是有用和实用的,所以 scsh 顺便说一下是掌握 Scheme 的一种好方法(尽管如果那是你的目标,那么你现在不妨直接使用 Racket)。
函数式语言的优势不仅仅在于列表密集型任务(尽管由于它们的历史,它们倾向于将列表作为数据结构)——一旦你喝了正确的 kool-aid,它是一种编写程序的真正强大的方法。
sh 样式的 shell 的功能性没有任何实际意义,而 Python 的功能性仅在于其具有 lambda 函数这一边缘意义。