新手问题 Ruby 的调用方法设计的很不一致,是因为没设计好吗

lilijreey · 2018年09月08日 · 最后由 fenginsc 回复于 2020年02月21日 · 2334 次阅读

最近发现 Ruby 在调用方法(lamdb,proc 等等可调用的对象)的书写上很不一致。 比如对于方法来说,

def met
end
直接写met 就是调用,你不想调用都不行,
而对于lamdba 则不能直接使用()调用很不统一, 使用l=[],.call, .()
lm = lamdb{ ...} 
lm() #error
lm # not call
lm.call #ok
lm[] #ok
lm.() #ok 
这样无意对代码的一致性造成了很不好的印象。 
比如我写一个高阶函数, 那我就不能统一写成 fn(),
而是写成fn.call 感觉有点非主流。
lilijreey 关闭了讨论。 09月08日 11:08
lilijreey 重新开启了讨论。 09月08日 11:08

刚刚看了一些帖子,自问自答一波 在 ruby 中方法与其他 lamdab ,block, proc 很不同, 方法可以接收 block,但是其他的都不可以。 也就是说, 在函数式语言中所说的 function-first-class 在 ruby 中不成立。 所以写高阶函数时,可考虑用 lamdba 替代。

  1. 调用方法也不是括号, 而是 call . 例如 ```ruby tt = ->(fn, arg) {fn.call(fn.call(arg)} aa = -> arg {arg << '!'}

tt.call(aa, 'ook')

这样子就可以是函数first的了。 如果定义成方法则很不方便。

再说说设计的问题, ruby 的方法设计为自动调用,原因可以是收到 Lisp 的影响, 设计者不希望以()显示的限制 ruby 的书写方法。 因为很多时候强制使用()来表示调用语义会限制 DSL 的设计。 但是这样以来,也会产生很多问题, 这样的方式和大部分语言都不一致。 lisp 特殊的 S 表达式,则没有这种问题。 所以设计的一致性是很重要的。

设计都是权衡取舍。好处是你不会像 JS 或者 Python 那样因漏写一个括号而传了一个 function 给需要 function() 的地方。

方法调用,还有 lambda, proc 等,在 Ruby 里是不一样的东西。至于为什么这样设定,这是作者是这样想的。对我个人来说,没有什么好与不好。如果与 JS 等语言比,方法、函数、lamba 其实就是一个东西,确实是更一致,但是 JS 也有 JS 不一致的地方。

实际上,Ruby 因为有 block 的存在,很多时候并不像是 JS 一样,是函数传来传去的,它是传 block。以你的例子(我帮你格式化了,不知道是不是你本身的意图)

tt = ->(fn, arg) {
  fn.call(fn.call(arg))
}

aa = ->(arg) {
  arg << '!'
}

tt.call(aa, 'ok')

首先在 Ruby 里我们可能不太会去定义高阶函数,而会去使用一个私有方法。在我接受高阶函数的概念后,我也尝试在 JS, Scala 里用高阶函数来封装局部逻辑,但是事实证明是这带来了代码可维护性的降低。因为本身这种需要局部高阶函数的函数,逻辑就很复杂,这时候使用高阶函数,相对于另一个私有方法,本身就在增加复杂函数的长度。

如果我把你的 tt 当成是一个方法,而不是一个高阶函数,那可以这样写:

def tt(arg)
  yield(yield(arg)) # 这里我不清楚你的意图,一般应该不会这样做,我只是复制你的逻辑
end

tt('ok', &block) # block是这个调用tt的方法的一个block参数

是不是相对你的版本好看一些?

JS 里的

var hide = function() {
  // ...
}

本来在 Ruby 里,我们就会用一个方法来代替的,所以就基本不存在你说的连环a_lambda.call()的调用。

Xenofex 回复

不错我现在知道怎么写了.

不写括号,很多时候你不知道是属性还是方法,还有方法可以不写 return 的智障设计,括号和 return 的提示作用很重要

括号:有时候觉得不写,是很好的感觉,比如在 erb 中,和 html 有亲切感;

return:我每次都写,为了便于维护,不敢不写

不写括号是对的,程序员就是匹配括号白了头。

习惯了就好了。

直接使用方法名称是省略 () 的简写来着

不写括号,更接近人类语言

可以这样认为,一开始设计成可以省略括号,结果后来使用的人多了发现带来的问题更多。 还不如抄袭 Smalltalk 彻底一点,连逗号都没有,比如: https://www.gnu.org/software/smalltalk/manual/html_node/Files.html#Files

请问引用一个已有方法怎么写

需要 登录 后方可回复, 如果你还没有账号请 注册新账号