Scala风格:嵌套功能有多远?

Jam*_*abe 5 coding-style scala nested function

Scala的一个优点是它可以让您很好地控制范围.您可以嵌套这样的函数:

def fn1 = {
  def fn11 = {
    ...
  }
  def fn12 = {
    ...
    def fn121 = {
      ...
    }
  }
  ...
  def fn13 = {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是fn1可能开始看起来有点吓人.来自Java背景,我们建议保持足够小的功能,以便在IDE中的单个"页面"上查看.

你会怎么看待基于这个推理从fn1中取出fn12:"它现在只在fn1中使用,但它可能会在以后的其他地方有用......"

此外,您是否会优先考虑在何处放置嵌套函数 - 在调用它们的代码之前或之后?

Lui*_*hys 6

一般来说,我没有在实际代码中看到多少函数嵌套.它违背了保持方法简单和简洁的精神.这样的嵌套主要用于你将使用外部作用域中的一些参数(例如递归函数的内部循环)的闭包,因此它比在外部声明它并且必须显式地重新传递这些参数更清晰.

您必须将嵌套函数放在调用它们的代码之前,或者它是一个前向引用,并且不会编译.(在对象/类中,您可以将它们放在后面,但不放在方法中.)


Rex*_*err 5

有一些模式可以利用一层嵌套.

递归,用于隐藏实现细节(并且比分成两个单独的顶级方法更清晰):

def callsRecursive(p: Param): Result = {
  def recursive(p: Param, o: OtherParam, pr: PartialResult = default): Result = {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

范围安全不要重复自己:

def doesGraphics(p: Point) {
  def up(p: Point): Point = // ...
  def dn(p: Point): Point = // ...
  def lf(p: Point): Point = // ...
  def rt(p: Point): Point = // ...
  /* Lots of turtle-style drawing */
}
Run Code Online (Sandbox Code Playgroud)

还有更多深奥的技巧,比如为本地块隐藏隐式转换.

如果你需要这两个,我可以设想嵌套两次.更多的可能是矫枉过正,主要是因为你可能会让一种方法做得太多.你应该考虑如何用干净的接口细分问题,然后可以成为他们自己的方法,而不是在方法中定义的各种变量周围有一个混乱的大杂烩.大方法就像全局变量:一切都变得过于依赖于实现的细节而且很难跟踪.如果你已经准备好做适当的思考以使某些东西具有合适的界面,即使你只需要它一次,那么考虑把它带到顶层.如果你不这么认为,我倾向于把它留在里面以避免污染界面.

无论如何,不​​要害怕在任何需要的地方创建方法.例如,假设您发现自己深入某个方法中有两个集合,每个集合必须在逻辑中的特定点对它们执行相同的操作.如果您有一两种或三种方法,请不要担心!只需在需要的地方创建方法,然后调用它而不是重复自己.(请记住,如果您只需要在同一个地方处理多件事情,那么创建列表和映射是另一种选择.)