(no subject)
6/10/06 14:33![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Хороший человек
vbayda показал, как он использует boost::bind:
Как на меня, мягко выражаясь, выглядит не слишком читабельно.
Понял слова Алана Перлиса "избыток синтаксического сахара приводит к раку фигурных скобок" (переврал цитату, и ну его).
Не слишком-то C++ пригоден для функциональщины. Правда, синтаксис получился не намного хуже, чем у Lisp-а.
Попытался переписать это на Haskell. Не могу скомпилировать, хоть ты тресни. Хотя выглядит немного лучше.
Комментирую синтаксис "в стиле учебника" для тех, кто не знает языка.
Итого получается (получилось бы, если бы я лучше понимал синтаксис и типизацию)
или, без промежуточной "объясняющей" функции
Считаем скобки, почти как в Лиспе. Кстати, синтаксис Лиспа должен был быть похож на хаскельный. Но его где-то там не смогли заимплементить и бросили нынешнем виде, который предназначался только для списковых данных.
![[livejournal.com profile]](https://www.dreamwidth.org/img/external/lj-userinfo.gif)
if (entityes_.end() == std::find_if(entityes_.begin(), entityes_.end(),
boost::bind < bool > (&intersect < double >, c,
boost::bind(&world::positions::entity::shape_,
boost::bind(&world::entity::positions_, _1)
)
)
))
Как на меня, мягко выражаясь, выглядит не слишком читабельно.
Понял слова Алана Перлиса "избыток синтаксического сахара приводит к раку фигурных скобок" (переврал цитату, и ну его).
Не слишком-то C++ пригоден для функциональщины. Правда, синтаксис получился не намного хуже, чем у Lisp-а.
Попытался переписать это на Haskell. Не могу скомпилировать, хоть ты тресни. Хотя выглядит немного лучше.
Комментирую синтаксис "в стиле учебника" для тех, кто не знает языка.
module Main
where
-- это описание типа данных - "записи" с конструктором и одним полем
data Entity = CreateEntity { position :: Position }
data Position = CreatePosition { circle :: Circle }
data Circle = CreateCircle { x, y, r :: Float }
-- указание типа функции (аргументов и параметров).
-- Обычно можно опустить, type inferrance его определяет.
circlesIntersect :: Circle -> Circle -> Bool
-- это собственно описание функции: имя, параметры, =, тело-выражение
circlesIntersect c1 c2 = sqr (r c1 + r c2) < sqr (x c1 - x c2) + sqr (y c1 - y c2)
where sqr x = x*x
findIntersecting :: Circle -> [Entity] -> Entity
findIntersecting circle entities =
-- это тот самый байнд одного (первого) параметра. Выглядит так: (имя функции) параметр.
find ((entityMatches) circle) entities
where
entityMatches :: Circle -> Entity -> Bool
entityMatches c e = circlesIntersect c (circle position e)
-- Оказывается, в Haskell обращение к полям структуры выглядит не как c.x, а как x(c).
-- Или x c, что в этом случае то же самое.
main = putStr "Hello\n"
Итого получается (получилось бы, если бы я лучше понимал синтаксис и типизацию)
findIntersecting circle entities = find ((entityMatches) circle) entities where entityMatches c e = circlesIntersect c (circle position e)
или, без промежуточной "объясняющей" функции
findIntersecting circle entities = find (((circlesIntersect) c (circle position e)) circle) entities
Считаем скобки, почти как в Лиспе. Кстати, синтаксис Лиспа должен был быть похож на хаскельный. Но его где-то там не смогли заимплементить и бросили нынешнем виде, который предназначался только для списковых данных.
Tags:
(no subject)
6/10/06 13:57 (UTC)>Синтаксический сахар вызывает рак точек с запятой (semicolon).
Эта цитата в переводе звучит глупо.
Colon - это и двоеточие, и толстая кишка.
(no subject)
6/10/06 20:43 (UTC)(no subject)
6/10/06 14:27 (UTC)(no subject)
6/10/06 17:20 (UTC)2. насчет жутких тормозов - неуверен, лишнеие вызовы - это не жуткие тормоза;
3. отлаживать осбо нечего: брек поинт ты на забинженую функцию всегда можешь поставить, правильно ли ты сбиндил - проверяется во времени компиляции. Единственное что может раздражать при отладке так это call stack:) (например в boost::serialization - он вообще сумашедший ), ну и здесь немаленький будет;
4. да, неплохо было бы что-то вроде лямбды только на уровне языка
и с возможностями побольше чем в boost::lambda :));
(no subject)
6/10/06 19:14 (UTC)3. Имелась ввиду отладка километровых сообщений об ошибках компиляции с метровыми именами типов
4. Помогли бы локальные анонимные функции: Тут заодно я использовал for_each, принимающий в качестве аргумента range (нечто с begin() и end(). range вроде обещают скоро включить в стандарт.
Более того, в рамках можели исполнения C++ ничего не стоит реализовать для локальных функций частичную функциональность closures - позволить локальным функциям ссылаться на внешние переменные на стеке.
Но честно говоря, я бы предпочел что-то вроде nemerle (суперязык под .NET) + barton (компилятор MSIL -> Native из проекта Singularity). C++ слишком разжирел - новые && ссылки это просто бред и хак.
Нужен сверхбыстрый язык без наследия.
(no subject)
7/10/06 17:49 (UTC)3. есть такое, но к этому привыкаешь. А еще гдето встречались скрипты, преобразующиее большой и сложный output с ошибками в нечто более простое, правда они сильно под STL заточены были;
(no subject)
7/10/06 18:32 (UTC)3. Привыкание ничего не меняет. Люди и при -60, и при +50 градусах живут, но я к такому привыкать не хочу.
С++ - реально калообразный язык. Нужно "что-то массовое, современное", но столь же быстрое. Я фанат скорости С++, а во всем остальном он полный отстой. STL и исключения использовать нельзя почти никогда - они сразу становятся ботлнеком. А если скорость некритична - можно какой язык попроще и погибче выбрать.
(no subject)
6/10/06 20:37 (UTC)Я имел в виду, что считать здесь нужно закрывающие скобки в хаскельном варианте. Он короче, но всё равно скобками подозрительно похож на Лисп.
А вот что в C++ нужна порция сахара для функционального программирования - не думаю. Это уже будет чёрт-те-что.
Как сказал Филип Гринспун, "Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp"
Правда, 0x уже будет черт-те-чем. И никак его уже не упростишь, обратная совместимость тянет ко дну. А обратная совместимость - это всё, что осталось у C++.
(no subject)
6/10/06 21:04 (UTC)Хаскель не годится, потому что он чисто функциональный. Надо перековывать мозги для перехода на функциональную модель вычислений, а для вдекватного понимания и использование монад нужно матобразование.
(no subject)
6/10/06 21:21 (UTC)Неплохой идеей будет примазаться к C#/.NET. Посмотрю-ка я на этот Nemerle. Design by contract - это хорошо; жаль, его компилятор ещё не умеет проверять контракты в compile time.
С одной стороны, кажется, что многовато в нём сахару. Перегрузка синтаксиса и те пе. С другой, Пёрлу-то обилие сахара не очень мешает.
(no subject)
6/10/06 22:02 (UTC)Супер-производительность важна для того чтобы умер С++. Иначе этот зомби будет всех мучать и в третьем тысячелетии.
Unmanaged и даже отсутствие gc - не важно. Важна скорость, которой можно добиться и в рамках garbage collected managed x86 (я подразумеваю аналог пока не существующего Microsoft Singularity TAL - обычный код + метаданные обеспечивающие верифицируемость). Ну и конечно нужен очень мощный компилятор и JITter - теоретически функциональный код лучше оптимизируются чем императивный. Сейчас компилятор C# вообще не содержит оптимизатора.
Еще нужны модульный рантайм и новая технология распространения приложений через веб чтобы рантайм не таскать за собой.
Мейнстрим и сам выживет - важно убить ++, Open Source сразу расцветет.
(no subject)
7/10/06 08:49 (UTC)(no subject)
7/10/06 08:50 (UTC)(no subject)
7/10/06 08:51 (UTC)(no subject)
7/10/06 18:39 (UTC)(no subject)
7/10/06 20:56 (UTC)(no subject)
8/10/06 07:46 (UTC)> findIntersecting :: Circle -> [Entity] -> Maybe Entity
> findIntersecting circle_ entries =
> find (circlesIntersect circle_ . circle . position) entries
Re: Reply to your comment...
8/10/06 09:21 (UTC)Тип, действительно, можно не указывать - он будет выведен автоматически.
Re: Reply to your comment...
8/10/06 11:44 (UTC)Что полезного дает спецификация типа? Меняется ли от наличия спецификации в данном случае какое-либо поведение времени компиляции и времени исполнения?
Re: Reply to your comment...
9/10/06 06:06 (UTC)Если нужно возвращать что-то конкретное, можно воспользоваться функцией maybe, имеющей тип b -> (a -> b) -> Maybe a -> b - первый аргумент задаёт значение в случае Nothing, второй - функцию, обрабатывающую x в случае Just x. Так, fromJust можно определить как maybe (error "Что-то там ошибочное") id.
Спецификация даёт проверку при компиляции на отсутствие тривиальных ошибок. Точнее, даёт возможность отловить ошибку поближе к тому месту, где она допущена.
Поведение правильно написанной программы от наличия спецификации не меняется.
Иногда ОТСУТСТВИЕ спецификации позволяет обнаружить, что написанная функция более обща, чем казалось.
Type inference как преимущество языка
16/10/06 16:28 (UTC)В "скриптовых" языках все не только умудряются жить "без типов", но и даже находят в этом определенные преимущества.
Вопрос: Чем чреват подход, при котором типы не специфицируются без крайней необходимости? Можно привести какие-то примеры ошибок, легче диагностирующихся при полной спецификации?
Вы имеете ввиду такой пример? Скажем в стеке вызовов функций все функции принимают произвольный тип, но несуществующий интерфейс требует скажем только самая нижняя (самая внутренняя) функция. В этом случае компилятор выдаст ошибку во внутренней функции и стек вызовов придется отслеживать самому. А в случае явной спецификации компилятор укажет на ошибку сразу на самом верху?
Re: Type inference как преимущество языка
17/10/06 05:02 (UTC)Я написал "иногда". В общем случае, нужны более серьёзные телодвижения. Хотя к спецификации типов они имеют весьма опосредованное отношение.
nis> В "скриптовых" языках все не только умудряются жить "без типов", но и даже находят в этом определенные преимущества.
Здесь следует различать. Есть языки со слабой типизацией - например, Perl. Там вполне можно написать 2+"three" и получить более-менее осмысленный результат. ИМХО, такой подход имеет право на существование, если мы пишем очень маленькие скрипты для выполнения небольших задач. Пожалуй, единственное значимое исключение здесь (из известных мне) - Tcl, пригодный для относительно крупных вещей, благодаря некоей объединяющей идее ("всё есть строка"). На самом деле, там с типами тоже не всё так просто, и перловской мешанины там нет.
А есть языки с сильной, но динамической типизацией. Где рассогласование типов вызывает ошибку времени ИСПОЛНЕНИЯ. И вот здесь появляются наиболее мощные вещи - Lisp, SmallTalk, JavaScript (ох... вынужден я сейчас писать на некоем диалекте жабаскрипта - тех, кто его (диалект) придумывал, убить мало; надо ж так кастрировать замечательный язык). Вот они, как раз, пригодны для очень серьёзных проектов.
Я бы сказал так. Языки со статической сильной типизацией (тот же Haskell, например; C++ к ним не относится, там типизация слабая) хороши тогда, когда мы совершенно чётко представляем себе, что мы пишем. Если же проект предполагает некое исследование возможностей, если могут случиться очень серьёзные изменения дизайна - нужен язык с динамической сильной типизацией. Языки же со слабой типизацией нужны для маленьких вещей, где можно обойтись без дизайна вообще и сделать нужную программу на интуиции.
nis> Вы имеете ввиду такой пример? Скажем в стеке вызовов функций все функции принимают произвольный тип, но несуществующий интерфейс требует скажем только самая нижняя (самая внутренняя) функция. В этом случае компилятор выдаст ошибку во внутренней функции и стек вызовов придется отслеживать самому. А в случае явной спецификации компилятор укажет на ошибку сразу на самом верху?
Да, например, вполне возможный сценарий. Именно поэтому в Лиспе, например, предусмотрено объявление типов переменных (хотя и является необязательным).
Динамическая типизация и размер проекта
17/10/06 09:11 (UTC)А как же стоимость исправления ошибки, которая растет экспоненциально по времени?
Ошибка времени компиляции стоит гораздо дешевле. Даже не в деньгах, во времени. Неужели динамическая типизация уменьшает количество ошибок согласования типов, скажем, в 10 раз?
Re: Reply to your comment...
16/10/06 16:41 (UTC)Re[2]: Reply to your comment...
17/10/06 05:02 (UTC)(no subject)
9/10/06 08:23 (UTC)(no subject)
9/10/06 08:51 (UTC)(no subject)
16/10/06 16:45 (UTC)(no subject)
8/10/06 10:54 (UTC)Это именно те советы, которые мне были нужны.
Какое место из учебников мне нужно перечитать?
(no subject)
9/10/06 06:11 (UTC)(no subject)
9/10/06 08:55 (UTC)Только позавчера вспомнил, что есть ещё ru_lambda, а в ней какие-то ссылки. Почитаю и их.
(no subject)
22/11/06 20:48 (UTC)Пересечение кругов на Smalltalk-е:
circles anySatisfy:
[:e | (c center dist: e center) < c radius + e radius]
Здесь "c" - круг с которым мы ищем пересечения. dist: - вычилсяет растояние между точками.
Ответом будет true либо false. Если надо выбрать только круги пересекающий данный то надо anySatisfy: заменить на select:
Ну и на всякий случай, пересечение контуров окружностей:
circles anySatisfy:
[:e |
(c center dist: e center)
between: (c radius - e radius) abs
and: c radius + e radius]
Alex Baran
(no subject)
23/11/06 10:06 (UTC)И обращения к полям bind-ились с функцией пересечения окружностей.
Кстати, страничка почему-то показывается в KOI-8, хотя она в 1251.
(no subject)
23/11/06 10:57 (UTC)Circle>>intersect: c2
^(self center dist: c2 center) < (self radius + c2 radius)
entities anySatisfy: [:entity | entity position circle intersect: c]
(no subject)
22/11/06 22:32 (UTC)http://aleksijb.googlepages.com/circlesIntersections.htm