Ruby 从实践谈 Ruby 语法上的几个设计不一致带来的问题。

lilijreey · 2020年11月08日 · 最后由 dayudodo 回复于 2020年12月23日 · 1119 次阅读

首先这个不是黑 ruby,每个语言都有优缺点,都有历史包袱。这个只是从个人实践观点谈 ruby 的一些语法设计带来的问题。

  1. 以 end 为结尾的语法,相比花括号语法冗余。但是对花括号语法支持不全面,带来的风格上的不一致问题。
 比如 . block 支持 do ... end {} 两种语法 但是模块函数等定义不支持花括号
导致在编程时一部分注意力需要思考到底是使用哪种方式

2 if 的单行形式与多行相差很大,导致编程思维不一致

如果你要写 if + 单表达式的逻辑。有两种选择

  1. if testExp exp end

2 exp if testExp

可以发现两种 if 对应的编程思考逻辑是完全不同的 单行的语法貌似看上去可读性很高,其实隐藏着一个大问题。因为代码应该反映·逻辑的顺序· 而是一味地最求像自然语言。这是一种舍本逐末的行为。 你会发现写单行 if 的时候 你需要先思考 if 成立后做什么,而不是 if 什么。也就是说你需要把 if 的 testExp 暂时记录到脑子里,然后思考成立后的逻辑, 写完后再把暂存在脑子里的 testExp 拿出来。这样其实加大了编程的心智负担。而且这种先 exp 在 if testExp 的语法和其他 if 格式不一致。也影响了 代码阅读的流畅性。

几种单行if的比较
if testExp then exp end # 支持但是冗余
if testExp {exp} # 不支持
exp if testExp # 支持但是思考和书写方式又和其他if不一样
testExp and expt ; 支持但是没有if前导 影响阅读性

个人的一些感受:

  1. 不要意味的最求“可读性”,而丢到了逻辑正确性 因为可读性是一个相对概念,通常来说数学公式的可读性要比自然语言差。 比如但是对于专业人员看了公式的可读性很好,因为公式更短,更精确。而自然语言有更长还可能有二义性。
  2. 对于语言的语法来说,尽量跟随主流 C like 风格,是一个明智的选择。语法尽量简单。
  1. do ... end 默认用于多行, {} 是单行,没有思考过程
  2. 相信你的大脑,它会习惯的。德语里面,二位数,先说个位,再说十位。法语里面二位数表达要用加法,你搜索一下。大家用得都挺开心的。
  3. 个人感觉 C like 反而不好,一眼看到代码还不知道是什么语言,其实更头痛。我现在用 C++, Delphi, Ruby, Python 还有 VBS,如果都是 C like 就有点无聊了,还容易混乱。

逻辑也分简单和复杂的 简单的就把 if 写后面 复杂的就先 if 然后再写一堆
象 block 和 module/class 也是不同层次的 module/class是完整的代码组织单元 而 block 更象临时的寄生代码,在其他语言里,block 算是 callback 所以 ruby 这样不同层次用不同的代码表现形式,层次分明,更有条理,反而 python/java 事无巨细,强求一致的方式更象是给机器人用的

完全同意你的观点。天天嚷嚷着可读性,程序员幸福最大化。但做一件事提供了 N 种方法,写个代码老要思考用哪种方法,幸福感都没了。为什么比不过 PHP,Python,Go,大多数 Ruby 程序员心里一点二叉树都没,不从自身找原因,怪罪历史选择。

if 后缀反思维模式,所以主流编程语言都没有,哪里来那么多自豪感。

研究表明,end 比花括号带来更多的视觉障碍。如果当初设计时整体上都使用花括号很大可能就不会产生后缀 if。

离 c-like 近一点,在编程语言排位也能高一些。

想要这些,出门左转 python

if 后缀反思维模式

后置条件在英文中是常见的句式,只是在中文中可能少见

Peter 回复

do ... end 默认用于多行, {} 是单行,这个只是人为规定的。而且你要想想到底是单行还是多行。 还有个问题,为啥{} 用于单行,为{} 不能用于多行。你会发下其实都可以用。上面的规定背后没有任何明显正确的理由

写法太多,要处理的情况自然多,性能也就低。。

adamshen 回复

这个不能再贴切。

我说的 “默认” 就是约定的意思,在一般情况下都可以。就你在 C 里面,i=i+1; 可以用 i++;, ++i; 代替,但后两者在行内又有不同。这个 C 里面的不同在此处对应的就是:Ruby 中大括号的优先级是高于 do ... end 的,这就是大括号存在的 正确的理由

如果你想知道例子可以 google ruby do end vs curly braces

pynix 回复

此处不是 写法太多,是优先级的问题而已。

就算写法太多也不是性能低的直接原因。你有一百万种写法,如果是编译型语言没有任何关系,就算是 Ruby,如果条件允许,用上 --jit 参数也可以消除写法太多的影响。

Rei 回复

看完上面论调后,发现这个果断 star 一下,好货。

同意 1 楼的。

第一,花括号和 do end 这个从没有思考过程,就是单行/多行 第二,if 这个,写 if 的时候我思考方式是这样:要么是情况比较简单,我就会想 if a 则 b,这样就看这个 a 是不是足够简单,如果是就写单行,不是就考虑多行。否则我就是 if esle 先铺好,再填内容。无论哪一种我不会纠结单行还是多行。

关于以上两点,还有一点可提的是,ruby 这些功能都是为了可读性而设立的,不是为了一次打字不纠结设立的。写代码的时候为了可读性而改已写好的部分是很经常的事情。退一步讲就算我写了单行 block,我发现此处多行可读性更强,那我就回头改为多行。这就跟回过头去对齐等号,加注释等等行为是完全一样的。

我不认为“有更多选择”就带来“纠结”。抛开语法层面,本身代码逻辑,一种逻辑也有很多种可能的形式。那这一点我们为什么不纠结呢?

然后就是可读性问题了。如果你习惯 C,那么 C 和 C++ 的很多发展本身也都是在提高可读性。举个简单的例子,上学的时候我和小伙伴写 C,包括老师,我们都是写 while(1) 来做死循环,大家都看得懂,但是按现在眼光都会用 true 代替 1。

关于最后一点 c like 的问题,这世界上编程语言可以说五花八门海了去了,见得多了,每种风格都有它的好处。这一点个人认为不仅不是障碍,而且是必经之路。

不知道为什么,我后置的 if 还挺符合直觉的?

我一般用在 return xxx if xxx 中

感觉这种用法会减少很多嵌套

最后剩下的逻辑就特别简单

几种写法各有利弊,Ruby 不做裁决,而是把自由裁量的权力交给你。

你的编辑器支持这些小功能就不会难受了:一键切换后缀 if / unless,一键切换 do ... end 和 {}

说到底,ruby 是为英文程序员们设计的,符合英文的习惯,尤其是 do something if conditon. rails 那就更是单复数让无数咱中文入门人士头大不已,编程语言界现状就是如此,英文的天下。

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