Учебники

F # — Краткое руководство

F # — Обзор

F # — это функциональный язык программирования. Чтобы понять конструкции F #, вам нужно прочитать пару строк о парадигме программирования, называемой функциональным программированием .

Функциональное программирование рассматривает компьютерные программы как математические функции. В функциональном программировании основное внимание будет уделяться константам и функциям, а не переменным и состояниям. Потому что функции и константы — это вещи, которые не меняются.

В функциональном программировании вы будете писать модульные программы, то есть программы будут состоять из функций, которые будут принимать другие функции в качестве входных данных.

Программы, написанные на функциональном языке программирования, как правило, лаконичны.

О F #

Ниже приведены основные сведения о F # —

  • Он был разработан в 2005 году в Microsoft Research.
  • Это часть семейства Microsoft .Net языка.
  • Это функциональный язык программирования.
  • Он основан на функциональном языке программирования OCaml.

Особенности F #

  • Это реализация .Net OCaml.

  • Он компилирует байт-код .Net CLI (Common Language Interface) или MSIL (Microsoft Intermediate Language), который работает на CLR (Common Language Runtime).

  • Это обеспечивает вывод типа.

  • Это обеспечивает богатые конструкции сопоставления с образцом.

  • Он имеет интерактивные возможности сценариев и отладки.

  • Это позволяет писать функции более высокого порядка.

  • Это обеспечивает хорошо разработанную объектную модель.

Это реализация .Net OCaml.

Он компилирует байт-код .Net CLI (Common Language Interface) или MSIL (Microsoft Intermediate Language), который работает на CLR (Common Language Runtime).

Это обеспечивает вывод типа.

Это обеспечивает богатые конструкции сопоставления с образцом.

Он имеет интерактивные возможности сценариев и отладки.

Это позволяет писать функции более высокого порядка.

Это обеспечивает хорошо разработанную объектную модель.

Использование F #

F # обычно используется в следующих областях —

  • Создание научной модели
  • Решение математических задач
  • Исследовательская работа по искусственному интеллекту
  • Финансовое моделирование
  • Графический дизайн
  • Дизайн процессора
  • Программирование компилятора
  • связь

Он также используется в приложениях CRUD, веб-страницах, играх с графическим интерфейсом и других программах общего назначения.

F # — Настройка среды

Инструменты, необходимые для программирования на F #, обсуждаются в этой главе.

Интегрированная среда разработки (IDE) для F #

Microsoft предоставляет Visual Studio 2013 для F # программирования.

Бесплатная версия Visual Studio 2013 Community Edition доступна на официальном сайте Microsoft. Visual Studio 2013 Community и более поздние версии поставляются с инструментами Visual F #. Подробная информация об установке доступна на учебнике Asp.net . Средства Visual F # включают в себя компилятор командной строки (fsc.exe) и F # Interactive (fsi.exe).

Установщик Visual Studio

Используя эти инструменты, вы можете писать все виды программ на F # от простых приложений командной строки до более сложных приложений. Вы также можете писать файлы исходного кода F # с помощью обычного текстового редактора, такого как Блокнот, и компилировать код в сборки, используя компилятор командной строки.

Вы можете скачать его из Microsoft Visual Studio. Он автоматически устанавливается на ваш компьютер.

Написание F # программ по ссылкам

Пожалуйста, посетите официальный сайт F # для получения последних инструкций по получению инструментов в виде пакета Debian или их компиляции непосредственно из источника — https://fsharp.org/use/linux/.

F # — Структура программы

F # — это язык функционального программирования.

В F # функции работают как типы данных. Вы можете объявить и использовать функцию так же, как и любую другую переменную.

В общем случае приложение F # не имеет какой-либо конкретной точки входа. Компилятор выполняет все операторы верхнего уровня в файле сверху вниз.

Тем не менее, для соблюдения процедурного стиля программирования многие приложения сохраняют единый оператор верхнего уровня, который вызывает основной цикл.

Следующий код показывает простую программу F # —

Live Demo

open System
(* This is a multi-line comment *)
// This is a single-line comment

let sign num =
   if num > 0 then "positive"
   elif num < 0 then "negative"
   else "zero"

let main() =
   Console.WriteLine("sign 5: {0}", (sign 5))

main()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

sign 5: positive

Пожалуйста, обратите внимание, что —

  • Файл кода F # может начинаться с нескольких открытых операторов, которые используются для импорта пространств имен.

  • Тело файлов включает в себя другие функции, которые реализуют бизнес-логику приложения.

  • Основной цикл содержит верхние исполняемые операторы.

Файл кода F # может начинаться с нескольких открытых операторов, которые используются для импорта пространств имен.

Тело файлов включает в себя другие функции, которые реализуют бизнес-логику приложения.

Основной цикл содержит верхние исполняемые операторы.

F # — основной синтаксис

Вы видели базовую структуру программы на F #, поэтому вам будет легко понять другие основные строительные блоки языка программирования F #.

Жетоны в F #

Программа F # состоит из различных токенов. Токен может быть ключевым словом, идентификатором, константой, строковым литералом или символом. Мы можем разделить токены F # на два типа:

  • Ключевые слова
  • Символ и операторы

F # Ключевые слова

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

Ключевое слово Описание
Аннотация Указывает на метод, который либо не имеет реализации в типе, в котором он объявлен, либо является виртуальным и имеет реализацию по умолчанию.
а также Используется во взаимно рекурсивных привязках, в объявлениях свойств и с несколькими ограничениями на общие параметры.
как Используется для присвоения объекту текущего класса имени объекта. Также используется для присвоения имени целому шаблону в соответствии с шаблоном.
утверждать Используется для проверки кода во время отладки.
база Используется в качестве имени объекта базового класса.
начать В подробном синтаксисе указывает начало блока кода.
учебный класс В подробном синтаксисе указывает начало определения класса.
дефолт Указывает на реализацию абстрактного метода; используется вместе с объявлением абстрактного метода для создания виртуального метода.
делегат Используется для объявления делегата.
делать Используется в циклических конструкциях или для выполнения императивного кода.
сделанный В подробном синтаксисе указывает конец блока кода в циклическом выражении.
удрученный Используется для преобразования в тип, который находится ниже в цепочке наследования.
Downto В выражении for , используемом для обратного отсчета.
Элиф Используется в условном ветвлении. Краткая форма еще, если.
еще Используется в условном ветвлении.
конец

В определениях типов и расширениях типов указывает конец раздела определений элементов.

В подробном синтаксисе используется для указания конца блока кода, который начинается с ключевого слова begin.

исключение Используется для объявления типа исключения.
внешний Указывает, что объявленный программный элемент определен в другом двоичном файле или сборке.
ложный Используется как логический литерал.
в конце концов Используется вместе с попыткой ввести блок кода, который выполняется независимо от того, происходит ли исключение.
за Используется в циклических конструкциях.
веселье Используется в лямбда-выражениях, также известных как анонимные функции.
функция Используется в качестве более короткой альтернативы ключевому слову fun и выражению соответствия в лямбда-выражении с сопоставлением с шаблоном в одном аргументе.
Глобальный Используется для ссылки на пространство имен .NET верхнего уровня.
если Используется в условных ветвящихся конструкциях.
в Используется для выражений последовательности и, в подробном синтаксисе, для отделения выражений от привязок.
унаследовать Используется для указания базового класса или базового интерфейса.
в соответствии Используется для обозначения функции, которая должна быть интегрирована непосредственно в код вызывающего абонента.
интерфейс Используется для объявления и реализации интерфейсов.
внутренний Используется для указания того, что элемент виден внутри сборки, но не снаружи.
ленивый Используется для указания вычисления, которое должно выполняться только тогда, когда требуется результат.
позволять Используется для привязки или привязки имени к значению или функции.
позволять! Используется в асинхронных рабочих процессах для привязки имени к результату асинхронного вычисления или в других выражениях вычислений, используется для привязки имени к результату, который имеет тип вычисления.
матч Используется для ветвления путем сравнения значения с шаблоном.
член Используется для объявления свойства или метода в типе объекта.
модуль Используется для связывания имени с группой связанных типов, значений и функций, чтобы логически отделить его от другого кода.
изменчивый Используется для объявления переменной, то есть значения, которое можно изменить.
Пространство имен Используется для связывания имени с группой связанных типов и модулей, чтобы логически отделить его от другого кода.
новый

Используется для объявления, определения или вызова конструктора, который создает или может создавать объект.

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

не На самом деле не ключевое слово. Однако, не структура в комбинации используется как ограничение общего параметра.
ноль

Указывает на отсутствие объекта.

Также используется в общих ограничениях параметров.

из Используется в различимых объединениях для указания типа категорий значений, а также в объявлениях делегатов и исключений.
открыть Используется, чтобы сделать содержимое пространства имен или модуля доступным без квалификации.
или же

Используется с логическими условиями в качестве логического или оператора. Эквивалент ||

Также используется в ограничениях членов.

переопределение Используется для реализации версии абстрактного или виртуального метода, которая отличается от базовой версии.
частный Ограничивает доступ члена к коду того же типа или модуля.
общественности Разрешает доступ к члену вне типа.
запись Используется для указания того, что функция является рекурсивной.
вернуть Используется для указания значения, предоставляемого в результате выражения вычисления.
вернуть! Используется для указания выражения вычисления, которое при оценке предоставляет результат содержащего выражения вычисления.
Выбрать Используется в выражениях запросов, чтобы указать, какие поля или столбцы нужно извлечь. Обратите внимание, что это контекстное ключевое слово, что означает, что оно на самом деле не является зарезервированным словом и действует только как ключевое слово в соответствующем контексте.
статический Используется для указания метода или свойства, которое может быть вызвано без экземпляра типа, или элемента значения, который используется всеми экземплярами типа.
структура

Используется для объявления типа структуры.

Также используется в общих ограничениях параметров.

Используется для совместимости с OCaml в определениях модулей.

затем

Используется в условных выражениях.

Также используется для выполнения побочных эффектов после строительства объекта.

в Используется в циклах for для обозначения диапазона.
правда Используется как логический литерал.
пытаться Используется для введения блока кода, который может генерировать исключение. Используется вместе с или наконец.
тип Используется для объявления класса, записи, структуры, различаемого объединения, типа перечисления, единицы измерения или сокращения типа.
вентиляционный Используется для преобразования в тип, который находится выше в цепочке наследования.
использование Используется вместо let для значений, которые требуют вызова Dispose для освобождения ресурсов.
использовать! Используется вместо пусть! в асинхронных рабочих процессах и других выражениях вычислений для значений, которые требуют, чтобы Dispose вызывался для освобождения ресурсов.
вал Используется в подписи для обозначения значения или в типе для объявления члена в ограниченных ситуациях.
недействительным Указывает тип .NET void. Используется при взаимодействии с другими языками .NET.
когда Используется для логических условий (когда охранники) при сопоставлении с образцом и для введения условия ограничения для параметра универсального типа.
в то время как Вводит циклическую конструкцию.
с Используется вместе с ключевым словом соответствия в выражениях сопоставления с образцом. Также используется в объектных выражениях, выражениях копирования записей и расширениях типов для представления определений членов и для представления обработчиков исключений.
Уступать Используется в выражении последовательности для получения значения последовательности.
Уступать! Используется в выражении вычисления, чтобы добавить результат данного выражения вычисления в коллекцию результатов для содержащего выражения вычисления.

В определениях типов и расширениях типов указывает конец раздела определений элементов.

В подробном синтаксисе используется для указания конца блока кода, который начинается с ключевого слова begin.

Используется для объявления, определения или вызова конструктора, который создает или может создавать объект.

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

Указывает на отсутствие объекта.

Также используется в общих ограничениях параметров.

Используется с логическими условиями в качестве логического или оператора. Эквивалент ||

Также используется в ограничениях членов.

Используется для объявления типа структуры.

Также используется в общих ограничениях параметров.

Используется для совместимости с OCaml в определениях модулей.

Используется в условных выражениях.

Также используется для выполнения побочных эффектов после строительства объекта.

Некоторые зарезервированные ключевые слова пришли из языка OCaml —

аср земельные участки лор LSL LSR lxor модификация сиг

Некоторые другие зарезервированные ключевые слова сохраняются для будущего расширения F #.

атомное перерыв проверено составная часть Const ограничение конструктор
Продолжить нетерпеливый событие внешний фиксированный функтор включают
метод Mixin объект параллельно процесс защищенный чистый
запечатанный tailcall черта характера виртуальный летучий

Комментарии в F #

F # предоставляет два типа комментариев —

  • Однострочный комментарий начинается с символа //.
  • Многострочный комментарий начинается с (* и заканчивается *).

Базовая точка входа в программу и приложение в F #

Как правило, у вас нет явной точки входа для программ на F #. Когда вы компилируете приложение F #, последний файл, предоставленный компилятору, становится точкой входа, и все операторы верхнего уровня в этом файле выполняются сверху вниз.

Хорошо написанная программа должна иметь один оператор верхнего уровня, который будет вызывать основной цикл программы.

Очень минималистичная F # -программа, которая будет отображать «Hello World» на экране —

Live Demo

(* This is a comment *)
(* Sample Hello World program using F# *)
printfn "Hello World!"

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Hello World!

F # — Типы данных

Типы данных в F # можно классифицировать следующим образом:

  • Интегральные типы
  • Типы с плавающей точкой
  • Типы текста
  • Другие типы

Интегральный тип данных

В следующей таблице приведены интегральные типы данных F #. Это в основном целочисленные типы данных.

Тип F # Размер Спектр пример замечания
SByte 1 байт От -128 до 127

42y

-11y

8-разрядное целое число со знаком
байт 1 байт От 0 до 255

42uy

200uy

8-битное целое число без знака
int16 2 байта От -32768 до 32767

42s

-11s

16-разрядное целое число со знаком
uint16 2 байта От 0 до 65 535

42us

200us

16-разрядное целое число без знака
INT / int32 4 байта От -2 147 483 648 до 2 147 483 647

42

-11

32-разрядное целое число со знаком
uint32 4 байта От 0 до 4 294 967 295

42U

200U

32-разрядное целое число без знака
int64 8 байт От -9,223,372,036,854,775,808 до 9,223,372,036,854,775,807

42L

-11L

64-разрядное целое число со знаком
uint64 8 байт От 0 до 18 446 744 073 709 551 615

42UL

200ul

64-разрядное целое число без знака
BIGINT Не менее 4 байтов любое целое число

42i

1499999

9999999

9999999

9999999

9999i

произвольное число точности

42y

-11y

42uy

200uy

42s

-11s

42us

200us

42

-11

42U

200U

42L

-11L

42UL

200ul

42i

1499999

9999999

9999999

9999999

9999i

пример

Live Demo

(* single byte integer *)
let x = 268.97f
let y = 312.58f
let z = x + y

printfn "x: %f" x
printfn "y: %f" y
printfn "z: %f" z

(* unsigned 8-bit natural number *)

let p = 2uy
let q = 4uy
let r = p + q

printfn "p: %i" p
printfn "q: %i" q
printfn "r: %i" r

(* signed 16-bit integer *)

let a = 12s
let b = 24s
let c = a + b

printfn "a: %i" a
printfn "b: %i" b
printfn "c: %i" c

(* signed 32-bit integer *)

let d = 212l
let e = 504l
let f = d + e

printfn "d: %i" d
printfn "e: %i" e
printfn "f: %i" f

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

x: 1
y: 2
z: 3
p: 2
q: 4
r: 6
a: 12
b: 24
c: 36
d: 212
e: 504
f: 716

Типы данных с плавающей точкой

В следующей таблице представлены типы данных с плавающей запятой F #.

Тип F # Размер Спектр пример замечания
float32 4 байта ± 1,5e-45 до ± 3,4e38

42.0F

-11.0F

32-разрядное число с плавающей запятой со знаком (7 значащих цифр)
поплавок 8 байт От ± 5,0e-324 до ± 1,7e308

42,0

-11,0

64-разрядное число с плавающей запятой со знаком (15-16 значащих цифр)
десятичный 16 байт ± 1,0e-28 до ± 7,9e28

42.0M

-11.0M

128-битное число с плавающей запятой со знаком (28-29 значащих цифр)
BigRational Не менее 4 байтов Любое рациональное число.

42N

-11N

Произвольная точность рационального числа. Для использования этого типа требуется ссылка на FSharp.PowerPack.dll.

42.0F

-11.0F

42,0

-11,0

42.0M

-11.0M

42N

-11N

пример

Live Demo

(* 32-bit signed floating point number *)
(* 7 significant digits *)

let d = 212.098f
let e = 504.768f
let f = d + e

printfn "d: %f" d
printfn "e: %f" e
printfn "f: %f" f

(* 64-bit signed floating point number *)
(* 15-16 significant digits *)
let x = 21290.098
let y = 50446.768
let z = x + y

printfn "x: %g" x
printfn "y: %g" y
printfn "z: %g" z

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

d: 212.098000
e: 504.768000
f: 716.866000
x: 21290.1
y: 50446.8
z: 71736.9

Типы текстовых данных

В следующей таблице приведены типы текстовых данных F #.

Тип F # Размер Спектр пример замечания
голец 2 байта От U + 0000 до U + FFFF

‘Икс’

«\ Т»

Одиночные символы юникода
строка 20 + (2 * длина строки) байтов От 0 до около 2 миллиардов символов

«Привет»

«Мир»

Текст Unicode

‘Икс’

«\ Т»

«Привет»

«Мир»

пример

Live Demo

let choice = 'y'
let name = "Zara Ali"
let org = "Tutorials Point"

printfn "Choice: %c" choice
printfn "Name: %s" name
printfn "Organisation: %s" org

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Choice: y
Name: Zara Ali
Organisation: Tutorials Point

Другие типы данных

В следующей таблице приведены некоторые другие типы данных F #.

Тип F # Размер Спектр пример замечания
BOOL 1 байт Только два возможных значения, истина или ложь

правда

ложный

Хранит логические значения

правда

ложный

пример

Live Demo

let trueVal = true
let falseVal = false

printfn "True Value: %b" (trueVal)
printfn "False Value: %b" (falseVal)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

True Value: true
False Value: false

F # — Переменные

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

Объявление переменных в F #

Ключевое слово let используется для объявления переменных —

Например,

let x = 10

Он объявляет переменную x и присваивает ей значение 10.

Вы также можете назначить выражение для переменной —

let x = 10
let y = 20
let z = x + y

Следующий пример иллюстрирует концепцию —

пример

Live Demo

let x = 10
let y = 20
let z = x + y

printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

x: 10
y: 20
z: 30

Переменные в F # являются неизменяемыми, что означает , что как только переменная связана со значением, она не может быть изменена. Они фактически скомпилированы как статические свойства только для чтения.

Следующий пример демонстрирует это.

пример

Live Demo

let x = 10
let y = 20
let z = x + y

printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

let x = 15
let y = 20
let z = x + y

printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

Когда вы компилируете и запускаете программу, она показывает следующее сообщение об ошибке —

Duplicate definition of value 'x'
Duplicate definition of value 'Y'
Duplicate definition of value 'Z'

Определение переменной с объявлением типа

Определение переменной сообщает компилятору, где и сколько хранилища для переменной следует создать. Определение переменной может указывать тип данных и содержит список из одной или нескольких переменных этого типа, как показано в следующем примере.

пример

Live Demo

let x:int32 = 10
let y:int32 = 20
let z:int32 = x + y

printfn "x: %d" x
printfn "y: %d" y
printfn "z: %d" z

let p:float = 15.99
let q:float = 20.78
let r:float = p + q

printfn "p: %g" p
printfn "q: %g" q
printfn "r: %g" r

Когда вы компилируете и запускаете программу, она показывает следующее сообщение об ошибке —

x: 10
y: 20
z: 30
p: 15.99
q: 20.78
r: 36.77

Изменяемые переменные

Иногда вам нужно изменить значения, хранящиеся в переменной. Чтобы указать, что может быть изменение значения объявленной и присвоенной переменной, в более поздней части программы F # предоставляет ключевое слово mutable . Вы можете объявить и назначить изменяемые переменные, используя это ключевое слово, значения которого вы будете изменять.

Ключевое слово mutable позволяет объявлять и назначать значения в изменяемой переменной.

Вы можете присвоить некоторое начальное значение изменяемой переменной, используя ключевое слово let . Однако, чтобы присвоить ему новое последующее значение, вам нужно использовать оператор .

Например,

let mutable x = 10
x ← 15

Следующий пример прояснит концепцию —

пример

Live Demo

let mutable x = 10
let y = 20
let mutable z = x + y

printfn "Original Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

printfn "Let us change the value of x"
printfn "Value of z will change too."

x <- 15
z <- x + y

printfn "New Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Original Values:
x: 10
y: 20
z: 30
Let us change the value of x
Value of z will change too.
New Values:
x: 15
y: 20
z: 35

F # — Операторы

Оператор — это символ, который указывает компилятору выполнять определенные математические или логические манипуляции. F # богат встроенными операторами и предоставляет следующие типы операторов —

  • Арифметические Операторы
  • Операторы сравнения
  • Булевы операторы
  • Битовые операторы

Арифметические Операторы

В следующей таблице показаны все арифметические операторы, поддерживаемые языком F #. Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать пример

оператор Описание пример
+ Добавляет два операнда А + Б даст 30
Вычитает второй операнд из первого A — B даст -10
* Умножает оба операнда А * Б даст 200
/ Делит числитель на числитель Б / у даст 2
% Оператор модуля и остаток от целочисленного деления B% A даст 0
** Оператор возведения в степень, поднимает операнд во власть другого Б ** А даст 20 10

Операторы сравнения

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

Предположим, что переменная A содержит 10, а переменная B содержит 20, тогда —

Показать пример

оператор Описание пример
знак равно Проверяет, равны ли значения двух операндов или нет, если да, тогда условие становится истинным. (A == B) не соответствует действительности.
<> Проверяет, равны ли значения двух операндов или нет, если значения не равны, тогда условие становится истинным. (A <> B) верно.
> Проверяет, больше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A> B) не соответствует действительности.
< Проверяет, меньше ли значение левого операнда, чем значение правого операнда, если да, тогда условие становится истинным. (A <B) верно.
> = Проверяет, больше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A> = B) не соответствует действительности.
<= Проверяет, меньше ли значение левого операнда или равно значению правого операнда, если да, тогда условие становится истинным. (A <= B) верно.

Булевы операторы

В следующей таблице показаны все логические операторы, поддерживаемые языком F #. Предположим, что переменная A имеет значение true, а переменная B содержит значение false, тогда —

Показать пример

оператор Описание пример
&& Вызывается логическим оператором AND. Если оба операнда отличны от нуля, условие становится истинным. (A && B) неверно.
|| Вызывается логическим оператором ИЛИ Если любой из двух операндов отличен от нуля, условие становится истинным. (A || B) верно.
не Вызывается логическое НЕ оператор. Используйте для изменения логического состояния своего операнда. Если условие истинно, то оператор Логический НЕ будет делать ложь. не (A && B) верно.

Битовые операторы

Битовые операторы работают с битами и выполняют побитовые операции. Таблицы истинности для &&& (побитовое И), ||| (побитовое ИЛИ) и ^^^ (побитовое исключающее ИЛИ):

Показать пример

п Q p &&& q р ||| Q p ^^^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Предположим, если А = 60; и B = 13; теперь в двоичном формате они будут выглядеть следующим образом —

A = 0011 1100

B = 0000 1101

——————

A &&& B = 0000 1100

A ||| B = 0011 1101

A ^^^ B = 0011 0001

~~~ A = 1100 0011

Побитовые операторы, поддерживаемые языком F #, перечислены в следующей таблице. Предположим, что переменная A содержит 60, а переменная B содержит 13, тогда —

