LINUX.ORG.RU
Ответ на: комментарий от tailgunner

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

geekless ★★
()
Ответ на: комментарий от geekless

Снова неудачный пример.

Да нет, с этим премером все ok.

Вкури вот это в качестве удачного примера

Чем отличается от?

def bar():
    return "hello"

def baz():
    return 1/0

try:
    print bar()
except:
    "error"

try:
    print baz()
except:
    "error"
alienclaster ★★★
()
Ответ на: комментарий от alienclaster

В чем вопрос?

В том, что есть разные модели полиморфизма - параметрический, ad-hoc, подтипирования. Я догадываюсь, что речь про ad-hoc.

Специализация (в обычных языках) метода по одному классу - полиморфизм, который реализуется через перегрузку.

«Обычные языки» это слишком туманно (мало ли, что для кого-то является обычным). Но понятно - С++ и последователи.

Если множественную диспетчеризацию в CLOS можно назвать паттерн матчингом

Нельзя (она, хотя бы, не вложенная, ЕМНИП, archimag жаловался, что не может делать нормальный defmethod по массивам). Это, с натяжкой, ad-hoc полиморфизм, плюс свои какие-то особенности.

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

Вот именно - осторожней нужно. switch компилятор может превратить в нечто if-подобное, а может сразу в условные переходы ассемблера, не нужно прыгать с уровня на уровень (тут у нас мультиметоды, а тут - cond и if, а тут - ассемблер, не надо смешивать).

Тем не менее у компилятора / рантайма мультиметоды устороены, грубо говоря, как хэш-табличка из которой диспетчер выбирает спецификацию метода при вызове. Естественно, на каком-то уровне это данные в памяти и специальная форма вроде if или cond, на каком-то - память и машинный код. Просто не смешиваем уровни.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Или по крайней мере пиши как product [1 .. n]

Я специально так не написал, чтобы продемонстрировать декларативность, даже в отсутствии встроенной product.

Что-нибудь вроде бинарной сериализации. Или интерпретатора / компилятора.

Ты спустился на низкий уровень, заведомо предполагающий сплошной императив в погоне за скоростью.

ML был выбран не случайно, как пишет автор.

Ну он же не мог написать, что выбрал язык «от фонаря», не солидно. На месте ML мог оказаться haskell, ocaml, lisp, scheme. И каждый из них (ну конечно же) был бы выбран не случайно! нет-нет

Но это бессмысленно обсуждать - разработка в типах / функциях ML-ей похожа на разработку в классах / мультиметодах CLOS

Разработка в типах не то что не похожа, а _противоположна_ разработке на динамически-типизированном языке, с классами или без классов вообще

А «декларативность» тут - какое-то слово-паразит

Декларативность - это средство, которое экономит наше время и нервы

вот language agnostic design concepts полезнее.

Можешь в двух словах объяснить, что это?

alienclaster ★★★
()
Ответ на: комментарий от quasimoto

Вообще, мультиметоды не имеют отношения к PM вообще. Мультиметоды они на типах, а PM - на термах. Мультиметоды в CL диспетчеризируются довольно просто (или глупо, это как посмотреть - type expressions-то бедные). А вот NPM - по вложенным образцам.

quasimoto ★★★★
()
Ответ на: комментарий от tailgunner

Вложенность отражается отступами. Начало блока - первая строка блока, конец блока - последняя строка. Что непонятно?

Непонятно, чем вызвано твое (кажется, немного притворное) удивление моим утверждением «отделяет начало блока, его продолжение и окончание» по поводу идентации. Кроме начала и конца блока, у нас есть и его продолжение. Могу лишь повториться, что отступы как идентификатор окончания логического блока - отстой по причинам: 1) неудобно воспринимать глазами даже небольшую функцию с тремя уровнями вложенности, особенно если вложенность уровней идет не в порядке ее возрастания 2) невозможности автоматической идентации с целью восстановить логику программы при частичном случайном смешении блоков.

alienclaster ★★★
()
Ответ на: комментарий от alienclaster

Ты ничего не понял. begin...end — это выражение. Такое же полноценное выражение, как любое 2+2. И как у любого выражения, у него есть значение. if...then...else...end — это тоже выражение. И даже def или class — выражения.

Если всё еще не дошло, объясняю на пальцах. Пример кода на Руби выведет

Hello
error

Твой пример выведет

hello
А зачем ты там строк понавешал в except — загадка...

geekless ★★
()
Ответ на: комментарий от alienclaster

Непонятно, чем вызвано твое (кажется, немного притворное) удивление моим утверждением «отделяет начало блока, его продолжение и окончание» по поводу идентации

Нет ни начала блока, ни продолжения, ни окончания. Есть просто блок.

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

tailgunner ★★★★★
()
Ответ на: комментарий от alienclaster

Я специально так не написал, чтобы продемонстрировать декларативность, даже в отсутствии встроенной product.

0_o Я уже ничего не понимаю :) Продемонстрировать декларативность в хаскеле в котором, как я понял, нужно было продемонстрировать её отсутствие (тупой паттерн-матчинг же мешает).

Что-нибудь вроде бинарной сериализации. Или интерпретатора / компилятора.

Ты спустился на низкий уровень, заведомо предполагающий сплошной императив в погоне за скоростью.

Ладно сериализацию (там просто забавно в binary / derive), но интерпретатор / компилятор это высокий уровень. Компилятор только и делает что детерминировано гоняет разные структуры данных (вплоть до сложных графов, где уж тут низкий уровень) с помощью разных алгоритмов. ADT и PM тут весьма полезны оказываются.

заведомо предполагающий сплошной императив в погоне за скоростью

«императив», «декларативность» - ты вкладываешь какие-то магические смыслы в эти слова, которые я не могу понять.

Почему PM != декларативность, императив != декларативность?

На месте ML мог оказаться haskell, ocaml, lisp, scheme. И каждый из них (ну конечно же) был бы выбран не случайно! нет-нет

ML (в т.ч. ocaml) и haskell это языки одного семейства - с типизированными ФВП, ADT, паттерн матчингом и модулями.

Я правда не думаю, что лиспы подходят для систем вроде конпеляторов (хотя, вспоминаются книжки S.I.C.P. и L.i.S.P.).

Разработка в типах не то что не похожа, а _противоположна_ разработке на динамически-типизированном языке, с классами или без классов вообще

Типы ~ классы CLOS. Классы в CLOS это и есть местные ADT, а мультиметоды - ad-hoc полиморфные функции. Как ты вообще сможешь что-то написать если не выстроишь иерархию классов и схемы действия методов (весьма похоже на иерархии ADT и функций).

Декларативность - это средство, которое экономит наше время и нервы

«экономит наше время и нервы» - можно прилепить к рекламе чего угодно :)

Можешь в двух словах объяснить, что это?

Концепты, паттерны (назовём паттерном коцепт, не имеющий прямого выражения в конструкциях языка, в ассемблере - if и функции это коцепты-паттерны, в си - коцепты-конструкции языка, AMP в Erlang - коцепты-конструкции, в си - коцепты-паттерны).

В тех самых обычных языках, это, например, паттерны GoF. Если говорить о CLOS то это что-то другое (http://norvig.com/design-patterns/), в Erlang есть свои паттерны, в ML family ещё что-то третье.

Не всегда, конечно, language agnostic (вот MVC - универсальный концепт, а какой-нибудь артефакт плюсов - нет).

Знание таких вещей экономит наше время и нервы.

quasimoto ★★★★
()
Ответ на: комментарий от anonymous

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

grouzen ★★
() автор топика
Ответ на: комментарий от quasimoto

Согласен по всем пунктам, я об этом в общем-то и писал.

alienclaster ★★★
()
Ответ на: комментарий от geekless

> Дык любому рубисту фичи очевидны.

Ну я не рубист, мне не очевидно :)

> 3. catch-throw для выхода из глубоко вложенных конструкций. (Не путать с begin-raise-rescue-ensure-end.)

Чем catch-throw принципиально отличается от питоновского raise-try-except?

provaton ★★★★★
()
Ответ на: комментарий от geekless

Ты ничего не понял. begin...end — это выражение. Такое же полноценное выражение, как любое 2+2

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

А зачем ты там строк понавешал в except — загадка...

Должно быть print «error»

alienclaster ★★★
()
Ответ на: комментарий от tailgunner

Нет ни начала блока, ни продолжения, ни окончания. Есть просто блок.

У отрезка нет ни начала, ни продолжения, ни окончания. Есть просто отрезок. Круто, чо.

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

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

alienclaster ★★★
()
Ответ на: комментарий от provaton

Чем catch-throw принципиально отличается от питоновского raise-try-except?

Тем, что это НЕ механизм бросания исключений, а механизм выхода из вложенных конструкций.

geekless ★★
()
Ответ на: комментарий от alienclaster

Нет ни начала блока, ни продолжения, ни окончания. Есть просто блок.

У отрезка нет ни начала, ни продолжения, ни окончания.

Зато в Киеве есть дядька.

Мне нужно непробельное окончание блока

Ты так говоришь, будто у блока есть пробельное окончание.

tailgunner ★★★★★
()
Ответ на: комментарий от geekless

> Тем, что это НЕ механизм бросания исключений, а механизм выхода из вложенных конструкций.

Бросание исключений можно тоже использовать для выхода из вложенных конструкций. типа:

class MySuperException(Exception): pass

try:
   while True:
       do_something()
       if otherthing():
          raise MySuperException()
except MySuperException:
   print 'Iteration stopped'
provaton ★★★★★
()
Ответ на: комментарий от provaton

Опять начинается. Сначала «можно и исключения использовать», затем «можно и именованные функции использовать вместо блоков», по 100500 разу.

Ты спросил, чем язык удобен, я ответил.

geekless ★★
()
Ответ на: комментарий от tailgunner

Зато в Киеве есть дядька.

Это какое-то из правил демагога, напомни? Уцепиться непонятно за что, а в конце спора написать «при чем здесь это». Выглядит эталонно.

Ты так говоришь, будто у блока есть пробельное окончание.

Нет, я сказал кое-что другое.ир

alienclaster ★★★
()
Ответ на: комментарий от geekless

Ну так сказал бы сразу, что это просто другой вариант обработки эксепшнов, более удобный в некоторых ситуациях.

provaton ★★★★★
()
Ответ на: комментарий от grouzen

Я, наоборот, ruby, а потом perl. Иногда грустно, что не выходит писать кратко, как в perl, но это другой язык. Так, мне кажется, сможешь, но не понятно, где особенно выиграешь.

anonymous
()
Ответ на: комментарий от provaton

Это не «просто другой вариант обработки экспепшнов» %) Любые (или почти любые) инструкции возвращают значения. Это удобно, но не сказать что слишком критично, тем более для тех областей, в которых используется питон. Приятная мелочь, не более

alienclaster ★★★
()
Ответ на: комментарий от alienclaster

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

http://shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=python3...

provaton ★★★★★
()

Потому что Гвидо на удивление адекватный BDFL, а Мацумото - сектант, потерявший связь с реальностью.

vasilenko ★★
()
Ответ на: комментарий от grouzen

смогу ли я заменить им перл для системного администрирования.

Легко.

LamerOk ★★★★★
()
Ответ на: комментарий от provaton

просто другой вариант обработки эксепшнов, более удобный в некоторых ситуациях.

Если так обобщать, то и break окажется «вариантом обработки эксепшнов». %-\

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

Исключение возбуждается при ошибке. throw используется to jump out of some deeply nested construct during normal processing.

При возбуждении исключения в обработчик передаётся объект произвольного класса, а поиск обработчика выполняется по сопоставлению с заявленным классом. При броске throw передаётся атом и произвольное возвращаемое значение, а поиск точки «выброса» выполняется по значению этого атома.

Обработка исключения приводит к передаче управления в специальный обработчик — секцию rescue. Обработка throw приводит к возвращению из catch-блока значения, переданного от throw. (Точно так же, как return возвращает значение из функции.)

geekless ★★
()
Ответ на: комментарий от alienclaster

Да все я понял, в исключении пишем print

Взаимоисключающие параграфы.

LamerOk ★★★★★
()
Ответ на: комментарий от tailgunner

Удобнейшая работа с лямбдами в виде блоков

Overrated. Единственное преимущество перед локальной функцией - 1 строка кода, да и то не всегда.

Без блоков были бы невозможны DSL-подобные API как в rspec, rake, puppet. А это собственно единственная изюминка Ruby. Кроме того, лямбды просто удобны. Сколько я видел скриптовых расширений на Lua, JS и Perl - везде анонимные функции используются в полный рост, но их вид ужасен. Только в Руби для них сделали человеческий синтаксис. Что же касается Питона... Ну да, только и остается утешаться локальными функциями, которые вообще не в тему. Их придумали совсем для другой цели, а используют как лямбды от безысходности.

anonymous
()
Ответ на: комментарий от provaton

Я не знаю, как там правильно эти графики и таблицы смотреть, но вот по этой странице — http://shootout.alioth.debian.org/u32/which-programming-languages-are-fastest... — получается, что у них примерно равная производительность? Как так?

geekless ★★
()
Ответ на: комментарий от alienclaster

Это какое-то из правил демагога, напомни?

Нет. Это другой способ сказать «я считаю, что ты выдаешь логически бессвязные сентенции».

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Без блоков были бы невозможны DSL-подобные API как в rspec, rake, puppet

Это ты хорошо сказал - DSL-подобные.

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

Лямбды и есть локальные функции.

tailgunner ★★★★★
()
Ответ на: комментарий от quasimoto

0_o Я уже ничего не понимаю :) Продемонстрировать декларативность в хаскеле в котором, как я понял, нужно было продемонстрировать её отсутствие (тупой паттерн-матчинг же мешает).

Я продемонстрировал два способа решения: паттерн матчинг (частные случаи) vs композиция функций (функциональный стиль). Оценить какое из решений является более декларативным можно самостоятельно.

но интерпретатор / компилятор это высокий уровень.

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

«императив», «декларативность» - ты вкладываешь какие-то магические смыслы в эти слова, которые я не могу понять.

Ничего магического: в первом случае мы говорим, как делать (имератив), во втором - что хотим получить (декларатив).

Почему PM != декларативность, императив != декларативность?

Я не сказал что PM - всегда != декларативность и даже указал случаи, когда наоборот ==.

А почему императив != декларативность - ну, наверное потому что определения у них разные...

Я правда не думаю, что лиспы подходят для систем вроде конпеляторов

А я наоборот - что они подходят _наилучшим_ образом.

Типы ~ классы CLOS

Типы это всегда ~ классы (ну или - классы это такие типы на стероидах), не важно CLOS это или поскакаль.

Классы в CLOS это и есть местные ADT, а мультиметоды - ad-hoc полиморфные функции.

Кто спорит

Как ты вообще сможешь что-то написать если не выстроишь иерархию классов и схемы действия методов (весьма похоже на иерархии ADT и функций).

Наверное никак, а к чему вопрос?

Можешь в двух словах объяснить, что это?

Концепты, паттерны

То есть это какой-то модный базворд для паттернов проектирования без учета языка. Жаль

alienclaster ★★★
()
Ответ на: комментарий от tailgunner

Это какое-то из правил демагога, напомни?

Нет. Это другой способ сказать «я считаю, что ты выдаешь логически бессвязные сентенции».

Я знаю что обозначает фразеологизм «в огороде бузина...». Но в данном случае его употребление - прием демагога: ты начал «дое*%ваться до столба», а позже когда стало ясно что говорить здесь не о чем и ты сказал о том же другими словами - заявил о «дядьке в Киеве». Зачем так делать, не знаю - с одной стороны не в тему, с другой - скучно и не смешно.

alienclaster ★★★
()
Ответ на: комментарий от provaton

Повтыкал внимательно в таблицу. В 3-х тестах Руби примерно в 2 раза быстрее. В 4-х тестах Питон быстрее, но без особого преимущества. В 2-х тестах Питон быстрее примерно в 2 раза. Еще в одном тесте Питон почему-то быстрее в целых 6 раз.

Преимущество на лицо, но не сказал бы, что это тянет на:

руби в несколько раз тормознее.

geekless ★★
()
Ответ на: комментарий от geekless

> Еще в одном тесте Питон почему-то быстрее в целых 6 раз.

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

http://shootout.alioth.debian.org/u32/program.php?test=pidigits&lang=yarv...

http://shootout.alioth.debian.org/u32/program.php?test=pidigits&lang=pyth...

provaton ★★★★★
()

Сегодня я в роли Капитана Очевидности

Потому, что Ruby - менее универсальный и более тормозный.

Deleted
()
Ответ на: комментарий от anonymous

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

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

archimag ★★★
()
Ответ на: комментарий от tailgunner

идентация

Индентация, блин. Indent же.

pevzi ★★★★★
()
Ответ на: комментарий от alienclaster

Мне нужно непробельное окончание блока, не с помощью идентации отступами

Зачем тебе еще как-то обозначать конец блока, если он уже и так обозначен уменьшением отступа?

pevzi ★★★★★
()
Ответ на: комментарий от geekless

Чем catch-throw принципиально отличается от питоновского raise-try-except?

Тем, что это НЕ механизм бросания исключений, а механизм выхода из вложенных конструкций

Дык а принципиальная разница в чем?

pevzi ★★★★★
()
Ответ на: комментарий от alienclaster

неудобно воспринимать глазами

Дело вкуса. Мне, например, неудобно смотреть скорее на лесенки из end'ов.

невозможности автоматической идентации с целью восстановить логику программы при частичном случайном смешении блоков

Ну, с таким же успехом можно и end случайно не туда воткнуть.

pevzi ★★★★★
()
Ответ на: комментарий от pevzi

Дело вкуса

Я привел объективный пример когда это неудобно

неудобно смотреть скорее на лесенки из end'ов.

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

Ну, с таким же успехом можно и end случайно не туда воткнуть.

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

alienclaster ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.