Здравствуйте, Gaperton, Вы писали:
G>Здравствуйте, FR, Вы писали:
FR>>ФЯ тут ни причем, это будет также просто и на императивном языке с FR>>хорошей реализацией встроенных списков, например на питоне: G>Питон позволяет писать в функциональном стиле, было-бы желание. Что мы и видим в твоем примере. Так что ФЯ здесь причем — откуда, ты думаешь, в питоне взялись list comprehensions?
Извини, но в этом примере я не вижу ни грамма функциональности, наоборот это пример применения декларативно-императивных средств которые активно продвигаются создателями пимтона в последних версиях. А списки по моему безразличны к ФЯ и ИЯ (и к ЛЯ в прологе списки не хуже лисповских), и там и там их можно красиво реализовать,
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Nick_, Вы писали:
WH>>>Находит все простые числа меньше заданного. Изобрази этот алгоритм на функциональном языке, а мы посмеемся...
N_>>primes определен как я писал выше.
FR>нет на самом деле уже смешно, про эффективность конечно вообще забываем, но ладно но различий с ИЯ тут тоже нет на C++ это тоже одна строка с готовой то функцией primes.
Да, а еще на С++ 2+2 выглядит совершенно так же, как на хаскель. Сразу видно — у языков много общего — да одно и тоже практически.
На, посмотри, как мы забиваем на эффективность. И найди здесь свой питон (подсказка: ищи в конце), который проиграл вдвое даже динамически типизированному Erlang-у. А если обратить внимание, что в данный момент реализация на haskell занимает в рейтинге первое место, обогнав gcc, то просто обхохочешься.
Советую обратить внимание на позиции haskell и clean сравнительно с gcc — это чисто функциональные языки без императивных расширений. Если кого нибудь расстраивает позиция gcc или java — текст прог можно посмтореть на сайте, изменить, и отправить туда. Это открытое соревнование, так что я думаю, что Haskell недолго будет занимать первую позицию. Это и в самом деле странно.
Sieve of Eratosthenes (showing CPU minus startup)
[sort] [sort] [sort]
Source Code CPU (sec) Mem (KB) Lines Code Log ghc 0.11 1032 11 log out
sbcl 0.14 6256 12 log out gcc 0.14 264 19 log out
cmucl 0.15 4908 12 log out
oberon2 0.15 1096 28 log out
se 0.15 360 57 log out
stalin 0.16 684 20 log out ocaml 0.16 488 17 log out
bigloo 0.17 888 24 log out
nice 0.17 10340 15 log out
gcj 0.18 10208 15 log out
g++ 0.20 760 19 log out
mlton 0.21 588 39 log out clean 0.23 440 17 log out java 0.29 8828 15 log out
kaffe 0.31 6000 15 log out
gwydion 0.33 2300 27 log out
gnat 0.51 1016 33 log out smlnj 0.62 1116 34 log out
chicken 0.65 1088 23 log out
gforth 1.02 756 33 log out
mercury 7.13 8564 32 log out
sablevm 7.71 2832 15 log out
ocamlb 7.72 696 17 log out hipe 7.76 4992 18 log out
oz 7.84 4292 19 log out
rep 8.79 1192 18 log out
gij 8.88 10344 15 log out erlang 9.44 4548 18 log out
lua 10.83 932 21 log out
pike 13.57 2996 15 log out
slang 14.66 844 14 log out
xemacs 14.89 8200 16 log out
gst 15.57 4140 15 log out python 16.64 2112 18 log out
Здравствуйте, Nick_, Вы писали:
VD>>Многое же выдаваемое за достоинство ФЯ на самом деле является всего лишь фичами конкретных языков и без проблем может быть реализовано (да и реализуется) на ИЯ.
+1
N_>Голодная кума Лиса залезла в сад, N_> В нем винограду кисти рделись...
Не нада. А то будет как в прошлой ветке...
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Gaperton, Вы писали:
G>>Здравствуйте, FR, Вы писали:
FR>>>ФЯ тут ни причем, это будет также просто и на императивном языке с FR>>>хорошей реализацией встроенных списков, например на питоне: G>>Питон позволяет писать в функциональном стиле, было-бы желание. Что мы и видим в твоем примере. Так что ФЯ здесь причем — откуда, ты думаешь, в питоне взялись list comprehensions?
FR>Извини, но в этом примере я не вижу ни грамма функциональности, наоборот это пример применения декларативно-императивных средств которые активно продвигаются создателями пимтона в последних версиях.
Я вот в твоем коде не вижу императивности. Причем совсем. Ты бы для начала почитал где-нибудь, что такое "функциональность", например в comp.lang.functional FAQ. Но впрочем, что это я к тебе пристаю? Не видишь — и хорошо.
FR> А списки по моему безразличны к ФЯ и ИЯ (и к ЛЯ в прологе списки не хуже лисповских), и там и там их можно красиво реализовать,
Конечно можно. Кто-то здесь утверждал обратное?
Эратосфен — явно итеративный алгоритм, так что чудес от функционального cтиля в нем не найти.
Так что функциональный аналог выглядит практически один-в один.
let addprime arr n size = fold (fun a i -> set a (i*n)) [2..(size/n)] arr
let sieve size = fold (fun a i -> if get a i then addprime a i size else a) [2..size] (make size true)
На выходе sieve массив с true для простых и false для составных.
fold fun list accum — переводится примерно как foreach value in list (accum := fun accum value).
Например, fold (+) [1..10] 0 равно 55.
get a i — возвращает значение iго элемента массива a
set a i v — массив, в ктоором iый элемент установлен в v, остальные — так же, как в a
make size v — создает массив размером s забитый значениями v
.
FR>>нет на самом деле уже смешно, про эффективность конечно вообще забываем, но ладно но различий с ИЯ тут тоже нет на C++ это тоже одна строка с готовой то функцией primes.
G>Да, а еще на С++ 2+2 выглядит совершенно так же, как на хаскель. Сразу видно — у языков много общего — да одно и тоже практически.
Практически везде функциональчики утверждают, что программы на функциональных языках короче и легче для понимания чем на императивных, но чем дальше я пытаюсь изучать эти языки тем меньше это вижу.
G>На, посмотри, как мы забиваем на эффективность. И найди здесь свой питон (подсказка: ищи в конце), который проиграл вдвое даже динамически типизированному Erlang-у. А если обратить внимание, что в данный момент реализация на haskell занимает в рейтинге первое место, обогнав gcc, то просто обхохочешься.
Не стоит так эмоционально реагировать. Под эффективностью я имел в виду только то что используется абсолютно тупейший алгоритм, и с таким алгоритмом это и на си выглядит красиво и коротко.
А по питону они в этом тесте смухлевали, JIT компилятор закоментировали
FR>>Извини, но в этом примере я не вижу ни грамма функциональности, наоборот это пример применения декларативно-императивных средств которые активно продвигаются создателями пимтона в последних версиях. G> G>Я вот в твоем коде не вижу императивности. Причем совсем. Ты бы для начала почитал где-нибудь, что такое "функциональность", например в comp.lang.functional FAQ. Но впрочем, что это я к тебе пристаю? Не видишь — и хорошо.
то есть цикл for это теперь функциональный стиль? Спасибо не знал.
FR>> А списки по моему безразличны к ФЯ и ИЯ (и к ЛЯ в прологе списки не хуже лисповских), и там и там их можно красиво реализовать, G>Конечно можно. Кто-то здесь утверждал обратное?
Подразумевал, когда приводил алгоритм сортировки на языке со встроенными списками.
Здравствуйте, FR, Вы писали:
FR>то есть цикл for это теперь функциональный стиль? Спасибо не знал.
Функциональный стиль это теперь, как и всегда, в первую очередь — отсутствие побочных эффектов, а не наличие рекурсии со встроенными списками или отсутствие слова for в языке. Не зачто, всегда пожалуйста .
Кстати, слепенький я наверно. Ну не вижу я цикла for в твоем коде. А вот list comprehensions вижу, как и отсутствие побочных эффектов.
def qsort(aList):
if not aList:
return []
ltList=[y for y in aList[1:] if y<aList[0]]
gtList=[y for y in aList[1:] if y>=aList[0]]
return qsort(ltList)+[aList[0]]+qsort(gtList)
FR>>> А списки по моему безразличны к ФЯ и ИЯ (и к ЛЯ в прологе списки не хуже лисповских), и там и там их можно красиво реализовать, G>>Конечно можно. Кто-то здесь утверждал обратное? FR>Подразумевал, когда приводил алгоритм сортировки на языке со встроенными списками.
Откуда ты знаешь, что именно он подразумевал? Ментальное сканирование?
Что характерно, если ты добавишь в любой язык встроенные списки так, как это сделано в современных ФЯ, то на нем сразу станет удобно писать в функциональном стиле. Одного не понимаю, каким именно образом это порочит "светлую идею" ФЯ?
Здравствуйте, VladD2, Вы писали:
_>>Вообщем pattern matching -та черта ФЯ полезность которой не вызывает сомнений VD>+1
Опять же, является ли это чертой именно ФЯ...
_>>2.Для реализации алгоритмов легко распадающиеся не составные части VD>Для этого нужна поддержка компилятра вот и все. Тот же С++ прекрасно распараллеливается спец. средствами (например, от Интел).
Поддержка компилятора и распараллеливания разруливание ручками под каждую кончигурацию машины?
Или ты хочешь сказать, что на C или C++ можно написать код, который компилятор сам эффективно распараллелит?
_>>3.Где активно применяется рекурсия например LL — разбор VD>Но опчему-то для постраения парсеров в ФЯ все равно создают постоители парсеров (вроде Яка/Лекса).
Обычно на функциональных языках. Хотя бывают варианты. В Ocaml есть и чисто камшловый парсер, и парсер со вставками на C.
VD>Так что приемущества именно в декларативности и фичах вроде патерн-матчинга и функциях высшего порядка. VD>Многое же выдаваемое за достоинство ФЯ на самом деле является всего лишь фичами конкретных языков и без проблем может быть реализовано (да и реализуется) на ИЯ.
Я бы сказал, функции высшего порядка и высокий уровень абстракции. Функциональные языки оперируют наиболее простыми единицами языка — значениями, множествами(т.е. типами) и отображениями (функциями). Все что нужно, ничего лишнего. На этом уровне инкапсуляция иполиморфизм получается гораздо лучше чем в ООП — программа состоит как правило из меньших и менее связанных элементов, чем программа в объектном стиле.
N_>primes определен как я писал выше.
1)Всеравно кода получилось больше.
2)Давай сравним производительность на болие серьезном объеме. Думаю миллиарда будет достаточно
unsigned x=1;
timer_t timer;
unsigned size=1000000000;
std::vector<bool> is_prime(size, true);//помечаем все числа как простыеfor(unsigned i=2;i<size;++i)//ищем очередное не вычеркнутое числоif(is_prime[i])
{
//i очередное простое числоif(i>x)//иначе вывод становится ОЧЕНЬ узким местом
{
std::cout<<i<<" "<<timer.time()<<"\n";
x<<=1;
}
for(unsigned n=i+i;n<size;n+=i)//вычеркиваем все числа кратные данному числу
is_prime[n]=false;
}
std::cout<<timer.time()<<"\n";
В прочем можешь не напрягаться я и так знаю что твоя программа на ТАКИХ объемах просто сдохнет. Ибо ты использовал ТУПОЙ алгоритм.
Разберись с моей программой и попробуй реализовать МОЙ алгоритм на ФЯ.
ЗЫ Gaperton в соседнем флейме расписался
в том что не может сделать алгоритм на ФЯ быстрее.
ЗЗЫ Все дело в том что сложность твоего алгоритма O(N*sqrt(N)). Сложность моего алгоритма мне лень считать но она около O(N*log(N)) к тому же у меня константа меньше.
... << RSDN@Home 1.1.4 rev. 185 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
также в том, что заметил лучшую асимптотику твоего алгоритма но не хочет заниматься алгоритмической оптимизацией. Лень ему, понимаешь, и смысла в этом он не видит. Что ты сравнить хочешь, эффективность компиляторов, или что?
G>Кстати, слепенький я наверно. Ну не вижу я цикла for в твоем коде. А вот list comprehensions вижу, как и отсутствие побочных эффектов.
перевожу для слабовидящих:
ltList=[y for y in aList[1:] if y<aList[0]]
равносильно
ltList = []
for y in aList[1:] :
if y<aList[0]: ltList.append(y)
просто ты не хочешь признать что императивный язык тоже может быть декларативным.
FR>>>> А списки по моему безразличны к ФЯ и ИЯ (и к ЛЯ в прологе списки не хуже лисповских), и там и там их можно красиво реализовать, G>>>Конечно можно. Кто-то здесь утверждал обратное? FR>>Подразумевал, когда приводил алгоритм сортировки на языке со встроенными списками. G>Откуда ты знаешь, что именно он подразумевал? Ментальное сканирование?
ну там прямо дальше говорилось Императивные аналоги, я думаю, Вы себе представляете
я представил и оказалсь разницы нет.
G>Что характерно, если ты добавишь в любой язык встроенные списки так, как это сделано в современных ФЯ, то на нем сразу станет удобно писать в функциональном стиле. Одного не понимаю, каким именно образом это порочит "светлую идею" ФЯ?
я не собираюсь ничего порочить, просто пытаюсь понять смогу ли я использовать ФЯ в своей практической работе, пока преимуществ не вижу, буду изучать как хобби
По тестам которые ты выше привел, на другой странице я нашел тест с psyco(jit компилятор питона) у них результаты практически одинаковы с интерпретатором, у меня при включении psyco тест срабатывает в 25 раз быстрее чем интерпретируемый, если они и с остальными языками также намеряли, то доверия к ним нет никакого.
Здравствуйте, Gaperton, Вы писали:
G>На, посмотри, как мы забиваем на эффективность. И найди здесь свой питон (подсказка: ищи в конце), который проиграл вдвое даже динамически типизированному Erlang-у. А если обратить внимание, что в данный момент реализация на haskell занимает в рейтинге первое место, обогнав gcc, то просто обхохочешься.
До 8192 это даже не смешно. Вот если они сделают тесты до 10'000'000 вот тогда будет понятно кто тут рулит. К стати почему там нет VC++?
int main()
{
int NUM = 10;
const unsigned size=8192;
static char flags[size + 1];
int count = 0;
while (NUM--)
{
count = 0;
for (unsigned i=2; i <= size; i++)
flags[i] = 1;
for (unsigned i=2; i <= size; i++)
if (flags[i])
{
// remove all multiples of prime: ifor (unsigned k=i+i; k <= size; k+=i)
flags[k] = 0;
count++;
}
}
printf("Count: %d\n", count);
}
_main PROC NEAR ; COMDAT
; 4 : {
push ebx
push esi
push edi
; 5 : int NUM = 10;
mov ebx, 10 ; 0000000aH
xor edx, edx
npad 6
$L64207:
; 11 : {
; 12 : count = 0;
; 13 : for (unsigned i=2; i <= size; i++)
; 14 : flags[i] = 1;
mov ecx, 2047 ; 000007ffH
mov eax, 16843009 ; 01010101H
mov edi, OFFSET FLAT:?flags@?1??main@@9@4PADA+2
rep stosd
stosw
xor esi, esi
stosb
; 15 : for (unsigned i=2; i <= size; i++)
mov ecx, 2
npad 5
$L64214:
; 16 : if (flags[i])
cmp BYTE PTR ?flags@?1??main@@9@4PADA[ecx], dl
je SHORT $L64215
; 17 : {
; 18 : // remove all multiples of prime: i
; 19 : for (unsigned k=i+i; k <= size; k+=i)
cmp ecx, 4096 ; 00001000H
lea eax, DWORD PTR [ecx+ecx]
ja SHORT $L64221
$L64219:
; 20 : flags[k] = 0;
mov BYTE PTR ?flags@?1??main@@9@4PADA[eax], dl
add eax, ecx
cmp eax, 8192 ; 00002000H
jbe SHORT $L64219
$L64221:
; 21 : count++;
inc esi
$L64215:
; 15 : for (unsigned i=2; i <= size; i++)
inc ecx
cmp ecx, 8192 ; 00002000H
jbe SHORT $L64214
; 6 : const unsigned size=8192;
; 7 : static char flags[size + 1];
; 8 : int count = 0;
; 9 :
; 10 : while (NUM--)
dec ebx
jne SHORT $L64207
; 22 : }
; 23 : }
; 24 : printf("Count: %d\n", count);
push esi
push OFFSET FLAT:??_C@_0L@NKLBHBJO@Count?3?5?$CFd?6?$AA@
call _printf
add esp, 8
pop edi
pop esi
; 25 : }
xor eax, eax
pop ebx
ret 0
_main ENDP
Ктонить покажите что gcc генерит.
... << RSDN@Home 1.1.4 rev. 185 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, FR, Вы писали: G>>Кстати, слепенький я наверно. Ну не вижу я цикла for в твоем коде. А вот list comprehensions вижу, как и отсутствие побочных эффектов.
FR>перевожу для слабовидящих: FR>
FR>ltList=[y for y in aList[1:] if y<aList[0]]
FR>
FR>равносильно FR>
FR>ltList = []
FR>for y in aList[1:] :
FR> if y<aList[0]: ltList.append(y)
FR>
Да ну? А я думал, это равносильно маленькой рекурсивной функции, или коду с оператором goto, или вставке на языке Клиппер (для скорости).
А на самом деле это один из вариантов ZF-нотации, что и есть list comprehensions. В питоне заимствовано из функциональных языков.
ltList = [ y | y <- tail( aList ), y < head( aList ) ]
FR>просто ты не хочешь признать что императивный язык тоже может быть декларативным.
Просто ты за меня выдумываешь, что я имею в виду. Прочитай comp.lang.functional FAQ, чтобы понять, что такое функциональный стиль и при каких условиях язык можно отнести к функциональному. Питон, например, вполне можно — было-бы желание.
FR>я не собираюсь ничего порочить, просто пытаюсь понять смогу ли я использовать ФЯ в своей практической работе, пока преимуществ не вижу, буду изучать как хобби
Успехов.
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, Gaperton, Вы писали:
G>>На, посмотри, как мы забиваем на эффективность. И найди здесь свой питон (подсказка: ищи в конце), который проиграл вдвое даже динамически типизированному Erlang-у. А если обратить внимание, что в данный момент реализация на haskell занимает в рейтинге первое место, обогнав gcc, то просто обхохочешься. WH>До 8192 это даже не смешно.
Согласен.
WH>Вот если они сделают тесты до 10'000'000 вот тогда будет понятно кто тут рулит. К стати почему там нет VC++?
Потому что тесты пускаются под линухом. А сети есть вариант этих тестов под Win32, может там есть.
Здравствуйте, FR, Вы писали:
FR>Здравствуйте, Gaperton, Вы писали:
FR>По тестам которые ты выше привел, на другой странице я нашел тест с psyco(jit компилятор питона) у них результаты практически одинаковы с интерпретатором, у меня при включении psyco тест срабатывает в 25 раз быстрее чем интерпретируемый, если они и с остальными языками также намеряли, то доверия к ним нет никакого.
Возможно, у них старая версия этого psyco. Возможно, это просто ошибка. Возможно, ты смотришь страницу где включено время старта проги. Если ты им напишешь, они поправят.
Q>>Вызов по имени в целом более выгоден, _>Спорно сам пишешь ниже.Выгодно когда то что нужно вычислить достатчно мало (занимает мало памяти для описания) _>а вычисления достаточно долгие например 1000000000000! и не выгодно когда вычисленный результат во много раз меньше чем исходный.Например размер дерева или списка — проще сразу получить размер и удалить саму структуру(если она не используется далее) чем хранить ее до последнего
Да, это верно. Вернее было бы сказать теоретически более выгоден. На практике, я думаю, выгоден симбиоз ленивых и строгих вычислений.
_>И Haskell и Ocaml поддерживают оба способа.Просто по умолчанию поведение Haskell нестрогое а OCaml строгое.
Так можно сказать, что и С поддерживает ленивые вычисления и это будет правдой. Просто уровень поддержки существенно разный. Haskell изначально поддерживает один тип вызова функций, а OCaml другой. Это существенная разница, поскольку это влияет на то, как будет написан компилятор.
Q>> Основным типом ФЯ можно назвать список _>Основным типом ФЯ Haskell является алгебраический тип данных.Близкий аналог в ИЯ это enum(C).
Это верно, конечно, что список и кортеж частные случаи более общего типа данных. Но они играют довольно важную роль в функциональных программах, поэтому, я думаю, стоит особо отметить их роль.
Enums лишь слегка похожи на алгебраический тип данных, как ты выражаешься, поскольку они нерекурсивны и не могут содержать другие типы данных.
Q>>Карринг _>Предположим есть функция — сложение. _>Можно рассматривать ее как функцию от 2 аргументов int и возвращающюю int _>А можно как функцию 1-ого числа x возвращающюю другую функцию 1-ого аргумента f ,такую что f y =x+y — это карринг или частичное применение функции
Про карринг можно и нужно написать больше, поскольку это очень важная на мой взгляд концепция.
G>А на самом деле это один из вариантов ZF-нотации, что и есть list comprehensions. В питоне заимствовано из функциональных языков. G>ltList = [ y | y <- tail( aList ), y < head( aList ) ]
а я говорю они это из пролога уперли
FR>>просто ты не хочешь признать что императивный язык тоже может быть декларативным. G>Просто ты за меня выдумываешь, что я имею в виду. Прочитай comp.lang.functional FAQ, чтобы понять, что такое функциональный стиль и при каких условиях язык можно отнести к функциональному. Питон, например, вполне можно — было-бы желание.
На питоне можно писать и в чисто функциональном стиле, я не спорю, просто тот же list comprehensions в питоне на обычный язык все таки переводится как императивный алгоритм, но кроме него в новых версия много вещей (те же итераторы и генераторы) которые императивно делают то что раньше было проще делать функционально.