Понимание типов данных в Ruby

Введение

При написании программ вы используете типы данных, чтобы классифицировать данные. Типы данных сообщают компьютеру, как обрабатывать данные в вашей программе. Они также определяют, что вы можете делать с данными, включая операции, которые вы можете выполнять.

Один из способов думать о типах данных – это рассматривать разные типы данных, которые мы используем в реальном мире. Например, мы используем целые числа (0, 1, 2, …), целые числа (…, -1, 0, 1, …) и иррациональные числа (π).

Обычно в математике мы можем объединять числа разных типов и получать некоторый ответ. Например, мы можем хотеть добавить 5 к π:

5 + π

Мы можем либо оставить уравнение как ответ, чтобы учесть иррациональное число, либо округлить π до числа с небольшим количеством десятичных знаков и затем сложить числа вместе:

5 + π = 5 + 3.14 = 8.14

Но если мы попытаемся вычислить числа с другим типом данных, например, словами, вещи начнут становиться менее понятными. Как бы мы решили следующее уравнение?

sky + 8

Это не то, что мы сразу же знаем, как решить. Компьютер тоже не может, потому что данные принадлежат двум разным типам. “Небо” – это слово, а 8 – целое число. Когда мы пишем программы, мы должны быть осторожными в том, как мы присваиваем значения и как мы их обрабатываем через операции, такие как сложение, вычитание, умножение и другие.

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

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

Давайте начнем с того, как работать с целыми числами в Ruby.

Целые числа

Как и в математике, целые числа в программировании – это целые числа, которые могут быть положительными, отрицательными или 0 (…, -1, 0, 1, …). Целое число также часто называется int.

Вы можете вывести целое число таким образом:

print -25
Output
-25

Вы также можете сохранить целое число в переменной и затем вывести значение, обращаясь к переменной:

my_int = -25
print my_int
Output
-25

С целыми числами также можно выполнять математические операции. Например, вы можете вычислить сумму двух чисел и вывести результат:

sum = 116 - 68
print sum
Output
48

Когда мы записываем большие числа, мы обычно используем запятые, чтобы их было легче читать. Например, мы бы написали 1,000,000 для “один миллион”. Вы не можете использовать запятые в своем коде, но Ruby позволяет использовать символ подчеркивания (_), чтобы сделать большие числа более читаемыми.

Попробуйте это:

large_number.rb
large_number = 1_234_567
print large_number

Вы увидите целое число, напечатанное без подчеркиваний:

Output
1234567

Подчеркивания позволяют вам писать более читабельный код, если вам приходится представлять большие числа в ваших программах.

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

Вещественные числа

A floating-point number or a float represents a real number. Real numbers can be either a rational or an irrational number; numbers that contain a fractional part, such as 9.0 or -116.42. In other words, a float in a Ruby program is a number that contains a decimal point.

Вы можете выводить числа с плавающей точкой в Ruby так же, как и целые числа:

print 17.3
Output
17.3

Вы также можете объявить переменную и присвоить ей значение с плавающей точкой:

my_float = 17.3
print my_float
Output
17.3

И, как и с целыми числами, вы можете выполнять математические операции с числами с плавающей точкой в Ruby:

sum = 564.0 + 365.24
print sum
Output
929.24

Если вы добавите число с плавающей точкой к целому числу в Ruby, вы получите число с плавающей точкой:

sum = 564 + 365.24
print sum
Output
929.24

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

Далее давайте посмотрим на логические значения в Ruby.

Логические типы данных

Логические значения используются для представления истинных значений, связанных с логической ветвью математики, которая информирует алгоритмы в компьютерной науке. В Ruby мы представляем этот тип данных одним из двух значений: либо true, либо false.

Многие операции в математике дают нам ответы, которые оцениваются как истина или ложь:

  • больше
  • 500 > 100 true
  • 1 > 5 false
  • меньше
  • 200 < 400 true
  • 4 < 2 false
  • равно
  • 5 = 5 true
  • 500 = 400 false

