- PVSM.RU - https://www.pvsm.ru -
Друзья, продолжаем разбираться в функциональном программировании. Во второй части из этой серии статей вы познакомитесь с основными принципами этой парадигмы разработки и поймёте, как этот подход отличается от объектно-ориентированного или императивного программирования.

Первая часть [1].
Ещё раз рассмотрим эту простую функцию.
let add1 x = x + 1
Что здесь означает «x»:
x» для предоставления этого значения, чтоб к нему можно было обратиться позже.Использование имени для представления значения называется «привязкой» (binding). Имя «x» «привязано» к входному значению.
Так что если вычислить функцию с входным значением, скажем, равным 5, то произойдёт следующее: везде, где стоит «x» в изначальном определении, ставится значение 5, аналогично функции «найти и заменить» в текстовом редакторе.
let add1 x = x + 1
add1 5
// заменяем «x» with «5»
// add1 5 = 5 + 1 = 6
// результат 6
Важно понимать, что это не присваивание. «x» не «слот» и не переменная с присвоенным значением, которое можно изменить позднее. Это разовая ассоциация имени «x» с неким значением. Это значение — одно из предопределённых целых чисел, оно не может быть изменено. Т.е. однажды привязанный x не может быть изменён. Метка единожды ассоциированная со значением, навсегда связана с этим значением.
Данный принцип — критически важная часть функционального : нет «переменных», только значения.
Если поразмыслить над этим чуть подольше, можно увидеть, что имя «add1» само по себе — это просто привязка к «функции, которая увеличивает ввод на единицу». Сама функция независима от имени, которое к ней привязано.
Введя let add1 x = x + 1, мы говорим компилятору F# «каждый раз когда ты видишь имя «add1», замени его на функцию, которая добавляет 1 к вводу». «add1» называется функцией-значением (function value).
Чтобы увидеть, что функция не зависит от своего имени, достаточно выполнить следующий код:
let add1 x = x + 1
let plus1 = add1
add1 5
plus1 5
Как видно, «add'» и «plus» — это два имени, привязанных к одной и той же функции.
Идентифицировать функцию-значение всегда можно по её сигнатуре, которая имеет стандартную форму domain -> range. Обобщенная сигнатура функции-значения:
val functionName : domain -> range
Представим операцию, которая ничего не принимает и всегда возвращает 5.

