Ruby

Особенность eval[править]

Когда один из моих студентов занимался разработкой калькулятора на Ruby, то он столкнулся с одной интересной особенностью метода . В случае синтаксической ошибки в строке, переданой в качестве параметра, программа вылетала с ошибкой . Ниже идет пример, который демонстрирует эту ситуацию:

begin 
    eval('2+2+') 
rescue 
    p "error" 
end

Для контроля за ситуацией надо явно указать ошибку, которую вы хотите контролировать (в нашем случае ).

begin 
   eval('2+2+') 
rescue SyntaxError 
   p "error" 
end

Теперь все работает! Осталось только заметить, что если строка приходит из внешнего источника, то желательно ее предварительно проверить на соответствие вашим ожиданиям. Иначе, вы будете кормить хакеров… :-) Как пояснил Yuri Leikind, этот эффект связан с тем, что rescue без параметра отлавливает ошибки выполнения программы (), а приведенный выше пример вызывает исключение (). В общем, проблема все равно решается так, как я описал выше. :-)

Условные

При программировании мы часто хотим проверить наличие определенного условия, а затем на основе этого условия выполнить то или иное действие. Они называются условными. Давайте посмотрим на условное выражение в Ruby:

Разберем код:

  • Этот код будет распечатан The number is between 1 and 5, потому что номер, присвоенный переменной numberв первой строке, равен 3. Это означает, что вызов метода number.between?(1, 5)возвращается true.
  • Ruby выполнит код в ifветке и проигнорирует остальную часть оператора.

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

Trailing 

Мы можем добавить наш ifоператор к коду в ifветке, если он находится всего в одной строке. Итак, вместо этого:

Вместо этого мы можем сделать это:

Это отличный пример удобочитаемого синтаксиса Ruby. Второй пример не только экономит нам две строки, но и очень хорошо читается!

unless

В Ruby также есть unlessинструкция, которую мы можем использовать, когда хотим что-то сделать, если условие не применяется (не имеет значения true). Опять же, мы можем добавить unlessоператор в конец строки. Эти два одинаковые:

Parentheses

В Ruby, когда вы определяете или выполняете метод, вы можете опустить круглые скобки. Следующие две строки кода означают одно и то же:

Итак, когда я могу использовать круглые скобки, а когда их опускать?

Отличный вопрос! На самом деле нет четкого правила на этот счет, но есть некоторые условности. Вот что мы рекомендуем вам пока придерживаться:

  • Используйте круглые скобки для всех вызовов методов, которые принимают аргументы, за исключением puts, p, requireиinclude
  • Если метод не принимает аргументов, не добавляйте пустые скобки, просто опустите их.

Подпрограммы: функции, методы и другие…[править]

Многие из студентов уже встречались с такими словами и даже пытались самостоятельно понять, что они значат. Но вопрос все равно возникает, и хотелось бы его разобрать по кускам, чтобы он больше не возникал. Начнем с того, что подпрограммы, функции и методы — это все одно и тоже. Отличия лишь в незначительных деталях. Все это кусок программы, которые программист решил объявить всего лишь один раз, а потом вызывать столько сколько душе угодно. Например, программисту заказали программу подсчета суммы факториалов (помните ) двух чисел. Вот как он написал бы программу, если бы у него не было возможности составлять подпрограммы:

n1, n2 = 4, 5 
p1, p2 = 1, 1 
n1.times{ |i| p1 *= i + 1 } 
n2.times{ |i| p2 *= i + 1 } 
puts "#{n1}! + #{n2}! = #{p1 + p2}"

Он тут же смекнул, что писать кусок программы подсчета факториала числа он написал дважды (чисел, то две штуки) и решил написать подпрограмму, которая этот факториал числа вычислит. Вот как будет выглядеть более продвинутая программа:

def fact( int ) 
    pr = 1 
    int.times{ |i| pr *= i + 1 } 
    pr 
