سؤال

جو فان ديك طلبت القائمة البريدية لروبي:

أهلاً،

في روبي، أعتقد أنه لا يمكنك تنظيم كائن lambda/proc، أليس كذلك؟هل هذا ممكن في LISP أو لغات أخرى؟

ما كنت أحاول القيام به:

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

لذلك ، أرسل BackgroundJob كائن Lambda ، والذي يحتوي على السياق/الكود لما يجب القيام به.ولكن أعتقد أن ذلك لم يكن ممكنا.انتهى بي الأمر بتنظيم كائن روبي طبيعي يحتوي على تعليمات لما يجب القيام به بعد تشغيل البرنامج.

جو

هل كانت مفيدة؟

المحلول

لا يمكنك تنظيم Lambda أو Proc.وذلك لأن كلاهما يعتبران إغلاقين، مما يعني أنهما ينغلقان حول الذاكرة التي تم تعريفهما عليها ويمكنهما الرجوع إليها.(من أجل تنظيمها، يجب عليك تنظيم كل الذاكرة التي يمكنهم الوصول إليها في وقت إنشائها.)

كما أشار غايوس، يمكنك استخدام Ruby2Ruby للحصول على عقد من سلسلة البرنامج.أي أنه يمكنك تنظيم السلسلة التي تمثل رمز روبي ثم إعادة تقييمها لاحقًا.

نصائح أخرى

يمكنك أيضًا إدخال الكود الخاص بك كسلسلة:

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

ثم قم بتنفيذه بالتقييم

eval code

والتي سوف تعود روبي لامدا.

باستخدام %{} format يفلت من السلسلة، ولكنه يغلق فقط على قوس غير متطابق.أي.يمكنك عش الأقواس مثل هذا %{ [] {} } وما زال مغلقًا.

لا تدرك معظم أدوات تمييز بناء الجملة النصية أن هذه سلسلة، لذلك لا تزال تعرض تمييز التعليمات البرمجية بشكل منتظم.

إذا كنت مهتمًا بالحصول على نسخة سلسلة من كود روبي باستخدام Ruby2Ruby، فقد ترغب في ذلك هذا الموضوع.

يحاول Ruby2Ruby

لقد وجدت proc_to_ast للقيام بأفضل عمل: https://github.com/joker1007/proc_to_ast.

يعمل بالتأكيد في روبي 2+، ولقد قمت بإنشاء علاقات عامة للتوافق مع روبي 1.9.3+ (https://github.com/joker1007/proc_to_ast/pull/3)

إذا تم تعريف proc في ملف، فيمكنك الحصول على موقع ملف proc ثم إجراء تسلسل له، ثم بعد إلغاء التسلسل استخدم الموقع للعودة إلى proc مرة أخرى

proc_location_array = proc.source_location

بعد إلغاء التسلسل:

اسم الملف = proc_location_array[0]

line_number = proc_location_array[1]

proc_line_code = IO.readlines(اسم_الملف)[رقم_الخط - 1]

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

proc = eval("lambda #{proc_hash_string}")

ذات مرة، كان هذا ممكنًا باستخدام جوهرة الياقوت الداخلية (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 (على التصوير بالرنين المغناطيسي) أو الرمز الثانوي (على YARV) ليس بالأمر السهل.

يعمل الكود أعلاه على YARV (حتى 1.9.3) والتصوير بالرنين المغناطيسي (حتى 1.8.7).لا يوجد سبب يمنع تشغيله على Ruby 2.x، مع قدر بسيط من الجهد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top