我经常看到它认为不应该使用重度嵌套的函数调用,因为它们是不可读的。但是,使用临时变量会产生大量不必要的冗长,并迫使读者在心理上将每个临时变量链接到它所代表的内容。在查看Lisp代码通常格式化的方式时,我发现嵌套函数调用实际上可以实现非常可读,如果您将它们格式化以反映嵌套。例如:
// Totally unreadable:
auto linesIter = filter!"a.length > 0"(map!strip(File(filename).byLine())))
// Perfectly readable. The only difference is formatting.
auto linesIter = filter!"a.length > 0"(
map!strip(
File(filename).byLine()
)
);
// Readable, but unnecessarily verbose:
auto rawLines = File(filename).byLine();
auto stripped = map!strip(rawLines);
auto filtered = filter!"a.length > 0"(stripped);
在嵌套函数形式中编写类似第一个示例的东西是,恕我直言,相当于在更多程序风格的代码中执行以下操作:
for(i = 0; i < 10; i++) { for(j = 0; j < 10; j++) { if(x < 2) { z++; } else { y++; }}}
在这两种情况下,真正的问题是格式不佳,而不是过度嵌套。您如何评价格式良好的嵌套函数版本与临时变量版本的可读性/可理解性?您认为重函数调用嵌套是不好的样式,即使它的格式是为了最大可读性?如果是这样,为什么?
答案 0 :(得分:2)
你说“使用临时变量会产生许多不必要的冗长,并迫使读者在心理上将每个临时变量与它所代表的相关联” - 但IMO只是另一种说法,你已经把事情分解成了读者可以一次理解一个步骤 - 换句话说,你已经使它更具可读性。
我很高兴添加一个额外的变量来打破一个长线分成单独的步骤(你的例子3),但对我来说关键是你是否可以把这个东西彻底打破成真正的强>步骤。一个好的指标是你是否能找到一个好的变量名;如果你做不到,也许这不是一个真正的单独步骤,需要拆分。
你的例子2没有什么不妥,但是比这长得多,我肯定会把它分解出来。在调试时你会感谢自己......
答案 1 :(得分:2)
我认为以您使用格式化的方式打破大型嵌套函数调用没有任何问题。它是可读的,这是意图。
对于临时变量,我尽量避免使用它们。唯一的原因很简单,我完全无法给他们好名字。我尝试的时候他们是绝对必要的,并最终浪费了5-10分钟的时间来思考“什么是可怕的等等的好名字”?如果它是一个数组,几乎总是放弃并使用buffer
,如果是标量,则最后放弃temp
等。
也就是说,使用嵌套结构,函数代表动词,而不是动词动作的产物,这是你用临时变量得到的。使用临时变量,您确实有机会为该产品命名。但是,如果动词和直接对象本身(verb(directObject)
)更好地描述了这一点,那么这就是你应该采取的路线。
答案 2 :(得分:1)
恕我直言,应该仔细选择对象和名称,以便在执行功能样式编码时将 读取,如同在第一个示例中一样将所有内容都砰地一声。如果完全不可读,有人选择了坏名字。您的目标是,如果某些内容 off ,通常意味着存在错误。
在现实世界中,当你必须处理那些选择不当的名字时,创建具有适当名称的临时常量(甚至例程)来清理一些东西没有任何问题。它胜过评论,因为它编译并且更容易修改。
答案 3 :(得分:0)
我个人认为,如果没有性能惩罚,可读性就更重要了。虽然我对Lisp语法一无所知,但看起来您的示例会调用相同数量的调用?如果是这样的话,那就做可读的方式。但是如果你在一个循环中调用一个繁重的函数(比如打开一个文件并一次又一次地读取),你应该避免它。我希望这个答案很有用。
答案 4 :(得分:0)
我不喜欢使用过多的变量b / c它们通常是bug的来源。如果我可以表达一个单独的表达式,我更喜欢它。我可能会选择你的第二个例子。