Pull to refresh

Comments 47

УХ, теперь еще информативнее. Так держать. Учу вместе с вами.
уф, «с разгону» не осилить, чувствую вопросов много будет, но вечером

P.S. наверное стоило чуть поподробнее рассказать про nil, это ведь тоже объект, но не очень понятный
nil это объект-синглтон(т.е. единственный) класса NilClass. Присваевается переменным, не имеющим значения.
Пример из статьи:
a = Array.new(3) # [nil, nil, nil] — массив пустой, значит все элементы равны nil.
В условиях приравнивается к false
a = nil
puts "nil!" unless a # напечатает nil!

У каждого объекта есть метод проверки на nil.
puts "nil!" if a.nil? # опять напечатает nil!
Есть еще такой хитрый прием:
a ||= "sting"#присвоит переменной a значение "string" только если a=nil или a=false
a &&= "sting"#наоборот, присвоит только если a!=nil и a!=false
UFO just landed and posted this here
UFO just landed and posted this here
Кто-то еще считает, что стоит завести отдельный блог?
я считаю что стоит выносить в отдельный блог, если вы собираетесь написать хотя бы 15 статей… только не называйте его «Ruby по каплям»… назовите что-нить аля «Изучение Ruby» или вообще «Азы программирования», что нить в этом духе
Угу, количество статей тоже большую роль играет
По-моему хабр не предусматривает возможности «вложенных» блогов, так что лучше оставить в рамках Ruby. Следить, конечно, несколько неудобно, но вот найти потом будет проще
А может стоит завести отдельный standalone-блог?
После всех публикаций, например, или параллельно вести.
целиком поддерживаю идею блога, но параллельного.

Сам решил изучать ruby, и слежу за вашими постами.

Спасибо вам!
«Считывать значения можно и специальным простым методом at — он принимает только один параметр и поэтому работает немного быстрее»

интересно… попробую
UFO just landed and posted this here
collect или map (алиас) НЕ изменяет массив, а возвращает измененную копию.
А вот collect! и map! да.
mholub|mholub irb                                                         21:25
irb(main):001:0> a = [1, 2, 3]
=> [1, 2, 3]
irb(main):002:0> a.map { |x| 2 * x }
=> [2, 4, 6]
irb(main):003:0> a
=> [1, 2, 3]
irb(main):004:0> a.map! {|x| 2 * x }
=> [2, 4, 6]
irb(main):005:0> a
=> [2, 4, 6]

Вообще в ruby это такая идиома: predicate? и dangerous_method!

Ну и забыли про мой любимый итератор — inject.

inject это свертка (fold) или accumulate, известная любителям ФП.
Действует так, если inject-у указывается аргумент, то этот аргумент является начальным значением, inject проходит по массиву и для каждого элемента вызывает блок, передавая ему как параметры накопленное значение (на первой итерации как раз начальное) и сам элемент. Значение, которое вернет блок присваивается накопленному значению и идет переход к следующей итерации.
С примерами понятнее:
[1, 2, 3].inject(0) { |sum, x| sum + x } #сумма всех элементов массива

Если аргумент не передается, то начальным значением становится первый элемент, а итерация начинается со второго:
(1..10).inject { |fac, n| fac * n } #факториал от положительного n
[1, -3, 4, 5, -16, 23].inject { |min, el| min > el ? el : min } #минимальный элемент в массиве

Спасибо за замечания! Исправляем ;)
не разу не читал, есть ли в Ruby коллекции(STL C++), автор, если можно напишите каплю про эти нужные вещи.
точно не знаю, какой набор коллекций входит в STL, но базовые есть в core, а экзотика обязательно найдется на github.com и rubyforge.org
Ну если имели ввиду контейнеры, то: аналог vector-а массив, аналог map-а Hash. Set тоже есть, но для него надо подключить гем active_support. для функционирования Stack и Queue тоже подходит массив (есть соответствующие методы (push, pop, shift))
Заголовок прочитал как «покурим руби вместе».
кстати, метод [n..m] работает и со строками.

'string'[1..2] # 'tr'

и еще по операциям с массивами возможно стоит дополнить:

a = %w{1 2 3 4}
b = %w{3 4 5 6}

a — b # [1, 2] — разность массивов
a & b # [3, 4] — пересечение массивов
a | b # [1, 2, 3, 4, 5, 6] — объединение с удалением дупликатов
Еще повторение массивов:
a = [1,2]
a*2# [1,2,1,2]

