Vra

Joe Van Dyk gevra die Ruby poslys :

  

Hi,

     

In Ruby, ek dink jy kan 'n lambda / proc voorwerp nie beampte, reg? is   wat moontlik in lisp of ander tale?

     

Wat ek probeer doen:

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

So, Ek stuur BackgroundJob n lambda voorwerp, wat die bevat   konteks /-kode vir wat om te doen. Maar, dink dit nie moontlik was. Ek   beland Kombineer 'n normale robyn voorwerp wat instruksies vervat   vir wat om te doen na die program hardloop.

     

Joe

Was dit nuttig?

Oplossing

Jy kan 'n Lambda of Proc nie veiligheidsbeamptes gebruik nie. Dit is omdat beide van hulle word beskou as sluitings, wat beteken dat hulle toe te maak om die geheue waarop hulle gedefinieer en kan dit verwys. (Ten einde hulle veiligheidsbeampte jy wil hê om al die geheue wat hulle kon bekom ten tyde hulle geskape Marshal.)

As Gaius het daarop gewys al is, kan jy gebruik ruby2ruby om 'n houvas van die string van die kry program. Dit wil sê, jy kan die string wat die robyn kode verteenwoordig veiligheids- dan herevalueer dit later.

Ander wenke

jy kan ook gaan net jou kode as 'n string:

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

dan voer dit met eval

eval code

wat sal 'n robyn Lamda terugkeer.

met behulp van die %{} formaat ontsnap 'n string, maar net sluit op 'n onvergelykbare stut. maw jy kan nes draadjies soos hierdie %{ [] {} } en dit is nog steeds ingesluit.

die meeste teks sintaksis highlighters nie besef dit is 'n string, so nog vertoon gereelde kode beklemtoon.

As jy belangstel om 'n string weergawe van Ruby-kode behulp Ruby2Ruby is, kan jy wil hierdie draad .

Probeer ruby2ruby

As processed in 'n lêer word gedefinieer, U kan die lêer ligging van processed kry dan afleveringen dit, dan na deserialize gebruik die plek om terug na die proc weer kry

  

proc_location_array = proc.source_location

na deserialize:

  

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]

     

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

Eens op 'n tyd, dit was moontlik die gebruik van Ruby-interne juweel ( https://github.com / cout / Ruby-interne ), bv:

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

Daar is 'n paar voorbehoude, maar dit het baie jare en ek kan nie onthou die besonderhede. As 'n voorbeeld, ek is nie seker wat gebeur as 'n veranderlike is 'n dynvar in die binding waar dit gestort en 'n plaaslike in die binding waar dit weer gebind. Serializeren n AST (op MRI) of bytecode (op YARV) is nie-triviale.

Die bogenoemde kode werk op YARV (tot 1.9.3) en MRI (tot 1.8.7). Daar is geen rede waarom dit nie gedoen kan word om te werk op Ruby 2.x, met 'n klein hoeveelheid moeite.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top