Re[30]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 20.02.08 13:02
Оценка:
Здравствуйте, Трурль, Вы писали:

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

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

Учитывая то, что таким образом здесь решался конфликт двух отличающихся интуитивных представлений, то, что неинтуитивное определение будет противоречить одному из этих интуитивных представлений — неизбежно.
... << RSDN@Home 1.2.0 alpha rev. 774>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[31]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.02.08 08:41
Оценка:
Здравствуйте, Klapaucius, Вы писали:

E>>>>Разница всего-лишь в форме записи.

K>>>Ну да, конечно. И здесь тоже:
K>>>
K>>>foo(bar)
K>>>bar.foo()
K>>>

E>>Вы будете смеятся, но в Nice это совершенно одно и то же.
E>>И в D в некоторых случаях так же.

K>Не буду. В мультипарадигменном Nice первое сделано для поддержки ФП, а второе для поддержки ООП. Но речь не идет о том, что можно, а о том, что нельзя.


Речь о том, что когда вы не согласились с моим утверждением о том, что разница всего лишь в форме записи вызова, вы привели пример с различием foo(bar) и bar.foo(). Но ваш пример оказался неудачным, т.к. в нем опять таки различие всего лишь в форме записи. О чем я изначально и говорил.

K>В C# 2.0 тоже можно повсеместно оборачивать функцию в делегат явным образом, но ведь можно этого и не делать. А в Eiffel нельзя.


И в D нельзя. Но D вы не отказываете в праве быть функциональным.

K>Агент передается по правилам для объектов, у него есть метод call, который вызывается по правилам для объектов — я вижу семантику объекта. Если вызов функции через агент выглядит как вызов метода объекта, а не как вызов функции, почему агент следует считать функцией?


А я смотрю на Nice-вый код:
void main( String[] args )
  {
    let f = () => println( "Hello!" );
    let g = f;
    println( "g and f are: " + ( g == f ? "same" : "different" ) );
    println( f.getClass().getName() );
  }

и результат запуска:
gnu.expr.ModuleMethod
g and f are: same

и вижу, что f и g всего лишь ссылки на объект. Они подчиняются правилам ссылок. У объекта, который содержит анонимную функцию, есть обычные методы объекта. И все дело лишь в синтаксическом сахаре, который скрывает за f() обращение к gnu.expr.ModuleMethod.apply0(). А в Eiffel такого сахара нет (но вовсе не факт, что его туда невозможно было добавить по техническим причинам, скорее дело в идеологии Мейера).

Итак получается, что в Eiffel есть агенты, которые реализуются через объекты, но позволяют реализовывать HOF, вроде map, fold и пр. Но поскольку агенты -- это объекты, то Eiffel-ю в праве быть функциональным языком отказано. В Nice функции реализуются через объекты, позволяют реализовывать HOF, но поскольку функции в Nice -- это объекты, но их вызов подсахарен, то Nice считается функциональным языком.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[32]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 21.02.08 13:04
Оценка:
Здравствуйте, eao197, Вы писали:

K>>Не буду. В мультипарадигменном Nice первое сделано для поддержки ФП, а второе для поддержки ООП. Но речь не идет о том, что можно, а о том, что нельзя.

E>Речь о том, что когда вы не согласились с моим утверждением о том, что разница всего лишь в форме записи вызова, вы привели пример с различием foo(bar) и bar.foo(). Но ваш пример оказался неудачным, т.к. в нем опять таки различие всего лишь в форме записи. О чем я изначально и говорил.

О различии в форме записи можно говорить только в том случае, когда различие возможно. Если же возможен только один вариант — форма записи одна.

K>>В C# 2.0 тоже можно повсеместно оборачивать функцию в делегат явным образом, но ведь можно этого и не делать. А в Eiffel нельзя.

E>И в D нельзя. Но D вы не отказываете в праве быть функциональным.

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

K>>Агент передается по правилам для объектов, у него есть метод call, который вызывается по правилам для объектов — я вижу семантику объекта. Если вызов функции через агент выглядит как вызов метода объекта, а не как вызов функции, почему агент следует считать функцией?


E>А я смотрю на Nice-вый код:

E>
E>void main( String[] args )
E>  {
E>    let f = () => println( "Hello!" );
E>    let g = f;
E>    println( "g and f are: " + ( g == f ? "same" : "different" ) );
E>    println( f.getClass().getName() );
E>  }
E>

E>и результат запуска:
E>
E>gnu.expr.ModuleMethod
E>g and f are: same
E>

E>и вижу, что f и g всего лишь ссылки на объект. Они подчиняются правилам ссылок. У объекта, который содержит анонимную функцию, есть обычные методы объекта. И все дело лишь в синтаксическом сахаре, который скрывает за f() обращение к gnu.expr.ModuleMethod.apply0().

Совершенно верно. Но это детали реализации, которые на уровне кода не видны.

E>А в Eiffel такого сахара нет (но вовсе не факт, что его туда невозможно было добавить по техническим причинам, скорее дело в идеологии Мейера).


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

E>Итак получается, что в Eiffel есть агенты, которые реализуются через объекты, но позволяют реализовывать HOF, вроде map, fold и пр. Но поскольку агенты -- это объекты, то Eiffel-ю в праве быть функциональным языком отказано. В Nice функции реализуются через объекты, позволяют реализовывать HOF, но поскольку функции в Nice -- это объекты, но их вызов подсахарен, то Nice считается функциональным языком.


В Eiffel агенты это объекты. Проблема не в том, что агенты — это объекты. Функции — это не агенты. А агенты — это не функции.
Поэтому я и не считаю, что функции в Eiffel первоклассные.
Но от соотвествия Eiffel моему определению функционального языка его действительно отделяет только синтаксический сахар.
... << RSDN@Home 1.2.0 alpha rev. 774>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[33]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 21.02.08 14:12
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>>>В C# 2.0 тоже можно повсеместно оборачивать функцию в делегат явным образом, но ведь можно этого и не делать. А в Eiffel нельзя.

E>>И в D нельзя. Но D вы не отказываете в праве быть функциональным.

K>Почему не отказываю? Я оставил ваш пример на D без комментария, потому, что тогда думал, что и без комментария все очевидно.


Что очевидно? Не вы ли это факт давно признали
Автор: Klapaucius
Дата: 04.02.08
:

E>Так что, D уже функциональным языком стал?

Ну значит стал — не вижу в этом ничего сенсационного. Было бы странно, если бы язык, разрабатываемый в 2000-х годах им не стал.


Давайте определимся -- согласно вашего определения, D -- функциональный язык или нет?

E>>и вижу, что f и g всего лишь ссылки на объект. Они подчиняются правилам ссылок. У объекта, который содержит анонимную функцию, есть обычные методы объекта. И все дело лишь в синтаксическом сахаре, который скрывает за f() обращение к gnu.expr.ModuleMethod.apply0().


K>Совершенно верно. Но это детали реализации, которые на уровне кода не видны.


