Функциональный/нефункциональный
От: Klapaucius  
Дата: 01.02.08 16:30
Оценка: 40 (2) :)
Здравствуйте, eao197, Вы писали:

E>Nice -- не функциональный язык программирования.


Гм...

Для тех, кто интересуется фактами, приведу пример кода на нефункциональном языке Nice
<T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);

void main(String[] args) = println(curry((int a, int b) => a + b)(2)(2));


C:\Nice>nicec -a curry.jar curry
nice.lang: parsing
curry: parsing
curry: typechecking
curry: generating code
curry: linking
curry: writing in archive
nice.lang: writing in archive

C:\Nice>java -jar curry.jar
4
... << RSDN@Home 1.2.0 alpha rev. 726>>

01.03.08 23:30: Ветка выделена из темы C++0x начали урезать
Автор: Andrei F.
Дата: 09.11.07
— AndrewVK
'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: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 01.02.08 16:33
Оценка: -1 :)
Здравствуйте, Klapaucius, Вы писали:

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


E>>Nice -- не функциональный язык программирования.


K>Гм...


K>Для тех, кто интересуется фактами, приведу пример кода на нефункциональном языке Nice

K>
K><T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);

K>void main(String[] args) = println(curry((int a, int b) => a + b)(2)(2)); 
K>


Ну а паттерн-матчинг где?


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

K>>Для тех, кто интересуется фактами, приведу пример кода на нефункциональном языке Nice

K>>
K>><T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);

K>>void main(String[] args) = println(curry((int a, int b) => a + b)(2)(2)); 
K>>


E>Ну а паттерн-матчинг где?


Где имение? Где вода? Есть мнение, причем не только мое, что для того, чтобы язык являлся функциональным необходимы и достаточны функции, как первоклассные объекты, а значит и функции высокого порядка. И то и другое я продемонстрировал.
Quod erat, как говорится, demonstrandum.
Далее спор может продолжаться только как терминологический.
... << 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: Функциональный/нефункциональный
От: deniok Россия  
Дата: 01.02.08 17:00
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Гм...


K>Для тех, кто интересуется фактами, приведу пример кода на нефункциональном языке Nice

K>
K><T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);

K>void main(String[] args) = println(curry((int a, int b) => a + b)(2)(2)); 
K>


А вывести тип int умеет?
Re[3]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 01.02.08 17:05
Оценка: -1
Здравствуйте, Klapaucius, Вы писали:

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


K>>>Для тех, кто интересуется фактами, приведу пример кода на нефункциональном языке Nice

K>>>
K>>><T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);

K>>>void main(String[] args) = println(curry((int a, int b) => a + b)(2)(2)); 
K>>>


E>>Ну а паттерн-матчинг где?


K>Где имение? Где вода? Есть мнение, причем не только мое, что для того, чтобы язык являлся функциональным необходимы и достаточны функции, как первоклассные объекты, а значит и функции высокого порядка. И то и другое я продемонстрировал.

K>Quod erat, как говорится, demonstrandum.
K>Далее спор может продолжаться только как терминологический.

А как же немутабельные объекты?
А как же все возвращает значение? Скажем if в Scala и OCaml имеет свое значение и можно написать что-то типа:
let x = if( a ) b else c


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

Да и сам автор не причисляет Nice к функциональным языкам.


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

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


K>>Гм...


K>>Для тех, кто интересуется фактами, приведу пример кода на нефункциональном языке Nice

K>>
K>><T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);

K>>void main(String[] args) = println(curry((int a, int b) => a + b)(2)(2)); 
K>>


D>А вывести тип int умеет?


Насколько я знаю, типы аргументов в функциях в Nice нужно указывать явно. Так же, как и в туплах.


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

<T, U, V> T->U->V curry((T,U)->V func) = T parm1 => U parm2 => func(parm1, parm2);
void main(String[] args) = println(curry((int a, int b) => a + b)(2)(2));


D>А вывести тип int умеет?


Не умеет, но это только мое мнение. Дело в том, что я по Nice, мягко говоря, не специалист, а компилятор не блещет умом и сообразительностью рапортуя об ошибках. Сначала я написал без int, но получив такой вот рапорт
Encountered ", b ) =>".
Was expecting one of:
    "->" ...
    "?" ...
    <IDENT> ...
    "[]" ...
    "[?]" ...
    "." ...
    "<" ...
    "," "?" ...
    "," "!" ...
    "," "(" ...
    "," "alike" ...
    "," <IDENT> "." ...
    "," <IDENT> "<" ...
    "," <IDENT> "[]" ...
    "," <IDENT> "[?]" ...
    "," <IDENT> "?" ...
    "," <IDENT> "->" ...
    "," <IDENT> "," ...
    "," <IDENT> ")" "?" ...
    "," <IDENT> ")" "->" ...
    "," <IDENT> ")" "[]" ...
    "," <IDENT> ")" "[?]" ...
    "," <IDENT> ")" <IDENT> ...
    "(" ...
    ">" ...
    "," <IDENT> "(" ...
    "," <IDENT> <IDENT> ...
    "," <IDENT> ">" ...
    "," <IDENT> "!" ...
    "," <IDENT> "alike" ...
    "," <IDENT> ")" "=>" ...

compilation failed with 1 error

решил не связываться.
... << 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[3]: Функциональный/нефункциональный
От: WolfHound  
Дата: 01.02.08 18:17
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Сначала я написал без int, но получив такой вот рапорт

K>
ужос поскипан
K>

Мдя... даже в ошибках С++ных меташаблонов разобраться легче.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 04.02.08 13:50
Оценка: +1 :))
Здравствуйте, eao197, Вы писали:

E>А как же немутабельные объекты?

E>А как же все возвращает значение?

См. выше.

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


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

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


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

E>Да и сам автор не причисляет Nice к функциональным языкам.


Позиционирование имеет значение в данном случае? Если позиционировать грейпфрут как лимон с "человеческим лицом", означает ли это, что это уже не грейпфрут?
... << 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[5]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 04.02.08 14:07
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


E>>А как же немутабельные объекты?

E>>А как же все возвращает значение?

K>См. выше.


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


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

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


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


Чуть-чуть пострашнее, но ведь исходному определению функционального языка это же не мешат, не так ли?
import std.stdio;

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

    return &intermediateResult;
  }

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

// vim:ts=2:sts=2:sw=2:expandtab


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

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


Если вы все-таки желаете углубиться в терминологический спор, то приведите ваше определение функционального языка. Я свое определение привел и Nice полностью соответствует этому определению. То что предлагаете вы это простое перечисление совершенно несвязанных фич, и совершенно непонятно где оно должно начаться, а где закончится. Кто принимает решение входят ли в этот набор list comprehensions или классы типов? С таким же успехом можно утверждать что Java не является объектно ориентированным языком потому, что в ней нет мультиметодов, трейтсов и абстрактных интерфейсов a la тот же Nice. Безусловно, пищу для безудержного флейма на сто мореходных верст мелкими буквами такой подход дает, но я человек недостаточно прилежный или усидчивый чтобы принимать в нем участие заметное время.

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

E>боюсь, вы останетесь единственным, кто считает Nice функциональным языком.


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

Продолжать эту ветку не обещаю, не сочтите за неуважение — просто продолжительное участие в терминологическом споре в мои планы не входит. Прочитав о том, что Nice де язык не функциональный, я просто продемонстрировал некоторые факты, которые могут показаться читателю форумов более полезными чем простое препирательство нет-да-нет-да-нет-да. Ознакомившись с приведенным мной кодом каждый может сам сделать для себя вывод по этому вопросу. Имеющий глаза да увидит.
... << 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[7]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.02.08 08:55
Оценка: +1
Здравствуйте, Klapaucius, Вы писали:

K>Короче говоря, ваша позиция по этому вопросу мне не ясна.


Кажется, Страуструп сказал, что язык программирования поддерживает какую-то парадигму (да не обидится на меня Гена Васильев) только если язык поддерживает необходимые средства для использования этой парадигмы при программировании на этом языке. Например, поэтому язык C не считается ООЯ, хотя он и позволяет писать программы в стиле ООП. Поскольку по сравнению с ООЯ в C нужно прикладывать слишком много усилий для поддержки ООП.

Точно так же я смотрю и на функциональное программирование. Ключевым моментом в котором для меня является неизменяемость данных. Данные не изменяются и это делает возможным такие замечательные вещи, как прозрачный параллелизм без лишних синхронизаций, упрощенное тестирование, возможность при отладке возвращаться на произвольное число шагов (однако, лучше заглянуть сюда
Автор(ы): Вячеслав Ахмечет
Дата: 16.09.2006
Данная статья достаточно кратко и вполне доступно, используя примеры на Java (!), знакомит читателя с базовыми понятиями функционального программирования.
).

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

хвостовая рекурсия, которая позволяет выражать циклы без использования переменных цикла. Например, вот так:
void
readLines( boolean showGoodMessages )
  {
    let stdin = new BufferedReader( new InputStreamReader( System.in ) );
    void readAndProcessLine( String line )
      {
        if( line != null )
          {
            parseLine( line, showGoodMessages );
            readAndProcessLine( readLine( stdin ) );
          }
      }
    readAndProcessLine( readLine( stdin ) );
  }

вместо императивного:
void
readLines( boolean showGoodMessages )
  {
    let stdin = new BufferedReader( new InputStreamReader( System.in ) );
    var line = readLine( stdin );
    while( line != null )
      {
        parseLine( line, showGoodMessages );
        line = readLine( stdin );
      }
  }


иммутабельность данных, которая запрещает не только назначать переменным новые значения, но и запрещает изменять атрибуты уже собственных значений. Например, в OCaml для этого есть специальная синтаксическая конструкция, которая указывает при обращении к методу объекта создавать копию объекта с модифицированным значением:
class point =
  object
    val pos = 0
    method get = pos
    method set pos’ = {< pos = pos’ >}
  end;;


Отдельно стоит сказать еще и о паттерн-матчинге. На мой взгляд, это не обязательная фича для функциональных языков. Но, поскольку в функциональном подходе для поддержки иммутабельности данных и отсутствия побочных эффектов широко применяется возврат значений в виде разнообразных туплов, то паттерн-матчинг является черезвычайно удобным механизмом для работы в таком стиле. Ярким примером из Scala является тип Some, работа с котором строится через паттерн-матчинг.

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

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

E>>боюсь, вы останетесь единственным, кто считает Nice функциональным языком.


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


Недостатком вашего определения является его поверхностность. Под него, по большому счету, не только D, но и C попадает. Т.к. в C указателями на функции можно манипулировать так же, как и экземплярами любых других данных.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: Функциональный/нефункциональный
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 05.02.08 12:49
Оценка:
Здравствуйте, eao197, Вы писали:

E>хвостовая рекурсия, которая позволяет выражать циклы без использования переменных цикла.


Ну, надо сказать, чтобы с помощью ФЯ выразить подобие цикла в ИЯ, можно использовать рекурсию вообще. То, что некоторые языки оптимизируют хвостовую рекурсию, разворачивая её в цикл — это лишь детали реализации. С таким же успехом я могу сказать, что если оптимизатор не умеет делать линеаризации при необходимости (это, например, вынуждает вручную делать рекурсию концевой при вычислении факториала), то язык не является функциональным. Кроме того, разворачивание концевой рекурсии имеет сомнительную полезность в случае, если язык имеет ленивую семантику, и компилится во что-то вроде g-машины или категориальной машины (собственно, я вообще не представляю как это сделать в данном случае).
... << RSDN@Home 1.2.0 alpha rev. 672>>
Re[9]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.02.08 13:01
Оценка:
Здравствуйте, konsoletyper, Вы писали:

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


E>>хвостовая рекурсия, которая позволяет выражать циклы без использования переменных цикла.


K>Ну, надо сказать, чтобы с помощью ФЯ выразить подобие цикла в ИЯ, можно использовать рекурсию вообще.


И эта попытка завершается выходом за пределы стека при большом количестве итераций. Я привел примеры из программы на языке Nice для обработки текстовых файлов большого объема. Вариант с рекурсией ломался где-то после 3000-ысячной строки, а требовалось обрабатывать миллионы строк.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[9]: Функциональный/нефункциональный
От: deniok Россия  
Дата: 05.02.08 14:06
Оценка:
Здравствуйте, konsoletyper, Вы писали:

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


E>>хвостовая рекурсия, которая позволяет выражать циклы без использования переменных цикла.


K>Ну, надо сказать, чтобы с помощью ФЯ выразить подобие цикла в ИЯ, можно использовать рекурсию вообще. То, что некоторые языки оптимизируют хвостовую рекурсию, разворачивая её в цикл — это лишь детали реализации. С таким же успехом я могу сказать, что если оптимизатор не умеет делать линеаризации при необходимости (это, например, вынуждает вручную делать рекурсию концевой при вычислении факториала), то язык не является функциональным. Кроме того, разворачивание концевой рекурсии имеет сомнительную полезность в случае, если язык имеет ленивую семантику, и компилится во что-то вроде g-машины или категориальной машины (собственно, я вообще не представляю как это сделать в данном случае).


В G-машине, как я понимаю, это так и будет в виде циклического thunk'а храниться — будет немножко больше косвенности при обращении к аргументам (разыменование указателей). Но это — небольшая плата за приспособление к фон-неймановской архитектуре
Re[10]: Функциональный/нефункциональный
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 05.02.08 15:16
Оценка: +3
Здравствуйте, eao197, Вы писали:

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


Это проблема конкретной реализации. Никто не мешал сделать компилятор с данной оптимизацией, либо юзать велосипедный стек, который этого не боится. Но это никак не относится к тому, что язык является функциональным или нет.
... << RSDN@Home 1.2.0 alpha rev. 672>>
Re[11]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.02.08 15:24
Оценка: +1 -2
Здравствуйте, konsoletyper, Вы писали:

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


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


K>Это проблема конкретной реализации.


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

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


Я вот не понимаю. Допустим, язык Scala поддерживает хвостовую рекурсию. Может ли существовать компилятор Scala, не поддерживающий эту оптимизацию?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[12]: Функциональный/нефункциональный
От: konsoletyper Россия https://github.com/konsoletyper
Дата: 05.02.08 17:00
Оценка: +2
Здравствуйте, eao197, Вы писали:

K>>Это проблема конкретной реализации.


E>Есть единственная реализация языка в виде единственного компилятора. Отсутствие хвостовой рекурсии в этой реалиции оставляет возможность только абстрактных разговоров о поддержке этим языком функционального стиля программирования.


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

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


E>Я вот не понимаю. Допустим, язык Scala поддерживает хвостовую рекурсию. Может ли существовать компилятор Scala, не поддерживающий эту оптимизацию?


Язык Scala поддерживает общую рекурсию. Другое дело, что имеющийся в наличии компилятор умеет разворачивать хвостовую рекурсию в цикл. Вполне возможно создать компилятор, который не поддерживает данную оптимизацию. Более того, если завтра появится компьютер, процессор которого умеет непосредственно редуцировать лямбда-выражения или комбинаторы, то подобная оптимизация вообще не понадобится.
... << RSDN@Home 1.2.0 alpha rev. 672>>
Re[13]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.02.08 18:14
Оценка:
Здравствуйте, konsoletyper, Вы писали:

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


K>>>Это проблема конкретной реализации.


E>>Есть единственная реализация языка в виде единственного компилятора. Отсутствие хвостовой рекурсии в этой реалиции оставляет возможность только абстрактных разговоров о поддержке этим языком функционального стиля программирования.


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


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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 06.02.08 13:07
Оценка: 35 (1) +3 -1
Здравствуйте, eao197, Вы писали:

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


Не надо прикрываться Страуструпами. Даже если бы он обладал непогрешимостью в вопросах, объявляемых ex catedra ну или ex codex в данном случае — определению это не помогло бы, ведь оно ни о чем не говорит. Оно бессодержательно, как и определение веревки, согласно которому это вервие простое.
Я-то спрашивал, определение, из которого следует, какие средства необходимы. Мое определение заключается в том, что функциональный язык — это язык, в котором функции являются FCO.

E>Например, поэтому язык C не считается ООЯ, хотя он и позволяет писать программы в стиле ООП. Поскольку по сравнению с ООЯ в C нужно прикладывать слишком много усилий для поддержки ООП.


Нет, не поэтому. Слова "слишком" и "много" не имеют никакого смысла. Когда слишком много, а когда еще не слишком? И в сравнении с какими ООП языками? Каким образом происходит сравнение — по какой методике, чем измерим интервал между ООП и не ООП языком и на какой оси? ВСе очень туманно, определение ставит много вопросов и не дает совсем никаких ответов. Простите, но я ничего в нем не понял.
Я считаю, что C не считается ООП потому, что в нем нет объектов как FCO. Все.

E>Точно так же я смотрю и на функциональное программирование. Ключевым моментом в котором для меня является неизменяемость данных. Данные не изменяются и это делает возможным такие замечательные вещи, как прозрачный параллелизм без лишних синхронизаций, упрощенное тестирование, возможность при отладке возвращаться на произвольное число шагов (однако, лучше заглянуть сюда
Автор(ы): Вячеслав Ахмечет
Дата: 16.09.2006
Данная статья достаточно кратко и вполне доступно, используя примеры на Java (!), знакомит читателя с базовыми понятиями функционального программирования.
).


Это только для случая полной чистоты в смысле отсутствия сайд эффектов. Т.е. речь о чистых функциональных языках. Неизменяемые данные (наряду с изменяемыми) же поддерживаются и в нефункциональных языках — просто передаете интефейс только для чтения и все. Каким образом это обязательно для ФЯ непонятно.

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


E>хвостовая рекурсия, которая позволяет выражать циклы без использования переменных цикла.


В смысле, гарантированная раскрутка хвостовой рекурсии? Во-первых, это вопрос реализации. Который не имеет отношения к языку. Во-вторых, в ФП это плохой стиль. Что, кстати, хорошо видно по громоздкости кода. В таких случаях пользуются стандартными функциями высшего порядка вроде map, fold, etc. А как map реализован внутри не обязано никого волновать.

E>иммутабельность данных,

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

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

E>В отсутствии всего вышеперечисленного программирование на Nice в функциональном стиле, наверное, возможно. Но, как и с ООП в языке C, это будет слишком трудоемко по сравнению с действительно функциональными языками.

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

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

E>Недостатком вашего определения является его поверхностность.


Непонятно, что в данном случае означает "поверхностность"? В моем определении как раз только самая суть очищенная от всего наносного.

E>Под него, по большому счету, не только D, но и C попадает.


Похоже, вы не поняли мое определение.

E>Т.к. в C указателями на функции можно манипулировать так же, как и экземплярами любых других данных.


Действительно, не поняли. Функция в C не является первоклассным объектом. Указатель — является. Но вы, конечно, можете попробовать открыть для меня глубины C, продемонстрировав код на C соответствующий моему коду на Nice. Будет очень интересно.
... << 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[9]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.02.08 13:14
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


K>Да, мне кажется я понял. В данном случае Nice не функциональный язык в таком же точно смысле, в каком курица — не птица, а Болгария — не заграница.


Вы выбрали неподходящий объект для упражнений в остроумии.


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

E>Вы выбрали неподходящий объект для упражнений в остроумии.


Не могу с Вами согласиться. Объект для упражнений в остроумии вполне подходящий. Получил огромное удовольствие от разговора, спасибо.
... << 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[11]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 06.02.08 13:33
Оценка: :)
Здравствуйте, Klapaucius, Вы писали:

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


E>>Вы выбрали неподходящий объект для упражнений в остроумии.


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


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


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

K>Мы -то говорим о классификации языков безотносительно их удобства. По крайней мере, я так думал.


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

E>>Недостатком вашего определения является его поверхностность.


K>Непонятно, что в данном случае означает "поверхностность"? В моем определении как раз только самая суть очищенная от всего наносного.


Благодоря этой очишенной сути функциональными становятся такие языки как D, C# (начиная, если не ошибаюсь, с 1.0), Ruby, SmallTalk, Eiffel. А это противоречит моему ощущению реальности.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[9]: Функциональный/нефункциональный
От: Left2 Украина  
Дата: 06.02.08 13:51
Оценка: +1 :)
E>>Т.к. в C указателями на функции можно манипулировать так же, как и экземплярами любых других данных.
K>Действительно, не поняли. Функция в C не является первоклассным объектом. Указатель — является. Но вы, конечно, можете попробовать открыть для меня глубины C, продемонстрировав код на C соответствующий моему коду на Nice. Будет очень интересно.
А какая разница является first-class object указатель на функцию или сама функция? Концепция указателей насколько я понимаю вообще ортогональна функциональным/императивным языкам. Я вот нутром чую что C язык не функциональный, но наличие указателей на функцию меня сильно смущает когда пытаешься обьяснить почему
... << RSDN@Home 1.2.0 alpha rev. 717>>
Re[10]: Функциональный/нефункциональный
От: Трурль  
Дата: 06.02.08 19:50
Оценка: -1
Здравствуйте, eao197, Вы писали:

K>>Непонятно, что в данном случае означает "поверхностность"? В моем определении как раз только самая суть очищенная от всего наносного.


E>Благодоря этой очишенной сути функциональными становятся такие языки как D, C# (начиная, если не ошибаюсь, с 1.0), Ruby, SmallTalk, Eiffel. А это противоречит моему ощущению реальности.


А также такие как Forth, Algol-68 и CPL. Что касается последнего, то причисление к лику функциональных языка, введшего в обиход такое понятие как L-value, мне лично кажется кощунственным.
С другой стороны, некоторые почитаемые среди функциональщиков языки, в частности FP потеряют свой статус. Загадочным с этой точки зрения представляется и несколько пренебрежительное отношение общественности к добавлению в Erlang функциональных объектов, которые, собственно, и превратили его в функциональный язык. (Интересно, каким он был до этого?)

Человек — двуногое без перьев (и с плоскими ногтями). Так, кажется звучит определение, очищенное от всего наносного?
Re[11]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 06.02.08 19:55
Оценка:
Здравствуйте, Трурль, Вы писали:

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


K>>>Непонятно, что в данном случае означает "поверхностность"? В моем определении как раз только самая суть очищенная от всего наносного.


E>>Благодоря этой очишенной сути функциональными становятся такие языки как D, C# (начиная, если не ошибаюсь, с 1.0), Ruby, SmallTalk, Eiffel. А это противоречит моему ощущению реальности.


Т>А также такие как Forth, Algol-68 и CPL. Что касается последнего, то причисление к лику функциональных языка, введшего в обиход такое понятие как L-value, мне лично кажется кощунственным.

Т>С другой стороны, некоторые почитаемые среди функциональщиков языки, в частности FP потеряют свой статус. Загадочным с этой точки зрения представляется и несколько пренебрежительное отношение общественности к добавлению в Erlang функциональных объектов, которые, собственно, и превратили его в функциональный язык. (Интересно, каким он был до этого?)

Ну если вспомнить, что там был по сути Пролог, то был язык логического программирования + навороты для concurrency.
Re[10]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 07.02.08 13:02
Оценка: 6 (2) +5
Здравствуйте, Left2, Вы писали:

L>А какая разница является first-class object указатель на функцию или сама функция? Концепция указателей насколько я понимаю вообще ортогональна функциональным/императивным языкам. Я вот нутром чую что C язык не функциональный, но наличие указателей на функцию меня сильно смущает когда пытаешься обьяснить почему


Потому, что можно указать только на уже имеющуюся функцию, а сконструировать ее во время выполнения программы — нельзя.
Если функции у нас не FCO, но есть указатели на функцию, то можно написать некоторые функции высшего порядка. А некоторые нельзя. Например map можно, а flip и curry — нет.

Тут
Автор: Klapaucius
Дата: 01.02.07
уже была год назад дискуссия на эту тему.
... << 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[10]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 07.02.08 13:02
Оценка:
Здравствуйте, eao197, Вы писали:

E>Вы ошиблись, я не говорил об абстрактной классификации языков. Я говорил о возможности программирования на языке в функциональном стиле, поскольку меня интересует практика.


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

E>Благодоря этой очишенной сути функциональными становятся


Не становятся, а соответствуют этому определению. Если соответствуют.

E>такие языки как D,


Об этом мы уже говорили.

E>C# (начиная, если не ошибаюсь, с 1.0),


Скорее с более поздних. Но тут все не совсем очевидно и мнения могут различаться. Все-таки MulticastDelegate — это не совсем функциональный тип. Например, все отображения из A в A' имеют один тип A -> A', а делегаты Foo<A, A'> и Bar<A, A'> — это разные типы. В стандартной библиотеке C# 3.0 появился набор "функциональных типов" сделанных на базе делегатов. А во времена C# 2.0 можно было написать свою ФВП, которая возвращала функцию типа MYFunc<T1, T2> и она не состыковывалась бы с ФВП из библиотеки Имярека, принимающей функцию типа Fn<T1, T2>

E>SmallTalk,


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

E>Eiffel.


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

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

E>А это противоречит моему ощущению реальности.


Не согласен с тем, что противоречие неформализованному ощущению реальности — это проблема определения.
Вообще чистые реализации одной парадигмы не так уж часто встречаются, большинство языков — мультипарадигменные в той или иной степени. Если какая-то возможность практически полезна, то даже в чистой реализации другой парадигмы может появиться конвергентная фича вроде смолтоковских блоков кода, например.
... << 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[11]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 07.02.08 13:02
Оценка:
Здравствуйте, Трурль, Вы писали:

Т>А также такие как Forth,


По моему скромному разумению, функция в Forth это еще более странно, чем функция в Smalltalk.

Т>Algol-68 и CPL. Что касается последнего, то причисление к лику функциональных языка, введшего в обиход такое понятие как L-value, мне лично кажется кощунственным.

Т>С другой стороны, некоторые почитаемые среди функциональщиков языки, в частности FP потеряют свой статус.

C такой эрудицией, конечно, не мне тягаться.

Т>Загадочным с этой точки зрения представляется и несколько пренебрежительное отношение общественности к добавлению в Erlang функциональных объектов, которые, собственно, и превратили его в функциональный язык. (Интересно, каким он был до этого?)


По моему, классифицировать гибрид Smalltalk-72 и Prolog вообще проблема нетривиальная.

Т>Человек — двуногое без перьев (и с плоскими ногтями). Так, кажется звучит определение, очищенное от всего наносного?


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

p.s. Нельзя ли все-таки прояснить ваше сообщение здесь
Автор: Трурль
Дата: 04.02.08
, а то я сколько голову не ломал — так и не понял, к чему это было сказано.
... << 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[12]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 07.02.08 13:31
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


Т>>Загадочным с этой точки зрения представляется и несколько пренебрежительное отношение общественности к добавлению в Erlang функциональных объектов, которые, собственно, и превратили его в функциональный язык. (Интересно, каким он был до этого?)


K>По моему, классифицировать гибрид Smalltalk-72 и Prolog вообще проблема нетривиальная.


Можно комментарий по поводу выделенного? Желательно с фактами?
Re[11]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 07.02.08 13:41
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


E>>Вы ошиблись, я не говорил об абстрактной классификации языков. Я говорил о возможности программирования на языке в функциональном стиле, поскольку меня интересует практика.


K>Во первых, вы утверждали, что Scala от Nice отличается тем, что первый язык является функциональным, а второй — нет. Причем в контексте разговора весьма далекого от практики.


Мне казалось, что речь шла о как раз очень практических вещах, а именно -- о разработке (т.е. практическом создании) новых языков программирования.

K> Кроме того, возможность и удобство — разные вещи. Возможность я продемонстрировал, удобство — вопрос субъективный.


Удобство -- это как раз мера возможности на практике. Метапрограммирование на С++ возможно -- да, но неудобно. Настолько неудобно, что его применимость даже осознается далеко не всеми C++ разработчиками. В противовес этому есть Nemerle и Lisp, где метапрограммирование не только возможно, но и удобно.

E>>C# (начиная, если не ошибаюсь, с 1.0),


K>Скорее с более поздних. Но тут все не совсем очевидно и мнения могут различаться. Все-таки MulticastDelegate — это не совсем функциональный тип. Например, все отображения из A в A' имеют один тип A -> A', а делегаты Foo<A, A'> и Bar<A, A'> — это разные типы. В стандартной библиотеке C# 3.0 появился набор "функциональных типов" сделанных на базе делегатов. А во времена C# 2.0 можно было написать свою ФВП, которая возвращала функцию типа MYFunc<T1, T2> и она не состыковывалась бы с ФВП из библиотеки Имярека, принимающей функцию типа Fn<T1, T2>


В версии 1.0 можно было создавать делегаты для конкретных типов аргументов и возвращаемого значения. Т.е. можно было сделать curry для (int,int)->int отдельно, и curry для (float,float)->float отдельно. Но возможность сделать curry, в принципе, была.

E>>SmallTalk,


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


В SmallTalk и Ruby блоки кода могут использоваться для реализации curry. Более того, где-то кто-то даже пытался писать книгу об программировании с использованием ФВП в Ruby на основе блоков кода Ruby.

E>>Eiffel.


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


Не знаю, как агенты Eiffel-я соответствуют паттерну стратегия, но реализовать curry аналогичный Nice-вскому они смогут. Тем более, что сам язык предоставляет возможность назначать некоторым аргументам заранее заданные значения.

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


Eiffel-я, C# и SmallTalk у меня сейчас нет. О том, как реализовать curry на Ruby можно прочитать здесь.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[2]: Функциональный/нефункциональный
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.02.08 18:13
Оценка:
Здравствуйте, eao197, Вы писали:

E>Ну а паттерн-матчинг где?


Ой, значит это все что нужно чтобы язык был фунциональным? И значит Лисп который является родителем всех ФЯ вдруг становится не фунциональным?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Функциональный/нефункциональный
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.02.08 18:13
Оценка:
Здравствуйте, deniok, Вы писали:

D>В G-машине, как я понимаю, это так и будет в виде циклического thunk'а храниться — будет немножко больше косвенности при обращении к аргументам (разыменование указателей). Но это — небольшая плата за приспособление к фон-неймановской архитектуре


Большая. Хаскель это классно демонстрирует.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Функциональный/нефункциональный
От: VladD2 Российская Империя www.nemerle.org
Дата: 07.02.08 18:13
Оценка: +1
Здравствуйте, eao197, Вы писали:

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


E>Чуть-чуть пострашнее, ...


Ё! Предлагаю сойтись на мнении, что Найс более фунциональный чем Ди, но менее чем "позиционируемые как ФЯ языки". ОК?

А вообще, и Ди и Найс и даже похожн Эфиль поддерживают ФП. Но конечно одни больше другие меньше. И Найс, похоже, выглядит в данном случае вполне себе неполохо.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 07.02.08 20:33
Оценка:
Здравствуйте, eao197, Вы писали:

E>В версии 1.0 можно было создавать делегаты для конкретных типов аргументов и возвращаемого значения. Т.е. можно было сделать curry для (int,int)->int отдельно, и curry для (float,float)->float отдельно. Но возможность сделать curry, в принципе, была.


E>В SmallTalk и Ruby блоки кода могут использоваться для реализации curry. Более того, где-то кто-то даже пытался писать книгу об программировании с использованием ФВП в Ruby на основе блоков кода Ruby.


E>Не знаю, как агенты Eiffel-я соответствуют паттерну стратегия, но реализовать curry аналогичный Nice-вскому они смогут. Тем более, что сам язык предоставляет возможность назначать некоторым аргументам заранее заданные значения.

E>О том, как реализовать curry на Ruby можно прочитать здесь.

Да дело даже не в параметрическом полиморфизме, хотя carry только для int — это, конечно, анекдот.
C# 1.0 совершенно точно небыл языком с первоклассными функциями.
Нельзя было присвоить переменной функциональное значение.
// C# 1.0 - делегат создается явно
FuncType fvalue = new FuncType(Function);
// функция - гражданин второго сорта. Она унижена и прищемлена.

// С# 2.0 - делегат создается неявно
FuncType fvalue = Function;
// справедливость торжествует!

Нельзя было сконструировать функцию на месте. В C# 2.0 дела обстояли лучше.
// представляем анонимный метод(тм)!
FuncType fvalue = delegate(){return "я уродлив, но свое дело делаю";};


У Eiffel тоже первоклассных функций пока не видно.
class
  AGENT_PROVIDER
feature
  demo (i: INTEGER; s: STRING) is
    do
        -- тут что-то происходит
    end
end

class
  AGENT_CONSUMER
feature
  call_agent (a: PROCEDURE [ANY, TUPLE [INTEGER, STRING]]) is
    do
    -- хорошо видно, что агент это вовсе не функция - это класс
    -- с методом call
      a.call ( [0, "Hello, World"] )
    end
end

class
  APPLICATION
create
  make
feature
  make is
    local
      producer: AGENT_PROVIDER
      consumer: AGENT_CONSUMER
    do
      create producer
      create consumer
    -- а здесь мы наблюдаем, как функция (а точнее - метод) producer.demo
    -- явным образом оборачивается в класс - агент,
    -- становясь методом call этого класса.
      consumer.call_agent (agent producer.demo)
    end
end

Легко видеть, что функции fco в этом языке не являются. Так что за мировоззрение можно не беспокоится.

Что касается смолтока — еще раз повторяю, если нет функций, то бессмысленно говорить о том, являются ли они первоклассными объектами.
Блок кода в Ruby тоже, насколько мне известно, является объектом с методом call, а вовсе не функцией.
Карринг же (вернее, как его называет автор, карринг для бедных) в Ruby, судя по всему, реализуется с помощью метапрограммирования, если я, конечно, правильно понял семантику define_method.
'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[13]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 08.02.08 05:53
Оценка: -1
Здравствуйте, Klapaucius, Вы писали:

K>Что касается смолтока — еще раз повторяю, если нет функций, то бессмысленно говорить о том, являются ли они первоклассными объектами.

K>Блок кода в Ruby тоже, насколько мне известно, является объектом с методом call, а вовсе не функцией.
K>Карринг же (вернее, как его называет автор, карринг для бедных) в Ruby, судя по всему, реализуется с помощью метапрограммирования, если я, конечно, правильно понял семантику define_method.

Т.е., все возражения против C#, Eiffel, SmallTalk и Ruby свелись к тому, что там делегаты/агенты/блоки кода не называются "функциями"?

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


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

E>Т.е., все возражения против C#, Eiffel, SmallTalk и Ruby свелись к тому, что там делегаты/агенты/блоки кода не называются "функциями"?


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

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[13]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 08.02.08 15:07
Оценка:
Здравствуйте, Курилка, Вы писали:

K>>По моему, классифицировать гибрид Smalltalk-72 и Prolog вообще проблема нетривиальная.

К>Можно комментарий по поводу выделенного? Желательно с фактами?

Насколько я знаю, actor model выросла из идей, реализованных в Smalltalk-72.
... << 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[14]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 08.02.08 16:50
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


K>>>По моему, классифицировать гибрид Smalltalk-72 и Prolog вообще проблема нетривиальная.

К>>Можно комментарий по поводу выделенного? Желательно с фактами?

K>Насколько я знаю, actor model выросла из идей, реализованных в Smalltalk-72.



Шарп (и Немерле заодно) мы гибридом Симулы считать будем?
Ну и фактами чтот не пахнет, хотя неважно, нравится видеть там смолтолк — ради бога
Re[14]: Функциональный/нефункциональный
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.02.08 17:48
Оценка:
Здравствуйте, eao197, Вы писали:

E>Т.е., все возражения против C#, Eiffel, SmallTalk и Ruby свелись к тому, что там делегаты/агенты/блоки кода не называются "функциями"?


Ты как всегда ошибся. Вроде как твоей аппонент говорил о том, что в C# 1.0 и Eiffel функции не были первокласными объектами, хотя бы потому, что их нельзя было создать по месту и в рантайме. А Смолток и Руби вроде как оперирует понятиями объектов и посылки сообщений. В прочем, на мой взгляд, Руби все же неплохо эмулирует функции как первокласные объекты.
... << RSDN@Home 1.2.0 alpha rev. 672>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.02.08 12:55
Оценка:
Здравствуйте, VladD2, Вы писали:

E>>Т.е., все возражения против C#, Eiffel, SmallTalk и Ruby свелись к тому, что там делегаты/агенты/блоки кода не называются "функциями"?


VD>Ты как всегда ошибся. Вроде как твоей аппонент говорил о том, что в C# 1.0 и Eiffel функции не были первокласными объектами, хотя бы потому, что их нельзя было создать по месту и в рантайме.


В Eiffel нет такого ограничения, и ты, и мой оппонент мог бы это увидеть:

Существует так же возможность создавать т.н. inline agents, т.е. агентов тело которых определяется непосредственно в конструкции agent:

consumer.call_agent (
    agent (i: INTEGER; s: STRING) do io.put_string ("inline agent!%N") end)

Так что, по существу, агенты в Eiffel не сильно отличаются от блоков кода в Ruby (за исключением особенностей статической типизации).


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

VD>>Ты как всегда ошибся. Вроде как твоей аппонент говорил о том, что в C# 1.0 и Eiffel функции не были первокласными объектами, хотя бы потому, что их нельзя было создать по месту и в рантайме.

E>В Eiffel нет такого ограничения, и ты, и мой оппонент мог бы это увидеть:
E>

E>Существует так же возможность создавать т.н. inline agents, т.е. агентов тело которых определяется непосредственно в конструкции agent:
E>

E>consumer.call_agent (
E>    agent (i: INTEGER; s: STRING) do io.put_string ("inline agent!%N") end)
E>


По-существу, это литерал не для функции, а для агента. Вы могли бы и увидеть, что такой довод в числе прочих я выдвигал, аргументируя отсутствие первоклассных функций в C# 1.0. К Eiffel у меня другие претензии. Почему передавая в качестве аргумента не функцию, я не должен это явно указывать, а передавая функцию — должен, с помощью ключевого слова agent? Это явное, задаваемое программистом оборачивание функции в объект — точно как и в C# 1.0. Если уж на то пошло, в первом шарпе и то ситуация в этом плане была лучше. Вызов функции через делегат от просто вызова функции никак синтаксически не отличался, а в 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[15]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 11.02.08 13:53
Оценка:
Здравствуйте, Курилка, Вы писали:

K>>Насколько я знаю, actor model выросла из идей, реализованных в Smalltalk-72.


К>Шарп (и Немерле заодно) мы гибридом Симулы считать будем?


Я бы считал, если бы на временной оси между Simula и C# небыло бы ни одного известного мне языка с ООП. А между Smalltalk и Erlang я ни одного языка с actor model не знаю. Поэтому так и говорю.

К>Ну и фактами чтот не пахнет, хотя неважно, нравится видеть там смолтолк — ради бога


Какого рода факты интересуют? Я думаю, в статье Википедии про Actor model можно найти ссылки на заслуживающие доверия источники и изучить их — самому мне такую работу проделывать лень. Никакой заинтереснованности в том, чтобы этот мой взгляд на Erlang и смолток 72 разделял еще кто-то у меня нет.
... << 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[17]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.02.08 13:58
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>По-существу, это литерал не для функции, а для агента. Вы могли бы и увидеть, что такой довод в числе прочих я выдвигал, аргументируя отсутствие первоклассных функций в C# 1.0. К Eiffel у меня другие претензии. Почему передавая в качестве аргумента не функцию, я не должен это явно указывать, а передавая функцию — должен, с помощью ключевого слова agent?


Почему передавая в качестве аргумента в Nice не функцию я должен писать:
void f( A b ) { ... }

а передавая в качестве аргумента функцию я должен писать '->'
void f( ()->A b ) { ... }

?
Иными словами, почему "передавая в качестве аргумента не функцию, я не должен это явно указывать, а передавая функцию — должен, с помощью " специальной синтаксической конструкции `->`?


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

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

E>
E>void f( A b ) { ... }
E>


И где здесь передача? Это декларация типа.

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

E>
E>void f( ()->A b ) { ... }
E>

E>?

И тут ничего не передается — только тип декларируется.

E>Иными словами, почему "передавая в качестве аргумента не функцию, я не должен это явно указывать, а передавая функцию — должен, с помощью " специальной синтаксической конструкции `->`?


Вы шутите чтоли? Или не отличаете использования функции от ее декларации?

В Nice я вызываю curry так:
curry(foo);

А не
curry(agent foo);


Почему я не могу написать на Eiffel так:
consumer.call_agent (producer.demo)

А вынужден писать так:
consumer.call_agent (agent producer.demo)

При этом так
io.put_string (s) -- s - переменная, содержащая строку.

Я написать могу.
... << 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[19]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.02.08 14:23
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


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

E>>
E>>void f( A b ) { ... }
E>>


K>И где здесь передача? Это декларация типа.


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

E>>
E>>void f( ()->A b ) { ... }
E>>

E>>?

K>И тут ничего не передается — только тип декларируется.


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

E>>Иными словами, почему "передавая в качестве аргумента не функцию, я не должен это явно указывать, а передавая функцию — должен, с помощью " специальной синтаксической конструкции `->`?


K>Вы шутите чтоли? Или не отличаете использования функции от ее декларации?


K>В Nice я вызываю curry так:

K>
K>curry(foo);
K>

K>А не
K>
K>curry(agent foo);
K>


K>Почему я не могу написать на Eiffel так:

K>
K>consumer.call_agent (producer.demo)
K>

K>А вынужден писать так:
K>
K>consumer.call_agent (agent producer.demo)
K>


По той причине, что и необходимость взятия адреса у функции в D.
Дело в том, что в Eiffel выражение producer.demo означает вызов метода demo или получение значения атрибута demo (методы без аргументов в Eiffel вызываются без скобочек). Поэтому когда компилятор видит producer.demo, но оказывается, что метод demo требует, скажет, два аргумента, то это считается ошибкой -- разработчик не передал аргументы при вызове. А выражение agent producer.demo явно указывает компилятору, что это не вызов, а "взятие адреса" функции.

K>При этом так

K>
K>io.put_string (s) -- s - переменная, содержащая строку.
K>

K>Я написать могу.

Если у вас написано так:
local
  a: <тип агента>
do
  a = agent producer.demo
  -- то вы можете написать так же, как и с переменной s.
  consumer.call_agent (a)
end


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[17]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 11.02.08 14:57
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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

K>Это, собственно, и означает непервоклассность функций, надеюсь, теперь понятно?

Кстати, Эрланг тоже не функциональный, т.к. он гибрид смолтолка и для создания функциональных значений там надо использовать слово fun?
Re[20]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 12.02.08 13:45
Оценка: -1
Здравствуйте, eao197, Вы писали:

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


Рад, что недоразумение улажено, а понимание в этом вопросе наконец достигнуто.

K>>Почему я не могу написать на Eiffel так:

K>>
K>>consumer.call_agent (producer.demo)
K>>

K>>А вынужден писать так:
K>>
K>>consumer.call_agent (agent producer.demo)
K>>


E>По той причине, что и необходимость взятия адреса у функции в D.

E>Дело в том, что в Eiffel выражение producer.demo означает вызов метода demo или получение значения атрибута demo (методы без аргументов в Eiffel вызываются без скобочек). Поэтому когда компилятор видит producer.demo, но оказывается, что метод demo требует, скажет, два аргумента, то это считается ошибкой -- разработчик не передал аргументы при вызове. А выражение agent producer.demo явно указывает компилятору, что это не вызов, а "взятие адреса" функции.

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

E>Если у вас написано так:

E>
E>local
E>  a: <тип агента>
E>do
E>  a = agent producer.demo
E>  -- то вы можете написать так же, как и с переменной s.
E>  consumer.call_agent (a)
E>end
E>


Ну это-то понятно. a — переменная, содержащая агент. А присвоить ей функцию непосредственно также нельзя — нужно явно оборачивать ее в агент. Это, с моей точки зрения, также говорит о непервоклассности функции в Eiffel. Просто те задачи, которые в ФЯ решались бы с помощью первоклассных функций, решаются в ООП Eiffel с помощью конвергентной ООП-фичи. Точно также как и в SmallTalk/Ruby. С практической точки зрения это большого значения не имеет, но с терминологической — разница есть.
... << 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[21]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 12.02.08 14:06
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Не совсем понимаю проблему. Язык статически типизированный, у компилятора есть информация о типе параметра call_agent и типе функции producer.demo. Если тип параметра — это функциональный тип, соответствующий типу функции producer.demo — выполняется передача функционального значения, если тип, соответствующий возвращаемому типу producer.demo — выполняется вызов.

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

А как быть, если producer.demo -- это метод без параметров, возвращающий агента?


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

E>А как быть, если producer.demo -- это метод без параметров, возвращающий агента?


Т.е. () -> (U -> V) , например?

Если у параметра тип () -> (U -> V) -передается функциональное значение, а если тип U -> V — выполняется вызов.
В общем случае () -> X и X.
... << 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[23]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 13.02.08 09:08
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


E>>А как быть, если producer.demo -- это метод без параметров, возвращающий агента?


K>Т.е. () -> (U -> V) , например?


