Ruby等价于javascript自动执行函数

Ruby等价于javascript自动执行函数,javascript,ruby,Javascript,Ruby,我经常在javascript中这样做 some_var || some_var = function(){ return "blah"}(); 我想知道ruby中的等价物是什么,所以我可以这样做 some_var ||= # sequence of operations 编辑 Proc.new.call引起了我的注意,但我也在某人的代码中发现了这一点: a ||= begin # do some stuff # return some stuff end 这在功能上是否等同于使用P

我经常在javascript中这样做

some_var || some_var = function(){ return "blah"}();
我想知道ruby中的等价物是什么,所以我可以这样做

some_var ||= # sequence of operations
编辑

Proc.new.call
引起了我的注意,但我也在某人的代码中发现了这一点:

a ||= begin
  # do some stuff
  # return some stuff
end
这在功能上是否等同于使用
Proc.new.call

edit2 人们似乎对我想要达到的目标感到困惑。在javascript中想象一下:

function someExpensiveFunction(){
  # do some really expensive stuff
  return "some expensive calculations"
}

a || a = someExpensiveFunction();
显然,设置
a
一次。。。调用昂贵的函数一次。。。在这种情况下,我不关心作用域,我只需要返回值是一个经过计算的事件序列,而不是单个值


我很确定我上面的例子
a | |=begin。。。结束相当于

一开始我不确定你在问什么。逻辑
| |
确实会影响预期的操作。在Ruby中,等价物是:

s = Proc.new { 5 + 5 }.call
somevar = "blah" unless somevar;
如果somevar为nil值或false值,则将其更改为“blah”。如果somevar不是nil或true,则不执行该行。相反的行动是:

somevar = "blah" if somevar;
如果somevar为true或非nil,则将赋值为“blah”

Ruby具有类似于自执行函数的语言特性,许多javascript库都受到这些特性的启发

有关更多信息,请查看此页面:

关于“块和迭代器”的部分在这里很有意思。还有“事务块”和“块可以是闭包”


从本质上讲,Ruby块和Ruby lambda是最接近Javascript自动执行功能的东西。

您可以使用lambda块来实现它

some_var ||= lambda { "something" }.call

在JS中,自执行函数通常用于避免污染作用域,因此您可以在内部使用局部变量,但不要公开它们。不幸的是,如果在Ruby 1.9之前的版本中使用块,情况并非如此,块没有自己的作用域

# Ruby 1.8.7
x = "some initial value"
some_var ||= Proc.new { x = 10; x + 2 }.call #=> 12
x #=> 10
因此,如果是这样的话,可能有一个更好的解决方案来解决你的问题。Ruby不是Javascript

对不起,我忘记了作用域和变量赋值中的变量定义。根据您的评论更新了代码段以反映这一点:


不关心范围界定。。。只需要使用包含多行代码的| |=设置变量的干净语法

我不知道我是否理解你为什么觉得你没有使用| |和lambda。例如,您可以使用

if(some_var.nil?)
   # do some stuff
   some_var = result_of_doing_some_stuf
end
或者,正如您在示例中所说:

a ||= begin
  # do some stuff
  # return some stuff
end
我不清楚你为什么一定要使用proc或lambda

但如果您决心使用| |=和lambdas,您可以:

calculate = lambda { 1 + 1 }
some_var ||= calculate.call
你可以做:

def run
  @a ||= begin
    x = 1 + 1
    puts "Calculated x"
    x
  end
end
puts "run = #{run}" # => Calculated x, run = 2
puts "run = #{run}" # => run = 2
如果要传递变量,请使用lambda

def run
  @a ||= lambda do |i|
    x = i + i
    puts "Calculated x"
    x
  end.call(1)
end
puts "run = #{run}" # => Calculated x, run = 2
puts "run = #{run}" # => run = 2
但是如果你要立即调用lambda,那么使用一个方法就不那么神奇,也更具可读性

def calc(i)
  x = i + i
  puts "Calculated x"
  x
end

def run
  @a ||= calc(1)
end
puts "run = #{run}" # => Calculated x, run = 2
puts "run = #{run}" # => run = 2

块(开始…结束)proc和lambda之间的区别在于句柄返回的方式。块中不允许返回。在Proc中返回从定义它的位置返回,在Lambda中返回,执行预期的操作

所以

返回5(而不是15)

返回15(如预期)

不编译


如果在块中未使用return,则可以使用begin。。。do(顺便说一句,我喜欢)。

我了解| | |做什么,我想| | |做一些| | | | | | | | | | | |做一些|现在看到你的。您已经接受了答案,所以我不会尝试编辑此答案。我刚刚遇到:
a | | |=begin#一些代码结尾
您见过吗?它是等效的吗?一个糟糕的格式没有正确出现,我将编辑我的postRuby 1.8.6,在上面的块作用域示例中给出未定义的x。我所做的或读到的关于ruby的所有事情都表明它必须始终支持块作用域。请参阅我的更新答案,关于块范围,您是对的。我想知道OP试图用这种编程风格做什么。我仍然很困惑——上面的snipper中没有变量阴影。事实上,您正在演示相反的情况。例如,在JS中,您可以通过在内部/匿名函数中使用var声明一个名称相同但作用域不同的变量。如果不使用var标记它,它将通过闭包假定外部作用域的标识。在Ruby中,您永远不会像在JS中那样“声明”变量。内部块捕获闭包中的外部变量。如果它是阴影,结果将是“一些初始值”,但它不是-结果是10,表明没有阴影,只是一个闭包。好吧,我的观点是,在Ruby中,你不能在块作用域中声明局部变量。与…比较不管怎样,我刚刚看到了OP想要做什么,这样我们就可以把讨论转移到聊天室了?你到底想做什么?Ruby具有块级范围,这与JavaScript具有的词法范围不同。通常你会在JS中看到匿名函数来避免作用域问题。。。我只是想要一个干净的语法来使用| |=设置一个变量,它涉及多行代码。我实际上是在试图避免Proc/lambda,它只是作为一个例子给出的,这就是我引用它的原因。
def calc(i)
  x = i + i
  puts "Calculated x"
  x
end

def run
  @a ||= calc(1)
end
puts "run = #{run}" # => Calculated x, run = 2
puts "run = #{run}" # => run = 2
def f()
  a = Proc.new do
          return 5 # exit from f
      end.call
  # never called
  a+10
end 
def g()
  a = lambda do
        return 5
  end.call
  a+10
end
def f()
  a = begin
        return 5
  end 
  a+10
end