Это была бы «константная» операция.
Как можно было бы описать это в F#? Мы хотим сказать компилятору: «каждый раз, когда ты видишь имя c, замени его на 5». Вот так:
let c = 5
При вычислении вернётся:
val c : int = 5
В этот раз нет стрелки сопоставления, всего лишь один int. Из нового — знак равенства с реальным значением, выведенным после него. F# компилятор знает, что эта привязка имеет известное значение, которое будет возвращаться всегда, а именно — число 5.
Другими словами, мы только что определили константу, или, в терминах F#, простое значение.
Всегда можно отличить простое значение от функции-значения, потому все простые значения имеют подобную сигнатуру:
val aName: type = constant // Заметьте - стрелки отсутствуют
Важно понять, что в F#, в отличии от других языков, таких, как C#, существует очень небольшая разница между простыми значения и функциями-значениями. Оба типа являются значениями, которые могут быть связаны с именами (используя ключевое слово let), после чего они могут быть переданы везде. На самом деле, скоро мы увидим, идея о том, что функции — это значения, которые могут быть переданы как входные данные другим функциям, является одним из ключевых аспектов функционального
Следует учесть, что существует небольшая разница между простым значением и функцией-значением. Функция всегда имеет domain и range, и должна быть «применена» к аргументу, чтобы вернуть результат. Простое значение не надо вычислять после привязки. Используя пример выше, если мы захотим определить «константную функцию» которая возвращает 5, мы могли бы использовать:
let c = fun()->5
// or
let c() = 5
Сигнатура таких функций выглядит так:
val c : unit -> int
А не так:
val c : int = 5
Больше информации о unit, синтаксисе функций и анонимных функциях будет дано позднее.
В функциональных языках программирования, таких как F#, большинство вещей называется «значениями». В объектно-ориентированных языках, таких как C#, большинство вещей называются «объектами». Какова разница между «значением» и «объектом»?
Значение, как мы видели выше, является членом domain (домена). Домен целых чисел, домен строк, домен функций, которые сопоставляют целым числам строки, и так далее. В принципе, значения иммутабельны (не изменяемы). И значения не имеют поведения, прикрепленного к ним.
Объекты в каноническом определении являются инкапсуляцией структуры данных с ассоциированным поведением (методами). В общем случае, объекты должны иметь состояние (то есть, быть изменяемыми), и все операции, которые меняют внутреннее состояние, должны предоставляться самим объектом (через «dot»-нотацию).
В F#, даже примитивные значения обладают некоторым объем «объектного» поведения. Например, можно через точку получить длину строки:
«abc».Length
Но в целом, мы будем избегать термина «объект» для стандартных значений в F#, приберегая к нему для обращения к полноценным классам, или другим значениям, предоставляющим методы.
Стандартные правила именования, используемые для имён значений и функций, в основном, это алфавитно-цифровая строка + символы подчеркивания. Но есть пара дополнений:
A'b'c begin' // валидные имена
let f = x
let f' = derivative f
let f'' = derivative f'
или для переменных одноименных существующим ключевым словам
let if' b t f = if b then t else f
Можно также использовать двойные обратные кавычки для любой строки, чтобы сделать ее допустимым идентификатором.
``this is a name`` ``123`` //валидные имена
Случаи, когда может понадобиться использование трюка с двойными обратными кавычками:
let ``begin`` = «begin»
let ``is first time customer?`` = true
let ``add gift to order`` = ()
if ``is first time customer?`` then ``add gift to order``
// Юнит-тест
let [<Test>] ``When input is 2 then expect square is 4``=
// code here
// BDD clause
let [<Given>] ``I have (.*) N products in my cart`` (n:int) =
// code here
В отличие от C#, конвенция именования F# требует, чтобы функции и значения начинались со строчной буквы, а не прописной (camelCase, а не PascalCase), кроме тех случаев, когда они предназначены для взаимодействия с другими языками .NET. Однако типы и модули используют заглавные буквы (в начале).
Для F# существует множество самоучителей, включая материалы для тех, кто пришел с опытом C# или Java. Следующие ссылки могут быть полезными по мере того, как вы будете глубже изучать F#:
Также описаны еще несколько способов, как начать изучение F# [7].
И наконец, сообщество F# очень дружелюбно к начинающим. Есть очень активный чат в Slack, поддерживаемый F# Software Foundation, с комнатами для начинающих, к которым вы можете свободно присоединиться [8]. Мы настоятельно рекомендуем вам это сделать!
Не забудьте посетить сайт русскоязычного сообщества F# [9]! Если у вас возникнут вопросы по изучению языка, мы будем рады обсудить их в чатах:
#ru_general в Slack-чате F# Software Foundation [8]Автор перевода @kleidemos [12]
Перевод и редакторские правки сделаны усилиями русскоязычного сообщества F#-разработчиков [9]. Мы также благодарим @schvepsss [13] и @shwars [14] за подготовку данной статьи к публикации.
Автор: shwars
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/290756
Ссылки в тексте:
[1] Первая часть: https://habr.com/company/microsoft/blog/415189/
[2] мышления: http://www.braintools.ru
[3] F# Guide: https://docs.microsoft.com/en-US/dotnet/fsharp/
[4] F# for Fun and Profit: https://swlaschin.gitbooks.io/fsharpforfunandprofit/content/
[5] F# Wiki: https://en.wikibooks.org/wiki/F_Sharp_Programming
[6] Learn X in Y Minutes: F#: https://learnxinyminutes.com/docs/fsharp/
[7] начать изучение F#: https://docs.microsoft.com/en-us/dotnet/fsharp/get-started/
[8] можете свободно присоединиться: http://foundation.fsharp.org/join
[9] русскоязычного сообщества F#: http://fsharplang.ru
[10] чат в Telegram: https://t.me/Fsharp_chat
[11] чат в Gitter: http://gitter.im/fsharplang_ru
[12] @kleidemos: https://habrahabr.ru/users/kleidemos/
[13] @schvepsss: https://habrahabr.ru/users/schvepsss/
[14] @shwars: https://habr.com/users/shwars/
[15] Источник: https://habr.com/post/420039/?utm_campaign=420039
Нажмите здесь для печати.