【问题标题】:Higher Order Functions or pass by reference?高阶函数还是通过引用传递?
【发布时间】:2016-09-26 18:15:08
【问题描述】:

我对何时应该使用高阶函数而不是使用函数引用感到困惑。

考虑以下:

引用外部函数:

(+++) :: Int -> Int -> Int
(+++) a b = a + b

myFunction :: [Int] -> [Int] -> [Int]
myFunction (x : xs) (y : ys) = result : myFunction xs ys
     where
       result = x +++ y 

将函数作为参数传递:

(+++) :: Int -> Int -> Int
(+++) a b = a + b

myFunction :: [Int] -> [Int] -> (Int -> Int -> Int) -> [Int] 
myFunction (x : xs) (y : ys) func = result : myFunction xs ys
    where
       result = func x y

不同方法的优缺点是什么?

注意,我知道 Prelude zipWith - 这纯粹是为了说明

【问题讨论】:

  • 如果您认为使用(+++) 以外的其他参数作为最后一个参数调用myFunction 会有一些用处,那么作为参数传递是正确的做法。否则就没有意义了。
  • 我不确定这些是否真的可以比较。这就像比较\x y -> x + y\x -> x + 7。第一个严格来说更笼统。第二个可能正是您在给定上下文中想要的。
  • 如果您想避免指定该函数的具体实现并在使用时保留该函数,则需要将函数作为参数传递。好像你的函数不需要任何外部依赖传递函数是没有意义的。
  • 我认为这主要是编码的美学/艺术方面——你的定义有多笼统?对我来说,有一个“感觉正确”的普遍水平——我会说尽可能笼统,然后再让事情变得更笼统变得难以忍受,因为要解决的问题变得难以忍受,其中可承受性也是一种感觉......跨度>

标签: haskell higher-order-functions


【解决方案1】:

我认为默认情况下,您应该对所有函数调用进行硬编码。在本例中,myFunction 应该只调用 +++

但是,我知道这条规则有三个例外

  1. 通过不对函数调用进行硬编码,您的代码会变得更加清晰。
  2. 您的代码多次使用具有不同参数的参数版本。
  3. 您有理由相信,未来的代码将多次使用带有不同参数的参数版本。

请注意,第 3 点中的“未来代码”可以指您自己的代码(您计划下周添加另一个模块,该模块使用具有不同参数的参数版本,因此您今天已经添加了参数版本)或其他人的代码(您将参数版本导出到库中,并且您猜测库的用户会希望使用不同的参数调用参数版本。

虽然第 1 点和第 2 点相当明确,但第 3 点需要对您未来的需求或其他人的需求进行大量猜测。因此,对于您今天的代码应该准备多少以满足未来的需求,存在不同的思想流派。我猜很多 Haskell 程序员最终会更多地关注参数方面的事情。

【讨论】:

    猜你喜欢
    • 2011-06-22
    • 2017-07-05
    • 1970-01-01
    • 2020-04-01
    • 2014-07-26
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多