Ruby 我喜欢酱紫的 Hash

ery · 2015年03月11日 · 最后由 lhy20062008 回复于 2015年03月18日 · 3397 次阅读
options = {}
options[:url] = "好看"
options[:host] = "我喜欢"
options[:customer] = {}
options[:customer][:name] = "爱死了"
options[:customer][:number] = "越看越喜欢"
options[:customer][:bills] = []
options[:customer][:bills] << {number: "白", memo: "漂亮"}
options[:customer][:bills] << {number: "富", memo: "漂亮"}
options[:customer][:bills] << {number: "美", memo: "漂亮"}
options[:comments] = []
options[:comments] << "有人说酱紫冗余"
options[:comments] << "的确有点,不过我依然喜欢酱紫"

我讨厌酱紫的 Hash

options = {
  url: "注意!结尾必须写逗号",
  host: "如果不写逗号,那么会报错",
  customer: {
    name: "逗号很小, 不明显, 不小心删掉了,都很难发现",
    number: "结尾还有很多括号, 好崩溃呀",
    bills: [
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"},
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"},
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"}, #这个逗号不会报错 神奇吧
    ] # 最后一个元素可以不写逗号
  }, # 最后一个元素可以写逗号
}
options = {
  url: "注意!结尾必须写逗号"
  ,host: "如果不写逗号,那么会报错"
  ,customer: {
    name: "逗号很小, 不明显, 不小心删掉了,都很难发现"
    ,number: "结尾还有很多括号, 好崩溃呀"
    ,bills: [
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"}
      ,{number: "苦逼", memo: "苦逼苦逼苦逼苦逼"}
      ,{number: "苦逼", memo: "苦逼苦逼苦逼苦逼"}
    ]
  }
}

楼主喜欢的那种,optionscustomerbills 写了那么多次,不觉得冗余吗?

你讨厌的,正是我喜欢的。

逗号确实烦人啊。。。我觉得楼主的写法 写起来累,看起来舒服

神器赐予我力量吧! 之谁与争锋

倚天剑 ctrl+c ctrl+v 屠龙刀 Sublime 多光标 http://www.sublimetext.com/

#5 楼 @ery 你的工具再牛逼,我也觉得你的写法是 anti-pattern

如果你不需要团队,代码永远只是你自己维护,你爱怎么写怎么写。如果不是,请按惯例写。另外我也不认为你的写法好,第一,增加亢余定义,第二,对顺序有依赖,第三,本来是一个赋值被你改成了运算。

#7 楼 @billy 如果 惯例 是错的怎么办?

#6 楼 @libuchao 为什么是“anti-pattern” ?请详细说明,非常感谢!

#9 楼 @ery 你的写法最多是在【外形】上整齐了点罢了,可能非计算机专业的人看起来舒服点,实际上可读性很差。

还有一个原因我在 #3 楼 也说过了, 冗余

可读性一目了然,又省的写代码出错,果断赞磊哥

options = {}
options[:url] = "好看"
options[:host] = "我喜欢"
options[:customer] = {}
options[:customer][:name] = "爱死了"
options[:customer][:number] = "越看越喜欢"
options[:customer][:bills] = []
options[:customer][:bills] << {number: "白", memo: "漂亮"}
options[:customer][:bil1s] << {number: "富", memo: "漂亮"}
options[:customer][:bills] << {number: "美", memo: "漂亮"}

大家一起来找错 😄

#11 楼 @luotuo 你要不说认识我,也许更有说服力!你说哪?

我的好兄弟,心里有苦我对你说!

#12 楼 @saiga

options = {
  url: "注意!结尾必须写逗号",
  host: "如果不写逗号,那么会报错",
  customer: {
    name: "逗号很小, 不明显, 不小心删掉了,都很难发现",
    number: "结尾还有很多括号, 好崩溃呀",
    bills: [
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"},
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"},
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"}, #这个逗号不会报错 神奇吧
    ] # 最后一个元素可以不写逗号
  }   # 最后一个元素可以写逗号
}

大家一起来找错 😄

慕容绝技 之 斗转星移

还有一种写法

bills = []
bills << {number: "白", memo: "漂亮"}
bills << {number: "富", memo: "漂亮"}
bills << {number: "美", memo: "漂亮"}

customer = {}
customer[:name] = "爱死了"
customer[:number] = "越看越喜欢"
customer[:bills] = bills

options = {}
options[:url] = "好看"
options[:host] = "我喜欢"
options[:customer] = customer

都不用语法检查的吗?逗号什么的根本不是个事儿啊