оператор Описание пример
&&& Двоичный оператор AND немного копирует результат, если он существует в обоих операндах. (A &&& B) даст 12, что составляет 0000 1100
||| Оператор двоичного ИЛИ копирует немного, если он существует в любом из операндов. (A ||| B) даст 61, что составляет 0011 1101
^^^ Двоичный оператор XOR копирует бит, если он установлен в одном операнде, но не в обоих. (A ^^^ B) даст 49, что составляет 0011 0001
~~~ Оператор дополнения двоичных единиц является унарным и имеет эффект «переворачивания» битов. (~~~ A) даст -61, что составляет 1100 0011 в форме дополнения 2.
<<< Двоичный оператор левого сдвига. Значение левого операнда перемещается влево на количество битов, указанное правым операндом. <<< 2 даст 240, что составляет 1111 0000
>>> Оператор двоичного правого сдвига. Значение левого операнда перемещается вправо на количество битов, указанное правым операндом. A >>> 2 даст 15, что равно 0000 1111

Приоритет операторов

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

Показать пример

оператор Ассоциативность
как Правильно
когда Правильно
| (Труба) Оставил
; Правильно
позволять Не ассоциативный
функция, веселье, матч, попытаться Не ассоциативный
если Не ассоциативный
Правильно
знак равно Правильно
, Не ассоциативный
или || Оставил
&, && Оставил
<op,> op, =, | op, & op Оставил
&&&, |||, ^^^, ~~~, <<<, >>> Оставил
^ op Правильно
:: Правильно
:?>,:? Не ассоциативный
— оп, + оп, (бинарный) Оставил
* op, / op,% op Оставил
** оп Правильно
fx (функция приложения) Оставил
| (образец соответствия) Правильно
префиксные операторы (+ op, -op,%, %%, &, &&,! op, ~ op) Оставил
, Оставил
F (X) Оставил
F <типы> Оставил

F # — Принятие решений

Структуры принятия решений требуют, чтобы программист определил одно или несколько условий, которые будут оцениваться или тестироваться программой. Это должно быть вместе с оператором или инструкциями, которые должны быть выполнены, если условие определено как истинное, и, необязательно, другие операторы, которые должны быть выполнены, если условие определено как ложное.

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

Принятие решения

Язык программирования F # предоставляет следующие типы операторов принятия решений.

утверждение Описание
утверждение if / then Оператор if / then состоит из логического выражения, за которым следует один или несколько операторов.
оператор if / then / else За оператором if / then может следовать необязательный оператор else, который выполняется, когда логическое выражение имеет значение false.
оператор if / then / elif / else Оператор if / then / elif / else позволяет вам иметь несколько других ветвей.
вложенные операторы if Вы можете использовать один оператор if или else if внутри другого оператора if или else if .

F # — Петли

Языки программирования предоставляют различные управляющие структуры, которые допускают более сложные пути выполнения.

Оператор цикла позволяет нам выполнять оператор или группу операторов несколько раз, и в большинстве языков программирования ниже приводится общая форма инструкции цикла.

Loop Statement

F # предоставляет следующие типы циклов для обработки требований цикла.

Тип петли Описание
для … для и для … вниз выражения Выражение for … to используется для итерации в цикле по диапазону значений переменной цикла. Выражение for… downto уменьшает значение переменной цикла.
для … в выражении Эта форма цикла for используется для перебора коллекций элементов, т. Е. Циклов над коллекциями и последовательностями.
Пока… делай петлю Повторяет оператор или группу операторов, пока данное условие выполняется. Он проверяет условие перед выполнением тела цикла.
вложенные циклы Вы можете использовать один или несколько циклов внутри любого другого цикла for или while.

F # — Функции

В F # функции работают как типы данных. Вы можете объявить и использовать функцию так же, как и любую другую переменную.

Поскольку функции могут использоваться как любые другие переменные, вы можете —

  • Создайте функцию с именем и свяжите это имя с типом.
  • Назначьте это значение.
  • Выполните некоторые расчеты по этому значению.
  • Передайте его в качестве параметра другой функции или подпрограмме.
  • Вернуть функцию как результат другой функции.

Определение функции

Функции определяются с помощью ключевого слова let . Определение функции имеет следующий синтаксис —

let [inline] function-name parameter-list [ : return-type ]
= function-body

Куда,

  • имя-функции — это идентификатор, который представляет функцию.

  • Параметр-список дает список параметров, разделенных пробелами. Вы также можете указать явный тип для каждого параметра и, если он не указан, компилятор стремится вывести его из тела функции (например, переменных).

  • function-body состоит из выражения или составного выражения, состоящего из ряда выражений. Последнее выражение в теле функции — это возвращаемое значение.

  • return-type — это двоеточие, за которым следует тип, и является необязательным. Если тип возвращаемого значения не указан, компилятор определяет его по окончательному выражению в теле функции.

имя-функции — это идентификатор, который представляет функцию.

Параметр-список дает список параметров, разделенных пробелами. Вы также можете указать явный тип для каждого параметра и, если он не указан, компилятор стремится вывести его из тела функции (например, переменных).

function-body состоит из выражения или составного выражения, состоящего из ряда выражений. Последнее выражение в теле функции — это возвращаемое значение.

return-type — это двоеточие, за которым следует тип, и является необязательным. Если тип возвращаемого значения не указан, компилятор определяет его по окончательному выражению в теле функции.

Параметры функции

Вы перечисляете имена параметров сразу после имени функции. Вы можете указать тип параметра. Тип параметра должен следовать за именем параметра, разделенным двоеточием.

Если тип параметра не указан, он выводится компилятором.

Например —

let doubleIt (x : int) = 2 * x

Вызов функции

Функция вызывается путем указания имени функции, за которым следует пробел, а затем любые аргументы, разделенные пробелами.

Например —

let vol = cylinderVolume 3.0 5.0

Следующие программы иллюстрируют концепции.

Пример 1

Следующая программа вычисляет объем цилиндра, когда радиус и длина заданы как параметры

Live Demo

// the function calculates the volume of
// a cylinder with radius and length as parameters

let cylinderVolume radius length : float =

   // function body
   let pi = 3.14159
   length * pi * radius * radius

let vol = cylinderVolume 3.0 5.0
printfn " Volume: %g " vol

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Volume: 141.372

Пример 2

Следующая программа возвращает большее значение двух заданных параметров —

Live Demo

// the function returns the larger value between two
// arguments

let max num1 num2 : int32 =
   // function body
   if(num1>num2)then
      num1
   else
      num2

let res = max 39 52
printfn " Max Value: %d " res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Max Value: 52

Пример 3

Live Demo

let doubleIt (x : int) = 2 * x
printfn "Double 19: %d" ( doubleIt(19))

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Double 19: 38

Рекурсивные функции

Рекурсивные функции — это функции, которые вызывают сами себя.

Вы определяете рекурсив с помощью комбинации ключевых слов let rec .

Синтаксис для определения рекурсивной функции —

//Recursive function definition
let rec function-name parameter-list = recursive-function-body

Например —

let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)

Пример 1

Следующая программа возвращает Фибоначчи от 1 до 10 —

Live Demo

let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2)
for i = 1 to 10 do
   printfn "Fibonacci %d: %d" i (fib i)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Fibonacci 1: 1
Fibonacci 2: 2
Fibonacci 3: 3
Fibonacci 4: 5
Fibonacci 5: 8
Fibonacci 6: 13
Fibonacci 7: 21
Fibonacci 8: 34
Fibonacci 9: 55
Fibonacci 10: 89

Пример 2

Следующая программа возвращает факториал 8 —

Live Demo

open System
let rec fact x =
   if x < 1 then 1
   else x * fact (x - 1)
Console.WriteLine(fact 8)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

40320

Обозначения стрелок в F #

F # сообщает о типе данных в функциях и значениях, используя цепочку обозначений стрелок. Давайте возьмем пример функции, которая принимает один ввод int и возвращает строку. В обозначении стрелки это написано как —

int -> string

Типы данных читаются слева направо.

Давайте возьмем другую гипотетическую функцию, которая принимает два ввода данных int и возвращает строку.

let mydivfunction x y = (x / y).ToString();;

F # сообщает тип данных, используя цепочку обозначений стрелок как —

val mydivfunction : x:int -> y:int -> string

Тип возвращаемого значения представлен крайним правым типом данных в нотации со стрелками.

Еще несколько примеров —

нотация Имея в виду
плавать → плавать → плавать Функция принимает два входа с плавающей точкой , возвращает еще один с плавающей точкой .
int → string → float Функция принимает int и строковый ввод, возвращает число с плавающей запятой .

Лямбда-выражения

Лямбда-выражение — это безымянная функция.

Давайте возьмем пример двух функций —

Live Demo

let applyFunction ( f: int -> int -> int) x y = f x y
let mul x y = x * y
let res = applyFunction mul 5 7
printfn "%d" res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

35

Теперь в приведенном выше примере, если бы вместо определения функции mul мы могли бы использовать лямбда-выражения как —

Live Demo

let applyFunction ( f: int -> int -> int) x y = f x y
let res = applyFunction (fun x y -> x * y ) 5 7
printfn "%d" res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

35

Композиция функций и конвейерная обработка

В F # одна функция может быть составлена ​​из других функций.

В следующем примере показана композиция функции с именем f из двух функций function1 и function2 —

Live Demo

let function1 x = x + 1
let function2 x = x * 5

let f = function1 >> function2
let res = f 10
printfn "%d" res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

55

F # также предоставляет функцию, называемую конвейерной передачей функций. Конвейерная обработка позволяет объединять вызовы функций как последовательные операции.

Следующий пример показывает, что —

Live Demo

let function1 x = x + 1
let function2 x = x * 5

let res = 10 |> function1 |> function2
printfn "%d" res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

55

F # — Струны

В F # строковый тип представляет неизменный текст как последовательность символов Юникода.

Строковые литералы

Строковые литералы разделяются символом кавычки («).

Для специальных целей используются некоторые специальные символы, такие как перевод строки, табуляция и т. Д. Они кодируются с использованием символа обратной косой черты (\). Символ обратной косой черты и связанный символ составляют escape-последовательность. В следующей таблице показана escape-последовательность, поддерживаемая F #.

символ Последовательность побега
возврат на одну позицию \ б
Новая линия \ п
Возврат каретки
табуляция \ т
бэкслэш \\
Кавычка
Апостроф
Unicode персонаж \ uXXXX или \ UXXXXXXXX (где X обозначает шестнадцатеричное число)

Способы игнорирования последовательности побега

Следующие два способа заставляют компилятор игнорировать escape-последовательность —

  • Используя символ @.
  • Заключение строки в тройные кавычки.

Когда строковому литералу предшествует символ @, он называется дословной строкой. Таким образом, все escape-последовательности в строке игнорируются, за исключением того, что два символа кавычки интерпретируются как один символ кавычки.

Если строка заключена в тройные кавычки, то игнорируются также все escape-последовательности, включая символы двойной кавычки.

пример

В следующем примере демонстрируется этот метод, показывающий, как работать с XML или другими структурами, включающими встроенные кавычки.

Live Demo

// Using a verbatim string
let xmldata = @"<book author=""Lewis, C.S"" title=""Narnia"">"
printfn "%s" xmldata

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

<book author="Lewis, C.S" title="Narnia">

Основные операторы на строках

В следующей таблице приведены основные операции со строками:

Значение Описание
собирать: (символ → строка) → строка → строка Создает новую строку, символы которой являются результатом применения указанной функции к каждому из символов входной строки и конкатенации полученных строк.
concat: string → seq <string> → string Возвращает новую строку, созданную путем объединения указанных строк с разделителем.
существует: (char → bool) → string → bool Проверяет, удовлетворяет ли какой-либо символ строки указанному предикату.
forall: (char → bool) → строка → bool Проверяет, все ли символы в строке удовлетворяют данному предикату.
init: int → (int → string) → string Создает новую строку, символы которой являются результатом применения указанной функции к каждому индексу и конкатенации полученных строк.
iter: (символ → единица) → строка → единица Применяет указанную функцию к каждому символу в строке.
iteri: (int → char → unit) → string → unit Применяет указанную функцию к индексу каждого символа в строке и самому символу.
длина: строка → int Возвращает длину строки.
карта: (символ → символ) → строка → строка Создает новую строку, символы которой являются результатом применения указанной функции к каждому из символов входной строки.
mapi: (int → char → char) → строка → строка Создает новую строку, символы которой являются результатом применения указанной функции к каждому символу и индексу входной строки.
копия: int → строка → строка Возвращает строку путем конкатенации указанного количества экземпляров строки.

Следующие примеры демонстрируют использование некоторых из вышеуказанных функций —

Пример 1

Функция String.collect создает новую строку, символы которой являются результатом применения указанной функции к каждому из символов входной строки и конкатенации полученных строк.

Live Demo

let collectTesting inputS =
   String.collect (fun c -> sprintf "%c " c) inputS
printfn "%s" (collectTesting "Happy New Year!")

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

H a p p y N e w Y e a r !

Пример 2

Функция String.concat объединяет данную последовательность строк с разделителем и возвращает новую строку.

Live Demo

let strings = [ "Tutorials Point"; "Coding Ground"; "Absolute Classes" ]
let ourProducts = String.concat "\n" strings
printfn "%s" ourProducts

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Tutorials Point
Coding Ground
Absolute Classes

Пример 3

Метод String.replicate возвращает строку путем конкатенации указанного количества экземпляров строки.

Live Demo

printfn "%s" <| String.replicate 10 "*! "

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

*! *! *! *! *! *! *! *! *! *!

F # — Опции

Тип опции в F # используется в вычислениях, когда может существовать или не существовать значение для переменной или функции. Типы опций используются для представления необязательных значений в расчетах. Они могут иметь два возможных значения — Some (x) или None .

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

Опция имеет базовый тип и может содержать значение этого типа или может не иметь значения.

Использование параметров

Давайте возьмем пример функции деления. Следующая программа объясняет это —

Давайте напишем функцию div и отправим ей два аргумента 20 и 5 —

Live Demo

let div x y = x / y
let res = div 20 5
printfn "Result: %d" res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Result: 4

Если второй аргумент равен нулю, то программа выдает исключение —

Live Demo

let div x y = x / y
let res = div 20 0
printfn "Result: %d" res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Unhandled Exception:
System.DivideByZeroException: Division by zero

В таких случаях мы можем использовать типы опций, чтобы возвращать Some (значение) в случае успешной операции или None в случае сбоя операции.

Следующий пример демонстрирует использование опций —

пример

Live Demo

let div x y =
   match y with
   | 0 -> None
   | _ -> Some(x/y)

let res : int option = div 20 4
printfn "Result: %A " res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Result: Some 5

Свойства и методы опций

Тип параметра поддерживает следующие свойства и методы:

Свойство или метод Тип Описание
Никто Т вариант Статическое свойство, позволяющее создать значение параметра со значением None .
IsNone BOOL Возвращает true, если параметр имеет значение None .
IsSome BOOL Возвращает true, если параметр имеет значение, отличное от None .
Немного Т вариант Статический член, который создает параметр, значение которого не равно None .
Значение «T Возвращает базовое значение или выдает исключение NullReferenceException, если значение равно None .

Пример 1

Live Demo

let checkPositive (a : int) =
   if a > 0 then
      Some(a)
   else
      None

let res : int option = checkPositive(-31)
printfn "Result: %A " res

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Result: <null>

Пример 2

Live Demo

let div x y =
   match y with
   | 0 -> None
   | _ -> Some(x/y)

let res : int option = div 20 4
printfn "Result: %A " res
printfn "Result: %A " res.Value

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Result: Some 5
Result: 5

Пример 3

Live Demo

let isHundred = function
   | Some(100) -> true
   | Some(_) | None -> false

printfn "%A" (isHundred (Some(45)))
printfn "%A" (isHundred (Some(100)))
printfn "%A" (isHundred None)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

false
true
false

F # — Кортежи

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

Например, («Зара Али», «Хайдарабад», 10) представляет собой 3-кортеж с двумя строковыми значениями и значением int, он имеет тип (string * string * int).

Кортежи могут быть парами, тройками и т. Д. Одного и того же или разных типов.

Некоторые примеры приведены здесь —

// Tuple of two integers.
( 4, 5 )

// Triple of strings.
( "one", "two", "three" )

// Tuple of unknown types.
( a, b )

// Tuple that has mixed types.
( "Absolute Classes", 1, 2.0 )

// Tuple of integer expressions.
( a * 4, b + 7)

пример

Эта программа имеет функцию, которая принимает кортеж из четырех значений с плавающей запятой и возвращает среднее значение —

Live Demo

let averageFour (a, b, c, d) =
   let sum = a + b + c + d
   sum / 4.0

let avg:float = averageFour (4.0, 5.1, 8.0, 12.0)
printfn "Avg of four numbers: %f" avg

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Avg of four numbers: 7.275000

Доступ к отдельным членам кортежа

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

Следующий пример иллюстрирует концепцию —

пример

Live Demo

let display tuple1 =
   match tuple1 with
   | (a, b, c) -> printfn "Detail Info: %A %A %A" a b c

display ("Zara Ali", "Hyderabad", 10 )

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Detail Info: "Zara Ali" "Hyderabad" 10

F # имеет две встроенные функции, fst и snd, которые возвращают первый и второй элементы в двух кортеже.

Следующий пример иллюстрирует концепцию —

пример

Live Demo

printfn "First member: %A" (fst(23, 30))
printfn "Second member: %A" (snd(23, 30))

printfn "First member: %A" (fst("Hello", "World!"))
printfn "Second member: %A" (snd("Hello", "World!"))

let nameTuple = ("Zara", "Ali")

printfn "First Name: %A" (fst nameTuple)
printfn "Second Name: %A" (snd nameTuple)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

First member: 23
Second member: 30
First member: "Hello"
Second member: "World!"
First Name: "Zara"
Second Name: "Ali"

F # — Записи

Запись похожа на кортеж, однако содержит именованные поля. Например,

type website =
   { title : string;
      url : string }

Определение записи

Запись определяется как тип с использованием ключевого слова type , а поля записи определяются как список, разделенный точкой с запятой.

Синтаксис для определения записи —

type recordName =
   { [ fieldName : dataType ] + }

Создание записи

Вы можете создать запись, указав ее поля. Например, давайте создадим запись веб-сайта с именем homepage

let homepage = { Title = "TutorialsPoint"; Url = "www.tutorialspoint.com" }

Следующие примеры объяснят понятия —

Пример 1

Эта программа определяет тип записи с именем веб-сайта. Затем он создает некоторые записи типа веб-сайта и печатает записи.

Live Demo

(* defining a record type named website *)
type website =
   { Title : string;
      Url : string }

(* creating some records *)
let homepage = { Title = "TutorialsPoint"; Url = "www.tutorialspoint.com" }
let cpage = { Title = "Learn C"; Url = "www.tutorialspoint.com/cprogramming/index.htm" }
let fsharppage = { Title = "Learn F#"; Url = "www.tutorialspoint.com/fsharp/index.htm" }
let csharppage = { Title = "Learn C#"; Url = "www.tutorialspoint.com/csharp/index.htm" }

(*printing records *)
(printfn "Home Page: Title: %A \n \t URL: %A") homepage.Title homepage.Url
(printfn "C Page: Title: %A \n \t URL: %A") cpage.Title cpage.Url
(printfn "F# Page: Title: %A \n \t URL: %A") fsharppage.Title fsharppage.Url
(printfn "C# Page: Title: %A \n \t URL: %A") csharppage.Title csharppage.Url

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Home Page: Title: "TutorialsPoint"
       URL: "www.tutorialspoint.com"
C Page: Title: "Learn C"
      URL: "www.tutorialspoint.com/cprogramming/index.htm"
F# Page: Title: "Learn F#"
      URL: "www.tutorialspoint.com/fsharp/index.htm"
C# Page: Title: "Learn C#"
      URL: "www.tutorialspoint.com/csharp/index.htm"

Пример 2

Live Demo

type student =
   { Name : string;
      ID : int;
      RegistrationText : string;
      IsRegistered : bool }

let getStudent name id =
   { Name = name; ID = id; RegistrationText = null; IsRegistered = false }

let registerStudent st =
   { st with
      RegistrationText = "Registered";
      IsRegistered = true }

let printStudent msg st =
   printfn "%s: %A" msg st

let main() =
   let preRegisteredStudent = getStudent "Zara" 10
   let postRegisteredStudent = registerStudent preRegisteredStudent

   printStudent "Before Registration: " preRegisteredStudent
   printStudent "After Registration: " postRegisteredStudent

main()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Before Registration: : {Name = "Zara";
   ID = 10;
   RegistrationText = null;
   IsRegistered = false;}
After Registration: : {Name = "Zara";
   ID = 10;
   RegistrationText = "Registered";
   IsRegistered = true;}

F # — Списки

В F # список — это упорядоченная, неизменная серия элементов одного типа. Это в какой-то степени эквивалентно структуре данных связанного списка.

Модуль F #, Microsoft.FSharp.Collections.List, имеет общие операции со списками. Однако F # импортирует этот модуль автоматически и делает его доступным для каждого приложения F #.

Создание и инициализация списка

Ниже приведены различные способы создания списков.

  • Использование списка литералов .

  • Использование оператора cons (: :).

  • Использование метода List.init модуля List.

  • Использование некоторых синтаксических конструкций, называемых списками .

Использование списка литералов .

Использование оператора cons (: :).

Использование метода List.init модуля List.

Использование некоторых синтаксических конструкций, называемых списками .

Список литералов

В этом методе вы просто указываете разделенную точкой с запятой последовательность значений в квадратных скобках. Например —

let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]

Минусы (: 🙂 Оператор

С помощью этого метода вы можете добавить некоторые значения, добавив или добавив их в существующий список с помощью оператора ::. Например —

let list2 = 1::2::3::4::5::6::7::8::9::10::[];;

[] обозначает пустой список.

Метод инициализации списка

Метод List.init модуля List часто используется для создания списков. Этот метод имеет тип —

val init : int -> (int -> 'T) -> 'T list

Первый аргумент — это желаемая длина нового списка, а второй аргумент — функция инициализатора, которая генерирует элементы в списке.

Например,

let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))

Здесь индексная функция генерирует список.

Список Пониманий

Постижения списков — это специальные синтаксические конструкции, используемые для генерации списков.

Синтаксис понимания списка F # представлен в двух формах — диапазонах и генераторах.

Диапазоны имеют конструкции — [начало .. конец] и [начало .. шаг .. конец]

Например,

let list3 = [1 .. 10]

Генераторы имеют конструкцию — [для x в коллекции do … yield expr]

Например,

let list6 = [ for a in 1 .. 10 do yield (a * a) ]

Когда ключевое слово yield помещает одно значение в список, ключевое слово yield !, помещает коллекцию значений в список.

Следующая функция демонстрирует вышеуказанные методы —

пример

Live Demo

(* using list literals *)
let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1

(*using cons operator *)
let list2 = 1 :: 2 :: 3 :: []
printfn "The list: %A" list2

(* using range constructs*)
let list3 = [1 .. 10]
printfn "The list: %A" list3

(* using range constructs *)
let list4 = ['a' .. 'm']
printfn "The list: %A" list4

(* using init method *)
let list5 = List.init 5 (fun index -> (index, index * index, index * index * index))
printfn "The list: %A" list5

(* using yield operator *)
let list6 = [ for a in 1 .. 10 do yield (a * a) ]
printfn "The list: %A" list6

(* using yield operator *)
let list7 = [ for a in 1 .. 100 do if a % 3 = 0 && a % 5 = 0 then yield a]
printfn "The list: %A" list7

(* using yield! operator *)
let list8 = [for a in 1 .. 3 do yield! [ a .. a + 3 ] ]
printfn "The list: %A" list8

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The list: [1; 2; 3]
The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The list: ['a'; 'b'; 'c'; 'd'; 'e'; 'f'; 'g'; 'h'; 'i'; 'j'; 'k'; 'l'; 'm']
The list: [(0, 0, 0); (1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64)]
The list: [1; 4; 9; 16; 25; 36; 49; 64; 81; 100]
The list: [15; 30; 45; 60; 75; 90]
The list: [1; 2; 3; 4; 2; 3; 4; 5; 3; 4; 5; 6]

Свойства типа данных списка