end 
n1, n2 = 4, 5 
puts "#{n1}! + #{n2}! = #{fact(n1) + fact(n2)}"

А если нужно было бы складывать три числа? Выигрыш в простоте очевиден. А теперь давайте разберемся, что же такое мы написал смекалистый программист. Разберем сначала верхний кусок. Он называется ОПРЕДЕЛЕНИЕМ ПОДПРОГРАММЫ или ОПРЕДЕЛЕНИЕМ МЕТОДА (от англ. define methods). Верхняя строчка состоит из ключевого слова , названия метода (в нашем случае ) и списка аргументов, то есть входных данных (в нашем случае )

Если в списке аргументов указано всего одно имя переменной, то и передавать в метод (при вызове) надо тоже один аргумент (обратите внимание на вызов метода ,. Его не обязательно вызывать с переменной в качестве аргумента

Достаточно указать какое либо число, например ). Помимо того, взгляните на в конце тела метода. ЛЮБОЙ МЕТОД должен заканчиваться . Типичный шаблон для создания метода выглядит примерно так:

def имя_метода( имя_первого_аргумента, имя_второго_аргумента, и т.д.) 
    кусок_программы_который_мы_хотим_поместить_в_подпрограмму 
end

Вызывать наш метод надо примерно так:

имя_метода( значение_первого_аргумента, значение_второго_аргумента, и т.д.)

Теперь обратите внимание на то, что переменная pr в теле метода (на которую мы заменили переменные p1 и p2) расположена в последней строчке подпрограммы (т.е. непосредственно перед end)

Вроде как она там прохлаждается и совсем не нужна, но это не так. Таким образом, мы говорим, что переменная pr является РЕЗУЛЬТАТОМ РАБОТЫ ПОДПРОГРАММЫ. И как раз результат перемножения хранится в этой переменной, т.е. данная переменная содержит факториал числа int (т.е. числа, которое передано в качестве первого аргумента). Отсюда и получается, что наша подпрограмма ВОЗВРАЩАЕТ факториал числа. Теперь ПРАВИЛО: программный КОД, который ПОВТОРЯЕТСЯ больше двух раз, ДОЛЖЕН быть ВЫНЕСЕН В ПОДПРОГРАММУ. А сейчас немного о различиях между подпрограммой, функцией и методом. Дело в том, что ПОДПРОГРАММА — это ОБЩЕЕ НАЗВАНИЕ методов, функций и процедур, т.е. объединяющее понятие. Если программист говорит подпрограмма, то он может иметь в виду как метод, так и процедуру. Теперь про различия между методами, функциями и процедурами. Процедуры — это устаревшая конструкция, от которой многие языки программирования отказались. На данный момент она используется только в языке Pascal. СЕЙЧАС в основном ОСТАЛИСЬ только МЕТОДЫ, и ФУНКЦИИ. От процедур их отличает то, что ОНИ ВОЗВРАЩАЮТ РЕЗУЛЬТАТ. Иными словами, ПРОЦЕДУРА — это метод или функция, которые НЕ ВОЗВРАЩАЮТ РЕЗУЛЬТАТА. Теперь пор различия между методами и функциями. МЕТОДЫ есть только в ОБЪЕКТНО-ОРИЕНТИРОВАННЫХ ЯЗЫКАХ. ФУНКЦИИ во всех ОСТАЛЬНЫХ. Отсюда можно заключить, что мы написали с вами подпрограмму, которая является методом, т.к. Ruby — ОБЪЕКТНО-ОРИЕНТИРОВАННЫЙ ЯЗЫК. PS. Большие буквы — это влияние самоучителя Драгункина… :-)

Тенденции в ООП[править]

Просматривая исходники некоторых стандартных библиотек Ruby наткнулся на интересную тенденцию в описании классов. Мое наблюдение касается объявление методов класса. Напомню, что такое метод класса… Метод класса — это метод, который вызывается не относительно объекта, а относительно самого класса. Пример:

