История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...
Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...
Топ:
Комплексной системы оценки состояния охраны труда на производственном объекте (КСОТ-П): Цели и задачи Комплексной системы оценки состояния охраны труда и определению факторов рисков по охране труда...
Основы обеспечения единства измерений: Обеспечение единства измерений - деятельность метрологических служб, направленная на достижение...
Определение места расположения распределительного центра: Фирма реализует продукцию на рынках сбыта и имеет постоянных поставщиков в разных регионах. Увеличение объема продаж...
Интересное:
Национальное богатство страны и его составляющие: для оценки элементов национального богатства используются...
Принципы управления денежными потоками: одним из методов контроля за состоянием денежной наличности является...
Аура как энергетическое поле: многослойную ауру человека можно представить себе подобным...
Дисциплины:
2022-09-29 | 28 |
5.00
из
|
Заказать работу |
|
|
В ходе дальнейшего развития нашего проекта мы сможем получать ежедневные курсы обмена валют из XML-файлов, размещенных на веб-сайте. Они содержат эту информацию в следующей форме:
<title> 1 USD = 0,74402487 GBP </title>
На данный момент нашей программе известна базовая валюта USD и валюта обмена GBP, и мы хотим получить обменный курс 0.74402487.
Вот как мы можем сделать это:
types_and_control_flow/curr_conv4.cr
base_currency = "USD"
currency = "GBP"
line = "<title>1 USD = 0.74402487 GBP</title>" # exchange rate format
regex = {
:open => /<title>1 #{base_currency} = /,
:close => / #{currency}<\/title>/
}
rate = line.gsub(regex[:open], "").gsub(regex[:close], "").to_f
# => 0.74402487
Шаблон регулярного выражения /<title\>1 #{base_currency} = /
позволяет нам достичь тождества с первой частью строки line (перед дробным числом обменного курса).
Таким же образом шаблон /#{currency} <\/title\>/
соответствует закрывающей части. Последовательное применение ме-тода gsub замещает эти шаблоны таким образом, что остается только строка обменного коэффициента вместе с to_f, завершающим её.
После Хэшей и Массивов: больше составных типов
Составные типы, такие как массивы и хэши, с которыми мы познакомились в предыдущей главе, упрощают создание более сложных приложений. Crystal предлагает больше возможностей на базе других моделей данных, таких как кортежи и наборы. Кортежи группируют связанные значения для различных (но не обязательно) типов данных.
Их можно создавать, записывая значения внутри {фиг. скобок}, или с помощью Tuple.new:
tpl = {42, "silver", 'C'}
tpl.class # => Tuple(Int32, String, Char)
a = Tuple.new(42, "silver", 'C')
Если вам интересно, как работают множественные назначения,
например "n, m = 42, 43", то они используют кортежи. Вы можете получить доступ к элементам кортежа по индексу:
|
tpl[0] # => 42 (Int32)
tpl[1] # => "silver" (String)
tpl[2] # => 'C' (Char)
var = 89
tpl[var] # => Index out of bounds (IndexError)
tpl[var]? # => nil
Индекс проверяется, и в тех случаях, когда он неверен и вы исполь-зовали литералы, — возникает ошибка во время компиляции; простое несовпадение индекса — ошибка индексирования (IndexError) во время выполнения. Как и для массивов, безопаснее будет использовать метод "[]?", который возвращает ноль в подобных случаях. Вы можете использовать все методы из класса Tuple, такие как "size, each,
includes?, map" и так далее.
Поскольку кортежи создаются в стеке, они легковесны и подвижнее массивов, которым выделено место в общей куче ОП, особенно при размещении внутри циклов.
Использование ярлыка ||= (синтаксис которого мы представили ранее в §"Обработка пользовательского ввода") — отличный способ добавления пар данных:
h = {1 => 'A'}
h[3] ||= 'C'
h # => {1 => 'A', 3 => 'C'}
Мы могли бы использовать эту форму в нашем проекте валютной конверсии следующим образом:
rates[curr] ||= rate.to_f
Это означает, что валютный курс будет установлен первым значением, последующие значения не изменят его.
Если вы хотите больше смысла в вашей структуре данных, в Crystal
также имеются именованные кортежи, которые подобны реестрам
или протоколам, применяемым в некоторых ЯП:
tpl = {name: "Crystal", year: 2017} # NamedTuple(name: String, year: Int32)
tpl[:name] # => "Crystal" (String)
Поскольку кортежи имеют фиксированный размер и стековое раз-мещение, они очень эффективны. Также компилятор может различать типы данных для каждой позиции. В этом отличие от массивов, которые могут меняться в размерах, поэтому следует отдавать предпочтение кортежам в случаях, когда размер множества постоянен и используются разные типы данных.
Для ключей символьного или строкового типа можно использовать именованные кортежи:
|
# Вместо {:key1 => 'a',:key2 => 'b'} вы можете сделать:
{key1: 'a', key2: 'b'}
# Взамен {"key1" => 'a', "key2" => 'b'} используйте:
{"key1": 'a', "key2": 'b'}
Если имена, индексы или порядок следования не важны, но необ-
ходимо сохранить уникальные значения, используйте набор:
set = Set{41, 42, 43} # => Set{41, 42, 43}
set.class # => Set(Int32)
# The above is equivalent to
set = Set(Int32).new
set << 42
set << 41
set << 43
set << 41
set # => Set{42, 41, 43}
Ваш черёд № 4
Деструктуризация: Каковы значения переменных левее знака = (присвоение)?
var1, var2, var3 = [78, 56, 42] # array
var1, var2, var3 = {78, 56, 42} # tuple
Это хороший способ вывести значения из массива или кортежа. Мы можем использовать его в нашей программе "Конвертер валют" для замены:
arr = input.split(" - ")
curr = arr[0]
rate = arr[1]
более компактной записью:
curr, rate = input.split(" - ")
Из предыдущих примеров ясно, что Массив, Кортеж, Хэш и Набор могут принимать различные типы данных в качестве своих элементов, в то время как их методы работают со всеми этими типами. Вы можете заметить, что они используют некий тип (T, или K, или V) в качестве параметра.
Например, Array (T), Hash (K, V) и так далее, где T может означать
Int32, String, Char или любой другой тип. Другими словами: это общие (или универсальные) типы.
В главе 6 вы увидите, как определять собственные общие классы,
которые способны работать с любым типом.
Nil-типы
Как нам объявить переменную определенного типа, но также могущую принять нулевое значение (nil), т.н. «nilable»? Вы видели раньше, что в определенных ситуациях Crystal присваивает объекту тип объединения
во время компиляции.
Можно объявить тип nilable как тип объединения, но вы можете
также объявить его тип, приписав в конце "?", как показано здесь:
types_and_control_flow/type_nil.cr
n: Int32 | Nil
n = 42
p typeof(n) # => Int32
a: Int32?
a = 42
p typeof(a) # => Int32
b: Int32?
b = nil
p typeof(b) # => Nil
a.try { p a + 1 } # => 43
b.try { p b + 1 } # => no error!
При использовании nil-типов метод "try" может оказаться очень кстати: компилятор не будет сигнализировать об ошибках тогда, когда значе-
ние может оказаться нулевым. Но имейте в виду, что если вы таким способом заблокируете компилятор, то дальше вы сами по себе!
Теперь для вас пришло время работать с типами объединения самостоятельно:
|
Ваш черёд № 5
1. Типы объединений.
Какому типу соответствует переменная mineral в следующем фрагменте кода? Напишите конструкцию if для отображения названия минерала
в каждом возможном случае:
arr = ["anadite", "humite", "roselite"]
mineral = arr[4]?
2. Вот два пустых хэша, в которых присутствуют типы объединения. Каковы типы ключа и значения? Добавьте к ним пары "ключ-значение" так, чтобы использовать все типы, а также добавьте пару, которую
нельзя скомпилировать.
h1 = Hash(Int32 | Char, Int32).new
h2 = {} of String | Int32 => Bool | String
3. Каков тип времени компиляции и тип времени выполнения у переменной var1, вызываемой после выражений if, следующих ниже, и почему это так?
if rand < 0.5
var1 = 7
end # branches that are not present return nil;
#
var1 = 42
if rand < 0.5
var1 = "Crystal"
end
var1 = 42
if rand < 0.7
var1 = "Crystal"
else
var1 = true
end
#
if rand < 0.5
var1 = 42
else
var1 = "Crystal"
end
var2 = var1 * 2
var3 = var1 - 1 # <= What does this return?
|
|
Поперечные профили набережных и береговой полосы: На городских территориях берегоукрепление проектируют с учетом технических и экономических требований, но особое значение придают эстетическим...
Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...
Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...
История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!