注意:英文的逗号后面不加空格,不会那么好看,比如本回复。

喜好正好相反。第一种:

  1. 可读性不好,看不清楚嵌套结构。
  2. 写起来累,修改一个 key 还要批量修改。

其实 Hash 或者 Array 遵循一条规则 始终打逗号 即可。最坑爹的是 JavaScript 这种最后一个元素不能打逗号的,配合 ExtJS 这种拿 POJO 当配置的框架就是要人命。

#16 楼 @nightire 请问你说的是 Sublime RubyCheckOnSave https://packagecontrol.io/packages/RubyCheckOnSave

我以前没听说过,也没用过,干菜试了一下,果然不同反响。

#1 楼 @Rei 干脆使用 YAML 好啦!

#19 楼 @ery 人生苦短,我不用 py。你可以试试,py 强制最后那个逗号不能写。

#21 楼 @flowerwrong

$ python Python 2.7.8 (default, Oct 19 2014, 16:02:00) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.54)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> [1,2,3] [1, 2, 3] >>> [1,2,3,] [1, 2, 3] >>> {'a': 1, 'b': 2,} {'a': 1, 'b': 2}

#21 楼 @flowerwrong 我觉得 Ruby 挺好的,我喜欢酱紫的 Hash

#19 楼 @ery 我不用 ST,我是 Vim 党,我用 Syntastic。重点是任何靠谱的编辑器必然都会有语法检查的功能或插件,我们写代码要遵循代码规范,但是规范本身并不应该靠人工去检查,也不值得人工去打各种 patch。所以为什么不用语法检查呢?

#24 楼 @nightire 因为我是测试驱动

#24 楼 @nightire 说到语法检查、自动补全什么的,我觉得 IDE 比 Vim 好多了,比如说 Rubymine。

#25 楼 @ery 测试驱动和语法检查不冲突,你可以把两者都合并到你的 automation workflow 里,配置好的话也可以通过 Growl 或 Notification 做通知。we are programmers, we can program everything

#26 楼 @cuterxy 呵呵,不做主观评价谁好谁坏,事实上我也经常用 Jetbrains 家的各种 IDE,我只能说大家都不错,但是不至于“好多了”,也许是因为你不太会配置 Vim 吧?Vim 可以做到和 Jetbrains 一样好,其他的语言我不熟,但至少 Ruby/Javascript 是如此。我举个例子吧,比如说 WebStorm 做语法检查是用什么呢?它允许你使用 JSHint JSLing ESLint 等等常用的语法检查器,IDE 所做的就是把反馈集成到 Editor 的窗口里。那么 Vim 也一样啊,比如说我用的 Syntastic,它本身只是一个语法检查的驱动器,它的功能就是第一:允许为任何一种语言指定一个或多个语法检查器;第二:允许你配置这些语法检查器如何工作,以及 Vim 如何进行反馈。

IDE 会把这些事情事先为你做好,也可以提供给你一定的选项做调整,这自然是极好的,然而你无法做出超出 IDE 能力以外的设置。可是 Vim 不同,它可以做出更多的可控性,对于大多数程序员来说是“没有 Vim 做不到,只有你想不到”。比如说我用 Vim 可以让语法检查的结果反馈通过 Growl 或 Notification 通知给出来——这不算什么,IDE 想做到也不难,但是如果把反馈换成调用操作系统的语音引擎输出呢?甚至可以转换多语言进行语音播报呢?当然 IDE 能做到,但是值不值得去做,给不给你去做,这些是掌握在 IDE 的厂商手中的;而 Vim 是允许你掌握在自己手中的。

我举的这个例子可不是脑洞大开,事实上去年末在日本举办了一个 Vim 爱好者的会议,这个语音反馈提示已经有人做出来了,YouTube 上有现场视频,该作者展示了用日本语反馈单元测试结果的 Demo,真的很牛。

所以说语法检查、自动补全之类的事情对 Vim 来说也不算个事,IDE 会专门针对这些做优化并且让开发者开箱即用这当然是好事,Vim 想要配置到这个水准当然不容易,这是它的劣势。然而不能因此说 Vim 不如 xxx 之类的,这就有点无脑喷了。

#28 楼 @nightire 呵呵。我的确是无脑喷了。不过事实上我是对 vim 和 emacs 之类的繁琐配置厌倦了。不否认他们的可玩性很强,但是如果你不够深入了解的话,出了点问题就会很头疼,大大影响编程的心情。IDE 解决了绝大部分需求,其他一些炫酷的功能要玩的话,进入门槛太高了。有限的时间和精力还不如专注到真正要解决的业务问题上。说到底,是个人兴趣问题,好不好也是主观的。哈哈!

