Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot iterate over a Hash without allocating an array? #3073

kolmogorov-fan-account opened this issue Jan 6, 2016 · 2 comments


Copy link

kolmogorov-fan-account commented Jan 6, 2016

I currently use mrb_hash_keys to iterate over a hash like this

mrb_value keys = mrb_hash_keys(mrb, value);
for (mrb_int i = 0, f = mrb_ary_len(mrb, keys); i < f; ++i) {
  mrb_value key = mrb_ary_ref(mrb, keys, i);
  mrb_value value = mrb_hash_get(self->state, value, key);
  my_function(key, value);

This has the downside of allocating an array and copying the keys, just to discard it it right after.

The fact that mrb_hash_tbl is exposed as a public API suggests that it is fine to access directly the kh_ht. This would allow to iterate without copying by using kh_begin and kh_end. The problem is that they do not work because these macros rely on the declaration of struct kh_ht which is private in hash.c. In that case, I wonder if the kh_ht is really mean to be public?

  • If yes, can I move KHASH_DECLARE to khash.h so it is usable from outside?
  • If no, I guess mrb_hash_tbl should not be public at all. In that case, what do you think of adding functions similar to these to the Hash API?
typedef size_t mrb_hash_iter_t;
mrb_hash_iter_t mrb_hash_begin(struct mrb_state *mrb, mrb_value hash);
mrb_hash_iter_t mrb_hash_end(struct mrb_state *mrb, mrb_value hash);
mrb_hash_iter_t mrb_hash_next(struct mrb_state *mrb, mrb_value hash, mrb_hash_iter_t iter);

Thank you.

Copy link

mattn commented Jan 7, 2016

One another suggestion to use callback.

/* callback can break loop with return FALSE */
void mrb_each_with_index(
    struct mrb_state *mrb,
    mrb_value hash_or_array,
    int (*callback)(mrb_value index, mrb_value value));

Copy link

matz commented Jan 7, 2016

It may cause serious problems if the hash is modified during the iteration. So I am not positive about providing public API to iterate over hashes. Instead I'd rather move KHASH_DECLARE to mruby/hash.h.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
None yet

No branches or pull requests

3 participants