【发布时间】:2021-11-17 21:31:17
【问题描述】:
我有一个如下所示的 CSV 文件:
CountryCode,CountryName
AD,Andorra
AE,United Arab Emirates
AF,Afghanistan
AG,Antigua and Barbuda
// -- snip -- //
还有一个看起来像这样的类:
module OpenData
class Country
def initialize(@code : String, @name : String)
end
end
end
我希望在编译时自动加载模块中的类变量,如下所示:
module OpenData
@@countries : Array(Country) = {{ run "./sources/country_codes.cr" }}
end
我尝试通过以下代码使用上面的“运行”宏:
require "csv"
require "./country"
content = File.read "#{__DIR__}/country-codes.csv"
result = [] of OpenData::Country
CSV.new(content, headers: true).each do |row|
result.push OpenData::Country.new(row["CountryCode"], row["CountryName"])
end
result
但这会导致
@@countries : Array(Country) = {{ run "./sources/country_codes.cr" }}
^
Error: class variable '@@countries' of OpenData must be Array(OpenData::Country), not Nil
由于各种原因,我的所有其他尝试都以某种方式失败了,例如无法在宏中调用.new 或类似的东西。这是我在 Elixir 和其他支持宏的语言中经常做的事情,而且我怀疑 Crystal 也可以实现......我也会采取任何其他方式在编译时完成任务!
基本上还有几个文件我想用这种方式处理,它们更长/更复杂......提前致谢!
编辑:
发现问题。看来我必须从“运行”宏返回一个包含实际水晶代码的字符串。于是,“run”文件中的代码就变成了:
require "csv"
content = File.read "#{__DIR__}/country-codes.csv"
lines = [] of String
CSV.new(content, headers: true).each do |row|
lines << "Country.new(\"#{row["CountryCode"]}\", \"#{row["CountryName"]}\")"
end
puts "[#{lines.join(", ")}]"
一切正常!
【问题讨论】:
-
您可以在 SO 中为您自己的问题添加答案 :)
标签: crystal-lang