Рубиновый эквивалент javascript-функции - PullRequest
5 голосов
/ 24 ноября 2010

Я часто это делаю в javascript

some_var || some_var = function(){ return "blah"}();

Мне интересно, каким может быть эквивалент в ruby, поэтому я могу сделать

some_var ||= # sequence of operations

edit

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; ... end; эквивалентен ...

Ответы [ 6 ]

2 голосов
/ 24 ноября 2010

За ваш комментарий:

не волнует область видимости ... просто нужен чистый синтаксис для установки переменной с использованием || =, который включает несколько строк кода

Я не уверен, что понимаю, почему вы чувствуете, что используете || = и лямбду. Вы можете, например, использовать

if(some_var.nil?)
   # do some stuff
   some_var = result_of_doing_some_stuf
end

Или, как вы выразились в своем примере:

a ||= begin
  # do some stuff
  # return some stuff
end

Мне не понятно, почему вы должны использовать процедуру или лямбду.

Но если вы хотите использовать || = и лямбды, вы можете сделать:

calculate = lambda { 1 + 1 }
some_var ||= calculate.call
1 голос
/ 24 ноября 2010
s = Proc.new { 5 + 5 }.call
0 голосов
/ 24 ноября 2010

Разница между блоком (начало ... конец), процедурой и лямбда - способ возврата дескриптором.возврат не разрешен в блоке.Возврат в Proc, возврат из того места, где он был определен, и возврат в Lambda, что ожидается

Так что

def f()
  a = Proc.new do
          return 5 # exit from f
      end.call
  # never called
  a+10
end 

возвращает 5 (а не 15)

def g()
  a = lambda do
        return 5
  end.call
  a+10
end

возвращает 15 (как и ожидалось)

и

def f()
  a = begin
        return 5
  end 
  a+10
end

не компилируется.

Если вы не используете return в своем блоке, тогда вы можете использовать начало... делать (мне это кстати нравится).

0 голосов
/ 24 ноября 2010

Вы можете сделать:

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

Или использовать лямбду, если хотите передать переменную

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

Но это менее волшебно и более читабельно использовать метод, еслинемедленно позвоню в лямбду

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
0 голосов
/ 24 ноября 2010

Вы можете сделать это с лямбда-блоками

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

или

some_var ||= Proc.new { "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 .}

РЕДАКТИРОВАТЬ: Извините, я забыл об определении переменной в областях против присвоения переменной.Обновлен фрагмент для отражения этого

0 голосов
/ 24 ноября 2010

Сначала я не был уверен, о какой части вы спрашиваете. Логический || влияет на ваши ожидаемые операции. В Ruby эквивалент:

somevar = "blah" unless somevar;

Если somevar равен нулю или ложное значение меняется на «бла». Если somevar не nil или true, строка не выполняется. Противоположное действие будет:

somevar = "blah" if somevar;

Это назначило бы "бла", если somevar истинно или нет nil.

В Ruby есть языковые функции, схожие с функциями автозапуска, и многие библиотеки javascript были вдохновлены этими функциями.

Проверьте эту страницу для получения дополнительной информации:

http://www.ruby -doc.org / документы / ProgrammingRuby / html / tut_containers.html

Здесь будет интересен раздел «Блоки и итераторы». Также «Блоки для транзакций» и «Блоки могут быть замыканиями».

По сути, блок Ruby и рубиновая лямбда - самые близкие к самовыполняющейся функции Javascript.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...