Здравствуйте, deniok, Вы писали:
D>Потому что "гражданские" исходно были ориентированы на максимально "чистое" ООП. Паттерн матчинг хорош, когда внутренняя (алгебраическая) структура типа максимально открыта, тогда по ней тип легко разбирать. А в ООП, наоборот, стремились к унификации всего и вся, в том смысле, что всё есть объект, работа с которым идет через набор методов и свойств, а структурные детали инкапсулированы.
Не думаю, что это проблема. Любой объект имеет публичный интерфейс. Большинство новых языков выражают его в виде свойств. И я не вижу огромной разницы между список публичных свойств и полями алгеброических типов.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Tonal-, Вы писали:
T>То что нет паттерн-матчинг-а — жалко конечно, но он как бы не является основорологающим.
Для меня, на сегодняЮ, он является определяющим в ыборе языка.
VD>>Ну, а писать в функциональном стиле можно и на C# 2.0. На C# 3.0 это будет делать даже пожалуй удобно. Но вот однажды написав 100 кил с паттерн-матчингом потом уже без него писать не хочется. T>Давно не интересовался. T>А там уже есть лямбды, картежи и замыкания?
Лямбды (правдо немного многословные) и замыкания были в 2005-ом в C# 2.0. Сильно ты отстал.
Краткие лямбды и аналог кортежей появились в C# 3.0. В прочем, с кортежами не все однозначно. С одной стороны они лучше, так как у них есть именованные поля, но с другой нельзя описать тип кортежа (он толко может быть выведен), что не дает возвращать кортежи из функций.
T>И можно не писать класс на каждый чих?
Согласен. Только есть языки и с кортежами, и ООП, и с паттерн-мачингом. Они еще к тому же компилируемые и шустные. Внимание вопрос! Нахрена упал Питон?
VD>>Вообще, я никак не могу понять почему гражданские (как их называет Гапертон) языки не рассмотрели этой очень удобной фишки. Как показал опыт Скалы и Немерла она прекрасно интегрируется во вполне себе ООЯ. То есть по сути фича к ФП отношения не имеет. Просто удачное решение родившееся в среде ФП. T>Надеюсь, что в Python-е оно появиться.
А я почему-то не уверен в этом. Что-то большно сильно мэйнстрим обходит паттерн-мачинг. Как-будтно он заразный.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>>>Вообще, я никак не могу понять почему гражданские (как их называет Гапертон) языки не рассмотрели этой очень удобной фишки. Как показал опыт Скалы и Немерла она прекрасно интегрируется во вполне себе ООЯ. То есть по сути фича к ФП отношения не имеет. Просто удачное решение родившееся в среде ФП. T>>Надеюсь, что в Python-е оно появиться.
VD>А я почему-то не уверен в этом. Что-то большно сильно мэйнстрим обходит паттерн-мачинг. Как-будтно он заразный.
Может, он слишком сложен в реализации? (Это не праздный вопрос, действительно интересно)
Здравствуйте, Mamut, Вы писали:
M>Может, он слишком сложен в реализации? (Это не праздный вопрос, действительно интересно)
Я не скажу за Скалу (в его компиляторе не разбирался), но судя по Немрлу все не так сложно. Да конечно реализация паттерн-матчинга это не пара ифов, но и сверх сложной задачей ее назвать нельзя. Самый сложный кусок — это построитель дерева решений. Код, конечно, не тривильный (сложная математика), но алгоритмы уже известны и не раз описаны. Есть и готовые реализации. В Немерле его тупо скомуниздили из МЛ-я: http://nemerle.org/svn/nemerle/trunk/ncc/typing/DecisionTreeBuilder.n
а вот и описание: http://www.dina.kvl.dk/~sestoft/papers/match.ps.gz (к сожалению, постскрипт).
Вообще, Немерловцы поступили очень прикольно. Они тупо написали первую версию компилятора на ML-е (ОКамле, если не ошибаюсь) и когда получили первую хоть как-то рабочую версию, переписали его на самом себе (благо база общая).
С паттерн-матчингом другая проблема. Он плохо сочетается с ОО-классами. Алгоритм ML рассчитан на работу с алгеброическими типами данных. Все известные мне языки поддерживающие ПМ реализуют и их. В Нмерле это варианты, в Скале кейс-классы, в Эрланге записи (ну, не считаю кортежей) и так дале. Возможно авторы мэйнстримных ООЯ просто боятся вводить в язык еще одну сущность позволяющую хранить данные. Впрочем Васик сто лет имет в своем распоряжении тип данных вариант который очень похож по устройству на алгеброические типы, так что в чем реальная проблема не ясно.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, deniok, Вы писали:
D>>Потому что "гражданские" исходно были ориентированы на максимально "чистое" ООП. Паттерн матчинг хорош, когда внутренняя (алгебраическая) структура типа максимально открыта, тогда по ней тип легко разбирать. А в ООП, наоборот, стремились к унификации всего и вся, в том смысле, что всё есть объект, работа с которым идет через набор методов и свойств, а структурные детали инкапсулированы.
VD>Не думаю, что это проблема. Любой объект имеет публичный интерфейс. Большинство новых языков выражают его в виде свойств. И я не вижу огромной разницы между список публичных свойств и полями алгеброических типов.
Алгебраические типы структурно строятся на основе двух операций над типами: "сложения" (disjoint union, перечисление) и "умножения" (cartesian product, кортежи). Плюс (в некоторых языках) — допустима рекурсия в определении типа. То есть типы, в принципе, как строятся, так и матчатся. Список публичных свойств, ИМХО, — более однородная структура — умножение есть, а сложения нету. В каноническом ООП у объекта может быть "и Свойство1, и Свойство2 и Свойство3", но вот "или Свойство4, или Свойство5" — такое только в вариантах или enum'ах. В, Nemerle, насколько я понимаю, это решено через варианты.
Здравствуйте, VladD2, Вы писали:
VD> И я не вижу огромной разницы между список публичных свойств и полями алгеброических типов.
Разница в точнностиравна разнице между инициальными и финальными алгебрами.
Здравствуйте, deniok, Вы писали:
D>Алгебраические типы структурно строятся на основе двух операций над типами: "сложения" (disjoint union, перечисление) и "умножения" (cartesian product, кортежи). Плюс (в некоторых языках) — допустима рекурсия в определении типа. То есть типы, в принципе, как строятся, так и матчатся. Список публичных свойств, ИМХО, — более однородная структура — умножение есть, а сложения нету. В каноническом ООП у объекта может быть "и Свойство1, и Свойство2 и Свойство3", но вот "или Свойство4, или Свойство5" — такое только в вариантах или enum'ах. В, Nemerle, насколько я понимаю, это решено через варианты.
Извини, но это все пустые слова. Для паттерн-матчинга нужно всего лишь знать описание интерфейса объекта, чтобы можно было создать паттерн сопоставляемый с объектом. В F# и Scala даже разработали по решению для матчига обычных объектов. Оба основаны на идее запоковки и распаковки. В F# решение более декларативно, в Скале это просто объект с двумя функциями (распаковки и запаковки).
Уверен, что можно сделать паттерн-матчинг и без всех этих ухищьрений.
Например:
class A { public Prop1 : int { get{...} }
class B: A { public Prop2 : A { get{...} }
match (x)
{
| B{ Prop1=1; Prop2=B { Prop1=2; }; } => ...
| A{ Prop1=1; } => ...
}
впроле можно обработать компилятором. Просто алгоритм будет по сложнее.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
D>>Не вижу тут главной вкусности — рекурсивного разбора по конструкторам рекурсивно определённого типа данных.
VD>Ну, так попей чайку и еще раз внимательно погляди. Конструкторов конечно ты не увидишь, так как не в нихсуть, но все остальное в наличии.
VD>Матчинг по последовательностям тоже можно сделать.
VD>В общем, надо всего лишь забыть о наукообразии и поглядеть на реальные потребности реальных людей.
Мы вообще-то про "гражданские" языки говорим или про Nemerle? В Nemerle, ага, я знаю disjoint union есть, и разбирается всё по вариантам конструкторов (ну может терминология другая) Red, Black:
/// Описывает ветку дерева «красно-черного» дерева.
public variant Node[T] : IEnumerable[T] where T : IComparable[T]
{
| Red { key : T; lchild : Node[T]; rchild : Node[T]; }
| Black { key : T; lchild : Node[T]; rchild : Node[T]; }
| Leaf
/// Подсчет количества элементов.
public Count : int
{
get
{
match (this)
{
| Red(_, left, right) | Black(_, left, right) =>
1 + left.Count + right.Count
| _ => 0
}
}
}
Здравствуйте, deniok, Вы писали:
D>Мы вообще-то про "гражданские" языки говорим или про Nemerle? В Nemerle, ага, я знаю disjoint union есть, и разбирается всё по вариантам конструкторов (ну может терминология другая) Red, Black:
Пример я вроде привел довольно доходчивый. Что в нем не ясно? Синаксис я использовал Немерловый так как он мне ближе. Но код — это не совсем неперловый. Ты еще раз его погляди...
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
VD>Пример я вроде привел довольно доходчивый. Что в нем не ясно? Синаксис я использовал Немерловый так как он мне ближе. Но код — это не совсем неперловый. Ты еще раз его погляди...
Гляжу ещё раз.
VD>>
VD>>class A { public Prop1 : int { get{...} }
VD>>class B: A { public Prop2 : A { get{...} }
VD>>match (x)
VD>>{
VD>> | B{ Prop1=1; Prop2=B { Prop1=2; }; } => ...
VD>> | A{ Prop1=1; } => ...
VD>>}
VD>>
Разматченное слево от => (образец) как тут связывается для использования в правой?
VD>>>class A { public Prop1 : int { get{...} }
VD>>>class B: A { public Prop2 : A { get{...} }
VD>>>match (x)
VD>>>{
VD>>> | B{ Prop1=1; Prop2=B { Prop1=2; }; } => ...
VD>>> | A{ Prop1=1; } => ...
VD>>>}
VD>>>
D>Разматченное слево от => (образец) как тут связывается для использования в правой?
Никак. Этот образец всего лишь находит нужную конструкцию. Он находит экземпляр класса B свойство Prop1 которого равно еденице, а свойство Prop2 ссылается на объект (оптять же) класса B свйосво Prop1 которого равно двум. Если нужна связь, то это будет как-о так:
| B { Prop1=1; Prop2=B { Prop1=2; } as b; } => b.Prop2 *= 2;
или так:
| B { Prop1=1; Prop2=B { Prop1=x; }; } => x
Другими словами мы рассматриваем паттерн как состояние объекта. Уаказываем чему должны быть равны его свойства или используем переменные для связывания со значениями.
Причем обрати внимание, в примере, свойство Prop2 у объекта имеет тип A, что допускает наличие там экземпляра классов наследников A. Соответственно паттерн проверяет, что свойство содержит именно экземпляр класса B и проверяет уже его свойства. Таким образом обходится одно из неприятнешийх свойств ООЯ — необходимость неуклюжих up-cast-ов при работе со списками или иерархиями. Одно это сделало бы язык значительно удобнее.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
D>>Разматченное слево от => (образец) как тут связывается для использования в правой?
VD>Никак. Этот образец всего лишь находит нужную конструкцию. Он находит экземпляр класса B свойство Prop1 которого равно еденице, а свойство Prop2 ссылается на объект (оптять же) класса B свйосво Prop1 которого равно двум. Если нужна связь, то это будет как-о так: VD>
VD>| B { Prop1=1; Prop2=B { Prop1=2; } as b; } => b.Prop2 *= 2;
VD>
VD>или так: VD>
VD>| B { Prop1=1; Prop2=B { Prop1=x; }; } => x
VD>
VD>Другими словами мы рассматриваем паттерн как состояние объекта. Уаказываем чему должны быть равны его свойства или используем переменные для связывания со значениями. VD>Причем обрати внимание, в примере, свойство Prop2 у объекта имеет тип A, что допускает наличие там экземпляра классов наследников A. Соответственно паттерн проверяет, что свойство содержит именно экземпляр класса B и проверяет уже его свойства. Таким образом обходится одно из неприятнешийх свойств ООЯ — необходимость неуклюжих up-cast-ов при работе со списками или иерархиями. Одно это сделало бы язык значительно удобнее.
А чем это в гипотетическом гражданском языке удобнее, чем
if (typeof(x)=B && x.Prop1=1 && typeof(x.Prop2)=B && x.Prop2.Prop1=2)
{x.(добрались через "." до нужного свойства)*=2;}
else if (typeof(x)=A && x.Prop1=1)
{...}
Чуть длиннее, но ИМХО требования к x выражены более ясно
Еще раз намекаю, что оверквотить не стоит.
D>А чем это в гипотетическом гражданском языке удобнее, чем
D>
D>if (typeof(x)=B && x.Prop1=1 && typeof(x.Prop2)=B && x.Prop2.Prop1=2)
D> {x.(добрались через "." до нужного свойства)*=2;}
D>else if (typeof(x)=A && x.Prop1=1)
D> {...}
D>
D>Чуть длиннее, но ИМХО требования к x выражены более ясно
Начнем с того, что это уже 4 строки вместо одной. А закочим тем, что они не равнозначны. Полный код будет выглядеть так:
// | B{ Prop1=1; Prop2=B { Prop1=2; }; } => ...
B b1 = x as B.
if (b1 != null && b1.Prop1 == 1)
{
B b2 = b1.Prop2 as B;
if (b2 != null && b2.Prop1 == 2)
{
...
}
}
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Немного о функциональном подходе
От:
Аноним
Дата:
16.05.07 12:52
Оценка:
А>>По ML: А>>
К сожалению данное семейство также не является чисто функциональным.
А>>В заключении: А>>
Поэтому нет смысла сравнивать эти подходы или противопоставлять, гораздо лучше их совместить
U>Просто при беглом обзоре языков, акцентировалось внимание на том является ли язык чисто фунциональным, возможно с целью поиска максимально близкого к эталонному ФЯ, инетерес был вызван чисто академическими соображениями. В конце статьи делаются выводы относительно того, что наиболее рациональным использованием ФП является его совмещение с ИЯ, что и нашло отражение во многих существующих языках. Поэтому никакого противоречия я не вижу.
Читающий такую статью новичок (а если не новчиок — зачем ему введение?) не в курсе истории.
У него основная мысль: что это, чем так хорошо что мне нужно (и нужно ли) учить что-то совсем новое и незнакомое ?
И для него эти куски как раз будут говорить что чистая функциональность это хорошо и к этому нужно стремиться и что чистая функциональность это плохо и нужно стремиться к смеси функциональности с императивностью.
Re[3]: Немного о функциональном подходе, вопрос
От:
Аноним
Дата:
16.05.07 13:01
Оценка:
L>Функциональный подход — это декларативный подход, рассматривающий программу, как одну большую функцию (в математическом смысле). Исполнение программы — вычисление функции. L>Декларативность подразумевает независимость программы от расположения деклараций (в императивной зависит от расположения инструкций).
Тогда Эрланг не функционален, поскольку не декларативен.
Мне кажется есть мнооого JS-программеров, даже вероятно больше чем питоновцев.
Правда их опыт — 10 функций на 100 страничек.
Но так тем более они новички и аудитория этой статьи.