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

>initials firstname lastname = [f] ++ ". " ++ [l] ++ "."

>  where (f:_) = firstname

>        (l:_) = lastname

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

Функции в блоке where

Точно так же, как мы определяли константы в секции >where, можно определять и функции. Придерживаясь нашей темы «здорового» программирования, создадим функцию, которая принимает список из пар «вес–рост» и возвращает список из ИМТ.

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

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

>  where bmi weight height = weight / height    2

Видите, что происходит? Причина, по которой нам пришлось представить >bmi в виде функции в данном примере, заключается в том, что мы не можем просто вычислить один ИМТ для параметров, переданных в функцию. Нам необходимо пройтись по всему списку и для каждой пары вычислить ИМТ.

Пусть будет let


Определения, заданные с помощью ключевого слова >let, очень похожи на определения в секциях >where. Ключевое слово >where – это синтаксическая конструкция, которая позволяет вам связывать выражения с переменными в конце функции; объявленные переменные видны во всём теле функции, включая сторожевые условия. Ключевое же слово >let позволяет связывать выражения с именами в любом месте функции; конструкции >let сами по себе являются выражениями, но их область видимости ограничена локальным контекстом. Таким образом, определение >let, сделанное в охранном выражении, видно только в нём самом.

Как и любые другие конструкции языка Haskell, которые используются для привязывания имён к значениям, определения >let могут быть использованы в сопоставлении с образцом. Посмотрим на них в действии! Вот как мы могли бы определить функцию, которая вычисляет площадь поверхности цилиндра по высоте и радиусу:

>cylinder :: Double -> Double -> Double

>cylinder r h =

>  let sideArea = 2 * pi * r * h

>    topArea = pi * r    2

>  in sideArea + 2 * topArea

Общее выражение выглядит так: >let <определения> in <выражение>. Имена, которые вы определили в части >let, видимы в выражении после ключевого слова >in. Как видите, мы могли бы воспользоваться ключевым словом >where для той же цели. Обратите внимание, что имена также выровнены по одной вертикальной позиции. Ну и какая разница между определениями в секциях >where и >let? Просто, похоже, в секции >let сначала следуют определения, а затем выражение, а в секции >where – наоборот.

На самом деле различие в том, что определения >let сами по себе являются выражениями. Определения в секциях >where – просто синтаксические конструкции. Если нечто является выражением, то у него есть значение. >"Фуу!" – это выражение, и >3+5 – выражение, и даже >head [1,2,3]. Это означает, что определение >let можно использовать практически где угодно, например:

>ghci> 4 * (let a = 9 in a + 1) + 2

>42

Ключевое слово >let подойдёт для определения локальных функций:

>ghci> [let square x = x * x in (square 5, square 3, square 2)]

>[(25,9,4)]

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