puts Dir.getwd # getwd -- метод класса 
Dir.new("testdir").each{|x| puts "Got #{x}" } # each -- метод объекта, а new -- метод класса.

В первом случае происходит вызов метода класса, а во втором — метода объекта (метод класса создает объект, от которого вызывается метод ). Перед вызовом метода класса всегда идет название класса (в нашем случае ). В чем же их отличие при объявлении? Ниже представлен пример объявления класса метода и класса объекта:

class Dir 
    def Dir.getwd 
        # тело метода 
    end 
    def each 
        # тело метода 
    end 
end

Теперь про тенденцию… Если методов класса много, то в стандартных библиотеках просто создают еще один блок, в который помещают методы класса. Пример:

class Dir 
    class << self
        def getwd 
            # тело метода 
        end 
    end 
    def each 
        # тело метода 
    end 
end

Вот такое интересное наблюдение. Думаю, что эта методика закреплена в каком либо регламентирующем документе и в дальнейшем будет стандартом.

Константы при программировании окошек[править]

Во время программирования окошек всегда приходится создавать массу констант. Чтобы потом на эти константы вешать обработчики событий. И вот какая меня посетила идея по этому поводу. Чаще всего первые строчки типичной оконной программы выглядят примерно так:

ID_FRAME = 1
ID_DIALOG_1 = 2
ID_DIALOG_2 = 3
ID_DIALOG_3 = 4

Иногда можно увидеть, как разработчик выравнивает объявления констант в одну строчку:

ID_FRAME, ID_DIALOG_1, ID_DIALOG_2, ID_DIALOG_3 = 1,2,3,4

А теперь продолжим мысль и заменим правую часть более короткой записью:

ID_FRAME, ID_DIALOG_1, ID_DIALOG_2, ID_DIALOG_3 = (1..4).to_a

Теперь используем оператор вместо метода .to_a, что позволит запись сделать более изящной, но и более непонятной:

Побитовые операторы в Ruby

Побитовый оператор работает с битами и выполняет побитовую операцию.

Предположим, что a = 60; и b = 13; теперь в двоичном формате они будут выглядеть следующим образом:

 a    =  0011 1100
 b    =  0000 1101
 ------------------
 a&b  =  0000 1100
 a|b  =  0011 1101
 a^b  =  0011 0001
 ~a   =  1100 0011

Язык Ruby поддерживает следующими побитовые операторы.

оператор Описание пример
& Двоичный оператор AND копирует бит в результат, если он существует в обоих операндах. (a & b) даст 12, что составляет 0000 1100
| Двоичный оператор OR копирует бит, если он существует в любом из операндов. (a | b) даст 61, что составляет 0011 1101
^ Оператор двоичного XOR копирует бит, если он установлен в один операнд, но не тот и другой. (a ^ b) даст 49, то есть 0011 0001
~ Binary Ones Оператор дополнения является унарным и имеет эффект «flipping» бит. (~ a) даст -61, что составляет 1100 0011 в форме дополнения 2 из-за подписанного двоичного числа.
<< Двойной левый оператор сдвига.Значение левых операндов перемещается влево на количество бит, заданных правым операндом. a << 2 даст 240, что составляет 1111 0000
>> Двоичный оператор правого сдвига.Значение левых операндов перемещается вправо на количество бит, заданных правым операндом. a >> 2 даст 15, то есть 0000 1111

100 популярнейших методов в Ruby[править]

Какие методы в Ruby самые популярные? Естественно, что ответ на подобный вопрос зависит от опытности программиста и его собственного стиля. А ведь хочется узнать ответ «в общем»… Для чего мне это? Ну как же, детей надо обучать методам первой необходимости (остальные сами выучат). Им же лень учить все! Поэтому при проектировании учебных пособий следует учитывать частоту использования тех или иных методов. Метод (он же ) учитывать не будем, ибо ясно, что он один из популярнейших. Чтобы найти наши 100 излюбленных методов Руби мы напишем простенькую программу (которая имеет право глючить) и натравим ее на каталог ruby (для узости можно натравить только на каталог ruby/lib). Методы будем искать и в строках и в коментариях. Для тех, кто хочет чистоты эксперимента, может удалять из обработки строки и коментарии. Я их оставил умышленно. Итак, код программы:

