Jump to content

Синтаксис Рубина

Синтаксис языка программирования Ruby во многом аналогичен синтаксису Perl и Python . Определения классов и методов обозначаются ключевыми словами, тогда как блоки кода могут определяться либо ключевыми словами, либо фигурными скобками. В отличие от Perl, переменные не обязательно имеют префикс сигилы . При использовании символ меняет семантику области действия переменной. Для практических целей нет различия между выражениями и утверждениями . [1] [2] Разрывы строк значимы и считаются концом оператора; эквивалентно может быть использована точка с запятой. В отличие от Python, отступы не имеют значения.

Одним из отличий от Python и Perl является то, что Ruby сохраняет все свои переменные экземпляра полностью закрытыми для класса и предоставляет их только через методы доступа ( attr_writer, attr_reader, и т. д.). В отличие от методов «getter» и «setter» других языков, таких как C++ или Java , методы доступа в Ruby могут быть созданы с помощью одной строки кода посредством метапрограммирования ; однако методы доступа также можно создавать традиционным способом C++ и Java. Поскольку вызов этих методов не требует использования круглых скобок, превратить переменную экземпляра в полную функцию очень просто, не изменяя ни одной строки вызывающего кода или не проводя рефакторинга, обеспечивая функциональность, аналогичную C# и VB.NET. членам свойств .

Дескрипторы свойств Python похожи, но в процессе разработки приходится идти на компромисс. Если кто-то начинает работать с Python с использования общедоступной переменной экземпляра, а затем изменяет реализацию, чтобы использовать частную переменную экземпляра, предоставляемую через дескриптор свойства, возможно, потребуется скорректировать внутренний код класса для использования частной переменной, а не публичного свойства. . Дизайн Ruby требует, чтобы все переменные экземпляра были закрытыми, но также предоставляет простой способ объявления set и get методы. Это соответствует идее, что в Ruby никогда не осуществляется прямой доступ к внутренним членам класса извне класса; скорее, каждый передает сообщение классу и получает ответ.

Интерактивные сессии

[ редактировать ]

Следующие примеры можно запустить в оболочке Ruby, например Interactive Ruby Shell , или сохранить в файле и запустить из командной строки, набрав ruby <filename>.

Классический Hello world пример :

puts 'Hello World!'

Некоторый базовый код Ruby:

# Everything, including a literal, is an object, so this works:
-199.abs # => 199
'ice is nice'.length # => 11
'ruby is cool.'.index('u') # => 1
"Nice Day Isn't It?".downcase.split('').uniq.sort.join
# => " '?acdeinsty"

Вход:

print 'Please type name >'
name = gets.chomp
puts "Hello #{name}."

Конверсии:

puts 'Give me a number'
number = gets.chomp
puts number.to_i
output_number = number.to_i + 1
puts output_number.to_s + ' is a bigger number.'

В Ruby существует множество способов определения строк.

Следующие задания эквивалентны:

a = "\nThis is a double-quoted string\n"
a = %Q{\nThis is a double-quoted string\n}
a = %{\nThis is a double-quoted string\n}
a = %/\nThis is a double-quoted string\n/
a = <<-BLOCK

This is a double-quoted string
BLOCK

Строки поддерживают интерполяцию переменных :

var = 3.14159
"pi is #{var}"
=> "pi is 3.14159"

Следующие присваивания эквивалентны и создают необработанные строки :

a = 'This is a single-quoted string'
a = %q{This is a single-quoted string}

Коллекции

[ редактировать ]

Создание и использование массива :

a = [3, 'hello', 14.5, 1, 2, [6, 15]]

a[2] # => 14.5
a.[](2) # => 14.5
a.reverse # => [[6, 15], 2, 1, 14.5, 'hello', 3]
a.flatten.uniq # => [3, 'hello', 14.5, 1, 2, 6, 15]

Создание и использование ассоциативного массива (в Ruby называемого хешем ):

hash = Hash.new # equivalent to hash = {}
hash = { water: 'wet', fire: 'hot' } # makes the previous line redundant as we are now
 # assigning hash to a new, separate hash object
puts hash[:fire] # prints "hot"

hash.each_pair do |key, value| # or: hash.each do |key, value|
 puts "#{key} is #{value}"
end
# returns {:water=>"wet", :fire=>"hot"} and prints:
# water is wet
# fire is hot

hash.delete :water # deletes the pair :water => 'wet' and returns "wet"
hash.delete_if {|key,value| value == 'hot'} # deletes the pair :fire => 'hot' and returns {}

Структуры управления

[ редактировать ]

Если заявление:

# Generate a random number and print whether it's even or odd.
if rand(100).even?
 puts "It's even"
else
 puts "It's odd"
end

Блоки и итераторы

[ редактировать ]

Два синтаксиса для создания блока кода:

{ puts 'Hello, World!' } # note the braces
# or:
do
 puts 'Hello, World!'
end

Блок кода можно передать методу в качестве необязательного аргумента блока. Многие встроенные методы имеют такие аргументы:

File.open('file.txt', 'w') do |file| # 'w' denotes "write mode"
 file.puts 'Wrote some text.'
end # file is automatically closed here

File.readlines('file.txt').each do |line|
 puts line
end
# => Wrote some text.

Передача параметров блока для замыкания :

# In an object instance variable (denoted with '@'), remember a block.
def remember(&a_block)
 @block = a_block
end

# Invoke the preceding method, giving it a block that takes a name.
remember {|name| puts "Hello, #{name}!"}

# Call the closure (note that this happens not to close over any free variables):
@block.call('Jon') # => "Hello, Jon!"

Создание анонимной функции :

proc {|arg| puts arg}
Proc.new {|arg| puts arg}
lambda {|arg| puts arg}
->(arg) {puts arg} # introduced in Ruby 1.9

Возврат замыканий из метода:

def create_set_and_get(initial_value=0) # note the default value of 0
 closure_value = initial_value
 [ Proc.new {|x| closure_value = x}, Proc.new { closure_value } ]
end

setter, getter = create_set_and_get # returns two values
setter.call(21)
getter.call # => 21

# Parameter variables can also be used as a binding for the closure,
# so the preceding can be rewritten as:

def create_set_and_get(closure_value=0)
 [ proc {|x| closure_value = x } , proc { closure_value } ]
end

Передача потока управления программой блоку, который был предоставлен во время вызова:

def use_hello
 yield "hello"
end

# Invoke the preceding method, passing it a block.
use_hello {|string| puts string} # => 'hello'

Перебор перечислений и массивов с использованием блоков:

array = [1, 'hi', 3.14]
array.each {|item| puts item }
# prints:
# 1
# 'hi'
# 3.14

array.each_index {|index| puts "#{index}: #{array[index]}" }
# prints:
# 0: 1
# 1: 'hi'
# 2: 3.14

# The following uses a (a..b) Range
(3..6).each {|num| puts num }
# prints:
# 3
# 4
# 5
# 6

# The following uses a (a...b) Range
(3...6).each {|num| puts num }
# prints:
# 3
# 4
# 5

Такой метод, как inject может принимать как параметр, так и блок. inject метод перебирает каждый член списка, выполняя над ним некоторую функцию, сохраняя при этом агрегат. Это аналогично foldl функции в функциональных языках программирования . Например:

[1,3,5].inject(10) {|sum, element| sum + element} # => 19

При первом проходе блок получает 10 (аргумент для инъекции) как sumи 1 (первый элемент массива) как element. Это возвращает 11, которое затем становится sum на следующем проходе. Оно добавляется к 3, чтобы получить 14, которое затем добавляется к 5 на третьем проходе, чтобы в конечном итоге вернуть 19.

Использование перечисления и блока для возведения в квадрат чисел от 1 до 10 (с использованием диапазона ):

(1..10).collect {|x| x*x} # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

Или вызвать метод для каждого элемента ( map является синонимом collect):

(1..5).map(&:to_f) # => [1.0, 2.0, 3.0, 4.0, 5.0]

Следующий код определяет класс с именем Person. В дополнение к initialize, обычный конструктор для создания новых объектов, имеет два метода: один для переопределения <=> оператор сравнения (так Array#sort можно сортировать по возрасту), а другой — переопределить to_s метод (так Kernel#puts может форматировать вывод). Здесь, attr_reader является примером метапрограммирования в Ruby: attr_accessor определяет методы получения и установки переменных экземпляра, но attr_reader только методы получения. Последний вычисленный оператор в методе является его возвращаемым значением, что позволяет опустить явный оператор. return заявление.

class Person
 attr_reader :name, :age
 def initialize(name, age)
 @name, @age = name, age
 end
 def <=>(person) # the comparison operator for sorting
 @age <=> person.age
 end
 def to_s
 "#{@name} (#{@age})"
 end
end

group = [
 Person.new("Bob", 33),
 Person.new("Chris", 16),
 Person.new("Ash", 23)
]

puts group.sort.reverse

Приведенный выше код выводит три имени в обратном порядке возраста:

Bob (33)
Ash (23)
Chris (16)

Person является константой и является ссылкой на Class объект.

Открытые занятия

[ редактировать ]

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

# re-open Ruby's Time class
class Time
 def yesterday
   self - 86400
 end
end

today = Time.now # => 2013-09-03 16:09:37 +0300
yesterday = today.yesterday # => 2013-09-02 16:09:37 +0300

Добавление методов к ранее определенным классам часто называется «обезьяньим исправлением» . Если выполнять эту практику безрассудно, эта практика может привести как к коллизиям поведения с последующими неожиданными результатами, так и к проблемам масштабируемости кода.

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

# re-open Ruby's Time class
module RelativeTimeExtensions
 refine Time do
   def half_a_day_ago
     self - 43200
   end
 end
end

module MyModule
 class MyClass
   # Allow the refinement to be used
   using RelativeTimeExtensions

   def window
     Time.now.half_a_day_ago
   end
 end
end

Исключения

[ редактировать ]

Исключение вызывается с помощью raise вызов:

raise

К исключению можно добавить необязательное сообщение:

raise "This is a message"

Исключения также могут быть указаны программистом:

raise ArgumentError, "Illegal arguments!"

Альтернативно, экземпляр исключения может быть передан в метод raise метод:

raise ArgumentError.new("Illegal arguments!")

Эта последняя конструкция полезна при создании экземпляра пользовательского класса исключений с конструктором, принимающим более одного аргумента:

class ParseError < Exception
 def initialize(input, line, pos)
 super "Could not parse '#{input}' at line #{line}, position #{pos}"
 end
end

raise ParseError.new("Foo", 3, 9)

Исключения обрабатываются rescue пункт. Такое предложение может перехватывать исключения, которые наследуются от StandardError. Другие ключевые слова управления потоком, которые можно использовать при обработке исключений: else и ensure:

begin
 # do something
rescue
 # handle exception
else
 # do this if no exception was raised
ensure
 # do this whether or not an exception was raised
end

Распространенной ошибкой является попытка перехватить все исключения с помощью простого предложения спасения. Чтобы перехватить все исключения, нужно написать:

begin
 # do something
rescue Exception
 # Exception handling code here.
 # Don't write only "rescue"; that only catches StandardError, a subclass of Exception.
end

Или поймайте определенные исключения:

begin
 # do something
rescue RuntimeError
 # handle only RuntimeError and its subclasses
end

Также можно указать, чтобы объект исключения был доступен для предложения обработчика:

begin
 # do something
rescue RuntimeError => e
 # handling, possibly involving e, such as "puts e.to_s"
end

Альтернативно, самое последнее исключение сохраняется в глобальном волшебном файле. $!.

Также можно поймать несколько исключений:

begin
 # do something
rescue RuntimeError, Timeout::Error => e
 # handling, possibly involving e
end

Metaprogramming

[ редактировать ]

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

Например, следующий код Ruby генерирует новые методы для встроенного String класс, основанный на списке цветов. Методы оборачивают содержимое строки HTML-тегом, оформленным соответствующим цветом.

COLORS = { black: "000",
 red: "f00",
 green: "0f0",
 yellow: "ff0",
 blue: "00f",
 magenta: "f0f",
 cyan: "0ff",
 white: "fff" }

class String
 COLORS.each do |color,code|
 define_method "in_#{color}" do
 "<span style=\"color: ##{code}\">#{self}</span>"
 end
 end
end

Сгенерированные методы затем можно было бы использовать следующим образом:

"Hello, World!".in_blue
 => "<span style=\"color: #00f\">Hello, World!</span>"

Чтобы реализовать эквивалент на многих других языках, программисту пришлось бы написать каждый метод ( in_black, in_red, in_greenи т. д.) отдельно.

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

  • перехват и изменение вызовов методов
  • внедрение новых моделей наследования
  • динамическое создание классов из параметров
  • автоматическая сериализация объектов
  • интерактивная помощь и отладка
  1. ^ «[ruby-talk:01120] Re: Значение while...» В синтаксисе Ruby оператор — это всего лишь особый случай выражения, которое не может выступать в качестве аргумента (например, множественное присваивание).
  2. ^ "[ruby-talk:02460] Re: Вопрос о приоритете" . оператор [...] не может быть частью выражения, если он не сгруппирован в круглые скобки.
Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: 9a53ee8d3ee310dc70765fa5b9033b8e__1708151520
URL1:https://arc.ask3.ru/arc/aa/9a/8e/9a53ee8d3ee310dc70765fa5b9033b8e.html
Заголовок, (Title) документа по адресу, URL1:
Ruby syntax - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)