Т.е. на уровне кода не видно, что f и g -- это ссылки на _объекты_?

K>В Eiffel агенты это объекты. Проблема не в том, что агенты — это объекты. Функции — это не агенты. А агенты — это не функции.


Почему же это самое нельзя адресовать к Nice?

K>Поэтому я и не считаю, что функции в Eiffel первоклассные.

K>Но от соотвествия Eiffel моему определению функционального языка его действительно отделяет только синтаксический сахар.

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[34]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 23.02.08 12:32
Оценка:
Здравствуйте, eao197, Вы писали:

E>>>И в D нельзя. Но D вы не отказываете в праве быть функциональным.

K>>Почему не отказываю? Я оставил ваш пример на D без комментария, потому, что тогда думал, что и без комментария все очевидно.
E>Что очевидно? Не вы ли это факт давно признали
Автор: Klapaucius
Дата: 04.02.08
:

E>

E>>Так что, D уже функциональным языком стал?
E>Ну значит стал — не вижу в этом ничего сенсационного. Было бы странно, если бы язык, разрабатываемый в 2000-х годах им не стал.


Ну да, а у Ильича есть известное высказывание "было бы величайшей ошибкой думать".
Вы спросили:

А пример, приведенный вашему, можно и на D 2.0 изобразить, там уже замыкания есть. Так что, D уже функциональным языком стал?

Я ответил:

E>А пример, приведенный вашему, можно и на D 2.0 изобразить, там уже замыкания есть.

И как это будет выглядеть?

E>Так что, D уже функциональным языком стал?

Ну значит стал — не вижу в этом ничего сенсационного.


Понятно, что если на D можно повторить мой пример, в нем есть первоклассные функции. Откуда же мне было знать, что у нас с вами такие разные взгляды на первоклассные функции в тот момент диалога? Получается недобросовестное цитирование — нехорошо!

E>Давайте определимся -- согласно вашего определения, D -- функциональный язык или нет?


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

E>>>и вижу, что f и g всего лишь ссылки на объект. Они подчиняются правилам ссылок. У объекта, который содержит анонимную функцию, есть обычные методы объекта. И все дело лишь в синтаксическом сахаре, который скрывает за f() обращение к gnu.expr.ModuleMethod.apply0().

K>>Совершенно верно. Но это детали реализации, которые на уровне кода не видны.
E>Т.е. на уровне кода не видно, что f и g -- это ссылки на _объекты_?

Видно, конечно. Но видно также и то, что функция — объект не хуже прочих.

K>>В Eiffel агенты это объекты. Проблема не в том, что агенты — это объекты. Функции — это не агенты. А агенты — это не функции.

E>Почему же это самое нельзя адресовать к Nice?

Потому, что в Eiffel функции — это не объекты. Функциональный объект конструируется явным образом и имеет отличающийся синтаксис вызова.

K>>Поэтому я и не считаю, что функции в Eiffel первоклассные.

K>>Но от соотвествия Eiffel моему определению функционального языка его действительно отделяет только синтаксический сахар.
E>Да уж, когда на принадлежность языка той или иной категории влияет синтаксический сахар, а не фундаментальные возможности...

Влияет синтаксический сахар и фундаментальные возможности. Роль синтаксического сахара я бы недооценивать не стал.
... << RSDN@Home 1.2.0 alpha rev. 726>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[35]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.02.08 13:21
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Понятно, что если на D можно повторить мой пример, в нем есть первоклассные функции. Откуда же мне было знать, что у нас с вами такие разные взгляды на первоклассные функции в тот момент диалога?


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

E>>Давайте определимся -- согласно вашего определения, D -- функциональный язык или нет?


K>Я не знаю D. Если без указания & будет, например, возвращена не ссылка на класс, реализующий замыкание, а копия класса, реализующего замыкание — то функции в D первоклассные — ergo D соотвествует моему определению функционального языка.


А при чем здесь классы? Мы же о функциях речь ведем. В D есть отдельное, независимое от классов/объектов понятие делегата (что-то вроде указателя на функцию в C++, но дополнительно с сохранением контекста). Операция &, примененная к имени функции/метода, возвращает делегат. Это не объект, это отдельное понятие.

Так же в D есть возможность конструирования анонимных функций/делегатов. Где временами используется ключевое слово delegate, а иногда -- нет (зависит от контекста). См. описание FunctionLiteral

E>>>>и вижу, что f и g всего лишь ссылки на объект. Они подчиняются правилам ссылок. У объекта, который содержит анонимную функцию, есть обычные методы объекта. И все дело лишь в синтаксическом сахаре, который скрывает за f() обращение к gnu.expr.ModuleMethod.apply0().

K>>>Совершенно верно. Но это детали реализации, которые на уровне кода не видны.
E>>Т.е. на уровне кода не видно, что f и g -- это ссылки на _объекты_?

K>Видно, конечно. Но видно также и то, что функция — объект не хуже прочих.


А в функциональном языке функция -- это объект?
Подтвердите это примерами, например, из Haskell или OCaml, или Erlang. Что-то я не помню, чтобы в Erlang-е или OCaml-е по ссылке на функцию можно было определить класс, объектом которого эта функция является. В функциональных языках, насколько я знаю, функция -- сама по себе, объект сам по себе (OCaml здесь может быть примером -- там есть и объекты, и функции. Но каждый из них сам по себе). А вот в Nice функция -- это объект, т.е. часть не функциональной, а объектно-ориентированной системы.

K>>>В Eiffel агенты это объекты. Проблема не в том, что агенты — это объекты. Функции — это не агенты. А агенты — это не функции.

E>>Почему же это самое нельзя адресовать к Nice?

K>Потому, что в Eiffel функции — это не объекты. Функциональный объект конструируется явным образом и имеет отличающийся синтаксис вызова.


А как же замечание, кажется, Курилки, о том, что в Erlang функциональные объекты конструируются с помощью специального ключевого слова fun?

K>>>Поэтому я и не считаю, что функции в Eiffel первоклассные.

K>>>Но от соотвествия Eiffel моему определению функционального языка его действительно отделяет только синтаксический сахар.
E>>Да уж, когда на принадлежность языка той или иной категории влияет синтаксический сахар, а не фундаментальные возможности...

K>Влияет синтаксический сахар и фундаментальные возможности.


Тогда у фундаментальных возможностях. Тот факт, что агенты на Eiffel позволяют реализовывать HOF вроде map/fold/filter и пр. что-нибудь доказывает или нет? Вот в Java, например, это без дополнительных интерфейсов и анонимных вложенных классов не сделать. А в Eiffel -- без проблем.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[36]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 23.02.08 20:23
Оценка:
Здравствуйте, eao197, Вы писали:

K>>Понятно, что если на D можно повторить мой пример, в нем есть первоклассные функции. Откуда же мне было знать, что у нас с вами такие разные взгляды на первоклассные функции в тот момент диалога?

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

Я делал заявление о том, что D соответствует моему определению функционального языка в том случае, если на нем можно повторить мой пример на Nice. Это заявление чисто аналитическое и верно. Заявление о том, что мой пример можно повторить на D сделали вы. Обладая, очевидно, глубоким знанием предмета. Это утверждение синтетическое и может быть опровергнуто опытом. Опыт был проделан, код написан. Утверждение было опровергнуто этим опытом. Я поблагодарил вас оценкой за проделанный труд и посчитал, что тема закрыта. Насчет темы я ошибся.
Я доступно объяснил?

E>>>Давайте определимся -- согласно вашего определения, D -- функциональный язык или нет?

K>>Я не знаю D. Если без указания & будет, например, возвращена не ссылка на класс, реализующий замыкание, а копия класса, реализующего замыкание — то функции в D первоклассные — ergo D соотвествует моему определению функционального языка.
E>А при чем здесь классы? Мы же о функциях речь ведем. В D есть отдельное, независимое от классов/объектов понятие делегата (что-то вроде указателя на функцию в C++, но дополнительно с сохранением контекста). Операция &, примененная к имени функции/метода, возвращает делегат. Это не объект, это отдельное понятие.

Я не был уверен, что & в данном случае обязателен — у меня была вторая версия о том, что он определяет способ передачи сущности, хранящей контекст. Поэтому я и уточнил.

Из описания я понял, что это первоклассная сущность, его можно создавать, передовать, возвращать и т.д. как и объект.
Допустим, что мы ведем речь о функциях — тогда должны констатировать, что делегат в данном случае это "что-то вроде указателя на функцию в C++, но дополнительно с сохранением контекста" а вовсе не функция. Если бы функция оборачивалась в этот делегат неявно, то функция являлась бы первоклассным значением.

E>>>>>и вижу, что f и g всего лишь ссылки на объект. Они подчиняются правилам ссылок. У объекта, который содержит анонимную функцию, есть обычные методы объекта. И все дело лишь в синтаксическом сахаре, который скрывает за f() обращение к gnu.expr.ModuleMethod.apply0().

K>>>>Совершенно верно. Но это детали реализации, которые на уровне кода не видны.
E>>>Т.е. на уровне кода не видно, что f и g -- это ссылки на _объекты_?
K>>Видно, конечно. Но видно также и то, что функция — объект не хуже прочих.
E>А в функциональном языке функция -- это объект?

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

E>А вот в Nice функция -- это объект, т.е. часть не функциональной, а объектно-ориентированной системы.


Ну так что? В мультипарадигменных языках это распространенное решение. К моему определению это никакого отношения не имеет. Если функция — первоклассная сущность, ее можно сконструировать, передать, вернуть уже не имеет значения чем она еще является, объектом, сепулькой или шалтаем-болтаем. Все это вынесено за рамки определения и я не могу понять, на каком основании нужно отклоняться от основного направления разговора в эту сторону.
Если же функцию нельзя сконструировать или передать или вернуть — она не является первоклассной сущностью, даже если мы можем явно обернуть ее в объект, сепульку или шалтая-болтая, которые в этом языке равны, полноправны, но все равнее функции.

K>>>>В Eiffel агенты это объекты. Проблема не в том, что агенты — это объекты. Функции — это не агенты. А агенты — это не функции.

E>>>Почему же это самое нельзя адресовать к Nice?
K>>Потому, что в Eiffel функции — это не объекты. Функциональный объект конструируется явным образом и имеет отличающийся синтаксис вызова.
E>А как же замечание, кажется, Курилки, о том, что в Erlang функциональные объекты конструируются с помощью специального ключевого слова fun?

Оно к делу отношения не имеет, на самом деле, как и все это циклически повторяющееся перечисление языков.
Вообще, классификация — это чистая условность, вопрос договоренности. Поэтому доказать мою правоту — либо неправоту невозможно. Можно было бы прийти к какому-то компромисному варианту, но дискуссия явно не в этом направлении движется.
Перечисление набора языков, раз за разом — это контрпродуктивно на мой взгляд. Например потому, что принадлежность языков из этого списка к (не) функциональным как бы сама собой разумеется, но на самом деле ниоткуда не следует. Было бы интересно ознакомится с внятно сформулированным альтернативным определением, но я его так и не увидел.
Проблемы своего определения я осознаю, как уже писал здесь
Автор: Klapaucius
Дата: 16.02.08
, но от отказа от него предчувствую еще большее количество проблем. Камнем преткновения, насколько я понимаю, является определение первоклассности функций, его можно трактовать строго (как делаю я) либо мягко — до какой степени неизвестно. Но от этого зависит классификация некоторого числа языков.
Все эти языки, по сути, мультипарадигменные — никаких проблем с классификацией более или менее чистых реализаций функциональной парадигмы нет. Можно, конечно, ввести переходный класс между функциональными и нефункциональными языками, но от такой нечеткости, как мне кажется, только дополнительная головная боль.
Причем, как мне кажется, вне зависимости от строгости определения первоклассности функций язык Nice все равно соответствует моему определению. Можно ли в таком случае считать хотя-бы этот вопрос решенным?

E>>>Да уж, когда на принадлежность языка той или иной категории влияет синтаксический сахар, а не фундаментальные возможности...

K>>Влияет синтаксический сахар и фундаментальные возможности.
E>Тогда у фундаментальных возможностях. Тот факт, что агенты на Eiffel позволяют реализовывать HOF вроде map/fold/filter и пр. что-нибудь доказывает или нет?

Вообще-то, HOF это функция, принимающая и/или возвращающая функцию. В Eiffel можно написать функцию, которая принимает/возвращает агент и агент, метод которого принимает/возвращает агент. Учитывая, что функция не тождественна агенту — и то и другое не HOF просто по определению. Это мое мнение.

E>Вот в Java, например, это без дополнительных интерфейсов и анонимных вложенных классов не сделать. А в Eiffel -- без проблем.


Ценное замечание. А почему без анонимных классов? Также можно сказать, что в Eiffel аналог Hof без агентов не сделать, а в Java с анонимными классами без проблем, хотя и с синтаксическим оверхедом. Но не вы ли в прошлом сообщении так скептически высказывались о роли синтаксического сахара?
... << RSDN@Home 1.2.0 alpha rev. 726>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[37]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 24.02.08 06:54
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Здравствуйте, eao197, Вы писали:


K>>>Понятно, что если на D можно повторить мой пример, в нем есть первоклассные функции. Откуда же мне было знать, что у нас с вами такие разные взгляды на первоклассные функции в тот момент диалога?

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

K>Я делал заявление о том, что D соответствует моему определению функционального языка в том случае, если на нем можно повторить мой пример на Nice. Это заявление чисто аналитическое и верно. Заявление о том, что мой пример можно повторить на D сделали вы. Обладая, очевидно, глубоким знанием предмета. Это утверждение синтетическое и может быть опровергнуто опытом. Опыт был проделан, код написан. Утверждение было опровергнуто этим опытом. Я поблагодарил вас оценкой за проделанный труд и посчитал, что тема закрыта. Насчет темы я ошибся.

