Function 什么样的功能被视为;可组合的;?
维基百科的文章说: 就像数学中常见的函数组合一样,每个函数的结果作为下一个函数的参数传递,最后一个函数的结果就是整个函数的结果 我有两个问题:Function 什么样的功能被视为;可组合的;?,function,scala,functional-programming,Function,Scala,Functional Programming,维基百科的文章说: 就像数学中常见的函数组合一样,每个函数的结果作为下一个函数的参数传递,最后一个函数的结果就是整个函数的结果 我有两个问题: 可组合函数必须同时具有参数和返回值 因此,以下功能不适用: def doNothing(): Unit = () def myName(): String = "My name" def eat(food:String): Unit = () 我的理解正确吗 这个功能会有副作用吗 def hello(name:String):String = {
def doNothing(): Unit = ()
def myName(): String = "My name"
def eat(food:String): Unit = ()
我的理解正确吗def hello(name:String):String = {
println("name: " + name) // side-effect
name + "!"
}
我们仍然认为它是“可组合的”吗?
<p>2)如果函数有副作用,则不能认为它是函数
1) 如果函数没有参数-它是一个常量。如果函数没有返回值-其返回值为单位
(也可以是输入参数)
另外,你也可以为“脏”函数定义一个“函数”(子程序)组合,但这不是人们通常所说的意思;正如数学中的函数合成一样,它意味着纯函数的合成
谈论Scala:
scala> def doNothing(): Unit = ()
doNothing: ()Unit
scala> (doNothing _)
res0: () => Unit = <function0>
scala> (doNothing _) andThen (doNothing _)
<console>:9: error: value andThen is not a member of () => Unit
(doNothing _) andThen (doNothing _)
^
scala> def doSomething(a: Int) = a
doSomething: (a: Int)Int
scala> (doSomething _) andThen (doSomething _)
res2: Int => Int = <function1>
数学的形式语言和编程的口语语言的混合使得这些对话变得困难。您在这里处理的是两个上下文加载的单词:“composable”和“function” 数学中的函数合成 “函数”的数学概念→ B是从某个集合a到某个集合B的映射,“函数组合”是由
∘代码>。对于某些f:A→ B
和g:B→ C
,g∘f
是一个函数a→ C
,使
(g∘f) (x)=g(f(x))用于A
中的所有x
。如果任何两个函数的域/辅域以这种方式匹配(换句话说,这样的一对函数“可以组合”),则该组合被定义为任意两个函数,我们通过声明“函数是可组合的”来描述这一点
编程中的可组合性
作为一个定性术语,我们经常在软件中使用“可组合性”来描述一组组合的能力,这些组合可以通过组合小的组合来构建大的东西。从这个意义上讲,程序员将函数(作为一个整体)描述为“非常可组合”,因为函数可以(并且,在Haskell这样的纯函数语言中,函数可以)构成整个程序的大小部分
在软件中,我们还看到“可组合”一词的用法更加人性化,它往往与“模块化”有关。当组件是无状态的,关注点是分离的,并且API具有较低的表面积时,编写程序更容易而不会出错。我们称赞这种设计的组件是“可组合的”——不仅因为它们可以组合,还因为它们易于正确组合
函数在程序设计中的应用
我将使用稍微过时的术语“子程序”,因为我不知道用我们这个时代的说法来讨论这个问题的好方法。如果子例程不执行任何IO(并且总是停止,不抛出…),那么它实现(或“是”)数学意义上的“函数”。IO子例程表面上与函数相似,因为它们可能有输入和输出值,但相似性仅限于此。我们第一次讨论的关于“函数组合”的对话都不适用
这是我们遇到的最棘手的语言难题,因为“函数”一词已成为任何子程序的常用词,即使是执行IO的子程序。FP爱好者倾向于与之抗争——人们说“如果它有IO,它就不是一个功能”——但这场流行之战已经失败,现在已经没有回头路了。在大多数编程环境中,所有子例程都称为“函数”,区分满足数学定义的函数的唯一方法是将它们称为“纯函数”
根据这些定义,让我们来回答您的问题: “可组合函数必须同时具有参数和返回值?” 关于这个问题,有一些无聊的事情需要指出。首先,Scala中的每个函数在技术上都有一个返回类型。如果该类型是
Unit
,为简洁起见,可以省略它,但它仍然是返回类型
一个空值(0-arg)函数可以简单地转换成一个带参数的等价函数。所以说真的,没关系。如果您需要用参数组合函数,而f
没有参数,那么您可以只编写\uu=>f
“这个功能会有副作用吗?”
只是语义上的争论。在Scala的上下文中,最恰当的说法是它是一个函数
(或者在技术上是一个“方法”,取决于它的定义),但由于副作用,它不是一个纯函数
“我们仍然认为这是“合乎情理的”吗?
有点。所有这些东西仍然以一种相当普遍的方式“结合在一起”,所以是的,它们确实是在软件意义上组合的。虽然纯函数比不纯函数组成得更好。函数组合的数学概念不适用于非纯函数的子程序
最后,如果您想知道它们是否真的在Scala中使用compose
方法进行组合,则不需要堆栈溢出;只要问问编译器。你认为我在问题中定义的“函数”中没有一个是不可组合的吗?或者其中一些是?
scala> def eat(food:String): Unit = ()
eat: (food: String)Unit
scala> (eat _) andThen (doNothing _)
<console>:10: error: type mismatch;
found : () => Unit
required: Unit => ?
(eat _) andThen (doNothing _)
^
scala> def doNothingU(u: Unit): Unit = ()
doNothingU: (u: Unit)Unit
scala> (doNothingU _) andThen (doNothingU _)
res5: Unit => Unit = <function1>
scala> (eat _) andThen (doNothingU _)
res6: String => Unit = <function1>
scala> (doNothingU _) compose eat
res11: String => Unit = <function1>