Concurrent code in Ruby 1.8.6 through inlining

Posted by Chuck Vose Mon, 07 Jan 2008 19:11:00 GMT

Slight typo in the code fixed: 2008-01-08

Toshiyuki and I have released a new gem called rbridge which allows us to execute functional, side-effect free, concurrent code directly in Ruby regardless of the version by using Erlang as a processor. This includes using the Mnesia distributed database and ETS/DETS.

To try it out please follow these steps:

1. Download Erlang for your os. Windows has binaries and OS X can be configured with `./configure—prefix=/opt/local` to make MacParts happy. I haven’t yet tried it with Linux but the default configure options should be okay.

2. Download the rbridge gem. `sudo gem install rbridge`

3. Start the rulang server in Erlang on port 9900. Change dir to the gem directory which is usually /usr/local/lib/ruby/gems/1.8/gems/rbridge-0.1/lib and run sudo erlc rulang.erl. Enter the Erlang shell by typing erl. Finally, start the server with rulang:start_server(9900). (There’s a dot at the end of the command).

4. Require rubygems and rbridge in your code and create a new connection to the rulang server. This is the simplest bit of inline code I can think of but there is a lot more we can do: asynchronous access and ruby-style syntax specifically.

require 'rubygems'
require 'rbridge'

@r = RBridge.new(nil, 'localhost', 9900)

puts @r.erl('10*10.')

To read more check out the documentation on ruby-mnesia.rubyforge.org.

Aside: Toshiyuki Hirooka found me. Thank you to everyone that helped search and offered to translate for us. I’m constantly impressed by the support from the Ruby community.

Posted in ,  | Tags , , , ,  | no comments

rbridge 0.1 Released

Posted by Chuck Vose Sat, 05 Jan 2008 01:54:00 GMT

FEATURES:

Allows use of Erlang code within Ruby

Changes:

v0.1 / 2008-01-04 (vosechu)

1 major enhancement

  • Allows many-lined Erlang commands when using the Erlang class for direct access.

3 minor enhancements

  • Revised error checking to allow custom resolution
  • stop_server/0 now shuts down any servers running in an erl shell
  • created tests to run with RSpec and autotest (erl server must be running on port 9900).

3 other changes

  • Forked onto rubyforge complete with rdocs, gem, etc.
  • Translated some comments into english as well as the README
  • Packaged explicitly with gpl documentation

Posted in , ,  | Tags , , ,  | no comments

Complex commands with Rulang

Posted by Chuck Vose Thu, 03 Jan 2008 18:17:00 GMT

Rulang was giving me a lot of trouble with regards to multi-line commands and complex commands in general. After hacking on it for a while I’ve developed a patch that will allow ruby code such as the following:

require 'rulang'

@mnesia = RulangBridge::Erlang.new("localhost", 9900)

def find
  @mnesia.eval(<<-EOF
    QH = qlc:q([X || X <- mnesia:table(shop)]),
    F = fun() -> qlc:eval(QH) end,
    {atomic, Val} = mnesia:transaction(F),
    Val.
  EOF
  )
end

puts find

PATCH

diff -u Desktop/rulangbridge/rulang.erl Current Schoolwork/Project/mnesia/rulang_test/rulang.erl
--- Desktop/rulangbridge/rulang.erl     2007-05-17 20:25:50.000000000 -0700
+++ Current Schoolwork/Project/mnesia/rulang_test/rulang.erl    2008-01-03 10:12:05.000000000 -0800
@@ -30,11 +30,15 @@
 handle_connection(Socket) ->
-       Reason = (catch communication(Socket)),
-       gen_tcp:send(Socket, io_lib:format("Error: ~w~n", [Reason])),
+       try communication(Socket)
+  catch
+    error:Reason ->
+         {gen_tcp:send(Socket, io_lib:format("Error: ~p~n", [Reason]))}
+  end,
        ok = gen_tcp:close(Socket).

+% Try to evaluate the code submitted throwing an exception if the evaluation
+% doesn't work. Return the code submitted.
 communication(Socket) ->
        {ok, Binary} = gen_tcp:recv(Socket, 0),
        {ok, Result} = eval(binary_to_list(Binary)),
@@ -43,9 +47,9 @@

 eval(Expression) ->
-       {ok, Scanned, _} = erl_scan:string(Expression),
-       {ok, [Parsed]} = erl_parse:parse_exprs(Scanned),
-       {value, Result, _} = erl_eval:expr(Parsed, []),
+       {done, {ok, Scanned, _}, _} = erl_scan:tokens([], Expression, 0),
+       {ok, Parsed} = erl_parse:parse_exprs(Scanned),
+       {value, Result, _} = erl_eval:exprs(Parsed, []),
        {ok, Result}.

diff -u Desktop/rulangbridge/rulang.rb Current Schoolwork/Project/mnesia/rulang_test/rulang.rb
--- Desktop/rulangbridge/rulang.rb      2007-05-24 10:42:22.000000000 -0700
+++ Current Schoolwork/Project/mnesia/rulang_test/rulang.rb     2008-01-03 10:02:19.000000000 -0800
@@ -79,7 +79,7 @@
                def eval(command)
                        socket = TCPSocket.new(@host, @port)
                        socket.write(command)
-                       socket.gets # ...?
+                       socket.read # ...?
                end

Posted in , ,  | Tags , , ,  | no comments