ݺߣ

ݺߣShare a Scribd company logo
Андрей Голованов, ФогСофт
IT-Десант, 18.04.2013
 Read – Evaluate – Print - Loop
 В Emacs используется интерпретатор
NJ/SML
 Статическая и динамическая среда
выполнения
 Рестарт для зачистки данных в среде
val x = e;
 Синтаксис:
◦ Ключевые слова val = ;
◦ Переменная x
◦ Выражение e
 Поддерживаются вложенные выражения
val z = (x + y) + (y + 2);
 Синтаксис (как записывается)
 Правила проверки типов
◦ Определение типа или ошибка
◦ Примеры типов: int bool unit
 Правила вычисления выражения
(применяются после успешной проверки
типа)
◦ Возвращается значение или exception или
бесконечный цикл
 Демо...
 val a = 1
val b = a (* b присваивается 1 *)
val a = 2
 Не важно что будет дальше со значением a
 Переменной нельзя присвоить значение
повторно, его можно только затенить
 Синтаксис:
◦ e1 + e2 где e1 и e2 это выражения
 Проверка типа:
◦ Если e1 и e2 имеют тип int,
то e1 + e2 тоже будет иметь тип int
 Вычисление выражения:
◦ Если e1 вычисляется в v1 и e2 вычисляется в v2,
то e1 + e2 рассчитывается как сложение v1 и v2.
 Значение – это выражение, которое не
требует вычислений
◦ 8+9 - это не значение
 Любое значение – это выражение
 Не все выражения являются значениями
 Каждое значение «вычисляется в само в
себя» без
• Примеры:
◦ 34, 17, 42 имеет тип int
◦ true, false имеет тип bool
◦ () имеет тип unit
 Синтаксис: (e1, e2, … en)
 Проверка типов: если e1 – имеет тип t1, …
en – tn, то выражение имеет тип t1 *…* tn
 Вычисление: e1 – v1, … en – vn, то результат
(v1, … , vn)
 Синтаксис: #1 e, #2 e, …
 Проверка типов: если e имеет тип t1*…*tn,
то #1 e имеет тип t1, …
 Вычисление: возвращается
соответствующий элемент кортежа
 Допустимы вложенные кортежи
val x1 = ((1,2), (3, (4,4)))
 Построение списков
◦ [] – пустой список
◦ [v1, v2, …, vN] – список
◦ e1::e2 – добавление элемента e1 в список e2
◦ e1@e2 – слияние списков e1 и e2
 Проверка типов
◦ Список содержит элементы одного типа. Пример
int list, bool list, int list list
 Вспомогательные функции
◦ null e, hd e, tl e, length e …
 В сравнении с методом из ООП языков
