×
Traktatov.net » Изучай Haskell во имя добра! » Читать онлайн
Страница 31 из 245 Настройки

>ghci> (let a = 10; b = 20 in a*b, let foo="Эй, "; bar = "там!" in foo ++ bar)

>(200,"Эй, там!")

Как мы уже говорили ранее, определения в секции >let могут использоваться при сопоставлении с образцом. Они очень полезны, к примеру, для того, чтобы быстро разобрать кортеж на элементы и привязать значения элементов к переменным, а также в других подобных случаях.

>ghci> (let (a,b,c) = (1,2,3) in a+b+c) * 100

>600

Если определения >let настолько хороши, то почему бы только их всё время и не использовать? Ну, так как это всего лишь выражения, причём с локальной областью видимости, то их нельзя использовать в разных охранных выражениях. К тому же некоторые предпочитают, чтобы их переменные вычислялись после использования в теле функции, а не до того. Это позволяет сблизить тело функции с её именем и типом, что способствует большей читабельности.

Выражения let в генераторах списков

Давайте перепишем наш предыдущий пример, который обрабатывал списки пар вида (вес, рост), чтобы он использовал секцию >let в выражении вместо того, чтобы определять вспомогательную функцию в секции >where.

>calcBmis :: [(Double, Double)] -> [Double]

>calcBmis xs = [bmi | (w, h) <– xs, let bmi = w / h 2]

Мы поместили выражение >let в генератор списка так, словно это предикат, но он не фильтрует список, а просто определяет имя. Имена, определённые в секции >let внутри генератора списка, видны в функции вывода (часть до символа |) и для всех предикатов и секций, которые следуют после ключевого слова >let. Так что мы можем написать функцию, которая выводит только толстяков:

>calcBmis :: [(Double, Double)] -> [Double]

>calcBmis xs = [bmi | (w, h) <– xs, let bmi = w / h ^ 2, bmi > 25.0]

Использовать имя >bmi в части >(w, h) <– xs нельзя, потому что она расположена до ключевого слова >let.

Выражения let в GHCi

Часть >in также может быть пропущена при определении функций и констант напрямую в GHCi. В этом случае имена будут видимы во время одного сеанса работы GHCi.

>ghci> let zoot x y z = x * y + z

>ghci> zoot 3 9 2

>29

>ghci> let boot x y z = x * y + z in boot 3 4 2

>14

>ghci> boot

>:1:0: Not in scope: `boot'

Поскольку в первой строке мы опустили часть >in, GHCi знает, что в этой строке >zoot не используется, поэтому запомнит его до конца сеанса. Однако во втором выражении >let часть >in присутствует, и определённая в нём функция >boot тут же вызывается. Выражение >let, в котором сохранена часть >in, является выражением и представляет некоторое значение, так что GHCi именно это значение и печатает.

Выражения для выбора из вариантов


Во многих императивных языках (C, C++, Java, и т. д.) имеется оператор >case, и если вам доводилось программировать на них, вы знаете, что это такое. Вы берёте переменную и выполняете некую часть кода для каждого значения этой переменной – ну и, возможно, используете финальное условие, которое срабатывает, если не отработали другие.

Язык Haskell позаимствовал эту концепцию и усовершенствовал её. Само имя «выражения для выбора» указывает на то, что они являются… э-э-э… выражениями, так же как >if>then