K>Я доступно объяснил?

Да. Не объяснили только, почему вы не считаете решение на D повторением решения на Nice. Результаты тестов провалены или что?

K>Допустим, что мы ведем речь о функциях — тогда должны констатировать, что делегат в данном случае это "что-то вроде указателя на функцию в C++, но дополнительно с сохранением контекста" а вовсе не функция. Если бы функция оборачивалась в этот делегат неявно, то функция являлась бы первоклассным значением.


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

E>>А в функциональном языке функция -- это объект?


K>В общем случае это не имеет значения.


Правда? А функтор в C++ -- это значит функция? Ведь значения не имеет, что это объект, зато вызов происходит как f() -- от функции не отличить.

E>В случае Nice это просто легкий способ доказать, что функция — первоклассная сущность, принимая за данность, что объект в Nice сущность первоклассная.


Но ведь функция -- это в принципе не объект.
Значит то, что функции в Nice реализуются через объекты и детали этой реализации видны программисту, как раз показатель, что функции -- это некий довесок к объектно ориентированной системе.

E>>А вот в Nice функция -- это объект, т.е. часть не функциональной, а объектно-ориентированной системы.


K>Ну так что? В мультипарадигменных языках это распространенное решение. К моему определению это никакого отношения не имеет. Если функция — первоклассная сущность, ее можно сконструировать, передать, вернуть уже не имеет значения чем она еще является, объектом, сепулькой или шалтаем-болтаем. Все это вынесено за рамки определения и я не могу понять, на каком основании нужно отклоняться от основного направления разговора в эту сторону.


Да потому, что под вот это ваше расширенное описание попадают даже C++ функторы!

K>Если же функцию нельзя сконструировать или передать или вернуть — она не является первоклассной сущностью, даже если мы можем явно обернуть ее в объект, сепульку или шалтая-болтая, которые в этом языке равны, полноправны, но все равнее функции.


А теперь ответе: делагаты в D нельзя конструировать, передавать, возвращать, создавать из них агрегаты (в виде массивов)? Агентов в Eiffel нельзя конструировать, передавать, возвращать, создавать из них агрегаты?

K>>>>>В Eiffel агенты это объекты. Проблема не в том, что агенты — это объекты. Функции — это не агенты. А агенты — это не функции.

E>>>>Почему же это самое нельзя адресовать к Nice?
K>>>Потому, что в Eiffel функции — это не объекты. Функциональный объект конструируется явным образом и имеет отличающийся синтаксис вызова.
E>>А как же замечание, кажется, Курилки, о том, что в Erlang функциональные объекты конструируются с помощью специального ключевого слова fun?

K>Оно к делу отношения не имеет, на самом деле, как и все это циклически повторяющееся перечисление языков.


Имеет, так как к агентам Eiffel у вас было три претензии: для их конструирования нужно использовать специальное колючевое слово agent, агент является объектом и синтаксис вызова отличается от синтаксиса вызова функции. Но, если глянуть вокруг, то окажется:
— даже в функциональных языках определение определение функциональных объектов (или правильно называть их анонимными функциями?) происходит с использованием специальных ключевых слов, см.пример Erlang-а. Значит претензии к специальному синтаксису agent не обоснованны;
— в языке Nice функции так же представляются объектами и пользователь это видит, в точности как в Eiffel. Но для Nice это по-вашему проблемой не является;
— остается синтаксис вызова. Здесь да, вроде как Eiffel и Nice серьезно различаются. Хотя на практике, различие обеспечено всего лишь синтаксическим сахаром.

Но даже когда вы отказываете Eiffel-ю в праве соответствовать вашему определению, то совершенно не понятно, почему же тогда пролетает D? Ведь в D даже не объект, а отдельная сущность. Вполне себе такая первоклассная, имхо.

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


Вопрос для меня состоит не в правоте/неправоте, поскольку от этого никакого сухого материального остатка все равно не будет. Я хочу понять, почему одни языки вы считаете удовлетворяющие вашему определению, а другие (аналочиные по своим возможностям) -- нет.

K>Вообще-то, HOF это функция, принимающая и/или возвращающая функцию. В Eiffel можно написать функцию, которая принимает/возвращает агент и агент, метод которого принимает/возвращает агент. Учитывая, что функция не тождественна агенту — и то и другое не HOF просто по определению. Это мое мнение.


Т.е. в программах можно будет использовать map/fold и co, но это будет не функциональным программированием.

E>>Вот в Java, например, это без дополнительных интерфейсов и анонимных вложенных классов не сделать. А в Eiffel -- без проблем.


K>Ценное замечание. А почему без анонимных классов? Также можно сказать, что в Eiffel аналог Hof без агентов не сделать, а в Java с анонимными классами без проблем, хотя и с синтаксическим оверхедом. Но не вы ли в прошлом сообщении так скептически высказывались о роли синтаксического сахара?


А здесь дело не в синтаксическом сахаре. А в том, что в Java в принципе нельзя получить ссылку на метод в compile-time. Поэтому для выполнения каких-либо действий, например, определения критерия сортировки, в Java вводят отдельную сущность -- интерфейс Comparator, и заставляют программиста этот интерфейс реализовывать. В то время как в языках, позволяющих манипулировать функциями/указателями на функцию/делагатами/агентами не требуется никаких объектно-ориентированных сущностей для этого -- достаточно в одном месте указать прототип требуемой функции, а в другом предоставить эту функцию. И все. Более того, одна и та же функция/делегат/указатель/агент может использоваться в разных контекстах -- в одном месте для сортировки, в другом, например, для фильтрации. В то время как с интерфейсами вроде Comparator-а это не пройдет.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[38]: Функциональный/нефункциональный
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 24.02.08 09:28
Оценка:
Здравствуйте, eao197, Вы писали:

E> Более того, одна и та же функция/делегат/указатель/агент может использоваться в разных контекстах -- в одном месте для сортировки, в другом, например, для фильтрации.


Это как?
http://www.smalltalk.ru << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[38]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 24.02.08 15:35
Оценка: +1
Здравствуйте, eao197, Вы писали:

K>>Я делал заявление о том, что D соответствует моему определению функционального языка в том случае, если на нем можно повторить мой пример на Nice. Это заявление чисто аналитическое и верно. Заявление о том, что мой пример можно повторить на D сделали вы. Обладая, очевидно, глубоким знанием предмета. Это утверждение синтетическое и может быть опровергнуто опытом. Опыт был проделан, код написан. Утверждение было опровергнуто этим опытом. Я поблагодарил вас оценкой за проделанный труд и посчитал, что тема закрыта. Насчет темы я ошибся.

K>>Я доступно объяснил?
E>Да. Не объяснили только, почему вы не считаете решение на D повторением решения на Nice.