require 'find' 
result = [] 
Find.find('c:/ruby/'){ |path| 
    if test(?f,path) && path =~ /&#92;.rbw?$/ 
        result += IO.read( path ).scan( /&#92;.+/ ) 
    end 
} 
puts (result - '.com','.jp','.org','.rb','.rbw','.amazon').inject( Hash.new() ){ |result,elem| 
    result elem  = result elem succ result }.sort_by{ |array| array1 
}.reverse...100map{ |array| array.reverse.join(' : ') }

Как видно из кода программы, она предельно проста и хватает даже доменные зоны в качестве методов (а чего?! метод .com очень даже ничего). Результат ее работы примерно такой (цифра слева — это частота использования):

11866 : .new 
 2075 : .each 
 1589 : .create 
 1409 : .kind_of? 
 1178 : .pack 
 1140 : .size 
 1047 : .to_s 
 1046 : .join 
  914 : .name 
  832 : .nil? 
  817 : .freeze 
  711 : .push 
  692 : .to_i 
  620 : .id 
  615 : .empty? 
  583 : .delete 
  571 : .length 
  569 : .class 
  563 : .collect 
  555 : .shift
  519 : .path 
  513 : .call 
  433 : .add 
  423 : .data 
  419 : .bind 
  415 : .inspect 
  413 : .split 
  370 : .value 
  349 : .text 
  329 : .include?
  324 : .manager
  316 : .index
  315 : .connect
  312 : .open
  305 : .is_a?
  303 : .dup 
  282 : .insert
  267 : .gsub
  266 : .print
  260 : .concat
  256 : .close
  255 : .puts 
  248 : .destroy 
  231 : .read 
  231 : .start
  231 : .pop
  220 : .set
  212 : .parse
  207 : .ac
  204 : .parent
  203 : .match
  200 : .kyutech
  200 : .last
  193 : .current
  189 : .root
  179 : .update
  177 : .ruby
  177 : .respond_to?
  174 : .downcase
  171 : .grid
  171 : .properties
  169 : .key?
  169 : .gsub!
  165 : .to_f
  162 : .type
  160 : .write
  159 : .message
  156 : .width
  154 : .to_a
  151 : .find
  149 : .invoke
  145 : .require
  144 : .critical
  140 : .nodeType
  138 : .mainloop
  136 : .configure
  133 : .unpack
  129 : .has_key?
  129 : .clear
  128 : .map
  127 : .exist?
  122 : .chr
  121 : .html
  120 : .strip
  118 : .now
  117 : .namespace
  115 : .handle
  114 : .first
  114 : .method
  112 : .sub 
  112 : .unshift
  112 : .sort
  112 : .sub!
  109 : .scan
  109 : .run
  107 : .body
  107 : .appendItem
  105 : .taint
  103 : .height
  103 : .id2obj

Все это конечно бред, зато прикольно и есть над чем подумать! :-)

Типы переменных в Ruby

Существует пять типов переменных:

1. Константы.2. Глобальная переменная.3. Переменная класса.4. Переменная экземпляра.5. Локальная переменная.
  1. Пример объявления константы:
a = "This is my book."

2. Пример объявления глобальной переменной (используется символ ):

$var = 'I love my-self'

3. Пример объявления переменной класса (используется символ @@):

@@instances = 0

4. Пример объявления переменной экземпляра (используется символ @):

@var = 'Ruby Programming'

5. Пример объявления локальной переменной:

Локальные переменные — самые распространенные, они не выходят за рамки области видимости. Эти переменные объявляются без использования перед именем переменной символов или , при этом имя переменной не должно быть целиком заглавными буквами.

var = 10
Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Мой редактор ОС
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: