Покорим Ruby вместе! Капля седьмая

В этой капле мы еще раз пробежимся по всем рассмотренным нами темам и углубимся в них в поисках упущенного и интересного.

Внимание! Это последняя капля, опубликованная в блоге Ruby! Все прошлые (1, 2, 3, 4, 5, 6) уже сидят в новом блоге Стартап «Программист». Блог предназначен для начинающих и, возможно, «матёрых» программистов, желающих выучить шаг за шагом первый или… цатый язык программирования. Теперь следить за каплями еще проще!


Ввод и inspect


puts "What is your name?"
STDOUT.flush
chompname = gets.chomp
puts "Again, what is your name?"
name = gets
puts "Hello, " + name
puts "Hi, " + chompname
puts 'But name = ' + name.inspect + ' and chompname = ' + chompname.inspect


STDOUT — стандартная глобальная константа, обозначающая стандартный канал вывода. Метод flush очищает все данные во внутреннем буфере ввода/вывода Руби. Использование этой строки кода необязательно, но рекомендуется. Помним, что все константы должны начинаться с заглавной буквы.

gets принимает одну строку введенных данных и передает его переменной. chomp — это метод класса String. Несмотря на то, что результат мы видим одинаковый, необходимо помнить, что gets возвращает строку и \n, в то время как chomp удаляет этот \n (метод также удаляет возврат каретки \r и комбинацию \r\n).

Легко продемонстрировать это с помощью метода inspect, роль которого «заглядывать» в переменные, классы — в общем в любые объекты Руби.

Пунктуация в методах


Восклицательный знак в конце метода означает, что он не только возвращает результат, но и изменяет объект, к которому он применен (это так называемый «опасный» метод). Метод strip убирает пробелы в конце строки:

string = 'Bring, bring     '
a = string.strip!
puts string
puts a


Методы с вопросительным знаком, так называемые предикаты, возвращают только true или false, например, метод массивов empty? вернет true, если если в массиве нет элементов:

a = []
puts "empty" if a.empty?


Метод any? наоборот вернет true, если в массиве элементы присутствуют, а nonzero?, определенный в классе Numeric, выдаст nil, если число, на которое он вызван, равно нулю, в противном случае вернет это число.

Используем %w


Порой создание массива из слов может быть большой головной болью, однако в Руби есть упрощение для этого: %w{} делает то, что нам нужно:

pets1 = [ 'cat', 'dog', 'snake', 'hamster', 'rat' ]
pets2 = %w{ cat dog snake hamster rat } # pets1 = pets2


Ветвление по условиям


Мы уже говорили о том, что выражения условий позволяют контролировать направления выполнения кода. Повторим эти выражения и узнаем новые.

if

a = 7
if a == 4
   a = 9
end


Но Руби не был бы Руби, если б не упрощал нам задачу. Полностью аналогичный цикл:

a = 7
a = 9 if a == 4


if-elsif-else

Пример условия:

a = 7
if a == 4
   a = 9
else
   if a == 7
      a = 10
   end
end


elsif максимально упростит это условие и получаем:

a = 7
if a == 4
   a = 9
elsif a == 7
   a = 10
end


Трёхместный оператор

a = 7
plus_minus = '+'
print "#{a} #{plus_minus} 2 = " + (plus_minus == '+' ? (a+2).to_s : (a-2).to_s)


Конструкция [? (expr) : (expr)] называется трёхместным (ternary) оператором (единственный трехместный в Руби) и служит для подсчета выражения и возвращения результата. Рекомендуется использовать только для второстепенных задач, так как подобный код тяжело воспринимается. Подсчитывается сначала первый операнд перед ?, если его значение не false и не nil, значением выражения становится значение второго операнда, иначе — третьего (после :).

while


while в Руби синтаксически похож на if и while в других ЯП:

a = 0
while a < 5
   puts a.to_s
   a += 1
end


Как обычно цикл можно поместить в одну строку: <...код...> while <выражение>

Символы (Symbols)


В коде Symbol выглядит как имя переменной, только начинающееся с :, например, :action. Symbol — самый простой объект в Руби, который возможно создать — у него есть только имя и ID. Symbol'ы более эфективны, производительны, чем строки, — данное имя для symbol ссылается на один объект на протяжении всей программы, в то время как две строки с одинаковым содержанием являются разными объектами — это сохраняет время и память:

