2015-09-27 4 views
2

Я просто копал ruby ​​и хотел знать, почему я не могу повторно назначить значение элементу массива с использованием метода перечислимого типа (first или last).ruby ​​присвоение значения массиву с использованием перечислимого метода

Я знаю, что могу присваивать значения индексом, но я хочу узнать об этом больше. Я не нашел много объяснений в here и here.

array1 = [1,2,3,4,5] 
array1.first # returns 1 
array1.first = 7 
NoMethodError: undefined method `first=' for [1, 2, 3, 4, 5]:Array 

Ruby 2.0 

Благодаря

+2

Потому что существует ['Array # [] ='] (http://ruby-doc.org/core-2.2.0/Array.html#method-i-5B-5D-3D), но есть no 'Array # first ='. Вы спрашиваете, почему они их не поместили? – ndn

+0

@ndn да, точно. – Aparichith

+0

Как было сказано несколькими читателями, существует метод экземпляра [Array # [\] =] (http://ruby-doc.org/core-2.2.0/Array.html#method-i-5B-5D-3D), но не метод экземпляра 'Array # first ='. Это так просто. Требуется ли 'Array # first ='? Нет, потому что можно использовать '[] ='. Требуется ли 'Array # first' (что нам нужно)? Нет, потому что можно использовать [Array # [\]] (http://ruby-doc.org/core-2.2.0/Array.html#method-i-5B-5D) (что, кстати, так же отличается из 'Array [] =' как ночь с дня). Итак, почему мы имеем 'Array # first', но не' Array # first = '? Потому что те, кто выступал за добавление последнего, несли день. –

ответ

4

Есть два способа этот вопрос можно прочитать:

  1. Технически, почему работа индексирования решения, но не first один?

Причина заключается в том, что для того, чтобы иметь возможность использовать foo.bar = :baz, класс foo «s должен реализовать метод bar=.

class X 
    def initialize(y) 
    @y = y 
    end 

    def y 
    @y 
    end 
end 

x = X.new(3) 
x.y  # => 3 
x.y = 7 # => NoMethodError: undefined method `y=' for #<X:0x007fb272726d80 @y=3> 

class X 
    def initialize(y) 
    @y = y 
    end 

    def y 
    @y 
    end 

    def y=(new_y) 
    @y = new_y 
    end 
end 

x = X.new(3) 
x.y  # => 3 
x.y = 7 
x.y  # => 7 

Ядро библиотеки делает реализацию Array#[]=, но не Array#first=.

  1. В чем причина, по которой они решили не реализовывать Array#first=?

first метод фактически является частью Enumberable и если один класс реализован first=, это выглядело бы противоречивым, если не было реализации Enumerable#first=.

И этого не может быть, потому что для некоторых перечислений такой метод не имеет смысла (Enumerator). Это также потребует от вас большего количества перечислимых функций. На данный момент для того, чтобы класс стал перечислимым, ему просто нужно реализовать метод each и включить модуль Enumerable.

+0

Я не понимаю вашу точку № 2. Какой метод относится к методу «...»? Почему это было бы несовместимо с тем, что 'Array # first =', но не 'Enumerable # first =', учитывая, что мы имеем 'Array # [] =', но не 'Enumerable # [] ='? –

+0

@CarySwoveland, 'Array # [] =' не противоречит, потому что нет 'Enumerable # []'. Поэтому индексирование является расширением в 'Array', которое не происходит из' Enumerable', и нет никаких ожиданий, чтобы другие перечисляемые индексы также были индексируемыми. Вот что я имел в виду. * Метод is ... * имел в виду 'Enumerable # first'. – ndn

1

Метод массива .first это метод для чтения атрибутов, он не имеет письменного разрешения. Посмотрите на массив Ruby Documentation. Вам нужно переназначить значение по заданному индексу в массиве просто следовать тому, что @Andrey написал

+0

Я не нашел нигде в документе #first «не имеет разрешения на запись». У вас есть. Извините, если я пропустил в документе. Это то, что я получил от doc 'Возвращает первый элемент или первые n элементов массива. Если массив пуст, первая форма возвращает nil, а вторая форма возвращает пустой массив. См. Также #last для противоположного эффекта. ' – Aparichith

+0

@ h.APP.y: это то, что говорит док:« возвращает элемент ». Нигде это не говорит «О, и кстати, вы также можете ** установить ** элементы с этим» –

0

На самом деле вы можете создать first(12), представьте, насколько неудобным был метод, если вы можете установить first=(12,arr), метод становится неоднозначным (если массив не имеет 12 элементов, должен ли он добавлять элементы или должен ли он редактировать x первые элементы), потому что first(12) из массива из 5 элементов возвращает 5 элементов. Написание такого метода, как это, будет нарушать принцип единой ответственности.

+2

Я уверен, что 'x.first (12) = foo' является недопустимым синтаксисом :) –

+0

Вы правы, мой плохой, я отредактировал свой ответ :) –

+0

« нарушит принцип единой ответственности »- многие методы в рубине нарушать СРП. Так что это не похоже на то, что эта причина когда-либо останавливала кого-либо. :) –