Comments 47
Большое спасибо за перевод. Самое дельное введение в монады из всех что приходилось читать.
По-моему лучше найти девушку, и с ней заниматься сексом, чем с функциональными языками=)
Хотя как говорится на вкус и цвет, друзей нет=)
Хотя как говорится на вкус и цвет, друзей нет=)
Что вы. Лучше найти девушку и заниматься сексом и с ней и с функциональными языками, чем с одними только оъектно-ориентированными. ;)
Интересно, почему оппоненты ФП всегда соскакивают на вопрос девушек. Больная тема? ;)
А почему, если кто-то упоминает девушек в споре, то сразу возникает ответные меры. А именно шаблонная фраза, переводящая стрелки?)
А если серьезно, то я не вижу особых причин программировать на ФП, кроме как понасиловать себе мозг. Это же ведь трудно, медленно и не оптимально…
А если серьезно, то я не вижу особых причин программировать на ФП, кроме как понасиловать себе мозг. Это же ведь трудно, медленно и не оптимально…
Но видите причины всем об этом рассказать? Занятно.
ООП (в неполноценной реализации Java, C# и т.д.) — тоже неоптимально. Если использование нескольких языков неприемлемо, то Оптимальный Подход — мультипарадигменный язык, например, Common Lisp.
И в стотысячный раз повторю, что нужно смотреть по задаче. Где-то ООП будет трудным, медленным и неоптимальным по сравнению с ФП.
И в стотысячный раз повторю, что нужно смотреть по задаче. Где-то ООП будет трудным, медленным и неоптимальным по сравнению с ФП.
Забавный вы человек.
Для разных задач разные языки! Но Оптимальный является Common Lisp=-) (ну если один выбирать)
Противоречите сами же себе. Тем более оптимальность рассматривать нужно отностиельно какого то параметра. Иначе это диарея из слов и не более…
С мнение, что для разных задач нужны разные языки, я согласен.
Давайте рассмотрим типовые задачи.
1) Нужно чтобы работало очень быстро АСМ или Си…
2) Задачи требующие параллельности вон Fortan или Си + DVM или MPI
3) Огромные етерпрайз приложения. C#, Java и тп
4) Если приложение чуть более чем полностью состоит из всяких там словарей списков, где типы меняются как перчатки, то можно взять Python, Ryby и тп =)
5) Web программирование Perl, PHP, Python, Ruby, Asp.net, js да куча всего=)
Ну конечно остатеся внутренный язык в приложении. Но чет в последнее время отдают не Лиспу предпочтение, а Js=)
Так что я особо не вижу где бы его применить этот великий и ужасный Common Lisp. (Т.е. не знаю где бы он был оптимален)
Для разных задач разные языки! Но Оптимальный является Common Lisp=-) (ну если один выбирать)
Противоречите сами же себе. Тем более оптимальность рассматривать нужно отностиельно какого то параметра. Иначе это диарея из слов и не более…
С мнение, что для разных задач нужны разные языки, я согласен.
Давайте рассмотрим типовые задачи.
1) Нужно чтобы работало очень быстро АСМ или Си…
2) Задачи требующие параллельности вон Fortan или Си + DVM или MPI
3) Огромные етерпрайз приложения. C#, Java и тп
4) Если приложение чуть более чем полностью состоит из всяких там словарей списков, где типы меняются как перчатки, то можно взять Python, Ryby и тп =)
5) Web программирование Perl, PHP, Python, Ruby, Asp.net, js да куча всего=)
Ну конечно остатеся внутренный язык в приложении. Но чет в последнее время отдают не Лиспу предпочтение, а Js=)
Так что я особо не вижу где бы его применить этот великий и ужасный Common Lisp. (Т.е. не знаю где бы он был оптимален)
К комментарию добавлю, что безотносительно направлений разработки, существуют такие вещи как генетические алгоритмы, лексический анализ текста, распознавание изображений/голоса, автоматическое доказательство теорем, символьные вычисления(?).
В этих направлениях очень сильно выигрывают функциональные языки, и лисп в частности (в холивар про то какой язык уместнее вдаваться не хочу). В любом случае «there is no silver bullet».
В этих направлениях очень сильно выигрывают функциональные языки, и лисп в частности (в холивар про то какой язык уместнее вдаваться не хочу). В любом случае «there is no silver bullet».
Блин скока умных слов.
Генетической программирование… Умный вид тупо перебора. Да я как раз это писал на Scheme… И вот мне сам лисп по себе только мешал это делать. Вместо 1 дня на Pyton я потратил полторы недели на Схеме…
Лексический анализ — А не легче ли взять, что нить аля ANTLR + Java
Распознование изображении — Делал на Qt, имхо не понимаю, чем бы мне помог Лисп…
Автоматической доказательство теорем — Да согласен, тут удобен лисп, тока в это направление не особо развивается, там какие то проблемы=)
Символьные вычисления — ничего не могу сказать, никогда этим не занимался=)
В общем, давайте все же не путать две вещи:
1) для чего создавался лисп
2) для чего его удобно использовать…
Генетической программирование… Умный вид тупо перебора. Да я как раз это писал на Scheme… И вот мне сам лисп по себе только мешал это делать. Вместо 1 дня на Pyton я потратил полторы недели на Схеме…
Лексический анализ — А не легче ли взять, что нить аля ANTLR + Java
Распознование изображении — Делал на Qt, имхо не понимаю, чем бы мне помог Лисп…
Автоматической доказательство теорем — Да согласен, тут удобен лисп, тока в это направление не особо развивается, там какие то проблемы=)
Символьные вычисления — ничего не могу сказать, никогда этим не занимался=)
В общем, давайте все же не путать две вещи:
1) для чего создавался лисп
2) для чего его удобно использовать…
я не лиспер, поэтому его защищать не буду :)
идея моего комментария была в том, что все эти пункты можно написать как на императивных языках программирования, так и на функциональных, но на функциональных это пишется проще и быстрее и эффективнее. Естественно при наличии опыта разработки. И это было скорее дополнения к комментарию о месте языков на различных сегментах, а не попытка опровержения.
P.S. не мои слова и вряд ли я буду искать ссылки и подтверждения. Но есть информация, что данные языки вполне себе используются на благо военки. А сегмент это достаточно широкий. (опять же это дополнение, а не опровержение чего бы то ни было).
идея моего комментария была в том, что все эти пункты можно написать как на императивных языках программирования, так и на функциональных, но на функциональных это пишется проще и быстрее и эффективнее. Естественно при наличии опыта разработки. И это было скорее дополнения к комментарию о месте языков на различных сегментах, а не попытка опровержения.
P.S. не мои слова и вряд ли я буду искать ссылки и подтверждения. Но есть информация, что данные языки вполне себе используются на благо военки. А сегмент это достаточно широкий. (опять же это дополнение, а не опровержение чего бы то ни было).
Вы (оба) можете собственно ничего даже не писать, а просто кидаться ссылками на соответствующие места старых топиков. Тут такие холивары на эти темы были. Даже драмы, когда люди уходили громко хлопнув дверью. Один до сих пор сидит обиженный у себя в уютной жжшке.
Это как анекдот про англичан, которые шутили номерами анекдотов :-D
Это как анекдот про англичан, которые шутили номерами анекдотов :-D
Я тут уже участвовал по поводу лиспа в холиварах=)
Вон карма ишь какая стала-=) Школота постаралась=)
Вон карма ишь какая стала-=) Школота постаралась=)
Мне почему-то кажется, что карму вам слили не за «противодействие» лиспу, а за методы ведения дискуссий о нем (и, возможно, не только о нем).
Дискуссия была только о нем и аргументированная, я даже кидался своим кодом (на лиспе), чего не делали оппоненты…
habrahabr.ru/blogs/lisp/89097/
Но лиспоиди они фанатики. Им никакие доводы не важны=)
habrahabr.ru/blogs/lisp/89097/
Но лиспоиди они фанатики. Им никакие доводы не важны=)
А зачем же вы писали на лиспе, да еще так плохо, при этом мучая себя?
Возможно для того, чтобы потом вступать в дискуссии с криками: «Лисп говно! Точно вам говорю, я на нем программы программировал!».
Так, чтоли? (-:
Возможно для того, чтобы потом вступать в дискуссии с криками: «Лисп говно! Точно вам говорю, я на нем программы программировал!».
Так, чтоли? (-:
ойвэй… habrahabr.ru/blogs/lisp/89097/#comment_2675958 не стоит вам про лисп рассуждать, не стоит.
та ветка целиком — шедевр.
Интересно почему не стотит?
На нем неудобно программировать и это факт.
А что вам не нравится?
XML (англ. eXtensible Markup Language — расширяемый язык разметки;
ru.wikipedia.org/wiki/Xml
XML != язык программирования
XML как и HTML используется, для структурированного хранения данных.
Это я и сказал.
На нем неудобно программировать и это факт.
А что вам не нравится?
XML (англ. eXtensible Markup Language — расширяемый язык разметки;
ru.wikipedia.org/wiki/Xml
XML != язык программирования
XML как и HTML используется, для структурированного хранения данных.
Это я и сказал.
За такой код вешать надо, а не минусовать…
car и cdr используются только в однострочных фукнкциях для реализации аксесоров к структурам данных. Вы СИКП чтоли не читали?
> Вместо 1 дня на Pyton я потратил полторы недели на Схеме…
Схема в принципе где-то мешает, где-то помогает. Мешает ИМХО немного больше.
НО! Вы ведь не пытаетесь сказать, что Схема на порядок менее эффективна, чем Python? Я имею опыт и в том и в другом и авторитетно заявляю, что эффективность разработки на них (если не считать библиотеки) отличается на проценты, а не порядки.
Схема в принципе где-то мешает, где-то помогает. Мешает ИМХО немного больше.
НО! Вы ведь не пытаетесь сказать, что Схема на порядок менее эффективна, чем Python? Я имею опыт и в том и в другом и авторитетно заявляю, что эффективность разработки на них (если не считать библиотеки) отличается на проценты, а не порядки.
6) кишки телекома (не биллинг. звучит почти как HOT GAY) — эрланг ;)
Пожалуй единственный ФП-язык добившийся широкого практического применения. В заметном сегменте, во всяком случае.
Пожалуй единственный ФП-язык добившийся широкого практического применения. В заметном сегменте, во всяком случае.
Для 2, 3 и 5 erlang отлично подходит в некоторых случаях. Нужно смотреть конкретные условия задачи.
Common Lisp является оптимальным в тех случаях, когда о решении задачи ничего не известно и никто её раньше не решал, или просто вы затрудняетесь определиться с парадигмой. Лучше взять язык, где всё реализовано на уровне. И ООП, и ФП, и метапрограммирование, и всё это не отказываясь от процедурного.
"…Please don't assume Lisp is only useful for Animation and Graphics, AI, Bioinformatics, B2B and E-Commerce, Data Mining, EDA/Semiconductor applications, Expert Systems, Finance, Intelligent Agents, Knowledge Management, Mechanical CAD, Modeling and Simulation, Natural Language, Optimization, Research, Risk Analysis, Scheduling, Telecom, and Web Authoring just because these are the only things they happened to list."
--Kent Pitman
Common Lisp является оптимальным в тех случаях, когда о решении задачи ничего не известно и никто её раньше не решал, или просто вы затрудняетесь определиться с парадигмой. Лучше взять язык, где всё реализовано на уровне. И ООП, и ФП, и метапрограммирование, и всё это не отказываясь от процедурного.
"…Please don't assume Lisp is only useful for Animation and Graphics, AI, Bioinformatics, B2B and E-Commerce, Data Mining, EDA/Semiconductor applications, Expert Systems, Finance, Intelligent Agents, Knowledge Management, Mechanical CAD, Modeling and Simulation, Natural Language, Optimization, Research, Risk Analysis, Scheduling, Telecom, and Web Authoring just because these are the only things they happened to list."
--Kent Pitman
Дадада это все так удобно, настолько удобно, что этим никто не пользуется.
Имхо было бы все просто и удобно, народ бы пользовался… (Бизнес выбрал свой оптимальный, по деньгам, времени разработки и поддержке, путь)
«Common Lisp является оптимальным в тех случаях, когда о решении задачи ничего не известно и никто её раньше не решал, или просто вы затрудняетесь определиться с парадигмой.»
Что за детский лепет. По какому параметру оптимальный?
«Лучше взять язык, где всё реализовано на уровне.»
Эм… C#, Java — все реализовано…
(ну создайте один класс, и в нем пишите себе процедуры, вот вам процедурное программирование)
В C# допустим нет необходимости в ФП, т.к. там круче штучка есть LINQ, которая более удачно заменяет эту парадигму=)
Имхо было бы все просто и удобно, народ бы пользовался… (Бизнес выбрал свой оптимальный, по деньгам, времени разработки и поддержке, путь)
«Common Lisp является оптимальным в тех случаях, когда о решении задачи ничего не известно и никто её раньше не решал, или просто вы затрудняетесь определиться с парадигмой.»
Что за детский лепет. По какому параметру оптимальный?
«Лучше взять язык, где всё реализовано на уровне.»
Эм… C#, Java — все реализовано…
(ну создайте один класс, и в нем пишите себе процедуры, вот вам процедурное программирование)
В C# допустим нет необходимости в ФП, т.к. там круче штучка есть LINQ, которая более удачно заменяет эту парадигму=)
> Дадада это все так удобно, настолько удобно, что этим никто не пользуется.
Пользуются.
> Имхо было бы все просто и удобно, народ бы пользовался… (Бизнес выбрал свой оптимальный, по деньгам, времени разработки и поддержке, путь)
Пользуются. Бизнес выбрал. Вы в каком-то неправильном бизнесе работаете.
>> Common Lisp является оптимальным в тех случаях, когда о решении задачи ничего не известно и никто её раньше не решал, или просто вы затрудняетесь определиться с парадигмой.
> Что за детский лепет. По какому параметру оптимальный?
По человеческим ресурсам, потраченным на поиск, реализацию, отладку и, возможно, сопровождение решения.
>> Лучше взять язык, где всё реализовано на уровне.
> Эм… C#, Java — все реализовано…
> (ну создайте один класс, и в нем пишите себе процедуры, вот вам процедурное программирование)
Лексические замыкания со сборщиком мусора можно и на ассемблере написать, но зачем? Отдельно хотелось бы поинтересоваться насколько «всё реализовано» в области метапрограммирования в C# и Java.
Пользуются.
> Имхо было бы все просто и удобно, народ бы пользовался… (Бизнес выбрал свой оптимальный, по деньгам, времени разработки и поддержке, путь)
Пользуются. Бизнес выбрал. Вы в каком-то неправильном бизнесе работаете.
>> Common Lisp является оптимальным в тех случаях, когда о решении задачи ничего не известно и никто её раньше не решал, или просто вы затрудняетесь определиться с парадигмой.
> Что за детский лепет. По какому параметру оптимальный?
По человеческим ресурсам, потраченным на поиск, реализацию, отладку и, возможно, сопровождение решения.
>> Лучше взять язык, где всё реализовано на уровне.
> Эм… C#, Java — все реализовано…
> (ну создайте один класс, и в нем пишите себе процедуры, вот вам процедурное программирование)
Лексические замыкания со сборщиком мусора можно и на ассемблере написать, но зачем? Отдельно хотелось бы поинтересоваться насколько «всё реализовано» в области метапрограммирования в C# и Java.
Вы не привели ни одного аргумента…
Статистика это печально:
давайте вводить по очереди в гугль %Language% вакансия.
Lisp Результатов: примерно 6 220
haskell Результатов: примерно 3 540
erlang Результатов: примерно 2 350
asm Результатов: примерно 28 200
c++ Результатов: примерно 414 000
c# Результатов: примерно 315 000
java Результатов: примерно 1 020 000
python Результатов: примерно 120 000
ruby Результатов: примерно 90 900
js Результатов: примерно 136 000
Мы походу живем в разных мирах…
Статистика это печально:
давайте вводить по очереди в гугль %Language% вакансия.
Lisp Результатов: примерно 6 220
haskell Результатов: примерно 3 540
erlang Результатов: примерно 2 350
asm Результатов: примерно 28 200
c++ Результатов: примерно 414 000
c# Результатов: примерно 315 000
java Результатов: примерно 1 020 000
python Результатов: примерно 120 000
ruby Результатов: примерно 90 900
js Результатов: примерно 136 000
Мы походу живем в разных мирах…
> Дадада это все так удобно, настолько удобно, что этим никто не пользуется.
Это своё утверждение вы только что сами опровергнули. Другое дело, что эти решения непопулярны, но тут другие причины. Не в ущербности языков, а в их мифической «непривычности».
Это своё утверждение вы только что сами опровергнули. Другое дело, что эти решения непопулярны, но тут другие причины. Не в ущербности языков, а в их мифической «непривычности».
Так работает образовательная машина.
так работает рынок. Ему требуют, знаете ли, промышленные языки.
И что с того, что в MIT бог знает сколько лет преподавали на младших курсах Scheme? С недавних пор там Питон в этой роли выступает.
И что с того, что в MIT бог знает сколько лет преподавали на младших курсах Scheme? С недавних пор там Питон в этой роли выступает.
MIT в данном случае не показатель, как раз. Далеко, очень далеко не всякий программист — выпускник MIT-а.
да хрен с ним, с MIT. В моем питерском политехе обязательный курс функциональный языков. Полагаю, это общая для всех тема.
Просто действительно трудно найти работу по фунциональной теме, тем более выпускнику.
насколько вижу ситуацию, специалистами по теме становятся много позже, уже с большим опытом императивного программирования и с самостоятельным изучением Scala, Haskell, F# и так далее.
Просто действительно трудно найти работу по фунциональной теме, тем более выпускнику.
насколько вижу ситуацию, специалистами по теме становятся много позже, уже с большим опытом императивного программирования и с самостоятельным изучением Scala, Haskell, F# и так далее.
> В C# допустим нет необходимости в ФП, т.к. там круче штучка есть LINQ, которая более удачно заменяет эту парадигму=)
en.wikipedia.org/wiki/LINQ
Куда смотреть: Map, Filter, Bind, Fold.
Потом осознать, что это всё, во-первых, ФП, а во-вторых, лишь малая его часть.
en.wikipedia.org/wiki/LINQ
Куда смотреть: Map, Filter, Bind, Fold.
Потом осознать, что это всё, во-первых, ФП, а во-вторых, лишь малая его часть.
Просто интересно почему Java и C# «неполноценные» ООП языки??
И как бы вы продолжили это и т.д. C++, Smalltalk??
И что же тогда полноценный ООП язык?
И как бы вы продолжили это и т.д. C++, Smalltalk??
И что же тогда полноценный ООП язык?
По задумке автора, каждый объект должен быть реализован отдельным потоком или даже железкой и взаимодействовать объекты должны *только* отправкой друг другу сообщений. Рекомендую познакомиться с erlang'ом. Из современных языков он наиболее точно реализует идею Алана Кея.
С довольно постоноянной переодичностью проскакивают такие вот вакансии в банках на Haskell программистов: alexott-ru.blogspot.com/2010/06/blog-post_15.html
Ага, erlang-mnesia-video.ru/, См. где «Erlang-программисты — заботливые отцы, а значит их любят девушки!» :)
Приятная статья, по-человечески написана.
Плохо, что кое-где оставлен английский текст или переделан выход промпта. Вроде перевод достаточно качественный в основном, может стоит ещё немного потратить времени и довести до конца?
Плохо, что кое-где оставлен английский текст или переделан выход промпта. Вроде перевод достаточно качественный в основном, может стоит ещё немного потратить времени и довести до конца?
статью в оригинале не читал, только этот перевод, за него и спасибо.
в меру возможностей пытался исправить очепятки:
по сути являются одним решением и тем же решением.
->
по сути являются одним и тем же решением.
Мы можем записать простую композицию начальный функций
->
Мы можем записать простую композицию начальных функций
2ая диаграмма немного разъехалась
ввести функцию, назовём её bind. Со следующими типами
->
ввести функцию, назовём её bind, со следующими типами
композицию отладочных функций,f' и g'.
->
композицию отладочных функций, f' и g'.
Даже если несмотря на то, что вывод g' несовместим с входом f' у нас появился
->
Даже несмотря на то, что вывод g' несовместим с входом f', у нас появился
так же sqrt должна выбрасывает исключение для
->
так же sqrt должна выбрасывать исключение для
числа, кроме нуля, должно имеется 2 квадратных корня.
->
числа, кроме нуля, должно иметься 2 квадратных корня.
и объединить все результаты один длинный список.
->
и объединить все результаты в один длинный список.
возвращать список состоящий из одного элемента
->
возвращать список, состоящий из одного элемента
Случайные в Haskell выглядят
->
Случайные числа(?) в Haskell выглядят
Замечу, что это проблема похожа на
->
Замечу, что эта проблема похожа на
Итак функция, которая является
->
Итак, функция, которая является
как сделать композицию 2ух
->
как сделать композицию 2-х
возвращаемое в f вторым элементом пары
->
возвращаемое f вторым элементом пары
что и предполагается оно переводит
->
что и предполагается — оно переводит
Покажите, что f * unit = unit * f = f and lift f * lift g = lift (f.g)
->
Покажите, что f ° unit = unit ° f = f и lift f ° lift g = lift (f.g)
где (°) и lift, где определены в терминах unit и bind.
->
где (°) и lift, определены в терминах unit и bind.
Итак я должен связать это с определением монад Haskell.
->
Итак, я должен связать это с определением монад Haskell.
И первую вещь, которую я отразил это определение bind и обозначил словом 'bind', который записывается как как оператор >>=.
->
Первую вещь, которую я отразили и обозначил словом 'bind' — это определение функции bind, которая записывается как как оператор >>=.
И я связка f x переписывается как x >>=f.
->
Тогда связка f x переписывается как x >>= f.
Во-вторых unit называется return.
->
Во-вторых, unit называется return.
целый абзац:
Итак, я должен связать это с определением монад Haskell. Первую вещь, которую я отразили и обозначил словом 'bind' — это определение функции bind, которая записывается как как оператор >>=. Тогда связка f x переписывается как x >>= f. Во-вторых, unit называется return. В третьих, для переопределения функций >>= и return мы должны использовать type classes. В Haskell'е Debuggable — это монада Writer, Multivalued — монада List, Randomized — монада State.
Если проверите определения следующих вещей:
больше не осилил
в меру возможностей пытался исправить очепятки:
по сути являются одним решением и тем же решением.
->
по сути являются одним и тем же решением.
Мы можем записать простую композицию начальный функций
->
Мы можем записать простую композицию начальных функций
2ая диаграмма немного разъехалась
ввести функцию, назовём её bind. Со следующими типами
->
ввести функцию, назовём её bind, со следующими типами
композицию отладочных функций,f' и g'.
->
композицию отладочных функций, f' и g'.
Даже если несмотря на то, что вывод g' несовместим с входом f' у нас появился
->
Даже несмотря на то, что вывод g' несовместим с входом f', у нас появился
так же sqrt должна выбрасывает исключение для
->
так же sqrt должна выбрасывать исключение для
числа, кроме нуля, должно имеется 2 квадратных корня.
->
числа, кроме нуля, должно иметься 2 квадратных корня.
и объединить все результаты один длинный список.
->
и объединить все результаты в один длинный список.
возвращать список состоящий из одного элемента
->
возвращать список, состоящий из одного элемента
Случайные в Haskell выглядят
->
Случайные числа(?) в Haskell выглядят
Замечу, что это проблема похожа на
->
Замечу, что эта проблема похожа на
Итак функция, которая является
->
Итак, функция, которая является
как сделать композицию 2ух
->
как сделать композицию 2-х
возвращаемое в f вторым элементом пары
->
возвращаемое f вторым элементом пары
что и предполагается оно переводит
->
что и предполагается — оно переводит
Покажите, что f * unit = unit * f = f and lift f * lift g = lift (f.g)
->
Покажите, что f ° unit = unit ° f = f и lift f ° lift g = lift (f.g)
где (°) и lift, где определены в терминах unit и bind.
->
где (°) и lift, определены в терминах unit и bind.
Итак я должен связать это с определением монад Haskell.
->
Итак, я должен связать это с определением монад Haskell.
И первую вещь, которую я отразил это определение bind и обозначил словом 'bind', который записывается как как оператор >>=.
->
Первую вещь, которую я отразили и обозначил словом 'bind' — это определение функции bind, которая записывается как как оператор >>=.
И я связка f x переписывается как x >>=f.
->
Тогда связка f x переписывается как x >>= f.
Во-вторых unit называется return.
->
Во-вторых, unit называется return.
целый абзац:
Итак, я должен связать это с определением монад Haskell. Первую вещь, которую я отразили и обозначил словом 'bind' — это определение функции bind, которая записывается как как оператор >>=. Тогда связка f x переписывается как x >>= f. Во-вторых, unit называется return. В третьих, для переопределения функций >>= и return мы должны использовать type classes. В Haskell'е Debuggable — это монада Writer, Multivalued — монада List, Randomized — монада State.
Если проверите определения следующих вещей:
больше не осилил
Sign up to leave a comment.
Dan Piponi