K>Если у параметра тип () -> (U -> V) -передается функциональное значение, а если тип U -> V — выполняется вызов.

K>В общем случае () -> X и X.

Насколько я понимаю у тебя тип агента U -> V, тогда вызов должен выполняться при сигнатуре параметра () -> (U -> V), а при U -> V просто передаваться функция. И если даже ты запутался (хотя может и я вру), то тебе не кажется, что это несколько не совсем простые правила? Хотя людям знакомым с Хиндли-Милнером это всё семечки имхо.
P.S. Или имелся в виду тип параметра в сигнатуре функции (consumer.call_agent), которой нужен агент? Тогда какая-то совсем непонятная нотация выходит.
Re[23]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.02.08 09:10
Оценка: +1
Здравствуйте, Klapaucius, Вы писали:

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


E>>А как быть, если producer.demo -- это метод без параметров, возвращающий агента?


K>Т.е. () -> (U -> V) , например?


K>Если у параметра тип () -> (U -> V) -передается функциональное значение, а если тип U -> V — выполняется вызов.

K>В общем случае () -> X и X.

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

Если применить ваш подход, когда встретив выражение:
something( producer.demo )

только компилятор на основании типа producer.demo сможет сделать вывод о том, что же будет выполнено -- вызов demo или взятие адреса demo, то это нарушит одну из целей языка. Человек сможет разобраться в этом только с помощью IDE и только если заострит внимание именно на этом выражении. В то время как выражение:
something( agent producer.demo )

дает однозначное толкование как для читающего код человека (не важно, с экрана ли код читается или из книги) так и для компилятора.

Я, помнится, столкнулся в Nemerle с тем, что написав вызов чего-то без скобочек получил не вызов, а возврат лямбды. Но здесь Nemerl-исты мне ответили, что мол нефиг без нормальной IDE код писать и читать. В отличии от Nemerle в Eiffel такой ошибки нельзя совершить в принципе.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[24]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 13.02.08 09:41
Оценка: +1
Здравствуйте, eao197, Вы писали:

[cut]
E>Я, помнится, столкнулся в Nemerle с тем, что написав вызов чего-то без скобочек получил не вызов, а возврат лямбды. Но здесь Nemerl-исты мне ответили, что мол нефиг без нормальной IDE код писать и читать. В отличии от Nemerle в Eiffel такой ошибки нельзя совершить в принципе.

Только это делает язык многословней и в итоге менее читабельным, если надо "навернуть" что-нибудь посложней. С другой стороны есть всякие Хаскели и Джей, где записывается оно кратко, только для понимания нужны умственные усилия (хотя может быть и там можно IDE заставить помогать, только как-то люди без неё справляются в основном).
Т.е. получается с одной стороы краткость/многословность, а с другой стороны сложность концепций/высота абстракции. Где найти точку оптимума имхо вопрос сильно субъективный. Плюс надо не забывать другие факторы, чтоб посчитать корректно TCO.
Re[25]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.02.08 10:01
Оценка:
Здравствуйте, Курилка, Вы писали:

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


К>[cut]

E>>Я, помнится, столкнулся в Nemerle с тем, что написав вызов чего-то без скобочек получил не вызов, а возврат лямбды. Но здесь Nemerl-исты мне ответили, что мол нефиг без нормальной IDE код писать и читать. В отличии от Nemerle в Eiffel такой ошибки нельзя совершить в принципе.

К>Только это делает язык многословней и в итоге менее читабельным, если надо "навернуть" что-нибудь посложней. С другой стороны есть всякие Хаскели и Джей, где записывается оно кратко, только для понимания нужны умственные усилия (хотя может быть и там можно IDE заставить помогать, только как-то люди без неё справляются в основном).


Ну особенность Eiffel-я как раз в том и состоит, что в нем невозможно построить короткое, но сложное выражение, для понимания которого нужно прилагать серьезные умственные усилия. Сами принципы Eiffel-я этому противоречат (в частности Command/Query Separation Principle). Кому-то это может нравится, кому-то нет. Мне кажется, что в большие компании, где над проектами работают команды в сотни программистов, Eiffel удалось протолкнуть именно благодоря этому.

К>Т.е. получается с одной стороы краткость/многословность, а с другой стороны сложность концепций/высота абстракции. Где найти точку оптимума имхо вопрос сильно субъективный. Плюс надо не забывать другие факторы, чтоб посчитать корректно TCO.


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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[26]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 13.02.08 10:28
Оценка:
Здравствуйте, eao197, Вы писали:

E>Ну особенность Eiffel-я как раз в том и состоит, что в нем невозможно построить короткое, но сложное выражение, для понимания которого нужно прилагать серьезные умственные усилия. Сами принципы Eiffel-я этому противоречат (в частности Command/Query Separation Principle). Кому-то это может нравится, кому-то нет. Мне кажется, что в большие компании, где над проектами работают команды в сотни программистов, Eiffel удалось протолкнуть именно благодоря этому.

Вопрос — а так ли нужны эти сотни? Формализм (в данном случае языка) это палка о двух концах. Думаю ты не будешь спорить, что создать формально правильный, но монструозный проект можно вполне запросто
Хотя это уже совсем оффтопик.

E>Собственно, дело не в определении TCO, а в том, делает ли использование ключевого слова 'agent' в Eiffel невозможным признание самого факта существования функций высшего порядка в Eiffel.


Ну сорри, я просто чуть крупнее вопрос затронул
Всё, закругляемся с оффтопиком
Re[27]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.02.08 11:17
Оценка:
Здравствуйте, Курилка, Вы писали:

E>>Ну особенность Eiffel-я как раз в том и состоит, что в нем невозможно построить короткое, но сложное выражение, для понимания которого нужно прилагать серьезные умственные усилия. Сами принципы Eiffel-я этому противоречат (в частности Command/Query Separation Principle). Кому-то это может нравится, кому-то нет. Мне кажется, что в большие компании, где над проектами работают команды в сотни программистов, Eiffel удалось протолкнуть именно благодоря этому.

К>Вопрос — а так ли нужны эти сотни?

Думаю, что есть области, где наверняка нужны. Вот ты как-то говорил, что сейчас в области телекома работаешь. Я к этой области так же более-менее причастен. Так здесь куда не плюнь таких задачек нарыть можно. Тот же проект AXD301 взять -- там на Erlang-е, если не ошибаюсь, человек 50 писало. Или вот задастся кто-нибудь целью в сжатые сроки создать свою реализацию софта для средней руки SMS-центра для GSM-оператора -- сотню толковых программистов здесь озадачить можно запросто. А уж бестолковых...

Просто со временем ловишь себя на мысли, что чем больше кода приходится поддерживать, тем больше уважения получают языки вроде Eiffel. И если бы мне сейчас пришлось делать что-нибудь критически важное (ну не ядерные ректоры, но что-нибудь из этой же оперы), то я бы, наверное, Eiffel бы рассматривал среди наиболее вероятных вариантов.

К>Формализм (в данном случае языка) это палка о двух концах. Думаю ты не будешь спорить, что создать формально правильный, но монструозный проект можно вполне запросто


Дык до маразма довести можно что угодно. Или если деньги на проект нужно быстро и "грамотно" оприходывать

К>Хотя это уже совсем оффтопик.


Зато философский


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

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


E>Если применить ваш подход, когда встретив выражение:

E>
E>something( producer.demo )
E>

E>только компилятор на основании типа producer.demo сможет сделать вывод о том, что же будет выполнено -- вызов demo или взятие адреса demo, то это нарушит одну из целей языка. Человек сможет разобраться в этом только с помощью IDE и только если заострит внимание именно на этом выражении. В то время как выражение:
E>
E>something( agent producer.demo )
E>

E>дает однозначное толкование как для читающего код человека (не важно, с экрана ли код читается или из книги) так и для компилятора.

Собственно, именно это я и имел в виду, когда написал:

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


E>Я, помнится, столкнулся в Nemerle с тем, что написав вызов чего-то без скобочек получил не вызов, а возврат лямбды. Но здесь Nemerl-исты мне ответили, что мол нефиг без нормальной IDE код писать и читать. В отличии от Nemerle в 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[24]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 13.02.08 13:31
Оценка:
Здравствуйте, Курилка, Вы писали:

K>>Если у параметра тип () -> (U -> V) -передается функциональное значение, а если тип U -> V — выполняется вызов.

K>>В общем случае () -> X и X.

К>Насколько я понимаю у тебя тип агента U -> V, тогда вызов должен выполняться при сигнатуре параметра () -> (U -> V), а при U -> V просто передаваться функция. И если даже ты запутался (хотя может и я вру), то тебе не кажется, что это несколько не совсем простые правила? Хотя людям знакомым с Хиндли-Милнером это всё семечки имхо.

К>P.S. Или имелся в виду тип параметра в сигнатуре функции (consumer.call_agent), которой нужен агент? Тогда какая-то совсем непонятная нотация выходит.

псевдокод:
//Есть HOF без параметров, возвращающая функцию a -> b. 
//Т.е. тип функционального значения для нее () -> (a -> b)

foo : a -> b
{
    //...
}

//Имеем функцию высшего порядка

bar1(a : () -> (a -> b))
{
    //...
}

bar1(foo) // передаем в bar1 функциональное значение.

//Имеем функцию высшего порядка

bar2(a : a -> b)
{
    //...
}

bar2(foo) // вызываем foo и передаем в bar2 результат.

Я имел в виду именно это.
Правила может и не простые (хотя мне они кажутся простыми, ну да это не важно), но я то и говорю о том, что дело не в компиляторе, а в программисте. Явное конструирование agent сделано для программиста, далекого от ФП, для компилятора я проблемы пока не вижу.
... << 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[25]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.02.08 13:43
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>псевдокод:

K>
K>//Есть HOF без параметров, возвращающая функцию a -> b. 
K>//Т.е. тип функционального значения для нее () -> (a -> b)

K>foo : a -> b
K>{
K>    //...
K>}

K>//Имеем функцию высшего порядка

K>bar1(a : () -> (a -> b))
K>{
K>    //...
K>}

K>bar1(foo) // передаем в bar1 функциональное значение.
K>


А как будет различаться вызов foo, если его результат никуда не передается. Например, есть запись:
_ = foo

Это что?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[16]: Функциональный/нефункциональный
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.08 13:47
Оценка:
Здравствуйте, eao197, Вы писали:

E>

E>Существует так же возможность создавать т.н. inline agents, т.е. агентов тело которых определяется непосредственно в конструкции agent:
E>

E>consumer.call_agent (
E>    agent (i: INTEGER; s: STRING) do io.put_string ("inline agent!%N") end)
E>

E>Так что, по существу, агенты в Eiffel не сильно отличаются от блоков кода в Ruby (за исключением особенностей статической типизации).

А замыкания в этих инлайн-агентах допустимы? Могу я написать как-то так:
consumer.call_agent (
    agent () do io.put_string (X) end)
E>

Где Х — переменная обявленная выше в этом методе?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.02.08 13:52
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А замыкания в этих инлайн-агентах допустимы? Могу я написать как-то так:

VD>
VD>consumer.call_agent (
VD>    agent () do io.put_string (X) end)
E>>

VD>Где Х — переменная обявленная выше в этом методе?

Да


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

E>А как будет различаться вызов foo, если его результат никуда не передается. Например, есть запись:

E>
E>_ = foo
E>

E>Это что?

Это уже более интересный вопрос.
Если мы предположим, что это передача функционального значения в никуда — то данный участок кода ничего не делает.
Если же мы предположим, что это вызов функции ради сайд эффекта и игнорирование возвращаемого значения — получается, что данный код что-то делает. Исходя из тех соображений, что код пишется для того, чтобы организовать какое-то вычисление, а не для того, чтобы он ничего не делал, выбираем второй вариант.
... << 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[24]: Функциональный/нефункциональный
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.02.08 13:55
Оценка:
Здравствуйте, eao197, Вы писали:

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


Если это так, то фунциональная составляющая в этом языке точно провальная, так как синтаксис громоздок и неуклюж. Сравни сам. Это твой пример на Эфиле:
consumer.call_agent (
   agent (i: INTEGER; s: STRING) do io.put_string ("inline agent!%N") end)


А это Немерле:
consumer((_, _) => io.put_string ("inline agent!%N"));


Если конечно я правильно понимаю смысл этих выкрутасов с агентами.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[25]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 13.02.08 13:58
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Собственно, именно это я и имел в виду, когда написал:

K>

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


