Руби отправить без символа - PullRequest
2 голосов
/ 23 июня 2010

Возможно ли отправить объекту ничего?

Позвольте мне уточнить.Например, у меня может быть что-то вроде этого:

val = some_stack.include?(some_val) ? some_val : nil

obj1.obj2.send(val).obj3.obj4

Вышеуказанный вызов не будет работать, потому что nil не является символом.Таким образом, решение:

if val.nil?
  obj1.obj2.obj3.obj4
else
  obj1.obj2.send(val).obj3.obj4
end

Однако я не слишком люблю это.Есть ли другой способ?

Ответы [ 3 ]

5 голосов
/ 23 июня 2010

Я не знаю ни одного метода, который возвращает self без каких-либо аргументов (но я мог бы что-то пропустить), но нет никаких причин, по которым вы не можете monkeypatch один в используемом классе:

irb(main)> class Object
irb(main)>   def ignore
irb(main)>     self
irb(main)>   end
irb(main)> end
=> nil
irb(main)> msg = nil
=> nil
irb(main)> 'hi'.send(msg || :ignore).upcase
=> "HI"
irb(main)> msg = :reverse
=> :reverse
irb(main)> 'hi'.send(msg || :ignore).upcase
=> "IH"
4 голосов
/ 23 июня 2010

нет встроенного способа.Вы можете сделать следующее:

module Kernel
  def __self__
    self
  end
end

obj1.obj2.send(val || :__self__).obj3.obj4

еще более загадочно:

[:obj1, :obj2, val, :obj3, :obj4].compact.inject(self, :send)
# (assuming that obj1 is a method call like obj2, ...)

, но я бы рекомендовал сделать это простым:

intermediate = obj1.obj2
intermediate = intermediate.some_val if some_stack.include?(some_val)
intermediate.obj3.obj4
2 голосов
/ 24 июня 2010

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

В Ruby отправка сообщения объекту означает, что этот объект должен каким-то образом ответить на запрошенное сообщение (которое в данном случае обозначается символом).Сообщение - это то, что мы обычно называем вызовом метода.В этом примере «send» - это сообщение, отправленное объекту, а объект, который получает сообщение «send», принимает переданные аргументы (символ для другого метода) и отправляет себе (объекту) сообщение, соответствующее методу дляпропущенный символ

Таким образом, отправка объекта nil почти равносильна тому, чтобы ничего не отправлять объекту, за исключением того, что вы уже фактически отправили объекту сообщение, только одно, которое не имеет никакого содержимого.Таким образом, объект неизбежно запутывается в отношении того, что он должен делать, поскольку ему было сказано ничего не делать.Разве вы не будете смущены, если кто-то потребует, чтобы вы ничего не делали? :)

Итак, обратимся к конкретному вопросу:

Перефразирую ваш вопрос (чтобы понять, понимаю ли я его),Я думаю, что вы спрашиваете: возможно ли объединить в цепочку серию вызовов, при которых один из вызовов в цепочке происходит, только если переменная (метод, вызываемый посредством отправки сообщения) не равна нулю?

Возможно, это лучше для решения общего назначения?

obj2 = obj1.obj2
obj2 = obj2.send( val ) if val
obj2.obj3.obj4

В противном случае, чтобы действительно ответить на ваш вопрос (который сейчас имеет смысл, но может сделать вещи более запутанными), вы можете поместить это в свой класс:

def send( method, *args )
    super if method
end

В качестве альтернативы вы можете сделать это:

class Object
    def send( method, *args )
        super if method
    end
end

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

Это решение будетвызвать предупреждение [sic]:

предупреждение: переопределение ` send 'может вызвать серьезную проблему

Вы можете отключить это предупреждение, перенаправив $ stderr, но это не потокобезопасно(говорит Мац из краткого поиска Google).

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