Functional programming 在函数式编程中,是;“拯救国家”;一个算法在递归函数参数欺骗?
例如,假设我们必须编写一个算法来获取整数数组的最大值,如果我们让递归函数返回模拟全局对象赋值的各种信息,我们还能调用代码函数吗?例如:Functional programming 在函数式编程中,是;“拯救国家”;一个算法在递归函数参数欺骗?,functional-programming,Functional Programming,例如,假设我们必须编写一个算法来获取整数数组的最大值,如果我们让递归函数返回模拟全局对象赋值的各种信息,我们还能调用代码函数吗?例如: function getMax(array, props={}) { const {index = 0, actualMax = array[0]}= props ///initial props const arrayNotEnded = array[index + 1] !== undefined if (arrayNotEnded)
function getMax(array, props={}) {
const {index = 0, actualMax = array[0]}= props ///initial props
const arrayNotEnded = array[index + 1] !== undefined
if (arrayNotEnded) {
const maxOf= (a, b) => a > b ? a : b
const newMax = maxOf(actualMax, array[index+1])
const nextIndex = index+1
return getMax(array, {index:nextIndex, actualMax:newMax} )
}else return actualMax
}
<有趣的是,在Haskell,我们不能有可选的参数,所以这个逻辑不会是很酷的工作,因为每次我们需要调用这个函数时,我们都必须通过最初的道具。
是的,你可以认为它是作弊,但是这是函数编程中的一个众所周知的技术。累加器参数。记住:代码不会因为没有状态而变得功能化,函数式编程就是要使状态显式化。没有比将其作为函数的参数更好的方法了
不过,您的代码还有一些其他问题。最重要的是,状态应该是函数的内部状态,只传递给助手函数(可能是本地声明的或单独的),而不是作为函数公共接口的一部分。这还可以防止通过传递无效状态(例如越界索引)而混淆助手函数。是的,可选参数也有气味——不是因为您认为这在Haskell中是不可能的(使用可能),而是因为它可能被遗忘或错误地传递。相反,helper函数应该有一个必需的状态参数,getMax
应该没有状态参数。
最后但并非最不重要的一点是,您应该避免对数组进行越界索引访问-检查长度以了解结束位置,不要与未定义的进行比较。这包括无条件地访问数组[0]
——这很容易忽略函数可以返回未定义的。也要明确此错误条件
我是这样写的:
function getMax(array) {
if (!array.length)
throw new Error("array must be non-empty");
else
return maxFrom(1, array[0]);
function maxFrom(index, max) {
if (index < array.length)
return maxFrom(index+1, array[index] > max ? array[index] : max);
else
return actualMax
}
}
函数getMax(数组){
如果(!array.length)
抛出新错误(“数组必须非空”);
其他的
返回maxFrom(1,数组[0]);
函数maxFrom(索引,最大值){
if(索引<数组长度)
返回maxFrom(索引+1,数组[index]>max?数组[index]:max);
其他的
返回实际最大值
}
}
甚至比抛出异常更好的是,如果您手头有一个代数数据类型,您可以返回它来表示错误或结果。Haskell可能会为此使用嵌套函数,例如getMax arr=innerMax 0(head arr),其中innerMax arr index actualMax=…
。它不会改变状态,每次调用都会给出相同的答案,所以我称之为函数。只是一个疑问:当你说Haskell中的Maybe to do可选参数时,你是说允许一个参数为“Nothing”吗?您确定这可以视为可选参数吗?因为我们需要指定我们希望该参数为空,不像其他语言(如javascript)那样,我们可以在没有参数的情况下简单地调用函数。@Vitorfigm是的,它在语义上是等价的,就像在javascript中传递未定义的。在JS中可以省略undefined
参数只是一个语法特性。当然,Haskell中还有其他解决方案,从使用默认值可以覆盖或不覆盖的记录参数,到允许可变(省略表)参数的高级重载技巧。