First taste of rocaml

本文探讨了使用Rocaml为Ruby编写扩展的方法,并通过一个示例对比了Rocaml与C语言在实现上的差异及性能表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[url=http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/256569]Rocaml[/url] lets you wrtie Ruby extension in Ocaml. It can be a relief to my project, I truely hope. We are using Ocaml with Rails by means of fork or socket and dealing with the format of communication between two sides is just boring.

Now let's have a look at how rocaml works. I'm gonna translate an [url=http://blog.evanweaver.com/articles/2007/03/14/getting-dirty-with-rubyinline]example[/url] in rubyinline to rocaml. Since rubyinline supports basic type transaltion between Ruby and C, the orginal example is forced to declare a lot of complex data type defined in ruby.h by hand:
[code]
require 'rubygems'
require 'inline'

class Check
class << self
inline do |builder|
builder.c_raw "
static VALUE check(int argc, VALUE *argv, VALUE self) {
double x = NUM2DBL(RARRAY(argv[1])->ptr[0]);
double y = NUM2DBL(RARRAY(argv[1])->ptr[1]);

int len = RARRAY(argv[0])->len;
double last_x = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[len-1])->ptr[0]);
double last_y = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[len-1])->ptr[1]);
double cur_x, cur_y = 0.0;

int i, c = 0;
for (i = 0; i < len; i++) {
cur_x = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[i])->ptr[0]);
cur_y = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[i])->ptr[1]);
if ((((cur_y <= y) && (y < last_y)) ||
((last_y <= y) && (y < cur_y))) &&
(x < (last_x - cur_x) * (y - cur_y) / (last_y - cur_y) + cur_x)) {
c = !c;
}
last_x = cur_x;
last_y = cur_y;
}
if (c == 1) return Qtrue;
return Qfalse;
}
"
end
end
end
[/code]

comparing to Ocaml code:

[code]
let check polygon point =
let len = Array.length polygon in
let last = polygon.(len - 1) in
let result = ref false in
for i = 0 to (len - 1) do
let current = polygon.(i) in
if ((current.(1) <= point.(1) && last.(1) > point.(1)) ||
(last.(1) <= point.(1) && current.(1) > point.(1))) &&
(point.(0) < ((last.(0) -. current.(0)) *.
(point.(1) -. current.(1)) /.
(last.(1) -. current.(1)) +. current.(0)))
then
begin
result := not !result
end;
last.(0) <- current.(0); last.(1) <- current.(1)
done;
!result

open Callback
let _ =
register "Check.check" check[/code]
and then we only have to declare a simple function interface in extconf.rb:

[code]Interface.generate("check") do
def_module("Check") do
fun "check", [ARRAY(ARRAY(FLOAT)), ARRAY(FLOAT)] => BOOL
end
end[/code]

Unfortunately though the ocaml code is more clear than the C one without being polluted by all kinds of type constants, the benchmark shows the rocaml extension is about 5 times slower than the C one. It seems the type conversion is still pricy considering Ocaml code generally should be on the same page with C in terms of speed.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值