Как я маршал лямбда (Proc) в Ruby?
Joe Van Dyk спросил список рассылки Ruby:
Привет,
В Ruby, я думаю, вы не можете маршалировать объект лямбда /proc, верно? Является что возможно в lisp или на других языках?
Что я пытался сделать:
l = lamda { ... }
Bj.submit "/path/to/ruby/program", :stdin => Marshal.dump(l)
Итак, я отправляю BackgroundJob лямбда-объект, который содержит контекст/код, что делать. Но, думаю, это было невозможно. я закончил маршалинг обычного объекта ruby, который содержал инструкции что делать после запуска программы.
Джо
Ответы
Ответ 1
Вы не можете маршалировать Лямбду или Прок. Это связано с тем, что оба они считаются закрытыми, что означает, что они закрывают память, на которой они были определены, и могут ссылаться на нее. (Чтобы их маршалировать, вы должны были бы маршалировать всю память, к которой они могли получить доступ в момент их создания.)
Как указал Гай, вы можете использовать ruby2ruby, чтобы удержать строку программы. То есть вы можете упорядочить строку, представляющую код ruby, а затем переоценить ее позже.
Ответ 2
вы также можете просто ввести свой код в виде строки:
code = %{
lambda {"hello ruby code".split(" ").each{|e| puts e + "!"}}
}
затем выполните его с помощью eval
eval code
который вернет рубиновую ламду.
используя формат %{}
, вытесняет строку, но закрывается только на непревзойденной фигурной скобке. т.е. вы можете вставить скобки, подобные этому %{ [] {} }
, и все еще прилагается.
в большинстве текстовых синтаксисов не понимают, что это строка, поэтому все равно отображают регулярное выделение кода.
Ответ 3
Если вам интересно получить строчную версию Ruby-кода с помощью Ruby2Ruby, вам может понравиться этот поток.
Ответ 4
Попробуйте ruby2ruby
Ответ 5
Я нашел proc_to_ast для выполнения наилучшей работы: https://github.com/joker1007/proc_to_ast.
Работает наверняка в ruby 2+, и я создал PR для совместимости с ruby 1.9.3+ (https://github.com/joker1007/proc_to_ast/pull/3)
Ответ 6
Если proc определен в файл, U может получить местоположение файла proc, а затем сериализует его, а затем после десериализации используйте это место, чтобы вернуться к proc снова
proc_location_array = proc.source_location
после десериализации:
имя_файла = proc_location_array [0]
line_number = proc_location_array [1]
proc_line_code = IO.readlines(имя_файла) [line_number - 1]
proc_hash_string = proc_line_code [proc_line_code.index( "{" ).. proc_line_code.length]
proc = eval ( "lambda # {proc_hash_string}" )