Как и с числами, вы можете сохранить значение true или false в переменной:

result = 5 > 8

Затем вы можете распечатать логическое значение с помощью вызова функции print():

print result

Поскольку 5 не больше 8, вы увидите следующий результат:

Output
false

По мере того как вы будете писать больше программ на Ruby, вы станете более знакомы с тем, как работают логические значения и как различные функции и операции, оцениваясь как true или false, могут изменить ход программы.

Далее давайте изучим работу с текстом в наших программах.

Строки

A string is a sequence of one or more characters, such as letters, numbers, and symbols. Strings primarily exist within either single quotes (') or double quotes (") in Ruby, so to create a string, enclose a sequence of characters in quotes, like this:

"This is a string in double quotes."

Небольшая программа “Привет, мир!” демонстрирует, как строка может быть использована в программировании, так как символы, составляющие фразу Привет, мир!, представляют собой строку.

print "Hello, World!"

Как и с другими типами данных, строки можно хранить в переменных:

output = "Hello, World!"

И выводить строку, вызывая переменную:

print output
Output
Hello, World!

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

Иногда вам нужно работать с списками данных. Вот где пригодятся массивы.

Массивы

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

Массивы определяются указанием значений в квадратных скобках [ ], разделенных запятыми.

Массив целых чисел выглядит следующим образом:

[-3, -2, -1, 0, 1, 2, 3]

A array of floats looks like this:

[3.14, 9.23, 111.11, 312.12, 1.05]

Вот список строк:

['shark', 'cuttlefish', 'squid', 'mantis shrimp']

Как и другие типы данных, вы можете присвоить массив переменной:

sea_creatures = ['shark', 'cuttlefish', 'squid', 'mantis shrimp']

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

print sea_creatures
['shark', 'cuttlefish', 'squid', 'mantis shrimp']

Доступ к отдельным элементам массива осуществляется с использованием номера индекса, начиная с 0.

puts sea_creatures[0] # акула
puts sea_creatures[2] # кальмар

Чтобы вывести последнее значение, вы можете использовать индекс -1. Ruby также предоставляет методы .first и .last для получения первой и последней записи, соответственно:

puts sea_creatures.first # акула
puts sea_creatures.last # мантисса-креветка

Массивы в Ruby могут содержать множество различных типов данных. Вы можете хранить строки, символы, и даже другие массивы в массиве:

record = [
:en,
"Sammy",
42,
[
"coral",
"reef"
]
]

Массивы в Ruby являются изменяемыми, что означает, что вы можете добавлять значения, удалять значения, и даже изменять записи в массиве.

Иногда нам нужен способ маркировать вещи в программе. Для этого и существуют символы.

Символы

A symbol is a special data type that acts like a label or an identifier in a Ruby program. Symbols are immutable, which means that they cannot be changed. A symbol looks like a variable declaration without a value. Here’s an example of a symbol:

:time_zone

В Ruby вы обычно используете символ для идентификации чего-то важного, тогда как строку вы используете для работы с текстом или его обработки. Каждая строка в программе на Ruby является отдельным объектом с собственным уникальным местоположением в памяти, даже если строки идентичны.

Но если вы ссылаетесь на один и тот же символ несколько раз, вы ссылаетесь на один и тот же объект во всех частях программы, что означает, что вы ссылаетесь на одно местоположение в памяти.

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

Хэши

A hash is a dictionary-like collection of keys and values. These key-value pairs provide a useful way to store and access data. Hashes are often used to hold data that are related, such as the information about a user. You define a hash like this:

{"first_name" => "Sammy", "last_name" => "Shark"}

Вы можете присваивать хэши переменным так же, как и другие типы данных:

user = {"first_name" => "Sammy", "last_name" => "Shark"}

Чтобы получить значения из хэша user, вы используете ключ для значения:

print user["first_name"] # "Sammy"
print user["last_name"] # "Shark"

Вы можете использовать символы в качестве ключей в хэше вместо строк:

user = {:first_name => "Sammy", :last_name => "Shark"}

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

Когда вы используете символы в качестве ключей, вы также используете символы для получения значений:

print user[:first_name] # "Sammy"
print user[:last_name] # "Shark"

Вы также можете использовать немного другой синтаксис при определении хэша:

user = {first_name: "Sammy", last_name: "Shark"}

Этот синтаксис аналогичен синтаксису, используемому в JavaScript и других языках. Этот синтаксис определяет ключи как символы, поэтому вы будете получать доступ к записям, используя :first_name и :last_name, а не строки "first_name" и "last_name".

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

Динамическая типизация

В Ruby вы не объявляете явно тип данных перед присвоением значения; тип данных определяется присваиваемым значением. Ruby использует динамическую типизацию, что означает, что проверка типов выполняется во время выполнения, а не во время компиляции, как в языках, использующих статическую типизацию. Ruby определяет тип данных из данных, хранящихся в переменной. Это аналогично типам данных в Python и типам данных в JavaScript.

Переменная t в следующем примере может быть установлена в любой доступный тип данных:

t = 42 # t is an Integer
t = "Sammy" # t is a String
t = :sammy # t is a Symbol
t = true # t is a boolean (true)
t # t is nil

С динамически типизированными языками вы можете повторно использовать существующую переменную для хранения различных типов данных.

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

print "Please enter the length of the room: "
length = gets.chop

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

# Преобразование суммы в тип Float.
length = length.to_f

Метод to_f преобразует строку в число с плавающей точкой. Ruby также предоставляет метод to_i для преобразования строк в целые числа, и большинство объектов можно преобразовать в строки с помощью метода to_s:

42.to_s # "42"
(42.5).to_s # "42.5"
["Sammy", "Shark"].to_s # "[\"Sammy\", \"Shark\"]"

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

print 5 + "5"
Output
TypeError: String can't be coerced into Integer

Также этот код вызовет ошибку:

print "5" + 5
Output
TypeError: no implicit conversion of Integer into String

Если вы хотите сложить числа вместе и получить 10, преобразуйте строку в целое число. Если вы хотите объединить их вместе и получить "55", преобразуйте целое число в строку.

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

Идентификация типов данных

В Ruby практически все является объектом. Целые числа, числа с плавающей запятой, массивы, символы и хэши – все это объекты Ruby, и у них всех есть метод с именем class, который сообщает вам, какого они типа. Даже логические значения true и false, а также значение nil являются объектами. Попробуйте сами:

42.class # Целое число
(42.2).class # Число с плавающей запятой
["Sammy", "Shark"].class # Массив
true.class # Класс TrueClass
nil.class # Класс NilClass

Кроме того, вы можете использовать метод kind_of? для проверки определенного типа данных, как показано здесь:

42.kind_of?(Integer) # true

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

# где-то в коде...
sharks = ["Hammerhead", "Tiger", "Great White"]
...
# еще где-то...

sharks.kind_of?(Hash) # false
sharks.kind_of?(Array) # true

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

if data.kind_of? String
data = data.to_f
end

Ruby также предоставляет метод is_a?, который выполняет ту же функцию, что и kind_of?, но может быть немного проще для чтения для некоторых разработчиков:

if data.is_a? String
data = data.to_f
end

Использование class, kind_of? и is_a? может помочь вам убедиться, что вы работаете с правильным типом данных. По мере изучения Ruby вы обнаружите другие способы работы с данными, которые не включают явную проверку типа данных.

Заключение

Вы будете использовать множество различных типов данных в ваших программах на Ruby. Теперь у вас есть лучшее понимание основных типов данных, доступных в программах на Ruby.

Ознакомьтесь с этими учебниками, чтобы продолжить изучение типов данных Ruby:

Source:
https://www.digitalocean.com/community/tutorials/understanding-data-types-in-ruby