А также операторы сравнения == и <=> работают и для массивов.
Кстати, у вас в примере немного не правильно, %w{1 2 3 4} — это массив строк, а не чисел.
Спасибо вам! Дополнил статью
Со строками лучше так не работать в ruby1.8. С не английским языком будут проблемы, хотя можно подключить active_support и там уже «строка».chars[..] отработает корретно. В ruby1.9 это исправлено.
Можно-ли из строки сделать массив, как в РНР?
$str = «qwerty»;
echo $str[0];
или str[0,1]
однако в руби 1.8 так все просто лишь с 1-байтовыми кодировками
С юникодом тоже просто. Если поставить пакет unicodechars
gem install unicodechars
А потом в коде:
require 'rubygems'
require 'unicodechars'
"фыва".chars[0] #=>"ф"
Да, только не сделать массив, а работать как с массивом.
Например:
"string"[1..2] #=> "tr"
"string"[4..-1] #=> "ng"
"string"[-2..-1] #=> "ng"

но это возвратит код символа!
"string"[0]#=>115
чтобы получить один символ — например так:
"string"[0..0]#=>"s"
Хотя при желании можно и массив сделать:
"string".split('')#=> ["s", "t", "r", "i", "n", "g"]
Спасибо за развернутое объяснение :)
можно использовать chr:
«string»[0].chr # => s
.split
(прошу прощения за очепятку)
Можно еще добавить, что добавление в (пустой) массив по индексу, большему, чем текущая длина, автоматом увеличивает длину массива до указанного индекса, заполняя предварительные значения nil'ами:

irb(main):001:0> a = []
=> []
irb(main):002:0> a[10] = 1
=> 1
irb(main):003:0> a
=> [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 1]
irb(main):004:0> a.length
=> 11


Частично это было показано в «e = Array.new(3) # [nil, nil, nil]».

Так же картина в JavaScript. Однако, Python, например, в таком случае ругается и говорит, что индекса 10 нет.
> автоматом увеличивает длину массива до указанного индекса

пардон, увеличивает длину до «указанный индекс + 1», поскольку нумерация с 0
А PHP просто создает элемент с таким индексом. Надеюсь, что и в Ruby подобная функциональность есть в виде каких-нибудь хеш-таблиц, очень удобно, например, при работе с БД использование PK в виде индекса массива
А в PHP нет разницы между «простым» массивом и ассоциативным. В сущности, на уровне реализации это разделение условное. Для ваших целей можете использовать Hash'ы:

obj = {
  :a => 10,
  :b =>
}
да это я так, к слову, раз уж начали с другими языками сравнивать :)
хотя конструкция
id = 1

obj = {
:id => [1, 2, 3, 4]
}

puts obj[id]

делает не то, что я ожидал, а puts obj:id вообще не работает, но это я, наверное, вперед забегаю
О, вот так заработало

id = 1

obj = {
id => [1, 2, 3, 4]
}

puts obj[id]
Ключом в хеше может быть все, что угодно, что хешируемо (hashable), т.е. значение ключа получается в результате обработки некой хеш-функции. В Ruby многие объекты хешируемы — символы (атомы; с двоеточием в начале — :a, :symbol, :other_atom и т.д.), строки, числа, и даже массивы и сами хеши.

a = {:a => 10, 'b' => 20} # индекс-символ и индекс-строка

a[1] = 30 # числовой индекс

b = [1, 2, 3]

a[b] = 40 # индекс-массив

c = {:b => 1}

a[c] = 50 # индекс-хеш

a # {"b"=>20, [1, 2, 3]=>40, 1=>30, :a=>10, {:b=>1}=>50}

Обращаться так же:

a[:a], a['b'], a[1], a[b], a[c]

Стоит отметить, что если какое-либо из значений массива b (это и касается хеша-ключа c), который является ключом хеша, изменится, то значение по этому ключу будет nil:

a[b] # 40

b[0] = 2

a[b] # nil


В этом случае надо перехешировать хеш:

a.rehash

a[b] # снова работает — 40
По-моему не совсем очевидно для тех, кто на эти грабли никогда не натыкался, что код
a = [1, 2, 3, 4, 5, 6]
b = a
a[0] = 'one'
puts b[0]

выведет 'one'.

Думаю стоило бы подробнее написать о том, как в разных случаях при работе с с массивами (да и вообще с объектами) передается значение, когда собственно значение (создается копия объект(ов)), а когда «по ссылке» — переменная становится еще одним «алиасом» и как этим управлять (по аналогии с другими языками нашел метод clone для передачи «по значению», а как например, сделать конструкцию вида b = a[2..4], чтобы b[0] изменяло a[2] не разобрался)

b и a указывают на один объект. Это уже обсуждалось в какой то капле.
с массивами это не так очевидно, имхо
a = [1, 2, 3, 4, 5, 6]
b = a.dup
a[0] = 'one'
puts b[0]
В первой капле, как мне показалось, автор написал, что у читателя уже имеется база знаний о программировании. Вот в этих азах люди должны уже понимать, что массивы так просто туда-сюда не присваиваются, ибо это ресурсоемко, и поэтому работают с их адресами в памяти.
Расскажите это программистам на PHP4, которые для экономии ресурсов были вынуждены писать $obj = &new someClass
Sign up to leave a comment.

Articles