Re[10]: ФП: вводная статья
От: Gaperton http://gaperton.livejournal.com
Дата: 28.09.04 15:27
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


G>>Я тоже хочу именно этого. Приступим. Вот дословный перевод твоего алгоритма на Clean.

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

G>>Давай мы все-таки не будем меряться скоростью свопа и количеством оперативки, хорошо?

WH>А у тебя что меньше ста дватцати метров?
Нет, дело в том, что компилятор Clean не умеет паковать unboxed bool массивы в битовые маски, вот и все. Так что у меня это гиг. В теории, это поправимо, нет серьезных причин мешающих добавить эту оптимизацию в компилятор.

G>>23.59 секунд на моей системе.

WH>Execution: 21.31 Garbage collection: 0.21 Total: 21.53 и примерно 290 метров памяти.
WH>Моя программа
WH>8.66727 и примерно 12.8 метров памяти.
В 2.5 раза быстрее. Вполне адекватно. Я, правда, рассчитывал на проигрыш максимум вдвое. У них видимо большой оверхэд на управление памятью. На самом деле, нет никаких принципиальных проблем, мешающих сгенерировать эффективный код по приведенной программе на Clean. Кстати, не хочешь померять на векторе char вместо bool? Просто любопытно, как изменится скорость.

WH>Хотя если выкинуть std::vector<bool> и работать с битами ручками то получается лучше хотя и не на много

Ну ты еще SSE2 c MMX поюзай. Пишем обычный гражданский код, нечего тут
Re[10]: ФП: вводная статья
От: Gaperton http://gaperton.livejournal.com
Дата: 28.09.04 17:39
Оценка:
Здравствуйте, WolfHound, Вы писали:

G>>23.59 секунд на моей системе.

WH>Execution: 21.31 Garbage collection: 0.21 Total: 21.53 и примерно 290 метров памяти.
WH>Моя программа
WH>8.66727 и примерно 12.8 метров памяти.

Чудеса оптимизации.

sieve primes i
    | i == Size    = primes
     | primes.[ i ] = sieve { primes & [ n * i ] = False \\ n <- [ 2.. (Size - 1)/i ] } ( i + 1 )
                        = sieve primes ( i + 1 )


Что сделано: заменяем [ 2*i, 3*i..Size-1 ] на [ 2..(Size — 1)/i ].

15.67 секунд, 98 мегов памяти. Вот теперь все нормально.
У тебя на компе будет ~14.16 секунд. Против 8.66 твоих. Теперь ты примерно в 1.6 раз быстрее. А разница в расходе памяти объясняется только отсутствием упаковки bool массивов. Т. е. все в порядке. Хотя такие вещи компилятор мог бы делать и сам. Ну как, сделаешь версию на char?

экзешник я заменил на новый.
Re: ФП: БИБЛИОТЕКИ???
От: Дм.Григорьев  
Дата: 28.09.04 18:19
Оценка:
Здравствуйте, Quintanar, Вы писали:

[skipped]

Прочитал с интересом почти все (и в этой теме, и в флейме про ФЯ), кое-что даже понял, и созрел у меня серьезный вопрос: БИБЛИОТЕКИ??? Работа с файлами, GUI, TCP-сокеты, интерфейсы к базам данных, написание служб NT, multitier, и т.д., и т.п. Реально на нынешних ФЯ написать реальные программы? А то все эти демонстрации возможностей смахивают больше на школьный курс программирования, или на фортран в руках математика:

10 input(n)
20 длинный алгоритим без ввода-вывода
1000 output(s)


Не выльется ли разработка скажем простейшей складской программы для малого предприятия в извращение, вроде моих отчаянных попыток использовать XML-файлы в веб-сайтах любой сложности, чтобы не связываться с непонравившимся мне MySQL?
http://dimgel.ru/lib.web — thin, stateless, strictly typed Scala web framework.
Re: ФП: вводная статья
От: Banch  
Дата: 28.09.04 18:21
Оценка: 1 (1) +1
Здравствуйте, Quintanar, Вы писали:

