Pull to refresh

Comments 7

Мне вот в Токайдо что не понятно — они все gem'ы собираются в комплекте поставлять? Сколько это весить будет. Одного набора nokogiri (libxml2), therubyracer (libv8), openssl, ldap и прочая фигня будет вместе с Токайдо в одной папке? А чтобы версию одной из либ обновить это надо всё заново качать? А зачем всё это должно в одной папке лежать?
Как всегда отличный подкаст. Причем, смог заинтересовать не только меня, но и мою кошку :)
На МобиРуби интересно будет посмотреть когда зарелизится.
Спасибо за задачку, приятно пошевилить мозгами под конец рабочей недели :)
пошевелить конечно же :)
По поводу ИДЕ, опять же, в RubyMine есть как переход к определению методов/переменных, так и вывод всех мест, где они используются. Учитывая динамическую природу Руби, майн пытается угадать подозрительные места, где еще может быть вызыван метод, например, одноименные символы.

По поводу массивов в MRI:

Первое, что пришло в голову: << для Array [1]:

  VALUE
  rb_ary_push(VALUE ary, VALUE item)
  {
      rb_ary_modify(ary);
      return rb_ary_push_1(ary, item);
  }


Смотрим [2], что за rb_ary_push_1 такая:
  static VALUE
  rb_ary_push_1(VALUE ary, VALUE item)
  {
      long idx = RARRAY_LEN(ary);

    if (idx >= ARY_CAPA(ary)) {
        ary_double_capa(ary, idx);
    }
    RARRAY_PTR(ary)[idx] = item;
    ARY_SET_LEN(ary, idx + 1);
    return ary;
  }


Нас интересует строка RARRAY_PTR(ary)[idx] = item;, заглянем в описание этого макроса [3]:
#define RARRAY_PTR(a) \
    ((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ? \
    RARRAY(a)->as.ary : \
    RARRAY(a)->as.heap.ptr)

// .....

#define RARRAY(obj)  (R_CAST(RArray)(obj))


ничего криминального тут нет, для очистки совести осталось посмотреть на RArray [4]:
struct RArray {
    struct RBasic basic;
    union {
    struct {
        long len;
        union {
        long capa;
        VALUE shared;
        } aux;
        VALUE *ptr;
    } heap;
    VALUE ary[RARRAY_EMBED_LEN_MAX];
    } as;
};


Как видим, макрос RARRAY_PTR выбирает реализацию между полями union, не помню такого в старых версиях, не буду гадать, для чего это нужно.

Итак, используя мои полузабытые знания Си, восстанавливаем упрощенную картину добавления элемента к массиву в Руби. Когда мы делаем foo << bar в Руби, MRI:

1) Находит foo, которе, как и все объекты, изначально VALUE (указатель на unsigned int в 1.9.3)
2) приводит его к RArray с выбором текущей реализации
3) Высчитывает размер массива, и, судя по названиям методов, динамически расширает его размер, пользуясь стратегией удвоения текущего размера каждый раз, как понадобится (может быть там и честное 2.71 даже, к слову, в старых реализациях jvm использовалась такая же стратегия для всяких Vectorов и Listов, если мне не изменяет память )
4) Записывает VALUE bar в настоящий массив :)

1) www.ruby-doc.org/core-1.9.3/Array.html#method-i-3C-3C
2) rxr.whitequark.org/mri/source/array.c?v=1.9.3#730
3) rxr.whitequark.org/mri/source/include/ruby/ruby.h#731
4) rxr.whitequark.org/mri/source/include/ruby/ruby.h#708
Only those users with full accounts are able to leave comments. Log in, please.