Это не правда. Я объяснил и не один раз. Возможно недостаточно доходчиво, но объяснил.
Могу попробовать обяснить еще раз. Разница между примером на Nice и примером на D заключается в том, что в D делается два явных конструирования делегата из функции.

K>>Допустим, что мы ведем речь о функциях — тогда должны констатировать, что делегат в данном случае это "что-то вроде указателя на функцию в C++, но дополнительно с сохранением контекста" а вовсе не функция. Если бы функция оборачивалась в этот делегат неявно, то функция являлась бы первоклассным значением.


E>Думаю, что для продолжения разговора, вам нужно озвучить свое определение функции


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

E>и первоклассного значения.


Также ничего экстраординарного. Фактически, это классическое определение Кристофера Срейчи, даже смягченное.
Я его несколько раз повторял выше, иллюстрировал примерами, объяснял. Оно достаточно простое.
Первоклассность некоторой сущности означает, что мы можем передать эту сущность в функцию, возвратить из функции, сконструировать в рантайм.

E>>>А в функциональном языке функция -- это объект?

K>>В общем случае это не имеет значения.
E>Правда?

Правда.

E>А функтор в C++ -- это значит функция?


Можно и так сказать — Это функция с замыканием контекста, которое сделано вручную. Замыканием лексическим или динамическим — как написали. Так что с точки зрения того кто использует функтор — это функция. С точки зрения того, кто его описывает — нет.

E>Ведь значения не имеет, что это объект, зато вызов происходит как f() -- от функции не отличить.


Да, синтаксис вызова похож на синтаксис вызова функции.
Вообще, этот вопрос тоже вполне обсуждаемый и требующий отдельного изучения, которого я не проводил, но раз вы приводите в пример функтор из C++ , вы и какие-нибудь возражения приберегли, нет? Когда вы их представите можно будет продолжить обсуждение.

E>>В случае Nice это просто легкий способ доказать, что функция — первоклассная сущность, принимая за данность, что объект в Nice сущность первоклассная.

E>Но ведь функция -- это в принципе не объект.

Неужели? Это само собой разумаеется или откуда-то следует.

E>Значит то, что функции в Nice реализуются через объекты и детали этой реализации видны программисту, как раз показатель, что функции -- это некий довесок к объектно ориентированной системе.


Довесок, привесок, навесок — хоть горшком назовите. Передать в другую функцию можно, вернуть можно, сконструировать можно, литерал есть. В моем определении нет ничего про довески, как видите.

E>>>А вот в Nice функция -- это объект, т.е. часть не функциональной, а объектно-ориентированной системы.

K>>Ну так что? В мультипарадигменных языках это распространенное решение. К моему определению это никакого отношения не имеет. Если функция — первоклассная сущность, ее можно сконструировать, передать, вернуть уже не имеет значения чем она еще является, объектом, сепулькой или шалтаем-болтаем. Все это вынесено за рамки определения и я не могу понять, на каком основании нужно отклоняться от основного направления разговора в эту сторону.
E>Да потому, что под вот это ваше расширенное описание попадают даже C++ функторы!

Экземпляр функтора в C++ это первоклассная сущность, как и экземпляр любого другого типа. Правда, функция и функтор все же не одно и то же. Различия между декларацией функции и класса с перегруженным оператором () найдете?

K>>Если же функцию нельзя сконструировать или передать или вернуть — она не является первоклассной сущностью, даже если мы можем явно обернуть ее в объект, сепульку или шалтая-болтая, которые в этом языке равны, полноправны, но все равнее функции.

E>А теперь ответе: делагаты в D нельзя конструировать, передавать, возвращать, создавать из них агрегаты (в виде массивов)? Агентов в Eiffel нельзя конструировать, передавать, возвращать, создавать из них агрегаты?

Вообще-то в процитированном вами абзаце уже содержиться ответ на ваше возражение. Но если вам так интереснее можно продолжать в этом же духе.
Делегаты — можно. Агенты — можно. Функции — нельзя.

K>>Оно к делу отношения не имеет, на самом деле, как и все это циклически повторяющееся перечисление языков.


E>Имеет, так как к агентам Eiffel у вас было три претензии:


У меня нет никаких претензий к агентам. У меня претензии к функциям.

E>для их конструирования нужно использовать специальное колючевое слово agent,


Меня не волнуют ключевые слова. Я обращал внимание на то, что функция оборачивается в агент явно.

E>агент является объектом и синтаксис вызова отличается от синтаксиса вызова функции.


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

E>- даже в функциональных языках определение определение функциональных объектов (или правильно называть их анонимными функциями?) происходит с использованием специальных ключевых слов, см.пример Erlang-а. Значит претензии к специальному синтаксису agent не обоснованны;


Во-первых, мне кажется, что вы недостаточно внимательно читали мое сообщение. Еще раз:

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

Я не считаю себя компетентным в вопросах связанных с эрлангом, но насколько я знаю, никакого преобразования функций в "функциональный объект" там делать не надо. Нам нужно явно указывать что атом — это функция (сам динамический язык этого, видимо узнать в общем случае не может), впрочем, если мне память не изменяет, передача кортежа из атома-имени модуля и атома-имени функции — работает.

E>- в языке Nice функции так же представляются объектами и пользователь это видит, в точности как в Eiffel. Но для Nice это по-вашему проблемой не является;

E>- остается синтаксис вызова. Здесь да, вроде как Eiffel и Nice серьезно различаются. Хотя на практике, различие обеспечено всего лишь синтаксическим сахаром.
E>Но даже когда вы отказываете Eiffel-ю в праве соответствовать вашему определению, то совершенно не понятно, почему же тогда пролетает D? Ведь в D даже не объект, а отдельная сущность. Вполне себе такая первоклассная, имхо.

см. выше.

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


E>Вопрос для меня состоит не в правоте/неправоте, поскольку от этого никакого сухого материального остатка все равно не будет. Я хочу понять, почему одни языки вы считаете удовлетворяющие вашему определению, а другие (аналочиные по своим возможностям) -- нет.


Мы вообще-то про классификацию говорим, а не про возможности. Я же говорил про конвергентные фичи. Если бы класифицировали по возможностям — дельфин был бы рыбой, раз он плавает под водой и на рыбу похож. Вот только дельфин — не рыба, а схожесть объясняется конвергенцией.

K>>Вообще-то, HOF это функция, принимающая и/или возвращающая функцию. В Eiffel можно написать функцию, которая принимает/возвращает агент и агент, метод которого принимает/возвращает агент. Учитывая, что функция не тождественна агенту — и то и другое не HOF просто по определению. Это мое мнение.

E>Т.е. в программах можно будет использовать map/fold и co, но это будет не функциональным программированием.

Функциональное программирование — это способ декомпозиции. Программировать функционально можно на нефункциональном языке. Точно также как применять ОО-декомпозицию можно при написании ОО программ на C.

E>А здесь дело не в синтаксическом сахаре. А в том, что в Java в принципе нельзя получить ссылку на метод в compile-time. Поэтому для выполнения каких-либо действий, например, определения критерия сортировки, в Java вводят отдельную сущность -- интерфейс Comparator, и заставляют программиста этот интерфейс реализовывать.