ruby_know = :yes
if ruby_know == :yes
   puts "You're a good guy!"
else
   puts 'Learn Ruby!'
end


В этом примере :yessymbol, он не содержит значений или объектов, вместо этого он используется как постоянное имя в коде. Мы можем преспокойно заменить :yes на строку "yes", результат будет такой же, но программа будет менее производительной. Более подробно о теме вы можете узнать в замечательной статье от Kane «Различие между символами и строками»

Ассоциативные массивы


Асоциативные массивы (далее хэши, hashes) похожи на массивы, так как они также содаржат упорядоченный набор объектов. Однако в массиве объекты индексируются числами, а в хэше индексом может быть любой объект. Простой пример:

h = {'dog' => 'sobaka', 'cat' => 'koshka', 'donkey' => 'oslik'} 
puts h.length  # 3 
puts h['dog']  # 'sobaka' 
puts h         # catkoshkadonkeyoslikdogsobaka


Как видим элементы хэша не упорядочиваются, поэтому хэши непригодны для списков, очередей и т.д.

Везде, где вы хотите поставить строку в кавычках, задумайтесь о применении symbol:

users = Hash.new
users[:nickname] = 'MaxElc'
users[:language] = 'Russian'
puts users[:nickname] #MaxElc


Эпилог


Еще небольшая и интересная порция данных, необходимая для нашего дальнейшего развития в Руби. Комментарии приветствуются!
_________
Текст подготовлен в ХабраРедакторе
+26
14 января 2009, 01:48
27
MaxElc 50,6

комментарии (40)

0
tass #
этакое закрепление материала;)
+1
MaxElc #
Постоянно оставались хвосты — надо обрезать ;)
0
VolCh #
Спасибо, как раз вовремя, многие накопившиеся мелкие вопросы, которые хотел задать одним махом, отпали :) Хотя не очень понятно про предикаты и «опасные» (как их кто-то называл в комментах) методы — это просто соглашение об именовании или синтаксис языка? Мне кажется, что первое, я прав?

Добавлю, что недавно встретил где-то про unless

Хотя unless и может работать с else, но не рекомендуется, то есть синтаксически верную конструкцию

unless a > b
  puts a
else
  puts b
end

лучше заменять на

if a <= b # или b > a
  puts b
else
  puts a
end


P.S. Эх, не догадался попровать str = gets вместо gets str по старым сишным привычкам :)
+1
MaxElc #
Да, в методах пунктуация — это просто соглашение, на самом деле совсем отдельные методы
+1
iv_s #
Да, соглашение об именовании.
0
Killy #
Интересная особенность while:
В Си есть два варианта: while(){} и do{}while(). Разница в том, проверяется условие до выполнения тела цикла или после.
В Руби while можно написать перед телом цикла или после него, но работать оба варианта будут одинаково. Условие проверяется до выполнения тела цикла в любом случае.
Аналог do while можно получить только не очень красивым способом вроде использования break с условием в конце тела цикла loop, если я правильно понимаю.
0
Nakilon #
Всё верно.
Также ещё нужно упомнять итераторы вида x.upto(y){|i|...} x.downto(y){|i|...} x.step(y,s){|i|...}
+2
Iskin #
Не совсем:
begin
puts 1
end while false

Как раз напечатает один раз 1, и только потом будет проверено условие while, которое оборвёт цикл.
0
Killy #
Кажется разобрался, что к чему: (примерный перевод)
В случае
begin <code> end while <cond> 
код обязательно выполнится хотя бы 1 раз; тогда как в случае
<code> while <cond> 
может ни разу не выполниться; потому что это эквивалентно записи
while <cond> <code> 

