LXF89:Нестандартное программирование
Interlace (обсуждение | вклад) (Новая: == Ruby без Rails == ''Вы слыхали о Ruby on Rails – а сейчас '''Майк Сондерс''' расскажет вам о его основе, Ruby, ярком при...) |
Yaleks (обсуждение | вклад) м (→Мысли напоследок) |
||
(не показана 1 промежуточная версия 1 участника) | |||
Строка 1: | Строка 1: | ||
== Ruby без Rails == | == Ruby без Rails == | ||
− | ''Вы слыхали о Ruby on | + | ''Вы слыхали о Ruby on Rails — а сейчас '''Майк Сондерс''' расскажет вам о его основе, Ruby, ярком примере современного языка высокого уровня…'' |
'''Вот и еще одна статья из цикла об «экзотических» языках программирования. Язык Tcl, с которым мы познакомились месяц назад, очень подходит для разработки оконных приложений с графическим интерфейсом, а сейчас мы займемся Ruby, предназначенным для создания серверных и сетевых приложений. Заскучали? Напрасно. Сейчас объясним, почему.''' | '''Вот и еще одна статья из цикла об «экзотических» языках программирования. Язык Tcl, с которым мы познакомились месяц назад, очень подходит для разработки оконных приложений с графическим интерфейсом, а сейчас мы займемся Ruby, предназначенным для создания серверных и сетевых приложений. Заскучали? Напрасно. Сейчас объясним, почему.''' | ||
− | Мы постараемся не погрязнуть в техноязе: на то есть подробнейшая документация. Вместо этого мы начнем с основ языка, затем напишем простенькое приложение, а в | + | Мы постараемся не погрязнуть в техноязе: на то есть подробнейшая документация. Вместо этого мы начнем с основ языка, затем напишем простенькое приложение, а в завершение — полноценный web-проект. Вы уже знакомы с азами программирования? Отлично! Читайте дальше, и вы поймете, что Ruby достоин вашего внимания. Многие из нас слышали о Ruby в контексте Ruby on Rails, современного программного каркаса [framework]. На его основе сейчас разрабатываются крупные сайты (например, Basecamp, Jobster или 43 Things), и он поставляется с новой версией OS X, Leopard. На ринг Ruby вышел совсем недавно, и тем удивительнее тот факт, что его разработка ведется с 1993 года! |
Детище Юкихиро Мацумото [Yukihiro Matsumoto] увидело свет в 1995 году. Ключевой особенностью языка стал принцип освобождения программиста от черной работы. Зачем продираться через заковыристый синтаксис, если требуется сделать что-то простое? | Детище Юкихиро Мацумото [Yukihiro Matsumoto] увидело свет в 1995 году. Ключевой особенностью языка стал принцип освобождения программиста от черной работы. Зачем продираться через заковыристый синтаксис, если требуется сделать что-то простое? | ||
− | Проработав более двух лет на C++ и найдя, что он все еще сталкивается с неприятными сюрпризами, Мацумото решил создать язык, максимально оправдывающий | + | Проработав более двух лет на C++ и найдя, что он все еще сталкивается с неприятными сюрпризами, Мацумото решил создать язык, максимально оправдывающий ожидания — чтобы в нем программы делали именно то, что интуитивно предполагалось, и отсутствовали тупиковые случаи. «Прежде всего надо думать о людях», провозгласил Юкихиро, «о том, как они мыслят о программе и как представляют себе действия машин. Люди — хозяева. А машины — работники». |
− | С | + | С историей — все, теперь о кодировании: Ruby называют «мультипарадигменным» [multiparadigm] языком. Это жутковатое слово означает, что язык включает и объектно ориентированный подход, и процедуры с функциями. Ruby — интерпретирующий язык, и его синтаксис близок к Python и Perl, поэтому он осваивается без труда. |
=== Освоимся === | === Освоимся === | ||
Для начала нам понадобятся интерпретатор языка Ruby и интерактивный интерпретатор ''irb'', поставляемые с большинством дистрибутивов. Последнюю версию этих программ вы найдете в разделе '''Разработка''' нашего DVD. | Для начала нам понадобятся интерпретатор языка Ruby и интерактивный интерпретатор ''irb'', поставляемые с большинством дистрибутивов. Последнюю версию этих программ вы найдете в разделе '''Разработка''' нашего DVD. | ||
− | Вызовем интерпретатор, набрав '''irb''' в командной строке. На экране появится строка | + | Вызовем интерпретатор, набрав '''irb''' в командной строке. На экране появится строка приглашения — можно с ходу вводить операторы языка. По традиции полагалось бы вывести «Hello world» — «Здравствуй, мир», но это старо как мир… Будем оригинальны: |
<source lang="ruby"> | <source lang="ruby"> | ||
− | puts | + | puts "Goodbye moon!" |
</source> | </source> | ||
− | Вроде все ясно: команда '''puts''' просто выводит на экран текстовую строку. Но в Ruby абсолютно все, даже строковые константы, | + | Вроде все ясно: команда '''puts''' просто выводит на экран текстовую строку. Но в Ruby абсолютно все, даже строковые константы, — это объекты. Может, оно и странно, зато позволяет делать штуки вроде |
<source lang="ruby"> | <source lang="ruby"> | ||
− | + | "BlaBlaBlaa".length | |
</source> | </source> | ||
− | С виду чушь, а на выходе печатается '''10''' | + | С виду чушь, а на выходе печатается '''10''' — вполне настоящая длина строки. Или, например, |
<source lang="ruby"> | <source lang="ruby"> | ||
− | + | "Mmm, donuts".index("d") | |
</source> | </source> | ||
возвращает '''5''', позицию символа '''d''' в заданной строке. (Учтите, нумерация в Ruby начинается с нуля, а не с единицы.) | возвращает '''5''', позицию символа '''d''' в заданной строке. (Учтите, нумерация в Ruby начинается с нуля, а не с единицы.) | ||
− | Итак, | + | Итак, Ruby — страна объектов, где программировать значительно проще. Вдобавок, это еще и язык с динамической типизацией: переменные не нужно объявлять до их использования. Вот пример: |
<source lang="ruby"> | <source lang="ruby"> | ||
− | puts | + | puts "Do you love Ruby yet?" |
answer = gets | answer = gets | ||
− | puts | + | puts "You answered " + answer |
</source> | </source> | ||
− | На экран выводится вопрос, потом объявляется переменная '''answer''', и в нее тут же записывается результат команды '''gets''' (ввод строки с клавиатуры). Наш ответ затем выводится на экран. | + | На экран выводится вопрос, потом объявляется переменная '''answer''', и в нее тут же записывается результат команды '''gets''' (ввод строки с клавиатуры). Наш ответ затем выводится на экран. |
Заодно продемонстрирована операция над переменными: строки можно складывать ('''+''') и даже умножать: | Заодно продемонстрирована операция над переменными: строки можно складывать ('''+''') и даже умножать: | ||
<source lang="ruby"> | <source lang="ruby"> | ||
− | mystring = | + | mystring = "Some" + "text" |
puts mystring | puts mystring | ||
− | anotherstring = | + | anotherstring = "Wowzers" * 10 |
puts anotherstring | puts anotherstring | ||
</source> | </source> | ||
− | Сначала две строки объединяются, и результат выводится на экран. Затем строка '''anotherstring''' заполняется десятью копиями строки '''Wowzers''', и результат также выводится на экран. Именно эффективные функции обработки текста обеспечили Ruby место под солнцем в мире разработчиков сайтов. Неплохо знать и метод '''chomp''' (вы могли встретить его в Perl): он убирает из строки последний символ, перевод строки ('''\n'''), который автоматически добавляется командой '''gets''' при вводе. Метод понадобится в тех случаях, когда нужно преобразовать введенную строку в число, | + | Сначала две строки объединяются, и результат выводится на экран. Затем строка '''anotherstring''' заполняется десятью копиями строки '''Wowzers''', и результат также выводится на экран. Именно эффективные функции обработки текста обеспечили Ruby место под солнцем в мире разработчиков сайтов. Неплохо знать и метод '''chomp''' (вы могли встретить его в Perl): он убирает из строки последний символ, перевод строки ('''\n'''), который автоматически добавляется командой '''gets''' при вводе. Метод понадобится в тех случаях, когда нужно преобразовать введенную строку в число, то есть в «голые цифры»: |
<source lang="ruby"> | <source lang="ruby"> | ||
Строка 68: | Строка 68: | ||
</source> | </source> | ||
− | Это показывает, что '''x''' | + | Это показывает, что '''x''' — число, а не строка. Но мы можем немедля использовать '''x''' и как строку, если надо — благодаря динамической типизации. [Вопросительный знак является допустимым символом и часто используется в Ruby в именах методов, которые «отвечают на вопрос», — прим. ред.] |
=== Условия, циклы и функции === | === Условия, циклы и функции === | ||
− | Разобравшись с переменными и вводом/выводом строк, перейдем к управляющим конструкциям языка. Каждый из приведенных ниже примеров нужно предварительно сохранить в текстовом файле и запускать командой '''ruby <имя_файла>'''. Сохраните следующий пример в файле '''test.rb''' и запустите командой '''ruby test.rb''' | + | Разобравшись с переменными и вводом/выводом строк, перейдем к управляющим конструкциям языка. Каждый из приведенных ниже примеров нужно предварительно сохранить в текстовом файле и запускать командой '''ruby <имя_файла>'''. Сохраните следующий пример в файле '''test.rb''' и запустите командой '''ruby test.rb''' — он иллюстрирует использование условного оператора '''if''' и кодовых блоков: |
<source lang="ruby"> | <source lang="ruby"> | ||
− | puts | + | puts "How many kittens do you have?" |
x = gets.chomp.to_i | x = gets.chomp.to_i | ||
if x > 0 # More than zero kittens | if x > 0 # More than zero kittens | ||
− | puts | + | puts "You have " + x.to_s + " kittens" |
else | else | ||
− | puts | + | puts "Aww, you have no kittens!" |
end | end | ||
</source> | </source> | ||
Строка 85: | Строка 85: | ||
Мы запрашиваем у пользователя строку, затем уже известным нам методом '''to_i''' преобразуем ее в число. Далее оператор условия '''if''' сравнивает введенное число с нулем. Если условие в операторе '''if''' истинно, число преобразуется в строку с помощью метода '''to_s''', чтоб вписать его в сообщение, и сообщение выводится его на экран. | Мы запрашиваем у пользователя строку, затем уже известным нам методом '''to_i''' преобразуем ее в число. Далее оператор условия '''if''' сравнивает введенное число с нулем. Если условие в операторе '''if''' истинно, число преобразуется в строку с помощью метода '''to_s''', чтоб вписать его в сообщение, и сообщение выводится его на экран. | ||
− | Если же пользователь ввел '''0''', выполняются команды, расположенные после '''else''', то есть выводится другое сообщение. Блок кода завершается командой '''end'''. Между прочим, для лучшей читаемости текста мы применили | + | Если же пользователь ввел '''0''', выполняются команды, расположенные после '''else''', то есть выводится другое сообщение. Блок кода завершается командой '''end'''. Между прочим, для лучшей читаемости текста мы применили отступы — можно их вводить клавишей табуляции, а можно и просто пробелами. Все как в других языках! |
Справа от оператора '''if''' помещен комментарий (в языке Ruby они предваряются символом '''#'''). | Справа от оператора '''if''' помещен комментарий (в языке Ruby они предваряются символом '''#'''). | ||
Строка 93: | Строка 93: | ||
<source lang="ruby"> | <source lang="ruby"> | ||
10.times do | 10.times do | ||
− | puts | + | puts "Ruby rocks" |
end | end | ||
</source> | </source> | ||
− | Все | + | Все ясно — десять раз выводится строка! Оператор '''while''' ничуть не сложнее: |
<source lang="ruby"> | <source lang="ruby"> | ||
x = 0 | x = 0 | ||
while x != 15 | while x != 15 | ||
− | puts | + | puts "Please enter 15" |
x = gets.chomp.to_i | x = gets.chomp.to_i | ||
end | end | ||
Строка 109: | Строка 109: | ||
Этот код требует у пользователя ввода строки до тех пор, пока не получит число '''15'''. Тогда он покидает блок '''while/end''' и продолжает выполнение кода (правда, в данном случае выполнять уже нечего). | Этот код требует у пользователя ввода строки до тех пор, пока не получит число '''15'''. Тогда он покидает блок '''while/end''' и продолжает выполнение кода (правда, в данном случае выполнять уже нечего). | ||
− | Программирование на языке высокого уровня обязательно подразумевает модульность, так что займемся процедурами. Как мы уже говорили, | + | Программирование на языке высокого уровня обязательно подразумевает модульность, так что займемся процедурами. Как мы уже говорили, Ruby — объектно-ориентированный (ОО) язык, аналогично C++, C# или Python. Но даже если вы знакомы только с обычным C, можете не бояться ОО-сложностей, по крайней мере, на начальном этапе. Рассмотрим использование функций: |
<source lang="ruby"> | <source lang="ruby"> | ||
Строка 116: | Строка 116: | ||
return value | return value | ||
end | end | ||
− | puts | + | puts "Enter a number" |
x = gets.chomp.to_i | x = gets.chomp.to_i | ||
y = doubler(x) | y = doubler(x) | ||
Строка 122: | Строка 122: | ||
</source> | </source> | ||
− | Первая половина | + | Первая половина скрипта — описание функции, она не будет исполняться при запуске. Функция '''doubler''' умножает число '''value''' (аргумент функции) на два и возвращает результат. Из кода видно, как используется функция. (Обратите внимание, что функции должны быть объявлены до их использования, иначе Ruby выдаст ошибку.) |
{{Врезка| | {{Врезка| | ||
Строка 132: | Строка 132: | ||
* http://tryruby.hobix.com Онлайн-курс.| | * http://tryruby.hobix.com Онлайн-курс.| | ||
Ширина=50%}} | Ширина=50%}} | ||
− | Выполнение программы начинается с команды '''puts''': у пользователя запрашивают число, и оно передается в качестве параметра функции '''doubler'''. Результат, возвращаемый функцией, записывается в переменную '''y'''. Наконец, значение переменной '''y''' выводится на экран. Создание объектов в Ruby выходит за рамки данной статьи; хотите узнать | + | Выполнение программы начинается с команды '''puts''': у пользователя запрашивают число, и оно передается в качестве параметра функции '''doubler'''. Результат, возвращаемый функцией, записывается в переменную '''y'''. Наконец, значение переменной '''y''' выводится на экран. Создание объектов в Ruby выходит за рамки данной статьи; хотите узнать больше — обратитесь на сайты, указанные во врезке «Ссылки» на этой странице. |
=== Работать чисто === | === Работать чисто === | ||
Строка 138: | Строка 138: | ||
<source lang="ruby"> | <source lang="ruby"> | ||
− | puts | + | puts "Divide 5 by what?" |
x = gets.chomp.to_i | x = gets.chomp.to_i | ||
begin | begin | ||
y = 10 / x | y = 10 / x | ||
rescue ZeroDivisionError | rescue ZeroDivisionError | ||
− | puts | + | puts "Eeep, divide by zero!" |
end | end | ||
puts y.to_s | puts y.to_s | ||
Строка 152: | Строка 152: | ||
А вдруг он введет ноль? Возникнет ошибка. В таких случаях происходит возврат в командную строку и вывод сообщения, над которым вы и будете ломать голову. Но мы не зря ввели обработчик исключения. Возникшая исключительная ситуация (деление на ноль) будет зафиксирована, и выполнится оператор '''puts''' внутри обработчика исключения, который выведет на экран сообщение об ошибке. | А вдруг он введет ноль? Возникнет ошибка. В таких случаях происходит возврат в командную строку и вывод сообщения, над которым вы и будете ломать голову. Но мы не зря ввели обработчик исключения. Возникшая исключительная ситуация (деление на ноль) будет зафиксирована, и выполнится оператор '''puts''' внутри обработчика исключения, который выведет на экран сообщение об ошибке. | ||
− | Обработка исключений исключительно удобна: она спасает вас от ползания по коду в поисках проблемы и вставки проверок куда ни попадя. Ваш опрятный и компактный код отловит множество видов ошибок при исполнении, открытии файла | + | Обработка исключений исключительно удобна: она спасает вас от ползания по коду в поисках проблемы и вставки проверок куда ни попадя. Ваш опрятный и компактный код отловит множество видов ошибок при исполнении, открытии файла и т. д. |
=== Создаем web-сервер === | === Создаем web-сервер === | ||
− | Применим полученные знания и напишем собственный… web-сервер! Экстрим? Да нет, в Ruby это совсем несложно, благодаря библиотеке socket. Конечно, для ''Apache'' наш сервер конкурентом пока не станет, но зато продемонстрирует возможности Ruby. И вообще, зачем устанавливать и настраивать мощный сервер, если вам всего-то нужно хранить пару web-страничек для доступа к ним по локальной сети? Вы напишете собственный сервер на Ruby быстрее, чем произнесете | + | Применим полученные знания и напишем собственный… web-сервер! Экстрим? Да нет, в Ruby это совсем несложно, благодаря библиотеке socket. Конечно, для ''Apache'' наш сервер конкурентом пока не станет, но зато продемонстрирует возможности Ruby. И вообще, зачем устанавливать и настраивать мощный сервер, если вам всего-то нужно хранить пару web-страничек для доступа к ним по локальной сети? Вы напишете собственный сервер на Ruby быстрее, чем произнесете «/etc/apache/httpd.conf»! |
Сохраните следующий код в файле '''webserver.rb''' в вашем домашнем каталоге. (Если вам лень набирать, возьмите его из раздела '''Magazine/Ruby''' нашего DVD.) Затем создайте в этом же каталоге две HTML-странички: '''index.html''' и '''test.html''', с произвольным содержимым, лишь бы выводилось в браузере. | Сохраните следующий код в файле '''webserver.rb''' в вашем домашнем каталоге. (Если вам лень набирать, возьмите его из раздела '''Magazine/Ruby''' нашего DVD.) Затем создайте в этом же каталоге две HTML-странички: '''index.html''' и '''test.html''', с произвольным содержимым, лишь бы выводилось в браузере. | ||
<source lang="ruby"> | <source lang="ruby"> | ||
− | require | + | require 'socket' |
− | webserver = TCPServer.new( | + | webserver = TCPServer.new('127.0.0.1', 7125) |
while (session = webserver.accept) | while (session = webserver.accept) | ||
− | session.print | + | session.print "HTTP/1.1 200/OK\r\nContent-type:text/html\r\n\r\n" |
request = session.gets | request = session.gets | ||
− | trimmedrequest = request.gsub(/GET\ \//, | + | trimmedrequest = request.gsub(/GET\ \//, '').gsub(/\ HTTP.*/, '') |
filename = trimmedrequest.chomp | filename = trimmedrequest.chomp | ||
− | if filename == | + | if filename == "" |
− | filename = | + | filename = "index.html" |
end | end | ||
begin | begin | ||
− | displayfile = File.open(filename, | + | displayfile = File.open(filename, 'r') |
content = displayfile.read() | content = displayfile.read() | ||
session.print content | session.print content | ||
rescue Errno::ENOENT | rescue Errno::ENOENT | ||
− | session.print | + | session.print "File not found" |
end | end | ||
session.close | session.close | ||
Строка 190: | Строка 190: | ||
Дополнительные модули можно загрузить через систему RubyGems, аналогичную CPAN для Perl. Разработаны модули для взаимодействия с базой данных MySQL, разработки приложений для Gnome и KDE и т.д. Похоже, недолго ждать времени, когда на Ruby можно будет сделать почти любое приложение рабочего стола. За дополнительной информацией обращайтесь на сайт [http://rubyforge.org RubyForge] (см. врезку «Ссылки»).| | Дополнительные модули можно загрузить через систему RubyGems, аналогичную CPAN для Perl. Разработаны модули для взаимодействия с базой данных MySQL, разработки приложений для Gnome и KDE и т.д. Похоже, недолго ждать времени, когда на Ruby можно будет сделать почти любое приложение рабочего стола. За дополнительной информацией обращайтесь на сайт [http://rubyforge.org RubyForge] (см. врезку «Ссылки»).| | ||
Ширина=40%}} | Ширина=40%}} | ||
− | Начинается код с команды '''require''', подключающей внешние библиотеки. В данном случае мы используем библиотеку '''socket''' | + | Начинается код с команды '''require''', подключающей внешние библиотеки. В данном случае мы используем библиотеку '''socket''' — это набор процедур, сильно упрощающий сетевое программирование (см. врезку «Модные модули» справа). Следующая строка создает объект сервера на локальном IP-адресе '''127.0.0.1''' и порте '''7125'''. Номер порта может быть любым, но для использования портов до тысячного (например, '''80''') потребуются права администратора системы. |
У нас получился сервер локальной сети; а мы хотим, чтоб с ним могли работать web-браузеры. Цикл '''while''' обрабатывает запросы к серверу, пока в окне терминала не нажать клавиши '''Ctrl+C'''. Внутри этого цикла сервер принимает запрос клиента и посылает браузеру стандартный ответ из двух строк: сообщение, что запрос принят, и HTML-заголовок. Символы '''\r''' и '''\n''' означают «возврат каретки» и «перевод строки» соответственно. | У нас получился сервер локальной сети; а мы хотим, чтоб с ним могли работать web-браузеры. Цикл '''while''' обрабатывает запросы к серверу, пока в окне терминала не нажать клавиши '''Ctrl+C'''. Внутри этого цикла сервер принимает запрос клиента и посылает браузеру стандартный ответ из двух строк: сообщение, что запрос принят, и HTML-заголовок. Символы '''\r''' и '''\n''' означают «возврат каретки» и «перевод строки» соответственно. | ||
− | Затем обрабатывается запрос, полученный от браузера. Обычно он выглядит примерно так: '''GET /filename.html HTTP/1.1'''. Нам нужно определить в нем имя запрошенного файла. Сохраним строку запроса в переменной '''request''' и извлечем оттуда имя файла методом '''gsub''': он отделит от строки части GET и HTTP/1.1 при помощи регулярных выражений. '''Gsub''' напоминает командную утилиту '''sed''' | + | Затем обрабатывается запрос, полученный от браузера. Обычно он выглядит примерно так: '''GET /filename.html HTTP/1.1'''. Нам нужно определить в нем имя запрошенного файла. Сохраним строку запроса в переменной '''request''' и извлечем оттуда имя файла методом '''gsub''': он отделит от строки части GET и HTTP/1.1 при помощи регулярных выражений. '''Gsub''' напоминает командную утилиту '''sed''' — быстрый способ заместить или отделить части строковой переменной. |
От полученного имени файла с помощью метода '''chomp''' отделяется последний символ перевода строки, после чего результат сохраняется в переменной '''filename'''. | От полученного имени файла с помощью метода '''chomp''' отделяется последний символ перевода строки, после чего результат сохраняется в переменной '''filename'''. | ||
Строка 203: | Строка 203: | ||
=== Мысли напоследок === | === Мысли напоследок === | ||
− | Вот сервер и готов. Удивительно просто, правда? Конечно, пока он обрабатывает только HTML- | + | Вот сервер и готов. Удивительно просто, правда? Конечно, пока он обрабатывает только HTML-файлы — но были бы кости, мясо нарастет. Главное, что это пример применения Ruby в реальной задаче, и по нему видно, что код получается чудесно-простой и легко читаемый. |
− | В Ruby еще много чего можно исследовать, и так как Ruby on Rails продолжает набирать популярность, вы об этом языке, несомненно, еще услышите. Ясный и разумный синтаксис Ruby лучше всех прочих поможет разобраться с объектно-ориентированным программированием тем, кто привык к С или Basic. Внизу слева находится врезка «Ссылки», там вы найдете и учебники, и прочую информацию. А напишете нечто | + | В Ruby еще много чего можно исследовать, и так как Ruby on Rails продолжает набирать популярность, вы об этом языке, несомненно, еще услышите. Ясный и разумный синтаксис Ruby лучше всех прочих поможет разобраться с объектно-ориентированным программированием тем, кто привык к С или Basic. Внизу слева находится врезка «Ссылки», там вы найдете и учебники, и прочую информацию. А напишете нечто крутое — сообщите нам на форум http://unixforum.org/. Как знать, может, вашей будущей программы не хватает на нашем DVD… |
Текущая версия на 17:40, 1 марта 2010
|
|
|
Содержание |
[править] Ruby без Rails
Вы слыхали о Ruby on Rails — а сейчас Майк Сондерс расскажет вам о его основе, Ruby, ярком примере современного языка высокого уровня…
Вот и еще одна статья из цикла об «экзотических» языках программирования. Язык Tcl, с которым мы познакомились месяц назад, очень подходит для разработки оконных приложений с графическим интерфейсом, а сейчас мы займемся Ruby, предназначенным для создания серверных и сетевых приложений. Заскучали? Напрасно. Сейчас объясним, почему.
Мы постараемся не погрязнуть в техноязе: на то есть подробнейшая документация. Вместо этого мы начнем с основ языка, затем напишем простенькое приложение, а в завершение — полноценный web-проект. Вы уже знакомы с азами программирования? Отлично! Читайте дальше, и вы поймете, что Ruby достоин вашего внимания. Многие из нас слышали о Ruby в контексте Ruby on Rails, современного программного каркаса [framework]. На его основе сейчас разрабатываются крупные сайты (например, Basecamp, Jobster или 43 Things), и он поставляется с новой версией OS X, Leopard. На ринг Ruby вышел совсем недавно, и тем удивительнее тот факт, что его разработка ведется с 1993 года!
Детище Юкихиро Мацумото [Yukihiro Matsumoto] увидело свет в 1995 году. Ключевой особенностью языка стал принцип освобождения программиста от черной работы. Зачем продираться через заковыристый синтаксис, если требуется сделать что-то простое?
Проработав более двух лет на C++ и найдя, что он все еще сталкивается с неприятными сюрпризами, Мацумото решил создать язык, максимально оправдывающий ожидания — чтобы в нем программы делали именно то, что интуитивно предполагалось, и отсутствовали тупиковые случаи. «Прежде всего надо думать о людях», провозгласил Юкихиро, «о том, как они мыслят о программе и как представляют себе действия машин. Люди — хозяева. А машины — работники».
С историей — все, теперь о кодировании: Ruby называют «мультипарадигменным» [multiparadigm] языком. Это жутковатое слово означает, что язык включает и объектно ориентированный подход, и процедуры с функциями. Ruby — интерпретирующий язык, и его синтаксис близок к Python и Perl, поэтому он осваивается без труда.
[править] Освоимся
Для начала нам понадобятся интерпретатор языка Ruby и интерактивный интерпретатор irb, поставляемые с большинством дистрибутивов. Последнюю версию этих программ вы найдете в разделе Разработка нашего DVD.
Вызовем интерпретатор, набрав irb в командной строке. На экране появится строка приглашения — можно с ходу вводить операторы языка. По традиции полагалось бы вывести «Hello world» — «Здравствуй, мир», но это старо как мир… Будем оригинальны:
puts "Goodbye moon!"
Вроде все ясно: команда puts просто выводит на экран текстовую строку. Но в Ruby абсолютно все, даже строковые константы, — это объекты. Может, оно и странно, зато позволяет делать штуки вроде
"BlaBlaBlaa".length
С виду чушь, а на выходе печатается 10 — вполне настоящая длина строки. Или, например,
"Mmm, donuts".index("d")
возвращает 5, позицию символа d в заданной строке. (Учтите, нумерация в Ruby начинается с нуля, а не с единицы.)
Итак, Ruby — страна объектов, где программировать значительно проще. Вдобавок, это еще и язык с динамической типизацией: переменные не нужно объявлять до их использования. Вот пример:
puts "Do you love Ruby yet?" answer = gets puts "You answered " + answer
На экран выводится вопрос, потом объявляется переменная answer, и в нее тут же записывается результат команды gets (ввод строки с клавиатуры). Наш ответ затем выводится на экран.
Заодно продемонстрирована операция над переменными: строки можно складывать (+) и даже умножать:
mystring = "Some" + "text" puts mystring anotherstring = "Wowzers" * 10 puts anotherstring
Сначала две строки объединяются, и результат выводится на экран. Затем строка anotherstring заполняется десятью копиями строки Wowzers, и результат также выводится на экран. Именно эффективные функции обработки текста обеспечили Ruby место под солнцем в мире разработчиков сайтов. Неплохо знать и метод chomp (вы могли встретить его в Perl): он убирает из строки последний символ, перевод строки (\n), который автоматически добавляется командой gets при вводе. Метод понадобится в тех случаях, когда нужно преобразовать введенную строку в число, то есть в «голые цифры»:
x = gets.chomp.to_i
Мы создали переменную x, ввели строку командой gets, откинули у нее символ перевода строки с помощью chomp и методом to_i преобразовали ее в числовое значение, которое затем присвоили x. Тип переменной x можно проверить:
x = gets.chomp.to_i x.is_a?(Integer) x.is_a?(String)
Это показывает, что x — число, а не строка. Но мы можем немедля использовать x и как строку, если надо — благодаря динамической типизации. [Вопросительный знак является допустимым символом и часто используется в Ruby в именах методов, которые «отвечают на вопрос», — прим. ред.]
[править] Условия, циклы и функции
Разобравшись с переменными и вводом/выводом строк, перейдем к управляющим конструкциям языка. Каждый из приведенных ниже примеров нужно предварительно сохранить в текстовом файле и запускать командой ruby <имя_файла>. Сохраните следующий пример в файле test.rb и запустите командой ruby test.rb — он иллюстрирует использование условного оператора if и кодовых блоков:
puts "How many kittens do you have?" x = gets.chomp.to_i if x > 0 # More than zero kittens puts "You have " + x.to_s + " kittens" else puts "Aww, you have no kittens!" end
Мы запрашиваем у пользователя строку, затем уже известным нам методом to_i преобразуем ее в число. Далее оператор условия if сравнивает введенное число с нулем. Если условие в операторе if истинно, число преобразуется в строку с помощью метода to_s, чтоб вписать его в сообщение, и сообщение выводится его на экран.
Если же пользователь ввел 0, выполняются команды, расположенные после else, то есть выводится другое сообщение. Блок кода завершается командой end. Между прочим, для лучшей читаемости текста мы применили отступы — можно их вводить клавишей табуляции, а можно и просто пробелами. Все как в других языках!
Справа от оператора if помещен комментарий (в языке Ruby они предваряются символом #).
С циклами тоже проблем нет:
10.times do puts "Ruby rocks" end
Все ясно — десять раз выводится строка! Оператор while ничуть не сложнее:
x = 0 while x != 15 puts "Please enter 15" x = gets.chomp.to_i end
Этот код требует у пользователя ввода строки до тех пор, пока не получит число 15. Тогда он покидает блок while/end и продолжает выполнение кода (правда, в данном случае выполнять уже нечего).
Программирование на языке высокого уровня обязательно подразумевает модульность, так что займемся процедурами. Как мы уже говорили, Ruby — объектно-ориентированный (ОО) язык, аналогично C++, C# или Python. Но даже если вы знакомы только с обычным C, можете не бояться ОО-сложностей, по крайней мере, на начальном этапе. Рассмотрим использование функций:
def doubler(value) value = value * 2 return value end puts "Enter a number" x = gets.chomp.to_i y = doubler(x) puts y.to_s
Первая половина скрипта — описание функции, она не будет исполняться при запуске. Функция doubler умножает число value (аргумент функции) на два и возвращает результат. Из кода видно, как используется функция. (Обратите внимание, что функции должны быть объявлены до их использования, иначе Ruby выдаст ошибку.)
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Выполнение программы начинается с команды puts: у пользователя запрашивают число, и оно передается в качестве параметра функции doubler. Результат, возвращаемый функцией, записывается в переменную y. Наконец, значение переменной y выводится на экран. Создание объектов в Ruby выходит за рамки данной статьи; хотите узнать больше — обратитесь на сайты, указанные во врезке «Ссылки» на этой странице.
[править] Работать чисто
Обработка исключительных ситуаций в Ruby блаженно проста, например:
puts "Divide 5 by what?" x = gets.chomp.to_i begin y = 10 / x rescue ZeroDivisionError puts "Eeep, divide by zero!" end puts y.to_s
Мы берем у пользователя число, потом входим в блок begin/end с разделом rescue внутри. Если пользователь, допустим, введет 5, в переменную y записывается частное от деления 10 на 5 и результат выводится на экран.
А вдруг он введет ноль? Возникнет ошибка. В таких случаях происходит возврат в командную строку и вывод сообщения, над которым вы и будете ломать голову. Но мы не зря ввели обработчик исключения. Возникшая исключительная ситуация (деление на ноль) будет зафиксирована, и выполнится оператор puts внутри обработчика исключения, который выведет на экран сообщение об ошибке.
Обработка исключений исключительно удобна: она спасает вас от ползания по коду в поисках проблемы и вставки проверок куда ни попадя. Ваш опрятный и компактный код отловит множество видов ошибок при исполнении, открытии файла и т. д.
[править] Создаем web-сервер
Применим полученные знания и напишем собственный… web-сервер! Экстрим? Да нет, в Ruby это совсем несложно, благодаря библиотеке socket. Конечно, для Apache наш сервер конкурентом пока не станет, но зато продемонстрирует возможности Ruby. И вообще, зачем устанавливать и настраивать мощный сервер, если вам всего-то нужно хранить пару web-страничек для доступа к ним по локальной сети? Вы напишете собственный сервер на Ruby быстрее, чем произнесете «/etc/apache/httpd.conf»!
Сохраните следующий код в файле webserver.rb в вашем домашнем каталоге. (Если вам лень набирать, возьмите его из раздела Magazine/Ruby нашего DVD.) Затем создайте в этом же каталоге две HTML-странички: index.html и test.html, с произвольным содержимым, лишь бы выводилось в браузере.
require 'socket' webserver = TCPServer.new('127.0.0.1', 7125) while (session = webserver.accept) session.print "HTTP/1.1 200/OK\r\nContent-type:text/html\r\n\r\n" request = session.gets trimmedrequest = request.gsub(/GET\ \//, '').gsub(/\ HTTP.*/, '') filename = trimmedrequest.chomp if filename == "" filename = "index.html" end begin displayfile = File.open(filename, 'r') content = displayfile.read() session.print content rescue Errno::ENOENT session.print "File not found" end session.close end
Запустите программу командой ruby webserver.rb и проверьте, как она работает. Для этого в адресной строке браузера введите http://127.0.0.1:7125. Если все нормально, вы должны увидеть содержимое странички index.html! Соответственно, набрав http://127.0.0.1:7125/test.html, вы увидите содержимое странички test.html. Код говорит сам за себя, но мы все равно разберем его подробно.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Начинается код с команды require, подключающей внешние библиотеки. В данном случае мы используем библиотеку socket — это набор процедур, сильно упрощающий сетевое программирование (см. врезку «Модные модули» справа). Следующая строка создает объект сервера на локальном IP-адресе 127.0.0.1 и порте 7125. Номер порта может быть любым, но для использования портов до тысячного (например, 80) потребуются права администратора системы.
У нас получился сервер локальной сети; а мы хотим, чтоб с ним могли работать web-браузеры. Цикл while обрабатывает запросы к серверу, пока в окне терминала не нажать клавиши Ctrl+C. Внутри этого цикла сервер принимает запрос клиента и посылает браузеру стандартный ответ из двух строк: сообщение, что запрос принят, и HTML-заголовок. Символы \r и \n означают «возврат каретки» и «перевод строки» соответственно.
Затем обрабатывается запрос, полученный от браузера. Обычно он выглядит примерно так: GET /filename.html HTTP/1.1. Нам нужно определить в нем имя запрошенного файла. Сохраним строку запроса в переменной request и извлечем оттуда имя файла методом gsub: он отделит от строки части GET и HTTP/1.1 при помощи регулярных выражений. Gsub напоминает командную утилиту sed — быстрый способ заместить или отделить части строковой переменной.
От полученного имени файла с помощью метода chomp отделяется последний символ перевода строки, после чего результат сохраняется в переменной filename.
Большинство web-серверов, если имя файла не указано, по умолчанию загружают index.html. Блок if так и делает: если строка с именем файла пуста, переменной filename присваивается index.html. Можно, конечно, использовать и другой файл.
После этого (внутри блока begin/end) мы открываем полученный файл на чтение и записываем в переменную content его содержимое, прочитанное с помощью функции read(). Содержимое файла отсылается браузеру, методом session.print. А вдруг такого файла не найдется? Тогда rescue отправит браузеру сообщение об ошибке.
[править] Мысли напоследок
Вот сервер и готов. Удивительно просто, правда? Конечно, пока он обрабатывает только HTML-файлы — но были бы кости, мясо нарастет. Главное, что это пример применения Ruby в реальной задаче, и по нему видно, что код получается чудесно-простой и легко читаемый.
В Ruby еще много чего можно исследовать, и так как Ruby on Rails продолжает набирать популярность, вы об этом языке, несомненно, еще услышите. Ясный и разумный синтаксис Ruby лучше всех прочих поможет разобраться с объектно-ориентированным программированием тем, кто привык к С или Basic. Внизу слева находится врезка «Ссылки», там вы найдете и учебники, и прочую информацию. А напишете нечто крутое — сообщите нам на форум http://unixforum.org/. Как знать, может, вашей будущей программы не хватает на нашем DVD…