Какая же это отдельная сущность?

E>В то время как в языках, позволяющих манипулировать функциями/указателями на функцию/делагатами/агентами не требуется никаких объектно-ориентированных сущностей для этого -- достаточно в одном месте указать прототип требуемой функции, а в другом предоставить эту функцию.


В языках, позволяющих манипулировать функциями — да. А в остальных, делегаты и агенты как раз и являются ОО-сущностями для этого.

E>И все. Более того, одна и та же функция/делегат/указатель/агент может использоваться в разных контекстах -- в одном месте для сортировки, в другом, например, для фильтрации.


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

E>В то время как с интерфейсами вроде Comparator-а это не пройдет.


Вместо интерфейса компаратора —
interface IAgent<T, U, V>
{
    V call(T a, U b);
}

Такой же "функциональный тип" как и агент — ничуть не хуже. Более громоздкий синтаксис при оборачивании функции — да. Но факт явного оборачивания в обоих случаях — налицо. Использование вообще ничем не отличается.
... << RSDN@Home 1.2.0 alpha rev. 726>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[39]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.02.08 08:16
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Здравствуйте, eao197, Вы писали:


E>> Более того, одна и та же функция/делегат/указатель/агент может использоваться в разных контекстах -- в одном месте для сортировки, в другом, например, для фильтрации.


ANS>Это как?


Ну на счет сортировки и фильтрации -- это я, наверное, со зла.
Хотя, наверное, если брать сортировку, где предикат должен возвращать значения меньше нуля, ноль, больше нуля, то в качестве предиката может выступать operator-(a,b). А в другом месте этот же оператор будет использоваться для выполнения арифметических операций.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[39]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.02.08 09:58
Оценка:
Здравствуйте, Klapaucius, Вы писали:

E>>Да. Не объяснили только, почему вы не считаете решение на D повторением решения на Nice.


K>Это не правда. Я объяснил и не один раз. Возможно недостаточно доходчиво, но объяснил.

K>Могу попробовать обяснить еще раз. Разница между примером на Nice и примером на D заключается в том, что в D делается два явных конструирования делегата из функции.

Здесь происходит что-то, что находится за гранью моего понимания. Поскольку форма явно доминирует над содержанием. Продемонстрирую это.
В Nice для декларации типа функции используется синтаксис:
(список аргументов)->тип результата

В D этот же самый эффект достигается с помощью синтаксиса:
тип результата delegate(список аргументов)

Разница только в порядке элементов и использовании delegate вместо ->.
Далее, запись в Nice:
T p => D

это всего лишь сокращенный вариант для:
(T p) => { return D; }

Что соответствует в D:
(T p) { return D; }

При этом синтаксис Nice не позволяет указать для анонимной функции тип возвращаемого значения (он выводится), тогда как D может это сделать при использовании ключевого слова delegate. Т.е. запись в D:
delegate V(T p) { return D; }

могла бы быть эквивалентом следующей конструкции в Nice:
(T p)->V => { return D; }
// или же
(T p)->V => D

если бы Nice допускал синтаксис (args)->R при определении анонимной функции. Однако, суть не в том, что Nice не позволяет делать это, а в том, что в Nice конструкция => играет ту же самую роль, что и ключевое слово delegate в D.

Исходя из вышеизложенного, приведенный вами первоначально пример curry на Nice:
<T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);

является ничем иным, как сокращенной формой для:
<T, U, V>
T->(U->V) curry((T,U)->V func) {
    return (T parm1) => {
        return (U parm2) => {
            return func(parm1, parm2); }; };
}

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

Что же касается D, то вариант:
import std.stdio;

V delegate(U) delegate(T) curry(T, U, V)( V delegate(T, U) func )
  {
    return (T a) { return (U b) { return func(a, b); }; };
  }

void main()
  {
    int x = curry( ( int a, int b ) { return a + b; } )( 3 )( 2 );
    writefln( "x=", x );
  }

Практически один в один копирует вариант на Nice, учивая, что:
V delegate(U) delegate(T)

это D-шный вариант Nice-вского
T->(U->V)

А D-шный:
V delegate(T, U) func

это то же самое, что в Nice:
(T, U)->V func

(просто другой порядок следования элементов и -> вместо delegate).

Далее, по поводу конструирования делегата. Если в Nice есть код:
int->int demo()
    {
        int inc( int a ) = a + 1;
        return inc;
    }

то при возврате inc, Nice конструирует объект, который будет выполнять вызов inc. В точности то же самое происходит в D при записи:
int delegate(int) demo()
    {
        int inc( int a ) { return a + 1; }
        return &inc;
    }

Явное конструирование делегата с помощью &, на котором вы акцентируете внимание, не является показателем ущербности поддержки функций в D по сравнению с Nice. Это всего лишь показатель того, что в D используется более последовательный подход к вызову методов без аргументов. Так, в D:
class Demo {
    int f() { return 0; }
    int demo() { return f; }
}

внутри Demo.demo() обращение к f -- это всегда вызов метода/функции с именем f без параметров.
Тогда как в Nice:
class Demo {
    int f() { return 0; }
    int demo() { return f; }
}

возникает ошибка, т.к. Demo.demo() возвращает функцию (Demo)->int. Но стоит чуть изменить код:
class Demo {
    int f() { return 0; }
    int demo() { return this.f; }
}

как оказывается, что возвращается не функция, а результат вызова метода f. Но в D такой непоследовательности нет: 'f;' и 'this.f;' всегда означают одно и то же. Точно так же в D:
void demo() {
  void endl() { writefln; }
  endl;
}

обращение к endl -- это всегда вызов. Тогда как в Nice:
void demo() {
  void endl() { println(); }
  endl;
}

обращение к endl -- это синтаксическая ошибка (однако, если бы endl был бы методом какого-то объекта, то вызов 'o.endl;' прошел бы). Поэтому-то я и не считаю, что использования & в D является признаком какой-то ущербности -- это всего лишь способ заставить пользователя явно указывать на то, что он хочет -- вызвать функцию или получить ссылку на функцию.

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

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[39]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 25.02.08 09:59
Оценка:
Здравствуйте, Klapaucius, Вы писали:

E>>В то время как с интерфейсами вроде Comparator-а это не пройдет.


K>Вместо интерфейса компаратора -

K>
K>interface IAgent<T, U, V>
K>{
K>    V call(T a, U b);
K>}
K>

K>Такой же "функциональный тип" как и агент — ничуть не хуже. Более громоздкий синтаксис при оборачивании функции — да. Но факт явного оборачивания в обоих случаях — налицо. Использование вообще ничем не отличается.

Попробуйте передать реализацию этого интерфейса в конструктор TreeMap или в метод Arrays.sort вместо Comparator-а.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[40]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 25.02.08 17:33
Оценка: 6 (1) +1 -2
Здравствуйте, eao197, Вы писали:

К чему эти многословные рассуждения о синтаксисе декларации функциональных типов и делегатов? Зачем обсуждение синтаксиса литералов для функций в Nice и делегатов в D? Разве это предмет обсуждения?

E>
E>import std.stdio;

E>V delegate(U) delegate(T) curry(T, U, V)( V delegate(T, U) func )
E>  {
E>    return (T a) { return (U b) { return func(a, b); }; };
E>  }

E>void main()
E>  {
E>    int x = curry( ( int a, int b ) { return a + b; } )( 3 )( 2 );
E>    writefln( "x=", x );
E>  }
E>

E>Практически один в один копирует вариант на Nice

По форме, но не по содержанию. Разница между D и Nice в том, что "лямбда" в D это литерал для делегата, а не для функции, как в Nice. Снова повторяю, то, что делегат — сущность первоклассная я не отрицал, не отрицаю и отрицать не собираюсь. Функция же — сущность не первоклассная — вернуть ее из функции нельзя.
Если бы можно было написать так:
 V finalResult( U b )
    {
        return func( a, b );
    }
return finalResult;

Было бы очевидно, что функцию вернуть можно.
Тем не менее, ее приходится явным образом оборачивать в делегат, который, естественно, можно вернуть:
return &finalResult;

Что в этом непонятного?

E>Явное конструирование делегата с помощью &, на котором вы акцентируете внимание, не является показателем ущербности поддержки функций в D по сравнению с Nice.


К чему все эти эмоционально окрашенные слова вроде "ущербности"? Явное конструирование является показателем того, что функцию нельзя вернуть без явного преобразования. Также это показатель того, что функция и делегат — разные сущности. В Nice никакие делегаты не нужны — как раз потому, что функции — первоклассные. И тип возвращаемого значения там — функциональный тип, а не тип делегата. Вы же не вынуждены оборачивать числов какое-то траляля для того, чтобы вернуть его из функции, верно? А функцию оборачивать вынуждены — эта ситуация и называется первоклассностью числа и непервоклассностью функции. Это вопрос терминологии, а не личной обиды.

E>Это всего лишь показатель того, что в D используется более последовательный подход к вызову методов без аргументов. Так, в D:

E>
E>class Demo {
E>    int f() { return 0; }
E>    int demo() { return f; }
E>}
E>

E>внутри Demo.demo() обращение к f -- это всегда вызов метода/функции с именем f без параметров.
E>Тогда как в Nice:
E>
E>class Demo {
E>    int f() { return 0; }
E>    int demo() { return f; }
E>}
E>

E>возникает ошибка, т.к. Demo.demo() возвращает функцию (Demo)->int. Но стоит чуть изменить код:
E>
E>class Demo {
E>    int f() { return 0; }
E>    int demo() { return this.f; }
E>}
E>

E>как оказывается, что возвращается не функция, а результат вызова метода f. Но в D такой непоследовательности нет: 'f;' и 'this.f;' всегда означают одно и то же. Точно так же в D:
E>
E>void demo() {
E>  void endl() { writefln; }
E>  endl;
E>}
E>

E>обращение к endl -- это всегда вызов. Тогда как в Nice:
E>
E>void demo() {
E>  void endl() { println(); }
E>  endl;
E>}
E>

E>обращение к endl -- это синтаксическая ошибка (однако, если бы endl был бы методом какого-то объекта, то вызов 'o.endl;' прошел бы). Поэтому-то я и не считаю, что использования & в D является признаком какой-то ущербности -- это всего лишь способ заставить пользователя явно указывать на то, что он хочет -- вызвать функцию или получить ссылку на функцию.

Об этом мы уже говорили в случае с Eiffel — это выбор между устранением непоследовательности и первоклассностью функций. Дизайнеры Eiffel и D выбрали устранение непоследовательности, а дизайнер Nice — первоклассные функции.
Никакой ущербности здесь нет — здесь выбор у которого есть свои сильные стороны и свои недостатки — только и всего. В данном случае разница настолько незначительная, что с практической точки зрения существенного значения не имеет — но если мы решаем проблему классификации и демаркации — границу надо где-то проводить — и я провожу ее именно здесь.

E>А посему я могу констатировать: вы защищается определение, которое можно считать _необходимым_ для признания того или иного языка функциональным. Но которое вряд ли является _достаточным_ для этого.


Я считаю первоклассность функций не только необходимым, но и достаточным условием. Если вы так не считаете — сформулируйте свое определение.

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


Все это жонглирование псевдофилософскими понятиями вроде "формы" и "содержания" ничего не дает. Что есть форма — синтаксис? Но есть ли основания считать синтаксис менее важным в данном вопросе, чем, например, семантика? Я таких оснований пока не вижу. Кроме того, рассуждая о моем принебрежении содержанием (семантикой?) сами отказываетесь видеть, что семантика функции и, например, делегата в D различна. "Вещи" которые "скрываются" под сущностями того или иного языка — могут быть одними и теми же либо различными, но в системе определений, которые не имеют отношения к языку.
Еще раз, можно сказать, что агенты — это просто, по сути своей, подмножество анонимных классов из Java — что же мешает в таком случае считать функции в Java первоклассными? Ограничения агентов в сравнении с анонимными классами?
... << RSDN@Home 1.2.0 alpha rev. 726>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[40]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 25.02.08 17:33
Оценка:
Здравствуйте, eao197, Вы писали:

K>>Вместо интерфейса компаратора -

K>>
K>>interface IAgent<T, U, V>
K>>{
K>>    V call(T a, U b);
K>>}
K>>

K>>Такой же "функциональный тип" как и агент — ничуть не хуже. Более громоздкий синтаксис при оборачивании функции — да. Но факт явного оборачивания в обоих случаях — налицо. Использование вообще ничем не отличается.

E>Попробуйте передать реализацию этого интерфейса в конструктор TreeMap или в метод Arrays.sort вместо Comparator-а.


Вы о чем? Попробуете передать в Eiffel агента через параметр со строковым типом, или так понятно что будет? Я показал, как делаются агенты в Java — то что стандартная библиотека их сейчас не поддерживает — другой вопрос.
... << RSDN@Home 1.2.0 alpha rev. 726>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[41]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.02.08 08:31
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Здравствуйте, eao197, Вы писали:


K>К чему эти многословные рассуждения о синтаксисе декларации функциональных типов и делегатов? Зачем обсуждение синтаксиса литералов для функций в Nice и делегатов в D? Разве это предмет обсуждения?


Нет не предмет. Для вас. Поскольку вы считаете, что раз в Nice что-то называется функцией, значит это функция. А если это же самое называется в другом языке делегатом, то это не функция.

Хотя разницу между ними найти лично мне очень тяжело.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[41]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.02.08 08:53
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Здравствуйте, eao197, Вы писали:


K>>>Вместо интерфейса компаратора -