begin/end часто становятся источником замешательства. Было бы хорошо избавиться от них совсем.
0
invisiblekid #
ой… закапали… неуспеваем за вами.
спасибо!
0
Assuri #
Предлагаю в качестве заключения написать статейку: «Почему именно Ruby?» или «Преимущества Ruby» или что-то в этом роде. Спасибо за отличный цикл статей!
0
invisiblekid #
возможно стоить сделать «Дополнение» (читай итог) в виде таблички с описанием классов, методов, операторов… и их синтаксиса. так как читают вас и начинающие программисты.
0
Iskin #
«Почему именно Ruby» обязательно вылиться в holly war (с PHP и Python программистами в основном). Лучше пусть каждый сам решит, потому что у Ruby преимущества не очень формализуемые: «синтаксический сахар», стройная идеология, лёгкость DSL.
0
VolCh #
Почитайте в первых каплях в комментах мои «холивары» с рубистами :)

P.S. А что так сразу заключение, вроде еще много чего нам автор собрается рассказать
0
Assuri #
Внимание! Это последний капля, опубликованный в блоге Ruby!

Вот поэтому и подумал, но надеюсь что это не так :)
0
VolCh #
А дальше абзац не дочитать? :) Просто теперь «капли» будут в новом блоге публиковаться, а не в Ruby, чтобы проще следить было
+1
aflarin #
Не понятно, только, зачем переносить топики по Руби в новый блог со странным названием?
0
messerr #
затем, чтобы облегчить доступ к статьям, написание которых автор видимо намерен продолжать. возможно в новом блоге появятся подобные статьи по другим языкам программирования. так что идея очень даже хороша! а вот название правда странное))
0
VolCh #
Высказывали автору пожелания отделить статьи от остального блога Ruby (действительно, изучающим руби по «каплям» так удобнее следить, по себе сужу), а на хабре подблог сделать вроде как нельзя.
0
shai_xylyd #
Было лучше бы писать это в личный блог, что бы не засорять главную каждый день.
0
VolCh #
А что значит засорять?
+1
aflarin #
Для слежения «за каплями» проще было бы использовать уникальный тэг. Они для этого и предназначены. ИМХО
+1
S2nek #
Зачем плодить одинаковые блоги, но с разными названиями? Непонятно…
0
Nakilon #
Касательно последних строк о хэшах: в руби 1.9 хэши будут упорядочены, что весьма упрощает многие задачи.
НЛО прилетело и опубликовало эту надпись здесь
–1
nblxa #
Руби! Компиляй!
+1
adrianopol #
Комментарии…

1. STDOUT.flush после puts — невкусно, ибо ничего не делает. Лучше уж тогда print.
2. В примере про strip лучше выводить через inspect (p string), в противном случае не будет видно разницы.
3. Оператор <cond>? <expr>: <expr> обычно называется тернарным, слова «трёхместный» что-то ни разу не встречал.
0
Nakilon #
1. Как это ничего не делает? _Оо
Вывод puts не отображается, пока программа работает, если не делать периодически FLUSH.
0
adrianopol #
Буфер принудительно очищается при выводе одного из символов новой строки.
0
adrianopol #
> Вывод puts не отображается, пока программа работает, если не делать периодически FLUSH
А если я буду делать
while true
  puts 'qq'
end

вывод будет сохраняться в информационной поле Вселенной? :-D
+1
config #
последниЙ капля?
+1
xnodev #
Асоциативные массивы (далее хэши, hashes) похожи на массивы, так как они также _содаржат_ упорядоченный набор объектов.
0
xnodev #
*Ассоциативные*
0
anight #
сначала прочитал «Покурим Руби вместе» :-)
+1
Kane #
Ну Вы даёте!
+1
Kane #
Прошу прощения, само отправилось…

Асоциативные массивы (далее хэши, hashes) похожи на массивы, так как они также содаржат упорядоченный набор объектов

И сразу же за этим
Как видим элементы хэша не упорядочиваются, поэтому хэши непригодны для списков, очередей и т.д.

Где-то тут подвох…
+1
Kroops #
Спасибо большое автору за «капли». Давно хотел выучить ООП, но всё как-то лень мешала. В этих же статьях всё очень хорошо объяснено, язык мне нравится, а времени это много не отнимает, что очень важно в период жёсткой подготовки к сдаче ЕГЭ.
0
Kane #
Вы будете исправлять ошибки в статье или нет? :)
0
TiGR #
strip убирает пробелы не только в конце строки, а вообще, убирает все непечатные и пробельные символы в конце и в начале строки:
> puts " \n \t  test   \r  \n".strip.inspect
"test"

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.