2010-01-15 2 views
7

В SO question 2068165 один ответ выдвинул идею использовать что-то вроде этого:Это разумное использование для && = в Ruby?

params[:task][:completed_at] &&= Time.parse(params[:task][:completed_at]) 

как сушилке способ сказать

params[:task][:completed_at] = Time.parse(params[:task][:completed_at]) if params[:task][:completed_at] 

где PARAMS Hash будет приходить из (Rails/ActionView) форме ,

Это своего рода следствие известной идиомы ||=, установив значение, если LHS не nil/false.

Использует &&= как это действительно признанный рубинский идиом, который я как-то пропустил, или я просто забыл более часто используемую идиому? Это is Получение довольно поздно ...

+0

Анализатор делает некоторые странные вещи: а = 1, если ** работ ** и Ь = 1, если никогда не удается ** ** –

+0

добавить оскорбление в случае травмы, если xxx; ххх = 1; end ** fail ** –

ответ

5

Это должно быть. Если ничего больше, params[:task] оценивается только один раз при использовании формы &&=.

Для уточнения:

params[:task][:completed_at] = params[:task][:completed_at] && ... 

вызовы [](:task) на params дважды, [](:completed_at) и []=(:completed_at) один раз на params[:task].

params[:task][:completed_at] &&= ... 

называет [](:task) на params один раз, и его значение припрятал для обоих [](:completed_at) и []=(:completed_at) вызовов.


Фактический пример, описывающий то, что я пытаюсь показать (на основании примера кода Марк-Андре, много спасибо):

class X 
    def get 
    puts "get" 
    @hash ||= {} 
    end 
end 

irb(main):008:0> x = X.new 
=> #<X:0x7f43c496b130> 
irb(main):009:0> x.get 
get 
=> {} 
irb(main):010:0> x.get[:foo] = 'foo' 
get 
=> "foo" 
irb(main):011:0> x.get[:foo] 
get 
=> "foo" 
irb(main):012:0> x.get[:foo] &&= 'bar' 
get 
=> "bar" 
irb(main):013:0> x.get[:foo] = x.get[:foo] && 'bar' 
get 
get 
=> "bar" 

Обратите внимание, что с помощью «расширенной» формы вызывает «получить» в печататься дважды, но использование компактной формы заставляет его печатать только один раз.

+0

Ваш ответ неверный. Обе формы эквивалентны, а params [: task] [: completed_at] оценивается дважды (при условии его правдивости) (см. Мой ответ). –

+0

Думаю, мне нужно уточнить, что именно я отвечаю. :-P –

+0

Я как-то жалею, что вы были правы, но нет, геттер [: task] также будет выполняться столько раз в форме && =, как форма «if». Я обновил свой ответ, чтобы показать это. –

1

Использование &&=, в случае LHS является ложным, оно считывается только один раз, но не устанавливается. Это должно сделать его более ясным ...

class Test 
    def initialize(value) 
    @v = value 
    end 
    def v=(value) 
    puts "set" 
    @v = value 
    end 
    def v 
    puts "get=>#{@v}" 
    @v 
    end 
end 
t = Test.new(true) 

t.v = t.v && true 
puts '----' 

t.v &&= true 
puts '----' 

t = Test.new(false) # lets make LHS false 
t.v = t.v && true 
puts '----' 

t = Test.new(false) # lets make LHS false 
t.v &&= true 

Результат:

get=>true 
set 
---- 
get=>true 
set 
---- 
get=>false 
set 
---- 
get=>false 
+0

Когда LHS является ложным, это нормально: мы не хотим его устанавливать, если его нет, но нам может понадобиться преобразовать/проверить/проанализировать его, если он присутствует, но не в той форме, которую мы действительно хотим, например. где мы получаем дату/время в виде строки и хотим передать ее модели в том виде, который она ожидает. –

Смежные вопросы