Spec-Zone.ru › Ruby 4.0
  1. Перечислитель::
  2. ArithmeticSequence

класс Enumerator::ArithmeticSequence

Родительский класс:
Перечислитель

Enumerator::ArithmeticSequence — подкласс Enumerator, представляющий последовательности чисел с постоянной разностью. Экземпляры этого класса можно создать с помощью методов Range#step и Numeric#step.

Этот класс можно использовать для получения срезов Array (см. Array#slice) или пользовательских коллекций.

Общедоступные методы экземпляра

aseq == obj → true или false Показать исходный код
static VALUE
arith_seq_eq(VALUE self, VALUE other)
{
    if (!RTEST(rb_obj_is_kind_of(other, rb_cArithSeq))) {
        return Qfalse;
    }

    if (!rb_equal(arith_seq_begin(self), arith_seq_begin(other))) {
        return Qfalse;
    }

    if (!rb_equal(arith_seq_end(self), arith_seq_end(other))) {
        return Qfalse;
    }

    if (!rb_equal(arith_seq_step(self), arith_seq_step(other))) {
        return Qfalse;
    }

    if (arith_seq_exclude_end_p(self) != arith_seq_exclude_end_p(other)) {
        return Qfalse;
    }

    return Qtrue;
}

Возвращает true, только если obj является Enumerator::ArithmeticSequence и имеет эквивалентные значения begin, end, step и exclude_end?.

Также имеет псевдонимы: ===, eql?
===
Псевдоним для: ==
begin → число или nil Показать исходный код
static inline VALUE
arith_seq_begin(VALUE self)
{
    struct arith_seq *ptr;
    TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
    return ptr->begin;
}

Возвращает число, задающее первый элемент этой арифметической последовательности.

each {|i| block } → aseq Показать исходный код
each → aseq
static VALUE
arith_seq_each(VALUE self)
{
    VALUE c, e, s, len_1, last;
    int x;

    if (!rb_block_given_p()) return self;

    c = arith_seq_begin(self);
    e = arith_seq_end(self);
    s = arith_seq_step(self);
    x = arith_seq_exclude_end_p(self);

    if (!RB_TYPE_P(s, T_COMPLEX) && ruby_float_step(c, e, s, x, TRUE)) {
        return self;
    }

    if (NIL_P(e)) {
        while (1) {
            rb_yield(c);
            c = rb_int_plus(c, s);
        }

        return self;
    }

    if (rb_equal(s, INT2FIX(0))) {
        while (1) {
            rb_yield(c);
        }

        return self;
    }

    len_1 = num_idiv(num_minus(e, c), s);
    last = num_plus(c, num_mul(s, len_1));
    if (x && rb_equal(last, e)) {
        last = num_minus(last, s);
    }

    if (rb_num_negative_int_p(s)) {
        while (NUM_GE(c, last)) {
            rb_yield(c);
            c = num_plus(c, s);
        }
    }
    else {
        while (NUM_GE(last, c)) {
            rb_yield(c);
            c = num_plus(c, s);
        }
    }

    return self;
}
end → число или nil Показать исходный код
static inline VALUE
arith_seq_end(VALUE self)
{
    struct arith_seq *ptr;
    TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
    return ptr->end;
}

Возвращает число, задающее конец этой арифметической последовательности.

eql?
Псевдоним для: ==
exclude_end? → true или false Показать исходный код
static inline VALUE
arith_seq_exclude_end(VALUE self)
{
    struct arith_seq *ptr;
    TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
    return RBOOL(ptr->exclude_end);
}

Возвращает true, если эта арифметическая последовательность не включает конечное значение.

first → число или nil Показать исходный код
first(n) → массив
static VALUE
arith_seq_first(int argc, VALUE *argv, VALUE self)
{
    VALUE b, e, s;

    rb_check_arity(argc, 0, 1);

    b = arith_seq_begin(self);
    e = arith_seq_end(self);
    s = arith_seq_step(self);
    if (argc == 0) {
        if (NIL_P(b)) {
            return Qnil;
        }
        if (!NIL_P(e)) {
            VALUE zero = INT2FIX(0);
            int r = rb_cmpint(rb_num_coerce_cmp(s, zero, idCmp), s, zero);
            if (r > 0 && RTEST(rb_funcall(b, '>', 1, e))) {
                return Qnil;
            }
            if (r < 0 && RTEST(rb_funcall(b, '<', 1, e))) {
                return Qnil;
            }
        }
        return b;
    }

    return arith_seq_take(self, argv[0]);
}

Возвращает первое число этой арифметической последовательности или массив из первых n элементов.

hash → целое число Показать исходный код
static VALUE
arith_seq_hash(VALUE self)
{
    st_index_t hash;
    VALUE v;

    hash = rb_hash_start(arith_seq_exclude_end_p(self));
    v = rb_hash(arith_seq_begin(self));
    hash = rb_hash_uint(hash, NUM2LONG(v));
    v = rb_hash(arith_seq_end(self));
    hash = rb_hash_uint(hash, NUM2LONG(v));
    v = rb_hash(arith_seq_step(self));
    hash = rb_hash_uint(hash, NUM2LONG(v));
    hash = rb_hash_end(hash);

    return ST2FIX(hash);
}

Вычисляет хеш-значение этой арифметической последовательности. Для двух арифметических последовательностей с одинаковыми значениями begin, end, step и exclude_end? будут получены одинаковые хеш-значения.

См. также Object#hash.

inspect → строка Показать исходный код
static VALUE
arith_seq_inspect(VALUE self)
{
    struct enumerator *e;
    VALUE eobj, str, eargs;
    int range_p;

    TypedData_Get_Struct(self, struct enumerator, &enumerator_data_type, e);

    eobj = rb_attr_get(self, id_receiver);
    if (NIL_P(eobj)) {
        eobj = e->obj;
    }

    range_p = RTEST(rb_obj_is_kind_of(eobj, rb_cRange));
    str = rb_sprintf("(%s%"PRIsVALUE"%s.", range_p ? "(" : "", eobj, range_p ? ")" : "");

    rb_str_buf_append(str, rb_id2str(e->meth));

    eargs = rb_attr_get(eobj, id_arguments);
    if (NIL_P(eargs)) {
        eargs = e->args;
    }
    if (eargs != Qfalse) {
        long argc = RARRAY_LEN(eargs);
        const VALUE *argv = RARRAY_CONST_PTR(eargs); /* WB: no new reference */

        if (argc > 0) {
            VALUE kwds = Qnil;

            rb_str_buf_cat2(str, "(");

            if (RB_TYPE_P(argv[argc-1], T_HASH)) {
                int all_key = TRUE;
                rb_hash_foreach(argv[argc-1], key_symbol_p, (VALUE)&all_key);
                if (all_key) kwds = argv[--argc];
            }

            while (argc--) {
                VALUE arg = *argv++;

                rb_str_append(str, rb_inspect(arg));
                rb_str_buf_cat2(str, ", ");
            }
            if (!NIL_P(kwds)) {
                rb_hash_foreach(kwds, kwd_append, str);
            }
            rb_str_set_len(str, RSTRING_LEN(str)-2); /* drop the last ", " */
            rb_str_buf_cat2(str, ")");
        }
    }

    rb_str_buf_cat2(str, ")");

    return str;
}

Преобразует эту арифметическую последовательность в печатное представление.

last → число или nil Показать исходный код
last(n) → массив
static VALUE
arith_seq_last(int argc, VALUE *argv, VALUE self)
{
    VALUE b, e, s, len_1, len, last, nv, ary;
    int last_is_adjusted;
    long n;

    e = arith_seq_end(self);
    if (NIL_P(e)) {
        rb_raise(rb_eRangeError,
                 "cannot get the last element of endless arithmetic sequence");
    }

    b = arith_seq_begin(self);
    s = arith_seq_step(self);

    len_1 = num_idiv(num_minus(e, b), s);
    if (rb_num_negative_int_p(len_1)) {
        if (argc == 0) {
            return Qnil;
        }
        return rb_ary_new_capa(0);
    }

    last = num_plus(b, num_mul(s, len_1));
    if ((last_is_adjusted = arith_seq_exclude_end_p(self) && rb_equal(last, e))) {
        last = num_minus(last, s);
    }

    if (argc == 0) {
        return last;
    }

    if (last_is_adjusted) {
        len = len_1;
    }
    else {
        len = rb_int_plus(len_1, INT2FIX(1));
    }

    rb_scan_args(argc, argv, "1", &nv);
    if (!RB_INTEGER_TYPE_P(nv)) {
        nv = rb_to_int(nv);
    }
    if (RTEST(rb_int_gt(nv, len))) {
        nv = len;
    }
    n = NUM2LONG(nv);
    if (n < 0) {
        rb_raise(rb_eArgError, "negative array size");
    }

    ary = rb_ary_new_capa(n);
    b = rb_int_minus(last, rb_int_mul(s, nv));
    while (n) {
        b = rb_int_plus(b, s);
        rb_ary_push(ary, b);
        --n;
    }

    return ary;
}

Возвращает последнее число этой арифметической последовательности или массив из последних n элементов.

size → число или nil Показать исходный код
static VALUE
arith_seq_size(VALUE self)
{
    VALUE b, e, s, len_1, len, last;
    int x;

    b = arith_seq_begin(self);
    e = arith_seq_end(self);
    s = arith_seq_step(self);
    x = arith_seq_exclude_end_p(self);

    if (RB_FLOAT_TYPE_P(b) || RB_FLOAT_TYPE_P(e) || RB_FLOAT_TYPE_P(s)) {
        double ee, n;

        if (NIL_P(e)) {
            if (rb_num_negative_int_p(s)) {
                ee = -HUGE_VAL;
            }
            else {
                ee = HUGE_VAL;
            }
        }
        else {
            ee = NUM2DBL(e);
        }

        n = ruby_float_step_size(NUM2DBL(b), ee, NUM2DBL(s), x);
        if (isinf(n)) return DBL2NUM(n);
        if (POSFIXABLE(n)) return LONG2FIX((long)n);
        return rb_dbl2big(n);
    }

    if (NIL_P(e)) {
        return DBL2NUM(HUGE_VAL);
    }

    if (!rb_obj_is_kind_of(s, rb_cNumeric)) {
        s = rb_to_int(s);
    }

    if (rb_equal(s, INT2FIX(0))) {
        return DBL2NUM(HUGE_VAL);
    }

    len_1 = rb_int_idiv(rb_int_minus(e, b), s);
    if (rb_num_negative_int_p(len_1)) {
        return INT2FIX(0);
    }

    last = rb_int_plus(b, rb_int_mul(s, len_1));
    if (x && rb_equal(last, e)) {
        len = len_1;
    }
    else {
        len = rb_int_plus(len_1, INT2FIX(1));
    }

    return len;
}

Возвращает количество элементов в этой арифметической последовательности, если она конечна. В противном случае возвращает nil.

step → число Показать исходный код
static inline VALUE
arith_seq_step(VALUE self)
{
    struct arith_seq *ptr;
    TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
    return ptr->step;
}

Возвращает число, задающее постоянную разность между двумя соседними элементами этой арифметической последовательности.

Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API