Так я и не могу понять, откуда же следует этот вывод.
Вот, кстати, в тему (http://www.faqs.org/faqs/eiffel-faq/):

LAGE: What are Eiffel agents?

In the early years of Eiffel, the language had no routine types
because having routines as distinct entities outside objects
was seen as incompatible with the OO method.

Nevertheless, it has now been accepted that routines as first
class objects are essential and the 'agents' facility has been
introduced. It has been implemented at least in part in Eiffel
Software's compiler and SmartEiffel. Other active vendors are
likely to follow.

While this feature is new and the standard is being finalised,
the core concepts, routine types and tuples for representing
the parameters and return type of a routine, are now well
understood.

An ordinary agent is created within the current object,
which provides a context and makes the facility as expressive as
higher order functions (closures) in functional programming
languages.


Т.е. агенты в Eiffel -- это непосредственный аналог HOF.


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

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


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


VD>Если это так, то фунциональная составляющая в этом языке точно провальная, так как синтаксис громоздок и неуклюж. Сравни сам. Это твой пример на Эфиле:

VD>
VD>consumer.call_agent (
VD>   agent (i: INTEGER; s: STRING) do io.put_string ("inline agent!%N") end)
VD>


VD>А это Немерле:

VD>
VD>consumer((_, _) => io.put_string ("inline agent!%N"));
VD>


По сравнению с языком с выводом типов -- да громоздок. Но даже не в части создания агента, а в части его последующего использования, т.е. вызова. Хотя ничем не хуже, чем делегаты в D или лямбды в Nice. А уж по сравнению с C++

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


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

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


E>>А как будет различаться вызов foo, если его результат никуда не передается. Например, есть запись:

E>>
E>>_ = foo
E>>

E>>Это что?

K>Это уже более интересный вопрос.

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

Мне кажется, что одной из задач ЯП является устранение неоднозначности конструкций и их зависимости от контекста. Причем это же не сложно в данном случае. Достаточно ввести простые правила: вызов функции/метода всегда записывается в форме f(), т.е. со скобочками. Но это нарушает такой прицип Eiffel, как Uniform Access Principle. Поэтому можно воспользоваться альтернативой: сделать специальный оператор для "взятия адреса" функции. Будет ли он ключевым словом agent, как в Eiffel или же оператором '&', как в D, уже не важно. Важно, что не будет неоднозначности.

А то ведь, может получиться как в C++:
void f()
  {
    A b(C);
  }

что такое b?


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

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


E>Так я и не могу понять, откуда же следует этот вывод.

E>Вот, кстати, в тему (http://www.faqs.org/faqs/eiffel-faq/):
E>

E>LAGE: What are Eiffel agents?

E>In the early years of Eiffel, the language had no routine types
E>because having routines as distinct entities outside objects
E>was seen as incompatible with the OO method.

E>Nevertheless, it has now been accepted that routines as first
E>class objects are essential and the 'agents' facility has been
E>introduced. It has been implemented at least in part in Eiffel
E>Software's compiler and SmartEiffel. Other active vendors are
E>likely to follow.

E>While this feature is new and the standard is being finalised,
E>the core concepts, routine types and tuples for representing
E>the parameters and return type of a routine, are now well
E>understood.

E>An ordinary agent is created within the current object,
E>which provides a context and makes the facility as expressive as
E>higher order functions (closures) in functional programming
E>languages.


E>Т.е. агенты в Eiffel -- это непосредственный аналог HOF.


Во-первых, тут терминологическая путаница. HOF — это функция, которая принимает и/или возвращает функцию. Например qsort из crt можно назвать непосредственным аналогом HOF.
Поэтому агенты не непосредственный аналог HOF, но с помощью них можно получить непосредственный аналог HOF.
Во-вторых, я же с самого начала говорил, что агенты в Eiffel предназанчены для решения тех задач, которые решаются в языках с первоклассными функциями без дополнительных сущностей. Но то, что agent является объектом, это не деталь реализации, (как являющийся объектом делегат в C# 2.0) агент отличается от функции и семантически и синтаксически, и при конструировании и при вызове. Именно поэтому я и утверждаю, что функции в Eiffel не являются первоклассными объектами — первоклассными объектами являются агенты, как и экземпляры любых других классов. Но средства, позволяющие реализовать аналог HOF, в Eiffel имеются — это факт. Просто объект с одним методом и функция это не одно и то же.
Язык с fco:
foo()
f = foo
f()

Язык без fco:
foo()
а = agent foo
a.call()


Вопрос о том, какой ценой дается первоклассность функций — отдельный и к спору о классификации 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[28]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 14.02.08 13:23
Оценка:
Здравствуйте, eao197, Вы писали:

E>Мне кажется, что одной из задач ЯП является устранение неоднозначности конструкций и их зависимости от контекста.


Согласен, что неоднозначность это плохо, но часто зависимость от контекста — это очень удобно.
Например, тип опрератора + зависит от конекста в подавляющем большинстве языков. Даже в тех, где нет перегрузки функций. Если уж на то пошло, ad hoc — полиморфизм есть зависимость от контекста по сути своей.

E>Причем это же не сложно в данном случае. Достаточно ввести простые правила: вызов функции/метода всегда записывается в форме f(), т.е. со скобочками. Но это нарушает такой прицип Eiffel, как Uniform Access Principle. Поэтому можно воспользоваться альтернативой: сделать специальный оператор для "взятия адреса" функции. Будет ли он ключевым словом agent, как в Eiffel или же оператором '&', как в D, уже не важно. Важно, что не будет неоднозначности.


Допустим, но это выбор между Uniform Access Principle и fco-функциями. Кроме того, я ведь не спорил с тем, что неоднозначность может представлять неудобство для программиста, я утверждал, что для компилятора статически и строго типизированного языка это не проблема.
... << 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[27]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 14.02.08 14:31
Оценка:
Здравствуйте, Klapaucius, Вы писали:

E>>Т.е. агенты в Eiffel -- это непосредственный аналог HOF.


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


А то, что в C вызов функции по указателю записывается не так, как вызов обычной функции -- это не является препятствием для того, чтобы qsort считать аналогом HOF?

K>Язык с fco:

K>
K>foo()
K>f = foo
K>f()
K>

K>Язык без fco:
K>
K>foo()
K>а = agent foo
K>a.call()
K>


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

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


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[27]: Функциональный/нефункциональный
От: Трурль  
Дата: 15.02.08 10:12
Оценка:
Здравствуйте, Klapaucius, Вы писали:
K>Язык с fco:
K>
K>foo()
K>f = foo
K>f()
K>

K>Язык без fco:
K>
K>foo()
K>а = agent foo
K>a.call()
K>


Язык с fco:
(define (foo)...)
(set! f  foo)
(f)


Язык без fco:
(defun foo ()...)
(setq f  (function foo))
(funcall f)
Re[28]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 16.02.08 10:53
Оценка:
Здравствуйте, eao197, Вы писали:

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

E>А то, что в C вызов функции по указателю записывается не так, как вызов обычной функции -- это не является препятствием для того, чтобы qsort считать аналогом HOF?

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

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


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

bar.foo()

Во-первых, разница не только в синтаксисе, но и в семантике. Я же говорю, что объект с одним методом это не то же самое, что функция. Ясно, что объект в Eiffel можно передавать по ссылке. Ну так и в 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[28]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 16.02.08 10:53
Оценка:
Здравствуйте, Трурль, Вы писали:

Т>Язык с fco:

Т>
Т>(define (foo)...)
Т>(set! f  foo)
Т>(f)
Т>


Т>Язык без fco:

Т>
Т>(defun foo ()...)
Т>(setq f  (function foo))
Т>(funcall f)
Т>


Ну так что из этого?
Это аргумент такого же класса, как и "Я отказываюсь верить, что число 4776913109852041418248056622882488319 — простое. Мне кажется, что оно ужасно сложное! Уж во всяком случае сложнее, чем 9"

Предположим, что мы хотим сформулировать какое-то правило, по которому отличим функциональный язык, от не функционального.
Есть, на самом деле, только два способа:
1) Индуктивный. Допустим, что у нас есть некий список языков, которые мы можем априорно считать функциональными, хотя и не знаем еще, что такое "функциональный". Например, этот список возвестили нам из горящего куста. Или утвердили на всемирном симпозиуме Организации Бюрократических Наций. Теперь проанализировав все случаи из этого списка, мы получим некоторое пересечение множеств фич этих языков, сопоставление с которым поможет нам определить функциональность языка, которого нет в списке.
Тут есть сложности. Во-первых, мы можем получить что-то вроде "двуногое без перьев", а во-вторых, непонятно, откуда это априорное знание о функциональности некоторых языков? На самом деле, для определения это не проблема. Все-таки определения существуют преимущественно для коммуникации, и тут общепринятость важна, но где взять этот список общепринятых функциональных языков?
2) Дедуктивный. Мы принимаем некоторые постулаты, и выводим из них некоторые следствия. Именно так я и сделал. Ясно, что результаты могут противоречить некоторым интуитивным представлениям. Но ведь согласовать два интуитивных представления тоже проблематично.
... << 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[29]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 16.02.08 11:01
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


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

K>
K>foo(bar)

K>bar.foo()
K>


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

K>Во-первых, разница не только в синтаксисе, но и в семантике. Я же говорю, что объект с одним методом это не то же самое, что функция. Ясно, что объект в Eiffel можно передавать по ссылке. Ну так и в Java можно по месту определить анонимный класс с одним методом. И что их этого следует? Что в Java функции первоклассные?


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

А вот агент в Eiffel -- это не объект.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[29]: Функциональный/нефункциональный
От: jazzer Россия Skype: enerjazzer
Дата: 16.02.08 11:07
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


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

K>
K>foo(bar)

K>bar.foo()
K>

эквивалентность этих двух синтаксисов, кстати, хотят ввести в будущих версиях С++ (в смысле, чтоб первое приводило к вызову второго).

K>Во-первых, разница не только в синтаксисе, но и в семантике. Я же говорю, что объект с одним методом это не то же самое, что функция. Ясно, что объект в Eiffel можно передавать по ссылке. Ну так и в Java можно по месту определить анонимный класс с одним методом. И что их этого следует? Что в Java функции первоклассные?

K>Во-вторых, когда речь идет о языке — форма записи это не какой-то незначительный вопрос.

А если этот метод имеет синтаксис вызова функции (как operator() в С++)?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[30]: Функциональный/нефункциональный
От: Курилка Россия http://kirya.narod.ru/
Дата: 16.02.08 11:13
Оценка:
Здравствуйте, eao197, Вы писали:

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


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


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

K>>
K>>foo(bar)

K>>bar.foo()
K>>


E>Вы будете смеятся, но в Nice это совершенно одно и то же.

E>И в D в некоторых случаях так же.

Плюс ещё в Скале подобная фишка, правда там нужен метод apply у класса для "закоса под функцию". Т.е. семантически класс с apply и функция есть одно и то же.
По-моему это вообще базовая фишка языков, которые допускают смешивание ФП и ООП.
BTW А в Немерле разве это нетак?
Re[29]: Функциональный/нефункциональный
От: Трурль  
Дата: 18.02.08 08:08
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Ну так что из этого?

K>Это аргумент такого же класса, как и "Я отказываюсь верить, что число 4776913109852041418248056622882488319 — простое. Мне кажется, что оно ужасно сложное! Уж во всяком случае сложнее, чем 9"
Нет, это аргумент такого же класса, как и "Я отказываюсь считать, что число 4776913109852041418248056622882488319 — простое, а число 0x397FFFFFFFFFFFFFFFFFFFFFFFFFFFF — нет".

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

Можно, конечно, делать и так. Но если результаты противоречат интуитивным представлениям, то получившийся термин будет иметь мало общего с исходным понятием.
Re[30]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 20.02.08 13:02
Оценка:
Здравствуйте, eao197, Вы писали:

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

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

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

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

K>>Во-первых, разница не только в синтаксисе, но и в семантике. Я же говорю, что объект с одним методом это не то же самое, что функция. Ясно, что объект в Eiffel можно передавать по ссылке. Ну так и в Java можно по месту определить анонимный класс с одним методом. И что их этого следует? Что в Java функции первоклассные?

E>Вообще-то, анонимный класс в Java как раз таки будет классом, со своим родительским классом и прочими атрибутами. В частности, для объекта этого класса можно определить его тип, базовый тип и т.д., выполнять приведение и прочее.
E>А вот агент в Eiffel -- это не объект.

Почему? Для того, чтобы быть объектом не нужно вообще-то иметь тип. Хотя тип у агента есть, не говоря уже о базовом классе.
Агент передается по правилам для объектов, у него есть метод call, который вызывается по правилам для объектов — я вижу семантику объекта. Если вызов функции через агент выглядит как вызов метода объекта, а не как вызов функции, почему агент следует считать функцией?
... << 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[30]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 20.02.08 13:02
Оценка:
Здравствуйте, jazzer, Вы писали:

K>>Во-первых, разница не только в синтаксисе, но и в семантике. Я же говорю, что объект с одним методом это не то же самое, что функция. Ясно, что объект в Eiffel можно передавать по ссылке. Ну так и в Java можно по месту определить анонимный класс с одним методом. И что их этого следует? Что в Java функции первоклассные?

K>>Во-вторых, когда речь идет о языке — форма записи это не какой-то незначительный вопрос.
J>А если этот метод имеет синтаксис вызова функции (как operator() в С++)?

Значит это шаг в направлении первоклассности функции.
... << 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[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++.
Re[44]: Функциональный/нефункциональный
От: dr.Chaos Россия Украшения HandMade
Дата: 26.02.08 12:19
Оценка:
eao197 wrote:

> Здравствуйте, dr.Chaos, Вы писали:

>
>>> Нет не предмет. Для вас. Поскольку вы считаете, что раз в Nice что-то
>>> называется функцией, значит это функция. А если это же самое называется
>>> в другом языке делегатом, то это не функция.
>>>
>>> Хотя разницу между ними найти лично мне очень тяжело.
>
> ИМХО эта разница примерно такая же, как между переменной и ссылкой на
> неё. В С++ это две разные сущности, хотя и могут применяться для
> решения одной и той же задачи.
>
> Я бы уточнил: разница как между объектом и ссылкой на него в таких языках,
> как Java/C#/D и др. Объект живет сам по себе, но обратиться к нему можно
> только через ссылку. И переменные в таких языках содержат не объекты, а
> ссылки на них.

Это уточнение меняет смысл моей фразы . Т.к. в этих языках сущность одна,
а то что там есть ссылка, дык это деталь реализации.

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

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

[skip]

Это особенность платформы. В Java, всё есть объект и трындец. Просто в Nice
эту особенность сделали, судя по твоим примерам, максимально незаметной.

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

> Nice они называются функциями.

Делегат это не функция . В Ди связка делегат+функция дают возможность
работать с функциями как с FCO. В Nice для этого достаточно лишь понятия
функции или функционального типа. В Ди есть функциональный тип?

> Т.е. дело только в названии.

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

>> Я бы уточнил: разница как между объектом и ссылкой на него в таких языках,

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

DC>Это уточнение меняет смысл моей фразы . Т.к. в этих языках сущность одна,

DC>а то что там есть ссылка, дык это деталь реализации.

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

DC>Делегат это не функция . В Ди связка делегат+функция дают возможность

DC>работать с функциями как с FCO. В Nice для этого достаточно лишь понятия
DC>функции или функционального типа. В Ди есть функциональный тип?

Не, ну сколько можно!
В Nice функциональный тип описывается как (A)->V, а в D как V delegate(A). Все остальное одно и то же.


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

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


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


Давайте попробуем вместе.

Вы утверждали, что & ставится для устранения неопределенности между вызовом и возвратом функционального значения.
Если мы имеем переменную со знаачением — делегатом — ситуация с неопределенностью в точности такая же, нес па?
Проделаем небольшой опыт. Я написал примеры на псевдо-D (я не знаю D и, вполне вероятно, допустил ошибки, надеюсь, что идея в каждом случае ясна):
Пример 1
T delegate(T a) foo(T)()
{
    T Id(T a)
    {
        return a;
    }
    
    return &Id; // в случае с Id неопределенность между вызовом и возвратом функции была бы возможна, 
    // если бы Id была функцией без параметров, зачем здесь уточнение непонятно, ну да ладно.
}

Пример 2
T delegate(T a) foo(T)()
{
    T delegate(T) id = (T a){return a;};
    
    return id; // в случае с id неопределенность между вызовом и возвратом функции была бы возможна и т.д.
    // ВОПРОС: сработает ли это без & ? 
}

Пример 3
T delegate() foo(T)()
{
    T bar()
    {
        // ничего не делается
    }
    
    return &bar; // в случае с bar неопределенность между вызовом и возвратом функции.
}

Пример 4
T delegate(T a) foo(T)()
{
    T delegate(T) bar = T delegate(){return a;};
    
    return bar; // в случае с bar неопределенность между вызовом и возвратом функции.
    // ВОПРОС: сработает ли это без & ? 
}

Если второй и четвертый примеры также требуют указания & — значит вы правы и & — просто указание для разрешения противоречия между вызовом и возвратом, если нет — значит прав я: делегат и функция — разные вещи не только на уровне реализации, но и на уровне языка.
... << 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[42]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 26.02.08 13:00
Оценка:
Здравствуйте, eao197, Вы писали:

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

K>>>>Такой же "функциональный тип" как и агент — ничуть не хуже. Более громоздкий синтаксис при оборачивании функции — да. Но факт явного оборачивания в обоих случаях — налицо. Использование вообще ничем не отличается.
E>>>Попробуйте передать реализацию этого интерфейса в конструктор TreeMap или в метод Arrays.sort вместо Comparator-а.
K>>Я показал, как делаются агенты в Java — то что стандартная библиотека их сейчас не поддерживает — другой вопрос.
E>Знаете, чем отличается математика от программирования? Это в математике можно показать способ решения какого-то класса задач и считать эту задачу решенной, а все остальное -- другой вопрос. В программировании мало показать способ -- нужно написать _работающую_ программу -- без программы нет решения. И это не другой -- это самый важный вопрос.

В огороде бузина — а в Киеве дядька. Допустим, что вопрос самый важный — но тем не менее другой. Факт, что у Java нет Map, Fold, Filter и "функциональных типов" в стандартной библиотеке, а если бы и были — пользоваться ими было бы не очень удобно из-за перегруженности синтаксиса анонимных классов. С практической точки зрения это имеет значение.
Тем не менее, в свете ваших заявлений о том, что надо смотреть не на "форму" (синтаксис?) а на "содержание" (семантику?) вопросы остаются.
Какая разница между агентом и анонимным классом с одним методом кроме синтаксической?
... << 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[43]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 26.02.08 15:46
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


Думаю, что по отношению к D это не совсем так, поскольку, как я говорил dr.Chaos, в Java нельзя получить ссылку на переменную, а вот в D можно. И использование &id или &bar во втором и четвертом примерах означало бы взятие адреса переменных id и bar.

Корректно ваш пример на D записывается следующим образом:
T delegate(T a) foo1(T)()
{
    T Id(T a)
    {
        return a;
    }
    
    return &Id;
}


T delegate(T a) foo2(T)()
{
    T delegate(T) id = (T a) { return a; };
    
    return id;
}


T delegate() foo3(T)()
{
    T bar() { return T.init; }
    
    return &bar;
}


T delegate(T a) foo4(T)()
{
    T delegate(T) bar = delegate T(T a) { return a; };
    
    return bar;
}

void main()
{
    auto f1 = foo1!(int)();
    auto f2 = foo2!(int)();
    auto f3 = foo3!(int)();
    auto f4 = foo4!(int)();
}


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

K>Тем не менее, в свете ваших заявлений о том, что надо смотреть не на "форму" (синтаксис?) а на "содержание" (семантику?) вопросы остаются.

K>Какая разница между агентом и анонимным классом с одним методом кроме синтаксической?

Агент может получать ссылку на уже реализованный в каком-то классе метод. Например:
agent my_object.some_method

Тогда как при инстанциировании анонимного класса нужно делать вызов этого метода явно внутри самостоятельно реализованного метода call:
new Agent { public void call() { myObject.some_method(); } };

Т.е. здесь программиста заставляют сделать две вещи: определить метод call() и самостоятельно написать вызов some_method. Тогда как в агенте указывается только какой метод должен вызываться.


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

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

E>Думаю, что по отношению к D это не совсем так, поскольку, как я говорил dr.Chaos, в Java нельзя получить ссылку на переменную, а вот в D можно. И использование &id или &bar во втором и четвертом примерах означало бы взятие адреса переменных id и bar.

Ну вот, значит & вовсе не является элементом синтаксиса для разрешения противоречия, ведь в случае
T delegate(T a) foo4(T)()
{
    T delegate(T) bar = delegate T(T a) { return a; };
    
    return bar;
}

компилятор принимает решение о том, что нужно возвращать делегат, а не вызывать функцию без параметров bar по сведеньям о типах, которые у него есть.
Как я и предполагал — делегат и функция — разные сущности и на уровне языка делегат это "ссылка на функцию" (пусть и с неявным контекстом), причем сходство с ссылкой на переменную подчеркивается.
Что касается примера с явой — там нет ссылки, как отдельной сущности — там есть ссылочные типы. А в D — ссылка это отдельная сущность. Точно также и делегат — сущность отдельная.
Можно сделать следующие выводы:
1) Функция и делегат разные сущности
2) Различается не только синтаксис, но и семантика.
... << 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[44]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 27.02.08 13:05
Оценка:
Здравствуйте, eao197, Вы писали:

K>>Какая разница между агентом и анонимным классом с одним методом кроме синтаксической?

E>Агент может получать ссылку на уже реализованный в каком-то классе метод. Например:
E>
E>agent my_object.some_method
E>

E>Тогда как при инстанциировании анонимного класса нужно делать вызов этого метода явно внутри самостоятельно реализованного метода call:
E>
E>new Agent { public void call() { myObject.some_method(); } };
E>

E>Т.е. здесь программиста заставляют сделать две вещи: определить метод call() и самостоятельно написать вызов some_method. Тогда как в агенте указывается только какой метод должен вызываться.

И это, по-вашему, разница по форме или по содержанию?
... << 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[45]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 27.02.08 13:58
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>>>Какая разница между агентом и анонимным классом с одним методом кроме синтаксической?

E>>Агент может получать ссылку на уже реализованный в каком-то классе метод. Например:
E>>
E>>agent my_object.some_method
E>>

E>>Тогда как при инстанциировании анонимного класса нужно делать вызов этого метода явно внутри самостоятельно реализованного метода call:
E>>
E>>new Agent { public void call() { myObject.some_method(); } };
E>>

E>>Т.е. здесь программиста заставляют сделать две вещи: определить метод call() и самостоятельно написать вызов some_method. Тогда как в агенте указывается только какой метод должен вызываться.

K>И это, по-вашему, разница по форме или по содержанию?


По содержанию.

Вызов f() вместо f.call() -- это синтаксический сахар.
Но вот инструкция agent вместо ручного инстанцирования интерфейса -- это уже не синтаксический сахар.


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

K>Как я и предполагал — делегат и функция — разные сущности и на уровне языка делегат это "ссылка на функцию" (пусть и с неявным контекстом), причем сходство с ссылкой на переменную подчеркивается.

K>Что касается примера с явой — там нет ссылки, как отдельной сущности — там есть ссылочные типы. А в D — ссылка это отдельная сущность. Точно также и делегат — сущность отдельная.
K>Можно сделать следующие выводы:
K>1) Функция и делегат разные сущности
K>2) Различается не только синтаксис, но и семантика.

Как я уже говорил, в языках типа D, Java, Nice функция -- это блок кода, который можно либо вызвать непосредственно, либо получить на него ссылку. Следовательно, любые переменные, которые ссылаются на функции -- это ссылки на функции, со своей семантикой. И ссылки не являются функциями. Только в D ссылки называются делагатами, а в Nice -- функциями. Но семантика ссылок сохраняется. И вот пример в подтверждение:
void main( String[] args )
    {
        int inc( int a ) = a + 1;
        int dec( int a ) = a - 1;

        (int)?->int f = inc;
        f = null;
        f = dec;
    }

Конструкция (int)?->int описывает ссылку на функцию (int)->int, которая может быть нулевой. И вы можете увидеть в примере, как переменной f присваивается null.


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

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

K>Если бы можно было написать так:
K>
K> V finalResult( U b )
K>    {
K>        return func( a, b );
K>    }
K>return finalResult;
K>

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


Вопрос, видимо, сводиться к тому, что, собственно, такое функция. Попробую определить функцию как нечто(некий черный ящик, к которому можно обратиться), что может быть вызвано с передачей параметров и возвращающее какое-то значение.
int f(int x, double y)
{
  return 1;
}

f — это функция. Вопрос в том, является ли &f тоже функцией, можно ли делать, например, так: z=(&f)(1,1.0) ?

  return  &f;

Это можно интерпретировать так
  return& f;

Т.е. для возвращения ф-ии необходим оперетор "return&"
Аналогично
  f2 =& f;

Для присваивания функций нужен оперетор "&=".
  f3(&f);

Даже здесь происходит неявное присваивание "=&" параметру ф-ии f3.
Т.е. ф-ии в С тоже первокласные, только для их использования нужны специальные операторы

ЗЫ Прошу воспринимать как шутку
Re[33]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 29.02.08 18:08
Оценка:
код:

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

void main (String[] args)
{
  let f = () => println("Hello!");
  println (f.getClass().getName());
  println (foo.getClass().getName() );
}


вывод:

gnu.expr.ModuleMethod
gnu.expr.ModuleMethod
... << 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[46]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 29.02.08 18:21
Оценка:
Здравствуйте, eao197, Вы писали:

E>Как я уже говорил, в языках типа D, Java, Nice функция -- это блок кода, который можно либо вызвать непосредственно, либо получить на него ссылку. Следовательно, любые переменные, которые ссылаются на функции -- это ссылки на функции, со своей семантикой. И ссылки не являются функциями. Только в D ссылки называются делагатами, а в Nice -- функциями. Но семантика ссылок сохраняется.


В Nice ссылка не называется функцией. Ссылки как отдельной сущности в Nice (как и в Java), насколько я понимаю, нет. Просто функциональный тип — это ссылочный тип. и семантика у него — семантика ссылочного типа.
Если бы функция в D была первоклассной, функциональный объект, представляющий из себя функцию и замыкание можно было бы передать не только по ссылке, но и копированием, не так ли?
... << 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[34]: Функциональный/нефункциональный
От: VoidEx  
Дата: 29.02.08 18:22
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>код:


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

K>void main (String[] args)
K>{
K>  let f = () => println("Hello!");
K>  println (f.getClass().getName());
K>  println (foo.getClass().getName() );
K>}
K>


K>вывод:


K>
K>gnu.expr.ModuleMethod
K>gnu.expr.ModuleMethod
K>


Спасибо, что все-таки ответили
Тогда я полностью разделяю вашу точку зрения.

Есть два возможных варианта:
1. foo — определение функции и тогда то, что foo также является объектом, уже роли никакой не играет. С ней можно обращаться как с любым объектом, т.е. она является первоклассной сущностью, в отличие от функций в Д, где их надо оборачивать в объект-делегат.
2. foo — определение не функции, а объекта, просто выглядящее, как определение функции. Тогда придется утверждать, что в Nice вообще нет функций, их роль выполняют объекты, а спор переходит уже в исключительно терминологический. Мне этот вариант кажется неприемлемым, потому что даже если это определение объекта, то как минимум с методом Тогда что такое метод?
Re[34]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 01.03.08 05:56
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>код:


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

K>void main (String[] args)
K>{
K>  let f = () => println("Hello!");
K>  println (f.getClass().getName());
K>  println (foo.getClass().getName() );
K>}
K>


K>вывод:


K>
K>gnu.expr.ModuleMethod
K>gnu.expr.ModuleMethod
K>


Если вы пропустите скомпилированный код через jad, то увидите, что конструкции f.getClass и foo.getClass применяются не к функциям, а к специальным объектам, которые Nice создает для хранения ссылок на эти функции.


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

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


E>>Как я уже говорил, в языках типа D, Java, Nice функция -- это блок кода, который можно либо вызвать непосредственно, либо получить на него ссылку. Следовательно, любые переменные, которые ссылаются на функции -- это ссылки на функции, со своей семантикой. И ссылки не являются функциями. Только в D ссылки называются делагатами, а в Nice -- функциями. Но семантика ссылок сохраняется.


K>В Nice ссылка не называется функцией. Ссылки как отдельной сущности в Nice (как и в Java), насколько я понимаю, нет.


Переменная, ссылающаяся на ссылочный тип или аргумент функции, ссылающийся на ссылочный тип, или атрибут класса, ссылающийся на ссылочный тип -- это все ссылки. Как в Nice, так и в Java.

K>Просто функциональный тип — это ссылочный тип. и семантика у него — семантика ссылочного типа.


Мне, вероятно, нужно еще многому учиться, чтобы понять, что функция может иметь прототип (int)->int, но не иметь тела, а быть null-ом.
Что так может быть с ссылкой, я понимаю. А вот что так может быть с функциями...

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


Если бы функция в Nice была первоклассной, функциональный объект, представляющий из себя функцию и замыкание можно было бы передать не только по ссылке, но и копированием, не так ли?


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

VE>Есть два возможных варианта:

VE>1. foo — определение функции и тогда то, что foo также является объектом, уже роли никакой не играет. С ней можно обращаться как с любым объектом, т.е. она является первоклассной сущностью, в отличие от функций в Д, где их надо оборачивать в объект-делегат.
VE>2. foo — определение не функции, а объекта, просто выглядящее, как определение функции. Тогда придется утверждать, что в Nice вообще нет функций, их роль выполняют объекты, а спор переходит уже в исключительно терминологический. Мне этот вариант кажется неприемлемым, потому что даже если это определение объекта, то как минимум с методом Тогда что такое метод?

Посмотрите на то, во что компилятор Nice превращает код по работе с функциями и ссылками на функции, например, вот здесь
Автор: eao197
Дата: 26.02.08
.
Там видно, что непосредственный вызов функции происходит совсем не так, как вызов через ссылку. Отличие Nice от D в том, что в Nice ссылки на функции генерируются неявно. Что не столько достоинство языка или показатель его функциональной оринтированности, сколько проявление непоследовательности, поскольку эквивалентные конструкции в Nice приводят к разным результатам. Так, в Nice:
class A {
  void f() {}
  void demo() {
    f; // Это ссылка на функцию.
    this.f; // Это вызов функции.
  }
}

Хотя казалось бы, в чем разница?
В то же время, в таких языках, как D или Eiffel обе эти конструкции означают одно и то же, что и ожидается.


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


E>Посмотрите на то, во что компилятор Nice превращает код по работе с функциями и ссылками на функции, например, вот здесь
Автор: eao197
Дата: 26.02.08
.

E>Там видно, что непосредственный вызов функции происходит совсем не так, как вызов через ссылку. Отличие Nice от D в том, что в Nice ссылки на функции генерируются неявно. Что не столько достоинство языка или показатель его функциональной оринтированности, сколько проявление непоследовательности, поскольку эквивалентные конструкции в Nice приводят к разным результатам. Так, в Nice:
E>
E>class A {
E>  void f() {}
E>  void demo() {
E>    f; // Это ссылка на функцию.
E>    this.f; // Это вызов функции.
E>  }
E>}
E>

E>Хотя казалось бы, в чем разница?
E>В то же время, в таких языках, как D или Eiffel обе эти конструкции означают одно и то же, что и ожидается.

Хм... Ну если компилятор неявно преобразовывает, то тут без ответа автора языка не обойтись. Реализация, конечно, важна, но чисто формально неявное преобразование и эквивалентность вещи разные. Возможно, там имеется ввиду именно то, что функция является объектом, а ее неявное преобразование — деталь реализации, а возможно и нет. Может, это и правда неявное преобразование.
Без ответа автора надо лишь искать различие в поведении с обычными объектами. Если никак не различимо, то тут неважно, как оно в реализации, но, видимо, код, приведенный вами, для других объектов будет означать уже одно и то же.
Но тут действительно непоследовательность, одно от другого по логике не должно отличаться. Даже если представить, что функция также является объектом, то что такое { f } должно определяться как-то однозначно, то ли ее вызов, то ли она сама (ссылка на нее, если угодно). Это уже, по-моему, такие тонкости, что не разберешь. Ибо в любом случае, если функция есть объект, как-то надо различать, "берем" мы этот объект, или вызываем его как функцию, может, это один из способов.
Re[37]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 02.03.08 06:51
Оценка:
Здравствуйте, VoidEx, Вы писали:

E>>В то же время, в таких языках, как D или Eiffel обе эти конструкции означают одно и то же, что и ожидается.


VE>Хм... Ну если компилятор неявно преобразовывает, то тут без ответа автора языка не обойтись.


Автор языка уже давно раставил все точки над i. У него в каждом исходном файле компилятора написано:
/**************************************************************************/
/*                                N I C E                                 */
/*             A high-level object-oriented research language             */

Ни о какой функциональности речи нет

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

VE>Но тут действительно непоследовательность, одно от другого по логике не должно отличаться. Даже если представить, что функция также является объектом, то что такое { f } должно определяться как-то однозначно, то ли ее вызов, то ли она сама (ссылка на нее, если угодно).


Я по ходу этой дискуссии попробовал получить в качестве функции метод объекта в Nice -- и не нашел как. Т.е., в случае со свободной функцией:
int inc( int a ) = a + 1;

void main( String[] args ) {
  let f = inc;
}

f -- это всегда (int)->int. Но в случае с объектом:
class A {
  int inc( int a ) = a + 1;
}

void main( String[] args ) {
  let o = new A();
  let f = o.f;
}

o.f -- это всегда вызов функции (хотя казалось бы, что в функциональном языке это должно было бы означать взятие ссылки на метод). И данный пример не скомпилируется, поскольку o.f требует аргумент. В то же время в D и Eiffel превращение метода объекта в делегат/агент опроисходит обычным образом.

Имхо, все это свидетельсво того, что Nice просто еще не доработан. Все-таки версия 0.9.13, не 1.0. И, возможно, будь он доработан до более-менее логичного поведения с функциями/методами, он бы не сильно отличался от D и Eiffel-я.


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

K>>В Nice ссылка не называется функцией. Ссылки как отдельной сущности в Nice (как и в Java), насколько я понимаю, нет.

E>Переменная, ссылающаяся на ссылочный тип или аргумент функции, ссылающийся на ссылочный тип, или атрибут класса, ссылающийся на ссылочный тип -- это все ссылки. Как в Nice, так и в Java.

Разница между языком со ссылками и языком со ссылочными типами в данном случае в том, что в первом можно и нужно явно указывать способ передачи — по ссылке или по значению, а во втором это определяется свойствами типа.
Можно ли в D передать объект по значению? Или только по ссылке?

И да, кстати, является ли тип RT delegate(T) типом всех видов функций T->RT в D (т.е. экземплярных, статических, свободных)?
... << 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[46]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 02.03.08 08:00
Оценка:
Здравствуйте, eao197, Вы писали:

K>>И это, по-вашему, разница по форме или по содержанию?

E>По содержанию.
E>Вызов f() вместо f.call() -- это синтаксический сахар.
E>Но вот инструкция agent вместо ручного инстанцирования интерфейса -- это уже не синтаксический сахар.

А какой критерий?

Разница между foo(bar) и foo(agent bar) — это синтаксический сахар или нет?
... << 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[35]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 02.03.08 08:00
Оценка:
Здравствуйте, eao197, Вы писали:

E>Если вы пропустите скомпилированный код через jad, то увидите, что конструкции f.getClass и foo.getClass применяются не к функциям, а к специальным объектам, которые Nice создает для хранения ссылок на эти функции.


Вообще-то это детали реализации.
... << 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[38]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 02.03.08 09:16
Оценка:
Здравствуйте, eao197, Вы писали:

E>Я по ходу этой дискуссии попробовал получить в качестве функции метод объекта в Nice -- и не нашел как. Т.е., в случае со свободной функцией:

E>
E>int inc( int a ) = a + 1;

E>void main( String[] args ) {
E>  let f = inc;
E>}
E>

E>f -- это всегда (int)->int. Но в случае с объектом:
E>
E>class A {
E>  int inc( int a ) = a + 1;
E>}

E>void main( String[] args ) {
E>  let o = new A();
E>  let f = o.f; // вы, конечно, имели в виду o.inc
E>}
E>


class A {
  int inc(int a ) = a + 1;
}

void main( String[] args ) {
  let o = new A();
  let i = o.inc(1);
  let f = inc; // вот как это делается
  let j = f(o, 1);
  println(i == j);
}

выводит true

Просто o.inc воспринимается как inc(o, ?), а частичного применения, как я понял, в Nice нет. Жалко, конечно, но жизнь есть жизнь.
... << 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[49]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 02.03.08 09:45
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


K>>>В Nice ссылка не называется функцией. Ссылки как отдельной сущности в Nice (как и в Java), насколько я понимаю, нет.

E>>Переменная, ссылающаяся на ссылочный тип или аргумент функции, ссылающийся на ссылочный тип, или атрибут класса, ссылающийся на ссылочный тип -- это все ссылки. Как в Nice, так и в Java.

K>Разница между языком со ссылками и языком со ссылочными типами в данном случае в том, что в первом можно и нужно явно указывать способ передачи — по ссылке или по значению, а во втором это определяется свойствами типа.

K>Можно ли в D передать объект по значению? Или только по ссылке?

В D, как и в C#, типы делятся на reference type (классы) и value type (структуры и элементарные типы). Соответственно экземпляры reference-типов передаются либо по ссылке, либо по указателю, но не по значению. А экземпляры value-типов передаются либо по значению, либо по указателю, но ссылок для них в D нет.

K>И да, кстати, является ли тип RT delegate(T) типом всех видов функций T->RT в D (т.е. экземплярных, статических, свободных)?


Насколько я знаю -- да.


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

K>
K>class A {
K>  int inc(int a ) = a + 1;
K>}

K>void main( String[] args ) {
K>  let o = new A();
K>  let i = o.inc(1);
K>  let f = inc; // вот как это делается
K>  let j = f(o, 1);
K>  println(i == j);
K>}
K>

K>выводит true

Теперь добавте в область видимости еще несколько объектов с методом inc или свободных функций inc.

И почему, внутри класса A метод inc имеет сигнатуру (int)->int, а вне -- (A,int)->int? Это, вообще-то говоря, разные функции. Ведь, например, если я имею некую HOF, который ожидает функцию вида (int)->int, то я не смогу передать в него метод inc именно объекта o.


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

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


K>>>И это, по-вашему, разница по форме или по содержанию?

E>>По содержанию.
E>>Вызов f() вместо f.call() -- это синтаксический сахар.
E>>Но вот инструкция agent вместо ручного инстанцирования интерфейса -- это уже не синтаксический сахар.

K>А какой критерий?


Мое субъективное восприятие синтаксического сахара.

K>Разница между foo(bar) и foo(agent bar) — это синтаксический сахар или нет?


Нет.


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

K>>
K>>class A {
K>>  int inc(int a ) = a + 1;
K>>}

K>>void main( String[] args ) {
K>>  let o = new A();
K>>  let i = o.inc(1);
K>>  let f = inc; // вот как это делается
K>>  let j = f(o, 1);
K>>  println(i == j);
K>>}
K>>

K>>выводит true

E>Теперь добавте в область видимости еще несколько объектов с методом inc или свободных функций inc.

E>И почему, внутри класса A метод inc имеет сигнатуру (int)->int, а вне -- (A,int)->int?

Это только сахар. В Nice вообще нет, фактически, обычных методов. Любой метод — частный случай мультиметода. Диспетчеризация-то множественная, в общем случае.

Фактически нет разницы между
class A {
  int inc(int a ) = a + 1;
}

И
class A {
}

int inc(A t, int a) = a + 1;


E>Это, вообще-то говоря, разные функции.


В том-то и дело, что нет.

E>Ведь, например, если я имею некую HOF, который ожидает функцию вида (int)->int, то я не смогу передать в него метод inc именно объекта o.


Точно. Частичного применения-то нет. Нужно писать так: curry(method_name)(object_variable)
... << 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[50]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 02.03.08 12:20
Оценка:
Здравствуйте, eao197, Вы писали:

K>>Разница между языком со ссылками и языком со ссылочными типами в данном случае в том, что в первом можно и нужно явно указывать способ передачи — по ссылке или по значению, а во втором это определяется свойствами типа.

K>>Можно ли в D передать объект по значению? Или только по ссылке?
E>В D, как и в C#, типы делятся на reference type (классы) и value type (структуры и элементарные типы). Соответственно экземпляры reference-типов передаются либо по ссылке, либо по указателю, но не по значению.

И & явно указывается?

E>А экземпляры value-типов передаются либо по значению, либо по указателю, но ссылок для них в D нет.


K>>И да, кстати, является ли тип RT delegate(T) типом всех видов функций T->RT в D (т.е. экземплярных, статических, свободных)?

E>Насколько я знаю -- да.

Я уже нашел здесь.

Delegates

There are no pointers-to-members in D, but a more useful concept called delegates are supported. Delegates are an aggregate of two pieces of data: an object reference and a function pointer. The object reference forms the this pointer when the function is called.

Delegates are declared similarly to function pointers, except that the keyword delegate takes the place of (*), and the identifier occurs afterwards:

int function(int) fp;    // fp is pointer to a function
int delegate(int) dg;    // dg is a delegate to a function


The C style syntax for declaring pointers to functions is also supported:

int (*fp)(int);        // fp is pointer to a function


A delegate is initialized analogously to function pointers:

int func(int);
fp = &func;        // fp points to func

class OB
{   int member(int);
}
OB o;
dg = &o.member;        // dg is a delegate to object o and
            // member function member


Delegates cannot be initialized with static member functions or non-member functions.

Delegates are called analogously to function pointers:

fp(3);        // call func(3)
dg(3);        // call o.member(3)

... << 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[41]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 02.03.08 12:43
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Фактически нет разницы между

K>
K>class A {
K>  int inc(int a ) = a + 1;
K>}
K>

K>И
K>
K>class A {
K>}

K>int inc(A t, int a) = a + 1;
K>


Между этими нет. Но проблема не в этом, а в том, что имея в одной области видимости:
class A { int inc(int a) = ... }
class B { int inc(int a) = ... }
int inc(int a) = ...;

В Nice не видно способа сделать выбор в пользу какого то из них.

E>>Это, вообще-то говоря, разные функции.


K>В том-то и дело, что нет.


Ну я не знаю, как, в принципе, (int)->int может быть тем же самым, что и (A, int)->int. Это разные функции и, как вы сами показали ниже, нужно вручную приводить одно к другому.

E>>Ведь, например, если я имею некую HOF, который ожидает функцию вида (int)->int, то я не смогу передать в него метод inc именно объекта o.


K>Точно. Частичного применения-то нет. Нужно писать так: curry(method_name)(object_variable)


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

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


K>>>Разница между языком со ссылками и языком со ссылочными типами в данном случае в том, что в первом можно и нужно явно указывать способ передачи — по ссылке или по значению, а во втором это определяется свойствами типа.

K>>>Можно ли в D передать объект по значению? Или только по ссылке?
E>>В D, как и в C#, типы делятся на reference type (классы) и value type (структуры и элементарные типы). Соответственно экземпляры reference-типов передаются либо по ссылке, либо по указателю, но не по значению.

K>И & явно указывается?


Где именно?
Вот как работают ссылочные типы в D:
class Demo { ... }
void f( Demo d ) {
  // d -- это ссылка на экземпляр Demo.
}
void g() {
  Demo o = new Demo; // o -- это ссылка на экземпляр Demo.
  f( o ); // Передача по ссылке.
}


E>>А экземпляры value-типов передаются либо по значению, либо по указателю, но ссылок для них в D нет.


K>>>И да, кстати, является ли тип RT delegate(T) типом всех видов функций T->RT в D (т.е. экземплярных, статических, свободных)?

E>>Насколько я знаю -- да.

K>Я уже нашел здесь.


Просуммировать то, что там написано можно так:
— свободные функции и статические методы -- это R function(A);
— методы объектов и вложенные функции -- это R delegate(A).


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

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


E>>Если вы пропустите скомпилированный код через jad, то увидите, что конструкции f.getClass и foo.getClass применяются не к функциям, а к специальным объектам, которые Nice создает для хранения ссылок на эти функции.


K>Вообще-то это детали реализации.


Это было бы деталями реализации, если бы у Nice была спецификация языка и несколько независимых реализаций компиляторов. А в данном случае это всего лишь демонстрация того, что при необходимости представления ссылки на функцию Nice прибегает к тем же средствам, что и Eiffel -- конструированию объекта, содержащего ссылку на функцию/метод. И того, что foo.getClass -- это обращение не к функции (т.е. функция не является объектом, в чем сомневался VoidEx), а к неявно сконструированному объекту, содержащему ссылку на функцию.


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

E>
E>class A { int inc(int a) = ... }
E>class B { int inc(int a) = ... }
E>int inc(int a) = ...;
E>

E>В Nice не видно способа сделать выбор в пользу какого то из них.

class A {
  int inc(int a ) = a + 1;
}

int inc(int a) = a + 1;

void main( String[] args ) {
  let o = new A();
  let i = o.inc(1);
  (A, int)->int f = inc;
  let j = f(o, 1);
  println(i == j);
}


E>Ну я не знаю, как, в принципе, (int)->int может быть тем же самым, что и (A, int)->int.

И почему, внутри класса A метод inc имеет сигнатуру (int)->int, а вне -- (A,int)->int? Это, вообще-то говоря, разные функции.


Еще раз. Метод имеет сигнатуру (A,int)->int. Внутри он, снаружи — это не важно. просто первый аргумент может в некоторых случаях быть неявным.
... << 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[52]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 02.03.08 15:07
Оценка:
Здравствуйте, eao197, Вы писали:

E>Вот как работают ссылочные типы в D:

E>
E>class Demo { ... }
E>void f( Demo d ) {
E>  // d -- это ссылка на экземпляр Demo.
E>}
E>void g() {
E>  Demo o = new Demo; // o -- это ссылка на экземпляр Demo.
E>  f( o ); // Передача по ссылке.
E>}
E>


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

K>>Я уже нашел здесь.

E>Просуммировать то, что там написано можно так:
E>- свободные функции и статические методы -- это R function(A);
E>- методы объектов и вложенные функции -- это R delegate(A).

Просуммировать это можно так. В D нет функциональных типов, а есть ссылка на функцию и то, что считается продвинутым аналогом указателя на член класса. Функции и "ссылки" на них делятся на два сорта, что не может не сказаться отрицательно на универсальности аналогов hof. Упрощенно говоря, задачи, которые решаются в функциональном языке первоклассными функциями, в D решаются с помощью четырех различных сущностей. C'est charmant!
... << 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[37]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 02.03.08 15:07
Оценка:
Здравствуйте, eao197, Вы писали:

E>>>Если вы пропустите скомпилированный код через jad, то увидите, что конструкции f.getClass и foo.getClass применяются не к функциям, а к специальным объектам, которые Nice создает для хранения ссылок на эти функции.

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

Детали реализации, на мой взгляд, — это детали реализации вне зависимости от того, существует одна реализация, две, или вообще ни одной.
Если это не деталь реализации, то это деталь чего, позвольте спросить?

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


Вот только в Eiffel это явно прописывается в коде, а в Nice на уровне языка никак не проявляется.
... << 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[43]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 02.03.08 16:32
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>
K>class A {
K>  int inc(int a ) = a + 1;
K>}

K>int inc(int a) = a + 1;

K>void main( String[] args ) {
K>  let o = new A();
K>  let i = o.inc(1);
K>  (A, int)->int f = inc;
K>  let j = f(o, 1);
K>  println(i == j);
K>}
K>


Это частный случай, когда можно сделать различие по типам аргументов. Представте, например, что есть:
// Первый файл.
package p1;

void serialize( String s, long l ) { ... }

// Второй файл.
package p2;

void serialize( String s, long l ) { ... }

// Третий файл.
import p1;
import p2;

void main( String[] args ) {
  (String, long)->void f = serialize;
}


Полное имя p1.serialize компилятор nice не считает валидным выражением.

E>>Ну я не знаю, как, в принципе, (int)->int может быть тем же самым, что и (A, int)->int.

K>

K>И почему, внутри класса A метод inc имеет сигнатуру (int)->int, а вне -- (A,int)->int? Это, вообще-то говоря, разные функции.


K>Еще раз. Метод имеет сигнатуру (A,int)->int. Внутри он, снаружи — это не важно. просто первый аргумент может в некоторых случаях быть неявным.


Да, это я ошибся.


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

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


E>>>>Если вы пропустите скомпилированный код через jad, то увидите, что конструкции f.getClass и foo.getClass применяются не к функциям, а к специальным объектам, которые Nice создает для хранения ссылок на эти функции.

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

K>Детали реализации, на мой взгляд, — это детали реализации вне зависимости от того, существует одна реализация, две, или вообще ни одной.


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

K>Если это не деталь реализации, то это деталь чего, позвольте спросить?


Реализации, реализации. Только вот эта деталь показывает, что функции в Nice не копируются. И функциональные типы в действительности являются ссылками на функции. Это такая деталь, которую хорошо бы понимать при использовании языка.

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


K>Вот только в Eiffel это явно прописывается в коде, а в Nice на уровне языка никак не проявляется.


Программист от этого вряд ли сильно страдает, ведь в Eiffel он все равно может делать то же самое, что и в Nice.


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

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


E>>Вот как работают ссылочные типы в D:

E>>
E>>class Demo { ... }
E>>void f( Demo d ) {
E>>  // d -- это ссылка на экземпляр Demo.
E>>}
E>>void g() {
E>>  Demo o = new Demo; // o -- это ссылка на экземпляр Demo.
E>>  f( o ); // Передача по ссылке.
E>>}
E>>


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


Что явным образом указывать? Ссылка на функцию -- это делегат. Делегат передается либо по значению, либо по указателю. Объекты тут причем? Объекты используются в Eiffel и Nice.

K>>>Я уже нашел здесь.

E>>Просуммировать то, что там написано можно так:
E>>- свободные функции и статические методы -- это R function(A);
E>>- методы объектов и вложенные функции -- это R delegate(A).

K>Просуммировать это можно так. В D нет функциональных типов, а есть ссылка на функцию и то, что считается продвинутым аналогом указателя на член класса. Функции и "ссылки" на них делятся на два сорта, что не может не сказаться отрицательно на универсальности аналогов hof.


С чего бы это? Когда в Nice нужно привести (A, int)->int к (int)->int вас не смущает использовать карринг. А в D выразить int function(int) через int delegate(int) как два байта переслать, и это орицательно сказывается?

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


Четыре откуда?


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

K>>Детали реализации, на мой взгляд, — это детали реализации вне зависимости от того, существует одна реализация, две, или вообще ни одной.

E>Если вообще нет ни одной реализации, то речь не может идти о языке программирования. Максимум -- о проекте языка.

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

E>Только вот эта деталь показывает, что функции в Nice не копируются.


А это, как раз, не деталь реализации. Это семантика функциональных типов. Они в Nice — ссылочные.

E>И функциональные типы в действительности являются ссылками на функции.


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

E>Это такая деталь, которую хорошо бы понимать при использовании языка.


Естественно.

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

K>>Вот только в Eiffel это явно прописывается в коде, а в Nice на уровне языка никак не проявляется.
E>Программист от этого вряд ли сильно страдает, ведь в Eiffel он все равно может делать то же самое, что и в Nice.

Еще раз. Мы говорим не о каких-то гипотетических страданиях программистов на 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[54]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 02.03.08 18:48
Оценка:
Здравствуйте, eao197, Вы писали:

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

E>Что явным образом указывать?

Явно указывать взятие ссылки на функцию.

E>Объекты тут причем?


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

K>>Просуммировать это можно так. В D нет функциональных типов, а есть ссылка на функцию и то, что считается продвинутым аналогом указателя на член класса. Функции и "ссылки" на них делятся на два сорта, что не может не сказаться отрицательно на универсальности аналогов hof.

E>С чего бы это? Когда в Nice нужно привести (A, int)->int к (int)->int вас не смущает использовать карринг. А в D выразить int function(int) через int delegate(int) как два байта переслать, и это орицательно сказывается?

Меня не смущает использование карринга для того, чтобы из функции типа A * int -> int сделать функцию типа int -> int. Но вот два несовместимых типа int -> int и int -> int меня несколько напрягают. На том же C# можно написать сколько угодно несовместимых типов int -> int, вот только функция типа int -> int будет подходить к любому из них.

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

E>Четыре откуда?

Два сорта функций и два сорта делегатов. Итого — четыре. То, что функция и подходящий ей делегат — разные сущности я уже продемонстрировал примером на псевдо-D выше.
... << 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[55]: Функциональный/нефункциональный
От: VoidEx  
Дата: 02.03.08 22:12
Оценка: 7 (1) :)
Здравствуйте, Klapaucius, Вы писали:

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

E>>Что явным образом указывать?

K>Явно указывать взятие ссылки на функцию.


E>>Объекты тут причем?


K>Объекты при том, что для их передачи не нужно явным образом брать ссылку. Они просто имеют семантику ссылочного типа — вот и все.


Кстати, с этой стороны тоже надо посмотреть на вопрос.

eao197, Klapaucius, если взять язык типа C#, но без struct. Т.е. все пользовательские объекты будут иметь ссылочную семантику. Вопрос: объекты будут первоклассными сущностями? Передать их в функцию нельзя (только ссылку), вернуть нельзя (только ссылку), но можно создавать и удалять.
Теперь возьмем работу с функцией как в C++, т.е. не обязательно указывать &foo, можно просто foo, и для вызова аналогично. Понятно, что это сахар, да еще, ЕМНИП, не стандартный, хотя тут не копался, не столь важный вопрос. Но все же — функции в данном случае первоклассны или нет?
Если объекты в приведенном псевдо-C# не первоклассны, то вопросов нет.
Если объекты первоклассны, а функции в Си++ — нет, тогда почему? Что еще нужно, создание и удаление?

Хотелось бы услышать мнение обоих, спасибо

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

void foo (int -> int & fun_ref)
{
  fun_ref << (x){ assert(x > 0); } // добавили новый код в начало - проверка параметра
}

int my (int x) { return x - 10; } // объявили новую функцию

void test()
{
  foo (my); // изменили ее
  my (-10); // ошибка!
}

Можно, правда, считать, что стандартное объявление — это именно определение константной функции, т.е.

int const x = 5;
int my_x (int x) { return x - 10; } // константная функция
int y = 6; // мутабельный объект
int -> int my_y = (x){return x - 10;} // мутабельная функция


Т.е. my_x — аналогично char const * c = "dsfsdf" которое может расположиться в read-only памяти и менять которое никак нельзя. А для того, чтобы быть функциональным, языку необходимо поддерживать именно копирование, создание, передачу по ссылке и все все, что имеется для объектов.
Т.е. варианта два: или наделять функции этими возможностями, или отнимать их у объектов. Например, убрать мутабельность
Re[40]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.03.08 06:24
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


