Haskell新手问题:是否有一种技术可以提高效率并避免对tail原始列表进行两次调用
func1 originalList =
func2 (doSomething (tail originalList)) (doSomethingDifferent (tail originalList))
doSomething listA =
....
doSomethingDifferent listB =
....
func2 listA listB =
....
Run Code Online (Sandbox Code Playgroud)
在命令式编程语言中,您只需调用一次函数,并将其存储到变量中.
在像Haskell这样的函数式编程语言中,您使用whereor let子句,因此也使用变量:
func1 originalList = func2 (doSomething t) (doSomethingDifferent t)
where t = tail originalListRun Code Online (Sandbox Code Playgroud)
所以在这里,你将构建一个表达,和论据doSomething,并doSomethingDifferent会参考到同一个表达式树.现在,因为哈斯克尔懒惰地工作 tail originalList将不会立即进行评估.
但是如果它(部分)被评估(例如在评估func2调用的第一个操作数时),则在通过另一种方式(例如第二个参数)计算表达式树时,不会重做该工作.现在,无论如何tail都没有太多工作.但如果它是一个更复杂的功能,它会带来更多回报.
请注意 - 就像@amalloy所说 - 如果是tail函数,则不必使用where子句:简单模式匹配就足够了:
func1 (_:t) = func2 (doSomething t) (doSomethingDifferent t)Run Code Online (Sandbox Code Playgroud)
请注意,这两者并不完全等效:因为现在存在一个约束,即只有列表包含至少一个元素时才会触发该行.有可能func2只是忽略两个参数,这样就不需要获得尾部(尽管这里不太可能).