K>>>
K>>>interface IAgent<T, U, V>
K>>>{
K>>>    V call(T a, U b);
K>>>}
K>>>

K>>>Такой же "функциональный тип" как и агент — ничуть не хуже. Более громоздкий синтаксис при оборачивании функции — да. Но факт явного оборачивания в обоих случаях — налицо. Использование вообще ничем не отличается.

E>>Попробуйте передать реализацию этого интерфейса в конструктор TreeMap или в метод Arrays.sort вместо Comparator-а.


K>Вы о чем? Попробуете передать в Eiffel агента через параметр со строковым типом, или так понятно что будет? Я показал, как делаются агенты в Java — то что стандартная библиотека их сейчас не поддерживает — другой вопрос.


Знаете, чем отличается математика от программирования? Это в математике можно показать способ решения какого-то класса задач и считать эту задачу решенной, а все остальное -- другой вопрос. В программировании мало показать способ -- нужно написать _работающую_ программу -- без программы нет решения. И это не другой -- это самый важный вопрос.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[32]: Функциональный/нефункциональный
От: VoidEx  
Дата: 26.02.08 10:16
Оценка:
Здравствуйте, eao197, Вы писали:

E>А я смотрю на Nice-вый код:

E>
E>void main( String[] args )
E>  {
E>    let f = () => println( "Hello!" );
E>    let g = f;
E>    println( "g and f are: " + ( g == f ? "same" : "different" ) );
E>    println( f.getClass().getName() );
E>  }
E>

E>и результат запуска:
E>
E>gnu.expr.ModuleMethod
E>g and f are: same
E>

E>и вижу, что f и g всего лишь ссылки на объект. Они подчиняются правилам ссылок. У объекта, который содержит анонимную функцию, есть обычные методы объекта.

У меня назрел вопрос в связи с незнанием Nice.

void foo () { println("Hello!"); }

void main (String[] args)
{
  println (foo.getClass().getName() );
}


Прокатит? И выведет то же, что и для

let f = () => println("Hello!");


?
Re[42]: Функциональный/нефункциональный
От: dr.Chaos Россия Украшения HandMade
Дата: 26.02.08 10:55
Оценка:
eao197 wrote:

> Нет не предмет. Для вас. Поскольку вы считаете, что раз в Nice что-то

> называется функцией, значит это функция. А если это же самое называется в
> другом языке делегатом, то это не функция.
>
> Хотя разницу между ними найти лично мне очень тяжело.

ИМХО эта разница примерно такая же, как между переменной и ссылкой на неё. В
С++ это две разные сущности, хотя и могут применяться для решения одной и
той же задачи.

Мне не понятно во что ты упёрся. Ведь в Ди делегат и функция две разных
сущности, а в Nice есть только функция. Реализовано это может быть через
объекты, но это особенность реализации с которой программист не почти
сталкивается. Это может быть важно с точки зрения практики, но определение
функционального языка имеет к практике весьма отдалённое отношение к
практике ИМХО. Например, в любом языке, который поддерживает замыкания
аргументов функции, можно реализовать построение списка исключительно на
функциях. С точки зрения практики это важно (не эффективно), с точки зрения
языка — без разницы, главное cons,car и cdr есть и список на них построить
можно.

Да и определение Klapaucius основывается на FCO, т.е., грубо говоря, на том,
что в языке первично объект или функция. Для Ди это объект, для Nice и
объект и функция, т.к. это смешанный язык.
Posted via RSDN NNTP Server 2.1 beta
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[43]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.02.08 11:50
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

>> Нет не предмет. Для вас. Поскольку вы считаете, что раз в Nice что-то

>> называется функцией, значит это функция. А если это же самое называется в
>> другом языке делегатом, то это не функция.
>>
>> Хотя разницу между ними найти лично мне очень тяжело.

DC>ИМХО эта разница примерно такая же, как между переменной и ссылкой на неё. В

DC>С++ это две разные сущности, хотя и могут применяться для решения одной и
DC>той же задачи.

Я бы уточнил: разница как между объектом и ссылкой на него в таких языках, как Java/C#/D и др. Объект живет сам по себе, но обратиться к нему можно только через ссылку. И переменные в таких языках содержат не объекты, а ссылки на них.

DC>Мне не понятно во что ты упёрся. Ведь в Ди делегат и функция две разных

DC>сущности, а в Nice есть только функция.

Вот именно в это и уперся. Поскольку в таких языках, как D и Nice функция -- это блок кода, реализующий функцию. Вызвать этот блок можно двумя способами: либо написав в коде обращение функции через ее имя (непосредственный вызов), либо получив ссылку на функцию. Но что такое ссылка? Это указатель на сам код + некий контекст, на котором этот код будет работать.

Так вот, в Nice:
void demo() {
  let f = () => println();
}

f -- это функция или все-таки ссылка на функцию? Как я показал в одном из примеров, f -- это ссылка.
А в D:
void demo() {
  auto f = () { writefln(); };
}

f -- это такая же ссылка с точно такими же возможностями.

Если бы в Nice ссылки на функции и сами функции были одним и тем же понятием, то между непосредственным вызовом функции и вызовом через ссылку не должно быть разницы. Но ведь разница-то есть. Вот такой простой пример:
void demo() {
    println( "Hello!" );
}

void main( String[] args ) {
    println( "calling demo..." );
    demo();
    println( "converting demo to function reference..." );
    let f = demo;
    println( "calling demo via reference..." );
    f();
}

Разворачивается в:
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 

package t2;


// Referenced classes of package t2:
//            fun

public class dispatch
{

    public static void main(String args[])
    {
        try
        {
            fun.main(args);
            return;
        }
        catch(Throwable uncaughtException)
        {
            nice.lang.dispatch.printStackTraceWithSourceInfo(uncaughtException);
        }
        System.exit(1);
    }

    public static void demo()
    {
        fun.demo();
    }

    public dispatch()
    {
    }
}
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 

package t2;

import gnu.expr.ModuleBody;
import gnu.expr.ModuleMethod;
import gnu.mapping.Procedure;
import nice.lang.dispatch;

// Referenced classes of package t2:
//            dispatch

public class fun extends ModuleBody
{

    public static void main(String args[])
    {
        dispatch.println("calling demo...");
        dispatch.demo();
        dispatch.println("converting demo to function reference...");
        Procedure f = demo;
        dispatch.println("calling demo via reference...");
        f.apply0();
    }

    public static void demo()
    {
        dispatch.println("Hello!");
    }

    public fun()
    {
    }

    public Object apply0(ModuleMethod modulemethod)
    {
        while(modulemethod.selector != 1) 
            throw new RuntimeException("bad case value!");
        dispatch.demo();
        return null;
    }

    public static final Procedure demo;
    public static final fun $instance;

    static 
    {
        $instance = new fun();
        demo = new ModuleMethod($instance, 1, "demo", 0);
    }
}


Т.е. разница в том, что в D ссылки на функции называются делегатами, а в Nice они называются функциями. Т.е. дело только в названии.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.