(Java, C#)
◦ Нет ключевого слова this
◦ Нет return инструкции
◦ Часто в ФЯ применяются рекурсивные вызовы,
например для обхода элементов коллекции
 Синтаксис: fun x0 (x1 : t1, … , xn : tn) = e
 Вычисление: функция – это значение!
 Добавляется x0 в динамическую среду
выполнения
 Проверка типов: значение функции
определяется автоматически через
выведение типов
 Объявляется переменная x0: (t1*t2…*tn)->t
 Синтаксис: e0 (e1, …, en)
 Проверка типов:
– e0 имеет тип (t1 * … * tn) -> t
 – e1 - t1, …, en - tn
 e0 (e1, … , en) имеет тип t
 Вычисляется e0 для fun x0 (x1 : t1, … , xn :
tn) = e
1. Вычисляются значения аргументов v1, …, vn
2. Результат вычисления e. Динамическая среда
расширена значениями x1 : v1, …, xn : vn, а
также есть x0 – для рекурсивных вызовов
десант презентация
 Синтаксис
◦ Let b1 b2 … bn in e end
bi – это объявление переменной, может
присваиваться выражение, объявляться функция
 Проверка типов
◦ Тип всего выражения определяется типом e
 Область видимости (scope)
 Реиспользование кода (уменьшение багов,
простота разработки, но тяжело вносить
изменения в реиспользуемый код)
 Рекурсивно заданная функция в своем
определении содержит себя
 Рекурсия заменяет циклы в языке ML
 Хвостовая рекурсия – дешевый вызов
рекурсии (пример расчета факториала с
простой и хвостовой рекурсией)
◦ Применение переменной аккумулятора
 t option – тип для любого типа t
 Типы options
◦ NONE имеет тип ‘a option
◦ SOME e имеет тип t option, если e имеет тип t
 Работа с options
◦ isSome тип ‘a option -> bool (false если
NONE)
◦ valOf тип ‘a option -> ‘a (исключение, если
NONE)
 Не возможно выполнять операцию
присвоения к переменным, частям
кортежей, элементам списка
 Aliasing – доступ к одному и тому же
объекту, используя разные переменные.
 Имея 2 функции sort_pair1 и sort_pair2, не
возможно отличить возвращается ли копия
кортежа или alias, в случае выполнения
условия if
fun sort_pair1 (pair : int * int) =
if #1 pair < #2 pair
then pair
else (#2 pair, #1 pair)
fun sort_pair2 (pair : int * int) =
if #1 pair < #2 pair
then (#1 pair, #2 pair)
else (#2 pair, #1 pair)
 Каковы преимущества?
◦ Нет возможности отличить используется ли alias
для объекта или его копия
◦ Нет необходимости думать об использовании
alias. Фокусируемся на других вещах
◦ Можно смело использовать alias, не опасаясь
возможности изменения передаваемого объекта
 Эта особенность применяется в
параллельных вычислениях
 Пример из Java. В Java поддерживается
изменение значения созданных
переменных
 Контейнер с именованными полями
 Синтаксис: {f1=e1, … , fn=en}, доступ к
полю #f1 {record}, f1 – имя поля.
 Кортежи – это синтаксический сахар для
записей вида {1=e1, 2=e2, …, n=en}.
Кортеж (e1, e2, … en), доступ #1 (tuple).
 Разобрали объявление переменных,
функций
 Пример
datatype mytype = TwoInts of int * int
| Str of string
| Pizza
 создали новый тип mytype. Тип имеет 3
конструктора TwoInts, Str и Pizza
 Создаем конструкторы, которые
производят значения нового типа
 Для определения какой конструктор
использован для данного экземпляра типа
используются case выражения
 Демо с арифметическими выражениями
 Pattern-matching (англ.)
 Используется при объявлении переменной
вместо указания имени переменной
val p = e
 Используется при объявлении функции
fun f p = e
 Каждая функция принимает только один
аргумент
 Пример с суммированием элементов
кортежа
 Можно указать в конструкторе datatype
использование любого типа
 демо с option и бинарным деревом,
суммирование узлов и листьев
 Объявление: exception <name> of t
 Вызов: raise <name> <значение>
 Обработка: e1 handle <name>
<параметры> => e2
 Функции первого класса – могут
использоваться как значения.
 Функции высшего порядка - могут
принимать другие функции в качестве
параметра.
 Пример f(f(f...f(x))) n раз (n_times)
 Разбор типа: fn : ('a -> 'a) * int * 'a -> 'a
 У анонимной функции нет имени, поэтому
еѐ нельзя вызывать рекурсивно
 fn args => e
 Пример, double_n_times
 Область видимости (англ. scope) – это
контекст выполнения программы, где по
имени можно обращаться к переменным
или функциям.
 Область видимости в блоке, в функции, в
let-выражении, глобальный, лексический
 Lexical scope. Не важно где вызывают
функцию, важно где еѐ объявили
 Значение функции состоит из двух частей:
◦ Код функции
◦ Среда, которая была на момент определения функции
 Эта пара значений называет замыканием
функции
 Доступ к этим свойствам значения функции
невозможен в коде
 При вызове функции вычисляется код в рамках
среды (которая дополняется аргументами
функции)
 Пример работы lexical scope.
 Тело функции не вычисляется пока функция
не будет вызвана
 Тело функции вычисляется каждый раз,
когда функция вызывается
 Выражение в определении переменной
вызывается один раз и вычисляется, когда
переменная объявляется.
 Основные операции со списками filter, map,
fold: f(f(f(acc, x1), x2), x3)
 Демо с реализацией и использованием
операций.
 Идиома – это элементарная конструкция
типичная для одного или нескольких
языков программирования в нашем случае
для функциональных языков
 Комбинирование функций (композиция)
 Currying
 Callback – подпись на события и обратный
вызов функций.
 SML использует жадную стратегию для
вычислений
fun f(x:int):bool = true;
fun arg () : int = 3;
f(arg()) (* вызовет метод arg, хотя параметр x
не используется *)
 Отложенные вычисления реализуются с
помощью обертки выражения анонимной
функцией (thunk).
 Статическая типизация – контроль за
типами при компиляции до запуска
программы (Pascal, C++, Java, C#)
 Динамическая типизация – контроль типов
во время выполнения программы (PHP,
Python, Ruby, Perl, Javascript)
 ML – статически типизированный
 ML – язык с неявным определением типов.
 Применяется выведение типов
 Выведение типов – процесс определения
типов выражений, переменных, который
приведет к успешной проверке типов.
 Задача выведения типов
◦ Установить типы переменных в коде.
◦ Удостовериться, что все выражения проходят
проверку типов.
 Неизменяемость значений переменных
 Использование функций в роли аргумента
 Рекурсивные типы данных
 Использование рекурсии в функции для
обхода элементов списка
 Использование сопоставления шаблонов
 Ленивая инициализация
 Функции первого порядка, closures в C#,
Java, Javascript
 Анонимные функции в C#, Javascript
 LINQ в C#
 Callback в C#, Javascript
 Полиморфизм типов (generics)
 Неявная типизация, выведение типов в C# и
Javascript
 Типы и операции, матрица
 Разрешение задачи на ООЯП через
выделение типов и интерфейса
 Решение на ФЯП через определение
datatype и выделения операций с
перечислением пар и pattern-matching’ом
eval toString hasZero
Int
Add
Negate
• В ФЯП декомпозиция по операциям
• В ООП декомпозиция по сущностям,
выполняющим действия
 задачи оптимизации,
 генетическое программировние,
 сложные доказательства
 эвристические задачи (например, шахматы)
 современные языки программирования
включают в себя различные парадигмы
программирования (multi-paradigm) в том
числе многие идиомы из ФЯ (например, C#,
Javascript).
 Списки – это тоже datatypes
 Вложенные шаблоны, пример zip3,
nondecreasing, multsign sgn = P | N | Z
 Синонимы типов
 Модули и сигнатуры
 Описание библиотечных типов языка SML
http://www.standardml.org/Basis/overview.h
tml
десант презентация

More Related Content

десант презентация

  • 2.  Read – Evaluate – Print - Loop  В Emacs используется интерпретатор NJ/SML  Статическая и динамическая среда выполнения  Рестарт для зачистки данных в среде
  • 3. val x = e;  Синтаксис: ◦ Ключевые слова val = ; ◦ Переменная x ◦ Выражение e  Поддерживаются вложенные выражения val z = (x + y) + (y + 2);
  • 4.  Синтаксис (как записывается)  Правила проверки типов ◦ Определение типа или ошибка ◦ Примеры типов: int bool unit  Правила вычисления выражения (применяются после успешной проверки типа) ◦ Возвращается значение или exception или бесконечный цикл  Демо...
  • 5.  val a = 1 val b = a (* b присваивается 1 *) val a = 2  Не важно что будет дальше со значением a  Переменной нельзя присвоить значение повторно, его можно только затенить
  • 6.  Синтаксис: ◦ e1 + e2 где e1 и e2 это выражения  Проверка типа: ◦ Если e1 и e2 имеют тип int, то e1 + e2 тоже будет иметь тип int  Вычисление выражения: ◦ Если e1 вычисляется в v1 и e2 вычисляется в v2, то e1 + e2 рассчитывается как сложение v1 и v2.
  • 7.  Значение – это выражение, которое не требует вычислений ◦ 8+9 - это не значение  Любое значение – это выражение  Не все выражения являются значениями  Каждое значение «вычисляется в само в себя» без • Примеры: ◦ 34, 17, 42 имеет тип int ◦ true, false имеет тип bool ◦ () имеет тип unit
  • 8.  Синтаксис: (e1, e2, … en)  Проверка типов: если e1 – имеет тип t1, … en – tn, то выражение имеет тип t1 *…* tn  Вычисление: e1 – v1, … en – vn, то результат (v1, … , vn)
  • 9.  Синтаксис: #1 e, #2 e, …  Проверка типов: если e имеет тип t1*…*tn, то #1 e имеет тип t1, …  Вычисление: возвращается соответствующий элемент кортежа  Допустимы вложенные кортежи val x1 = ((1,2), (3, (4,4)))
  • 10.  Построение списков ◦ [] – пустой список ◦ [v1, v2, …, vN] – список ◦ e1::e2 – добавление элемента e1 в список e2 ◦ e1@e2 – слияние списков e1 и e2  Проверка типов ◦ Список содержит элементы одного типа. Пример int list, bool list, int list list  Вспомогательные функции ◦ null e, hd e, tl e, length e …
  • 11.  В сравнении с методом из ООП языков (Java, C#) ◦ Нет ключевого слова this ◦ Нет return инструкции ◦ Часто в ФЯ применяются рекурсивные вызовы, например для обхода элементов коллекции
  • 12.  Синтаксис: fun x0 (x1 : t1, … , xn : tn) = e  Вычисление: функция – это значение!  Добавляется x0 в динамическую среду выполнения  Проверка типов: значение функции определяется автоматически через выведение типов  Объявляется переменная x0: (t1*t2…*tn)->t
  • 13.  Синтаксис: e0 (e1, …, en)  Проверка типов: – e0 имеет тип (t1 * … * tn) -> t  – e1 - t1, …, en - tn  e0 (e1, … , en) имеет тип t  Вычисляется e0 для fun x0 (x1 : t1, … , xn : tn) = e 1. Вычисляются значения аргументов v1, …, vn 2. Результат вычисления e. Динамическая среда расширена значениями x1 : v1, …, xn : vn, а также есть x0 – для рекурсивных вызовов
  • 15.  Синтаксис ◦ Let b1 b2 … bn in e end bi – это объявление переменной, может присваиваться выражение, объявляться функция  Проверка типов ◦ Тип всего выражения определяется типом e  Область видимости (scope)  Реиспользование кода (уменьшение багов, простота разработки, но тяжело вносить изменения в реиспользуемый код)
  • 16.  Рекурсивно заданная функция в своем определении содержит себя  Рекурсия заменяет циклы в языке ML  Хвостовая рекурсия – дешевый вызов рекурсии (пример расчета факториала с простой и хвостовой рекурсией) ◦ Применение переменной аккумулятора
  • 17.  t option – тип для любого типа t  Типы options ◦ NONE имеет тип ‘a option ◦ SOME e имеет тип t option, если e имеет тип t  Работа с options ◦ isSome тип ‘a option -> bool (false если NONE) ◦ valOf тип ‘a option -> ‘a (исключение, если NONE)
  • 18.  Не возможно выполнять операцию присвоения к переменным, частям кортежей, элементам списка  Aliasing – доступ к одному и тому же объекту, используя разные переменные.  Имея 2 функции sort_pair1 и sort_pair2, не возможно отличить возвращается ли копия кортежа или alias, в случае выполнения условия if
  • 19. fun sort_pair1 (pair : int * int) = if #1 pair < #2 pair then pair else (#2 pair, #1 pair) fun sort_pair2 (pair : int * int) = if #1 pair < #2 pair then (#1 pair, #2 pair) else (#2 pair, #1 pair)
  • 20.  Каковы преимущества? ◦ Нет возможности отличить используется ли alias для объекта или его копия ◦ Нет необходимости думать об использовании alias. Фокусируемся на других вещах ◦ Можно смело использовать alias, не опасаясь возможности изменения передаваемого объекта  Эта особенность применяется в параллельных вычислениях  Пример из Java. В Java поддерживается изменение значения созданных переменных
  • 21.  Контейнер с именованными полями  Синтаксис: {f1=e1, … , fn=en}, доступ к полю #f1 {record}, f1 – имя поля.  Кортежи – это синтаксический сахар для записей вида {1=e1, 2=e2, …, n=en}. Кортеж (e1, e2, … en), доступ #1 (tuple).
  • 22.  Разобрали объявление переменных, функций  Пример datatype mytype = TwoInts of int * int | Str of string | Pizza  создали новый тип mytype. Тип имеет 3 конструктора TwoInts, Str и Pizza  Создаем конструкторы, которые производят значения нового типа
  • 23.  Для определения какой конструктор использован для данного экземпляра типа используются case выражения  Демо с арифметическими выражениями
  • 24.  Pattern-matching (англ.)  Используется при объявлении переменной вместо указания имени переменной val p = e  Используется при объявлении функции fun f p = e  Каждая функция принимает только один аргумент  Пример с суммированием элементов кортежа
  • 25.  Можно указать в конструкторе datatype использование любого типа  демо с option и бинарным деревом, суммирование узлов и листьев
  • 26.  Объявление: exception <name> of t  Вызов: raise <name> <значение>  Обработка: e1 handle <name> <параметры> => e2
  • 27.  Функции первого класса – могут использоваться как значения.  Функции высшего порядка - могут принимать другие функции в качестве параметра.  Пример f(f(f...f(x))) n раз (n_times)  Разбор типа: fn : ('a -> 'a) * int * 'a -> 'a
  • 28.  У анонимной функции нет имени, поэтому еѐ нельзя вызывать рекурсивно  fn args => e  Пример, double_n_times
  • 29.  Область видимости (англ. scope) – это контекст выполнения программы, где по имени можно обращаться к переменным или функциям.  Область видимости в блоке, в функции, в let-выражении, глобальный, лексический  Lexical scope. Не важно где вызывают функцию, важно где еѐ объявили
  • 30.  Значение функции состоит из двух частей: ◦ Код функции ◦ Среда, которая была на момент определения функции  Эта пара значений называет замыканием функции  Доступ к этим свойствам значения функции невозможен в коде  При вызове функции вычисляется код в рамках среды (которая дополняется аргументами функции)  Пример работы lexical scope.
  • 31.  Тело функции не вычисляется пока функция не будет вызвана  Тело функции вычисляется каждый раз, когда функция вызывается  Выражение в определении переменной вызывается один раз и вычисляется, когда переменная объявляется.
  • 32.  Основные операции со списками filter, map, fold: f(f(f(acc, x1), x2), x3)  Демо с реализацией и использованием операций.
  • 33.  Идиома – это элементарная конструкция типичная для одного или нескольких языков программирования в нашем случае для функциональных языков  Комбинирование функций (композиция)  Currying  Callback – подпись на события и обратный вызов функций.
  • 34.  SML использует жадную стратегию для вычислений fun f(x:int):bool = true; fun arg () : int = 3; f(arg()) (* вызовет метод arg, хотя параметр x не используется *)  Отложенные вычисления реализуются с помощью обертки выражения анонимной функцией (thunk).
  • 35.  Статическая типизация – контроль за типами при компиляции до запуска программы (Pascal, C++, Java, C#)  Динамическая типизация – контроль типов во время выполнения программы (PHP, Python, Ruby, Perl, Javascript)  ML – статически типизированный  ML – язык с неявным определением типов.  Применяется выведение типов
  • 36.  Выведение типов – процесс определения типов выражений, переменных, который приведет к успешной проверке типов.  Задача выведения типов ◦ Установить типы переменных в коде. ◦ Удостовериться, что все выражения проходят проверку типов.
  • 37.  Неизменяемость значений переменных  Использование функций в роли аргумента  Рекурсивные типы данных  Использование рекурсии в функции для обхода элементов списка  Использование сопоставления шаблонов  Ленивая инициализация
  • 38.  Функции первого порядка, closures в C#, Java, Javascript  Анонимные функции в C#, Javascript  LINQ в C#  Callback в C#, Javascript  Полиморфизм типов (generics)  Неявная типизация, выведение типов в C# и Javascript
  • 39.  Типы и операции, матрица  Разрешение задачи на ООЯП через выделение типов и интерфейса  Решение на ФЯП через определение datatype и выделения операций с перечислением пар и pattern-matching’ом
  • 40. eval toString hasZero Int Add Negate • В ФЯП декомпозиция по операциям • В ООП декомпозиция по сущностям, выполняющим действия
  • 41.  задачи оптимизации,  генетическое программировние,  сложные доказательства  эвристические задачи (например, шахматы)  современные языки программирования включают в себя различные парадигмы программирования (multi-paradigm) в том числе многие идиомы из ФЯ (например, C#, Javascript).
  • 42.  Списки – это тоже datatypes  Вложенные шаблоны, пример zip3, nondecreasing, multsign sgn = P | N | Z  Синонимы типов  Модули и сигнатуры
  • 43.  Описание библиотечных типов языка SML http://www.standardml.org/Basis/overview.h tml