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

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

Comments

@kolmogorov-fan-account
Copy link
Contributor

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.

@mattn
Copy link
Contributor

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));

@matz
Copy link
Member

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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants