整理 DSL 用 Ruby 容易写的原因

寻技术 Ruby编程 2023年11月21日 99

这是什么

Ruby 有时被描述为“一种易于编写 DSL 的语言”。
我总结了为什么说 Ruby 易于编写 DSL。
如果您有类似“也有这样的元素”之类的内容,如果您可以发表评论或提出编辑请求,我会很高兴。

DSL 示例

DSL 代表领域特定语言。
简而言之,就像“用户可以自由地实现和提供接近语法的机制”。
我会把详细的解释留给维基百科。

Ruby 和 Rails 中使用的著名 DSL 是围绕 ActiveRecord 的实现。
这是一个例子。

用户.rb
class User < ApplicationRecord
  validates :name, presence: true
  has_many :articles
end

这样,使用 Rails 的 ActiveRecord 特定语法,您可以轻松设置验证、设置关系等。
我将组织为什么可以在 Ruby 中实现这样的 DSL。

用于实现 DSL 的 Ruby 属性

Ruby 有一些在其他语言中很少见的属性。
我将描述它们的特点。

1.调用方法时()可以省略

Ruby 在调用方法时可以省略()
这允许您将方法调用编写为类似于语法声明的代码。

例子.rb
def hello(args)
  "Hello #{args}"
end

hello 'world' #=> 'Hello world'

2.您可以将块作为参数传递

Ruby 允许在其他语言中使用块作为参数来定义方法。
有关其工作原理的详细信息,请参见下文

这使得实现涉及块表示法的代码变得容易,这通常只在其他语言的语法中可用。

例子是:

例子.rb
def two(&block)
  .times do |i|
    block.call(i)
  end
end

two do |i|
  puts "This is #{i+} times"
end

3. 在类声明块内直接执行方法

Ruby 允许在声明类时直接在类声明块内执行方法。
例如,以下代码可以正常工作。

例子.rb
class Base
  class << self
    def hello(arg)
      pp "Hello #{arg}"
    end
  end
end

class Example < Base
   hello 'world'
end
#=> 'Hello world'

4. 方法可以通过define_method等动态定义。

Ruby 可以使用define_methoddefine_singleton_method 等动态声明方法。
这使得根据方法接收到的值在类中定义方法变得容易。
有关这些机制,请参阅以下文章。

例子.rb
def define_call(&block)
  define_method :call do
    block.call
  end
end

define_call do
  pp 'Hello world'
end


call #=> 'Hello world'

写一个 DSL

让我们使用排列的属性实际编写 DSL。
这一次,我实现了一个 DSL 来为方法设置时间限制。

例子.rb
require 'timeout'

class Timer
  class << self
    def timeout(t)
      @@time = t
    end

    def process(&block)
      define_method :call do
        puts 'start'
        Timeout.timeout(@@time) do
          block.call
        end
        puts 'success'
      rescue Timeout::Error
        puts "timeout"
      end
    end
  end
end


class Example < Timer
  timeout 

  process do
    sleep 0.5
  end
end


Example.new.call

概括

通过这种方式,Ruby 的属性组合可以轻松实现专门用于特定领域的 DSL。
请尝试各种实现。

原创声明:本文系作者授权九品源码发表,未经许可,不得转载;

原文地址:https://www.19jp.com/show-308622228.html

关闭

用微信“扫一扫”