Ruby临时表达式模块:TExp

jopen 10年前

texpJim Weirich开发的Ruby临时表达式库,提供了模块化、可扩展的序列化语言。

临时表达式提供了一种精炼地表达重复性事件的方式。例如,每年的12月25日是圣诞节。一个代表圣诞节的临时表达式会返回真,如果日期是12月25日。

dec25 = Date.parse("Dec 25, 2008")  christmas_texp.includes?(dec25)      # => true  christmas_texp.includes?(dec25 + 1)  # => false

可以使用运算符组合临时表达式。例如,如果我有一个圣诞节的临时表达式和一个感恩节的临时表达式,我可以将它们合并成一个假日表达式:

holidays_texp = christmas_texp + thanksgiving_texp

TExp特性

  • 基本表达式

    • DayOfWeek
    • DayOfMonth
    • Week
    • Month
    • Year
    </li>
  • 复合表达式

    • AND
    • OR
    • NOT
    • 时间窗口
    • </ul> </li>
    • inspect的描述人类可读

    • 紧凑、可解析的编码

    • 可由用户扩展的临时表达式类型

    • 建构临时表达式的DSL

    • </ul>

      例子

      以下的例子使用了TExp DSL。DSL默认未开启,可以通过以下方式开启:

      • 使用全局texp方法和块

        te = texp { day(1) * month("Jan") } 
      • 在类中includeTExp::DSL模块

        include TExp::DSL te = day(1) * month("Jan")

      查看TExp::DSL模块获取所有DSL命令的完整描述。

      匹配周一

      te = dow(:monday)  te.includes?(Date.parse("Mar 3, 2008"))    # => true  te.includes?(Date.parse("Mar 4, 2008"))    # => false  te.includes?(Date.parse("Mar 10, 2008"))   # => true    # 等价于  te = TExp::DayOfWeek.new(Date::DAYNAMES.index("Monday"))    # 变体  dow("Mon", "Tues")     # 周一或周二

      匹配三月的任意一天

      te = month(:march)  te.includes?(Date.parse("Mar 1, 2008"))    # => true  te.includes?(Date.parse("Mar 31, 2008"))   # => true  te.includes?(Date.parse("Mar 15, 1995"))   # => true  te.includes?(Date.parse("Feb 28, 2008"))   # => false    # 等价于  te = TExp::Month.new(3)    # 变体  month(1,2,3)         # 一月、二月、三月  month("Nov", "Dec")  # 十一月或十二月

      匹配情人节

      如果你将临时表达式看成日期的集合,那么你可以以有趣的方式组合这些集合。例如,*运算符会创建两个日期集合的交集,只匹配同时满足两个表达式的日期。

      te = day(14) * month("Feb")    te.includes?(Date.parse("Feb 14, 2008"))  # => true  te.includes?(Date.parse("Feb 14, 2007"))  # => true    # 等价于  te = TExp::And.new(         TExp::DayOfMonth.new(14),         TExp::Month.new(2))

      匹配2008年的情人节

      te = day(14) * month("Feb") * year(2008)    te.includes?(Date.parse("Feb 14, 2008"))  # => true  te.includes?(Date.parse("Feb 14, 2007"))  # => false    # 等价于  te = TExp::And.new(         TExp::DayOfMonth.new(14),         TExp::Month.new(2),         TExp::Year.new(2008))

      匹配多个日期

      交集之外,我们可以请求两个临时表达式的并集。下面我们构建一个匹配圣诞节和新年的临时表达式:

      christmas = day(25) * month("Dec")  new_years = day(1) * month("Jan")    holidays = christmas + new_years    holidays.includes?(Date.parse("Jan 1, 2008"))   # => true  holidays.includes?(Date.parse("Dec 25, 2008"))  # => true  holidays.includes?(Date.parse("Jan 1, 2009"))   # => true    holidays.includes?(Date.parse("Feb 14, 2008"))  # => false    # 等价于  holidays = TExp::Or.new(    TExp::And.new( TExp::DayOfMonth.new(25), TExp::Month(12) ),    TExp::And.new( TExp::DayOfMonth.new(1),  TExp::Month(1)  ))

      排除日期

      除了月末的周五之外的其他周五都是Casual Friday:

      fridays = dow(:fri)  last_friday = week(:last) * dow(:fri)  casual_fridays = fridays - last_friday    casual_fridays.includes?(Date.new(2013, 6, 21))  # => true  casual_fridays.includes?(Date.new(2013, 6, 28))  # => false

      相关链接

      编译 SegmentFault