调用函数的新思路

免责声明:这将有点保修。 我对听起来给我们带来的“问题”并不感到沮丧; 相反,它用来强调我的思想过程为何做到了这一点。 我什至不打算使用标题标题,这对我来说很奇怪:)

我最近有一个关于调用函数的思考过程。 功能语言(有时甚至是其他语言)如何实现某个目标一直令我感到沮丧。

该目标是链接电话。

我认为似乎没有人做对。 唯一有效的方法是使用对象的流畅接口。 让我们以一个简单的例子filter荷兰国际集团的列表(称为myList的偶数)(谓词函数将被调用evens ),然后map平的结果squared

在具有用于filtermap泛型函数的典型多范例语言中,例如Python:

map(squared, filter(evens, myList))

或一种口齿不清的语言:

(map squared (filter evens myList))

首先让我想到的是,这些功能从右到左,由内而外运行。 对于那些经常从事数学工作的人来说,从内而外移动并不困难,但是我们仍然更喜欢从左到右(反正那些主要语言是从左到右的人)来做。 必须颠倒这些函数调用,这很麻烦,并且减慢了我们确定代码功能的能力。

注意:另外,请注意,这些函数将传入的函数放在参数列表中而不是列表中。 我个人一直认为最好将要处理的主要对象放在首位。 我可以想到的首先包含这些函数的唯一原因是,它通过使用currying或使用Python的partial提供了更易于创建的高抽象函数(例如,使reduce成为sum函数)。 参数的顺序将在稍后的“解决方案”中再次出现。

许多这些语言提供的一个有用的功能是组合函数,它使我们可以将函数调用组合成一个函数。 如果我们分别将mapfilter函数分别咖喱化或partial map_squaredfilter_evens ,则可以像下面这样进行compose调用:

compose(map_squared, filter_evens, myList)

或者像这样一口气:

(compose map_squared filter_evens myList)

注意到什么了吗? 我们仍在从右到左阅读! 出于某种原因,人们普遍同意compose(f, g, data)应该读为“ f of g ”(像数学家一样),而不是“ f then g ”(像其他任何人一样)。 当然,函数式编程(可能是其他编程的90%)是由对数学感兴趣的人员设计的。 哎呀,我很喜欢数学,曾经两次学过微积分(第一次是在高中,第二次是在大学,两次都是为了娱乐)。 但这仍然不是我喜欢的读写函数调用的方式。

我喜欢什么 如前所述,流畅的OO API可以很好地工作。 理想情况下,我想打电话给

myList.filter(evens).map(squared)

有人可能会认为这类似于Java 8的Stream API的外观。 这也与Kotlin的外观非常接近。

但是,这是OO方法的问题:

  • OO仅适用于OO语言(显然)
  • 为了完成这些流畅的API,您要么必须先将它们构建到对象中,要么必须创建某种实现它们的包装器类。
  • 即使您确实使用了流畅的API,以后仍可能会需要一些由于某些原因而无法添加的新功能。

使用扩展方法可以缓解最后两个问题(出于明显的原因,扩展方法仅包含在OO语言中),但是我决定从一种语言的角度出发,该语言要么是纯功能性的,要么至少是部分OO而不包含语言。创建扩展方法的方法。

我唯一的解决方案是为调用函数创建一种新的可选方法。 它部分地受到了Python方法的启发,这些方法已经做到了,但是相反。 它们允许像普通函数一样调用对象方法,而我的解决方案允许像对象方法那样调用普通函数。 有关Python如何执行前者的解释,请参阅本文,了解为何我认为self争论是个天才

因此,如果您还没有弄清楚,我的解决方案是让函数的第一个参数像您要调用该函数(作为“方法”)的对象一样工作。 这样,您可以采用许多Python的内置函数,例如leniternext等,并像这样调用它们:

myList.len()

myList.iter()

myIterator.next()

这更符合其他OO语言。

它们不是真正的方法,但是看起来像方法,它允许它们像流利的方法一样被链接起来。 回到前面的旁注中,我们必须颠倒filter和map(以及其他类似对象)的参数顺序,以使序列优先。 否则,我们的示例将无法正常工作,如下所示:

squared.map(evens.filter(myList))

哪一个甚至还没有开始解决问题。

那如何进行partial使用? 好吧,您似乎必须手动定义sum函数,而不是使用currying。 例如(假设reduce现在首先列出一个列表):

def sum(sequence):

return reduce(sequence, operator.add)

至于局部的,如果您使用关键字参数,它仍然可以工作:

sum = functools.partial(function=operator.add)

lisps呢? 他们没有OO调用语法。 这怎么可能与lisps一起工作? 简单:新方法可以将第一个参数放在第一位, 然后是被调用函数的名称,并以句点作为前缀。 例如,新的地图和过滤器语法如下所示:

((myList .filter evens) .map squared)

所以你怎么看? 你喜欢这个主意吗? 我很想开发一种具有这种功能的语言,但是我正忙于其他想法,以至于自己不愿意创建一种新语言。 如果当前使用的语言要在其功能表中添加这种语法糖,我会更喜欢它。 手指交叉。 因为我已经厌倦了为这类东西编写包装器类。

翻译自: https://www.javacodegeeks.com/2015/03/a-new-idea-for-calling-functions.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值