2

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?).

Matheus Moreira
  • 17,106
  • 3
  • 68
  • 107
Camilo
  • 635
  • 1
  • 5
  • 9
  • 1
    If you read the RDoc for TypeError: "Raised when encountering an object that is not of the expected type." I think that's exactly what happens in your case here. Falling back to a default value just causes confusion. If you properly document the method and the conditions for raising TypeError there is nothing bad about it imo. – emboss Jul 06 '11 at 19:58
  • Yeah I do do that on regular arguments to the function (non optional). I was wondering if it'd be too strict to do the same on optional params, but yeah you are right is better to fail noisily than end up with unexpected values. – Camilo Jul 07 '11 at 02:03

1 Answers1

0

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 your tmp 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".

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • Oh I do not mean about the array keys, it is a good idea to accept both string and symbol keys. The problem is on the value part of the hash, if for instance I need a string and someone passes an object. The to_s idea do sound like something I might end up doing when the value I'm expecting is a string but if the value I need is say a double on the C side an someone passes an object there is no obvious way to treat that. – Camilo Jul 07 '11 at 02:01
  • 1
    @Camilo: So your problem is with the values rather than the keys? In that case raising a TypeError is seems reasonable if you can't sensibly convert the value to what you need. – mu is too short Jul 07 '11 at 02:10