【问题标题】:How to merge NamedTuples in in a macro in Crystal?如何在 Crystal 的宏中合并 NamedTuples?
【发布时间】:2019-06-25 00:33:22
【问题描述】:

我正在尝试基于两个命名元组的合并在一个类 (OtherThing) 中执行 JSON.mapping

class Thing
  MAPPING = {
    id:                  {type: String, default: UUID.random.to_s},
    email:               {type: String, nilable: true},
  }

  JSON.mapping({{MAPPING}})
end

class OtherThing
  MAPPING = Thing::MAPPING.merge({
    address:                              String,
    city:                                 String,
    zip:                                  {type: String, nilable: true},
    latitude:                             {type: Float64, nilable: true},
    longitude:                            {type: Float64, nilable: true},
  })

  JSON.mapping({{MAPPING}})
end

这会根据我组织代码的方式产生错误。

一个错误:

Error expanding macro

FOR expression must be an array, hash or tuple literal, not Call:

Thing::MAPPING.merge

{% for key, value in _properties_ %}
                     ^~~~~~~~~~~~

另一个可能的错误:

undefined macro method 'NamedTupleLiteral#merge' 中的JSON.mapping OtherThing

【问题讨论】:

    标签: crystal-lang


    【解决方案1】:

    简而言之——不,你现在不能在宏中插入常量。

    @asterite:

    问题是映射宏期望 HashLiteral 作为 参数,但现在他们收到一个路径

    在您的情况下,NamedTuple 宏获得了 Call 节点。在 Crystal repo https://github.com/crystal-lang/crystal/issues/2388 的讨论中找到了解决方法,理论上可以解决这个问题,但 JSON.mapping 它是旧方法,将在下一个版本中从语言中删除,而是尝试 JSON::Serializable

    【讨论】:

      【解决方案2】:

      感谢@Blacksmoke16 的帮助指出,您可以通过使用 splats 定义自己的宏来实现预期的结果。

      下面的代码应该可以工作。归功于@Blacksmoke16

      macro define(*args)
        JSON.mapping(    
          {% for t in args %}
            {{t.double_splat}},
          {% end %}
        )
      end
      
      class Thing
        MAPPING = {
          id:                  {type: String, default: UUID.random.to_s},
          email:               {type: String, nilable: true},
        }
      
        define {{MAPPING}}
      end
      
      class OtherThing
        MAPPING = {
          address:                              String,
          city:                                 String,
          zip:                                  {type: String, nilable: true},
          latitude:                             {type: Float64, nilable: true},
          longitude:                            {type: Float64, nilable: true},
        }
      
        define {{MAPPING}}, {{Thing::MAPPING}}
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-03
        • 2021-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-01
        • 1970-01-01
        相关资源
        最近更新 更多