K>>>Детали реализации, на мой взгляд, — это детали реализации вне зависимости от того, существует одна реализация, две, или вообще ни одной.

E>>Если вообще нет ни одной реализации, то речь не может идти о языке программирования. Максимум -- о проекте языка.

K>C моей точки зрения, которая, насколько я знаю, не слишком отличается от общепринятой, язык программирования — это набор синтаксических и семантических правил. Наличие компилятора не обязательно.


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

E>>Только вот эта деталь показывает, что функции в Nice не копируются.


K>А это, как раз, не деталь реализации. Это семантика функциональных типов. Они в Nice — ссылочные.


Следовательно, конструкция:
f = () => { println( "Hello!" ); }

определяет f как ссылку на функцию. И в плане практического использования f не сильно-то отличается от делегатов в D и агентов в Eiffel.

E>>Программист от этого вряд ли сильно страдает, ведь в Eiffel он все равно может делать то же самое, что и в Nice.


K>Еще раз. Мы говорим не о каких-то гипотетических страданиях программистов на Eiffel, стонущих под гнетом отсутствия первоклассных функций в этом языке. Мы решаем проблему классификации и демаркации.


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


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

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


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

E>>Что явным образом указывать?

K>Явно указывать взятие ссылки на функцию.


Еще раз: чтобы явно различить вызов функции от получения ссылки на функцию.


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

VE>Кстати, с этой стороны тоже надо посмотреть на вопрос.


VE>eao197, Klapaucius, если взять язык типа C#, но без struct. Т.е. все пользовательские объекты будут иметь ссылочную семантику. Вопрос: объекты будут первоклассными сущностями? Передать их в функцию нельзя (только ссылку), вернуть нельзя (только ссылку), но можно создавать и удалять.

VE>Теперь возьмем работу с функцией как в C++, т.е. не обязательно указывать &foo, можно просто foo, и для вызова аналогично. Понятно, что это сахар, да еще, ЕМНИП, не стандартный, хотя тут не копался, не столь важный вопрос. Но все же — функции в данном случае первоклассны или нет?
VE>Если объекты в приведенном псевдо-C# не первоклассны, то вопросов нет.
VE>Если объекты первоклассны, а функции в Си++ — нет, тогда почему? Что еще нужно, создание и удаление?

VE>Хотелось бы услышать мнение обоих, спасибо


Извините, вряд ли я смогу дать вам интересный ответ, поскольку я не силен в теории и само понятие "первоклассный" для меня является не очень понятным. По мне, первоклассное -- это то, что поддерживается средствами языка. Например делегат в D -- это первоклассная сущность, которая связывает функцию/метод с неким контекстом. А вот в C++ делегат, в принципе, может быть создан через указатель на функцию + функтор, но это уже будет не первоклассная сущность, т.к. ее приходится создавать самому программисту.

Мне кажется, что в языках с сылочными типами объекты -- первоклассны. А вот ссылки на объекты -- нет. Здесь получается некий нонсенс для человека с C-ным прошлым: переменная ссылочного типа -- это ссылка, но сделать что-нибудь с самой переменной (например, взять указатель и заменить значение переменной через указатель) практически ничего нельзя. Хотя и есть один очень важный момент -- ссылку, в отличии от объекта, можно занулить. Т.е. объект либо есть, либо нет, объект не может быть null-ом. А вот переменная-ссылка может быть null-ом.

Ситуация с функциями чуть сложнее, чем с объектами. Ведь в рассматривавшихся здесь языках (C#, Java, Nice, Eiffel, D, C/C++) заменить тело функции невозможно. Так же, как и скопировать тело функции в другое место. Поскольку функция -- это скомпилированный в некое машинное представление код. Следовательно, все, что может предоставить язык программисту в этом случае -- это взятие ссылки на функцию. И здесь возникает вопрос -- что из себя будет представлять ссылка на функцию -- некую прозрачную и несамостоятельную сущность, как ссылка на объект (в языках типа C#, Java, D), или же самостоятельную сущность с собственным типом (как указатель на функцию в C/C++, делегат в D или агент в Eiffel). Различия здесь могут быть достаточно серьезными -- например, в D можно взять указатель переменной-делегата и изменить эту переменную через указатель.

Языки D и Eiffel демонстрируют, что в языках с ссылочными типами для ссылки на функцию уровень косвенности получается достаточно большим: есть функция (код), есть некий дескриптор (делегат, агент) и есть ссылка на этот дескриптор. И, что важно, программист видит всю эту косвенность.

В Nice доступ к функции выполняется точно так же: есть функция (код), есть некий дескриптор и есть ссылка на этот дескриптор. Но данная косвенность не так очевидна, хотя и программист все равно ее видит (например, метод getClass() относится не к функции, а к дескриптору).

При этом в языках D, Eiffel и Nice есть встроенные в язык средства для работы с функциями (делегаты в D, агенты в Eiffel, функциональные типы в Nice). Т.е. для того, чтобы получить ссылку на функцию, программисту не нужно писать собственный код (как в случае с функторами в C++), достаточно просто воспользоваться языковыми конструкциями.

Следовательно, вопрос сводится к тому, являются ли средства Nice более "правильными" по сравнению со средствами D/Eiffel. И здесь всплывают такие различия как то, что в D и Nice дескрипторы функций видны пользователю, что ссылку на функцию нужно получать явно, что вызов идет как-то не так. Но, на мой взгляд, это не является определяющим фактором, поскольку программист все равно имеет в своем распоряжении одинаковые по мощности средства. HOF типа map или fold можно реализовать на каждом из этих языков. Причем, отличия будут разве что на уровне синтаксиса, но не смысла происходящего.

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

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


По мне, так для того, чтобы быть функциональным, языку нужно позволять программисту писать в функциональном стиле. А здесь оказывается, что ни D, ни Eiffel, ни Nice не являются конкурентами таких общепризнаных функциональных языков, как OCaml или Erlang. А здесь ведущую роль играют уже не столько функции, сколько иммутабельность данных и возможности выражения циклов через рекурсию. Да и паттерн-матчинг не на последнем месте.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[57]: Функциональный/нефункциональный
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 03.03.08 08:29
Оценка:
Здравствуйте, eao197, Вы писали:

E>Извините, вряд ли я смогу дать вам интересный ответ, поскольку я не силен в теории и само понятие "первоклассный" для меня является не очень понятным. По мне, первоклассное -- это то, что поддерживается средствами языка.


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

Например, в Ява нельзя взять метод и передать как параметр. Хотя методы средствами языка поддерживаются.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[56]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 03.03.08 13:04
Оценка: +1
Здравствуйте, VoidEx, Вы писали:

VE>если взять язык типа C#, но без struct. Т.е. все пользовательские объекты будут иметь ссылочную семантику. Вопрос: объекты будут первоклассными сущностями? Передать их в функцию нельзя (только ссылку), вернуть нельзя (только ссылку), но можно создавать и удалять.


Будут, ведь ссылки как отдельной сущности не существует — есть ссылочные типы.

VE>Теперь возьмем работу с функцией как в C++, т.е. не обязательно указывать &foo, можно просто foo, и для вызова аналогично. Понятно, что это сахар, да еще, ЕМНИП, не стандартный, хотя тут не копался, не столь важный вопрос. Но все же — функции в данном случае первоклассны или нет?


Нет, но по другой причине.

VE>Если объекты первоклассны, а функции в Си++ — нет, тогда почему? Что еще нужно, создание и удаление?


Да, создание экземпляра функционального типа в рантайме.
... << 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[41]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 03.03.08 13:04
Оценка:
Здравствуйте, eao197, Вы писали:

K>>C моей точки зрения, которая, насколько я знаю, не слишком отличается от общепринятой, язык программирования — это набор синтаксических и семантических правил. Наличие компилятора не обязательно.

E>Это как в науке -- теория должна подтверждаться практикой. Язык без реализации -- это теория. В данном конкретном случае теория мне не интересна.

Язык — это не "теория".
Теория это некие нетривиальные предположения, которые могут быть опровергнуты эспериментом. Язык сам по себе не содержит никаких нетривиальных фальсифицируемых предположений — поэтому теорией не является. Язык это средство выражения абстракций или инструмент коммуникации.
Язык программирования это язык, который может быть использован для написания программ и коммуникации программистов.
Любой псевдокод — язык программирования, с его помощью программист A может донести идею для программиста B. Или даже программист A(t1) может записать на этом псевдокоде идею, а позже восстановить ее в памяти, будучи программистом A(t2). Программа транслятор (и кол-во программ-трансляторов) с одного искуственного языка на другой никакого отношения к определению языка не имеет.

K>>А это, как раз, не деталь реализации. Это семантика функциональных типов. Они в Nice — ссылочные.

E>Следовательно, конструкция:
E>
E>f = () => { println( "Hello!" ); }
E>

E>определяет f как ссылку на функцию.

Определение "ссылка на функцию" в данном случае может ввести в заблуждение из-за ошибочных аналогий с ссылкой на функцию в C, например.
Более корректно сказать — ссылка на экземпляр функционального типа.

E>И в плане практического использования f не сильно-то отличается от делегатов в D и агентов в Eiffel.


Совершенно верно.

K>>Еще раз. Мы говорим не о каких-то гипотетических страданиях программистов на Eiffel, стонущих под гнетом отсутствия первоклассных функций в этом языке. Мы решаем проблему классификации и демаркации.

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

Выделенное курсивом и означает, что вы пытаетесь решить проблему классификации и демаркации. Понятно?
... << 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[56]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 03.03.08 13:04
Оценка:
Здравствуйте, eao197, Вы писали:

K>>Явно указывать взятие ссылки на функцию.

E>Еще раз: чтобы явно различить вызов функции от получения ссылки на функцию.

А зачем это явно различать?
И если это так важно, почему вызов функции через делегат и возвращение делегата явно не различатся?
Или обернуть функцию без аргументов в делегат нельзя?
... << 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[42]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.03.08 13:18
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Теория это некие нетривиальные предположения, которые могут быть опровергнуты эспериментом. Язык сам по себе не содержит никаких нетривиальных фальсифицируемых предположений — поэтому теорией не является. Язык это средство выражения абстракций или инструмент коммуникации.

K>Язык программирования это язык, который может быть использован для написания программ и коммуникации программистов.
K>Любой псевдокод — язык программирования, с его помощью программист A может донести идею для программиста B. Или даже программист A(t1) может записать на этом псевдокоде идею, а позже восстановить ее в памяти, будучи программистом A(t2). Программа транслятор (и кол-во программ-трансляторов) с одного искуственного языка на другой никакого отношения к определению языка не имеет.

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

K>Определение "ссылка на функцию" в данном случае может ввести в заблуждение из-за ошибочных аналогий с ссылкой на функцию в C, например.


В C/C++ нет ссылки на функцию, есть указатели. А указатели и ссылки в C++ это разные вещи. Например, ссылку на int можно рассматривать как очень-очень прозрачный прокси к экземпляру int. И все операции над ссылкой будут прозрачным образом адресоваться к экземпляру. Например:
int a = 0, int b = 1;
int & ra = a;
int & rb = b;

ra = rb * 2; // В точности то же самое, что и a = b * 2;

Соответственно для объектов:
class functor_t {
  public: void operator() { ... }
};
functor_t a;
functor_t & ra = a;

ra(); // В точности то же самое, что и a().

Поэтому я и употребил термин "ссылка на функцию", т.к. это практически в точности соответствует ссылкам на объекты в C++.

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


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


Я не пытаюсь ее решить. Я пытаюсь понять, почему вы решили ее именно так.


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

K>>>Явно указывать взятие ссылки на функцию.

E>>Еще раз: чтобы явно различить вызов функции от получения ссылки на функцию.

K>А зачем это явно различать?


ИМХО, для повышения читабельности программы. Чтобы без дополнительных инструментов было видно, что к чему.

K>И если это так важно, почему вызов функции через делегат и возвращение делегата явно не различатся?


Вообще-то различается. Так, если есть:
int delegate() r = ...;
return r;

то здесь возвращается экземпляр делегата. А если написать так:
int delegate() r = ...;
return r();

то возвращается результат вызова делегата.

Почему сделано именно так -- не знаю. Возможно для того, чтобы избежать неоднозначности в подобных случаях: означает ли r само значение делегата или же результат вызова делегата.

K>Или обернуть функцию без аргументов в делегат нельзя?


Можно.


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

E>
E>int delegate() r = ...;
E>return r;
E>

E>то здесь возвращается экземпляр делегата. А если написать так:
E>
E>int delegate() r = ...;
E>return r();
E>

E>то возвращается результат вызова делегата.
E>Почему сделано именно так -- не знаю. Возможно для того, чтобы избежать неоднозначности в подобных случаях: означает ли r само значение делегата или же результат вызова делегата.

А для вызова функции без аргументов () — не используется, или это я с 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[59]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.03.08 13:53
Оценка:
Здравствуйте, Klapaucius, Вы писали:

E>>
E>>int delegate() r = ...;
E>>return r;
E>>

E>>то здесь возвращается экземпляр делегата. А если написать так:
E>>
E>>int delegate() r = ...;
E>>return r();
E>>

E>>то возвращается результат вызова делегата.
E>>Почему сделано именно так -- не знаю. Возможно для того, чтобы избежать неоднозначности в подобных случаях: означает ли r само значение делегата или же результат вызова делегата.

K>А для вызова функции без аргументов () — не используется, или это я с Eiffel путаю?


И там, и там функция без аргументов может вызываться без скобочек.

Но ситуация в D похожа на аналогичную в Nice -- запись r в Nice обозначает саму функцию, а не ее вызов:
int endln() { println(""); return 0; }

void main( String[] args )
    {
        let r = endln;
        println( r.getClass.getName );
    }

и
int endln() { println(""); return 0; }

void main( String[] args )
    {
        let r = endln();
        println( r.getClass.getName );
    }

Приводят к совершенно разным результатам.


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

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


Этим "реальный" от "вымышленного" (хотя, конечно, все языки вымышленные) врятли отличается. Ошибки, которых не ждали могут быть в коде и на том и на другом.

K>>Определение "ссылка на функцию" в данном случае может ввести в заблуждение из-за ошибочных аналогий с ссылкой на функцию в C, например.

E>В C/C++ нет ссылки на функцию, есть указатели.

Действительно, какая-то у меня неправильная ассоциация.

E>Поэтому я и употребил термин "ссылка на функцию", т.к. это практически в точности соответствует ссылкам на объекты в C++.


По моему, аналогия со ссылкой a la C++ не лучше, чем аналогия с указателем на функцию.

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

E>Я не пытаюсь ее решить. Я пытаюсь понять, почему вы решили ее именно так.

И для этого вам нужно сначала решить проблему классификации, чтобы классифицировать языки, а потом решить проблему демаркации для того, чтобы понять, в чем различие мужду классификацией и оценкой практических возможностей.
... << 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[44]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.03.08 14:06
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


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


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

E>Но ситуация в D похожа на аналогичную в Nice -- запись r в Nice обозначает саму функцию, а не ее вызов


Это понятно.
Непонятно почему в D для функций неопределенность разрешается явным указанием foo и &foo, а для делегатов foo() и foo соответственно.
Это должно упрощать чтение? пока я никакого упрощения не вижу. Напротив, строгий вариант определения fco представляется мне все более и более обоснованным. Я даже начинаю усматривать связь с практикой. Функции в Nice достаточно понятны (для меня, во всяком случае), а незначительный опыт программирования на функциональных языках приходит на помощь в трудной ситуации. В то же время, странная двойная классификация функций и делегатов в D, требующая каких-то поясняющих указаний то так — то эдак для меня совершенно контринтуитивна
и не облегчает ни чтения, ни описания.
Я, конечно понимаю: все это субъективно и тем, на кого ориентирован D серьезно облегчает чтение, но должен с сожалением констатировать, что я не из их числа.
... << 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[45]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 03.03.08 17:01
Оценка:
Здравствуйте, eao197, Вы писали:

E>У меня нет проблемы классификации.


Рад за вас, но все еще не понимаю, почему вы не формулируете свое определение.

E>Скорее у меня были трудности с пониманием вашей системы классификации языков.


Что не перестает меня удивлять. Определение fco Кристофера Стрейчи широко известно и легко доступно. Насколько я помню, оно упоминалось в одной из первых глав SICP. Оно и в Википедии совершенно точно есть.
Помимо знания этого определения требуется только умение отделить синтаксис и семантику языка от деталей конкретной реализации, что, вообще говоря, не должно вызывать сложностей у программиста.
... << 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[61]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 03.03.08 17:08
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


E>>Но ситуация в D похожа на аналогичную в Nice -- запись r в Nice обозначает саму функцию, а не ее вызов


K>Это понятно.

K>Непонятно почему в D для функций неопределенность разрешается явным указанием foo и &foo, а для делегатов foo() и foo соответственно.

Потому, что &foo для делегата будет означать указатель на делегата. Ведь делегат -- это первоклассный объект. А значит для него можно получить указаль в D, так же, как для объекта, экземпляра типа int и т.д.


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

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


E>>У меня нет проблемы классификации.


K>Рад за вас, но все еще не понимаю, почему вы не формулируете свое определение.


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

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

E>>Скорее у меня были трудности с пониманием вашей системы классификации языков.


K>Что не перестает меня удивлять. Определение fco Кристофера Стрейчи широко известно и легко доступно. Насколько я помню, оно упоминалось в одной из первых глав SICP. Оно и в Википедии совершенно точно есть.

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

У каждого свои недостатки.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[43]: Функциональный/нефункциональный
От: VoidEx  
Дата: 04.03.08 00:47
Оценка: 38 (1)
Здравствуйте, eao197, Вы писали:

E>В C/C++ нет ссылки на функцию, есть указатели.



#include <iostream>

int f(int x) { return x + 1; }

int main()
{
  int (&my)(int) = f;
  std::cout << my(5);
}

Re[44]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 04.03.08 06:58
Оценка:
Здравствуйте, VoidEx, Вы писали:

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


E>>В C/C++ нет ссылки на функцию, есть указатели.



VE>
VE>#include <iostream>

VE>int f(int x) { return x + 1; }

VE>int main()
VE>{
VE>  int (&my)(int) = f;
VE>  std::cout << my(5);
VE>}
VE>

VE>

Ахринеть!

Но в С-то точно нет ссылки на функцию


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

K>>Непонятно почему в D для функций неопределенность разрешается явным указанием foo и &foo, а для делегатов foo() и foo соответственно.

E>Потому, что &foo для делегата будет означать указатель на делегата. Ведь делегат -- это первоклассный объект. А значит для него можно получить указаль в D, так же, как для объекта, экземпляра типа int и т.д.

C делегатом все ясно. Непонятно почему для функции нельзя сделать foo() и foo. Вообще неудобно, что функция непосредственно используется иначе, чем через делегат — т.е. одинаковые семантически вещи выглядят в коде различно, а разные вроде указателя и делегата похоже.
Впрочем, обсуждать дизайн D мне не особенно интересно.
... << 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[47]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 04.03.08 13:05
Оценка:
Здравствуйте, eao197, Вы писали:

E>А вы бы могли сформулировать определение "полный человек"? А "толстый человек"?

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

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


Проблема определения "полный человек" в том, что разные люди проведут границу между "полный" и "вмеру упитанный" в разных точках на оси упитанности. Однако, все согласятся друг с другом, если нужно будет выбрать кто из двух людей упитаннее, начиная с некоторого интервала между ними на оси упитанности. Именно это и позволяет пользоваться определением.
С "особыми усилиями" дело обстоит гораждо хуже. Проблема не только в том, что разные люди разойдутся во мнении какие усилия считать особыми, а какие ординарными. Проблема возникнет также и с тем, что Петя будет без особых усилий программировать функционально на языке Блаблабла, и с особыми на языке Траляля. В то время как Вася, наоборот, без особых на Траляля и с особыми на Блаблабла.
Т.е. мы имеем дело с необъективностью следующего порядка.
... << 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[63]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 04.03.08 13:38
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>>>Непонятно почему в D для функций неопределенность разрешается явным указанием foo и &foo, а для делегатов foo() и foo соответственно.

E>>Потому, что &foo для делегата будет означать указатель на делегата. Ведь делегат -- это первоклассный объект. А значит для него можно получить указаль в D, так же, как для объекта, экземпляра типа int и т.д.

K>C делегатом все ясно. Непонятно почему для функции нельзя сделать foo() и foo.


Если речь о том, что foo() является вызовом, а foo -- получением ссылки на функцию, то тогда нарушится uniform access principle. Ведь тогда вызов любой функции/метода должен сопровождаться указанием (), а это ухудшает сопровождение программ, когда атрибут заменяется методом-getter-ом или наоборот. Например, было:
class Demo {
  public int priority;
  ...
}

auto d = new Demo();
writefln( d.priority );

а затем стало:
class Demo {
  public int priority() { return ... };
  ...
}

auto d = new Demo();
writefln( d.priority );

Изменения касаются только класса, но не кода, который использует этот класс. В C++, например, методы всегда вызываются через () и заменить атрибут методом-getter-ом в C++ сложнее, чем в D -- слишком много кода от этого изменения зависят.

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


Для функций с аргументами использование не отличается.
Различия проявляются только с функциями без аргументов. Однако, в Nice существует такая же дилема при использовании функционального типа:
{
  f = () => {}; // ()->void;
  f; // всегда ()->void.
  f(); // всегда вызов f.
  "hello".length; // всегда вызов length, даже без ().
  "hello".length(); // то же самое.
}


Имхо, в нормальных функциональных языках функции без аргументов -- это вообще скорее исключение из правил, чем норма. Ведь результат функции должен зависеть только от аргументов функции и функция при одинаковых значениях аргументов должна возвращать одинаковое значение (функция в математическом смысле, без побочных эффектов). Следовательно, при отсутствии аргументов функция должна вырождаться в константу. А посему я не знаю, бывают ли в "нормальных" функциональных языках функции без параметров (насколько я помню, то при чтении документации по OCaml я таких не видел).

K>а разные вроде указателя и делегата похоже.


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


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

K>С "особыми усилиями" дело обстоит гораждо хуже. Проблема не только в том, что разные люди разойдутся во мнении какие усилия считать особыми, а какие ординарными. Проблема возникнет также и с тем, что Петя будет без особых усилий программировать функционально на языке Блаблабла, и с особыми на языке Траляля. В то время как Вася, наоборот, без особых на Траляля и с особыми на Блаблабла.

K>Т.е. мы имеем дело с необъективностью следующего порядка.

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


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

K>>C делегатом все ясно. Непонятно почему для функции нельзя сделать foo() и foo.

E>Если речь о том, что foo() является вызовом, а foo -- получением ссылки на функцию, то тогда нарушится uniform access principle. Ведь тогда вызов любой функции/метода должен сопровождаться указанием (), а это ухудшает сопровождение программ, когда атрибут заменяется методом-getter-ом или наоборот. Например, было:
E>
E>class Demo {
E>  public int priority;
E>  ...
E>}
E>auto d = new Demo();
E>writefln( d.priority );
E>

E>а затем стало:
E>
E>class Demo {
E>  public int priority() { return ... };
E>  ...
E>}
E>auto d = new Demo();
E>writefln( d.priority );
E>

E>Изменения касаются только класса, но не кода, который использует этот класс.

Зато если сначала был геттер, а его сменили на публичное поле — сломается весь код, в котором создавался и использовался делегат для геттера. Кроме того, для доступа к функции через делегат этот uniform access principle все равно не выполняется.

E>Различия проявляются только с функциями без аргументов. Однако, в Nice существует такая же дилема при использовании функционального типа:

E>
E>{
E>  f = () => {}; // ()->void;
E>  f; // всегда ()->void.
E>  f(); // всегда вызов f.
E>  "hello".length; // всегда вызов length, даже без ().
E>  "hello".length(); // то же самое.
E>}
E>


Учитывая, что "hello".length — сахар для length("hello") тут все вполне логично.
Хуже другое — такая логика работает только в одну сторону:
class A {
  int inc(int a ) = a + 1;
}

void main( String[] args ) {
  let o = new A();
  let i = o.inc(1);
  let i2 = inc(o, 1); // так должно работать.
  let f = inc;
  let j = f(o, 1);
  let j2 = o.f(1); // так тоже должно, но не работает.
  println(i == j);
}

Вот это для меня оказалось неожиданностью.

E>Имхо, в нормальных функциональных языках функции без аргументов -- это вообще скорее исключение из правил, чем норма. Ведь результат функции должен зависеть только от аргументов функции и функция при одинаковых значениях аргументов должна возвращать одинаковое значение (функция в математическом смысле, без побочных эффектов). Следовательно, при отсутствии аргументов функция должна вырождаться в константу. А посему я не знаю, бывают ли в "нормальных" функциональных языках функции без параметров (насколько я помню, то при чтении документации по OCaml я таких не видел).


В "нормальных" функциональных языках "константа" это, в общем-то и есть функция без параметров.

K>>а разные вроде указателя и делегата похоже.

E>Если принять точку зрения, что делегат является аналогом указателя, то все станет на свои места.

До того, как в D добавили замыкания, так оно, в общем-то и было. Сейчас делегат аналогом указателя уже не является.
... << 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[49]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 04.03.08 14:08
Оценка: :)
Здравствуйте, eao197, Вы писали:

