在 ruby C 扩展中类型检查选项哈希值时的最佳实践是什么?
我正在为 ruby 开发一个 C 扩展,我正在访问的 C 库中的函数之一接收一个选项结构,该结构似乎自然地转换为 ruby 世界中的选项哈希。
当 ruby 端的哈希没有为给定选项定义值时,该结构将使用已知的默认值进行初始化。在 C 方面,我有一些类似的想法:
VALUE tmp;
tmp = rb_hash_aref(r_hash, rb_str_new2("opt1"));
if(TYPE(tmp) == T_STRING){
strcpy (c_learn_param->opt1, StringValuePtr(tmp));
}else{
strcpy (c_learn_param->opt1, "default value 1");
}
现在我的问题是,当一个选项具有定义的值但 ruby 类型在 C 中没有意义时。
即使对于可选值,我也应该引发类型错误吗?这似乎有点过分了,我应该回到默认值吗?回退到默认值的问题是用户传递 {"opt1" =>; 123 } 将看到与他没有定义 opt1 相同的行为,这似乎是一个坏主意,我应该回退并打印 ruby 警告吗? (人们甚至读过它们吗?)。
I'm developing a C extension for ruby, one of the functions from the C library I'm accessing receives an options struct which seems to be naturally translate to an options hash in ruby-world.
The struct is being initialized with known default values when the hash on the ruby side does not define a value for a given option. On the C side I have some along these lines:
VALUE tmp;
tmp = rb_hash_aref(r_hash, rb_str_new2("opt1"));
if(TYPE(tmp) == T_STRING){
strcpy (c_learn_param->opt1, StringValuePtr(tmp));
}else{
strcpy (c_learn_param->opt1, "default value 1");
}
Now my problem is when an option has a defined value but the ruby type does not make sense in C.
Should I raise type error even for an optional value? that seems overkill, should I fall back to a default? the problem with falling back to a default is a user passing {"opt1" => 123 } will see the same behaviour as if he had not defined opt1 which seems like a bad idea, should I fall back and print a ruby warning? (do people even read them?).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可能应该至少接受一个符号或一个字符串,因为它们在实践中几乎可以互换使用(因此 ActiveSupport::HashWithIn DifferentAccess)。
根据您的具体情况,在
tmp
上调用to_s
并让其中的任何内容都可以通过这种方式转换为字符串可能是有意义的。但是,如果只接受 String 或 Symbol 才有意义,那么引发 TypeError 是完全明智的做法。对输入尽可能灵活但对输出严格通常是一个好主意,并且有助于建立友好的库。
如果人们不阅读警告,那么当出现问题时,这就是他们自己的错,而你完全有权利傻笑并说“我告诉过你了”。
You should probably accept at least a Symbol or a String as they are, in practice, used nearly interchangeably (hence ActiveSupport::HashWithIndifferentAccess).
Depending on your specific situation, it might make sense to call
to_s
on yourtmp
and let anything in that can be converted to a String that way. However, if it only makes sense to accept a String or Symbol then raising a TypeError is a perfectly sensible thing to do.Being as flexible as possible with your inputs but strict with your outputs is usually a good idea and makes for friendly libraries.
If people don't read warnings then it is their own fault when things go wrong and you're well within your rights to smirk and say "I told you so".