新手问题 这样的代码如何改的更符合 Ruby 哲学?

lukertty · 2018年05月31日 · 最后由 lukertty 回复于 2018年06月01日 · 1749 次阅读
a = fun1
a = fun2 if a.pred
a = fun3 if a.pred
# ...

不符合条件,就找下一个,这里的 fun 有若干个。现在每次增加一个 fun,就要整句话抄一遍,有没有简洁清晰的写法?

先谢过了!

实际的需求来自 https://github.com/Homebrew/brew/pull/4241

def width
  width = `/bin/stty size 2>/dev/null`.split[1]
  width = `/usr/bin/tput cols 2>/dev/null`.split[0] if width.to_i.zero?
  width = 80 if width.to_i.zero?
  width.to_i
end

不知道怎么改好一点。。。

如果没有奇怪的 pred,用&&就好了

nouse 回复

有奇怪的 pred, 比如是 a.to_i.zero? (a 可能是 nil 或者 "0") 话说回复的好快

挺简洁清晰的,不用改

luikore 回复

我也觉得蛮好的,主要需求来自 https://github.com/Homebrew/brew/pull/4241

Could always make it a while loop or something?

不知道他需要的可能是什么样的 while....

好像更长了……

WidthMethods = [
  ->{`/bin/stty size 2>/dev/null`.split[1]},
  ->{`/usr/bin/tput cols 2>/dev/null`.split[0]},
  ->{80}
]

def width
  WidthMethods.each do |lm|
    w = lm.call.to_i
    return w if w != 0
  end
end

这样还好啦其实,你看看像 Go 没有单行 if 那代码简直了!

lukertty 回复

不知道是不是你想要的结果

`xxx` 命令行执行的结果貌似没有 nil,顶多是空字符串''

没有测试环境,所以没法一一验证代码的准确性。

`/bin/stty size 2>/dev/null`.split.yield_self { |_, width|
  width || `/usr/bin/tput cols 2>/dev/null`.split[0] || 80
}.to_i

另:xx.yield_self 仅限 Ruby 2.5.0 以上

[
  ->{0},
  ->{puts 'call1'; `/bin/stty size 2>/dev/null`.split[1].to_i},
  ->{puts 'call2'; `/usr/bin/tput cols 2>/dev/null`.split[0].to_i},
  ->{puts 'call3'; 80}
].lazy.map(&:call).drop_while(&:zero?).first

(多余的内容是测试用的,请自行删除。)

现在这样其实可以了,改成 early return 也不一定省多少,就是少个最后的 to i

width = `/bin/stty size 2>/dev/null`.split[1].to_i

return width unless width == 0

width = `/usr/bin/tput cols 2>/dev/null`.split[0].to_i

return width unless width == 0

return 80

谢谢各位~最后还是决定不改了。。。

lukertty 关闭了讨论。 06月01日 10:03
需要 登录 后方可回复, 如果你还没有账号请 注册新账号