Это разумное использование для && = в Ruby? - PullRequest
7 голосов
/ 15 января 2010

В ТА вопрос 2068165 один ответ поднял идею использования что-то вроде этого:

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 будет приходить из формы (Rails / ActionView).

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

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

Ответы [ 2 ]

5 голосов
/ 15 января 2010

Так и должно быть. Если ничего другого, 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"

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

1 голос
/ 15 января 2010

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

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...