函数有没有像*接口*这样的概念?

Is there a concept like *interface* for functions?

提问人:blue_note 提问时间:12/17/2017 更新时间:12/18/2017 访问量:68

问:

我有各种函数接受相同的参数并返回相同的类型。它们做类似的事情(例如,使用不同的近似方法进行集成),只是名称不同。我想强制所有变体具有相同的签名。

这可以通过将它们包装到类中来完成,但没有概念上的理由。那么,有没有类似于函数的概念呢?也就是说,有没有办法做类似的事情interface

abstract Double integration(Double[] xs, Double[] ys);
Double RiemmannIntegration implements integration(...) {...}

显然,这个问题只对函数是第一类对象的语言有意义(我最感兴趣的是python / javascript)。

JavaScript Python 语言不可知

评论

0赞 user2390182 12/17/2017
您希望在编译时强制执行吗?
3赞 jonrsharpe 12/17/2017
在函数是第一类对象的语言中,它们的可调用签名其接口的(一部分)。此外,您给出的两个示例是没有类型的语言(至少默认情况下;JS 有 TypeScript,见 typescriptlang.org/docs/handbook/functions.html,Python 有,见 docs.python.org/3/library/typing.html#callable)。typing
0赞 blue_note 12/17/2017
@schwobaseggl:最好是。类的方法会发生什么
0赞 Daniel Pryden 12/17/2017
@blue_note:但你说你对 Python 和 JavaScript 感兴趣,这两种语言没有任何类型的编译时检查,更不用说函数式了。这没有意义。
0赞 blue_note 12/17/2017
@DanielPryden:确实如此。然而,我最感兴趣的是在任何语言中是否存在这样的概念。此外,python 有类型注释,typescript 为 javascript 添加了类似的功能,因此可以实现类似的东西

答:

0赞 Blownhither Ma 12/17/2017 #1

在 python 中,可以强制执行类型检查

def type_check_decorator(args_types):
    def real_decorator(func):
        def wrapper(*args):
            # type checking
            for i, (a, t) in enumerate(zip(args, args_types)):
                if not isinstance(a, t):
                    raise ValueError('Type error on argument {}, should be {} but {} given'
                                     .format(i, t, type(a)))
            # execute real function
            return func(*args)
        return wrapper
    return real_decorator


my_interface = type_check_decorator([int, int])

@my_interface
def func1(a, b):
    return a + b

使用此装饰器,您可能拥有

func1(1, 2)    # OK
func1(1.1, 2)  # ValueError: Type error on argument 0, should be <type 'int'> but <type 'float'> given

若要使用此修饰器,请将args_types中的参数所需的类型作为数组,并将生成的接口应用于定义的函数。您可能仍然需要将库用于效果,例如“None-able”参数,或者通过修改此代码来实现自己的效果。事实上,这个装饰器的优点是使您能够定义任意类型检查例程(否则可能会更好)。typingtyping

如果所有函数的键入要求完全相同,则可以删除最外层的装饰器并使用硬编码的 .arg_types

评论

0赞 Daniel Pryden 12/17/2017
或者,在较新版本的 Python 中,您可以使用该模块。虽然可能有用的知识,但这并不能回答这个问题。typing
1赞 Daniel Pryden 12/17/2017 #2

你要寻找的概念是函数的类型。具体来说,这是一种“更高级”的类型,因为它是一种类型,而不是一种值类型。

在像 Haskell 这样的语言中,你必须传递这样的函数参数。如果未显式命名类型,编译器将为您推断该类型。但是,如果您尝试传递接受不同类型的不同函数,则会出现编译错误。

C# 具有用于声明函数类型的特殊语法,称为委托类型。Java 8+ 具有函数式接口的概念,或者只有一种方法的接口,并且具有一些语言特性,可以更轻松地传递表示给定类型函数的对象。

在 JavaScript 和 Python 中,对象实际上没有接口,至少没有显式接口。但是,您可以实现的是协议,在这些协议中,您要求参数是接受某些参数并以某种方式运行的函数。Python 标准库中的一个很好的例子是函数的参数:它必须是一个接受要排序的可迭代对象中的一个项目并返回一个可比较对象用作排序键的函数。keysorted()