несколько раз читал всякие вводные статьи по ФЯ и так ничего и не понял, потому что в какой-то момент автор вводил какую-нть закорюку и забывал ее объяснить, а потом оказывалось что на ней то все и строиться

немного моих вопросов, заранее прошу прощения если тупых:

Q>Вторым важным конструктором новых типов является кортеж (tuple). Это всего лишь набор разнотипных значений

Q>вроде
Q>
Q>(1,"str",'a')
Q>

Q>Кортежы используются для возвращения из функций нескольких значений, определения сложных типов типа деревьев
Q>или списков и т.п.

и чем тогда кортеж отличается от списка?
как я в структуре типа дерево отлечу какой элемент кортежа относиться к какой ветке? по индексу в кортеже?

Q>Например, определим тип для выражения

Q>в языке программирования
Q>
Q>data Expr = Var String | Integer Int | Str String | Assign Var Expr | Func Var [Expr]
Q>


что означает эта строка?
ну первую часть я кажется понял, но все равно не уверен

Q>Var, Integer, Str, Func и Assign — это так называемые конструкторы типа. С их помощью можно создать

Q>значение типа Expr
Q>
Q>Assign (Var "my_var") (Func (Var "my_func") [(Str "str"),(Integer 10)])
Q>

Q>Возможности впечатляют, однако, это еще не все.

какие возможности? написать нечитаемый ужас из смеси скобок?

Q>имеет тип

Q>
a->>[a]
Q>


хм, что это за тип?

Q>
Q>my_func my_func2
Q>my_func:(my_func my_func2)
Q>


что это за выражения? что в них написано?

Q>Остается добавить, что отдельные ФЯ расширяют стандартную систему типов разными способами. Например, в

Q>OCaml добавлены классы, а в Haskell'e существуют классы типов, которые чем-то похожи на интерфейсы в ООП
Q>языках.

а как тогда быть с бизнес объектами?
как разбивать логику?
с математическими задачами я примерно понял, действительно удобно

Q>Имея эту функцию мы можем создать новые функции типа

Q>
Q>inc x = add 1 x
Q>add10 x = add 10 x
Q>

Q>первая из которых увеличивает свой аргумент на 1, а вторая на 10. Разница с обычным вызовом более
Q>общей подфункции с некоторыми фиксированными аргументами заключается в том, что функция add 1 будет
Q>частично вычислена один раз и при дальнейших вызовах перевычислятся не будет.

не понял что там можно частично вычислить в выражении add 1 ?? заранее вычислить что 1 это 1 ?!
даже допустим там стоит не 1, а sqrt(2), ну и что — я могу положить это один раз в статическую переменную


Кроме того хотелось бы каких-нть реалистичных примеров, которые трудно или громоздко реализовать с помощью ИЯ (реализацию на ИЯ обязательно нужно тоже привести, причем несколько человек должны на этот код посмотреть и сказать что он действительно написан хорошо и довольно оптимально) и подробнейшего описания к этим примерам, до последней запятой, потому что, как я понял, любой знак в ФЯ может иметь кардинальное значение: за ним может стоять целая теория, мега базовая функциональность системы или библиотека.
Я понимаю что многого хочу, но если есть желание объяснять, то я готов разбираться
Re[2]: ФП: вводная статья
От: Дм.Григорьев  
Дата: 28.09.04 18:29
Оценка:
Здравствуйте, Banch, Вы писали:

B>немного моих вопросов, заранее прошу прощения если тупых:

B>[]

+1. Мне тоже интересно. Вводная статья не должна быть написана в предположении, что о синтаксических и прочих ньюансах читатели сами догадаются.
http://dimgel.ru/lib.web — thin, stateless, strictly typed Scala web framework.
Re[11]: ФП: вводная статья
От: WolfHound  
Дата: 28.09.04 20:03
Оценка: 12 (1)
Здравствуйте, Gaperton, Вы писали:

G>Чудеса оптимизации.

хъ
G>15.67 секунд, 98 мегов памяти. Вот теперь все нормально.
Гы!
G>У тебя на компе будет ~14.16 секунд. Против 8.66 твоих. Теперь ты примерно в 1.6 раз быстрее.
У меня Execution: 13.85 Garbage collection: 0.00 Total: 13.85
G>А разница в расходе памяти объясняется только отсутствием упаковки bool массивов.
Я тебе больше скажу... Этим же объясняется и разрыв в производительности... См ниже...
G>Ну как, сделаешь версию на char?
Сделал... Блин я чуть со стула не упал... 13.5022
int main()
{
    timer_t timer;
    unsigned size=100000000;
    std::vector<char> is_prime(size, true);    //помечаем все числа как простые
    for(unsigned i=2;i<size;++i)            //ищем очередное не вычеркнутое число
        if(is_prime[i])                        //i очередное простое число
            for(unsigned n=i+i;n<size;n+=i)    //вычеркиваем все числа кратные данному числу
                is_prime[n]=false;
    std::cout<<timer.time()<<"\n";
}

Хотя код получился на много меньше и с виду быстрее...
; 34   :     unsigned size=100000000;
; 35   :     std::vector<char> is_prime(size, true);    //помечаем все числа как простые

    lea    edx, DWORD PTR $T72542[esp+72]
    push    edx
    push    100000000                ; 05f5e100H
    lea    ecx, DWORD PTR _is_prime$[esp+80]
    mov    BYTE PTR $T72542[esp+80], 1
    call    ?_Construct_n@?$vector@DV?$allocator@D@std@@@std@@QAEXIABD@Z ; std::vector<char,std::allocator<char> >::_Construct_n

; 36   :     for(unsigned i=2;i<size;++i)            //ищем очередное не вычеркнутое число

    mov    esi, DWORD PTR _is_prime$[esp+76]
    mov    DWORD PTR __$EHRec$[esp+80], 0
    mov    ecx, 2
    npad    5
$L64503:

; 37   :         if(is_prime[i])                        //i очередное простое число

    cmp    BYTE PTR [esi+ecx], 0
    je    SHORT $L64504

; 38   :             for(unsigned n=i+i;n<size;n+=i)    //вычеркиваем все числа кратные данному числу

    cmp    ecx, 50000000                ; 02faf080H
    lea    eax, DWORD PTR [ecx+ecx]
    jae    SHORT $L64504
$L64508:

; 39   :                 is_prime[n]=false;

    mov    BYTE PTR [esi+eax], 0
    add    eax, ecx
    cmp    eax, 100000000                ; 05f5e100H
    jb    SHORT $L64508
$L64504:

; 36   :     for(unsigned i=2;i<size;++i)            //ищем очередное не вычеркнутое число

    inc    ecx
    cmp    ecx, 100000000                ; 05f5e100H
    jb    SHORT $L64503

Но оказывается узкое место ПАМЯТЬ...
Теперь понятно почему ручная работа с битами практически не сказалась на производительности...
... << RSDN@Home 1.1.4 rev. 185 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: ФП: вводная статья
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.09.04 20:03
Оценка:
Здравствуйте, Lloyd, Вы писали:

L>Удивительно, но у Кнута тогда он тоже перевран.


На память говорить не хорошо, но вроде бы был верным. Уж точно сортировка была по месту. К тмоу же у алгоритма есть автор. И кнут к нему не имеет ни малейшего отношения. Так что классический, есть классический.
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ФП: вводная статья
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.09.04 20:03
Оценка:
Здравствуйте, Quintanar, Вы писали:

Q>В OCaml есть парсер P4, с помощью которого можно сделать свой собственный синтаксис — хочешь императивный, хочешь функциональный.


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

В С++, в конце концов, тоже есть препроцессор с помощью которого и какой-то матери много чего можно сильно сократить. Только это уже не совсем выражение алгоритма на языке. К тому же пример был на Хаскеле, как я понимаю...
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ФП: вводная статья
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.09.04 20:03
Оценка:
Здравствуйте, Nick_, Вы писали:

VD>>Многое же выдаваемое за достоинство ФЯ на самом деле является всего лишь фичами конкретных языков и без проблем может быть реализовано (да и реализуется) на ИЯ.


N_>Голодная кума Лиса залезла в сад,

N_> В нем винограду кисти рделись.
N_> У кумушки глаза и зубы разгорелись;
N_>А кисти сочные как яхонты горят;
N_> Лишь то беда, висят они высоко:
N_> Отколь и как она к ним ни зайдет,
N_> Хоть видит око,
N_> Да зуб неймет.
N_> Пробившись попусту час целой,
N_>Пошла и говорит с досадою: "Ну, что ж!
N_> На взгляд-то он хорош,
N_> Да зелен — ягодки нет зрелой:
N_> Тотчас оскомину набьешь".

Ну, что же... достойный уход от дисскусси. Коне дет аргументов в бой идут аллегории. Так?
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ФП: вводная статья
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.09.04 20:03
Оценка:
Здравствуйте, INTP_mihoshi, Вы писали:

_>>>Вообщем pattern matching -та черта ФЯ полезность которой не вызывает сомнений

VD>>+1

INT>Опять же, является ли это чертой именно ФЯ...


Ну, в принцпе зачатки есть в С++. Но в большей степени они реализуется в ФЯ, да и само наличие pattern matching уже приводит к улучшению создания кода в функциональном стиле.

INT>Поддержка компилятора и распараллеливания разруливание ручками под каждую кончигурацию машины?


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

INT>Или ты хочешь сказать, что на C или C++ можно написать код, который компилятор сам эффективно распараллелит?


Мы ту недавно опубликовали статью на эту тему. Проще прочесть ее чем обсуждать
Автор(ы): Intel Corporation
Дата: 05.08.2004
Эта статья предоставлена Intel как часть программы для разработчиков Intel Developer Services. Участникам программы предоставляется доступ к полной версии этой и других статей. Чтобы стать участником программы, достаточно зарегистрироваться на нашем сайте по адресу http://rsdn.ru/article/baseserv/intel/reg.aspx.
.

INT>Обычно на функциональных языках. Хотя бывают варианты. В Ocaml есть и чисто камшловый парсер, и парсер со вставками на C.


Ну, создаются же? Зачем, если все так пушисто и без них?

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


Можно сказать и так. Тут бесспорно у ФЯ есть явные преимущества перед ИЯ.

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


Вот это уже спорно.

INT> — программа состоит как правило из меньших и менее связанных элементов, чем программа в объектном стиле.


Возможно. Но воспринимать функциональную запись сложно. Особенно если нет должной тренировки. А между тем полезные (с моей точки зрения) фичи ФЯ можно применять и с использыванием куда более интуитивно понятного синтаксиса. Более того. По-моему, нет особых пролем красиво сопрягать декларативных стиль кодирования и императивную реализацию. Грубо говоря декларативные вещи можно описывать в виду императивных алгоритмов, а потом использовать в чисто деларативном стиле. Это с одной стороны похоже на ФЯ, так как использует похожие принцип, но с другой несклько иная концепция и реализация. Но в итоге язык позволяющий объявлять чистые абстракции может давать значительно более понятный код. Ведь не нужно подстравиваться под принципы записи и ограничения. Вместо этого просто можно подстраивать сам язык. Собствнно это то, что мы хотим реализовать в R#-е. Думаю, что и многие функциональные фичи можно будет реализовать таким образом. Возможно я и не прав, но пока что эта идея мне кажется верной и я не вижу серьезной аргументации опровергающей ее.

ЗЫ

В общем, по-моему, ключевым моментом является именно повышение уровня абстракции и тут ФЯ, ЛЯ, ООП, АОП и то что хочется сделать мне пересекается. Так что есть о чем поговорить. Вот только хотелось бы без издевок и наездов. А то я тоже быстро завожусь.
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ФП: вводная статья
От: VladD2 Российская Империя www.nemerle.org
Дата: 28.09.04 20:03
Оценка:
Здравствуйте, Quintanar, Вы писали:

Q> А вот как выглядит монадный LL парсер написанный с помощью небольшой библиотеки базовых функций. Обрати внимание, что все детали реализации скрыты в монадах и остается только суть — сама граматика.


Да, согласен, не плохо. Но все же это не EBNF. Много лишней шелухи, другой синтаксис. Да и наверняка будет проблемы с отделением продукций от генерируемого АСТ. Вот собственно и хотелось бы заполучить продукт не имеющий вообще ограничений подобного рода (или хотя бы сводящий их к минимуму).

Q>Исходники библиотеки, кстати, можно изучить за час — два, настолько она проста.


Q>Здесь только часть парсера, чтобы была понятна идея. Думаю, надо написать LL парсер C# на Haskell'e и сравнить с вашей реализацией.


Ну, это явно не Шарп. Скорее похоже на Яву, да и то с горой ошибок и упущений. Из-за непривычного синтаксиса сразу сказать затрудняюсь. Граматика для LL(k)-парсера в формате EBNF (точнее генератора парсеров на C# CocoR) можно взять тут: http://gzip.rsdn.ru/projects/RSharp/vcs.aspx (там лежит граматика для C# 2.0).

Чистым LL(1) Шарп не парсится в принципе. Да и с нечистым возникают проблемы так как в языке есть контекстно-зависимые ключевые слова.
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: ФП: вводная статья
От: FR  
Дата: 28.09.04 20:29
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Возможно. Но воспринимать функциональную запись сложно. Особенно если нет должной тренировки. А между тем полезные (с моей точки зрения) фичи ФЯ можно применять и с использыванием куда более интуитивно понятного синтаксиса. Более того. По-моему, нет особых пролем красиво сопрягать декларативных стиль кодирования и императивную реализацию. Грубо говоря декларативные вещи можно описывать в виду императивных алгоритмов, а потом использовать в чисто деларативном стиле. Это с одной стороны похоже на ФЯ, так как использует похожие принцип, но с другой несклько иная концепция и реализация. Но в итоге язык позволяющий объявлять чистые абстракции может давать значительно более понятный код. Ведь не нужно подстравиваться под принципы записи и ограничения. Вместо этого просто можно подстраивать сам язык. Собствнно это то, что мы хотим реализовать в R#-е. Думаю, что и многие функциональные фичи можно будет реализовать таким образом. Возможно я и не прав, но пока что эта идея мне кажется верной и я не вижу серьезной аргументации опровергающей ее.


В последних версиях питона это практически реализовано.
Re[10]: ФП: вводная статья
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.09.04 06:20
Оценка: +1
Здравствуйте, FR, Вы писали:

FR>просто ты не хочешь признать что императивный язык тоже может быть декларативным.

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

Примеры функционально плоховыразимых задач лежат не здесь. Пока состояние маленькое, можно пользоваться семантикой копирования. В конце концов, есть алгоритмы SSA и SSI, которые превращают любую императивную программу в функциональную.
Что мне пока не очень ясно, так это как можно применять ФП для Enterprise — приложений. Ну вот типа есть у нас БД гигов на восемь-двенадцать. Нет, конечно формально мы можем функцию регистрации заказа определить как отображение одной БД на другую БД, в которой отличается только остаток товара на конкретном складе. Но как сделать СУБД, способную понять взаимозависимости между параллельно выполняемыми запросами в ФП-стиле, я понять не могу.
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: ФП: вводная статья
От: INTP_mihoshi Россия  
Дата: 29.09.04 07:20
Оценка: 4 (1)
Здравствуйте, Banch, Вы писали:

Q>>Кортежы используются для возвращения из функций нескольких значений, определения сложных типов типа деревьев

Q>>или списков и т.п.
B>и чем тогда кортеж отличается от списка?
Кортеж, он же tuple.
В данном случае — конечная последовательность значений. Отличается от списка тем, что кол-во элементов фиксировано и типы значений могут быть различными. От Cшной структуры отлисается тем, что элементы различаются по порядку, а не по имени.

Тип аргумента соответствует последовательности типов аргументов. Например, тип кортежа (1, 1., "1") равен int*float*string. Элементы из кортежа достаются обычно с помощью pettern-matching. Например:


let (min,max) = (main_and_max_of_list somelist) in
print_int min; 
print_int max;


B>как я в структуре типа дерево отлечу какой элемент кортежа относиться к какой ветке? по индексу в кортеже?

Примерно так. Например: let (leftleaf, rightleaf) = leafs_of node ...

Q>>
Q>>data Expr = Var String | Integer Int | Str String | Assign Var Expr | Func Var [Expr]
Q>>


B>что означает эта строка?

B>ну первую часть я кажется понял, но все равно не уверен

Это т.н. variant. Что-то типа Сшного union, но с известным типом текущего значения.
type expr = Integer of Int | Str of String | Assign of expr * expr обозначает, что значение типа Expr может быть равно Var строчка, Str строчка, Integer целое и т.д.


string_of_expr expr = match expr with
  |Var v -> "variable %s" v
  |Str v -> "string %s" v
  |Int v -> "integer %d" v
  |Assign lv rv -> sprintf "let %d = %d" (string_of_expr lv) (string_of_expr rv)
  | _ -> "don't know how to write it"


Вобщем, в языках со строгой типизацией вместо enum и union используются variant.


Q>>имеет тип

Q>>
a->[a]
Q>>


B>хм, что это за тип?


Отображение значения типа а в список значений типа а. В Ocaml перед a стоял бы апостроф, обозначающий, что a — произвольный тип, а не какой-то известный тип, названный a.

B>а как тогда быть с бизнес объектами?

B>как разбивать логику?
B>с математическими задачами я примерно понял, действительно удобно
Разбивать, как всегда, по модулям.

B>не понял что там можно частично вычислить в выражении add 1 ?? заранее вычислить что 1 это 1 ?!

B>даже допустим там стоит не 1, а sqrt(2), ну и что — я могу положить это один раз в статическую переменную

Нет, add 1 — это функция одного аргумента, возвращающая сумму его с 1.
Т.е., если мы даем функции меньше аргументов, чем необходимо, то получаем такую же функцию, но с уже известной частью аргументов. Вообще это иногда полезный побочный эффект карринга. Вобщем, того же эффекта можно добиться другими способами. Например, следующие определения совершенно эквивалентны
let inc v = add 1 v

let inc = add 1
Re[11]: ФП: вводная статья
От: FR  
Дата: 29.09.04 07:52
Оценка: +1
Здравствуйте, Sinclair, Вы писали:

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


FR>>просто ты не хочешь признать что императивный язык тоже может быть декларативным.

S>Увы. Самое главное — в твоем коде нет изменения состояния. Ты выразил именно зависимость между входом и выходом. А эквивалентность этого некоторому конкретному ходу исполнения императивной программы — не более чем забавный факт. В коде с циклом изменение состояния уже есть, поскольку можно фиксировать квантованные шаги, на которых ltList неполон. Т.е. в таком случае машина вынуждена делать определенные элементарные действия в определенном порядке.

На эту конструкцию можно смотреть с двух сторон, и я не думаю что один взгляд правильнее другого.
Re[2]: ФП: БИБЛИОТЕКИ???
От: Quintanar Россия  
Дата: 29.09.04 08:47
Оценка:
Здравствуйте, Дм.Григорьев, Вы писали:

ДГ>Прочитал с интересом почти все (и в этой теме, и в флейме про ФЯ), кое-что даже понял, и созрел у меня серьезный вопрос: БИБЛИОТЕКИ??? Работа с файлами, GUI, TCP-сокеты, интерфейсы к базам данных, написание служб NT, multitier, и т.д., и т.п. Реально на нынешних ФЯ написать реальные программы? А то все эти демонстрации возможностей смахивают больше на школьный курс программирования, или на фортран в руках математика:


У всех серьезных языков есть стандартные библиотеки, которые включают в себя всякие базовые нужные функции, работу с файлами, различными типами данных, системой, сетью. Есть, как правило, возможность использовать GUI типа TCL/TK. Есть и сторонние библиотеки, но их надо скачивать отдельно, где реализованы более специфические вещи типа Corba, DB и т.п. Если библиотеки нет, можно использовать внешние С-шные модули, они подключаются без особых трудозатрат.
Re[2]: ФП: вводная статья
От: Quintanar Россия  
Дата: 29.09.04 09:57
Оценка: 11 (2)
Здравствуйте, Banch, Вы писали:

B>и чем тогда кортеж отличается от списка?

B>как я в структуре типа дерево отлечу какой элемент кортежа относиться к какой ветке? по индексу в кортеже?

Кортеж имеет фиксированную длину и элементы в нем могут быть разных типов. В ИЯ его аналогом являются структуры. Доступ к элементам кортежа осуществляется с помощью pattern matching
let (x,y,z) = ("a",(1,'a'),'b')

здесь x будет связано со значением "a", y = (1,'a'), z = 'b'.
С деревом аналогично:
data Tree = Node Tree Tree | Leaf Int
do_something tree = 
  case tree of
    Node left right -> ...
    Leaf value -> ...


Q>>
Q>>data Expr = Var String | Integer Int | Str String | Assign Expr Expr | Func Expr [Expr]
Q>>

B>что означает эта строка?
B>ну первую часть я кажется понял, но все равно не уверен

Это объявление сложного типа Expr. Такая запись означает, что Expr может быть равен Var String, Integer Int и т.д. Первое имя в такой записи — конструктор типа, по которому мы можем в дальнейшем распознать чему равен Expr (как выше в примере с деревом), создать соответствующее значение этого типа (Var "my_var", например). Дальше идут типы аргументов конструктора типа. Запись Var String означает, что конструктор Var принимает аргумент типа String и создает значение типа Expr. Func Expr [Expr] значит, что конструктор Func принимает два аргумента типа Expr и список из Expr и создает значение типа Expr. Таким образом Expr может быть равен некоторой строке, целому, паре двух Expr'ов и т.д. Т.е. его можно представлять себе как объединение нескольких структур и простых типов, где доступ к различным элементам union осуществляется с помощью конструкторов типа.
union Expr = {
  Var : String,
  Integer : Int,
  Str : String,
  Assign: { Expr, Expr },
  Func : { Expr, [Expr] }
}


Q>>
Q>>Assign (Var "my_var") (Func (Var "my_func") [(Str "str"),(Integer 10)])
Q>>

B>какие возможности? написать нечитаемый ужас из смеси скобок?

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

Q>>
a->[a]
Q>>

B>хм, что это за тип?

У каждой переменной или функции есть тип. Записывается он следующим образом:
Если у переменной тип простой и заранее известный, то так и пишется — Int, String ...
Если тип переменной неизвестен, то пишется — a,b,c,... (или `a,`b... в зависимости от языка)
Если тип параметризирован, то пишется вместе с параметрами — [a], Tree Int, (Int, String) ...
[a] — список неизвестного типа, Tree Int — Дерево из Int'ов.
Если есть функция с n параметрами, то ее тип записывается следующим образом:
type of arg1 -> type of arg2 -> ... -> type of argn -> type of result
Для функции сложения тип будет такой — Int->Int->Int
Для функции добавления элемента в список — a->[a]->[a]
Для функции возвращающей первый элемент бинарного кортежа — (a,b)->a

Q>>
Q>>my_func my_func2
Q>>my_func:(my_func my_func2)
Q>>

B>что это за выражения? что в них написано?

my_func создает список состоящий из одного элемента = ее аргументу => в данном случае создается список функций, в котором лежит одна функция my_func2. Во втором случае в этот список добавляется второй элемент — сама функция my_func. Выглядит забавно, но зато демонстрирует, что мы можем свести полиморфный тип к более узкому типу (my_func имеет тип a->[a], а список состоит из элементов типа Expr->[Expr]).

B>а как тогда быть с бизнес объектами?

B>как разбивать логику?
B>с математическими задачами я примерно понял, действительно удобно

Приведи пример разбиения и я скажу как это делается в ФЯ, а так сложно сказать.

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

B>Я понимаю что многого хочу, но если есть желание объяснять, то я готов разбираться

Это надо посмотреть.
Re[6]: ФП: вводная статья
От: Quintanar Россия  
Дата: 29.09.04 10:02
Оценка:
Здравствуйте, VladD2, Вы писали:

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


Q>>В OCaml есть парсер P4, с помощью которого можно сделать свой собственный синтаксис — хочешь императивный, хочешь функциональный.


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


VD>В С++, в конце концов, тоже есть препроцессор с помощью которого и какой-то матери много чего можно сильно сократить. Только это уже не совсем выражение алгоритма на языке. К тому же пример был на Хаскеле, как я понимаю...


Не ты не понял. Ты жаловался на то, что в OCaml трудно понимать программы. Так вот у них там есть P4, с помощью которого можно адаптировать синтаксис OCaml'a к своим нуждам. У них самих на нем сделана новая форма записи — т.е. изменен синтаксис языка без изменения самого языка.
Re[7]: ФП: вводная статья
От: INTP_mihoshi Россия  
Дата: 29.09.04 10:38
Оценка:
Здравствуйте, Quintanar, Вы писали:

Q>Не ты не понял. Ты жаловался на то, что в OCaml трудно понимать программы. Так вот у них там есть P4, с помощью которого можно адаптировать синтаксис OCaml'a к своим нуждам. У них самих на нем сделана новая форма записи — т.е. изменен синтаксис языка без изменения самого языка.


Дополню.
Препроцессор P4 в Ocaml — это не макроподстановки. Это инструмент, который работает непосредственно с синтаксисом языка. Например, он позволяет не только добавлять, но и убирать правила из грамматики.
Пример с удаленями правил можно посмотреть в туториале.
Вот простой пример добавления правил — добавление конструкции repeat/until.

       open Pcaml;;
       EXTEND
         expr: LEVEL "expr1"
           [[ "repeat"; e1 = expr; "until"; e2 = expr ->
                 <:expr< do { $e1$; while not $e2$ do { $e1$; } } >> ]];
       END;;
Re[2]: ФП: БИБЛИОТЕКИ???
От: gloomy rocker Россия  
Дата: 29.09.04 10:42
Оценка:
Здравствуйте, Дм.Григорьев, Вы писали:

ДГ>Здравствуйте, Quintanar, Вы писали:


ДГ>[skipped]


ДГ>Прочитал с интересом почти все (и в этой теме, и в флейме про ФЯ), кое-что даже понял, и созрел у меня серьезный вопрос: БИБЛИОТЕКИ??? Работа с файлами, GUI, TCP-сокеты, интерфейсы к базам данных, написание служб NT, multitier, и т.д., и т.п. Реально на нынешних ФЯ написать реальные программы? А то все эти демонстрации возможностей смахивают больше на школьный курс программирования, или на фортран в руках математика:


ДГ>
ДГ>10 input(n)
ДГ>20 длинный алгоритим без ввода-вывода
ДГ>1000 output(s)
ДГ>


ДГ>Не выльется ли разработка скажем простейшей складской программы для малого предприятия в извращение, вроде моих отчаянных попыток использовать XML-файлы в веб-сайтах любой сложности, чтобы не связываться с непонравившимся мне MySQL?


Посмотри на F#
На нем можно писать код, используя FCL, в которой собрано огромное количество велосипедов.
... << Rsdn@Home 1.1.4 beta 1 >>
Скука — двигатель прогресса.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.