Сложим все вместе — конвертация валют (версия 2) — КиберПедия 

История развития хранилищ для нефти: Первые склады нефти появились в XVII веке. Они представляли собой землянные ямы-амбара глубиной 4…5 м...

Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...

Сложим все вместе — конвертация валют (версия 2)

2022-09-29 28
Сложим все вместе — конвертация валют (версия 2) 0.00 из 5.00 0 оценок
Заказать работу

 

В ходе дальнейшего развития нашего проекта мы сможем получать ежедневные курсы обмена валют из 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 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.028 с.