十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

crystalruby块传递完全攻略:Ruby与Crystal之间如何实现双向yield

crystalruby块传递完全攻略:Ruby与Crystal之间如何实现双向yield crystalruby块传递完全攻略Ruby与Crystal之间如何实现双向yield【免费下载链接】crystalrubyEmbed Crystal code directly in Ruby项目地址: https://gitcode.com/gh_mirrors/cr/crystalrubycrystalruby 是一个允许你在 Ruby 代码中直接内嵌并编译运行 Crystal 代码的 gem而crystalruby 块传递Block/Proc 传递是它最亮眼的能力之一你既可以让 Crystal 方法把值 yield 给 Ruby 块也能让 Ruby 方法接收来自 Crystal 的块。这篇crystalruby 双向 yield 实战指南将用最短的代码带你打通两个方向新手也能快速上手。为什么需要双向 yield先搞懂块传递的价值在纯 Ruby 里yield是再普通不过的语法。但当方法跑在 Crystal 里事情就变得有趣了块Block本质是一段可执行的代码回调跨语言传递意味着要把 Ruby 的 Proc 编译成 FFI 函数指针再交给 Crystal 调用反之亦然。crystalruby 的块传递设计解决了两类高频需求Crystal 方法 → Ruby 块让 CPU 密集型循环在 Crystal 中执行把每个中间结果吐回 Ruby 处理。Ruby 方法 → Crystal 块让 Crystal 代码把迭代逻辑传给 Ruby实现高度灵活的回调。对应的源码核心在 proc.rb它负责 Proc 类型跨 FFI 的装箱与调用转换。快速开始安装 crystalruby 并准备运行环境先确保机器上装有现代 Crystal 编译器然后安装 gemgem install crystalruby或者把下面这行加进 Gemfilegem crystalruby安装完成后用crystallize标记的方法就会被编译为 Crystal 并通过 FFI 调用首次运行会有一次编译过程属正常现象。方向一Crystal 方法向 Ruby 块 yieldRuby 传块给 Crystal这是最常见的方向。关键语法是在方法签名里增加一个yield: Proc(参数类型, 返回类型)参数然后在方法体内用yield关键字调用块。require crystalruby crystallize def yielder_cr(a: Int32, b: Int32, yield: Proc(Int32, Nil)) yield a b end yielder_cr(10, 20) { |sum| puts sum } # 30注意三点参数名必须叫yield类型是ProcProc(Int32, Nil)表示块接收一个Int32参数、无返回值调用方 Ruby 侧完全不用感知差异照常传块即可。方向二Ruby 方法接收 Crystal 传来的块Crystal 调 Ruby反向传递需要用expose_to_crystal把 Ruby 方法暴露给 Crystal同样声明yield: Proc(...)参数。下面这个例子中Crystal 方法向 Ruby 方法传块Ruby 方法内部再 yield 三次expose_to_crystal def yielder_rb(a: Int32, b: Int32, yield: Proc(Int32, Nil)) yield a b end crystallize def invoke_yielder_rb(a: Int32, b: Int32) yielder_rb(a, b) do |sum| puts sum end end invoke_yielder_rb(50, 50) # 100这里yielder_rb跑在 Ruby但它的调用方invoke_yielder_rb跑在 Crystal——Crystal 把块作为参数传给 RubyRuby 再用 yield 把值回传双向闭环由此形成。官方文档 Yielding 章节见 README.md完整测试用例可参考 test_proc.rb。实战带返回值的双向 yield 完整示例块不仅能接收参数还能把处理结果返回给调用方。看 test_expose_to_crystal.rb 中的用法Ruby 方法连续三次 yield把每次块的返回值累加crystallize :int def will_call_ruby(seed: Int32) ruby_yield(seed) do |value| value - 4 end end expose_to_crystal - { Int32 } def ruby_yield(initial: Int32, yield: Proc(Int32, Int32)) initial yield 14 initial yield 28 initial yield 32 initial endProc(Int32, Int32)中的第二个Int32就是块的返回值类型。这一能力非常适合「Crystal 循环计算 Ruby 灵活定制处理逻辑」的组合拳。进阶技巧异步模式下的块传递在多线程场景crystalruby 通过 Reactor 把调用多路复用到一个线程。用async: true可以让 Crystal 代码获得 Fiber 级并发且异步方法同样支持 yield见 test_async_methods.rbcrystallize async: true def yield_to_ruby(yield: Proc(Int32, Nil)) yield 10 yield 20 yield 30 end yielded [] yield_to_ruby { |val| yielded val } # yielded [10, 20, 30]异步下块回调会通过CrystalRuby.queue_callback排队回到 Ruby 线程执行从而保证 GC 与 Fiber 调度安全。底层实现可查看 function.rb 中的register_callback!与block_converter逻辑。常见踩坑与解决建议忘记声明yield:参数不声明块参数方法体里的yield无法编译记得严格按Proc(入参类型, 返回类型)书写。块与参数类型不匹配跨语言传递时类型校验很严格Proc(Int32, Nil)和Proc(Int32, Int32)不能混用否则运行时报ArgumentError。同步/异步选择默认同步模式简单直接高频小调用且单线程程序可开启single_thread_mode减少 Reactor 开销详见 config.rb。首次编译慢JIT 编译只有第一次慢后续调用会快很多生产环境可用CrystalRuby.compile!预编译。总结掌握 crystalruby 块传递本质就三句话签名里加yield: Proc(...)、方法体里用yield调块、用expose_to_crystal打通反向通道。双向 yield 让你既享受 Crystal 的高性能又保留 Ruby 的灵活回调是混合编程的黄金组合。动手跑一遍上面的例子你就能完全掌握这套双向 yield 玩法了【免费下载链接】crystalrubyEmbed Crystal code directly in Ruby项目地址: https://gitcode.com/gh_mirrors/cr/crystalruby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表