E>При большом количестве использующих язык программистов накопится достаточная статистика для того, чтобы считать какие-то усилия "особыми", а какие-то "ординарными". Соответственно, язык приобритет репутацию "функционального" или не приобритет ее.


При таком подходе, функциональность языков вроде Nice принципиально непозноваема. Не смотря на это, вы уверенно вынесли суждение о функциональности Nice, хотя большое количество программистов Nice не использует, и с очень хорошей вероятностью использовать не будет.
... << 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[50]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 04.03.08 14:19
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


E>>При большом количестве использующих язык программистов накопится достаточная статистика для того, чтобы считать какие-то усилия "особыми", а какие-то "ординарными". Соответственно, язык приобритет репутацию "функционального" или не приобритет ее.


K>При таком подходе, функциональность языков вроде Nice принципиально непозноваема. Не смотря на это, вы уверенно вынесли суждение о функциональности Nice,


Я вынес это суждение после того, как попробовал поработать на Nice. Мне показалось, что работа на нем мало отличается от работы на D или Eiffel. В отличии от, например, Scala или OCaml, которые заставляют программировать в ином ключе.

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


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

K>Зато если сначала был геттер, а его сменили на публичное поле — сломается весь код, в котором создавался и использовался делегат для геттера.


Это все равно гораздо лучше того, что есть в С++ и, насколько я помню, в Java.

K>Кроме того, для доступа к функции через делегат этот uniform access principle все равно не выполняется.


А uniform access principe распространяется не на работу с методами объекта, а на работу с атрибутами объекта. Т.е. благодоря этому принципу нет разницы между o.f и o.f, если f является атрибутом или методом-геттером.

E>>Различия проявляются только с функциями без аргументов. Однако, в Nice существует такая же дилема при использовании функционального типа:

E>>
E>>{
E>>  f = () => {}; // ()->void;
E>>  f; // всегда ()->void.
E>>  f(); // всегда вызов f.
E>>  "hello".length; // всегда вызов length, даже без ().
E>>  "hello".length(); // то же самое.
E>>}
E>>


K>Учитывая, что "hello".length — сахар для length("hello") тут все вполне логично.

K>Хуже другое — такая логика работает только в одну сторону:
K>
K>class A {
K>  int inc(int a ) = a + 1;
K>}

K>void main( String[] args ) {
K>  let o = new A();
K>  let i = o.inc(1);
K>  let i2 = inc(o, 1); // так должно работать.
K>  let f = inc;
K>  let j = f(o, 1);
K>  let j2 = o.f(1); // так тоже должно, но не работает.
K>  println(i == j);
K>}
K>

K>Вот это для меня оказалось неожиданностью.

Еще интереснее, когда внутри объекта используется функция без параметров:
class A {
  public int f() { ... };
  public int g() { doSomething( f ); /* oops! */ }
}
let o = new A();
doSomething( o.f );

Т.е. вызов метода без параметров f внутри класса A и снаружи выполняется по разному.

E>>Имхо, в нормальных функциональных языках функции без аргументов -- это вообще скорее исключение из правил, чем норма. Ведь результат функции должен зависеть только от аргументов функции и функция при одинаковых значениях аргументов должна возвращать одинаковое значение (функция в математическом смысле, без побочных эффектов). Следовательно, при отсутствии аргументов функция должна вырождаться в константу. А посему я не знаю, бывают ли в "нормальных" функциональных языках функции без параметров (насколько я помню, то при чтении документации по OCaml я таких не видел).


K>В "нормальных" функциональных языках "константа" это, в общем-то и есть функция без параметров.


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

Или можно?


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

DC>>Это уточнение меняет смысл моей фразы . Т.к. в этих языках сущность одна, а то что там есть ссылка, дык это деталь реализации.

E>От этой детали много чего зависит. Например, нельзя получить ссылку на переменную.
В C# можно. См ref и out параметры у функций.
... << RSDN@Home 1.2.0 alpha rev. 745>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[66]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 04.03.08 17:41
Оценка:
Здравствуйте, eao197, Вы писали:

K>>Зато если сначала был геттер, а его сменили на публичное поле — сломается весь код, в котором создавался и использовался делегат для геттера.

E>Это все равно гораздо лучше того, что есть в С++ и, насколько я помню, в Java.

Наверное. Но, на мой взгляд, хуже, чем в C#, например.

K>>Кроме того, для доступа к функции через делегат этот uniform access principle все равно не выполняется.

E>А uniform access principe распространяется не на работу с методами объекта, а на работу с атрибутами объекта. Т.е. благодоря этому принципу нет разницы между o.f и o.f, если f является атрибутом или методом-геттером.

Мммм... А что, геттер — не метод?

E>Еще интереснее, когда внутри объекта используется функция без параметров:

E>
E>class A {
E>  public int f() { ... };
E>  public int g() { doSomething( f ); /* oops! */ }
E>}
E>let o = new A();
E>doSomething( o.f );
E>

E>Т.е. вызов метода без параметров f внутри класса A и снаружи выполняется по разному.

Совершенно одинаково:
class A {
  int f() = 1;
  void g() = doSomething( f );
  void h() = doSomething( this.f );
}
void doSomething(int i) = println ("result");

void doSomething(A -> int fn) = println ("function");

void main( String[] args ) {
  let o = new A();
  o.g();
  doSomething( f );
  o.h();
  doSomething( o.f );
}

Выведет:
function
function
result
result


И, кстати, методов без параметров не бывает.

K>>В "нормальных" функциональных языках "константа" это, в общем-то и есть функция без параметров.

E>Но такую функцию, надо полагать, нельзя передать в качестве параметра и возвратить. Т.к. будет использоваться результат вызова функция (значение), но не сама функция.
E>Или можно?

Можно. "Нормальные" функциональные языки — ленивые. Если уж на то пошло, нужно приложить усилия, чтобы так не сделать. foo bar в таком языке это не "вызов функции foo с параметром bar", а конструирование функции без параметра из функции с параметром и функции без параметра.
... << 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[51]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 04.03.08 18:02
Оценка:
Здравствуйте, eao197, Вы писали:

E>>>При большом количестве использующих язык программистов накопится достаточная статистика ...

K>>При таком подходе, функциональность языков вроде Nice принципиально непозноваема. Не смотря на это, вы уверенно вынесли суждение о функциональности Nice,
E>Я вынес это суждение после того, как попробовал поработать на Nice. Мне показалось, что работа на нем мало отличается от работы на D или Eiffel. В отличии от, например, Scala или OCaml, которые заставляют программировать в ином ключе.

Что поделать — субъективность есть субъективность.
Конечно, в Nice параметрический полиморфизм с "классами типов", диспетчеризация для многих аргументов, отсутствуют касты и области видимости (конечно, можно написать private и public, но компилятор их игнорирует), зато есть лямбды с замыканиями (инкапсуляция возможна, кстати, ха-ха, только в замыкании. Объекты Nice прозрачны как слеза комсомолки) и функциональные типы.
Классика ООП, короче говоря.

E>Так что, если я составлял на тот момент значительную часть от программирующих на Nice программистов, то...


Вы же написали "большом", а не "большем". Впрочем, какая разница? Думаю, что я составляю не меньшее число программировавших на Nice чем вы, если, конечно, вы представляете из себя не коллектив авторов с одним псевдонимом.
... << 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[67]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 04.03.08 19:23
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


K>>>Зато если сначала был геттер, а его сменили на публичное поле — сломается весь код, в котором создавался и использовался делегат для геттера.

E>>Это все равно гораздо лучше того, что есть в С++ и, насколько я помню, в Java.

K>Наверное. Но, на мой взгляд, хуже, чем в C#, например.


Чем?

K>>>Кроме того, для доступа к функции через делегат этот uniform access principle все равно не выполняется.

E>>А uniform access principe распространяется не на работу с методами объекта, а на работу с атрибутами объекта. Т.е. благодоря этому принципу нет разницы между o.f и o.f, если f является атрибутом или методом-геттером.

K>Мммм... А что, геттер — не метод?


Я имел в виду, что когда кто-то пишет o.f, то ему интересно, что внутри у объекта.
Когда же кто-то пытается получить делегат для o.f, то он интересуется не значением атрибута объекта, а чем-то другим, например, способом взаимодействия с объектом в дальнейшем.

E>>Еще интереснее, когда внутри объекта используется функция без параметров:

E>>
E>>class A {
E>>  public int f() { ... };
E>>  public int g() { doSomething( f ); /* oops! */ }
E>>}
E>>let o = new A();
E>>doSomething( o.f );
E>>

E>>Т.е. вызов метода без параметров f внутри класса A и снаружи выполняется по разному.

K>Совершенно одинаково:

K>
K>class A {
K>  int f() = 1;
K>  void g() = doSomething( f );
K>  void h() = doSomething( this.f );
K>}
K>void doSomething(int i) = println ("result");

K>void doSomething(A -> int fn) = println ("function");

K>void main( String[] args ) {
K>  let o = new A();
K>  o.g();
K>  doSomething( f );
K>  o.h();
K>  doSomething( o.f );
K>}
K>

K>Выведет:
K>
K>function
K>function
K>result
K>result
K>


Вы написали собственный пример, введя вторую функцию doSomething с типом аргумента A->int. Оставте только одну с аргументом типа int и тогда получится то, о чем я говорил.


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

K>>>>Зато если сначала был геттер, а его сменили на публичное поле — сломается весь код, в котором создавался и использовался делегат для геттера.

E>>>Это все равно гораздо лучше того, что есть в С++ и, насколько я помню, в Java.
K>>Наверное. Но, на мой взгляд, хуже, чем в C#, например.
E>Чем?

Тем, что свойство это не метод, со всеми вытекающими. Впрочем, нет предела совершенству — было бы неплохо, если бы публичные поля в C# запретили.

E>Я имел в виду, что когда кто-то пишет o.f, то ему интересно, что внутри у объекта.

E>Когда же кто-то пытается получить делегат для o.f, то он интересуется не значением атрибута объекта, а чем-то другим, например, способом взаимодействия с объектом в дальнейшем.

И что? Это как-то снимает проблему?

E>Вы написали собственный пример, введя вторую функцию doSomething с типом аргумента A->int. Оставте только одну с аргументом типа int и тогда получится то, о чем я говорил.


class A {
  int f() = 1;
  void g() = doSomething( f );
  void h() = doSomething( this.f );
}
void doSomething(int i) = println ("result");

//void doSomething(A -> int fn) = println ("function");

void main( String[] args ) {
  let o = new A();
  o.g();
  doSomething( f );
  o.h();
  doSomething( o.f );
}

Получается:
C:\nice_projects\test\test.nice: line 3, column 14:
Arguments ((test.A)->nice.lang.int) do not fit:
nice.lang.void doSomething(nice.lang.int i)

C:\nice_projects\test\test.nice: line 13, column 3:
Arguments ((test.A)->nice.lang.int) do not fit:
nice.lang.void doSomething(nice.lang.int i)
compilation failed with 2 errors
... << 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[69]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 05.03.08 07:17
Оценка:
Здравствуйте, Klapaucius, Вы писали:

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


K>>>>>Зато если сначала был геттер, а его сменили на публичное поле — сломается весь код, в котором создавался и использовался делегат для геттера.

E>>>>Это все равно гораздо лучше того, что есть в С++ и, насколько я помню, в Java.
K>>>Наверное. Но, на мой взгляд, хуже, чем в C#, например.
E>>Чем?

K>Тем, что свойство это не метод, со всеми вытекающими.


Опять не понял. Если речь идет о properties, то они в D реализуются через методы.

E>>Я имел в виду, что когда кто-то пишет o.f, то ему интересно, что внутри у объекта.

E>>Когда же кто-то пытается получить делегат для o.f, то он интересуется не значением атрибута объекта, а чем-то другим, например, способом взаимодействия с объектом в дальнейшем.

K>И что? Это как-то снимает проблему?


Это говорит о том, что проблемы нет вообще. Uniform access principle гарантирует, что конструкции вида a = o.f или g(o.f) остануться корректными вне зависимости от того, является ли o.f атрибутом или методом.

Если же кто-то делает d = &o.f, значит его интересует не возврашаемое f значение, а сам f. А это уже просто не попадает под действие uniform access principle, имхо.

По поводу примера с doSomething -- да, я что-то перепутал. Методы объектов в Nice всегда должны вызываться в форме target.method. Вне зависимости от того, происходит ли вызов внутри объекта или снаружи.


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

K>Учитывая, что "hello".length — сахар для length("hello") тут все вполне логично.

K>Хуже другое — такая логика работает только в одну сторону:
K>
K>class A {
K>  int inc(int a ) = a + 1;
K>}

K>void main( String[] args ) {
K>  let o = new A();
K>  let i = o.inc(1);
K>  let i2 = inc(o, 1); // так должно работать.
K>  let f = inc;
K>  let j = f(o, 1);
K>  let j2 = o.f(1); // так тоже должно, но не работает.
K>  println(i == j);
K>}
K>

K>Вот это для меня оказалось неожиданностью.

А это тоже логично. Ведь встретив запись o.f(1) компилятор Nice ищет функцию f, которую можно вызывать как f(o,1). Но такой фукнции нет. Есть переменная f, являющаяся ссылкой на функцию (aka delegate в D), но она все-таки не функция, поэтому компилятор функцию f и не находит.


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

E>Опять не понял. Если речь идет о properties, то они в D реализуются через методы.


Это понятно, но в C# свойство инкапсулирует геттер и сеттер. Так что вышеописанная ситуация с делегатом на геттер маловероятна.
... << 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[66]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 05.03.08 13:01
Оценка:
Здравствуйте, eao197, Вы писали:

K>>
K>>class A {
K>>  int inc(int a ) = a + 1;
K>>}
K>>void main( String[] args ) {
K>>  let o = new A();
K>>  let i = o.inc(1);
K>>  let i2 = inc(o, 1); // так должно работать.
K>>  let f = inc;
K>>  let j = f(o, 1);
K>>  let j2 = o.f(1); // так тоже должно, но не работает.
K>>  println(i == j);
K>>}
K>>

E>А это тоже логично. Ведь встретив запись o.f(1) компилятор Nice ищет функцию f, которую можно вызывать как f(o,1). Но такой фукнции нет.

Вообще-то в случае с let j = f(o, 1) он находит функцию f без труда. Если бы компилятор просто вcегда преобразовывал x.y -> y(x) все бы работало. Вообще — это пример, который позволяет продемонстрировать разницу между функцией и методом. Функцию можно сконструировать в рантайме, а метод нет. Возможно, какая-то сермяжная правда в этом и есть, но при всем прочем, разница между методом и функцией в Nice выглядит как-то нелогично. Особенно, если учесть что это могут быть экземпляры одного и того же функционального типа.
... << 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[9]: Функциональный/нефункциональный
От: vdimas Россия  
Дата: 06.03.08 04:15
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Я-то спрашивал, определение, из которого следует, какие средства необходимы. Мое определение заключается в том, что функциональный язык — это язык, в котором функции являются FCO.


Так тебе уже ответили, что не согласны, и привели своё определние, согласно которому ф-й ЯП это тот, который нативно поддерживает функциональную парадигму. FCO явно недостаточно для этого.


K>Нет, не поэтому. Слова "слишком" и "много" не имеют никакого смысла. Когда слишком много, а когда еще не слишком? И в сравнении с какими ООП языками? Каким образом происходит сравнение — по какой методике, чем измерим интервал между ООП и не ООП языком и на какой оси?


На банальной оси числа строк программы.

K>Я считаю, что C не считается ООП потому, что в нем нет объектов как FCO. Все.


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


K>Мы -то говорим о классификации языков безотносительно их удобства.


почему ты отделяешь удобства от фич?


K>Действительно, не поняли. Функция в C не является первоклассным объектом. Указатель — является. Но вы, конечно, можете попробовать открыть для меня глубины C, продемонстрировав код на C соответствующий моему коду на Nice. Будет очень интересно.


Ну на C# можно, и согласно твоей логике, он является ФЯП.
Re[41]: Функциональный/нефункциональный
От: vdimas Россия  
Дата: 06.03.08 09:53
Оценка: 6 (1)
Здравствуйте, Klapaucius, Вы писали:


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

K>Если бы можно было написать так:
K>
K> V finalResult( U b )
K>    {
K>        return func( a, b );
K>    }
K>return finalResult;
K>

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

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

Это игра терминов. То, что в D называется делегатом, во многих ФЯ называется функцией. Просто напомню, что для нас (программистов) ЯП — лишь инструмент, и в этом смысле делегаты в D и ф-ии в ФЯ — это абсолютно один и тот же инструмент, хоть и называется по-разному в рамках разных языков.


K>К чему все эти эмоционально окрашенные слова вроде "ущербности"? Явное конструирование является показателем того, что функцию нельзя вернуть без явного преобразования.


Уточню, функцию в терминах D, что не есть эквивалент ф-ии из семейства ML, а вот полученный делегат — эквивалент, с точностью до терминологии.


K>Также это показатель того, что функция и делегат — разные сущности.


Опять же, в рамках терминологии языка D.

K>В Nice никакие делегаты не нужны — как раз потому, что функции — первоклассные.


Потому что других типов ф-ий нет, лишь те, что аналоги делегатов.


K>И тип возвращаемого значения там — функциональный тип, а не тип делегата.


Ес-но, ведь типа "делегат" там нет.


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


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


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


+1

K>Все это жонглирование псевдофилософскими понятиями вроде "формы" и "содержания" ничего не дает. Что есть форма — синтаксис? Но есть ли основания считать синтаксис менее важным в данном вопросе, чем, например, семантика?


Хм... Как раз-таки видна попытка проигнорировать эквивалентность семантик.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[10]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 06.03.08 13:10
Оценка:
Здравствуйте, vdimas, Вы писали:

V>привели своё определние, согласно которому ф-й ЯП это тот, который нативно поддерживает функциональную парадигму.


Т.е. функциональный язык — это функциональный язык? Содержательное определение, что тут скажешь. Если вам так больше понравится можно сформулировать вопрос иначе:

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

V>FCO явно недостаточно для этого.


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

K>>Нет, не поэтому. Слова "слишком" и "много" не имеют никакого смысла. Когда слишком много, а когда еще не слишком? И в сравнении с какими ООП языками? Каким образом происходит сравнение — по какой методике, чем измерим интервал между ООП и не ООП языком и на какой оси?

V>На банальной оси числа строк программы.

Что есть "число строк необходимое для поддержки ООП" и на каком числе строк находится граница между OO и неОО языком?

K>>Я считаю, что C не считается ООП потому, что в нем нет объектов как FCO. Все.

V>определение объекта в студию...

Допустим, АТД с состоянием. Годится?

V>а то может оказаться, что это заявление преждевременно.


Если и преждевременно — мне все равно. Обсуждение объектной ориентированности языка C мне не интересно и в данном случае является оффтопиком.

K>>Мы -то говорим о классификации языков безотносительно их удобства.

V>почему ты отделяешь удобства от фич?

Фича — характеристика языка. Удобство — характеристика системы язык-программист. Синтаксис с отступами — фича. С точки зрения Васи — это удобство, с точки зрения Пети — неудобство.

K>>Действительно, не поняли. Функция в C не является первоклассным объектом. Указатель — является. Но вы, конечно, можете попробовать открыть для меня глубины C, продемонстрировав код на C соответствующий моему коду на Nice. Будет очень интересно.

V>Ну на C# можно, и согласно твоей логике, он является ФЯП.

Это уже обсуждалось. Да, со второй версии он соответствует моему определению ФЯП.
... << 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[11]: Функциональный/нефункциональный
От: vdimas Россия  
Дата: 06.03.08 13:56
Оценка: 20 (2) +2
Здравствуйте, Klapaucius, Вы писали:

K>Что есть нативная поддержка функциональной парадигмы языком?

K>Мой ответ — первоклассность функций в этом языке.

K>Вы хотели сказать, что функций как FCO недостаточно?

K>С моей точки зрения — вполне достаточно.
K>А чего еще не хватает?

Функциональная парадигма в нынешнем виде — это не только первоклассность ф-ий и не столько. Когда-то обсуждали сам термин "парадигма" и пришли к выводу, что парадигма (относительно к IT) — это совокупность подходов, практик, идей и соответствующего инструментария, определяющих способ решения некоей задачи (среди бесконечного множества других способов). В интуитивном плане парадигма формирует точку зрения на проблему. Функциональная декомпозиция — это лишь один из кирпичиков этой парадигмы, как и первоклассность ф-ий. Считается, что в функциональной парадигме присутствует как минимум еще иммутабельность, и как следствие — инструментарий, типа туплов и прилагающегося к ним паттерн-матчинга, раскрутки рекурсии и встроенная возможность ленивости (не только при моделировании бесконечных списков, сам факт оперирования ф-иями как значениями предполагает отложенный вызов этих самых ф-ий). Т.е. вот минимальный "джентельменский" требований к инструментарию, для полной поддержки современной функциональной парадигмы.



K>>>Нет, не поэтому. Слова "слишком" и "много" не имеют никакого смысла. Когда слишком много, а когда еще не слишком? И в сравнении с какими ООП языками? Каким образом происходит сравнение — по какой методике, чем измерим интервал между ООП и не ООП языком и на какой оси?

V>>На банальной оси числа строк программы.

K>Что есть "число строк необходимое для поддержки ООП" и на каком числе строк находится граница между OO и неОО языком?


т.к. ось бесконечна, то интересует лишь ее отрезок — суть разность строк, применительно к какой-либо задаче.


K>>>Я считаю, что C не считается ООП потому, что в нем нет объектов как FCO. Все.

V>>определение объекта в студию...

K>Допустим, АТД с состоянием. Годится?


без "А" годится, ибо под классическое определение объекта попадает любой конечный автомат, разработанный (или смоделированный, не суть) на любом ЯП, например на том же С.


V>>а то может оказаться, что это заявление преждевременно.


K>Если и преждевременно — мне все равно. Обсуждение объектной ориентированности языка C мне не интересно и в данном случае является оффтопиком.


Ok, просто это как бы контрпример к тому, что наличие или отсутствие в инструменте какого-либо одного "кирпичика" не обязательно делает инструмент достаточно подходящим для использования в рамках какой-либо парадигмы, хотя и может сделать применение этой парадигмы с этим инструментом _возможным_. Дело, разумеется, лишь в количестве доп. приседаний, которые согласен делать применяющий, а так же в количестве _автоматически_ обнаруживаемых граблей, принадлежащих к парадигме генетически.


K>>>Мы -то говорим о классификации языков безотносительно их удобства.

V>>почему ты отделяешь удобства от фич?

K>Фича — характеристика языка. Удобство — характеристика системы язык-программист. Синтаксис с отступами — фича. С точки зрения Васи — это удобство, с точки зрения Пети — неудобство.


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


V>>Ну на C# можно, и согласно твоей логике, он является ФЯП.


K>Это уже обсуждалось. Да, со второй версии он соответствует моему определению ФЯП.


Тогда неудивительно, что вышел такой длинный спор.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[12]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 06.03.08 19:03
Оценка: 3 (1)
Здравствуйте, vdimas, Вы писали:

K>>Что есть нативная поддержка функциональной парадигмы языком?

K>>Мой ответ — первоклассность функций в этом языке.
K>>Вы хотели сказать, что функций как FCO недостаточно?
K>>С моей точки зрения — вполне достаточно.
K>>А чего еще не хватает?
V>Функциональная парадигма в нынешнем виде — это не только первоклассность ф-ий и не столько.

Допустим.

V>Когда-то обсуждали сам термин "парадигма" и пришли к выводу, что парадигма (относительно к IT) — это совокупность подходов, практик, идей и соответствующего инструментария, определяющих способ решения некоей задачи (среди бесконечного множества других способов). В интуитивном плане парадигма формирует точку зрения на проблему.


Все вышеописанное это парадигма не только относительно к IT. Но я парадигмы обсуждать не буду, дабы не призывать.

V>Функциональная декомпозиция — это лишь один из кирпичиков этой парадигмы, как и первоклассность ф-ий.


Краеуголный кирпичик.

V>Считается, что в функциональной парадигме присутствует как минимум еще иммутабельность, и как следствие — инструментарий, типа туплов


Кортежи — не следствие иммутабельности, вообще говоря. Что касается иммутабельности — о чем собственно идет речь — об отсутствии присваивания? Иммутабельность это интересный вопрос, который не мешало бы развить.

V> и прилагающегося к ним паттерн-матчинга,


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

V>раскрутки рекурсии


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

V> и встроенная возможность ленивости (не только при моделировании бесконечных списков, сам факт оперирования ф-иями как значениями предполагает отложенный вызов этих самых ф-ий).


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

V> Т.е. вот минимальный "джентельменский" требований к инструментарию,


Минимальный? Да нет. Минимальный — первоклассность функций. Язык с паттерн-матчингом, кортежами и "раскруткой хвостовой рекурсии" но без первоклассных функций не является функциональным, а язык без всего этого, но с первоклассными функциями — является. Хотябы потому, что лямбда-исчисление это функциональный язык.

Ну и что у нас осталось от этого "джентельменского набора" кроме первоклассных функций и иммутабельности, с которой разберемся позже?

V>для полной поддержки современной функциональной парадигмы.


Давайте без современной. Мы классифицируем языки, так что неплохо было бы использовать для этого предикат для языка. А "язык был функциональным, а после 70ой годовщины отябрьской революции перестал быть функциональным" — никуда не годится. Это предикат для языка и года. Например "современный язык".

K>>Что есть "число строк необходимое для поддержки ООП" и на каком числе строк находится граница между OO и неОО языком?

V>т.к. ось бесконечна, то интересует лишь ее отрезок — суть разность строк, применительно к какой-либо задаче.

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

V>>>определение объекта в студию...

K>>Допустим, АТД с состоянием. Годится?

V>без "А" годится,


А почему без А?

V>ибо под классическое определение объекта попадает любой конечный автомат, разработанный (или смоделированный, не суть) на любом ЯП, например на том же С.


Не понимаю этого возражения. В C нет сущности FSM. Точно также как и сущности "объект" там нет, но используя некоторые сущности существующие в этом языке можно и FSM написать и писать программы с применением объектной декомпозиции.

V>Ok, просто это как бы контрпример к тому, что наличие или отсутствие в инструменте какого-либо одного "кирпичика" не обязательно делает инструмент достаточно подходящим для использования в рамках какой-либо парадигмы, хотя и может сделать применение этой парадигмы с этим инструментом _возможным_. Дело, разумеется, лишь в количестве доп. приседаний, которые согласен делать применяющий, а так же в количестве _автоматически_ обнаруживаемых граблей, принадлежащих к парадигме генетически.


Зачем этот контрпример? Я и сам считаю,(и писал об этом прямо в этой теме), что можно писать программы с применением объектной декомпозиции на неООЯ и с применением функциональной на неФЯ.

V>>>почему ты отделяешь удобства от фич?

K>>Фича — характеристика языка. Удобство — характеристика системы язык-программист. Синтаксис с отступами — фича. С точки зрения Васи — это удобство, с точки зрения Пети — неудобство.
V>Что-то мне подсказывает, что фичи языков, да и сами ЯП высокого уровня появились в ответ на требование "удобства". Набор реализованных взаимодействующих фич в языке является, по-сути, реализацией неких требований удобства с т.з. авторов языка.

См. выделенное. Или это не возражение, а согласие с моими словами?

V>>>Ну на C# можно, и согласно твоей логике, он является ФЯП.

K>>Это уже обсуждалось. Да, со второй версии он соответствует моему определению ФЯП.
V>Тогда неудивительно, что вышел такой длинный спор.

Чувствуется ответственный подход к изучению дискуссии. Функциональность С# здесь еще никто не оспаривал, хотя это не может не удивлять.
На самом деле с ним не все просто и я об этом писал. Также я писал, что мы говорим не о позиционировании, а о классификации.
... << 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[13]: Функциональный/нефункциональный
От: vdimas Россия  
Дата: 10.03.08 18:24
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>Также я писал, что мы говорим не о позиционировании, а о классификации.


Похоже, ты пытаешься классифицировать по фичам, хоть и краеугольным. (Кстати, классифицировать можно много по чему) Тогда в чём полезность дискуссии? Мы ведь инструменты обсуждаем, а каким-то разделом мозга, отвечающим за интуицию, мне кажется, что инструменты имеет смысл классифицировать только по их позиционированию. Например, отвертка классическая и с электроприводом могли бы по очень многим параметрам быть отнесены к разной классификации, но меня бы больше всех интересовала только классификация по назначению. Хотя, достаточно тяжелой отвёрткой можно и гвозди забивать, особенно если классифицировать, скажем, по наличию тяжёлой металлической детали в составе инструмента.
Re[13]: Функциональный/нефункциональный
От: vdimas Россия  
Дата: 11.03.08 09:32
Оценка:
Здравствуйте, Klapaucius, Вы писали:


K>И паттерн-матчинг также не прилагается к кортежам. Паттерн матчинг это инструмент для диспетчеризации и, если есть сложные структуры — средство декомпозиции сложных структур (в частном случае — кортежей). Отношение к функциональному программированию он имеет, но весьма опосредованное. Есть языки с паттерн матчингом не являющиеся функциональными (Prolog) и функциональные языки без паттерн матчинга (Scheme)


Кстати, примеры неудачные привёл. Прологу паттерн-матчинг нужен именно для обработки кортежей.
А насчёт Схемы — вообще вопрос отдельный, согласно твоему же определению насчёт первоклассности Лисп/Схему нельзя отнести к функциональным языкам, ибо ф-ии представляются не "напрямую", как встроенная сущность, а с помощью доп. механизма — списка. В этом плане приведение ф-ий к делегатам в D кажется куда как более ближе к понятию первоклассности.


V>>раскрутки рекурсии


K>Это оптимизация, вообще говоря.


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

K>Как здесь уже правильно было замечено, язык поддерживает общую рекурсию, а раскручивается ли хвостовая рекурсия — вопрос реализации.


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


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


Ну вот, сам же и написал всё правильно. Если раскрутка включена в стандарт, то, может быть, это не просто оптимизация.

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


Они были малоприменимыми в качестве инструмента. Лисп — второй, после Фортрана ЯВУ в истории IT, а на практике применялся на несколько порядков меньше, оставаясь обучающим и исследовательским языком. Случайно ли?


K>Вот видите, вы же сами понимаете, что "возможность ленивости" есть во всех языках с первоклассными функциями, какой смысл в таком случае рассматривать эту характеристику отдельно?


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


V>> Т.е. вот минимальный "джентельменский" требований к инструментарию,


K>Минимальный? Да нет. Минимальный — первоклассность функций. Язык с паттерн-матчингом, кортежами и "раскруткой хвостовой рекурсии" но без первоклассных функций не является функциональным, а язык без всего этого, но с первоклассными функциями — является. Хотябы потому, что лямбда-исчисление это функциональный язык.


И всё-таки, тот же Лисп и Схема не имет ф-ий как первоклассных отдельный сущностей, а паттерн-матчинг (или нечно похожее по сути) там может быть сделан в виде пользовательских ф-ий, ввиду однородности представления данных, т.е., хоть эта фича и не встроенна в язык, её легко получить ср-вами языка (напр. Лисп-надстройка Qi).

Так что, если уж минимизировать, то я бы оставил только одно минимальное требование — конструирование сущностей, аналогичным ф-иям, в процессе работы программы. (Более полные требования уже перечислял в прошлом посте.) Делегаты и замыкания в D очень даже удовлетворяют этому минимальному требованию, так же как и представление ф-ий в виде списков в Лиспе/Схеме.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[14]: Функциональный/нефункциональный
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 11.03.08 09:37
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>>раскрутки рекурсии


K>>Это оптимизация, вообще говоря.


V>Если рассматривать языки ради языков, забыв, что это, в первую очередь — инструмент, то можно слишком на многое закрывать глаза. Мне же всё время хочется называть вещи своими именами, например, раскрутку рекурсии в языках, где это единственный способ организации цикла — условием существования языка в качестве применимого инструмента.


K>>Как здесь уже правильно было замечено, язык поддерживает общую рекурсию, а раскручивается ли хвостовая рекурсия — вопрос реализации.


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


Именно так и поступили для языка Scheme -- там требование поддержки хвостовой рекурсии описано непосредственно в стандарте языка.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[14]: Функциональный/нефункциональный
От: dr.Chaos Россия Украшения HandMade
Дата: 11.03.08 12:07
Оценка:
vdimas wrote:

> Кстати, примеры неудачные привёл. Прологу паттерн-матчинг нужен именно для

> обработки кортежей. А насчёт Схемы — вообще вопрос отдельный, согласно
> твоему же определению насчёт первоклассности Лисп/Схему нельзя отнести к
> функциональным языкам, ибо ф-ии представляются не "напрямую", как
> встроенная сущность, а с помощью доп. механизма — списка
. В этом плане
> приведение ф-ий к делегатам в D кажется куда как более ближе к понятию
> первоклассности.

Погоди, а можно ссылочку. Просто на Scheme, пишу учебные задачки. Чисто
внешне функция FCO. В SICP даже пример приведён как с помощью функций можно
реализовать список.

>

> V>>раскрутки рекурсии
>
> K>Это оптимизация, вообще говоря.
>
> Если рассматривать языки ради языков, забыв, что это, в первую очередь -
> инструмент, то можно слишком на многое закрывать глаза. Мне же всё время
> хочется называть вещи своими именами, например, раскрутку рекурсии в
> языках, где это единственный способ организации цикла — условием
> существования языка
в качестве применимого инструмента.

В Nice или в D это разве единственный способ?

> K>Как здесь уже правильно было замечено, язык поддерживает общую рекурсию,

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

Для Scheme это важно, т.к. там циклы по другому не делаются, для Nice/D
просто оптимизация.

> V>> Т.е. вот минимальный "джентельменский" требований к инструментарию,

>
> K>Минимальный? Да нет. Минимальный — первоклассность функций. Язык с
> паттерн-матчингом, кортежами и "раскруткой хвостовой рекурсии" но без
> первоклассных функций не является функциональным, а язык без всего этого,
> но с первоклассными функциями — является. Хотябы потому, что
> лямбда-исчисление это функциональный язык.
[]
> Так что, если уж минимизировать, то я бы оставил только одно минимальное
> требование — конструирование сущностей, аналогичным ф-иям, в процессе
> работы программы. (Более полные требования уже перечислял в прошлом
> посте.) Делегаты и замыкания в D очень даже удовлетворяют этому
> минимальному требованию, так же как и представление ф-ий в виде списков в
> Лиспе/Схеме.

На D и Nice можно писать в функциональном стиле практически одинаково
просто. Но разница между Nice и D в дизайне этой фичи — насколько я
понимаю, автор Nice сразу заложил в язык функции как FCO, но в некоторых
местах вылазят ограничение платформы, которые он толи не смог, толи не стал
скрывать. В D же автор эту фичу внёс уже позже и пришлось городить делегаты
и прочее. И выходит разница между ними, с точки зрения практики, только в
этом. Поскольку оба языка гибридные, то ИМХО в Nice код в функциональном
стиле выглядит органичнее и естественнее, чем такой же на D. Особенно после
Scheme или Haskell.
Posted via RSDN NNTP Server 2.1 beta
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[15]: Функциональный/нефункциональный
От: vdimas Россия  
Дата: 11.03.08 12:55
Оценка:
Здравствуйте, dr.Chaos, Вы писали:


DC>Погоди, а можно ссылочку. Просто на Scheme, пишу учебные задачки. Чисто

DC>внешне функция FCO.

Ну, полностью реализующих 5-й стандарт еще не видел. А для многих существующих реализаций-интерпретаторов ф-ия от списка мало чем отличается.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[16]: Функциональный/нефункциональный
От: dr.Chaos Россия Украшения HandMade
Дата: 11.03.08 13:24
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, dr.Chaos, Вы писали:



DC>>Погоди, а можно ссылочку. Просто на Scheme, пишу учебные задачки. Чисто

DC>>внешне функция FCO.

V>Ну, полностью реализующих 5-й стандарт еще не видел. А для многих существующих реализаций-интерпретаторов ф-ия от списка мало чем отличается.


А функция от этого перестаёт быть FCO? Насколько я понимаю там список нужен для хранения замкнутых переменных.

In computer science, a programming language is said to support first-class functions (or function literal) if it treats functions as first-class objects. Specifically, this means that the language supports constructing new functions during the execution of a program, storing them in data structures, passing them as arguments to other functions, and returning them as the values of other functions.
© Wikipedia


Что из этих действий я не могу делать с функциями в Scheme если они реализованы с помощью списков?
Побеждающий других — силен,
Побеждающий себя — Могущественен.
Лао Цзы
Re[17]: Функциональный/нефункциональный
От: vdimas Россия  
Дата: 11.03.08 15:01
Оценка:
Здравствуйте, dr.Chaos, Вы писали:

DC>>>Погоди, а можно ссылочку. Просто на Scheme, пишу учебные задачки. Чисто

DC>>>внешне функция FCO.

V>>Ну, полностью реализующих 5-й стандарт еще не видел. А для многих существующих реализаций-интерпретаторов ф-ия от списка мало чем отличается.


DC>А функция от этого перестаёт быть FCO? Насколько я понимаю там список нужен для хранения замкнутых переменных.


Да нет, само тело ф-ии — это список, системный eval делает apply к членам списка (apply просто берет голову списка, и вызывает её с хвостом в кач-ве аргумента). Результат хранения замкнутых переменных — это новая ф-ия, которая содержит в своём теле вызов исходной.


DC>

DC>In computer science, a programming language is said to support first-class functions (or function literal) if it treats functions as first-class objects. Specifically, this means that the language supports constructing new functions during the execution of a program, storing them in data structures, passing them as arguments to other functions, and returning them as the values of other functions.
DC>© Wikipedia


DC>Что из этих действий я не могу делать с функциями в Scheme если они реализованы с помощью списков?


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

А в классическом Лисп любые структуры данных организуются как списки, и тела ф-ий — в т.ч., т.е. нет отдельной сущности — функции. Сконструированный вручную список может представлять из себя ф-ию (речь о пользовательских ф-иях).
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[14]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 12.03.08 18:52
Оценка:
Здравствуйте, vdimas, Вы писали:

K>>И паттерн-матчинг также не прилагается к кортежам. Паттерн матчинг это инструмент для диспетчеризации и, если есть сложные структуры — средство декомпозиции сложных структур (в частном случае — кортежей). Отношение к функциональному программированию он имеет, но весьма опосредованное. Есть языки с паттерн матчингом не являющиеся функциональными (Prolog) и функциональные языки без паттерн матчинга (Scheme)

V>Кстати, примеры неудачные привёл. Прологу паттерн-матчинг нужен именно для обработки кортежей.

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

V>А насчёт Схемы — вообще вопрос отдельный, согласно твоему же определению насчёт первоклассности Лисп/Схему нельзя отнести к функциональным языкам, ибо ф-ии представляются не "напрямую", как встроенная сущность, а с помощью доп. механизма — списка.


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

V>В этом плане приведение ф-ий к делегатам в D кажется куда как более ближе к понятию первоклассности.


Проблема как раз в приведении. Но с первоклассностью делегатов я никогда и не спорил.

V>Если рассматривать языки ради языков, забыв, что это, в первую очередь — инструмент, то можно слишком на многое закрывать глаза. Мне же всё время хочется называть вещи своими именами, например, раскрутку рекурсии в языках, где это единственный способ организации цикла — условием существования языка в качестве применимого инструмента.


Безотносительно к тому является ли язык инструментом (а с моей точки зрения язык инструментом является) это все равно деталь реализации. Кроме того, для языков, в которых есть другие способы реализации цикла раскрутка хвостовой рекурсии "условием существования" (правильнее — условием существования реализации) не является.

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

V>Они были малоприменимыми в качестве инструмента.

Если есть набор стандартных комбинаторов вроде map и fold (как они реализованы внутри — неважно) гарантированная раскрутка хвостовой рекурсии теряет решающее значение.

V>Лисп — второй, после Фортрана ЯВУ в истории IT, а на практике применялся на несколько порядков меньше, оставаясь обучающим и исследовательским языком. Случайно ли?


Не думаю, что тут все дело в раскрутке хвостовой рекурсии. Но это разговор отдельный.

K>>Вот видите, вы же сами понимаете, что "возможность ленивости" есть во всех языках с первоклассными функциями, какой смысл в таком случае рассматривать эту характеристику отдельно?

V>Я, наверно, недостаточно раскрыл понятие "встроенной" ленивости. Я подразумевал "прозрачное" построение структурированных данных как цепочек ленивых вызовов.

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

V>И всё-таки, тот же Лисп и Схема не имет ф-ий как первоклассных отдельный сущностей,


Думаю, что Схема — имеет.

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


А зачем? Благодаря однородности представления данных он там и не нужен.

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


Это необходимо, но недостаточно — эти "аналогичные функциям сущности" нужно еще и передавать в другие "аналогичные функциям сущности" и возвращать из них.
... << RSDN@Home 1.2.0 alpha 3 rev. 880>>
'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[42]: Функциональный/нефункциональный
От: Klapaucius  
Дата: 12.03.08 18:52
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Это игра терминов. То, что в D называется делегатом, во многих ФЯ называется функцией. Просто напомню, что для нас (программистов) ЯП — лишь инструмент, и в этом смысле делегаты в D и ф-ии в ФЯ — это абсолютно один и тот же инструмент, хоть и называется по-разному в рамках разных языков.


Тем не менее, то, что в D называется функцией — первоклассным объектом не является. А то, что называется делегатом — является.

K>>В Nice никакие делегаты не нужны — как раз потому, что функции — первоклассные.

V>Потому что других типов ф-ий нет, лишь те, что аналоги делегатов.

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

В D есть четыре разновидности "аналогичных функциям сущностей" — два вида функций (статические+свободные и экземплярные методы) и два вида делегатов. Оба вида делегатов — первоклассные объекты.

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

Спасибо за дельное замечание.
... << RSDN@Home 1.2.0 alpha 3 rev. 880>>
'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
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.