Здравствуйте, VladD2, Вы писали:
VD>Он на Руби пишет, в лучшем случае. А там как и в С++ ООП основное средство декомпозиции. Других практически нет. Одними лямбдами (блоками) сыт не будешь.
Ага, а тебе еще паттерн-матчинг добавили. Он рулит покруче ООП и лямб вместе взятых.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[13]: BOOST, .NET, String.Split и производительность…
Здравствуйте, eao197, Вы писали:
E>По поводу наследования: в своих OpenSource проектах с ходу не нашел. А код из закрытых проектов не смотрел, т.к. результат все равно не смогу показать. Но раз или два пришлось делать наследование для функторов, чтобы общую функциональность в базовый класс поместить. Ну и простейший пример наследования для функторов -- наследование от std::unary_function .
Автор маньякЪ!
Мне лень разбиратся но у меня такое чувство что ты гдето нетак провел декомпозицию.
У меня никогда не возникало жилания сделать такие функторы.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[14]: BOOST, .NET, String.Split и производительность…
Здравствуйте, FR, Вы писали:
E>>Кстати, вопрос к тем, кто смайлики ставит: а что смешного?
FR>размер
Был бы это не функтор, а свободная функция или метод, размер бы не сильно уменьшился, а вот читабельность могла пострадать. Поскольку в случае функции цикл перебора коллекции пришлось бы размещать у нее внутри (там и так есть большой цикл), и все эти проверки были бы внутри цикла, либо их бы пришлось вынести в отдельную функцию, которая бы получала сонмище аргументов. Так что хрен редьки не слаще.
К тому же для реальной (а не форумной пенисометрии) задачи объем получился весьма удовлетворительный: декларация функтора, тело operator() и тело вспомогательного метода, поотдельности занимают не более одной странички A4.
Так что это real life, смешного, как обычно, не много.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[8]: BOOST, .NET, String.Split и производительность…
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Denis2005, Вы писали:
D>>Насчет черта лысого не уверен, но лямбда удалась на славу:
D>>
D>>void MyF1(vector<int>& vec, int s)
D>>{
D>> transform(vec.begin(), vec.end(), vec.begin(), (s + _1));
D>>}
D>>
VD>Да, уж на славу... для тех кто нормальной не видел. _1 уже круто. А возьми случаи чуть по сложнее и ты приплыл. Ведь лямбды хороши тем, что это фукнции высшего порядка которые можно комбинировать.
Они хороши только тем, что не потребовали расширения и без того очень 'широкого' языка.
Случаи чуть по сложнее решаются обычно функторами.
VD>Да и проблем с ними не оберешся. В языках где они реализовны нормально, они имеют лексическую область видимости и их время жизни оеределяется наличием ссылок на них. Тут же фиг. А на дисерт пиколы вроде ничаянного добавления переменной с именем _1 в локальную область видимости, невнятные сообщения об ошибках и т.п.
Невнятные сообщения об ошибках, это вполне нормальный случай, если библиотекой решается, то на, что изначально язык не был ориентирован.
VD>Кстати, даже в такх, примитивных, случаях языки с полноценной поддержкой функций высшего порядка выглядят лучше. VD>Вот как это будет выглядить не Немерле: VD>
VD>transform.(s + _);
VD>
VD>"s + _" автоматом преобразуется в лямбду с одним параметром (никаких лишних скобок и хардкодед-имен вроде "_1" не нужно). Да и отсуствие идиотизма с begin()/end() разгружает код. В итоге получается, что писать функционально конечно на С++ можно, но неудобно, не всегда быстро, и очень громоздко.
Без лишних скобок: transform(vec.begin(), vec.end(), vec.begin(), s + _1);
А вот насчет begin()/end() не понял. Чем итераторы то не угодили?
Re[14]: BOOST, .NET, String.Split и производительность…
Здравствуйте, eao197, Вы писали:
VD>>Он на Руби пишет, в лучшем случае. А там как и в С++ ООП основное средство декомпозиции. Других практически нет. Одними лямбдами (блоками) сыт не будешь.
E>Ага, а тебе еще паттерн-матчинг добавили. Он рулит покруче ООП и лямб вместе взятых.
Он не то чтобы по круче, но в купе с алгебраическими типами во многих случая получается куда как выразительнее, чем без них. В купе же я просто имею больше средств для выражения. Ведь я могу выбирать из довольно широкого списка:
1. ООП (причем отлично реализованный, модульный, компонентный...).
2. Функции высшего порядка (ФВП).
3. Макросы (тяжелая артилерия).
4. Алгебраические типы и паттерн-матчинг.
Причем последний пункт рельно по значемости я бы поставил на первое место.
Оно и не удивильно, что ты в случаях в кторых казалось бы классы на фиг не упали во всю их используешь да еще и "фанкторами" называешь. А меж тем Курилка прав. Подобные задачи без классов решаются только проще.
В общем-то я тут согласен с Гапертоном — классы больше подходят для общего дизайна прилоежния. Для реализации ФВП и другие прибмабасы лучше подходят.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: BOOST, .NET, String.Split и производительность…
Здравствуйте, Denis2005, Вы писали:
D>Они хороши только тем, что не потребовали расширения и без того очень 'широкого' языка.
Что широкого в этом языке? Почему его нельзя целенаправлено рсширить действительно общепризнанно удобными возможностями? Зачем их эмулировать на коленке?
Хотя... мне уже по фигу. Меня этот вопрос занимал несколько лет назад. Теперь моя позиция очень простая. Горбатого могила исправит. Пусть гниет дальше.
D>Случаи чуть по сложнее решаются обычно функторами.
"Обычными"? Это где они слали обычными? Что-то я такого чуда природы в языках с функциями высшего прядка вообще не видел. И знаешь, мне кажется, что это потому, что фанкторы на фиг не упали.
D>Невнятные сообщения об ошибках, это вполне нормальный случай,
Серьезно? Дочего можно довести себя самовнушением?!
D>если библиотекой решается, то на, что изначально язык не был ориентирован.
А зачем тогда делать это в библиотеке? Почему не расширить язык тем что многим так нужно? Ведь получится элегантнее, быстрее (код быстрее будет), удобнее и с нормальной диагностикой ошибок. Какова цель згонять популярный язык в угол?
D>Без лишних скобок: transform(vec.begin(), vec.end(), vec.begin(), s + _1); D>А вот насчет begin()/end() не понял. Чем итераторы то не угодили?
А зачем они нужны? В функциональных языках все обходятся одновсязанным списком, который так и называется "список".
Если в коде присуствует vec.begin() и vec.end() — это уже избыточный код. Ведь работа ведется со всем списком и отдельно указывать его голову так же глупо как на вопрос о расстоянии до объекта начинать давать его координаты и координаты место где ты находишся.
В общем, С++, точнее его создатели, нарушили один очень важный принцип KISS. И это его погубит. А пока он не умер, можно извлечь пользу для сбея и своей конторы перейдя на более продуктивный язык и набляюдая как туча ежиков колются, плачут но продолжают с упоением жрать это кактус.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: BOOST, .NET, String.Split и производительность…
Здравствуйте, eao197, Вы писали:
E>Был бы это не функтор, а свободная функция или метод, размер бы не сильно уменьшился,
Это зависит... от разрабочика. Разумный разработчик произвел бы декомпозицию функций и получил бы ряд более простых фунций и собераемую из инх более сложную функцию.
Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: BOOST, .NET, String.Split и производительность…
Здравствуйте, VladD2, Вы писали:
E>>Был бы это не функтор, а свободная функция или метод, размер бы не сильно уменьшился,
VD>Это зависит... от разрабочика. Разумный разработчик произвел бы декомпозицию функций и получил бы ряд более простых фунций и собераемую из инх более сложную функцию.
Ага, и программы у таких разработчиков работают, если в них ошибок нет.
Ты посмотри на код, там нет ничего сложного -- один цикл и несколько if-ов. Объем создает только форматирование и комментарии.
Но самое важное, что это только одна из простых функций, которые вместе реализуют довольно-таки сложный алгоритм. И мне было важно, чтобы на более высоком уровне я мог оперировать конструкциями типа std::for_each, std::find_if, std::transform и делать прозрачным более сложный код.
VD>Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции.
Ой-ой-ой. Не поверю.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[15]: BOOST, .NET, String.Split и производительность…
Здравствуйте, VladD2, Вы писали:
VD>Он не то чтобы по круче, но в купе с алгебраическими типами во многих случая получается куда как выразительнее, чем без них. В купе же я просто имею больше средств для выражения. Ведь я могу выбирать из довольно широкого списка: VD>1. ООП (причем отлично реализованный, модульный, компонентный...). VD>2. Функции высшего порядка (ФВП). VD>3. Макросы (тяжелая артилерия). VD>4. Алгебраические типы и паттерн-матчинг.
Можешь рассказать, какая помощь от макросов в обработке графовых структур?
VD>Причем последний пункт рельно по значемости я бы поставил на первое место. VD>Оно и не удивильно, что ты в случаях в кторых казалось бы классы на фиг не упали во всю их используешь да еще и "фанкторами" называешь. А меж тем Курилка прав. Подобные задачи без классов решаются только проще.
Нихрена они проще не получаются. Получаются те же продукты, только в профиль. Но об этом уже Cyberax сказал.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[10]: BOOST, .NET, String.Split и производительность…
Здравствуйте, VladD2, Вы писали:
VD>Что широкого в этом языке? Почему его нельзя целенаправлено рсширить действительно общепризнанно удобными возможностями? Зачем их эмулировать на коленке?
VD>А зачем тогда делать это в библиотеке? Почему не расширить язык тем что многим так нужно? Ведь получится элегантнее, быстрее (код быстрее будет), удобнее и с нормальной диагностикой ошибок. Какова цель згонять популярный язык в угол?
Понять жизнь можно лишь оглядываясь назад, но жить-то приходится, смотря вперед. (C) Сёрен Кьеркегор
Была избрана такая политика, чтобы помаксимому давить на библиотеки, т.к. язык и без того слишком сложный и многими местами противоричивый.
Ты же знаешь, сколько времени нужно WG21 X3J16 чтобы принят то или иное решение, особенно если оно касается расширений.
А сколько пройдет когда реальными компиляторами будет поддерживаться введеное расширение?
Вот с библиотекой дела обстоят немного попроще, поэтому на них и делается основной упор.
VD>Хотя... мне уже по фигу. Меня этот вопрос занимал несколько лет назад. Теперь моя позиция очень простая. Горбатого могила исправит. Пусть гниет дальше.
'Горбатый' еще задаст жару молодым неокрепшим умам
D>>Случаи чуть по сложнее решаются обычно функторами.
VD>"Обычными"? Это где они слали обычными? Что-то я такого чуда природы в языках с функциями высшего прядка вообще не видел. И знаешь, мне кажется, что это потому, что фанкторы на фиг не упали.
Я сказал обычно, и применительно для C++. В C# 2.0 нормально обхожусь анонимными делегатами.
VD>А зачем они нужны? В функциональных языках все обходятся одновсязанным списком, который так и называется "список". VD>Если в коде присуствует vec.begin() и vec.end() — это уже избыточный код. Ведь работа ведется со всем списком и отдельно указывать его голову так же глупо как на вопрос о расстоянии до объекта начинать давать его координаты и координаты место где ты находишся.
За всех говорит не стоит. Частенько бывает, что работа ведется с определенными фрагментами коллекции.
Хотя там где производительность особо не важна, можно и полными списками погонять.
VD>В общем, С++, точнее его создатели, нарушили один очень важный принцип KISS. И это его погубит. А пока он не умер, можно извлечь пользу для сбея и своей конторы перейдя на более продуктивный язык и набляюдая как туча ежиков колются, плачут но продолжают с упоением жрать это кактус.
Сам пишу пот .NET уже > 4 лет, если задача позволяет, поэтому про ежиков заканчивай.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[6]: BOOST, .NET, String.Split и производительность…
Здравствуйте, Odi$$ey, Вы писали:
MS>>Так что язык здесь ни при чем вообще.
OE> C# вроде как под той же виндой тестируют с той же самой ntdll.dll
Разница в том, что C# не вызывает ntdll по isspace (или какой там аналог?). А сишная библиотека от MS по кой-то фиг вызывает (ну или вызывала, не знаю как оно сейчас).
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[18]: BOOST, .NET, String.Split и производительность…
Здравствуйте, eao197, Вы писали:
E>конструкциями типа std::for_each, std::find_if, std::transform и делать прозрачным более сложный код.
Это называется функции высшего порядка реализованные через зад автогеном.
VD>>Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции. E>Ой-ой-ой. Не поверю.
А зря. Только к проблеме нужно подходить комплексно.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, Denis2005, Вы писали:
D>Компилятор: MS VC 8.0 D>Время работы: 20 секунд. (и это при полной оптимизации и отключенными проверками !?!)
D>Код на C#, .NET Framework: D>Время работы: ~1 сек, при 10^7 итераций ~6 сек.
Здравствуйте, WolfHound, Вы писали:
E>>конструкциями типа std::for_each, std::find_if, std::transform и делать прозрачным более сложный код. WH>Это называется функции высшего порядка реализованные через зад автогеном.
Мне по барабану, как они называются вообще, а для моего конкретного случая это означало бы, что я не мог бы вызывать внутри алгоритма лямбды на 30-ть строк длиной, а передавал бы в аналог for_each функцию. И вызов:
std::find_if( c.begin(), c.end(), functor )
не сильно отличается от
c.find_if &functor
поскольку тело functor-а и его инициализация определены где-то в другом месте.
VD>>>Кстати, это как раз тот случай когда как раз функции высшего порядка неимоверно "рулят". ООП обычно не дает детализировать алгоритмы, так как оверхэд на описание классов и их методов превышает выигрышь от самой декомпозиции. E>>Ой-ой-ой. Не поверю. WH>А зря. Только к проблеме нужно подходить комплексно.
Так подходите. Вы же даже не знаете задачи, частью которой является приведенный мной код, а ухмыляться себе позволяете. В форумах на словах все мастера.
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, VladD2, Вы писали:
VD>>Он на Руби пишет, в лучшем случае. А там как и в С++ ООП основное средство декомпозиции. Других практически нет. Одними лямбдами (блоками) сыт не будешь.
E>Ага, а тебе еще паттерн-матчинг добавили. Он рулит покруче ООП и лямб вместе взятых.
Все-таки паттерн матчинг вещь в хозяйстве полезная, неплохо было бы если бы его ввели в питон, да и в руби бы не помешал, притом для ввода например в питон даже не надо больших уж затрат и ломки старого кода, достаточно одного ключевого слова. Ну а пока не ввели, я тут играюсь библиотечными методами, вот например такой эскизик сегодня нарисовал:
class when:
patterns = []
def __init__(self, expr):
when.patterns.append(self)
self.expr = expr
def __call__(self, func):
arg0 = tuple(getargspec(func)[0])
self.func = func
def _wrap(*args):
d = dict(zip(arg0, args))
for pattern in when.patterns:
if pattern.func.__name__ == func.__name__ and eval(pattern.expr, globals(), d):
return pattern.func(*args)
raise TypeError("not find pattern: " + repr(d))
return _wrap
использование:
@when("n < 2")
def fib(n):
return 1
@when("n >= 2")
def fib(n):
return fib(n - 1) + fib(n - 2)
print fib(8)
@when("a == 0")
def ack(a, b):
return b + 1
@when("a != 0 and b == 0")
def ack(a, b):
return ack( a - 1, 1 )
@when("True")
def ack(a, b):
return ack( a - 1, ack( a, b - 1 ) );
print ack(3, 4)
Так что если очень хочется то и паттерн матчинг можно сделать
FR wrote: > Так что если очень хочется то и паттерн матчинг можно сделать
Очень забавный фокус, хотя это не паттерн матчинг. Да, похоже на guards,
но в паттерн матчинге важнее выбор пути исполнения в одновременно со
связыванием переменных, с разбором сложной структуры на части, а
этого в твоем примере ни разу нет.
<offtop>
А по каким словам надо гуглить, чтобы прочитать об этом трюке с @foobar?
Я тут для мелких скриптов начал Питон пробовать, но изучать некогда,
прыгать надо .
</foobar>
Здравствуйте, Programmierer AG, Вы писали:
PA>FR wrote: >> Так что если очень хочется то и паттерн матчинг можно сделать PA>Очень забавный фокус, хотя это не паттерн матчинг. Да, похоже на guards, PA>но в паттерн матчинге важнее выбор пути исполнения в одновременно со PA>связыванием переменных, с разбором сложной структуры на части, а PA>этого в твоем примере ни разу нет.
Угу это скорее ближе к мультиметодам, но упрощает решение тех же задач что паттерн матчинг.
При желании можно и связывание переменных добавить.
А струкуры и сейчас вполне разбираются, аргументом может быть любой логический предикат, при его истиности вызывается связанная функция
@when("isinstance(x, basestring)")
def my_print(x):
print '<' + x + '>'
@when("isinstance(x, list)")
def my_print(x):
print "["
for i in x:
my_print(i)
print "]"
@when("True")
def my_print(x):
print x
PA><offtop> PA>А по каким словам надо гуглить, чтобы прочитать об этом трюке с @foobar? PA>Я тут для мелких скриптов начал Питон пробовать, но изучать некогда, PA>прыгать надо . PA></foobar>