• RubyConf 2015 视频 at 2015年11月23日

    #4 楼 @jasl 感觉是被 tenderlover 带坏了。

  • 实现为 operator 是不是意味着它又是一个 method 的语法糖?我们可以覆盖它?YAVM 虚拟机上有对应的原语级操作么?

    #2 楼 @juanito 赞同 NullObject。但是 NullObject 只是转移了 overhead,并没有消除它。当我们有大量的 NullObject 的时候,又如何方便地管理呢?是用 https://github.com/avdi/naught 这种 builder 么?

  • #7 楼 @googya Puppet 可以管理整个主机的生命周期,Docker 这方面应该是比较欠缺的。

  • #5 楼 @kewin 已离职。相关文档已经走过公司流程,允许对外发布。

  • 友情 UP。

  • #62 楼 @oneapm 不能将 T 恤换成书么?

  • 😂 想要书的……不信一件 T 恤还不值一本书的钱……

  • #2 楼 @rubyu2 个人持不同意见。我是支持左边的写法,论点如下:

    1. 我觉得拆成三个函数这样语义更细化,也更清晰了。这样调试起来会更方便,假设 sum(x : Int32) 错了,我们只调试这个方法即可,不影响其它方法。

    之前还在说 Ruby 怎么为 foo(*bar) 定类型呢(详见:https://ruby-china.org/topics/25428#reply4),结果 Crystal 说我们用多态吧,2333。(BTW,Crystal 能不能把模式匹配搞进去啊?)

    1. 以前是要自己做参数匹配,现在把这个工作交给编译器/解释器了,很好。(想想,虽然自己做参数匹配固然更加灵活,但每个函数都做,岂不是又 Repeat Yourself 了么?)

    其实我想听听 @luikore 的深入见解。

  • Ruby under a Microscope 是本好书,之前 Ruby Hacking Guide 中译版夭折,就一直期待这本书能够出来。出版后一定支持一本!

  • [链接] Consider static typing at 2015年05月05日

    这个问题值得好好讨论一番。下面都是一家之言,如有纰漏,欢迎交流指正!

    最初的起源可见 hooopo 兄十个月前发的帖子:https://bugs.ruby-lang.org/issues/9999。这个问题甚至可以从 Feature #9999 追溯到 Feature #5583。

    继 Soft Typing 以后,Jeremy Siek 等人于 2006 年出来的 Gradual Typing(科普文章可见Jeremy Siel - 什么是 GRADUAL TYPING)早就在动态语言阵营中挂起一阵混搭旋风。也有很多人蠢蠢欲动往 Ruby 以及 Rails 里面加类型系统,比如:

    • The Ruby Type Checker, Brianna M. Ren, et al.
    • Static Typing for Ruby on Rails, Jong-hoon (David) An, et al.
    • Dynamic Inference of Static Types for Ruby, Jong-hoon (David) An, et al.

    是否引入类型系统,怎么引入,以及要用类型系统,都得看动机。

    为了规避不必要的运行时类型检查,以提高程序的运行效率,那么引入静态类型检查,在语法分析阶段确定好运算符/方法的分派是非常有必要的,但 Ruby 骨子里的动态性让这个有些难做,或者说,只能让程序做部分的静态类型检查(基本上就是 Gradual Typing 的思想)。正如视频里面提到的那样,Go 语言的 Structural Subtyping 跟 Duck Typing 有异曲同工之妙,都是面向协议编程(或者说面向接口编程)。

    反之,如果引入类型系统不当,反而会带来很多麻烦。Ruby 里面没有多态,有时候实现多态要靠参数列表来实现,请考虑下面的方法定义:

    def foo(*bar)
      # blah blah
    end
    

    怎么给 bar 加 annotation?ArrayArray<T>?由于数组内容通常还可能是不同类的实例,合法的类型标注可能是 Array<Object>,这不等于啥都没说嘛!要不要用 Dependent Type、**hash&blk 又怎么处理、为了让类型系统能够元编程,是否也要让类型成为 First class citizen?这些都是问题。

    部分人讨厌类型系统,是因为他们觉得写类型注释很恼人,很啰嗦。类型注释绝不是啰嗦,它其实也是一种 Specification,表明了程序员的意图。一方面来说,类型注释描述的是做什么(What to do),而具体的代码才是怎么去做(How to do)。我们有 Curry-Howard 同构告诉我们程序即证明,那么类型注释就是这个 Goal,我们编写代码让类型系统接受,就是去满足我们的 Specification,两者应该是相辅相成的。程序员觉得类型系统麻烦,只是因为在面向一些复杂类型时无从下手而已(比如一个很经典的问题就是:简单类型的 Lambda 演算系统中,没法给 Y 组合子定类型)。

    类型系统还有一个更重要的方面:类型安全。虽然 Ruby 本身是动态类型的语言,但它是强类型语言,所以目前 Ruby 在类型安全这方面做得不错了。前段时间有个叫 Rubype 的 Gem,作者声称是受Gradual Type Checking for Ruby这篇文章启发,而后面那篇文章也明确 Ref 了之前提到的 The Ruby Type Checker 这篇 Paper。

    这个 Gem 是在用户自定义级方法的层次上完成类型检查,再讨论 Rubype 之前,请考虑下面的定义:

    class Vector
      attr_reader :x, :y
    
      def initialize(x, y)
        @x = x
        @y = y
      end
    
      # 这里将向量的数乘(Scale)和点乘(Punktprodukt)都定义成了一个多态的 *
      def *(v)
        case v
        when Numeric
          Vector.new(x * v, y * v)
        when Vector
          x * v.x + y * v.y
        else
          raise TypeError
        end
      end
    
      def to_s
        "Vector: <#@x, #@y>"
      end
    
    end
    

    由于 Ruby 是不会做参数类型检查的,所以我们要自己去检查参数类型,并根据类型来分派需要执行的操作。显然将一个向量与字符串相乘是没有意义的,因此对于其它类型来说,我们要抛出 TypeError。实际上很多 Ruby 程序都有这样的需求,就跟函数的定义域一样,一个方法可能只是针对某个或某几个特殊的域(Domains)来定义的,对于不在这个定义域的参数,我们必须抛出一个错误,但每次都这么做,很容易违背 DRY 的原则。想一想也是,本来函数定义域这个东西,是属于“声明范畴”的,却要放在命令范畴让程序员自己写代码来做检查,确实有点离谱,所以就有了 Rubype。

    可惜的是,Rubype 它只能算作是一种语法糖,只是像 attr_* 系列方法那样,通过声明式的方式,将函数的类型注释维护起来。与手动写代码不同,Rubype 不但检查参数类型,还检查返回值类型,这也使得它的 Runtime Overhead 非常严重。Rubype 没有从根本上解决问题,当然要想从根本上解决这个问题必须在解释器上开刀。不过 Rubype 的“Meaningful error”和“Executable documentation”还是比较有亮点的。

    扯了这么半天,观点还是比较零碎,总结一下:

    • 类型系统很重要,得加,不能乱加,Ruby 里面黑魔法太多了,外表貌似“优雅”,内部及其混乱(比如 Proc、lambda、Block);
    • 类型系统跟数学结合紧密,必然会给程序员带来门槛,想想子类型系统中的 Liskov 替换原则就折磨了多少人,所以不要为了高大上就追求牛逼的数学模型合数学系统,Ruby 还是要以务实为主;
    • 现有类型系统很多,选择最适合 Ruby 的类型系统很重要,至少在表达 Ruby 常用的业务逻辑时要很方便,Ruby 的宗旨是让程序员快乐,可现有类型系统无论是编译器还是程序员都开心不起来;
    • 类型系统是个大头,加进来无论是解释器还是 Ruby 脚本,复杂度必然增长,如何合理控制这种复杂度,如何在动态合静态间进行取舍,这个也值得深究;

    类型系统往深了扯还涉及到程序设计语言的形式语义、程序正确性等问题,最近看屈延文院士的《形式语义学》一书中有这么一个说法:

    那么是否说采用 Dijkstra 方法就能保证程序正确呢?假如是一个理想的程序设计者,从不会出现任何错误,那么该方法设计出的程序是可靠的。我想,这就如同一个数学定理的证明一样,会有人证错。大概 Dijkstra 本人,如领导许多程序员按照他的方法设计程序,当程序员设计完程序后,向他说程序已经没有错误,他大概也只能相信他们是对的,而不能保证他们是对的。

    突然感觉就编程这方面,我们还任重而道远啊…………

    最后,Tom 那句话非常在理,这玩意儿不是脑袋一热一个 Pull Request 就可以搞定的,可能还真得一个需要 PhD Thesis(搞不好还得好多个 😄 )。

  • 我记得 Ruby 的文档都是会给使用范例的,类型什么的文档都说得很清楚。

    我感觉 Rubype 并不是真正意义上的 Gradual Type Checking,它只能算是一个 framework,本质上也是一个动态类型检查,只不过它把本来应该由程序员编写的运行时类型检查,通过声明式(Declarative)的方式让解释器执行罢了。

    我认为引入类型系统,一方面是为了确保程序的正确性(强类型),另一方面是加速程序的运行(尽早确定操作符,而不是动态派发)。但从 Benchmark 的结果来看,如果不再解释器的层次上实现 Type Annotation 和 Type Checking,实际应用的前途不太大啊。

    私货:http://deathking.github.io/2015/04/10/what-is-gradual-typing/

  • 我如何读书 at 2015年03月12日

    #3 楼 @tuliang 看你怎么想。就 Ruby China 社区的会员来说,前三章足矣,而且难度不算太大,网上也有习题解答参考。

  • 感觉这种算法题还是不要用 Ruby 吧,确实那个效率堪忧。 Ruby 拿来做做 Project Euler 还是挺不错的。

    呃,跟楼主竟然是校友……

  • #24 楼 @coral 恩。寒假只有 49 天的样子,从学校回家也得耽搁几天,确实很短。

  • 招实习生么?1 月中旬到农历新年前的样子。

  • parallelsdesktop 双十一半价 at 2014年11月07日

    囧死……前几天刚买。

  • 自顶一下

  • 哎呀,说过我经历过最常见的吧!莫过于词法作用域了!

    给没有逻辑学基础或者其他相关知识的同学,老是以为外面那个foobar里面那个foo是同一个foo,我倒是觉得怎么看怎么都是两个不同的东西。

    foo = 1
    
    def bar
      foo = 2
    end
    
    bar #=> 2
    foo #=> 1
    
  • #6 楼 @jiwoorico 怪我大意,若是回帖时声明此乃 2.0 之 Feature,想必那是极好的。

  • Why not? We also have splat operator. http://stackoverflow.com/questions/22026694/ruby-keyword-arugments-can-you-treat-all-of-the-keyword-arguments-as-a-hash

    def forward_all(*arguments, **keyword_arguments, &block)
      SomeOtherObject.some_other_method *arguments,
                                        **keyword_arguments,
                                        &block
    end
    
  • gnuplot?用贝塞尔曲线去平滑吧,我记得 gnuplot 自带这个选项。不过用贝塞尔曲线去平滑的话,会在部分波动较大的点失真。

  • 是我的错觉么?还是真把 Rails Developer 当作 Full Stack 了?怎么最近看到的招聘都是恨不得招一个全部活都给揽完的人啊!

    虽然我没啥工作经验,也不知道贵司的具体分工,但是还真是想吐槽几句,看您这岗位职责,符合这些要求的人为啥不去创业呢?

  • #3 楼 @flowerwrong 看了你的代码,豁然开朗。确实有效,感激不尽!

  • #1 楼 @hardywu 我的意思是,抽取的话应该放在哪里?我 google 过,Ajax 请求的话,Rails 会自动抽取 token 放到 Request 里面。但是我这种方式我就不太清楚了。

    实际上我比较疑惑的是,document.body.appendChild(form);明显是把我创建的 form 放在了原网页中再提交的,按理说还是有 CSRF_TOKEN 的啊!

  • 编程语言性能问题 at 2014年08月26日

    TL;DR

    编译器/解释器与程序员之间的博弈,看把脏活给谁做。

    Detail

    简单说下 Ruby 吧。由于 Ruby 是动态语言,所以类型检查是放在运行时的,不像 C 等静态类型语言,在编译时就可以确定类型。

    不要给我说 Ruby 是鸭子类型,那是 Ruby 层面,回到 CRuby 的实现层面,解释器需要对数据进行区分。CRuby 中的对象就是一个VALUE,根据 VALUE 是否为为特殊值QtrueQfalse等、VALUE是否为奇数判断是否为FIXNUM,然后再解释为RXXX的结构体。对于 C 来说,编译时做完类型检查就一劳永逸了,而 Ruby 却不得不在每次求值时做一次检查(为了知道这个VALUE是什么)。[之前貌似看到了说 Ruby 要引入静态类型?发帖前搜了下社区,好像是 Feature #9999,参见 Further Reading No.3]

    再比如,C 语言里面的字符串是非常 Dirty 的,比较轻量的就是栈上的字符数组(临时变量),再大不了就是堆上的存储空间(malloc等分配),为了存储一个大小为 X 字节的字符串,至多需要 X+1 字节的空间(算上\0),编译器不带检查溢出,因为它认为那是“程序员的事儿”,所以编译器就非常省事儿了。Ruby 就不一样了。Ruby 的字符串在建立时就需要经过一些检查,而且为了高效利用内存,Ruby 按照自己的方法设计了数据结构(比如下面)。很明显,Ruby 中一个大小为 X 字节的字符串,需要远多于 X 字节的空间,不要忘了还有一个指向这个RString结构体的VALUE,占用了一个机器字!

    struct RString {
          struct RBasic basic;
          long len;
          char *ptr;
          union {
              long capa;
              VALUE shared;
          } aux;
    };
    

    总而言之,你爽了,编译器/解释器就苦逼了。Dennis 把脏活推给程序员,Matz 让 Ruby 任劳任怨,各有各的道理。

    B.T.W. 如果想深入了解 Ruby 语言背后的细节,《Ruby Hacking Guide》是一份非常棒的参考资料。或者学习《The Structure and Interpretation of Computer Program》的第四章和第五章,了解一下如何做一个求值器,你应该能对这个问题有深入体会的。

    Reference

    1. 第二章:对象

    Further Reading

    1. Ruby China | 好像 Ruby 的性能问题始终是个大问题啊! » 社区,尤其注意 101 楼@luikore 吕大师的回答,我的观点和他是一致的。
    2. 弱类型、强类型、动态类型、静态类型语言的区别是什么? - 知乎
    3. https://bugs.ruby-lang.org/issues/9999
  • 不知大概几时结束。家在成都的郊区县,太晚了还不方便回去。

  • mruby 源码浏览 at 2014年06月16日

    #6 楼 @pynix 既然都做了这么多工作了,可以继续分析下去,做做 Diagram,理一下整个逻辑(解释流程)可能会好一点。我目前看过最漂亮的 C 语言实现的解释器应该是 Lua,云风大神也写过 Lua 的源码分析。

    还有,RHG(Ruby Hacking Guide)是一本很好的书,分析地也比较透彻。作者不是简单地向读者介绍如何去分析源码,而是在理解源码的接触上,又自己整理了一下。照这个势头,你完全可以写成 mruby hacking guide。

    mruby 的词法、语法分析可以略过,记忆中 Ruby 是拿 yacc 整的,其实也挺麻烦的。我觉得详细分析一下 Ruby 中的数据类型在 C 语言层面上是如何表示的。之前在 RHG 上看到 RString 和 RArray 里面有个 aux 域,感觉有点精妙。

    读源码是件乐事,可以从中学到很多东西,之前为了在实现一个 Scheme 解释器的时候,我就参考了 Lua 和 Ruby 的实现代码(Python 方面则是参考一个师兄之前做的讲座有介绍 CPython 的实现),偷学了不少技巧,就比如 Ruby 中对 VALUE 的处理。受用无穷。

    楼主加油!

  • mruby 源码浏览 at 2014年06月16日

    大有发展成 mruby hacking guide 之势。^_^

  • 说白了就是 Lambda 演算和 Church 编码。

  • @chenge 我拿 Scheme 写的,但基本上还是命令式的数据结构与算法的写法https://github.com/DeathKing/Hit-DataStructure-On-Scheme

    我觉得完全没必要用 Ruby 写,而且如果没有对数据结构与算法本身还有 Ruby 本身有深厚了解,写出来的代码也不够 Rubyist。另外,用 Ruby 和用 C 没有太大的 本质上的不同,包括我上面用 Scheme 写的代码也是(打着“函数式”语言的旗号,但很多地方还是用 set! 来改变状态)。完成了这些代码后,我觉得特别是用 Scheme 来写命令式的数据结构有时候麻烦地要死。

    有本 Pure Functional Data Structure,门槛有点高,不太适合(低年级)本科生。