我正在使用crystal language,到目前为止一直很棒 . 不幸的是,我觉得 my 代码变得有点太乱了,到处都是类型 .
例如:
# ---------=====----++---
# Grab characters
# ---------=====----++---
def handle_character_list(msg, client)
result = {} of String => Array(Tuple(Int64, String, String, Int16, Int8)) | Int32 | Int16 | Int64 | String
result["characters"] = db.query_all "select character_id, character_name, DATE_FORMAT(created, '%b:%d:%Y:%l:%i:%p') AS created, level, cc from rpg_characters where user_id = ? ", client.user_id,
as: {Int64, String, String, Int16, Int8}
result["max_char_slots"] = client.user_data["max_char_slots"]
puts result
end
在查看db.query_all method时,它说:
返回一个数组,其中每行的值被读取为给定类型
如上所述,为什么我需要再次将这些类型显式设置为我的 result
变量,如果它们将被返回?
我觉得我做错了什么,任何建议/见解都值得赞赏 .
1 回答
跳出来的第一件事就是哈希类型的大小 . 您似乎使用
Hash
与Ruby中的方式相同 . 别 .在Ruby或其他动态语言中,
Hash
es或对象用作通用数据容器,几乎与未命名的类一样 . 在Crystal中,哈希对于键具有单一类型,对于值具有单一类型,这使得它们不适合该任务 . 您想告诉Crystal更多有关数据结构的信息,因此您不必再重复这些内容 .首先要做的是查看
result
对象 . 它可以简单地转换为record Result
:然后该方法变为
但是,通过查看方法,可能只是在一个地方使用了
Result
记录 - 从此方法返回数据 . 在这种情况下,你不太可能想给它一个更正式的名字 . 在这种情况下,您可以使用NamedTuple
. 他们有点像匿名记录 .更进一步,我们可以看到“角色”也是一种类型:
然后我们可以使用
DB.mapping
来定义Character
类在数据库中的外观 .此定义与前一个定义相同,因为
DB.mapping
会自动为我们生成getter .更进一步,我可能会使
client.user_data
更安全:这只是我如何编写你所展示的代码的思考过程 . 我对你的代码和数据库做了很多假设,这可能是错误的(即“创建”是mysql中的DATETIME) . 我试图展示一个思考过程,而不是一个完成的解决方案 . 希望有所帮助 .