Контроль над исполнением кода и типами данных — КиберПедия 

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

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...

Контроль над исполнением кода и типами данных

2022-09-29 26
Контроль над исполнением кода и типами данных 0.00 из 5.00 0 оценок
Заказать работу

До сих пор типы, в сущности, были тем средством, что оградит наши программы от неприятностей. И хотя такая предосторожность довольно полезна, Crystal также предлагает много способов, чтобы вы могли написать код, ход выполнения которого обусловлен типами обрабатываемых данных. Это обеспечивает краткость кода, и вместе с
тем — распознавание множества различных видов информации.

В прошлой главе вы видели, какие управляющие конструкции обра-
зуют программную архитектуру, и вы, возможно, помните, что переменная, являющаяся условием запуска if-ветви, не должна соответствовать значению "nil" или "false". Кроме того, если имеется конструкция "if var1 && var2", то и var1, и var2 обязательно должны избегать нулевого значения. Эти теоретические основы полезны, но
Crystal предлагает гораздо большие возможности.

Вместо явного использования конструкций if можно использовать
более компактную троичную форму, как показано ниже:

var1 = if 1 > 2 3 else 4 end # => 4

# stated more concisely

var2 = 1 > 2? 3: 4 #=> 4

Что за тип времени компиляции у переменной var1 в примере ниже?

  # random choice between number and string

var1 = rand < 0.5? 42: "Crystal" #=> 42 or "Crystal"

 

Нетрудно догадаться: тип объединения "Int32 | String". Это означает,
что вызов метода abs для переменной var1 не работает:

typeof(var1) # => (Int32 | String)

var1.abs # => Error: undefined method 'abs' for String

Если вы твердо убеждены, что var1 является Int32, вы можете заста-
вить и компилятор поверить в это, использовав "as", чтобы однозначно зафиксировать тип:

  ivar1 = var1.as(Int32)

Но в данном случае нельзя знать наверняка, как же сработает rand, и
 если var1 всё же окажется типом String, использование метода "as" приведет к ошибке во время выполнения:

cast from String to Int32 failed (TypeCastError)

 

Чтобы предотвратить это, используйте вариант "as?", который воз-вращает ноль вместо возникновения исключительной ситуации, так
что вы можете проверить его с помощью if:

ivar1 = var1.as?(Int32) # => 42 or nil

# or retaining only the value 42 with if:

if ivar1 = var1.as?(Int32)

p ivar1.abs # => 42

 end

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

  if var1.nil?

# here var1 is nil

  end

Но это почти никогда не бывает необходимым. Просто используйте "if var1" с условным ветвлением "else" для обработки случая, когда выражение примет нулевое значение.

Вы можете проверить тип объекта с помощью метода "is_a?". Внутри конструкции if объект гарантированно будет соответствовать именно такому типу:

  var1 = 42

if var1.is_a?(Number)

# here var1 is a Number, which can be integer or floating point

end

Если вы тестируете целый ряд типов, лучше использовать "case":

case var1

when Number

p var1 + 42

when String

p "we have a string"

else

p "var1 is not a number or a string"

end

# => 84

 

case — это очень универсальная конструкция: она может использовать
все виды переменных, включая символы, перечисления и кортежи.
Она не только может тестировать тип переменной, но также может вызывать метод для нее, как показано в этом фрагменте:

  num = 42

case num

when.even?

puts "you have an even number"

when.odd?

puts "you have an odd number"

end

# => you have an even number

 

Использование переменной кортежа вместе с "case" делает возмож-
ным сопоставление некоторых шаблонов. FizzBuzz является обыденной задачей в программировании, в которой вас просят напечатать FizzBuzz, если число делится на 3 и 5, "Fizz" — если делится на 3, и "Buzz"
— если делится на 5, считая от 1 до 100. И "case" позволяет написать компактную версию решения:

(1..100).each do |i|

case {i % 3, i % 5}

when {0, 0}

puts "FizzBuzz"

when {0, _}

puts "Fizz"

when {_, 0}

puts "Buzz"

 

else

puts i

 end

end

 

% — операция по модулю, которая возвращает остаток от целочисленного деления. Обратите внимание, что вы можете использовать один (или несколько) символов _ при тестировании кортежа, заменяя ими значения, которые не столь важны.

Другой способ разобраться с типами — проверить, может ли содер-
жимое переменной отвечать на отправленный методом вызов.
Безопасное тестирование выполняется посредством "responds_to?":

 var1 = "Crystal"

if var1.responds_to?(:abs) # false in this case

var1.abs

end

 

Ваш черёд № 6

1) Какое значение у var1 после этого if?

if var1 = 1

puts "inside if "

var1 = 2

puts var1

end

Здесь ход выполнения отличается от характерного для многих других языков программирования!

2) Какой вывод порождает следующая программа?

if (num = 9) < 0

puts "#{num}, is negative"

elsif num < 10

puts "#{num}, has 1 digit"

else

puts "#{num}, has multiple digits"

end

3) Проверьте этот фрагмент кода и объясните его поведение. Вы ви-
дите способ улучшить его?

begin

a = 4 + 6

rescue

puts "an ex occurred"

ensure

puts a + 42

end

Подсказка: компилятор учитывает вероятность возникновения исключительной ситуации.

Заключение

В этой главе мы глубже изучили некоторые базовые вещи Кристаль-
ного Программирования, такие как символы, кортежи и оператор case. Для Руби-кодера, возможно, это все не в новинку, но вы теперь лучше знакомы с компилятором Crystal и с тем, как он использует типы объединения, чтобы сделать ваш код более безопасным.

Объединенные (или комбинированные) типы составляют крае-
угольный камень типовой системы Кристалла. Вооружившись этим пониманием, давайте приступим к изучению методов и процедур
(а также посмотрим, как здорово Crystal использует перегрузку) в
нашей следующей главе.

 

 


Поделиться с друзьями:

История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...

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

Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...

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



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.012 с.