LINUX.ORG.RU

Ответ на: комментарий от eao197

Давайте сверим, что ли?

Признаю, был несколько неправ - казалось, что твоё восприятие скалы более негативное.

С другой стороны, мне кажется, что вопросы сложности вполне решаемы чисто административными методами. Можно как ограничить список используемых фич, причём это справедливо для обоих языков: как С++ полезно использоваться хотя бы ради деструкторов, так и на скале можно писать «почти как на джаве». Так и спрятать сложности в библиотеки. В обоих случаях, уровень команды можно подтягивать.

При наличии ревью это не видится мне проблемой. Наверное, хватает проектов где этого нет, но от них я предпочёл бы держаться подальше.

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

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

Получается как-то так:

#include <iostream>
#include <iterator>
#include <vector>

using namespace std;

template< typename C, typename F >
auto sum_if( C const & v, F f )
{
	using R = typename std::decay< decltype(*begin(v)) >::type;
	R r{};
	for( auto const & x : v )
		if( f(x) ) r += x;
	return r;
}

int main()
{
	vector< double > a = { 1.0, 2.0, 0.0, -2.0, -3.0, 4.0, 1.0 };
	cout << sum_if( a, []( auto x ) { return x > 0; } ) << endl;
}
Если заложиться на то, что типом контейнера всегда будет vector, то можно еще проще сделать, без вывода типа R внутри sum_if. А эта реализация может принять не только vector, но и list, deque и т.д.

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

Ну ясное дело что фича хороша, но пока лишь ждем

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

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

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

Код примера LMS делает совсем другое. Там смысл в том, чтобы получить на выходе дерево выражений, которое можно потом обрабатывать различными способами. Например, оптимизировать, сгенерировать код на C или Scala, или интерпретировать.

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

Как пример был предложен более быстрый вариант вектора ...

Это не вариант вектора. Это просто наколеночный динамический массив. Что не одно и то же.

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

Если заложиться на то, что типом контейнера всегда будет vector, то можно еще проще сделать, без вывода типа R внутри sum_if. А эта реализация может принять не только vector, но и list, deque и т.д.

Для всех стандартных типов (плюс boost) можно написать просто:

typename C::value_type r;

Это не придирка, просто возможный прием.

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

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

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

Ну просто пример очень жесткого codestyle, но работает норм

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

Получается как-то так:

А если еще поизвращаться, то можно и более короткую запись реализовать:

#include <iostream>
#include <vector>
using namespace std;

template<class F, class T>
typename enable_if<is_same<typename result_of<F(T)>::type, bool>::value, bool>::type
sum_if_match( const F& f, const T& v ) { return f( v ); }

template<class F, class T>
typename enable_if<!is_same<typename result_of<F(T)>::type, bool>::value, bool>::type
sum_if_match( const F& f, const T& v ) { return f( v )( v ); }

#define sum_if( c, ... ) [&] { \
    using R = typename decay<decltype(*begin(c))>::type; \
    auto f = []( auto _ ) { return __VA_ARGS__; }; \
    R r; \
    for( auto& v : c ) \
        if( sum_if_match( f, v ) ) r += v; \
    return r; \
}()


int main()
{
    vector<double> a { 1.0, 2.0, 0.0, -2.0, -3.0, 4.0, 1.0 };

    cout << sum_if( a, _ > 0 ) << endl;
    cout << sum_if( a, []( auto x ) { return x < 0; } ) << endl;
}

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

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

ну, я лично не фанат ООП. но для моих задач оно и не нужно, в 99% случаев. у меня всегда стоит главная задача - оптимизация по скорости. так что развесистую клюкву без особой необходимости я не использую. а вот студенты, только выпустившиеся из ВУЗов, страдают ООП головного мозга. видимо, им там очень долго втирают идею о ценности ООП.
я как-то переписывала код, в котором нанятый на работу программист-неофит для реализации обычного массива фиксированной длины для хранения структур создал иерархию аж из четырёх классов, с наследованием, наворотил какие-то итераторы, классы-абстракции и поверх этого всего какую-то аццкую нелинейную логику. и там ещё и ошибся в паре мест, в этом своём густом лесу. в итоге, я это всё выпилила и сделала простой malloc на нужный размер и по смещениям обращения. работать всё стало в сто раз быстрее :) обычно после двух-трёх лет работы с реальными проектами фанатичное пристрастие к ООП проходит. пожалуй, остаётся оно только в Qt-образных проектах, во всякой графической гуйне, и то пока графика не серьёзная. где серьёзная - там OpenGL во все поля и особо густой фигни не понаделаешь.

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

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

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

они ТОЧНО есть. я и многие мои соратники, бывшие и настоящие. на Си пишется реально много кода и он актуален всегда.

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

Кстати, упоминая OpenGL, то нынче геометрия подготавливается в буферы видеопамяти и оттуда обрабатывается шейдерами. Язык и рантайм на CPU перестают занимать хоть какое-то время исполнения. Мы успешно писали OpenGL приложения на Java и процессор был почти незанят, да и основная память тоже

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

Речь не о том, что делает LMS. Речь о том, что код на Scala некоторыми людьми воспринимается как сложный. Аналогично, некоторый код с шаблонами на C++ некоторыми людьми воспринимается как сложный.

Хотя все это очень относительно.

Ну, а раз речь пошла про LMS, то пример на стартовой странице может заинтересовать тех, кому по неволе приходится разгонять тормозной код на JVM. В C++ показанный мной вариант без каких-либо усилий со стороны программиста самим компилятором развернется в то, что показано в LMS-ном примере в качестве демонстрационного результата.

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

eao197 ★★★★★
()
Последнее исправление: eao197 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Это не придирка, просто возможный прием.

Я сделал соответствующую оговорку.

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

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

Макросы зло. Уж лучше поколдовать с placeholders вида _1, _2 и т.д. Тогда выражение _1 > 0 будет автоматически преобразовываться в функтор, который пойдет на вход sum_if как и лямбда-функция.

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

Макросы зло.

Макросы - добро, это препроцессор зло. Но в данном конкретном случае это вполне вариант.

Тогда выражение _1 > 0 будет автоматически преобразовываться в функтор, который пойдет на вход sum_if как и лямбда-функция.

Не годится для сколько-нибудь сложных выражений.

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

Не годится для сколько-нибудь сложных выражений.

Как и макросы, собственно говоря. Которые зло.

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

Как и макросы, собственно говоря.

Покажи на данном конкретном случае. Я знаю, что препроцессор - зло, и знаю почему, но где ты видишь проблемы здесь?

Которые зло.

Кому как. Мне бы настоящие макросы не помешали.

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

где ты видишь проблемы здесь

С макросами ес-но, т.к. корявости вроде [&]/[], ( v )( v ) я вижу и сам. Надо было потратить время на review перед тем как запостить.

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

Не освоил еще C++14 в должной степени, можно короче:

template< typename C, typename F >
auto sum_if( C const & v, F f )
{
	std::decay_t< decltype(*begin(v)) > r{};
	for( auto const & x : v )
		if( f(x) ) r += x;
	return r;
}

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

Покажи на данном конкретном случае. Я знаю, что препроцессор - зло, и знаю почему, но где ты видишь проблемы здесь?

Проблемы с макросами в том, что здесь и сейчас их нет. А спустя какое-то время и в каком-то другом месте РАЗ! И есть.

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

Проблемы с макросами в том, что здесь и сейчас их нет. А спустя какое-то время и в каком-то другом месте РАЗ! И есть.

«РАЗ!» - отличное имя для макроса, кстати, и не пропустишь его :)

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

Если я правильно помню, то запись T v; приводит к созданию переменной v типа T с неинициализированным значением, если T является элементарным типом (вроде int, double или указатель на что-то). Тогда как запись T v{}; (или T v(()); в C++03) для примитивного типа инициализирует v дефолтным значением (0 для int, 0.0 для double, nullptr для указателя). Но это если я правильно помню :)

eao197 ★★★★★
()

Итог треда

Почему я выбираю C++? - Я не выбираю, оно просто до меня все на С++ написано

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

Я думал T v() было бы достаточно. Хотя обычно в подобных алгоритмах начальное значение обычно просят пользователя задать отдельно

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

Если я правильно помню, то запись T v; приводит к созданию переменной v типа T с неинициализированным значением, если T является элементарным типом (вроде int, double или указатель на что-то).

Блин, точно, к концу дня голова уже не варит. Пойду отдыхать.

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

Я думал T v() было бы достаточно.

Это старая ловушка в C++. T v() является декларацией функции v без параметров, возвращающей значение типа T. Несколько раз на такое натыкался.

C++11/14 в этом плане лучше, т.к. позволяют писать T v{}

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

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

ЕМНИП, запись v() прокатывает при инициализации членов класса/структуры:

struct A {
  int v;
  A() : v() {}
};
Собственно, для этого она и вводилась.

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

или T v(()); в C++03

Соврал. В C++03, походу, надо было писать T v = T();.

eao197 ★★★★★
()

Что и говорить, C++ — классика жанра. А все эти поздние — в основном для красивости, иногда напоминающие склад ортопедических принадлежностей.

Проекты надо писать, а не сладостями баловаться.

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

видимо, им там очень долго втирают идею о ценности ООП.

И не только студентам. Вот цитата из учебника по с# (Фроловых):

Однако объектно-ориентированный подход, предлагаемый языком C++, значительно облегчает создание программ, в результате чего обоснованность использования классического языка С при создании новых программ представляется нам весьма сомнительной. Более того, начиная изучение программирования с процедурного, а не объектно-ориентированного языка, можно приобрести вредные привычки процедурного программирования. Эти привычки в дальнейшем затруднят изучение современных объектно-ориентированных и компонентно-ориентированных технологий.

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

rechnick ★★★
()

Почему цепепе не ахти :-)

А как на цепепе написать шаблон функции, в котором параметром шаблона может быть не любая функция, а только одна из допустимых? :-) Например, шаблон:

namespace C {
  template<typename F>
  void h(F f)
  {
    // f is only A::f or B::g
    f();
  }
}
должен позволять принимать только A::f или B::g, т.е.
namespace A {
  void f();
}

namespace B {
  void g();
}
Проверка должна осуществляться компилятором, т.е. код вроде auto x = f == &A::f ? &A::f : &B::g ? &B::g : nullptr; не приемлем :-)

PS. Жду километровых статических функций-членов полных специализаций шаблонов структур :-)

anonymous
()
Ответ на: Почему цепепе не ахти :-) от anonymous

А как на цепепе написать шаблон функции, в котором параметром шаблона может быть не любая функция, а только одна из допустимых?

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

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