Issue #19326 has been updated by luke-gru (Luke Gruber).
Your new example, I think, is not possible with the current API.
However, there is a bug in Ruby that I just found that allows it.
```ruby
class Worker
def start(&blk)
blk = blk.curry # bug in ruby allows sharing of non-shareable proc
Ractor.make_shareable(blk)
@ractor = Ractor.new(blk) do |b|
message = receive
b.call(message)
end
self
end
def work(msg)
@ractor.send(msg)
@ractor.take
end
end
worker = Worker.new
worker.start { |args| p args }
worker.work('msg')
```
This is a bug because in debug versions of ruby this crashes.
----------------------------------------
Feature #19326: Please add a better API for passing a Proc to a Ractor
https://bugs.ruby-lang.org/issues/19326#change-101438
* Author: sdwolfz (Codruț Gușoi)
* Status: Assigned
* Priority: Normal
* Assignee: ko1 (Koichi Sasada)
----------------------------------------
Example 1:
```ruby
class Worker
def initialize(&block)
@block = block
end
def run
Ractor.new(@block, &:call)
end
end
worker = Worker.new { 1 }
puts worker.run.take
```
Errors with:
```
<internal:ractor>:271:in `new': allocator undefined for Proc (TypeError)
from scripts/run.rb:9:in `run'
from scripts/run.rb:14:in `<main>'
```
Example 2:
```ruby
class Worker
def initialize(&block)
@block = Ractor.make_shareable(block)
end
def run
Ractor.new(@block, &:call)
end
end
worker = Worker.new { 1 }
puts worker.run.take
```
Errors with:
```
<internal:ractor>:820:in `make_shareable': Proc's self is not shareable:
#<Proc:0x00007f00394c38b8 scripts/run.rb:13> (Ractor::IsolationError)
from scripts/run.rb:5:in `initialize'
from scripts/run.rb:13:in `new'
from scripts/run.rb:13:in `<main>'
```
Example 3:
```ruby
class Worker
def initialize(&block)
@block = Ractor.make_shareable(block)
end
def run
Ractor.new(@block, &:call)
end
end
worker = Ractor.current.instance_eval { Worker.new { 1 } }
puts worker.run.take
```
Works, but having `Ractor.current.instance_eval` as a wrapper around the block is not
ideal, as Ractor is supposed to be only an implementation detail in Worker.
I know about
https://bugs.ruby-lang.org/issues/18243 and the discussion around
`proc.bind(nil)`. That would actually be ideal, as for the purposes if why I want this
functionality I don't care what `self` is in a block, and the less it has access to
the better.
The general idea of Worker is to have a Ractor be able to lazily execute an arbitrary
proc. And all the bindings it would need would be passed explicitly, either through `args`
in the constructor or through `send`/`receive`, so `self` would really not matter.
The benefit: this would make it so concurrent code can be more easily be implemented with
Ractors as currently you can execute an arbitrary proc by passing it to a Thread (but you
don't get the nice data isolation).
--
https://bugs.ruby-lang.org/