编辑器加个保存 hook 检查语法很简单的...

楼主的写法性能低,所以一般我不会采纳

#32 楼 @ShiningRay +1,恩,有道理,如果有一个关于性能测试的数据报告,就更有说服力了。

#33 楼 @ery

require 'benchmark'

def test1
  options = {}
options[:url] = "好看"
options[:host] = "我喜欢"
options[:customer] = {}
options[:customer][:name] = "爱死了"
options[:customer][:number] = "越看越喜欢"
options[:customer][:bills] = []
options[:customer][:bills] << {number: "白", memo: "漂亮"}
options[:customer][:bills] << {number: "富", memo: "漂亮"}
options[:customer][:bills] << {number: "美", memo: "漂亮"}
options[:comments] = []
options[:comments] << "有人说酱紫冗余"
options[:comments] << "的确有点,不过我依然喜欢酱紫"
end

def test2
  options = {
  url: "注意!结尾必须写逗号",
  host: "如果不写逗号,那么会报错",
  customer: {
    name: "逗号很小, 不明显, 不小心删掉了,都很难发现",
    number: "结尾还有很多括号, 好崩溃呀",
    bills: [
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"},
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"},
      {number: "苦逼", memo: "苦逼苦逼苦逼苦逼"}, #这个逗号不会报错 神奇吧
    ] # 最后一个元素可以不写逗号
  }, # 最后一个元素可以写逗号
}
end

n = 5000000
Benchmark.bm do |x|
  x.report { n.times { test1 } }
  x.report { n.times { test2 } }
end


shanshan:~/tmp$ ruby test.rb
       user     system      total        real
  17.210000   0.030000  17.240000 ( 17.240030)
  14.190000   0.010000  14.200000 ( 14.208981)

测试环境:Mac OS X 10.9.5, Ruby 2.1.5

#34 楼 @ShiningRay +1 感谢你的测试数据 不过有点小问题,我做了一些调整

require 'benchmark'

def test1
  options = {}
  options[:url] = "TEST"
  options[:host] = "TEST"
  options[:customer] = {}
  options[:customer][:name] = "TEST"
  options[:customer][:number] = "TEST"
  options[:customer][:bills] = []
  options[:customer][:bills] << {number: "TEST", memo: "TEST"}
  options[:customer][:bills] << {number: "TEST", memo: "TEST"}
  options[:customer][:bills] << {number: "TEST", memo: "TEST"}
end

def test2
  options = {
    url: "TEST",
    host: "TEST",
    customer: {
      name: "TEST",
      number: "TEST",
      bills: [
        {number: "TEST", memo: "TEST"},
        {number: "TEST", memo: "TEST"},
        {number: "TEST", memo: "TEST"},
    ]
  },
}
end

n = 500000
Benchmark.bm do |x|
  x.report { n.times { test1 } }
  x.report { n.times { test2 } }
end
sl410:Desktop (ruby-2.2.0)(master) ruby test.rb
     user     system      total        real
 4.510000   0.000000   4.510000 (  4.845243)
 3.920000   0.000000   3.920000 (  4.193255)

我觉的这种 json 写法很自然啊

#32 楼 @ShiningRay #35 楼 @ery

除非 Ruby 解释器有别的魔法,1 条指令生成的 Hash 效率肯定比生成一个空 Hash 再一个一个 allocate 内存效果高的多。

#38 楼 @est #34 楼 @ShiningRay

可曾听说过 过早优化是万恶之源 我承认我喜欢的写法,比,我讨厌的写法,更消耗 CPU 性能。 但是牺牲的那点性能,值得关注吗? 我觉得大部分的情况下,不需要关注。

#39 楼 @ery 别人让你节约开发时间,先 make it work,并不是给你一个乱写代码的万能借口。。。。。。你第二种 Hash 写法其实开发时间,至少打字的篇幅要少的多。。。。。。

编码规范就是为了防止这种个人偏好的……

@ery query = { :query => { :filtered => { :query => { :multi_match => { :fields => ["title", "content"], :query => "呵呵" } } } } } 那么这个呢?

after_format

query = {
  :query => {
    :filtered => {
      :query => {
        :multi_match => {
          :fields => ["title", "content"],
          :query => "呵呵"
        }
      }
    }
  }
}

第二种写法在 Sublime Text 编辑器中有很好的收缩展开效果,很有层次感和可读性,在此强烈推荐。

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