В следующей таблице показаны различные свойства типа данных списка —

Имущество Тип Описание
Голова «T Первый элемент
пустой ‘T список Статическое свойство, которое возвращает пустой список соответствующего типа.
Пустой BOOL Значение true, если в списке нет элементов.
Вещь «T Элемент по указанному индексу (начиная с нуля).
длина ИНТ Количество элементов.
Хвост ‘T список Список без первого элемента.

В следующем примере показано использование этих свойств —

пример

Live Demo

let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]

// Use of Properties
printfn "list1.IsEmpty is %b" (list1.IsEmpty)
printfn "list1.Length is %d" (list1.Length)
printfn "list1.Head is %d" (list1.Head)
printfn "list1.Tail.Head is %d" (list1.Tail.Head)
printfn "list1.Tail.Tail.Head is %d" (list1.Tail.Tail.Head)
printfn "list1.Item(1) is %d" (list1.Item(1))

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

list1.IsEmpty is false
list1.Length is 8
list1.Head is 2
list1.Tail.Head is 4
list1.Tail.Tail.Head is 6
list1.Item(1) is 4

Основные операторы в списке

В следующей таблице приведены основные операции с типом данных списка —

Значение Описание
добавить: ‘T список →’ T список → ‘T список Возвращает новый список, который содержит элементы первого списка, за которыми следуют элементы второго.
средний: ‘T список → ^ T Возвращает среднее значение элементов в списке.
AverageBy: (‘T → ^ U) →’ T список → ^ U Возвращает среднее значение элементов, созданных путем применения функции к каждому элементу списка.
выберите: (опция ‘T →’ U) → ‘T list →’ U list Применяет данную функцию к каждому элементу списка. Возвращает список, состоящий из результатов для каждого элемента, где функция возвращает Some .
собрать: (‘T →’ U list) → ‘T list →’ U list Для каждого элемента списка применяется данная функция. Объединяет все результаты и возвращает объединенный список.
concat: seq <‘T list> →’ T list Возвращает новый список, который содержит элементы каждого списка в порядке.
пусто: ‘T список Возвращает пустой список данного типа.
существует: (‘T → bool) →’ T список → bool Проверяет, удовлетворяет ли какой-либо элемент списка данному предикату.
Существует2: (‘T1 →’ T2 → bool) → ‘Список T1 →’ Список T2 → bool Проверяет, удовлетворяет ли любая пара соответствующих элементов списков данному предикату.
фильтр: (‘T → bool) →’ T list → ‘T list Возвращает новую коллекцию, содержащую только те элементы коллекции, для которых данный предикат возвращает true .
найти: (‘T → bool) →’ T list → ‘T Возвращает первый элемент, для которого данная функция возвращает true .
findIndex: (‘T → bool) →’ T list → int Возвращает индекс первого элемента в списке, который удовлетворяет данному предикату.
свернуть: (‘State →’ T → ‘State) →’ State → ‘T list →’ State Применяет функцию к каждому элементу коллекции, пропуская аргумент аккумулятора через вычисления. Эта функция принимает второй аргумент и применяет к нему функцию и первый элемент списка. Затем он передает этот результат в функцию вместе со вторым элементом и так далее. Наконец, он возвращает окончательный результат. Если входной функцией является f, а элементами i0 … iN, то эта функция вычисляет f (… (fs i0) i1 …) iN.
fold2: (‘State →’ T1 → ‘T2 →’ State) → ‘State →’ T1 list → ‘T2 list →’ State Применяет функцию к соответствующим элементам двух коллекций, пропуская аргумент аккумулятора через вычисления. Коллекции должны иметь одинаковые размеры. Если входной функцией является f, а элементами являются i0 … iN и j0 … jN, то эта функция вычисляет f (… (fs i0 j0) …) iN jN.
foldBack: (‘T →’ State → ‘State) →’ T list → ‘State →’ State Применяет функцию к каждому элементу коллекции, пропуская аргумент аккумулятора через вычисления. Если входная функция isf и элементы i0 … iN, то вычисляется f i0 (… (f iN s)).
foldBack2: (‘T1 →’ T2 → ‘State →’ State) → ‘T1 list →’ T2 list → ‘State →’ State Применяет функцию к соответствующим элементам двух коллекций, пропуская аргумент аккумулятора через вычисления. Коллекции должны иметь одинаковые размеры. Если входной функцией является f, а элементами являются i0 … iN и j0 … jN, то эта функция вычисляет f i0 j0 (… (f iN jN s)).
forall: (‘T → bool) →’ T list → bool Проверяет, все ли элементы коллекции удовлетворяют данному предикату.
forall2: (‘T1 →’ T2 → bool) → ‘Список T1 →’ Список T2 → bool Проверяет, все ли соответствующие элементы коллекции удовлетворяют заданному предикату попарно.
руководитель: ‘T список →’ T Возвращает первый элемент списка.
init: int → (int → ‘T) →’ T list Создает список, вызывая данный генератор для каждого индекса.
isEmpty: ‘T list → bool Возвращает true, если список не содержит элементов, иначе false .
iter: (‘T → единица измерения) →’ T список → единица измерения Применяет данную функцию к каждому элементу коллекции.
iter2: (‘T1 →’ T2 → единица) → ‘Список T1 →’ Список T2 → единица Применяет данную функцию одновременно к двум коллекциям. Коллекции должны иметь одинаковый размер.
iteri: (int → ‘T → unit) →’ T list → unit Применяет данную функцию к каждому элементу коллекции. Целое число, переданное функции, указывает на индекс элемента.
iteri2: (int → ‘T1 →’ T2 → unit) → ‘T1 list →’ T2 list → unit Применяет данную функцию одновременно к двум коллекциям. Коллекции должны иметь одинаковый размер. Целое число, переданное функции, указывает на индекс элемента.
длина: ‘T список → int Возвращает длину списка.
карта: (‘T →’ U) → ‘T list →’ U list Создает новую коллекцию, элементы которой являются результатами применения данной функции к каждому из элементов коллекции.
map2: (‘T1 →’ T2 → ‘U) →’ список T1 → ‘список T2 →’ список U Создает новую коллекцию, элементы которой являются результатами применения данной функции к соответствующим элементам двух коллекций попарно.
map3: (‘T1 →’ T2 → ‘T3 →’ U) → ‘список T1 →’ список T2 → ‘список T3 →’ список U Создает новую коллекцию, элементы которой являются результатом применения данной функции к соответствующим элементам трех коллекций одновременно.
mapi: (int → ‘T →’ U) → ‘T list →’ U list Создает новую коллекцию, элементы которой являются результатами применения данной функции к каждому из элементов коллекции. Целочисленный индекс, переданный функции, указывает индекс (от 0) преобразовываемого элемента.
mapi2: (int → ‘T1 →’ T2 → ‘U) →’ список T1 → ‘список T2 →’ список U Как и List.mapi, но отображает соответствующие элементы из двух списков одинаковой длины.
max: ‘T list →’ T Возвращает наибольший из всех элементов списка по сравнению с использованием Operators.max.
maxBy: (‘T →’ U) → ‘T list →’ T Возвращает наибольший из всех элементов списка по сравнению с использованием Operators.max для результата функции.
мин: ‘T список →’ T Возвращает самый низкий из всех элементов списка по сравнению с использованием Operators.min.
minBy: (‘T →’ U) → ‘T list →’ T Возвращает самый низкий из всех элементов списка по сравнению с использованием Operators.min для результата функции
nth: ‘T list → int →’ T Индексы в список. Первый элемент имеет индекс 0.
ofArray: ‘T [] →’ T list Создает список из заданного массива.
ofSeq: seq <‘T> →’ T list Создает новый список из данного перечисляемого объекта.
раздел: (‘T → bool) →’ T list * ‘T list Разбивает коллекцию на две коллекции, содержащие элементы, для которых данный предикат возвращает true и false соответственно.
перестановка: (int → int) → ‘T list →’ T list Возвращает список со всеми переставленными элементами в соответствии с указанной перестановкой.
выберите: (опция ‘T →’ U) → ‘список T →’ U Применяет данную функцию к последовательным элементам, возвращая первый результат, где функция возвращает Some для некоторого значения.
уменьшить: (‘T →’ T → ‘T) →’ T list → ‘T Применяет функцию к каждому элементу коллекции, пропуская аргумент аккумулятора через вычисления. Эта функция применяет указанную функцию к первым двум элементам списка. Затем он передает этот результат в функцию вместе с третьим элементом и так далее. Наконец, он возвращает окончательный результат. Если входной функцией является f, а элементами — i0 … iN, то эта функция вычисляет f (… (f i0 i1) i2 …) iN.
ReduckBack: (‘T →’ T → ‘T) →’ T list → ‘T Применяет функцию к каждому элементу коллекции, пропуская аргумент аккумулятора через вычисления. Если входная функция isf и элементы i0 … iN, то эта функция вычисляет f i0 (… (f iN-1 iN)).
копия: (int → ‘T →’ T список) Создает список, вызывая данный генератор для каждого индекса.
rev: ‘T list →’ T list Возвращает новый список с элементами в обратном порядке.
scan: (‘State →’ T → ‘State) →’ State → ‘T list →’ Список состояний Применяет функцию к каждому элементу коллекции, пропуская аргумент аккумулятора через вычисления. Эта функция принимает второй аргумент и применяет к нему указанную функцию и первый элемент списка. Затем он передает этот результат в функцию вместе со вторым элементом и так далее. Наконец, он возвращает список промежуточных результатов и окончательный результат.
scanBack: (‘T →’ State → ‘State) →’ T list → ‘State →’ Список состояний Как и foldBack, но возвращает промежуточные и окончательные результаты
сортировка: ‘T list →’ T list Сортирует указанный список с помощью Operators.compare.
sortBy: (‘T →’ Key) → ‘T list →’ T list Сортирует данный список, используя ключи, заданные данной проекцией. Ключи сравниваются с помощью Operators.compare.
sortWith: (‘T →’ T → int) → ‘T list →’ T list Сортирует указанный список, используя данную функцию сравнения.
сумма: ^ T список → ^ T Возвращает сумму элементов в списке.
sumBy: (‘T → ^ U) →’ T список → ^ U Возвращает сумму результатов, полученных с помощью применения функции к каждому элементу списка.
хвост: ‘T список →’ T список Возвращает список ввода без первого элемента.
toArray: ‘T list →’ T [] Создает массив из заданного списка.
toSeq: ‘T list → seq <‘ T> Рассматривает данный список как последовательность.
tryFind: (‘T → bool) →’ T list → ‘T опция Возвращает первый элемент, для которого данная функция возвращает true . Вернуть None, если такого элемента не существует.
tryFindIndex: (‘T → bool) →’ T list → int option Возвращает индекс первого элемента в списке, который удовлетворяет данному предикату. Вернуть None, если такого элемента не существует.
tryPick: (опция ‘T →’ U) → опция ‘T list →’ U Применяет данную функцию к последовательным элементам, возвращая первый результат, где функция возвращает Some для некоторого значения. Если такого элемента не существует, вернуть None .
распаковать: (‘T1 *’ T2) список → ‘T1 список *’ список T2 Разбивает список пар на два списка.
распаковать3: (‘T1 *’ T2 * ‘T3) список →’ список T1 * ‘список T2 *’ список T3 Разбивает список троек на три списка.
zip: ‘T1 list →’ T2 list → (‘T1 *’ T2) список Объединяет два списка в список пар. Два списка должны иметь одинаковую длину.
zip3: ‘T1 list →’ T2 list → ‘T3 list → (‘ T1 * ‘T2 *’ T3) список Объединяет три списка в список троек. Списки должны иметь одинаковую длину.

Следующие примеры демонстрируют использование вышеуказанных функций —

Пример 1

Эта программа показывает рекурсивное изменение списка —

Live Demo

let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original list: %A" list1

let reverse lt =
   let rec loop acc = function
      | [] -> acc
      | hd :: tl -> loop (hd :: acc) tl
   loop [] lt

printfn "The reversed list: %A" (reverse list1)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]

Тем не менее, вы можете использовать функцию rev модуля для той же цели —

Live Demo

let list1 = [ 2; 4; 6; 8; 10; 12; 14; 16 ]
printfn "The original list: %A" list1
printfn "The reversed list: %A" (List.rev list1)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The original list: [2; 4; 6; 8; 10; 12; 14; 16]
The reversed list: [16; 14; 12; 10; 8; 6; 4; 2]

Пример 2

Эта программа показывает фильтрацию списка с использованием метода List.filter

Live Demo

let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1
let list2 = list1 |> List.filter (fun x -> x % 2 = 0);;
printfn "The Filtered list: %A" list2

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Filtered list: [2; 4; 6; 8; 10]

Пример 3

Метод List.map отображает список из одного типа в другой —

Live Demo

let list1 = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
printfn "The list: %A" list1
let list2 = list1 |> List.map (fun x -> (x * x).ToString());;
printfn "The Mapped list: %A" list2

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The Mapped list: ["1"; "4"; "9"; "16"; "25"; "36"; "49"; "64"; "81"; "100"]

Пример 4

Метод List.append и оператор @ добавляет один список в другой —

Live Demo

let list1 = [1; 2; 3; 4; 5 ]
let list2 = [6; 7; 8; 9; 10]
let list3 = List.append list1 list2

printfn "The first list: %A" list1
printfn "The second list: %A" list2
printfn "The appened list: %A" list3

let lt1 = ['a'; 'b';'c' ]
let lt2 = ['e'; 'f';'g' ]
let lt3 = lt1 @ lt2

