Книга: Программирование на языке Ruby

6.1.4. Преобразование строки в символ и обратно

6.1.4. Преобразование строки в символ и обратно

Строки и символы можно преобразовывать друг в друга с помощью методов to_str и to_sym:

a = "foobar"
b = :foobar
a == b.to_str # true
b == a.to_sym # true

Для метапрограммирования иногда бывает полезен такой метод:

class Symbol
 def +(other)
  (self.to_s + other.to_s).to_sym
 end
end

Он позволяет конкатенировать символы (или дописывать строку в конец символа). Ниже приведен пример использования; мы принимаем на входе символ и пытаемся определить, представляет ли он какой-нибудь метод доступа (то есть существует ли метод чтения или установки атрибута с таким именем):

class Object
 def accessor?(sym)
  return (self .respond_to?(sym) and self .respond_to?(sym+"="))
 end
end

Упомяну также о более изощренном способе применения символов. Иногда при выполнении операции map нужно указать сложный блок. Однако во многих случаях мы просто вызываем некоторый метод для каждого элемента массива или набора:

list = words.map {|x| x.capitalize }

He кажется ли вам, что для такой простой задачи слишком много знаков препинания? Давайте вместо этого определим метод to_proc в классе Symbol. Он будет приводить любой символ к типу объекта proc. Но какой именно объект proc следует вернуть? Очевидно, соответствующий самому символу в контексте объекта; иными словами, такой, который пошлет сам символ в виде сообщения объекту.

def to_proc
 proc {|obj, *args| obj.send(self, *args) }
end

Кстати, этот код заимствован из проекта Гэвина Синклера (Gavin Sinclair) «Расширения Ruby». Имея такой метод, мы можем следующим образом переписать первоначальный код:

list = words.map(&:capitalize)

Стоит потратить немного времени и разобраться, как это работает. Метод map обычно принимает только блок (никаких других параметров). Наличие знака & (амперсанд) позволяет передать объект proc вместо явно указанного блока. Поскольку мы применяем амперсанд к объекту, не являющемуся proc, то интерпретатор пытается вызвать метод to_proc этого объекта. Получающийся в результате объект proc подставляется вместо явного блока, чтобы метод map вызывал его для каждого элемента массива. А зачем передавать self в виде сообщения элементу массива? Затем, что объект proc является замыканием и, следовательно, помнит контекст, в котором был создан. А в момент создания self был ссылкой на символ, для которого вызывался метод to_proc.

Оглавление книги


Генерация: 0.992. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз