No commit activity in last 3 years
No release in over 3 years
Give & take, serializing a ruby proc is possible, though not a perfect one (yet).
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0

Runtime

>= 1.2.5
>= 0.2.2.1
 Project Readme

serializable_proc¶ ↑

IMPORTANT#1: SerializableProc was written in the days of ruby 1.9.x, it should be buggy for anything beyond that.¶ ↑

IMPORTANT#2: SerializableProc is no longer maintained, use it at your own risk, & expect no bug fixes.¶ ↑

As the name suggests, SerializableProc is a proc that can be serialized (marshalled). A proc is a closure, which consists of the code block defining it, and binding of local variables. SerializableProc’s approach to serializability is to extract:

  1. the code from the proc (using sourcify), and

  2. the local, instance, class & global variables reference within the proc from the proc’s binding, using deep copy via Marshal.load(Marshal.dump(var))

A SerializableProc differs from the vanilla Proc in the following 2 ways:

1. Isolated variables¶ ↑

By default, upon initializing, all variables (local, instance, class & global) within its context are extracted from the proc’s binding, and are isolated from changes outside the proc’s scope, thus, achieving a snapshot effect.

require 'rubygems'
require 'serializable_proc'

x, @x, @@x, $x = 'lx', 'ix', 'cx', 'gx'

s_proc = SerializableProc.new { [x, @x, @@x, $x].join(', ') }
v_proc = Proc.new { [x, @x, @@x, $x].join(', ') }

x, @x, @@x, $x = 'ly', 'iy', 'cy', 'gy'

s_proc.call # >> "lx, ix, cx, gx"
v_proc.call # >> "ly, iy, cy, gy"

Sometimes, we may want global variables to behave as truely global, meaning we don’t want to isolate globals at all, this can be done by declaring @@_not_isolated_vars within the code block:

s_proc = SerializableProc.new do
  @@_not_isolated_vars = :global # globals won't be isolated
  $stdout << "WakeUp !!"         # $stdout is the $stdout in the execution context
end

Supported values are :global, :class, :instance, :local & :all, with :all overriding all others. The following declares all variables as not isolatable:

s_proc = SerializableProc.new do
  @@_not_isolated_vars = :all
  ...
end

When invoking, Kernel.binding should be passed in to avoid unpleasant surprises:

s_proc.call(binding)

(take a look at SerializableProc’s rdoc for more details)

2. Marshallable¶ ↑

No throwing of TypeError when marshalling a SerializableProc:

Marshal.load(Marshal.dump(s_proc)).call # >> "lx, ix, cx, gx"
Marshal.load(Marshal.dump(v_proc)).call # >> TypeError (cannot dump Proc)

Installing It¶ ↑

The religiously standard way:

$ gem install serializable_proc

Gotchas¶ ↑

Under the hood, SerializableProc relies on sourcify to do code extraction, thus it shares the same gotchas as sourcify.

Supported Rubies¶ ↑

SerializableProc has been tested to work on the following rubies:

  1. MRI 1.8.6, 1.8.7 & 1.9.1

  2. REE 1.8.7

  3. JRuby 1.5.1+

Note on Patches/Pull Requests¶ ↑

  • Fork the project.

  • Make your feature addition or bug fix.

  • Add tests for it. This is important so I don’t break it in a future version unintentionally.

  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)

  • Send me a pull request. Bonus points for topic branches.

Copyright © 2010 NgTzeYang. See LICENSE for details.