printfn "The first list: %A" lt1
printfn "The second list: %A" lt2
printfn "The appened list: %A" lt3

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The first list: [1; 2; 3; 4; 5]
The second list: [6; 7; 8; 9; 10]
The appened list: [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
The first list: ['a'; 'b'; 'c']
The second list: ['e'; 'f'; 'g']
The appened list: ['a'; 'b'; 'c'; 'e'; 'f'; 'g']

Пример 5

Метод List.sort сортирует список. Метод List.sum дает сумму элементов в списке, а метод List.average — среднее значение элементов в списке.

Live Demo

let list1 = [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
printfn "The list: %A" list1

let list2 = List.sort list1
printfn "The sorted list: %A" list2

let s = List.sum list1
let avg = List.average list1
printfn "The sum: %f" s
printfn "The average: %f" avg

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The list: [9.0; 0.0; 2.0; -4.5; 11.2; 8.0; -10.0]
The sorted list: [-10.0; -4.5; 0.0; 2.0; 8.0; 9.0; 11.2]
The sum: 15.700000
The average: 2.242857

Операция «сгиба» применяет функцию к каждому элементу в списке, агрегирует результат функции в переменной аккумулятора и возвращает аккумулятор как результат операции сгиба.

Пример 6

Метод List.fold применяет функцию к каждому элементу слева направо, в то время как List.foldBack применяет функцию к каждому элементу справа налево.

Live Demo

let sumList list = List.fold (fun acc elem -> acc + elem) 0 list
printfn "Sum of the elements of list %A is %d." [ 1 .. 10 ] (sumList [ 1 .. 10 ])

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Sum of the elements of list [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] is 55.

F # — последовательности

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

Определение последовательности

Последовательности определяются с использованием следующего синтаксиса —

seq { expr }

Например,

let seq1 = seq { 1 .. 10 }

Создание последовательностей и выражений последовательностей

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

Выражения последовательностей — это выражения, которые вы можете написать для создания последовательностей. Это может быть сделано —

  • Указав диапазон.
  • Указав диапазон с приращением или уменьшением.
  • Используя ключевое слово yield для получения значений, которые становятся частью последовательности.
  • С помощью оператора →.

Следующие примеры демонстрируют концепцию —

Пример 1

Live Demo

(* Sequences *)
let seq1 = seq { 1 .. 10 }

(* ascending order and increment*)
printfn "The Sequence: %A" seq1
let seq2 = seq { 1 .. 5 .. 50 }

(* descending order and decrement*)
printfn "The Sequence: %A" seq2
let seq3 = seq {50 .. -5 .. 0}
printfn "The Sequence: %A" seq3

(* using yield *)
let seq4 = seq { for a in 1 .. 10 do yield a, a*a, a*a*a }
printfn "The Sequence: %A" seq4

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The Sequence: seq [1; 2; 3; 4; ...]
The Sequence: seq [1; 6; 11; 16; ...]
The Sequence: seq [50; 45; 40; 35; ...]
The Sequence: seq [(1, 1, 1); (2, 4, 8); (3, 9, 27); (4, 16, 64); ...]

Пример 2

Следующая программа печатает простые числа от 1 до 50 —

Live Demo

(* Recursive isprime function. *)
let isprime n =
   let rec check i =
      i > n/2 || (n % i <> 0 && check (i + 1))
   check 2

let primeIn50 = seq { for n in 1..50 do if isprime n then yield n }
for x in primeIn50 do
   printfn "%d" x

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

1
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47

Основные операции над последовательностью

В следующей таблице приведены основные операции с типом данных последовательности —

Значение Описание
append: seq <‘T> → seq <‘ T> → seq <‘T> Оборачивает два заданных перечисления как одно сцепленное перечисление.
среднее значение: seq <^ T> → ^ T Возвращает среднее значение элементов в последовательности.
AverageBy: (‘T → ^ U) → seq <‘ T> → ^ U Возвращает среднее значение результатов, полученных с помощью применения функции к каждому элементу последовательности.
кеш: seq <‘T> → seq <‘ T> Возвращает последовательность, которая соответствует кэшированной версии входной последовательности.
приведение: IEnumerable → seq <‘T> Обертывает свободно набранную Систему. Последовательность коллекций как типизированная последовательность.
выберите: (опция ‘T →’ U) → seq <‘T> → seq <‘ U> Применяет данную функцию к каждому элементу списка. Вернуть список, состоящий из результатов для каждого элемента, где функция возвращает Some .
собирать: (‘T →’ Коллекция) → seq <‘T> → seq <‘ U> Применяет данную функцию к каждому элементу последовательности и объединяет все результаты.
сравнить с: (‘T →’ T → int) → seq <‘T> → seq <‘ T> → int Сравнивает две последовательности, используя данную функцию сравнения, элемент за элементом.
concat: seq <‘Collection> → seq <‘ T> Объединяет данное перечисление перечислений в качестве единого каскадного перечисления.
countBy: (‘T →’ Key) → seq <‘T> → seq <‘ Key * int> Применяет функцию генерации ключа к каждому элементу последовательности и возвращает последовательность, дающую уникальные ключи и их количество вхождений в исходной последовательности.
задержка: (единица измерения → seq <‘T>) → seq <‘ T> Возвращает последовательность, которая построена из заданной отложенной спецификации последовательности.
отчетливый: seq <‘T> → seq <‘ T> Возвращает последовательность, которая не содержит повторяющихся записей в соответствии с общим сравнением хеша и равенства записей. Если элемент встречается в последовательности несколько раз, более поздние вхождения отбрасываются.
DifferentBy: (‘T →’ Key) → seq <‘T> → seq <‘ T> Возвращает последовательность, которая не содержит повторяющихся записей в соответствии с общим сравнением хэша и равенства для ключей, возвращаемых данной функцией генерации ключа. Если элемент встречается в последовательности несколько раз, более поздние вхождения отбрасываются.
пусто: seq <‘T> Создает пустую последовательность.
точно один: seq <‘T> →’ T Возвращает единственный элемент последовательности.
существует: (‘T → bool) → seq <‘ T> → bool Проверяет, удовлетворяет ли какой-либо элемент последовательности данному предикату.
существует2: (‘T1 →’ T2 → bool) → seq <‘T1> → seq <‘ T2> → bool Проверяет, удовлетворяет ли любая пара соответствующих элементов входных последовательностей данному предикату.
фильтр: (‘T → bool) → seq <‘ T> → seq <‘T> Возвращает новую коллекцию, содержащую только те элементы коллекции, для которых данный предикат возвращает true .
найти: (‘T → bool) → seq <‘ T> → ‘T Возвращает первый элемент, для которого данная функция возвращает true .
findIndex: (‘T → bool) → seq <‘ T> → int Возвращает индекс первого элемента, для которого данная функция возвращает true .
свернуть: (‘State →’ T → ‘State) →’ State → seq <‘T> →’ State Применяет функцию к каждому элементу коллекции, пропуская аргумент аккумулятора через вычисления. Если входная функция — f, а элементы — i0 … iN, то эта функция вычисляет f (… (fs i0) …) iN.
forall: (‘T → bool) → seq <‘ T> → bool Проверяет, все ли элементы последовательности удовлетворяют данному предикату.
forall2: (‘T1 →’ T2 → bool) → seq <‘T1> → seq <‘ T2> → bool Тесты всех пар элементов, взятых из двух последовательностей, удовлетворяют данному предикату. Если одна последовательность короче другой, то остальные элементы более длинной последовательности игнорируются.
groupBy: (‘T →’ Key) → seq <‘T> → seq <‘ Key * seq <‘T >> Применяет функцию генерации ключа к каждому элементу последовательности и выдает последовательность уникальных ключей. Каждый уникальный ключ также содержит последовательность всех элементов, соответствующих этому ключу.
head: seq <‘T> →’ T Возвращает первый элемент последовательности.
init: int → (int → ‘T) → seq <‘ T> Создает новую последовательность, которая после повторения возвращает последовательные элементы, вызывая данную функцию, до заданного количества. Результаты вызова функции не сохраняются, то есть функция применяется повторно по мере необходимости для регенерации элементов. В функцию передается индекс генерируемого элемента.
initInfinite: (int → ‘T) → seq <‘ T> Создает новую последовательность, которая после повторения будет возвращать последовательные элементы, вызывая данную функцию. Результаты вызова функции не сохраняются, то есть функция будет применяться повторно по мере необходимости для регенерации элементов. В функцию передается индекс генерируемого элемента.
isEmpty: seq <‘T> → bool Проверяет, есть ли в последовательности какие-либо элементы.
iter: (‘T → единица измерения) → seq <‘ T> → единица измерения Применяет данную функцию к каждому элементу коллекции.
iter2: (‘T1 →’ T2 → unit) → seq <‘T1> → seq <‘ T2> → unit Применяет данную функцию одновременно к двум коллекциям. Если одна последовательность короче другой, то остальные элементы более длинной последовательности игнорируются.
iteri: (int → ‘T → unit) → seq <‘ T> → unit Применяет данную функцию к каждому элементу коллекции. Целое число, переданное функции, указывает на индекс элемента.
последний: seq <‘T> →’ T Возвращает последний элемент последовательности.
длина: seq <‘T> → int Возвращает длину последовательности.
карта: (‘T →’ U) → seq <‘T> → seq <‘ U> Создает новую коллекцию, элементы которой являются результатами применения данной функции к каждому из элементов коллекции. Данная функция будет применена, поскольку элементы требуются с помощью метода MoveNext на счетчиках, извлеченных из объекта.
map2: (‘T1 →’ T2 → ‘U) → seq <‘ T1> → seq <‘T2> → seq <‘ U> Создает новую коллекцию, элементы которой являются результатами применения данной функции к соответствующим парам элементов из двух последовательностей. Если одна входная последовательность короче другой, то остальные элементы более длинной последовательности игнорируются.
mapi: (int → ‘T →’ U) → seq <‘T> → seq <‘ U> Создает новую коллекцию, элементы которой являются результатами применения данной функции к каждому из элементов коллекции. Целочисленный индекс, переданный функции, указывает индекс (от 0) преобразовываемого элемента.
max: seq <‘T> →’ T Возвращает наибольший из всех элементов последовательности, сравниваемых с помощью Operators.max.
maxBy: (‘T →’ U) → seq <‘T> →’ T Возвращает наибольший из всех элементов последовательности по сравнению с использованием Operators.max для результата функции.
min: seq <‘T> →’ T Возвращает самый низкий из всех элементов последовательности по сравнению с использованием Operators.min.
minBy: (‘T →’ U) → seq <‘T> →’ T Возвращает самый низкий из всех элементов последовательности по сравнению с использованием Operators.min для результата функции.
nth: int → seq <‘T> →’ T Вычисляет n-й элемент в коллекции.
ofArray: ‘T array → seq <‘ T> Рассматривает данный массив как последовательность.
ofList: ‘T list → seq <‘ T> Рассматривает данный список как последовательность.
попарно: seq <‘T> → seq <‘ T * ‘T> Возвращает последовательность каждого элемента во входной последовательности и его предшественника, за исключением первого элемента, который возвращается только как предшественник второго элемента.
выберите: (опция ‘T →’ U) → seq <‘T> →’ U Применяет данную функцию к последовательным элементам, возвращая первое значение, где функция возвращает значение Some .
только для чтения: seq <‘T> → seq <‘ T> Создает новый объект последовательности, который делегируется данному объекту последовательности. Это гарантирует, что исходная последовательность не может быть заново открыта и видоизменена при помощи приведения типа. Например, если задан массив, возвращаемая последовательность вернет элементы массива, но вы не можете преобразовать возвращенный объект последовательности в массив.
уменьшить: (‘T →’ T → ‘T) → seq <‘ T> → ‘T Применяет функцию к каждому элементу последовательности, пропуская аргумент аккумулятора через вычисления. Начните с применения функции к первым двум элементам. Затем введите этот результат в функцию вместе с третьим элементом и так далее. Верните окончательный результат.
scan: (‘State →’ T → ‘State) →’ State → seq <‘T> → seq <‘ State> Как и Seq.fold, но вычисляет по требованию и возвращает последовательность промежуточных и конечных результатов.
синглтон: ‘T → seq <‘ T> Возвращает последовательность, которая дает только один элемент.
skip: int → seq <‘T> → seq <‘ T> Возвращает последовательность, которая пропускает указанное количество элементов базовой последовательности, а затем возвращает остальные элементы последовательности.
skipWhile: (‘T → bool) → seq <‘ T> → seq <‘T> Возвращает последовательность, которая после итерации пропускает элементы базовой последовательности, в то время как заданный предикат возвращает true, а затем возвращает остальные элементы последовательности.
сортировать: seq <‘T> → seq <‘ T> Возвращает последовательность, упорядоченную по ключам.
sortBy: (‘T →’ Key) → seq <‘T> → seq <‘ T> Применяет функцию генерации ключа к каждому элементу последовательности и выдает последовательность, упорядоченную по ключам. Ключи сравниваются с использованием общего сравнения, реализованного Operators.compare.
сумма: seq <^ T> → ^ T Возвращает сумму элементов в последовательности.
sumBy Возвращает сумму результатов, сгенерированных путем применения функции к каждому элементу последовательности.
take: int → seq <‘T> → seq <‘ T> Возвращает первые элементы последовательности до указанного количества.
takeWhile: (‘T → bool) → seq <‘ T> → seq <‘T> Возвращает последовательность, которая при повторении возвращает элементы базовой последовательности, в то время как данный предикат возвращает true, а затем не возвращает никаких дополнительных элементов.
toArray: seq <‘T> →’ T [] Создает массив из данной коллекции.
toList: seq <‘T> →’ T list Создает список из данной коллекции.
усечение: int → seq <‘T> → seq <‘ T> Возвращает последовательность, которая при перечислении возвращает не более указанного числа элементов.
опция tryFind: (‘T → bool) → seq <‘ T> → ‘T Возвращает первый элемент, для которого данная функция возвращает true, или None, если такого элемента не существует.
опция tryFindIndex: (‘T → bool) → seq <‘ T> → int Возвращает индекс первого элемента в последовательности, который удовлетворяет данному предикату, или None, если такого элемента не существует.
tryPick: (опция ‘T →’ U) → опция seq <‘T> →’ U Применяет данную функцию к последовательным элементам, возвращая первое значение, где функция возвращает значение Some .
развернуть: (‘State →’ T * ‘State option) →’ State → seq <‘T> Возвращает последовательность, которая содержит элементы, сгенерированные данным вычислением.
где: (‘T → bool) → seq <‘ T> → seq <‘T> Возвращает новую коллекцию, содержащую только те элементы коллекции, для которых данный предикат возвращает true . Синоним для Seq.filter.
windowed: int → seq <‘T> → seq <‘ T []> Возвращает последовательность, которая дает скользящие окна, содержащие элементы, взятые из входной последовательности. Каждое окно возвращается в виде нового массива.
zip: seq <‘T1> → seq <‘ T2> → seq <‘T1 *’ T2> Объединяет две последовательности в список пар. Две последовательности не должны иметь одинаковую длину — когда одна последовательность исчерпана, любые оставшиеся элементы в другой последовательности игнорируются.
zip3: seq <‘T1> → seq <‘ T2> → seq <‘T3> → seq <‘ T1 * ‘T2 *’ T3> Объединяет три последовательности в список троек. Последовательности не должны иметь одинаковую длину — когда одна последовательность исчерпана, все остальные элементы в других последовательностях игнорируются.

Следующие примеры демонстрируют использование некоторых из вышеуказанных функций —

Пример 1

Эта программа создает пустую последовательность и заполняет ее позже —

Live Demo

(* Creating sequences *)
let emptySeq = Seq.empty
let seq1 = Seq.singleton 20

printfn"The singleton sequence:"
printfn "%A " seq1
printfn"The init sequence:"

let seq2 = Seq.init 5 (fun n -> n * 3)
Seq.iter (fun i -> printf "%d " i) seq2
printfn""

(* converting an array to sequence by using cast *)
printfn"The array sequence 1:"
let seq3 = [| 1 .. 10 |] :> seq<int>
Seq.iter (fun i -> printf "%d " i) seq3
printfn""

(* converting an array to sequence by using Seq.ofArray *)
printfn"The array sequence 2:"
let seq4 = [| 2..2.. 20 |] |> Seq.ofArray
Seq.iter (fun i -> printf "%d " i) seq4
printfn""

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The singleton sequence:
seq [20]
The init sequence:
0 3 6 9 12
The array sequence 1:
1 2 3 4 5 6 7 8 9 10
The array sequence 2:
2 4 6 8 10 12 14 16 18 20

Пожалуйста, обратите внимание, что —

  • Метод Seq.empty создает пустую последовательность.

  • Метод Seq.singleton создает последовательность только из одного указанного элемента.

  • Метод Seq.init создает последовательность, для которой элементы создаются с использованием данной функции.

  • Методы Seq.ofArray и Seq.ofList <‘T> создают последовательности из массивов и списков.

  • Метод Seq.iter позволяет выполнять итерацию последовательности.

Метод Seq.empty создает пустую последовательность.

Метод Seq.singleton создает последовательность только из одного указанного элемента.

Метод Seq.init создает последовательность, для которой элементы создаются с использованием данной функции.

Методы Seq.ofArray и Seq.ofList <‘T> создают последовательности из массивов и списков.

Метод Seq.iter позволяет выполнять итерацию последовательности.

Пример 2

Метод Seq.unfold генерирует последовательность из вычислительной функции, которая принимает состояние и преобразует его для создания каждого последующего элемента в последовательности.

Следующая функция выдает первые 20 натуральных чисел —

Live Demo

let seq1 = Seq.unfold (fun state -> if (state > 20) then None else Some(state, state + 1)) 0
printfn "The sequence seq1 contains numbers from 0 to 20."
for x in seq1 do printf "%d " x
printfn" "

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The sequence seq1 contains numbers from 0 to 20.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Пример 3

Метод Seq.truncate создает последовательность из другой последовательности, но ограничивает последовательность указанным количеством элементов.

Метод Seq.take создает новую последовательность, которая содержит указанное количество элементов с начала последовательности.

Live Demo

let mySeq = seq { for i in 1 .. 10 -> 3*i }
let truncatedSeq = Seq.truncate 5 mySeq
let takeSeq = Seq.take 5 mySeq

printfn"The original sequence"
Seq.iter (fun i -> printf "%d " i) mySeq
printfn""

printfn"The truncated sequence"
Seq.iter (fun i -> printf "%d " i) truncatedSeq
printfn""

printfn"The take sequence"
Seq.iter (fun i -> printf "%d " i) takeSeq
printfn""

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The original sequence
3 6 9 12 15 18 21 24 27 30
The truncated sequence
3 6 9 12 15
The take sequence
3 6 9 12 15

F # — Наборы

Набор в F # — это структура данных, которая действует как набор элементов без сохранения порядка вставки элементов. Наборы не позволяют дублировать записи для вставки в коллекцию.

Создание наборов

Наборы могут быть созданы следующими способами —

  • Создавая пустой набор с помощью Set.empty и добавляя элементы с помощью функции add.
  • Преобразование последовательностей и списков в наборы.

Следующая программа демонстрирует методы —

Live Demo

(* creating sets *)
let set1 = Set.empty.Add(3).Add(5).Add(7). Add(9)
printfn"The new set: %A" set1

let weekdays = Set.ofList ["mon"; "tues"; "wed"; "thurs"; "fri"]
printfn "The list set: %A" weekdays

let set2 = Set.ofSeq [ 1 .. 2.. 10 ]
printfn "The sequence set: %A" set2

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The new set: set [3; 5; 7; 9]
The list set: set ["fri"; "mon"; "thurs"; "tues"; "wed"]
The sequence set: set [1; 3; 5; 7; 9]

Основные операции над наборами

В следующей таблице приведены основные операции над наборами —

Значение Описание
добавить: ‘T → Set <‘ T> → Set <‘T> Возвращает новый набор с элементом, добавленным в набор. Исключение не возникает, если набор уже содержит данный элемент.
содержит: ‘T → Set <‘ T> → bool Значение true, если данный элемент находится в заданном наборе.
count: Set <‘T> → int Возвращает количество элементов в наборе.
Разница: Установите <‘T> → Установите <‘ T> → Установите <‘T> Возвращает новый набор, в котором элементы второго набора удалены из первого.
пусто: Set <‘T> Пустой набор для указанного типа.
существует: (‘T → bool) → Set <‘ T> → bool Проверяет, удовлетворяет ли какой-либо элемент коллекции указанному предикату. Если входной функцией является предикат, а элементами являются i0 … iN, то эта функция вычисляет предикат i0 или … или предикат iN.
фильтр: (‘T → bool) → Set <‘ T> → Set <‘T> Возвращает новую коллекцию, содержащую только те элементы коллекции, для которых данный предикат возвращает true .
свернуть: (‘State →’ T → ‘State) →’ State → Set <‘T> →’ State Применяет данную функцию накопления ко всем элементам набора.
foldBack: (‘T →’ State → ‘State) → Установить <‘ T> → ‘State →’ State Применяет данную функцию накопления ко всем элементам набора.
forall: (‘T → bool) → Установить <‘ T> → bool Проверяет, все ли элементы коллекции удовлетворяют данному предикату. Если входная функция p, а элементы i0 … iN, то эта функция вычисляет p i0 && … && p iN.
пересекаются: Set <‘T> → Set <‘ T> → Set <‘T> Вычисляет пересечение двух множеств.
intersectMany: seq <Set <‘T >> → Set <‘ T> Вычисляет пересечение последовательности множеств. Последовательность должна быть не пустой.
isEmpty: Set <‘T> → bool Возвращает true, если набор пуст.
isProperSubset: Set <‘T> → Set <‘ T> → bool Значение true, если все элементы первого набора находятся во втором, и хотя бы один элемент второго не находится в первом.
isProperSuperset: Set <‘T> → Set <‘ T> → bool Значение true, если все элементы второго набора находятся в первом, и хотя бы один элемент первого не находится во втором.
isSubset: Set <‘T> → Set <‘ T> → bool Значение true, если все элементы первого набора находятся во втором.
isSuperset: Set <‘T> → Set <‘ T> → bool Значение true, если все элементы второго набора находятся в первом.
iter: (‘T → единица измерения) → Установить <‘ T> → единицу измерения Применяет данную функцию к каждому элементу набора в порядке, соответствующем функции сравнения.
карта: (‘T →’ U) → Set <‘T> → Set <‘ U> Возвращает новую коллекцию, содержащую результаты применения данной функции к каждому элементу входного набора.
maxElement: установите <‘T> →’ T Возвращает самый высокий элемент в наборе в соответствии с порядком, используемым для набора.
minElement: Установите <‘T> →’ T Возвращает самый низкий элемент в наборе в соответствии с порядком, используемым для набора.
ofArray: ‘T массив → Set <‘ T> Создает набор, который содержит те же элементы, что и данный массив.
ofList: ‘T list → Set <‘ T> Создает набор, который содержит те же элементы, что и данный список.
ofSeq: seq <‘T> → Set <‘ T> Создает новую коллекцию из данного перечисляемого объекта.
раздел: (‘T → bool) → Set <‘ T> → Set <‘T> * Set <‘ T> Разбивает набор на два набора, содержащих элементы, для которых данный предикат возвращает true и false соответственно.
удалить: ‘T → Set <‘ T> → Set <‘T> Возвращает новый набор с удаленным заданным элементом. Исключение не возникает, если набор не содержит данный элемент.
синглтон: ‘T → Set <‘ T> Набор, содержащий данный элемент.
toArray: установить массив <‘T> →’ T Создает массив, содержащий элементы набора по порядку.
toList: Установить <‘T> →’ T список Создает список, содержащий элементы набора по порядку.
toSeq: Set <‘T> → seq <‘ T> Возвращает упорядоченное представление коллекции как перечислимый объект.
объединение: Set <‘T> → Set <‘ T> → Set <‘T> Вычисляет объединение двух наборов.
unionMany: seq <Set <‘T >> → Set <‘ T> Вычисляет объединение последовательности множеств.

В следующем примере демонстрируется использование некоторых из перечисленных выше функций.

пример

Live Demo

let a = Set.ofSeq [ 1 ..2.. 20 ]
let b = Set.ofSeq [ 1 ..3 .. 20 ]
let c = Set.intersect a b
let d = Set.union a b
let e = Set.difference a b

printfn "Set a: "
Set.iter (fun x -> printf "%O " x) a
printfn""

printfn "Set b: "
Set.iter (fun x -> printf "%O " x) b
printfn""

printfn "Set c = set intersect of a and b : "
Set.iter (fun x -> printf "%O " x) c
printfn""

printfn "Set d = set union of a and b : "
Set.iter (fun x -> printf "%O " x) d
printfn""

printfn "Set e = set difference of a and b : "
Set.iter (fun x -> printf "%O " x) e
printfn""

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Set a:
1 3 5 7 9 11 13 15 17 19
Set b:
1 4 7 10 13 16 19
Set c = set intersect of a and b :
1 7 13 19
Set d = set union of a and b :
1 3 4 5 7 9 10 11 13 15 16 17 19
Set e = set difference of a and b :
3 5 9 11 15 17

F # — Карты

В F # карта — это особый вид набора, который связывает значения с ключом. Карта создается аналогично тому, как создаются наборы.

Создание карт

Карты создаются путем создания пустой карты с помощью Map.empty и добавления элементов с помощью функции Add. Следующий пример демонстрирует это —

пример

Live Demo

(* Create an empty Map *)
let students =
   Map.empty. (* Creating an empty Map *)
      Add("Zara Ali", "1501").
      Add("Rishita Gupta", "1502").
      Add("Robin Sahoo", "1503").
      Add("Gillian Megan", "1504");;
printfn "Map - students: %A" students

(* Convert a list to Map *)
let capitals =
   [ "Argentina", "Buenos Aires";
      "France ", "Paris";
      "Chili", "Santiago";
      "Malaysia", " Kuala Lumpur";
      "Switzerland", "Bern" ]
   |> Map.ofList;;
printfn "Map capitals : %A" capitals

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Map - students: map
[("Gillian Megan", "1504"); ("Rishita Gupta", "1502"); ("Robin Sahoo", "1503
");
("Zara Ali", "1501")]
Map capitals : map
[("Argentina", "Buenos Aires"); ("Chili", "Santiago"); ("France ", "Paris");
("Malaysia", " Kuala Lumpur"); ("Switzerland", "Bern")]

Вы можете получить доступ к отдельным элементам на карте, используя ключ.

пример

Live Demo

(* Create an empty Map *)
let students =
   Map.empty. (* Creating an empty Map *)
      Add("Zara Ali", "1501").
      Add("Rishita Gupta", "1502").
      Add("Robin Sahoo", "1503").
      Add("Gillian Megan", "1504");;
printfn "Map - students: %A" students

(*Accessing an element using key *)
printfn "%A" students.["Zara Ali"]

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Map - students: map
[("Gillian Megan", "1504"); ("Rishita Gupta", "1502"); ("Robin Sahoo", "1503
");
("Zara Ali", "1501")]
"1501"

Основные операции на картах

Добавить имя модуля

В следующей таблице приведены основные операции на картах —

член Описание
добавлять Возвращает новую карту с привязкой, добавленной к данной карте.
ContainsKey Проверяет, находится ли элемент в домене карты.
подсчитывать Количество привязок на карте.
Пустой Возвращает true, если на карте нет привязок.
Вещь Поиск элемента на карте. Вызывает KeyNotFoundException, если на карте нет привязки.
Удалить Удаляет элемент из домена карты. Исключение не возникает, если элемент отсутствует.
TryFind Поиск элемента на карте, возвращая значение Some, если элемент находится в домене карты, и None, если нет.

В следующем примере демонстрируется использование некоторых из перечисленных выше функций.

пример

Live Demo

(* Create an empty Map *)
let students =
   Map.empty. (* Creating an empty Map *)
      Add("Zara Ali", "1501").
      Add("Rishita Gupta", "1502").
      Add("Robin Sahoo", "1503").
      Add("Gillian Megan", "1504").
      Add("Shraddha Dubey", "1505").
      Add("Novonil Sarker", "1506").
      Add("Joan Paul", "1507");;
printfn "Map - students: %A" students
printfn "Map - number of students: %d" students.Count

(* finding the registration number of a student*)
let found = students.TryFind "Rishita Gupta"
match found with
| Some x -> printfn "Found %s." x
| None -> printfn "Did not find the specified value."

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Map - students: map
[("Gillian Megan", "1504"); ("Joan Paul", "1507"); ("Novonil Sarker", "1506"
);
("Rishita Gupta", "1502"); ("Robin Sahoo", "1503");
("Shraddha Dubey", "1505"); ("Zara Ali", "1501")]
Map - number of students: 7
Found 1502.

F # — Дискриминационные Союзы

Объединения или различимые объединения позволяют создавать сложные структуры данных, представляющие четко определенный набор вариантов. Например, вам нужно построить реализацию переменной выбора , которая имеет два значения yes и no. Используя инструмент Unions, вы можете создать это.

Синтаксис

Дискриминационные союзы определяются с использованием следующего синтаксиса —

type type-name =
   | case-identifier1 [of [ fieldname1 : ] type1 [ * [ fieldname2 : ] 
type2 ...]
   | case-identifier2 [of [fieldname3 : ]type3 [ * [ fieldname4 : ]type4 ...]
...

Наша простая реализация, выбор, будет выглядеть следующим образом:

type choice =
   | Yes
   | No

В следующем примере используется выбор типа —

Live Demo

type choice =
   | Yes
   | No

let x = Yes (* creates an instance of choice *)
let y = No (* creates another instance of choice *)
let main() =
   printfn "x: %A" x
   printfn "y: %A" y
main()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

x: Yes
y: No

Пример 1

В следующем примере показана реализация состояний напряжения, которые устанавливают бит на высокий или низкий уровень.

Live Demo

type VoltageState =
   | High
   | Low

let toggleSwitch = function (* pattern matching input *)
   | High -> Low
   | Low -> High

let main() =
   let on = High
   let off = Low
   let change = toggleSwitch off

   printfn "Switch on state: %A" on
   printfn "Switch off state: %A" off
   printfn "Toggle off: %A" change
   printfn "Toggle the Changed state: %A" (toggleSwitch change)

main()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Switch on state: High
Switch off state: Low
Toggle off: High
Toggle the Changed state: Low

Пример 2

Live Demo

type Shape =
   // here we store the radius of a circle
   | Circle of float

   // here we store the side length.
   | Square of float

   // here we store the height and width.
   | Rectangle of float * float

let pi = 3.141592654

let area myShape =
   match myShape with
   | Circle radius -> pi * radius * radius
   | Square s -> s * s
   | Rectangle (h, w) -> h * w

let radius = 12.0
let myCircle = Circle(radius)
printfn "Area of circle with radius %g: %g" radius (area myCircle)

let side = 15.0
let mySquare = Square(side)
printfn "Area of square that has side %g: %g" side (area mySquare)

let height, width = 5.0, 8.0
let myRectangle = Rectangle(height, width)
printfn "Area of rectangle with height %g and width %g is %g" height width (area myRectangle)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Area of circle with radius 12: 452.389
Area of square that has side 15: 225
Area of rectangle with height 5 and width 8 is 40

F # — изменяемые данные

Переменные в F # являются неизменяемыми, что означает , что как только переменная связана со значением, она не может быть изменена. Они фактически скомпилированы как статические свойства только для чтения.

Следующий пример демонстрирует это.

пример

Live Demo

let x = 10
let y = 20
let z = x + y

printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

let x = 15
let y = 20
let z = x + y

printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

Когда вы компилируете и запускаете программу, она показывает следующее сообщение об ошибке —

Duplicate definition of value 'x'
Duplicate definition of value 'Y'
Duplicate definition of value 'Z'

Изменяемые переменные

Иногда вам нужно изменить значения, хранящиеся в переменной. Чтобы указать, что может быть изменение значения объявленной и назначенной переменной в более поздней части программы, F # предоставляет ключевое слово mutable . Вы можете объявить и назначить изменяемые переменные, используя это ключевое слово, значения которого вы будете изменять.

Ключевое слово mutable позволяет объявлять и назначать значения в изменяемой переменной.

Вы можете присвоить некоторое начальное значение изменяемой переменной, используя ключевое слово let . Однако, чтобы присвоить ему новое последующее значение, вам нужно использовать оператор <- .

Например,

let mutable x = 10
x <- 15

Следующий пример прояснит концепцию —

пример

Live Demo

let mutable x = 10
let y = 20
let mutable z = x + y

printfn "Original Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

printfn "Let us change the value of x"
printfn "Value of z will change too."

x <- 15
z <- x + y

printfn "New Values:"
printfn "x: %i" x
printfn "y: %i" y
printfn "z: %i" z

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Original Values:
x: 10
y: 20
z: 30
Let us change the value of x
Value of z will change too.
New Values:
x: 15
y: 20
z: 35

Использование изменяемых данных

Изменяемые данные часто требуются и используются при обработке данных, особенно в структуре данных записи. Следующий пример демонстрирует это —

Live Demo

open System

type studentData =
   { ID : int;
      mutable IsRegistered : bool;
      mutable RegisteredText : string; }

let getStudent id =
   { ID = id;
      IsRegistered = false;
      RegisteredText = null; }

let registerStudents (students : studentData list) =
   students |> List.iter(fun st ->
      st.IsRegistered <- true
      st.RegisteredText <- sprintf "Registered %s" (DateTime.Now.ToString("hh:mm:ss"))

      Threading.Thread.Sleep(1000) (* Putting thread to sleep for 1 second to simulate processing overhead. *))

let printData (students : studentData list) =
   students |> List.iter (fun x -> printfn "%A" x)

let main() =
   let students = List.init 3 getStudent

   printfn "Before Process:"
   printData students

   printfn "After process:"
   registerStudents students
   printData students

   Console.ReadKey(true) |> ignore

main()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Before Process:
{ID = 0;
IsRegistered = false;
RegisteredText = null;}
{ID = 1;
IsRegistered = false;
RegisteredText = null;}
{ID = 2;
IsRegistered = false;
RegisteredText = null;}
After process:
{ID = 0;
IsRegistered = true;
RegisteredText = "Registered 05:39:15";}
{ID = 1;
IsRegistered = true;
RegisteredText = "Registered 05:39:16";}
{ID = 2;
IsRegistered = true;
RegisteredText = "Registered 05:39:17";}

F # — Массивы

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

Создание массивов

Вы можете создавать массивы, используя различные синтаксисы и способы, или используя функции из модуля Array. В этом разделе мы обсудим создание массивов без использования функций модуля.

Существует три синтаксических способа создания массивов без функций —

  • Перечисляя последовательные значения между [| и |] и разделенные точкой с запятой.
  • Размещая каждый элемент на отдельной строке, в этом случае точка с запятой является необязательной.
  • Используя выражения последовательности.

Вы можете получить доступ к элементам массива, используя оператор точки (.) И скобки ([и]).

Следующий пример демонстрирует создание массивов —

Live Demo

//using semicolon separator
let array1 = [| 1; 2; 3; 4; 5; 6 |]
for i in 0 .. array1.Length - 1 do
   printf "%d " array1.[i]
printfn" "

// without semicolon separator
let array2 =
   [|
      1
      2
      3
      4
      5
   |]
for i in 0 .. array2.Length - 1 do
   printf "%d " array2.[i]
printfn" "

//using sequence
let array3 = [| for i in 1 .. 10 -> i * i |]
for i in 0 .. array3.Length - 1 do
   printf "%d " array3.[i]
printfn" "

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

1 2 3 4 5 6
1 2 3 4 5
1 4 9 16 25 36 49 64 81 100

Основные операции над массивами

Модуль библиотеки Microsoft.FSharp.Collections.Array поддерживает операции с одномерными массивами.

В следующей таблице приведены основные операции над массивами:

Значение Описание
добавьте: ‘T [] →’ T [] → ‘T [] Создает массив, который содержит элементы одного массива, за которыми следуют элементы другого массива.
среднее: ^ T [] → ^ T Возвращает среднее значение элементов в массиве.
AverageBy: (‘T → ^ U) →’ T [] → ^ U Возвращает среднее значение элементов, сгенерированных путем применения функции к каждому элементу массива.
blit: ‘T [] → int →’ T [] → int → int → unit Читает диапазон элементов из одного массива и записывает их в другой.
выберите: (опция ‘T → U) →’ T [] → ‘U [] Применяет предоставленную функцию к каждому элементу массива. Возвращает массив, содержащий результаты x для каждого элемента, для которого функция возвращает Some (x).
собрать: (‘T →’ U []) → T [] → ‘U [] Применяет предоставленную функцию к каждому элементу массива, объединяет результаты и возвращает объединенный массив.
concat: seq <‘T []> →’ T [] Создает массив, который содержит элементы каждой из предоставленных последовательностей массивов.
копия: ‘T →’ T [] Создает массив, который содержит элементы предоставленного массива.
создать: int → ‘T →’ T [] Создает массив, все элементы которого изначально имеют заданное значение.
пусто: ‘T [] Возвращает пустой массив данного типа.
существует: (‘T → bool) →’ T [] → bool Проверяет, удовлетворяет ли какой-либо элемент массива предоставленному предикату.
существует2: (‘T1 →’ T2 → bool) → ‘T1 [] →’ T2 [] → bool Проверяет, удовлетворяет ли любая пара соответствующих элементов двух массивов указанному условию.
заполните: ‘T [] → int → int →’ T → единица Заполняет диапазон элементов массива предоставленным значением.
фильтр: (‘T → bool) →’ T [] → ‘T [] Возвращает коллекцию, которая содержит только элементы предоставленного массива, для которого предоставленное условие возвращает true .
найти: (‘T → bool) →’ T [] → ‘T Возвращает первый элемент, для которого предоставленная функция возвращает true . Вызывает KeyNotFoundException, если такого элемента не существует.
findIndex: (‘T → bool) →’ T [] → int Возвращает индекс первого элемента в массиве, который удовлетворяет заданному условию. Вызывает KeyNotFoundException, если ни один из элементов не удовлетворяет условию.
свернуть: (‘State →’ T → ‘State) →’ State → ‘T [] →’ State Применяет функцию к каждому элементу массива, пропуская аргумент аккумулятора через вычисления. Если входной функцией является f, а элементами массива i0 … iN, эта функция вычисляет f (… (fs i0) …) iN.
fold2: (‘State →’ T1 → ‘T2 →’ State) → ‘State →’ T1 [] → ‘T2 [] →’ State Применяет функцию к парам элементов из двух предоставленных массивов слева направо, пропуская аргумент аккумулятора через вычисления. Два входных массива должны иметь одинаковую длину; в противном случае ArgumentException повышается.
foldBack: (‘T →’ State → ‘State) →’ T [] → ‘State →’ State Применяет функцию к каждому элементу массива, пропуская аргумент аккумулятора через вычисления. Если входной функцией является f, а элементами массива i0 … iN, эта функция вычисляет f i0 (… (f iN s)).
foldBack2: (‘T1 →’ T2 → ‘State →’ State) → ‘T1 [] →’ T2 [] → ‘State →’ State Применяет функцию к парам элементов из двух предоставленных массивов справа налево, пропуская аргумент аккумулятора через вычисления. Два входных массива должны иметь одинаковую длину; в противном случае ArgumentException повышается.
forall: (‘T → bool) →’ T [] → bool Проверяет, все ли элементы массива удовлетворяют предоставленному условию.
forall2: (‘T1 →’ T2 → bool) → ‘T1 [] →’ T2 [] → bool Проверяет, все ли соответствующие элементы двух предоставленных массивов удовлетворяют предоставленному условию.
получить: ‘T [] → int →’ T Получает элемент из массива.
init: int → (int → ‘T) →’ T [] Использует предоставленную функцию для создания массива предоставленного измерения.
isEmpty: ‘T [] → bool Проверяет, есть ли в массиве какие-либо элементы.
iter: (‘T → единица) →’ T [] → единица Применяет предоставленную функцию к каждому элементу массива.
iter2: (‘T1 →’ T2 → единица) → ‘T1 [] →’ T2 [] → единица) Применяет предоставленную функцию к паре элементов из совпадающих индексов в двух массивах. Два массива должны иметь одинаковую длину; в противном случае ArgumentException повышается.
iteri: (int → ‘T → unit) →’ T [] → unit Применяет предоставленную функцию к каждому элементу массива. Целое число, переданное функции, указывает индекс элемента.
iteri2: (int → ‘T1 →’ T2 → единица измерения) → ‘T1 [] →’ T2 [] → единица измерения Применяет предоставленную функцию к паре элементов из соответствующих индексов в двух массивах, также передавая индекс элементов. Два массива должны иметь одинаковую длину; в противном случае возникает ArgumentException.
длина: ‘T [] → int Возвращает длину массива. Свойство Length делает то же самое.
карта: (‘T →’ U) → ‘T [] →’ U [] Создает массив, элементы которого являются результатами применения предоставленной функции к каждому из элементов предоставленного массива.
map2: (‘T1 →’ T2 → ‘U) →’ T1 [] → ‘T2 [] →’ U [] Создает массив, элементы которого являются результатами применения предоставленной функции к соответствующим элементам двух предоставленных массивов. Два входных массива должны иметь одинаковую длину; в противном случае ArgumentException повышается.
mapi: (int → ‘T →’ U) → ‘T [] →’ U [] Создает массив, элементы которого являются результатами применения предоставленной функции к каждому из элементов предоставленного массива. Целочисленный индекс, переданный функции, указывает на индекс преобразуемого элемента.
mapi2: (int → ‘T1 →’ T2 → ‘U) →’ T1 [] → ‘T2 [] →’ U [] Создает массив, элементы которого являются результатами применения предоставленной функции к соответствующим элементам двух коллекций попарно, также передавая индекс элементов. Два входных массива должны иметь одинаковую длину; в противном случае ArgumentException повышается.
max: ‘T [] →’ T Возвращает самый большой из всех элементов массива. Operators.max используется для сравнения элементов.
maxBy: (‘T →’ U) → ‘T [] →’ T Возвращает наибольший из всех элементов массива по сравнению с Operators.max для результата функции.
мин: (‘T [] →’ T Возвращает наименьший из всех элементов массива. Operators.min используется для сравнения элементов.
minBy: (‘T →’ U) → ‘T [] →’ T Возвращает наименьший из всех элементов массива. Operators.min используется для сравнения элементов.
ofList: ‘T list →’ T [] Создает массив из предоставленного списка.
ofSeq: seq <‘T> →’ T [] Создает массив из предоставленного перечисляемого объекта.
раздел: (‘T → bool) →’ T [] → ‘T [] *’ T [] Разбивает массив на два массива, один из которых содержит элементы, для которых указанное условие возвращает true, а другой — те, для которых он возвращает false .
перестановка: (int → int) → ‘T [] →’ T [] Переставляет элементы массива в соответствии с указанной перестановкой.
выберите: (опция ‘T →’ U) → ‘T [] →’ U Применяет предоставленную функцию к последовательным элементам предоставленного массива, возвращая первый результат, где функция возвращает Some (x) для некоторого x. Если функция никогда не возвращает Some (x), вызывается KeyNotFoundException.
уменьшить: (‘T →’ T → ‘T) →’ T [] → ‘T Применяет функцию к каждому элементу массива, пропуская аргумент аккумулятора через вычисления. Если входной функцией является f, а элементами массива i0 … iN, эта функция вычисляет f (… (f i0 i1) …) iN. Если массив имеет нулевой размер, ArgumentException повышается.
ReduckBack: (‘T →’ T → ‘T) →’ T [] → ‘T Применяет функцию к каждому элементу массива, пропуская аргумент аккумулятора через вычисления. Если входная функция — f, а элементы — i0 … iN, эта функция вычисляет f i0 (… (f iN-1 iN)). Если массив имеет нулевой размер, ArgumentException повышается.
rev: ‘T [] →’ T [] Меняет порядок элементов в предоставленном массиве.
сканирование: (‘State →’ T → ‘State) →’ State → ‘T [] →’ State []) Ведет себя как фолд, но возвращает промежуточные результаты вместе с окончательными результатами.
scanBack: (‘T →’ State → ‘State) →’ T [] → ‘State →’ State [] Ведет себя как foldBack, но возвращает промежуточные результаты вместе с окончательными результатами.
установить: ‘T [] → int →’ T → единица Устанавливает элемент массива.
сортировка: ‘T [] →’ T [] Сортирует элементы массива и возвращает новый массив. Operators.compare используется для сравнения элементов.
sortBy: (‘T →’ Key) → ‘T [] →’ T [] Сортирует элементы массива с помощью предоставленной функции для преобразования элементов в тип, на котором основана операция сортировки, и возвращает новый массив. Operators.compare используется для сравнения элементов.
sortInPlace: ‘T [] → единица Сортирует элементы массива, изменяя массив на месте, используя предоставленную функцию сравнения. Operators.compare используется для сравнения элементов.
sortInPlaceBy: (‘T →’ Key) → ‘T [] → unit Сортирует элементы массива, изменяя массив на месте, используя предоставленную проекцию для ключей. Operators.compare используется для сравнения элементов.
sortInPlaceWith: (‘T →’ T → int) → ‘T [] → единица Сортирует элементы массива, используя предоставленную функцию сравнения, чтобы изменить массив на месте.
sortWith: (‘T →’ T → int) → ‘T [] →’ T [] Сортирует элементы массива с помощью предоставленной функции сравнения и возвращает новый массив.
sub: ‘T [] → int → int →’ T [] Создает массив, который содержит предоставленный поддиапазон, который определяется начальным индексом и длиной.
сумма: ‘T [] → ^ T Возвращает сумму элементов в массиве.
sumBy: (‘T → ^ U) →’ T [] → ^ U Возвращает сумму результатов, созданных путем применения функции к каждому элементу массива.
toList: ‘T [] →’ T list Преобразует предоставленный массив в список.
toSeq: ‘T [] → seq <‘ T> Рассматривает предоставленный массив как последовательность.
tryFind: (‘T → bool) → опция’ T [] → ‘T Возвращает первый элемент в предоставленном массиве, для которого предоставленная функция возвращает true . Возвращает None, если такого элемента не существует.
tryFindIndex: (‘T → bool) →’ T [] → int option Возвращает индекс первого элемента в массиве, который удовлетворяет заданному условию.
tryPick: (опция ‘T →’ U) → опция ‘T [] →’ U Применяет предоставленную функцию к последовательным элементам предоставленного массива и возвращает первый результат, где функция возвращает Some (x) для некоторого x. Если функция никогда не возвращает Some (x), None возвращается.
распаковать: (‘T1 *’ T2) [] → ‘T1 [] *’ T2 [] Разбивает массив пар кортежей на кортеж из двух массивов.
распаковать3: (‘T1 *’ T2 * ‘T3) [] →’ T1 [] * ‘T2 [] *’ T3 [] Разбивает массив кортежей из трех элементов на кортеж из трех массивов.
zeroCreate: int → ‘T [] Создает массив, элементы которого изначально установлены в значение по умолчанию Unchecked.defaultof <‘T>.
zip: ‘T1 [] →’ T2 [] → (‘T1 *’ T2) [] Объединяет два массива в массив кортежей, которые имеют два элемента. Два массива должны иметь одинаковую длину; в противном случае ArgumentException повышается.
zip3: ‘T1 [] →’ T2 [] → ‘T3 [] → (‘ T1 * ‘T2 * 113’ T3) [] Объединяет три массива в массив кортежей, которые имеют три элемента. Три массива должны иметь одинаковую длину; в противном случае ArgumentException повышается.

В следующем разделе мы увидим использование некоторых из этих функций.

Создание массивов с использованием функций

Модуль Array предоставляет несколько функций, которые создают массив с нуля.

  • Функция Array.empty создает новый пустой массив.

  • Функция Array.create создает массив указанного размера и устанавливает для всех элементов заданные значения.

  • Функция Array.init создает массив с заданным размером и функцией для генерации элементов.

  • Функция Array.zeroCreate создает массив, в котором все элементы инициализируются нулевым значением.

  • Функция Array.copy создает новый массив, содержащий элементы, которые копируются из существующего массива.

  • Функция Array.sub генерирует новый массив из поддиапазона массива.

  • Функция Array.append создает новый массив путем объединения двух существующих массивов.

  • Функция Array.choose выбирает элементы массива для включения в новый массив.

  • Функция Array.collect запускает указанную функцию для каждого элемента массива существующего массива, а затем собирает элементы, сгенерированные функцией, и объединяет их в новый массив.

  • Функция Array.concat берет последовательность массивов и объединяет их в один массив.

  • Функция Array.filter принимает булеву функцию условия и генерирует новый массив, который содержит только те элементы из входного массива, для которых условие выполняется.

  • Функция Array.rev генерирует новый массив, изменяя порядок существующего массива.

Функция Array.empty создает новый пустой массив.

Функция Array.create создает массив указанного размера и устанавливает для всех элементов заданные значения.

Функция Array.init создает массив с заданным размером и функцией для генерации элементов.

Функция Array.zeroCreate создает массив, в котором все элементы инициализируются нулевым значением.

Функция Array.copy создает новый массив, содержащий элементы, которые копируются из существующего массива.

Функция Array.sub генерирует новый массив из поддиапазона массива.

Функция Array.append создает новый массив путем объединения двух существующих массивов.

Функция Array.choose выбирает элементы массива для включения в новый массив.

Функция Array.collect запускает указанную функцию для каждого элемента массива существующего массива, а затем собирает элементы, сгенерированные функцией, и объединяет их в новый массив.

Функция Array.concat берет последовательность массивов и объединяет их в один массив.

Функция Array.filter принимает булеву функцию условия и генерирует новый массив, который содержит только те элементы из входного массива, для которых условие выполняется.

Функция Array.rev генерирует новый массив, изменяя порядок существующего массива.

Следующие примеры демонстрируют эти функции —

Пример 1

Live Demo

(* using create and set *)
let array1 = Array.create 10 ""
for i in 0 .. array1.Length - 1 do
   Array.set array1 i (i.ToString())
for i in 0 .. array1.Length - 1 do
   printf "%s " (Array.get array1 i)
printfn " "

(* empty array *)
let array2 = Array.empty
printfn "Length of empty array: %d" array2.Length

let array3 = Array.create 10 7.0
printfn "Float Array: %A" array3

(* using the init and zeroCreate *)
let array4 = Array.init 10 (fun index -> index * index)
printfn "Array of squares: %A" array4

let array5 : float array = Array.zeroCreate 10
let (myZeroArray : float array) = Array.zeroCreate 10
printfn "Float Array: %A" array5

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

0 1 2 3 4 5 6 7 8 9
Length of empty array: 0
Float Array: [|7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0; 7.0|]
Array of squares: [|0; 1; 4; 9; 16; 25; 36; 49; 64; 81|]
Float Array: [|0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0; 0.0|]

Пример 2

Live Demo

(* creating subarray from element 5 *)
(* containing 15 elements thereon *)

let array1 = [| 0 .. 50 |]
let array2 = Array.sub array1 5 15
printfn "Sub Array:"
printfn "%A" array2

(* appending two arrays *)
let array3 = [| 1; 2; 3; 4|]
let array4 = [| 5 .. 9 |]
printfn "Appended Array:"
let array5 = Array.append array3 array4
printfn "%A" array5

(* using the Choose function *)
let array6 = [| 1 .. 20 |]
let array7 = Array.choose (fun elem -> if elem % 3 = 0 then
                                             Some(float (elem))
                                          else
                                             None) array6
printfn "Array with Chosen elements:"
printfn "%A" array7

(*using the Collect function *)
let array8 = [| 2 .. 5 |]
let array9 = Array.collect (fun elem -> [| 0 .. elem - 1 |]) array8
printfn "Array with collected elements:"
printfn "%A" array9

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Sub Array:
[|5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19|]
Appended Array:
[|1; 2; 3; 4; 5; 6; 7; 8; 9|]
Array with Chosen elements:
[|3.0; 6.0; 9.0; 12.0; 15.0; 18.0|]
Array with collected elements:
[|0; 1; 0; 1; 2; 0; 1; 2; 3; 0; 1; 2; 3; 4|]

Поиск массивов

Функция Array.find принимает логическую функцию и возвращает первый элемент, для которого функция возвращает значение true, в противном случае возникает исключение KeyNotFoundException.

Функция Array.findIndex работает аналогично, за исключением того, что она возвращает индекс элемента вместо самого элемента.

Следующий пример демонстрирует это.

Microsoft предоставляет этот интересный пример программы, который находит первый элемент в диапазоне заданного числа, который является как идеальным квадратом, так и идеальным кубом —

Live Demo

let array1 = [| 2 .. 100 |]
let delta = 1.0e-10
let isPerfectSquare (x:int) =
   let y = sqrt (float x)
   abs(y - round y) < delta

let isPerfectCube (x:int) =
   let y = System.Math.Pow(float x, 1.0/3.0)
   abs(y - round y) < delta

let element = Array.find (fun elem -> isPerfectSquare elem && isPerfectCube elem) array1

let index = Array.findIndex (fun elem -> isPerfectSquare elem && isPerfectCube elem) array1

printfn "The first element that is both a square and a cube is %d and its index is %d." element index

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

The first element that is both a square and a cube is 64 and its index is 62.

F # — изменяемые списки

Класс List <‘T> представляет строго типизированный список объектов, к которым можно получить доступ по индексу.

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

Создание изменяемого списка

Списки создаются с использованием нового ключевого слова и вызова конструктора списка. Следующий пример демонстрирует это —

Live Demo

(* Creating a List *)
open System.Collections.Generic

let booksList = new List<string>()
booksList.Add("Gone with the Wind")
booksList.Add("Atlas Shrugged")
booksList.Add("Fountainhead")
booksList.Add("Thornbirds")
booksList.Add("Rebecca")
booksList.Add("Narnia")

booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

0: Gone with the Wind
1: Atlas Shrugged
2: Fountainhead
3: Thornbirds
4: Rebecca
5: Narnia

Список (T) Класс

Класс List (T) представляет строго типизированный список объектов, к которым можно получить доступ по индексу. Он предоставляет методы для поиска, сортировки и управления списками.

В следующих таблицах представлены свойства, конструкторы и методы класса List (T).

свойства

Имущество Описание
Вместимость Получает или задает общее количество элементов, которое может содержать внутренняя структура данных без изменения размера.
подсчитывать Получает количество элементов, содержащихся в списке (T).
Вещь Получает или задает элемент по указанному индексу.

Конструкторы

Конструктор Описание
Список (Т) () Инициализирует новый экземпляр класса List (T), который является пустым и имеет начальную емкость по умолчанию.
Список (T) (IEnumerable (T)) Инициализирует новый экземпляр класса List (T), который содержит элементы, скопированные из указанной коллекции, и имеет достаточную емкость для размещения количества скопированных элементов.
Список (Т) (Int32) Инициализирует новый экземпляр класса List (T), который является пустым и имеет указанную начальную емкость.

метод

методы Описание
добавлять Добавляет объект в конец списка (T).
AddRange Добавляет элементы указанной коллекции в конец списка (T).
AsReadOnly Возвращает доступную только для чтения оболочку IList (T) для текущей коллекции.
BinarySearch (Т) Выполняет поиск во всем отсортированном списке List (T) для элемента, используя компаратор по умолчанию, и возвращает индекс элемента, начинающийся с нуля.
Бинарный поиск (T, IComparer (T)) Выполняет поиск во всем отсортированном списке List (T) для элемента, используя указанный компаратор, и возвращает индекс элемента, начинающийся с нуля.
BinarySearch (Int32, Int32, T, IComparer (T)) Выполняет поиск в диапазоне элементов в отсортированном списке List (T) для элемента с использованием указанного компаратора и возвращает индекс элемента, начинающийся с нуля.
Очистить Удаляет все элементы из списка (T).
Содержит Определяет, есть ли элемент в списке (T).
ConvertAll (TOutput) Преобразует элементы в текущем списке (T) в другой тип и возвращает список, содержащий преобразованные элементы.
CopyTo (T []) Копирует весь список (T) в совместимый одномерный массив, начиная с начала целевого массива.
CopyTo (T [], Int32) Копирует весь список (T) в совместимый одномерный массив, начиная с указанного индекса целевого массива.
CopyTo (Int32, T [], Int32, Int32) Копирует диапазон элементов из списка (T) в совместимый одномерный массив, начиная с указанного индекса целевого массива.
Равно (Объект) Определяет, равен ли указанный объект текущему объекту. (Унаследовано от Object.)
Существует Определяет, содержит ли List (T) элементы, которые соответствуют условиям, заданным указанным предикатом.
завершать Позволяет объекту попытаться освободить ресурсы и выполнить другие операции очистки, прежде чем он будет утилизирован сборщиком мусора (Унаследовано от Object).
найти Ищет элемент, который соответствует условиям, определенным указанным предикатом, и возвращает первое вхождение во всем Списке (T).
Найти все Извлекает все элементы, которые соответствуют условиям, определенным указанным предикатом.
FindIndex (предикат (Т)) Ищет элемент, который соответствует условиям, определенным указанным предикатом, и возвращает нулевой индекс первого вхождения во всем Списке (T).
FindIndex (Int32, Предикат (T)) Ищет элемент, который соответствует условиям, определенным указанным предикатом, и возвращает нулевой индекс первого вхождения в пределах диапазона элементов в Списке (T), который простирается от указанного индекса до последнего элемента.
FindIndex (Int32, Int32, Предикат (T)) Выполняет поиск элемента, который соответствует условиям, заданным указанным предикатом, и возвращает нулевой индекс первого вхождения в диапазоне элементов списка (T), который начинается с указанного индекса и содержит указанное количество элементов.
FindLast Ищет элемент, который соответствует условиям, заданным указанным предикатом, и возвращает последнее вхождение во всем списке (T).
FindLastIndex (предикат (Т)) Ищет элемент, который соответствует условиям, определенным указанным предикатом, и возвращает нулевой индекс последнего вхождения во всем списке (T).
FindLastIndex (Int32, Предикат (T)) Ищет элемент, который соответствует условиям, определенным указанным предикатом, и возвращает нулевой индекс последнего вхождения в пределах диапазона элементов в Списке (T), который простирается от первого элемента до указанного индекса.
FindLastIndex (Int32, Int32, Предикат (T)) Выполняет поиск элемента, который соответствует условиям, определенным указанным предикатом, и возвращает нулевой индекс последнего вхождения в диапазоне элементов списка (T), который содержит указанное количество элементов и заканчивается указанным индексом.
Для каждого Выполняет указанное действие для каждого элемента списка (T).
GetEnumerator Возвращает перечислитель, который перебирает список (T).
GetHashCode Служит в качестве хэш-функции по умолчанию. (Унаследовано от Object.)
GetRange Создает поверхностную копию диапазона элементов в исходном списке (T).
GetType Получает тип текущего экземпляра. (Унаследовано от Object.)
IndexOf (Т) Выполняет поиск указанного объекта и возвращает нулевой индекс первого вхождения во всем списке (T).
IndexOf (T, Int32) Выполняет поиск указанного объекта и возвращает нулевой индекс первого вхождения в диапазоне элементов списка (T), который простирается от указанного индекса до последнего элемента.
IndexOf (T, Int32, Int32) Выполняет поиск указанного объекта и возвращает нулевой индекс первого вхождения в диапазоне элементов списка (T), который начинается с указанного индекса и содержит указанное количество элементов.
Вставить Вставляет элемент в список (T) по указанному индексу.
InsertRange Вставляет элементы коллекции в список (T) по указанному индексу.
LastIndexOf (Т) Ищет указанный объект и возвращает нулевой индекс последнего вхождения во всем Списке (T).
LastIndexOf (T, Int32) Выполняет поиск указанного объекта и возвращает нулевой индекс последнего вхождения в диапазоне элементов списка (T), который простирается от первого элемента до указанного индекса.
LastIndexOf (T, Int32, Int32) Выполняет поиск указанного объекта и возвращает нулевой индекс последнего вхождения в диапазоне элементов списка (T), который содержит указанное количество элементов и заканчивается указанным индексом.
MemberwiseClone Создает поверхностную копию текущего объекта. (Унаследовано от Object.)
Удалить Удаляет первое вхождение определенного объекта из списка (T).
Удалить все Удаляет все элементы, которые соответствуют условиям, заданным указанным предикатом.
RemoveAt Удаляет элемент по указанному индексу List (T).
RemoveRange Удаляет ряд элементов из списка (T).
Задний ход() Меняет порядок элементов во всем Списке (T).
Обратный (Int32, Int32) Меняет порядок элементов в указанном диапазоне.
Сортировать() Сортирует элементы во всем списке (T), используя компаратор по умолчанию.
Сортировка (Сравнение (Т)) Сортирует элементы во всем Списке (T), используя указанную Систему. Сравнение (Т).
Сортировка (IComparer (Т)) Сортирует элементы во всем Списке (T), используя указанный компаратор.
Сортировка (Int32, Int32, IComparer (T)) Сортирует элементы в диапазоне элементов в List (T), используя указанный компаратор.
ToArray Копирует элементы списка (T) в новый массив.
Нанизывать Возвращает строку, которая представляет текущий объект. (Унаследовано от Object.)
TrimExcess Устанавливает емкость для фактического количества элементов в Списке (T), если это число меньше порогового значения.
TrueForAll Определяет, соответствует ли каждый элемент в Списке (T) условиям, определенным указанным предикатом.

пример

Live Demo

(* Creating a List *)
open System.Collections.Generic

let booksList = new List<string>()
booksList.Add("Gone with the Wind")
booksList.Add("Atlas Shrugged")
booksList.Add("Fountainhead")
booksList.Add("Thornbirds")
booksList.Add("Rebecca")
booksList.Add("Narnia")

printfn"Total %d books" booksList.Count
booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])
booksList.Insert(2, "Roots")

printfn("after inserting at index 2")
printfn"Total %d books" booksList.Count

booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])
booksList.RemoveAt(3)

printfn("after removing from index 3")
printfn"Total %d books" booksList.Count

booksList |> Seq.iteri (fun index item -> printfn "%i: %s" index booksList.[index])

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Total 6 books
0: Gone with the Wind
1: Atlas Shrugged
2: Fountainhead
3: Thornbirds
4: Rebecca
5: Narnia
after inserting at index 2
Total 7 books
0: Gone with the Wind
1: Atlas Shrugged
2: Roots
3: Fountainhead
4: Thornbirds
5: Rebecca
6: Narnia
after removing from index 3
Total 6 books
0: Gone with the Wind
1: Atlas Shrugged
2: Roots
3: Thornbirds
4: Rebecca
5: Narnia

F # — изменчивый словарь

Класс Dictionary <‘TKey,’ TValue> является изменяемым аналогом структуры данных карты F # и содержит много одинаковых функций.

Повторяем из главы «Карта» в F #, карта — это особый вид набора, который связывает значения с ключом.

Создание изменчивого словаря

Изменяемые словари создаются с использованием нового ключевого слова и вызова конструктора списка. Следующий пример демонстрирует это —

Live Demo

open System.Collections.Generic
let dict = new Dictionary<string, string>()
dict.Add("1501", "Zara Ali")
dict.Add("1502","Rishita Gupta")
dict.Add("1503","Robin Sahoo")
dict.Add("1504","Gillian Megan")
printfn "Dictionary - students: %A" dict

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Dictionary - students: seq
[[1501, Zara Ali]; [1502, Rishita Gupta]; [1503, Robin Sahoo];
[1504, Gillian Megan]]

Словарь (TKey, TValue) Класс

Класс Dictionary (TKey, TValue) представляет собой набор ключей и значений.

В следующих таблицах представлены свойства, конструкторы и методы класса List (T).

свойства

Имущество Описание
Comparer Получает IEqualityComparer (T), который используется для определения равенства ключей для словаря.
подсчитывать Получает количество пар ключ / значение, содержащихся в словаре (TKey, TValue).
Вещь Получает или задает значение, связанное с указанным ключом.
Ключи Получает коллекцию, содержащую ключи в словаре (TKey, TValue).
Ценности Получает коллекцию, содержащую значения в словаре (TKey, TValue).

Конструкторы

Конструкторы Описание
Словарь (TKey, TValue) () Инициализирует новый экземпляр класса Dictionary (TKey, TValue), который является пустым, имеет начальную емкость по умолчанию и использует компаратор равенства по умолчанию для типа ключа.
Словарь (TKey, TValue) (IDictionary (TKey, TValue)) Инициализирует новый экземпляр класса Dictionary (TKey, TValue), который содержит элементы, скопированные из указанного IDictionary (TKey, TValue), и использует компаратор равенства по умолчанию для типа ключа.
Словарь (TKey, TValue) (IEqualityComparer (TKey)) Инициализирует новый экземпляр класса Dictionary (TKey, TValue), который является пустым, имеет начальную емкость по умолчанию и использует указанный IEqualityComparer (T).
Словарь (TKey, TValue) (Int32) Инициализирует новый экземпляр класса Dictionary (TKey, TValue), который пуст, имеет указанную начальную емкость и использует компаратор равенства по умолчанию для типа ключа.
Словарь (TKey, TValue) (IDictionary (TKey, TValue), IEqualityComparer (TKey)) Инициализирует новый экземпляр класса Dictionary (TKey, TValue), который содержит элементы, скопированные из указанного IDictionary (TKey, TValue), и использует указанный IEqualityComparer (T).
Словарь (TKey, TValue) (Int32, IEqualityComparer (TKey)) Инициализирует новый экземпляр класса Dictionary (TKey, TValue), который является пустым, имеет указанную начальную емкость и использует указанный IEqualityComparer (T).
Словарь (TKey, TValue) (SerializationInfo, StreamingContext) Инициализирует новый экземпляр класса ictionary (TKey, TValue) с сериализованными данными.

методы

метод Описание
добавлять Добавляет указанный ключ и значение в словарь.
Очистить Удаляет все ключи и значения из словаря (TKey, TValue).
ContainsKey Определяет, содержит ли словарь (TKey, TValue) указанный ключ.
ContainsValue Определяет, содержит ли словарь (TKey, TValue) определенное значение.
Равно (Объект) Определяет, равен ли указанный объект текущему объекту. (Унаследовано от Object.)
завершать Позволяет объекту попытаться освободить ресурсы и выполнить другие операции очистки, прежде чем он будет утилизирован сборщиком мусора. (Унаследовано от Object.)
GetEnumerator Возвращает перечислитель, который перебирает словарь (TKey, TValue).
GetHashCode Служит в качестве хэш-функции по умолчанию. (Унаследовано от Object.)
GetObjectData Реализует интерфейс System.Runtime.Serialization.ISerializable и возвращает данные, необходимые для сериализации экземпляра Dictionary (TKey, TValue).
GetType Получает тип текущего экземпляра. (Унаследовано от Object.)
MemberwiseClone Создает поверхностную копию текущего объекта. (Унаследовано от Object.)
OnDeserialization Реализует интерфейс System.Runtime.Serialization.ISerializable и вызывает событие десериализации, когда десериализация завершена.
Удалить Удаляет значение с указанным ключом из словаря (TKey, TValue).
Нанизывать Возвращает строку, которая представляет текущий объект. (Унаследовано от Object.)
TryGetValue Получает значение, связанное с указанным ключом.

пример

Live Demo

open System.Collections.Generic
let dict = new Dictionary<string, string>()

dict.Add("1501", "Zara Ali")
dict.Add("1502","Rishita Gupta")
dict.Add("1503","Robin Sahoo")
dict.Add("1504","Gillian Megan")

printfn "Dictionary - students: %A" dict
printfn "Total Number of Students: %d" dict.Count
printfn "The keys: %A" dict.Keys
printf"The Values: %A" dict.Values

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Dictionary - students: seq
[[1501, Zara Ali]; [1502, Rishita Gupta]; [1503, Robin Sahoo];
[1504, Gillian Megan]]
Total Number of Students: 4
The keys: seq ["1501"; "1502"; "1503"; "1504"]
The Values: seq ["Zara Ali"; "Rishita Gupta"; "Robin Sahoo"; "Gillian Megan"]

F # — Базовый ввод / вывод

Основной входной выход включает в себя —

  • Чтение и запись в консоль.
  • Чтение и запись в файл.

Модуль Core.Printf

Мы использовали функции printf и printfn для записи в консоль. В этом разделе мы рассмотрим детали модуля Printf для F #.

Помимо вышеупомянутых функций, модуль Core.Printf в F # имеет различные другие методы для печати и форматирования с использованием маркеров% в качестве заполнителей. В следующей таблице приведены методы с кратким описанием —

Значение Описание
bprintf: StringBuilder → BuilderFormat <‘T> →’ T Печать в StringBuilder.
eprintf: TextWriterFormat <‘T> →’ T Печатает форматированный вывод в stderr.
eprintfn: TextWriterFormat <‘T> →’ T Печатает форматированный вывод в stderr, добавляя новую строку.
failwithf: StringFormat <‘T,’ Result> → ‘T Печатает в строковый буфер и вызывает исключение с заданным результатом.
fprintf: TextWriter → TextWriterFormat <‘T> →’ T Печать для автора текста.
fprintfn: TextWriter → TextWriterFormat <‘T> →’ T Печатает на авторе текста, добавляя новую строку.
kbprintf: (unit → ‘Result) → StringBuilder → BuilderFormat <‘ T, ‘Result> →’ T Подобно bprintf, но вызывает указанную функцию для генерации результата.
kfprintf: (блок → ‘Результат) → TextWriter → TextWriterFormat <‘ T, ‘Результат> →’ T Подобно fprintf, но вызывает указанную функцию для генерации результата.
kprintf: (строка → ‘Результат) → StringFormat <‘ T, ‘Результат> →’ T Подобно printf, но вызывает указанную функцию для генерации результата. Например, они позволяют печати принудительно сбрасываться после того, как весь вывод был введен в канал, но не раньше.
ksprintf: (строка → ‘Результат) → StringFormat <‘ T, ‘Результат> →’ T Подобно sprintf, но вызывает указанную функцию для генерации результата.
printf: TextWriterFormat <‘T> →’ T Печатает форматированный вывод на стандартный вывод.
printfn: TextWriterFormat <‘T> →’ T Печатает форматированный вывод на стандартный вывод, добавляя новую строку.
sprintf: StringFormat <‘T> →’ T Печатает в строку, используя внутренний строковый буфер, и возвращает результат в виде строки.

Спецификации формата

Спецификации формата используются для форматирования ввода или вывода в соответствии с потребностями программистов.

Это строки с маркерами%, указывающими заполнители формата.

Синтаксис заполнителей формата:

%[flags][width][.precision][type]

Тип интерпретируется как —

Тип Описание
% б Форматирует bool, отформатированный как true или false .
% с Форматирует персонажа.
% s Форматирует строку, отформатированную как ее содержимое, без интерпретации управляющих символов.
% d,% i Форматирует любой базовый целочисленный тип, отформатированный как десятичное целое число, со знаком, если базовый целочисленный тип подписан.
% U Форматирует любой основной целочисленный тип, отформатированный как десятичное целое число без знака.
%Икс Форматирует любой основной тип целого числа, отформатированный как шестнадцатеричное целое число без знака, используя строчные буквы от a до f.
%ИКС Форматирует любой основной целочисленный тип, отформатированный как шестнадцатеричное целое без знака, используя заглавные буквы от A до F.
% о Форматирует любой основной целочисленный тип, отформатированный как восьмеричное целое без знака.
% e,% E,% f,% F,% g,% G Форматирует любой базовый тип с плавающей точкой (float, float32), отформатированный с использованием спецификаций формата с плавающей точкой в ​​стиле C.
% e,% E Форматирует значение со знаком в форме [-] d.dddde [sign] ddd, где d — одна десятичная цифра, dddd — одна или несколько десятичных цифр, ddd — ровно три десятичных цифры, а знак + или -.
% е Форматирует значение со знаком в форме [-] dddd.dddd, где dddd — одна или несколько десятичных цифр. Количество цифр перед десятичной запятой зависит от величины числа, а количество цифр после десятичной запятой зависит от запрошенной точности.
% g,% G Форматирует значение со знаком, напечатанное в формате f или e, в зависимости от того, что является более компактным для заданного значения и точности.
% M Форматирует десятичное значение.
% O Форматирует любое значение, напечатанное упаковкой объекта и используя его метод ToString .
% А,% + А Форматирует любое значение, напечатанное с настройками макета по умолчанию. Используйте% + A, чтобы напечатать структуру различаемых союзов с внутренними и частными представлениями.
% в

Общий спецификатор формата, требует двух аргументов. Первый аргумент — это функция, которая принимает два аргумента: во-первых, параметр контекста соответствующего типа для данной функции форматирования (например, TextWriter), а во-вторых, значение для печати, которое либо выводит, либо возвращает соответствующий текст.

Второй аргумент — это конкретное значение для печати.

% т Спецификатор общего формата требует один аргумент: функция, которая принимает параметр контекста соответствующего типа для данной функции форматирования (aTextWriter) и которая либо выводит, либо возвращает соответствующий текст. Основные целочисленные типы: байты, sbyte, int16, uint16, int32, uint32, int64, uint64, nativeint и unativeint. Основные типы с плавающей точкой: float и float32.

Общий спецификатор формата, требует двух аргументов. Первый аргумент — это функция, которая принимает два аргумента: во-первых, параметр контекста соответствующего типа для данной функции форматирования (например, TextWriter), а во-вторых, значение для печати, которое либо выводит, либо возвращает соответствующий текст.

Второй аргумент — это конкретное значение для печати.

Ширина является необязательным параметром. Это целое число, которое указывает минимальную ширину результата. Например,% 5d печатает целое число с пробелами не менее 5 символов.

Допустимые флаги описаны в следующей таблице —

Значение Описание
0 Определяет добавление нулей вместо пробелов для получения необходимой ширины.
Определяет выравнивание по левому краю результата в пределах указанной ширины.
+ Определяет добавление символа +, если число положительное (чтобы соответствовать знаку — для отрицательных чисел).
‘ ‘ (пространство) Определяет добавление дополнительного пробела, если число положительное (чтобы соответствовать — знак для отрицательных чисел).
# Недействительным.

пример

Live Demo

printf "Hello "
printf "World"
printfn ""
printfn "Hello "
printfn "World"
printf "Hi, I'm %s and I'm a %s" "Rohit" "Medical Student"

printfn "d: %f" 212.098f
printfn "e: %f" 504.768f

printfn "x: %g" 212.098f
printfn "y: %g" 504.768f

printfn "x: %e" 212.098f
printfn "y: %e" 504.768f
printfn "True: %b" true

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Hello World
Hello
World
Hi, I'm Rohit and I'm a Medical Studentd: 212.098000
e: 504.768000
x: 212.098
y: 504.768
x: 2.120980e+002
y: 5.047680e+002
True: true

Консольный класс

Этот класс является частью .NET Framework. Он представляет собой стандартные потоки ввода, вывода и ошибок для консольных приложений.

Он предоставляет различные методы для чтения и записи в консоли. В следующей таблице показаны методы —

метод Описание
Звуковой сигнал () Воспроизведение звукового сигнала через динамик консоли.
Beep (Int32, Int32) Воспроизведение звука звукового сигнала определенной частоты и длительности через консольный динамик.
Очистить Очищает буфер консоли и соответствующее окно консоли для отображения информации.
MoveBufferArea (Int32, Int32, Int32, Int32, Int32, Int32) Копирует указанную исходную область экранного буфера в указанную область назначения.
MoveBufferArea (Int32, Int32, Int32, Int32, Int32, Int32, Char, ConsoleColor, ConsoleColor) Копирует указанную исходную область экранного буфера в указанную область назначения.
OpenStandardError () Получает стандартный поток ошибок.
OpenStandardError (Int32) Получает стандартный поток ошибок, для которого установлен указанный размер буфера.
OpenStandardInput () Получает стандартный поток ввода.
OpenStandardInput (Int32) Получает стандартный поток ввода, для которого установлен указанный размер буфера.
OpenStandardOutput () Получает стандартный поток вывода.
OpenStandardOutput (Int32) Получает стандартный поток вывода, для которого установлен указанный размер буфера.
Читать Читает следующий символ из стандартного потока ввода.
ReadKey () Получает следующий символ или функциональную клавишу, нажимаемую пользователем. Нажатая клавиша отображается в окне консоли.
ReadKey (Boolean) Получает следующий символ или функциональную клавишу, нажимаемую пользователем. Нажатая клавиша дополнительно отображается в окне консоли.
ReadLine Читает следующую строку символов из стандартного потока ввода.
ResetColor Устанавливает цвета переднего плана и фона консоли по умолчанию.
SetBufferSize Устанавливает высоту и ширину области экранного буфера для указанных значений.
SetCursorPosition Устанавливает положение курсора.
SetError Устанавливает свойство Error для указанного объекта TextWriter .
SetIn Устанавливает свойство In для указанного объекта TextReader .
накрытый стол Устанавливает свойство Out для указанного объекта TextWriter .
SetWindowPosition Устанавливает положение окна консоли относительно буфера экрана.
SetWindowSize Устанавливает высоту и ширину окна консоли на указанные значения.
Write (Boolean) Записывает текстовое представление указанного логического значения в стандартный поток вывода.
Написать (Char) Записывает указанное значение символа Unicode в стандартный поток вывода.
Запись (Char []) Записывает указанный массив символов Unicode в стандартный поток вывода.
Написать (Decimal) Записывает текстовое представление указанного десятичного значения в стандартный поток вывода.
Написать (Двухместный) Записывает текстовое представление указанного значения с плавающей запятой двойной точности в стандартный поток вывода.
Написать (Int32) Записывает текстовое представление указанного 32-разрядного целого числа со знаком в стандартный поток вывода.
Написать (Int64) Записывает текстовое представление указанного 64-разрядного целого числа со знаком в стандартный поток вывода.
Write (Object) Записывает текстовое представление указанного объекта в стандартный поток вывода.
Написать (Single) Записывает текстовое представление указанного значения с плавающей запятой одинарной точности в стандартный поток вывода.
Write (String) Записывает указанное строковое значение в стандартный поток вывода.
Написать (UInt32) Записывает текстовое представление указанного 32-разрядного целого числа без знака в стандартный поток вывода.
Написать (UInt64) Записывает текстовое представление указанного 64-разрядного целого числа без знака в стандартный поток вывода.
Запись (строка, объект) Записывает текстовое представление указанного объекта в стандартный поток вывода с использованием информации указанного формата.
Запись (Строка, Объект []) Записывает текстовое представление указанного массива объектов в стандартный поток вывода, используя указанную информацию о формате.
Запись (Char [], Int32, Int32) Записывает указанный подмассив символов Unicode в стандартный поток вывода.
Запись (строка, объект, объект) Записывает текстовое представление указанных объектов в стандартный поток вывода с использованием информации указанного формата.
Запись (строка, объект, объект, объект) Записывает текстовое представление указанных объектов в стандартный поток вывода с использованием информации указанного формата.
Запись (строка, объект, объект, объект, объект) Записывает текстовое представление указанных объектов и список параметров переменной длины в стандартный поток вывода, используя информацию указанного формата.
ЕЫпе () Записывает текущий ограничитель строки в стандартный поток вывода.
ЕЫпе (Boolean) Записывает текстовое представление указанного логического значения, за которым следует текущий символ конца строки, в стандартный поток вывода.
ЕЫпе (Чар) Записывает указанный символ Unicode, сопровождаемый текущим ограничителем строки, значение в стандартный поток вывода.
ЕЫпе (Char []) Записывает указанный массив символов Unicode, за которым следует текущий символ конца строки, в стандартный поток вывода.
ЕЫпе (Десятичный) Записывает текстовое представление указанного десятичного значения с последующим разделителем текущей строки в стандартный поток вывода.
WriteLine (Двухместный) Записывает текстовое представление указанного значения с плавающей запятой двойной точности, за которым следует текущий ограничитель строки, в стандартный поток вывода.
ЕЫпе (Int32) Записывает текстовое представление указанного 32-разрядного целочисленного значения со знаком, за которым следует текущий символ конца строки, в стандартный поток вывода.
ЕЫпе (Int64) Записывает текстовое представление указанного 64-разрядного целого числа со знаком, за которым следует текущий символ конца строки, в стандартный поток вывода.
ЕЫпе (Объект) Записывает текстовое представление указанного объекта, за которым следует текущий ограничитель строки, в стандартный поток вывода.
ЕЫпе (ка) Записывает текстовое представление указанного значения с плавающей запятой одинарной точности, за которым следует текущий ограничитель строки, в стандартный поток вывода.
WriteLine (String) Записывает указанное строковое значение, сопровождаемое текущим ограничителем строки, в стандартный поток вывода.
ЕЫпе (UInt32) Записывает текстовое представление указанного 32-разрядного целого числа без знака, за которым следует текущий разделитель строк, в стандартный поток вывода.
ЕЫпе (UInt64) Записывает текстовое представление указанного 64-разрядного целого числа без знака, после которого следует текущий разделитель строк, в стандартный поток вывода.
WriteLine (Строка, Объект) Записывает текстовое представление указанного объекта, за которым следует текущий ограничитель строки, в стандартный поток вывода с использованием информации указанного формата.
WriteLine (String, Object []) Записывает текстовое представление указанного массива объектов, за которым следует текущий ограничитель строки, в стандартный поток вывода с использованием информации указанного формата.
WriteLine (Char [], Int32, Int32) Записывает указанный подмассив символов Unicode, за которым следует текущий символ конца строки, в стандартный поток вывода.
WriteLine (Строка, Объект, Объект) Записывает текстовое представление указанных объектов, за которым следует текущий ограничитель строки, в стандартный поток вывода с использованием информации указанного формата.
WriteLine (Строка, Объект, Объект, Объект) Записывает текстовое представление указанных объектов, за которым следует текущий ограничитель строки, в стандартный поток вывода с использованием информации указанного формата.
WriteLine (Строка, Объект, Объект, Объект, Объект) Записывает текстовое представление указанных объектов и список параметров переменной длины, за которым следует текущий ограничитель строки, в стандартный поток вывода с использованием информации указанного формата.

Следующий пример демонстрирует чтение из консоли и запись в нее —

пример

Live Demo

open System
let main() =
   Console.Write("What's your name? ")
   let name = Console.ReadLine()
   Console.Write("Hello, {0}\n", name)
   Console.WriteLine(System.String.Format("Big Greetings from {0} and {1}", "TutorialsPoint", "Absoulte Classes"))
   Console.WriteLine(System.String.Format("|{0:yyyy-MMM-dd}|", System.DateTime.Now))
main()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

What's your name? Kabir
Hello, Kabir
Big Greetings from TutorialsPoint and Absoulte Classes
|2015-Jan-05|

Пространство имен System.IO

Пространство имен System.IO содержит множество полезных классов для выполнения базовых операций ввода-вывода.

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

Классы, полезные для работы с файловой системой —

  • Класс System.IO.File используется для создания, добавления и удаления файлов.
  • Класс System.IO.Directory используется для создания, перемещения и удаления каталогов.
  • Класс System.IO.Path выполняет операции со строками, которые представляют пути к файлам.
  • Класс System.IO.FileSystemWatcher позволяет пользователям прослушивать каталог для внесения изменений.

Классы, полезные для работы с потоками (последовательность байтов) —

  • Класс System.IO.StreamReader используется для чтения символов из потока.
  • Класс System.IO.StreamWriter используется для записи символов в поток.
  • Класс System.IO.MemoryStream создает поток байтов в памяти.

В следующей таблице показаны все классы, представленные в пространстве имен, а также краткое описание.

Учебный класс Описание
BinaryReader Читает примитивные типы данных как двоичные значения в определенной кодировке.
BinaryWriter Записывает примитивные типы в двоичном виде в поток и поддерживает запись строк в определенной кодировке.
BufferedStream Добавляет слой буферизации для операций чтения и записи в другом потоке.
каталог Предоставляет статические методы для создания, перемещения и перечисления через каталоги и подкаталоги.
DirectoryInfo Объявляет методы экземпляра для создания, перемещения и перечисления через каталоги и подкаталоги.
DirectoryNotFoundException Исключение, которое выдается, когда не удается найти часть файла или каталога.
DriveInfo Предоставляет доступ к информации на диске.
DriveNotFoundException Исключение, которое выдается при попытке доступа к диску или общедоступному ресурсу, которые недоступны.
EndOfStreamException Исключение, которое выдается при попытке чтения после окончания потока.
ErrorEventArgs Предоставляет данные для события FileSystemWatcher.Error.
файл Предоставляет статические методы для создания, копирования, удаления, перемещения и открытия одного файла и помогает в создании объектов FileStream.
FileFormatException Исключение, которое выдается, когда входной файл или поток данных, который должен соответствовать определенной спецификации формата файла, искажен.
FileInfo Предоставляет свойства и методы экземпляра для создания, копирования, удаления, перемещения и открытия файлов, а также помогает в создании объектов FileStream.
FileLoadException Исключение, которое выдается, когда управляемая сборка найдена, но не может быть загружена.
FileNotFoundException Исключение, которое выдается при попытке доступа к файлу, который не существует на диске, не удалась.
FileStream Предоставляет поток вокруг файла, поддерживая синхронные и асинхронные операции чтения и записи.
FileSystemEventArgs Предоставляет данные для каталога событий — Изменено, Создано, Удалено.
FileSystemInfo Предоставляет базовый класс для объектов FileInfo и DirectoryInfo.
FileSystemWatcher Прослушивает уведомления об изменении файловой системы и вызывает события при изменении каталога или файла в каталоге.
InternalBufferOverflowException Исключение выдается при переполнении внутреннего буфера.
InvalidDataException Исключение, которое выдается, когда поток данных имеет недопустимый формат.
IODescriptionAttribute Устанавливает описание, которое визуальные дизайнеры могут отображать при обращении к событию, расширителю или свойству.
IOException Исключение, которое выдается при возникновении ошибки ввода-вывода.
MemoryStream Создает поток, чьим резервным хранилищем является память.
Дорожка Выполняет операции с экземплярами String, которые содержат информацию о пути к файлу или каталогу. Эти операции выполняются кроссплатформенным способом.
PathTooLongException Исключение, которое выдается, когда путь или имя файла длиннее, чем определенная системой максимальная длина.
PipeException Выдается при возникновении ошибки в именованном канале.
RenamedEventArgs Предоставляет данные для переименованного события.
Поток Предоставляет общий вид последовательности байтов. Это абстрактный класс.
StreamReader Реализует TextReader, который читает символы из байтового потока в определенной кодировке.
StreamWriter Реализует TextWriter для записи символов в поток в определенной кодировке. Чтобы просмотреть исходный код .NET Framework для этого типа, см. Справочный источник.
StringReader Реализует TextReader, который читает из строки.
StringWriter Реализует TextWriter для записи информации в строку. Информация хранится в базовом StringBuilder.
TextReader Представляет читателя, который может читать последовательные серии символов.
TextWriter Представляет писателя, который может написать последовательную серию символов. Этот класс является абстрактным.
UnmanagedMemoryAccessor Предоставляет произвольный доступ к неуправляемым блокам памяти из управляемого кода.
UnmanagedMemoryStream Предоставляет доступ к неуправляемым блокам памяти из управляемого кода.
WindowsRuntimeStorageExtensions Содержит методы расширения для интерфейсов IStorageFile и IStorageFolder в среде выполнения Windows при разработке приложений Магазина Windows.
WindowsRuntimeStreamExtensions Содержит методы расширения для преобразования потоков в среду выполнения Windows и управляемых потоков в приложениях .NET для Магазина Windows.

пример

В следующем примере создается файл с именем test.txt, записывается туда сообщение, считывается текст из файла и выводится его на консоль.

Примечание . Объем кода, необходимый для этого, на удивление меньше!

Live Demo

open System.IO // Name spaces can be opened just as modules
File.WriteAllText("test.txt", "Hello There\n Welcome to:\n Tutorials Point")
let msg = File.ReadAllText("test.txt")
printfn "%s" msg

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Hello There
Welcome to:
Tutorials Point

F # — Дженерики

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

Вы пишете спецификации для класса или метода с параметрами замены для типов данных. Когда компилятор встречает конструктор для класса или вызов функции для метода, он генерирует код для обработки определенного типа данных.

В F # значения функций, методы, свойства и агрегатные типы, такие как классы, записи и различимые объединения, могут быть общими.

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

Синтаксис

Синтаксис для написания универсальной конструкции выглядит следующим образом:

// Explicitly generic function.
let function-name<type-parameters> parameter-list =
   function-body

// Explicitly generic method.
[ static ] member object-identifer.method-name<type-parameters> parameter-list [ return-type ] =
   method-body

// Explicitly generic class, record, interface, structure,
// or discriminated union.
type type-name<type-parameters> type-definition

Примеры

Live Demo

(* Generic Function *)
let printFunc<'T> x y =
   printfn "%A, %A" x y

printFunc<float> 10.0 20.0

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

10.0, 20.0

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

Live Demo

(* Generic Function *)
let printFunction (x: 'a) (y: 'a) =
   printfn "%A %A" x y

printFunction 10.0 20.0

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

10.0 20.0

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

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

Общий класс

Как и универсальные функции, вы также можете писать универсальные классы. Следующий пример демонстрирует это —

Live Demo

type genericClass<'a> (x: 'a) =
   do printfn "%A" x

