![]() |
Модераторы: Се ля ви |
![]() ![]() ![]() |
|
Ch0bits |
|
|||
![]() Python Dev. ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2124 Регистрация: 21.2.2005 Где: Казань Репутация: нет Всего: 62 |
САБЖ
Объясните пожалуйста! ![]() |
|||
|
||||
Void |
|
||||||||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 9 Всего: 173 |
В контексте языков программирования под лямбда-функцией понимают анонимную функцию. Т.е. функцию, которой не сопоставлено никакое имя, просто значение функционального типа. Например:
C# 2.0:
OCaml:
Haskell:
Lisp:
Название пошло от Лямбда-исчисления. Лямбда-функции чаще всего используются совместно с замыканиями, однако это ортогональные понятия. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||||||||
|
|||||||||||
Ch0bits |
|
|||
![]() Python Dev. ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2124 Регистрация: 21.2.2005 Где: Казань Репутация: нет Всего: 62 |
Ну ты полиглот
![]() Но я ничего не понял! ![]() Ни про исчисления, ни про замыкания... ![]() Как это понимать? |
|||
|
||||
Void |
|
|||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 9 Всего: 173 |
Замыкание, это, фактически, захват контекста вызова. Т.е. в точке вызова функции доступны переменные, которые были в зоне видимости определения функции, но не видны в самой точке вызова. Например:
foo через замыкание получила доступ к n в bar, хотя прямой видимости нет. Почитай еще здесь. А про лямбда-исчисление написано в замечательной книги Харрисона и Филда «Функциональное программирование», которая есть на lib.ru. Ортогональные — значит не зависят друг от друга, одно не является следствием или непременным атрибутом другого. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
|||
|
||||
Ch0bits |
|
|||
![]() Python Dev. ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2124 Регистрация: 21.2.2005 Где: Казань Репутация: нет Всего: 62 |
В чём же преимущества такого подхода? Я пока вижу одну путаницу.
![]() |
|||
|
||||
Void |
|
||||||||||||||||||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 9 Всего: 173 |
Преимущества появляются, когда есть адекватный синтаксис и нормальная поддержка функций высшего порядка [1] со стороны библиотеки. В C# 2.0 первое хромает, а второе находится в зачаточном состоянии.
Преимущества в том, что многие операции можно параметризовать функциями. И очень часто функции, которые надо передать, имеют небольшой размер и имеют значение только для маленького участка кода, где они применяются. Отсюда возникает необходимость в синтаксисе, позволяющем описывать такие функции прямо по месту использования, не засоряя пространство имен. Далее, логично было бы использовать в этой анонимной функции переменные, описанные в текущей функции и внешнем пространстве имен. [1] — функцией высшего порядка называется функция, принимающая другие функции в качестве параметров и/или возвращающая функциональные значения. Попытаюсь объяснить преимущества и анонимных функций и замыканий, реализуя один и тот же пример на нескольких языках, с последовательно нарастающим уровнем абстракции. Допустим, у нас есть задача: найти в списке элемент, удовлетворяющий заданному условию (предикату). Представим себе, что у нас уже есть структура данных «список» и функция поиска, принимающая предикат, который также является функцией, возвращающей значений булевского типа. Шаг первый: ни анонимных функций, ни замыканий. Чистый Си.
Мы можем написать функцию greater где-то в файле, но передать значение n в нее мы можем только через глобальную переменную, а делать этого нам бы не хотелось. Выход один: добавить в find еще один параметр, который она будет передавать предикату при каждом его вызове. Поскольку предикату может понадобиться все что угодно, параметр придется делать типа void*. Прощай, типобезопасность, но мы же все-таки на Си пишем. Итак, новый вариант:
Не очень красиво, но достаточно гибко. Шаг один с половиной. Анонимных функций нет, замыкания есть, но толку от них… Паскаль.
Ошибка компиляции. Объявленные таким образом функции нельзя передавать в другие функции. Внутри области видимости используйте сколько угодно, они будут иметь доступ ко внешним переменным. А передать — ни-ни. Ну и зачем они такие нужны? А решение проблемы в итоге такое же, как в Си. Шаг два. В языке вроде бы нет ни того, ни другого, но все можно сделать своими руками. C++.
Синтаксис не блещет, но задачу мы все-таки решили, не вылезая за пределы своей функции и не теряя типобезопасности (хвала шаблонам). А предикат в виде класса можно вообще куда-нибудь в библиотеку выделить. Что, впрочем, создатели стандартной библиотеки и сделали.
Запись стала сущестенно короче, но не слишком понятнее. Отдельные индивидуумы пошли дальше, и задействовав головокружительную смесь шаблонов и перегрузки операторов, сумели создать библиотеку, позволяющую писать так:
Выглядит неплохо, но до первой опечатки. Компилятор с удовольствием выльет на вас килобайты грязи из несметных полчищ шаблонов. А когда исходник с десятком таких выражений будет компилироваться с минуту, вы поймете, что в C++ хоть и можно все сделать своими руками, но получается обычно через одно место. Шаг третий. Есть и анонимные функции и замыкания. Вот только пользоваться ими не очень удобно. C# 2.0.
Просто и элегантно. Но, во-первых, чуть более многословно, чем следовало бы. Во-вторых, имеющегося в стандартной библиотеке набора алгоритмических функций высшего порядка явно недостаточно. Шаг три с половиной. Синтаксис рулит, библиотеку писали с учетом всех возможностей языка. OCaml.
Или даже так:
Почему всего полшага? Если бы не один просчет создателей .NET Framework, я бы поставил OCaml на одну полку с C#. Дело в том, что функции высшего порядка в стандартной библиотеке что там, что там неполиморфны. В .NET нет функций, работающих с IList или IEnumerable. Только методы List, Array и т.д., хотя сам язык позволяет их написать. OCaml увы, этого рода полиморфизма лишен из-за свойств самого языка. Шаг четвертый. То же самое, плюс полиморфизм. Haskell (за счет type classes). Одна и та же функция будет работать и со списком, и с массивом, и с черт знает чем, лишь бы те предоставляли некоторый интерфейс. Код приводить не буду, т.к. знаком с языком очень поверхностно, лишь осведомлен о возможности такой реализации. Disclaimer: я упомянул далеко не все языки, поддерживающие замыкания и анонимные функции. Например, Python и Ruby (особенно Ruby) замечательно поддерживают и то и другое. И даже полиморфизм работает, правда, за счет duck typing'а со всеми вытекающими. Вывод: замыкания, функции высшего порядка и анонимные функции — очень удобный инструмент, если научиться им пользоваться, понять простейшие приемы функциональной декомпозици. Это сообщение отредактировал(а) Void - 15.5.2006, 22:09 -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
||||||||||||||||||
|
|||||||||||||||||||
batigoal |
|
|||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: 1 Всего: 151 |
Void, я потрясён.
-------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
|||
|
||||
Void |
|
|||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 9 Всего: 173 |
Lamer George, спасибо
![]() to all: Буду очень благодарен за любые дельные замечания к посту. Думаю, после некоторой обработки это можно разместить в Вики. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
|||
|
||||
ALKS |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 354 Регистрация: 22.3.2006 Репутация: нет Всего: 11 |
Хм.... а пример того же на Java?
![]() |
|||
|
||||
Void |
|
|||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 9 Всего: 173 |
ALKS, увы, Java я в лучшем случае могу читать. AFAIK, замыкания в Java можно изобразить на анонимных классах.
Добавлено @ 17:23 Уточнил в Гугле. Inner classes в Java копируют контекст вызова, а не захватывают его. Т.е. мы можем использовать внешние переменные, но не модифицировать их. -------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
|||
|
||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 1 Всего: 110 |
как-то пробовал так делать... ругается ![]() не хочет использовать локальный тип при специализации шаблона компилятор из VC++ 2003 Toolkit вопрос: это самодеятельность Microsoft или так должно быть по стандарту? -------------------- qqq |
|||
|
||||
maxim1000 |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 1 Всего: 110 |
зато можно так (только в том случае если тот не работает):
только здесь уже не совсем "не вылезая за пределы функции" - нужна небольшая подготовка Если всё будет оставаться в пределах видимости, можно даже рассчитывать на отсутствие потерь в производительности... -------------------- qqq |
|||
|
||||
svg |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 53 Регистрация: 13.4.2005 Репутация: нет Всего: 18 |
Полиморфная find (erlang)
Это сообщение отредактировал(а) svg - 16.5.2006, 20:15 |
||||
|
|||||
Ch0bits |
|
|||
![]() Python Dev. ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2124 Регистрация: 21.2.2005 Где: Казань Репутация: нет Всего: 62 |
svg
Это что у тебя за язык? Void Читал 5 раз, в разное время суток. Вроде что-то понял, но мне до этого расти да расти. ![]() Лови плюс. ![]() |
|||
|
||||
Void |
|
|||
![]() λcat.lolcat ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2206 Регистрация: 16.11.2004 Где: Zürich Репутация: 9 Всего: 173 |
-------------------- “Coming back to where you started is not the same as never leaving.” — Terry Pratchett |
|||
|
||||
![]() ![]() ![]() |
Правила раздела "Философия программирования": | |
|
Форум "Философия программирования" предназначен для обсуждения вопросов, так или иначе связанных с философскими аспектами разработки ПО: • вопросы перспективного развития методов написания ПО; • изменяющиеся языки и методологии программирования; Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Се ля ви. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Философия программирования | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |