这两行代码是否相同? JS vs Ruby

时间:2016-07-11 12:51:24

标签: javascript ruby-on-rails ruby

在红宝石中:

->  { 10.times {|i| puts i} }.call

使用Javascript:

(function (){
    for (i = 0; i<10; i++){
        console.log(i);
    }
})()

我来自JS背景,在学习lambdas和Procs时,我的兴趣达到了顶峰,它说这些函数没有被称为的名字。这让我想起了javascript中的匿名函数或IIFE。

这两个例子是否相同?如果没有什么区别?

1 个答案:

答案 0 :(得分:0)

这两条线在几乎每个方面都有很大不同。

最接近此Ruby片段的ECMAScript:

-> { 10.times {|i| puts i} }.call

会是这样的:

(() => { 10.times(i => puts(i)) }).call()

不幸的是,数字在ECMAScript中没有方法,所以我们不得不求助于这样的事情:

(() => { times(10, i => puts(i)) }).call()

显然,为了实现这一点,我们需要添加一些Ruby库支持代码:

(() => { times(10, i => puts(i)) }).call()

function times(i, f) { if (i-- === 0) return; else { times(i, f); f(i) }}
function puts(s) { console.log(s) }

这仍然与原始的Ruby语义不太相似,但比你的提议更接近:

  • 您的提案将i泄漏到全局范围内,Ruby代码甚至根本不泄漏i,它位于最里面的块的本地。
  • Ruby中没有函数调用操作符,而是使用方法Proc#call,ECMAScript也有(Function.prototype.call)。
  • 您使用for循环,而Ruby代码使用Integer上的方法进行迭代。
  • Kernel#puts将隐式写入您定义为默认输出流的任何内容,而您建议的ECMAScript解决方案将明确地始终写入控制台。
  • self在Ruby中被词法绑定,但this动态绑定到ECMAScript中的函数对象本身,除非您使用箭头函数文字,它以lexixally方式绑定this

另一方面,最接近Ruby的相当于:

(function (){
    for (i = 0; i<10; i++){
        console.log(i);
    }
})()

会是这样的:

-> { $i = 0; while $i < 10 do $stdout.puts($i); $i += 1 end }.()

同样,这不是100%等价的:

  • Ruby没有for循环(只有for … in迭代器),所以最接近的是while循环。
  • Ruby没有调用操作符,.()只是call方法的语法糖。
  • 嵌套函数表达式中的
  • this是动态绑定的,Ruby中的self是词法。