let gr = new genericClass<string>("zara")
let gs = genericClass( seq { for i in 1 .. 10 -> (i, i*i) } )

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

"zara"
seq [(1, 1); (2, 4); (3, 9); (4, 16); ...]

F # — делегаты

Делегат — это переменная ссылочного типа, которая содержит ссылку на метод. Ссылка может быть изменена во время выполнения. F # делегаты аналогичны указателям на функции в C или C ++.

Объявление делегатов

Объявление делегата определяет методы, на которые может ссылаться делегат. Делегат может ссылаться на метод, имеющий такую ​​же подпись, как и у делегата.

Синтаксис для объявления делегата —

type delegate-typename = delegate of type1 -> type2

Например, рассмотрим делегатов —

// Delegate1 works with tuple arguments.
type Delegate1 = delegate of (int * int) -> int
// Delegate2 works with curried arguments.
type Delegate2 = delegate of int * int -> int

Оба делегата могут использоваться для ссылки на любой метод, который имеет два параметра типа int и возвращает переменную типа int .

В синтаксисе —

  • type1 представляет тип аргумента (ов).

  • type2 представляет тип возвращаемого значения.

type1 представляет тип аргумента (ов).

type2 представляет тип возвращаемого значения.

Пожалуйста, обратите внимание —

  • Типы аргументов автоматически каррируются.

  • Делегаты могут быть присоединены к значениям функций, а также к статическим методам или методам экземпляра.

  • Значения функции F # могут передаваться непосредственно в качестве аргументов для делегирования конструкторов.

  • Для статического метода делегат вызывается с использованием имени класса и метода. Для метода экземпляра используются имя экземпляра объекта и метод.

  • Метод Invoke для типа делегата вызывает инкапсулированную функцию.

  • Кроме того, делегаты могут быть переданы в качестве значений функции, ссылаясь на имя метода Invoke без скобок.

Типы аргументов автоматически каррируются.

Делегаты могут быть присоединены к значениям функций, а также к статическим методам или методам экземпляра.

Значения функции F # могут передаваться непосредственно в качестве аргументов для делегирования конструкторов.

Для статического метода делегат вызывается с использованием имени класса и метода. Для метода экземпляра используются имя экземпляра объекта и метод.

Метод Invoke для типа делегата вызывает инкапсулированную функцию.

Кроме того, делегаты могут быть переданы в качестве значений функции, ссылаясь на имя метода Invoke без скобок.

Следующий пример демонстрирует концепцию —

пример

Live Demo

type Myclass() =
   static member add(a : int, b : int) =
      a + b
   static member sub (a : int) (b : int) =
      a - b
   member x.Add(a : int, b : int) =
      a + b
   member x.Sub(a : int) (b : int) =
      a - b

// Delegate1 works with tuple arguments.
type Delegate1 = delegate of (int * int) -> int
// Delegate2 works with curried arguments.
type Delegate2 = delegate of int * int -> int

let InvokeDelegate1 (dlg : Delegate1) (a : int) (b: int) =
   dlg.Invoke(a, b)
let InvokeDelegate2 (dlg : Delegate2) (a : int) (b: int) =
   dlg.Invoke(a, b)

// For static methods, use the class name, the dot operator, and the
// name of the static method.
let del1 : Delegate1 = new Delegate1( Myclass.add )
let del2 : Delegate2 = new Delegate2( Myclass.sub )

let mc = Myclass()
// For instance methods, use the instance value name, the dot operator, and the instance method name.

let del3 : Delegate1 = new Delegate1( mc.Add )
let del4 : Delegate2 = new Delegate2( mc.Sub )

for (a, b) in [ (400, 200); (100, 45) ] do
   printfn "%d + %d = %d" a b (InvokeDelegate1 del1 a b)
   printfn "%d - %d = %d" a b (InvokeDelegate2 del2 a b)
   printfn "%d + %d = %d" a b (InvokeDelegate1 del3 a b)
   printfn "%d - %d = %d" a b (InvokeDelegate2 del4 a b)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

400 + 200 = 600
400 - 200 = 200
400 + 200 = 600
400 - 200 = 200
100 + 45 = 145
100 - 45 = 55
100 + 45 = 145
100 - 45 = 55

F # — Перечисления

Перечисление — это набор именованных целочисленных констант.

В F # перечисления, также известные как перечисления, являются целочисленными типами, где метки присваиваются подмножеству значений. Вы можете использовать их вместо литералов, чтобы сделать код более читабельным и понятным.

Объявление Перечислений

Общий синтаксис объявления перечисления —

type enum-name =
   | value1 = integer-literal1
   | value2 = integer-literal2
...

Следующий пример демонстрирует использование перечислений —

пример

Live Demo

// Declaration of an enumeration.
type Days =
   | Sun = 0
   | Mon = 1
   | Tues = 2
   | Wed = 3
   | Thurs = 4
   | Fri = 5
   | Sat = 6

// Use of an enumeration.
let weekend1 : Days = Days.Sat
let weekend2 : Days = Days.Sun
let weekDay1 : Days = Days.Mon

printfn "Monday: %A" weekDay1
printfn "Saturday: %A" weekend1
printfn "Sunday: %A" weekend2

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Monday: Mon
Saturday: Sat
Sunday: Sun

F # — Pattern Matching

Сопоставление с образцом позволяет вам «сравнивать данные с логической структурой или структурами, разбивать данные на составные части или извлекать информацию из данных различными способами».

Другими словами, он обеспечивает более гибкий и мощный способ проверки данных в соответствии с рядом условий и выполнения некоторых вычислений на основе выполненного условия.

Концептуально это похоже на серию утверждений if… then.

Синтаксис

В терминах высокого уровня сопоставление с образцом следует этому синтаксису в F # —

match expr with
| pat1 - result1
| pat2 -> result2
| pat3 when expr2 -> result3
| _ -> defaultResult

Куда,

  • Каждый | Символ определяет условие.
  • Символ -> означает «если условие истинно, вернуть это значение …».
  • Символ _ обеспечивает шаблон по умолчанию, что означает, что он соответствует всем другим вещам, таким как подстановочный знак.

Пример 1

В следующем примере вычисляются числа Фибоначчи с использованием синтаксиса сопоставления с образцом —

Live Demo

let rec fib n =
   match n with
   | 0 -> 0
   | 1 -> 1
   | _ -> fib (n - 1) + fib (n - 2)
for i = 1 to 10 do
   printfn "Fibonacci %d: %d" i (fib i)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Fibonacci 1: 1
Fibonacci 2: 1
Fibonacci 3: 2
Fibonacci 4: 3
Fibonacci 5: 5
Fibonacci 6: 8
Fibonacci 7: 13
Fibonacci 8: 21
Fibonacci 9: 34
Fibonacci 10: 55

Вы также можете связать воедино несколько условий, которые возвращают одно и то же значение. Например —

Пример 2

Live Demo

let printSeason month =
   match month with
   | "December" | "January" | "February" -> printfn "Winter"
   | "March" | "April" -> printfn "Spring"
   | "May" | "June" -> printfn "Summer"
   | "July" | "August" -> printfn "Rainy"
   | "September" | "October" | "November" -> printfn "Autumn"
   | _ -> printfn "Season depends on month!"

printSeason "February"
printSeason "April"
printSeason "November"
printSeason "July"

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Winter
Spring
Autumn
Rainy

Функции сопоставления с образцом

F # позволяет писать функции сопоставления с образцом, используя ключевое слово function

Live Demo

let getRate = function
   | "potato" -> 10.00
   | "brinjal" -> 20.50
   | "cauliflower" -> 21.00
   | "cabbage" -> 8.75
   | "carrot" -> 15.00
   | _ -> nan (* nan is a special value meaning "not a number" *)

printfn "%g"(getRate "potato")
printfn "%g"(getRate "brinjal")
printfn "%g"(getRate "cauliflower")
printfn "%g"(getRate "cabbage")
printfn "%g"(getRate "carrot")

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

10
20.5
21
8.75
15

Добавление фильтров или охранников в шаблоны

Вы можете добавить фильтры или защитные элементы в шаблоны, используя ключевое слово when .

Пример 1

Live Demo

let sign = function
   | 0 -> 0
   | x when x < 0 -> -1
   | x when x > 0 -> 1

printfn "%d" (sign -20)
printfn "%d" (sign 20)
printfn "%d" (sign 0)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

-1
1
0

Пример 2

Live Demo

let compareInt x =
   match x with
   | (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2
   | (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
   | (var1, var2) -> printfn "%d equals %d" var1 var2

compareInt (11,25)
compareInt (72, 10)
compareInt (0, 0)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

11 is less than 25
72 is greater than 10
0 equals 0

Сравнение шаблонов с кортежами

В следующем примере демонстрируется сопоставление шаблона с кортежами —

Live Demo

let greeting (name, subject) =
   match (name, subject) with
   | ("Zara", _) -> "Hello, Zara"
   | (name, "English") -> "Hello, " + name + " from the department of English"
   | (name, _) when subject.StartsWith("Comp") -> "Hello, " + name + " from the department of Computer Sc."
   | (_, "Accounts and Finance") -> "Welcome to the department of Accounts and Finance!"
   | _ -> "You are not registered into the system"

printfn "%s" (greeting ("Zara", "English"))
printfn "%s" (greeting ("Raman", "Computer Science"))
printfn "%s" (greeting ("Ravi", "Mathematics"))

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Hello, Zara
Hello, Raman from the department of Computer Sc.
You are not registered into the system

Сопоставление образцов с записями

В следующем примере демонстрируется сопоставление с записями

Live Demo

type Point = { x: float; y: float }
let evaluatePoint (point: Point) =
   match point with
   | { x = 0.0; y = 0.0 } -> printfn "Point is at the origin."
   | { x = xVal; y = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal
   | { x = 0.0; y = yVal } -> printfn "Point is on the y-axis. Value is %f." yVal
   | { x = xVal; y = yVal } -> printfn "Point is at (%f, %f)." xVal yVal

evaluatePoint { x = 0.0; y = 0.0 }
evaluatePoint { x = 10.0; y = 0.0 }
evaluatePoint { x = 0.0; y = 10.0 }
evaluatePoint { x = 10.0; y = 10.0 }

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Point is at the origin.
Point is on the x-axis. Value is 10.000000.
Point is on the y-axis. Value is 10.000000.
Point is at (10.000000, 10.000000).

F # — Обработка исключений

Исключением является проблема, возникающая при выполнении программы. Исключение F # является ответом на исключительное обстоятельство, которое возникает во время работы программы, например, попытка деления на ноль.

Исключения предоставляют способ передачи управления из одной части программы в другую. Обработка исключений в F # обеспечивает следующие конструкции:

сооружать Описание
поднять expr Вызывает данное исключение.
failwith expr Вызывает исключение System.Exception .
попробуй expr с правилами Ловит выражения, соответствующие правилам шаблона.
попробуй expr наконец expr Выполнение выражения finally как при успешном вычислении, так и при возникновении исключения.
| 😕 ArgumentException Правило, соответствующее указанному типу исключения .NET.
| 😕 ArgumentException как е Правило, соответствующее указанному типу исключения .NET, связывающее имя e со значением объекта исключения.
| Ошибка (сообщение) → expr Правило, соответствующее данному несущему данные F # исключение.
| exn → expr Правило, соответствующее любому исключению, связывающее имя exn со значением объекта исключения.
| exn когда expr → expr Правило, соответствующее исключению при заданном условии, связывающее имя exn со значением объекта исключения.

Давайте начнем с основного синтаксиса обработки исключений.

Синтаксис

Основной синтаксис для блока обработки исключений F # —

exception exception-type of argument-type

Куда,

  • Тип исключения — это имя нового типа исключения F #.

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

  • Несколько аргументов могут быть указаны с помощью типа кортежа для типа аргумента.

Тип исключения — это имя нового типа исключения F #.

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

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

Выражение try … with используется для обработки исключений в языке F #.

Синтаксис для попытки … с выражением —

try
   expression1
with
   | pattern1 -> expression2
   | pattern2 -> expression3
...

Выражение try … finally позволяет выполнять код очистки, даже если блок кода вызывает исключение.

Синтаксис для выражения try… finally —

try
   expression1
finally
   expression2

Функция повышения используется, чтобы указать, что произошла ошибка или исключительное условие. Он также фиксирует информацию об ошибке в объекте исключения.

Синтаксис для функции повышения:

raise (expression)

Функция failwith генерирует исключение F #.

Синтаксис функции failwith:

failwith error-message-string

Функция invalidArg генерирует исключение аргумента.

invalidArg parameter-name error-message-string

Пример обработки исключений

Пример 1

Следующая программа показывает базовую обработку исключений с простой попыткой… с блоком —

Live Demo

let divisionprog x y =
   try
      Some (x / y)
   with
      | 😕 System.DivideByZeroException -> printfn "Division by zero!"; None

let result1 = divisionprog 100 0

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Division by zero!

Пример 2

F # предоставляет тип исключения для объявления исключений. Вы можете использовать тип исключения непосредственно в фильтрах в выражении try … with .

Следующий пример демонстрирует это —

Live Demo

exception Error1 of string
// Using a tuple type as the argument type.
exception Error2 of string * int

let myfunction x y =
   try
      if x = y then raise (Error1("Equal Number Error"))
      else raise (Error2("Error Not detected", 100))
   with
      | Error1(str) -> printfn "Error1 %s" str
      | Error2(str, i) -> printfn "Error2 %s %d" str i
myfunction 20 10
myfunction 5 5

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Error2 Error Not detected 100
Error1 Equal Number Error

Пример 3

В следующем примере демонстрируется обработка вложенных исключений —

Live Demo

exception InnerError of string
exception OuterError of string

let func1 x y =
   try
      try
         if x = y then raise (InnerError("inner error"))
         else raise (OuterError("outer error"))
      with
         | InnerError(str) -> printfn "Error:%s" str
   finally
      printfn "From the finally block."

let func2 x y =
   try
      func1 x y
   with
      | OuterError(str) -> printfn "Error: %s" str

func2 100 150
func2 100 100
func2 100 120

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

From the finally block.
Error: outer error
Error:inner error
From the finally block.
From the finally block.
Error: outer error

Пример 4

Следующая функция демонстрирует функцию failwith

Live Demo

let divisionFunc x y =
   if (y = 0) then failwith "Divisor cannot be zero."
   else
      x / y

let trydivisionFunc x y =
   try
      divisionFunc x y
   with
      | Failure(msg) -> printfn "%s" msg; 0

let result1 = trydivisionFunc 100 0
let result2 = trydivisionFunc 100 4
printfn "%A" result1
printfn "%A" result2

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Divisor cannot be zero.
0
25

Пример 5

Функция invalidArg генерирует исключение аргумента. Следующая программа демонстрирует это —

Live Demo

let days = [| "Sunday"; "Monday"; "Tuesday"; "Wednesday"; "Thursday"; "Friday"; "Saturday" |]
let findDay day =
   if (day > 7 || day < 1)
      then invalidArg "day" (sprintf "You have entered %d." day)
   days.[day - 1]

printfn "%s" (findDay 1)
printfn "%s" (findDay 5)
printfn "%s" (findDay 9)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Sunday
Thursday
Unhandled Exception:
System.ArgumentException: You have entered 9.
…

В зависимости от системы также будет отображаться некоторая другая информация о файле и переменной, вызывающей ошибку в системе.

F # — Классы

Классы — это типы, которые представляют объекты, которые могут иметь свойства, методы и события. «Они используются для моделирования действий, процессов и любых концептуальных объектов в приложениях».

Синтаксис

Синтаксис для определения типа класса выглядит следующим образом:

// Class definition:
type [access-modifier] type-name [type-params] [access-modifier] ( parameter-list ) [ as identifier ] =
   [ class ]
      [ inherit base-type-name(base-constructor-args) ]
      [ let-bindings ]
      [ do-bindings ]
      member-list
      ...
   [ end ]

// Mutually recursive class definitions:
type [access-modifier] type-name1 ...
and [access-modifier] type-name2 ...
...

Куда,

  • Имя типа — это любой допустимый идентификатор. Модификатор доступа по умолчанию для этого является публичным .

  • Тип-параметры описывают необязательные параметры универсального типа.

  • Список параметров описывает параметры конструктора. Модификатор доступа по умолчанию для основного конструктора — public .

  • Идентификатор, используемый с необязательным ключевым словом as, задает имя переменной экземпляра или самоидентификатор, который можно использовать в определении типа для ссылки на экземпляр типа.

  • Ключевое слово наследия позволяет вам указать базовый класс для класса.

  • Привязки let позволяют объявлять поля или значения функций, локальные для класса.

  • Раздел do-bindings содержит код, который должен быть выполнен при построении объекта.

  • Список членов состоит из дополнительных конструкторов, объявлений экземпляра и статического метода, объявлений интерфейса, абстрактных привязок, а также объявлений свойств и событий.

  • Ключевые слова class и end , обозначающие начало и конец определения, являются необязательными.

Имя типа — это любой допустимый идентификатор. Модификатор доступа по умолчанию для этого является публичным .

Тип-параметры описывают необязательные параметры универсального типа.

Список параметров описывает параметры конструктора. Модификатор доступа по умолчанию для основного конструктора — public .

Идентификатор, используемый с необязательным ключевым словом as, задает имя переменной экземпляра или самоидентификатор, который можно использовать в определении типа для ссылки на экземпляр типа.

Ключевое слово наследия позволяет вам указать базовый класс для класса.

Привязки let позволяют объявлять поля или значения функций, локальные для класса.

Раздел do-bindings содержит код, который должен быть выполнен при построении объекта.

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

Ключевые слова class и end , обозначающие начало и конец определения, являются необязательными.

Конструктор класса

Конструктор — это код, который создает экземпляр типа класса.

В F # конструкторы работают немного иначе, чем другие языки .Net. В определении класса аргументы первичного конструктора описываются как список параметров.

Тело конструктора состоит из привязок let и do .

Вы можете добавить дополнительные конструкторы, используя новое ключевое слово для добавления члена —

new (argument-list) = constructor-body

Следующий пример иллюстрирует концепцию —

пример

Следующая программа создает класс строки вместе с конструктором, который вычисляет длину строки при создании объекта класса —

Live Demo

type Line = class
   val X1 : float
   val Y1 : float
   val X2 : float
   val Y2 : float

   new (x1, y1, x2, y2) as this =
      { X1 = x1; Y1 = y1; X2 = x2; Y2 = y2;}
      then
         printfn " Creating Line: {(%g, %g), (%g, %g)}\nLength: %g"
            this.X1 this.Y1 this.X2 this.Y2 this.Length

   member x.Length =
      let sqr x = x * x
      sqrt(sqr(x.X1 - x.X2) + sqr(x.Y1 - x.Y2) )
end
let aLine = new Line(1.0, 1.0, 4.0, 5.0)

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Creating Line: {(1, 1), (4, 5)}
Length: 5

Пусть привязки

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

Live Demo

type Greetings(name) as gr =
   let data = name
   do
      gr.PrintMessage()
   member this.PrintMessage() =
      printf "Hello %s\n" data
let gtr = new Greetings("Zara")

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Hello Zara

Обратите внимание на использование самоидентификатора gr для класса Greetings .

F # — Структуры

Структура в F # является типом данных типа значения. Это поможет вам сделать одну переменную, хранить связанные данные различных типов данных. Ключевое слово struct используется для создания структуры.

Синтаксис

Синтаксис для определения структуры выглядит следующим образом:

[ attributes ]
type [accessibility-modifier] type-name =
   struct
      type-definition-elements
   end
// or
[ attributes ]
[<StructAttribute>]
type [accessibility-modifier] type-name =
   type-definition-elements

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

Элементы определения структуры обеспечивают —

  • Объявления и определения членов.
  • Конструкторы и изменяемые и неизменные поля.
  • Члены и реализации интерфейса.

В отличие от классов, структуры не могут наследоваться и не могут содержать привязки let или do. Поскольку структуры не имеют привязок let; Вы должны объявить поля в структурах, используя ключевое слово val .

Когда вы определяете поле и его тип с помощью ключевого слова val , вы не можете инициализировать значение поля, вместо этого они инициализируются нулями или нулями. Таким образом, для структуры, имеющей неявный конструктор, объявления val должны быть аннотированы атрибутом DefaultValue .

пример

Следующая программа создает структуру линии вместе с конструктором. Программа рассчитывает длину строки, используя структуру —

Live Demo

type Line = struct
   val X1 : float
   val Y1 : float
   val X2 : float
   val Y2 : float

   new (x1, y1, x2, y2) =
      {X1 = x1; Y1 = y1; X2 = x2; Y2 = y2;}
end
let calcLength(a : Line)=
   let sqr a = a * a
   sqrt(sqr(a.X1 - a.X2) + sqr(a.Y1 - a.Y2) )

let aLine = new Line(1.0, 1.0, 4.0, 5.0)
let length = calcLength aLine
printfn "Length of the Line: %g " length

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Length of the Line: 5

F # — Перегрузка оператора

Вы можете переопределить или перегрузить большинство встроенных операторов, доступных в F #. Таким образом, программист может использовать операторы с пользовательскими типами.

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

В следующем примере показан оператор + для комплексных чисел —

//overloading + operator
static member (+) (a : Complex, b: Complex) =
Complex(a.x + b.x, a.y + b.y)

Вышеуказанная функция реализует оператор сложения (+) для пользовательского класса Complex. Он добавляет атрибуты двух объектов и возвращает результирующий комплексный объект.

Реализация перегрузки оператора

Следующая программа показывает полную реализацию —

Live Demo

//implementing a complex class with +, and - operators
//overloaded
type Complex(x: float, y : float) =
   member this.x = x
   member this.y = y
   //overloading + operator
   static member (+) (a : Complex, b: Complex) =
      Complex(a.x + b.x, a.y + b.y)

   //overloading - operator
   static member (-) (a : Complex, b: Complex) =
      Complex(a.x - b.x, a.y - b.y)

   // overriding the ToString method
   override this.ToString() =
      this.x.ToString() + " " + this.y.ToString()

//Creating two complex numbers
let c1 = Complex(7.0, 5.0)
let c2 = Complex(4.2, 3.1)

// addition and subtraction using the
//overloaded operators
let c3 = c1 + c2
let c4 = c1 - c2

//printing the complex numbers
printfn "%s" (c1.ToString())
printfn "%s" (c2.ToString())
printfn "%s" (c3.ToString())
printfn "%s" (c4.ToString())

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

7 5
4.2 3.1
11.2 8.1
2.8 1.9

F # — Наследование

Одним из наиболее важных понятий в объектно-ориентированном программировании является наследование. Наследование позволяет нам определять класс в терминах другого класса, что облегчает создание и поддержку приложения. Это также дает возможность повторно использовать функциональность кода и быстрое время реализации.

При создании класса, вместо того, чтобы писать совершенно новые члены-данные и функции-члены, программист может указать, что новый класс должен наследовать члены существующего класса. Этот существующий класс называется базовым классом, а новый класс называется производным классом.

Идея наследования реализует отношения IS-A. Например, млекопитающее — это животное, собака — это млекопитающее, следовательно, собака — это тоже животное, и так далее.

Базовый класс и подкласс

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

Подкласс определяется с использованием ключевого слова наследия, как показано ниже —

type MyDerived(...) =
   inherit MyBase(...)

В F # класс может иметь не более одного прямого базового класса. Если вы не укажете базовый класс с помощью ключевого слова inherit, класс неявно наследуется от Object.

Пожалуйста, обратите внимание —

  • Методы и члены базового класса доступны пользователям производного класса, как и прямые члены производного класса.

  • Пусть привязки и параметры конструктора являются частными для класса и, следовательно, не могут быть доступны из производных классов.

  • Ключевое слово base относится к экземпляру базового класса. Он используется как самоидентификатор.

Методы и члены базового класса доступны пользователям производного класса, как и прямые члены производного класса.

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

Ключевое слово base относится к экземпляру базового класса. Он используется как самоидентификатор.

пример

Live Demo

type Person(name) =
   member x.Name = name
   member x.Greet() = printfn "Hi, I'm %s" x.Name

type Student(name, studentID : int) =
   inherit Person(name)
   let mutable _GPA = 0.0
   member x.StudentID = studentID
   member x.GPA
      with get() = _GPA
      and set value = _GPA <- value

type Teacher(name, expertise : string) =
   inherit Person(name)

   let mutable _salary = 0.0
   member x.Salary
      with get() = _salary
      and set value = _salary <- value
   member x.Expertise = expertise

//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")

p.Greet()
st.Greet()
tr.Greet()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam

Переопределяющие методы

Вы можете переопределить поведение по умолчанию метода базового класса и реализовать его по-разному в подклассе или производном классе.

Методы в F # не могут быть переопределены по умолчанию.

Чтобы переопределить методы в производном классе, вы должны объявить ваш метод как перезаписываемый с использованием абстрактных и ключевых слов по умолчанию следующим образом:

type Person(name) =
   member x.Name = name
   abstract Greet : unit -> unit
   default x.Greet() = printfn "Hi, I'm %s" x.Name

Теперь метод Greet класса Person может быть переопределен в производных классах. Следующий пример демонстрирует это —

пример

Live Demo

type Person(name) =
   member x.Name = name
   abstract Greet : unit -> unit
   default x.Greet() = printfn "Hi, I'm %s" x.Name

type Student(name, studentID : int) =
   inherit Person(name)

   let mutable _GPA = 0.0

   member x.StudentID = studentID
   member x.GPA
      with get() = _GPA
      and set value = _GPA <- value
   override x.Greet() = printfn "Student %s" x.Name

type Teacher(name, expertise : string) =
   inherit Person(name)
   let mutable _salary = 0.0
   member x.Salary
      with get() = _salary
      and set value = _salary <- value

   member x.Expertise = expertise
   override x.Greet() = printfn "Teacher %s." x.Name

//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")

//default Greet
p.Greet()

//Overriden Greet
st.Greet()
tr.Greet()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Hi, I'm Mohan
Student Zara
Teacher Mariam.

Абстрактный класс

Временами вам необходимо предоставить неполную реализацию объекта, которая не должна быть реализована в реальности. Позже, некоторый другой программист должен создать подклассы абстрактного класса для полной реализации.

Например, класс Person не понадобится в Системе управления школой. Тем не менее, потребуется класс ученика или учителя. В таких случаях вы можете объявить класс Person как абстрактный класс.

Атрибут AbstractClass сообщает компилятору, что класс имеет некоторые абстрактные члены.

Вы не можете создать экземпляр абстрактного класса, потому что этот класс не полностью реализован.

Следующий пример демонстрирует это —

пример

Live Demo

[<AbstractClass>]
type Person(name) =
   member x.Name = name
   abstract Greet : unit -> unit

type Student(name, studentID : int) =
   inherit Person(name)
   let mutable _GPA = 0.0
   member x.StudentID = studentID
   member x.GPA
      with get() = _GPA
      and set value = _GPA <- value
   override x.Greet() = printfn "Student %s" x.Name

type Teacher(name, expertise : string) =
   inherit Person(name)
   let mutable _salary = 0.0
   member x.Salary
      with get() = _salary
      and set value = _salary <- value
   member x.Expertise = expertise
   override x.Greet() = printfn "Teacher %s." x.Name

let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")

//Overriden Greet
st.Greet()
tr.Greet()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Student Zara
Teacher Mariam.

F # — Интерфейсы

Интерфейсы предоставляют абстрактный способ написания деталей реализации класса. Это шаблон, который объявляет методы, которые класс должен реализовать и публично представить.

Синтаксис

Интерфейс определяет наборы связанных членов, которые реализуют другие классы. Он имеет следующий синтаксис —

// Interface declaration:
[ attributes ]
type interface-name =
   [ interface ]
      [ inherit base-interface-name ...]
      abstract member1 : [ argument-types1 -> ] return-type1
      abstract member2 : [ argument-types2 -> ] return-type2
      ...
   [ end ]
	
// Implementing, inside a class type definition:
interface interface-name with
   member self-identifier.member1 argument-list = method-body1
   member self-identifier.member2 argument-list = method-body2
// Implementing, by using an object expression:
[ attributes ]
let class-name (argument-list) =
   { new interface-name with
      member self-identifier.member1 argument-list = method-body1
      member self-identifier.member2 argument-list = method-body2
      [ base-interface-definitions ]
   }
member-list

Пожалуйста, обратите внимание —

  • В объявлении интерфейса члены не реализованы.

  • Члены являются абстрактными, объявленными абстрактным ключевым словом. Однако вы можете предоставить реализацию по умолчанию, используя ключевое слово по умолчанию .

  • Вы можете реализовать интерфейсы либо с помощью выражений объектов, либо с помощью типов классов.

  • В реализации класса или объекта необходимо предоставить тела методов для абстрактных методов интерфейса.

  • Ключевые слова interface и end, которые отмечают начало и конец определения, являются необязательными.

В объявлении интерфейса члены не реализованы.

Члены являются абстрактными, объявленными абстрактным ключевым словом. Однако вы можете предоставить реализацию по умолчанию, используя ключевое слово по умолчанию .

Вы можете реализовать интерфейсы либо с помощью выражений объектов, либо с помощью типов классов.

В реализации класса или объекта необходимо предоставить тела методов для абстрактных методов интерфейса.

Ключевые слова interface и end, которые отмечают начало и конец определения, являются необязательными.

Например,

type IPerson =
   abstract Name : string
   abstract Enter : unit -> unit
   abstract Leave : unit -> unit

Вызов методов интерфейса

Методы интерфейса вызываются через интерфейс, а не через экземпляр класса или интерфейса реализации типа. Чтобы вызвать метод интерфейса, вы приведете тип интерфейса к типу, используя оператор :> (оператор upcast).

Например,

(s :> IPerson).Enter()
(s :> IPerson).Leave()

Следующий пример иллюстрирует концепцию —

пример

Live Demo

type IPerson =
   abstract Name : string
   abstract Enter : unit -> unit
   abstract Leave : unit -> unit

type Student(name : string, id : int) =
   member this.ID = id
   interface IPerson with
      member this.Name = name
      member this.Enter() = printfn "Student entering premises!"
      member this.Leave() = printfn "Student leaving premises!"

type StuffMember(name : string, id : int, salary : float) =
   let mutable _salary = salary

   member this.Salary
      with get() = _salary
      and set(value) = _salary <- value

   interface IPerson with
      member this.Name = name
      member this.Enter() = printfn "Stuff member entering premises!"
      member this.Leave() = printfn "Stuff member leaving premises!"

let s = new Student("Zara", 1234)
let st = new StuffMember("Rohit", 34, 50000.0)

(s :> IPerson).Enter()
(s :> IPerson).Leave()
(st :> IPerson).Enter()
(st :> IPerson).Leave()

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Student entering premises!
Student leaving premises!
Stuff member entering premises!
Stuff member leaving premises!

Наследование интерфейса

Интерфейсы могут наследоваться от одного или нескольких базовых интерфейсов.

В следующем примере показана концепция —

Live Demo

type Interface1 =
   abstract member doubleIt: int -> int

type Interface2 =
   abstract member tripleIt: int -> int

type Interface3 =
   inherit Interface1
   inherit Interface2
   abstract member printIt: int -> string

type multiplierClass() =
   interface Interface3 with
      member this.doubleIt(a) = 2 * a
      member this.tripleIt(a) = 3 * a
      member this.printIt(a) = a.ToString()

let ml = multiplierClass()
printfn "%d" ((ml:>Interface3).doubleIt(5))
printfn "%d" ((ml:>Interface3).tripleIt(5))
printfn "%s" ((ml:>Interface3).printIt(5))

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

10
15
5

F # — События

События позволяют классам отправлять и получать сообщения между собой.

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

Объекты общаются друг с другом посредством синхронной передачи сообщений.

События привязаны к другим функциям; объекты регистрируют функции обратного вызова для события, и эти обратные вызовы выполняются, когда (и если) событие запускается каким-либо объектом.

Класс события и модуль события

Класс Control.Event <‘T> помогает в создании наблюдаемого объекта или события.

У него есть следующие члены экземпляра для работы с событиями —

член Описание
Публиковать Публикует наблюдение как первоклассное значение.
Спусковой крючок Запускает наблюдение с использованием заданных параметров.

Модуль Control.Event предоставляет функции для управления потоками событий —

Значение Описание
добавить: (‘T → единица) → Событие <‘ Del, ‘T> → единица Запускает данную функцию каждый раз, когда происходит указанное событие.
выберите: (опция ‘T →’ U) → IEvent <‘Del,’ T> → IEvent <‘U> Возвращает новое событие, которое запускается при выборе сообщений из исходного события. Функция выбора переводит исходное сообщение в необязательное новое сообщение.
фильтр: (‘T → bool) → IEvent <‘ Del, ‘T> → IEvent <‘ T> Возвращает новое событие, которое прослушивает исходное событие и запускает результирующее событие, только когда аргумент события передает заданную функцию.
карта: (‘T →’ U) → IEvent <‘Del,’ T> → IEvent <‘U> Возвращает новое событие, которое передает значения, преобразованные данной функцией.
объединить: IEvent <‘Del1,’ T> → IEvent <‘Del2,’ T> → IEvent <‘T> Запускает выходное событие при срабатывании любого из входных событий.
попарно: IEvent <‘Del,’ T> → IEvent <‘T *’ T> Возвращает новое событие, которое срабатывает при втором и последующем срабатывании входного события. N-й триггер входного события передает аргументы от N-1-го и N-го триггеров в виде пары. Аргумент, переданный в N-1-й запуск, удерживается в скрытом внутреннем состоянии до тех пор, пока не произойдет N-й запуск.
раздел: (‘T → bool) → IEvent <‘ Del, ‘T> → IEvent <‘ T> * IEvent <‘T> Возвращает новое событие, которое прослушивает исходное событие и запускает первое результирующее событие, если применение предиката к аргументам события вернуло true, и второе событие, если оно вернуло false.
сканирование: (‘U →’ T → ‘U) →’ U → IEvent <‘Del,’ T> → IEvent <‘U> Возвращает новое событие, состоящее из результатов применения данной функции накопления к последовательным значениям, сработавшим во входном событии. Элемент внутреннего состояния записывает текущее значение параметра состояния. Внутреннее состояние не блокируется во время выполнения функции накопления, поэтому следует позаботиться о том, чтобы вход IEvent не запускался несколькими потоками одновременно.
split: (‘T → Choice <‘ U1, ‘U2>) → IEvent <‘ Del, ‘T> → IEvent <‘ U1> * IEvent <‘U2> Возвращает новое событие, которое прослушивает исходное событие и запускает первое результирующее событие, если приложение функции к аргументам события вернуло Choice1Of2, и второе событие, если оно возвращает Choice2Of2.

Создание событий

События создаются и используются через класс Event . Конструктор Event используется для создания события.

пример

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;
   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value

После этого вам нужно выставить поле nameChanged как открытый член, чтобы слушатели могли подключиться к событию, для которого вы используете свойство Publish события —

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = _name <- value
      nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = _shift <- value
   shiftChanged.Trigger() (* invokes event handler *)

Затем вы добавляете обратные вызовы к обработчикам событий. Каждый обработчик событий имеет тип IEvent <‘T>, который предоставляет несколько методов:

метод Описание
val Добавить: event 🙁 ‘T → unit) → unit Подключает функцию слушателя к событию. Слушатель будет вызван при возникновении события.
val AddHandler: ‘del → unit Соединяет объект делегата обработчика с событием. Обработчик может быть позже удален с помощью RemoveHandler. Слушатель будет вызван при возникновении события.
val RemoveHandler: ‘del → unit Удаляет делегат слушателя из хранилища слушателей событий.

В следующем разделе приведен полный пример.

пример

Следующий пример демонстрирует концепцию и методы, обсужденные выше —

Live Demo

type Worker(name : string, shift : string) =
   let mutable _name = name;
   let mutable _shift = shift;

   let nameChanged = new Event<unit>() (* creates event *)
   let shiftChanged = new Event<unit>() (* creates event *)

   member this.NameChanged = nameChanged.Publish (* exposed event handler *)
   member this.ShiftChanged = shiftChanged.Publish (* exposed event handler *)

   member this.Name
      with get() = _name
      and set(value) = 
         _name <- value
         nameChanged.Trigger() (* invokes event handler *)

   member this.Shift
      with get() = _shift
      and set(value) = 
         _shift <- value
         shiftChanged.Trigger() (* invokes event handler *)

let wk = new Worker("Wilson", "Evening")
wk.NameChanged.Add(fun () -> printfn "Worker changed name! New name: %s" wk.Name)
wk.Name <- "William"
wk.NameChanged.Add(fun () -> printfn "-- Another handler attached to NameChanged!")
wk.Name <- "Bill"

wk.ShiftChanged.Add(fun () -> printfn "Worker changed shift! New shift: %s" wk.Shift)
wk.Shift <- "Morning"
wk.ShiftChanged.Add(fun () -> printfn "-- Another handler attached to ShiftChanged!")
wk.Shift <- "Night"

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

Worker changed name! New name: William
Worker changed name! New name: Bill
-- Another handler attached to NameChanged!
Worker changed shift! New shift: Morning
Worker changed shift! New shift: Night
-- Another handler attached to ShiftChanged!

F # — Модули

Согласно библиотеке MSDN, модуль F # представляет собой группу конструкций кода F #, таких как типы, значения, значения функций и код в привязках do. Он реализован как класс среды CLR, в котором есть только статические члены.

В зависимости от ситуации, если весь файл включен в модуль, существует два типа объявлений модуля:

  • Объявление модуля верхнего уровня
  • Объявление локального модуля

В декларации модуля верхнего уровня весь файл включен в модуль. В этом случае первое объявление в файле — это объявление модуля. Вам не нужно вставлять объявления в модуль верхнего уровня.

В объявлении локального модуля только объявления, которые имеют отступ под этим объявлением модуля, являются частью модуля.

Синтаксис

Синтаксис для объявления модуля выглядит следующим образом:

// Top-level module declaration.
module [accessibility-modifier] [qualified-namespace.]module-name
   declarations
// Local module declaration.
module [accessibility-modifier] module-name =
   declarations

Обратите внимание, что модификатор accessibility может быть одним из следующих — публичный, приватный, внутренний. По умолчанию это общедоступный .

Следующие примеры продемонстрируют концепции —

Пример 1

Файл модуля Arithmetic.fs —

module Arithmetic
let add x y =
   x + y

let sub x y =
   x - y
	
let mult x y =
   x * y
	
let div x y =
   x / y

Файл программы main.fs —

// Fully qualify the function name.
open Arithmetic
let addRes = Arithmetic.add 25 9
let subRes = Arithmetic.sub 25 9
let multRes = Arithmetic.mult 25 9
let divRes = Arithmetic.div 25 9

printfn "%d" addRes
printfn "%d" subRes
printfn "%d" multRes
printfn "%d" divRes

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

34
16
225
2
110
90
1000
10

Пример 2

Live Demo

// Module1
module module1 =
   // Indent all program elements within modules that are declared with an equal sign.
   let value1 = 100
   let module1Function x =
      x + value1

// Module2
module module2 =
   let value2 = 200

   // Use a qualified name to access the function.
   // from module1.
   let module2Function x =
      x + (module1.module1Function value2)

let result = module1.module1Function 25
printfn "%d" result

let result2 = module2.module2Function 25
printfn "%d" result2

Когда вы компилируете и запускаете программу, она выдает следующий вывод:

125
325

F # — Пространства имен

Пространство имен предназначено для обеспечения способа отделить один набор имен от другого. Имена классов, объявленные в одном пространстве имен, не будут конфликтовать с теми же именами классов, объявленными в другом.

В соответствии с библиотекой MSDN, пространство имен позволяет вам организовать код в области связанных функций, позволяя вам присоединить имя к группе элементов программы.

Объявление пространства имен

Чтобы организовать ваш код в пространстве имен, вы должны объявить пространство имен как первое объявление в файле. Содержимое всего файла затем становится частью пространства имен.

namespace [parent-namespaces.]identifier

Следующий пример иллюстрирует концепцию —

пример

Live Demo

namespace testing

module testmodule1 =
   let testFunction x y =
      printfn "Values from Module1: %A %A" x y
module testmodule2 =
   let testFunction x y =
      printfn "Values from Module2: %A %A" x y

module usermodule =
   do
      testmodule1.testFunction ( "one", "two", "three" ) 150
      testmodule2.testFunction (seq { for i in 1 .. 10 do yield i * i }) 200

Когда вы компилируете и запускаете программу, она выдает следующий вывод: