Сведения о вопросе

GANGST1ER

04:17, 12th August, 2020

Теги

Как мне маршалировать a lambda (Proc) в Ruby?

Просмотров: 512   Ответов: 7

Джо Ван Дайк спросил список рассылки Ruby :

Привет,

В Ruby, я полагаю, вы не можете маршалировать объект lambda/proc, верно? Является это возможно в lisp или других языках?

То, что я пытался сделать:

l = lamda { ... }
Bj.submit "/path/to/ruby/program", :stdin => Marshal.dump(l)

Итак, я посылаю BackgroundJob a lambda объект, который содержит контекст/код для того, что нужно сделать. Но, наверное, это было невозможно. Я в итоге был выполнен маршалинг обычного объекта ruby, содержащего инструкции для того, что делать после запуска программы.

Джо



  Сведения об ответе

davran

08:43, 20th August, 2020

Вы не можете маршалировать Lambda или Proc. Это происходит потому, что оба они считаются closures, что означает, что они закрываются вокруг памяти, на которой они были определены, и могут ссылаться на нее. (Чтобы упорядочить их, вам придется упорядочить всю память, к которой они могли получить доступ в момент их создания.)

Однако, как отметил Гай, вы можете использовать ruby2ruby , чтобы получить доступ к строке программы. То есть вы можете маршалировать строку, представляющую код ruby, а затем повторно оценить ее позже.


  Сведения об ответе

SILA

09:59, 6th August, 2020

вы также можете просто ввести свой код в виде строки:

code = %{
    lambda {"hello ruby code".split(" ").each{|e| puts e + "!"}}
}

затем выполните его с помощью eval

eval code

который вернет ruby ламду.

использование формата %{} экранирует строку, но закрывается только на несопоставимой фигурной скобке. т. е. вы можете вложить фигурные скобки, как это %{ [] {} } , и он все еще заключен.

большинство текстовых синтаксических маркеров не понимают, что это строка, поэтому по-прежнему отображают обычную подсветку кода.


  Сведения об ответе

P_S_S

15:09, 26th August, 2020

Если вы заинтересованы в получении Строковой версии кода Ruby с помощью Ruby2Ruby, вам может понравиться этот поток .


  Сведения об ответе

P_S_S

16:04, 29th August, 2020

Попробовать ruby2ruby


  Сведения об ответе

FAriza

07:12, 5th August, 2020

Я нашел 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 )


  Сведения об ответе

prince

07:19, 26th August, 2020

Если proc определен в файл, U может получить расположение файла proc, затем сериализовать его, а затем после десериализации использовать расположение, чтобы снова вернуться к proc

proc_location_array = proc.source_location

после десериализации:

file_name = proc_location_array[0]

line_number = proc_location_array[1]

proc_line_code = IO.readlines(file_name) [line_number - 1]

proc_hash_string = proc_line_code[proc_line_code.index (" {")..proc_line_code.length]

тр = ивала("lambda #{proc_hash_string}")


  Сведения об ответе

qwerty101

17:19, 22nd August, 2020

Когда-то это было возможно с помощью ruby-internal gem ( https://github.com/cout/ruby-internal), например:

p = proc { 1 + 1 }    #=> #<Proc>
s = Marshal.dump(p)   #=> #<String>
u = Marshal.load(s)   #=> #<UnboundProc>
p2 = u.bind(binding)  #=> #<Proc>
p2.call()             #=> 2

Есть некоторые оговорки, но прошло уже много лет, и я не могу вспомнить подробности. Например, я не уверен, что произойдет, если переменная является dynvar в привязке, где она сбрасывается, и локальным в привязке, где она повторно привязывается. Сериализация AST (на MRI) или байт-кода (на YARV) нетривиальна.

Приведенный выше код работает на YARV (до 1.9.3) и MRI (до 1.8.7). Нет никаких причин, по которым его нельзя заставить работать на Ruby 2.x с небольшим количеством усилий.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться