Ruby to_proc взламывает с привязкой

Я пытаюсь создать немного взлома Ruby для создания чего-то как реверс взлома Symbol#to_proc. Принимая во внимание, что взлом Symbol#to_proc делает это возможным:

some_array.each(&:some_method)

совпадает с

some_array.each { |obj| obj.some_method }

Я хочу сделать это возможным:

some_array.each(&[:some_method])

совпал бы с

some_array.each { |obj| some_method(obj) }

Проблема состоит в том, что, если some_method не является методом ядра, что это действительно означало бы:

some_array.each { |obj| self.some_method(obj) }

Когда блок передается явно, он создается в рамках привязки, где эта строка записана, таким образом, сам правильно получает доступ к текущему объекту, и все хорошо работает. Однако, если блок создается в to_proc методе Массива, сам в рамках привязки Массива (и относится к самому массиву). Возможно, не возможно сделать то, что я пытаюсь сделать, но я любил бы некоторые идеи от сообщества.

Вот мой взлом до сих пор. Это работает, пока метод является методом ядра и доступен в Массиве:

class Array
  def to_proc
    lambda {|i| send(self.first, i)}
  end
end

С этим взломом работает эта строка, и помещает эти три символа:

[:foo, :bar, :bas].each(&[:puts])

Это уже полезно для меня, потому что часто я желаю для осмотра массива объектов ActiveRecord в консоли, и это сохраняет меня от ввода {|i |, помещает меня}. Но было бы еще более полезно смочь использовать его в объектах так, чтобы некоторый метод в объекте назвали с каждым объектом в массиве, переданном в качестве параметра.

Так какая-либо идея, как заставить обязательную проблему работать?

Не делайте обоих отвечаний, "Вы не хотите делать это, потому что оно сделает вещи выполненными медленнее" или "Вы не сохраняете столько ввода символов, но оно делает код менее читаемым" - я уже знаю эти вещи.:) Это - больше питания моего вида любопытства взлома. Просто удивление, если это возможно.

8
задан AstroCB 30 August 2014 в 21:10
поделиться

3 ответа

Вы ищете метод с именем метод :)

class Example
  def some(arg)
    p arg.size # just as a demo
  end
end

obj = Example.new
%w{the quick brown fox jumps over the lazy dog}.each(&obj.method(:some))

yield

3
5
5
3
5
4
3
4
3
10
ответ дан 5 December 2019 в 12:10
поделиться

Хотя у Адриана есть правильная идея с использованием метода , вы можете упростить это еще на один шаг:

# Works on any generic method
%w{the quick brown fox jumps over the lazy dog}.each(&method(:foo))

def foo(arg)
  p arg.size
end

# Works on user-defined methods, too
%w{the quick brown fox jumps over the lazy dog}.each(&method(:puts))

Вместо того, чтобы делать неловкую семантику с введением Array#to_proc, почему бы просто не написать свои собственные методы Enumerable, которые сделают вашу жизнь легче вместо этого? Возможно, что-то вроде этого:

module Enumerable
  def pass_each(method_name)
    each(&method(method_name.to_sym))
  end
end

%w{the quick brown fox jumps over the lazy dog}.pass_each(:puts)
3
ответ дан 5 December 2019 в 12:10
поделиться

Вот еще один способ сделать это без использования метода () :). Он использует блок для захвата привязки и затем вызывает соответствующий метод на self.

class Object
    def apply &block
        b = eval('self', block.binding)
        lambda { |param| b.send block.call, param }
    end
end


# use like this:
[1, 2, 3, 4].each &apply { :puts }

output: 1
        2
        3
        4
1
ответ дан 5 December 2019 в 12:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: