LINUX.ORG.RU

С++


0

1

Здравствуйте. Подскажите, есть ли для C++ в STL или BOOST функция аналогичная функции map в Haskell, Clean?

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

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

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

тут

    return [x](int y) { return op( x, y ); };
наверное должно быть так:
    return [x, op](int y) { return op( x, y ); };

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

> А чем тогда вас не устроил пример creepnee?

тем, что там не показан захват лексической области видимости.

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

Если она явно принимает массив списков - это уже не серьезно.

Ну а вообще требования такие:
1. Принимает функтор с числом аргументов n >= 1. Типы аргументов - произвольные.
2. Принимает n списков с элементами разного типа.

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

>Если она явно принимает массив списков - это уже не серьезно.
Что значит явно или неявно? Вам нужна функция принимающая чёрти что и на основе этого вы фейлите язык? Позиция Страуструпа известна, он не хочет тащить в язык кучу синтаксического сахара.

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

>тем, что там не показан захват лексической области видимости.
Захват это что, специфицирование захватываемых переменных? Есть такое в C++ лямбдах. Ещё в шаблонах можно было обращаться к переменным контекста.

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

>Что значит явно

Явный мап это функция от двух аргументов - функтор и массив списков.

>неявно?

Переменное число аргументов

>Вам нужна функция принимающая чёрти что

Не чёрти что, а

1. Принимает функтор с числом аргументов n >= 1. Типы аргументов - произвольные.
2. Принимает n списков с элементами разного типа.

>на основе этого вы фейлите язык?

Я ещё не начинал.

>Позиция Страуструпа известна, он не хочет тащить в язык кучу синтаксического сахара.

Т.е. вся проблема в реализации mapcar на плюсах - только в способе подачи несчатных списков? Ну вот, а я-то думал :)

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

>1. Принимает функтор с числом аргументов n >= 1. Типы аргументов - произвольные.

2. Принимает n списков с элементами разного типа.

В новом стандарте есть variadic templates и списки инициализации, так что реально.

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

Захват это что, специфицирование захватываемых переменных? Есть такое в C++ лямбдах. Ещё в шаблонах можно было обращаться к переменным контекста.

Curried curry (int x, Operator op)
{
    return [x, op](int y) { return op( x, y ); };
}

здесь замыкание — результат функции curry, т.е.

[x, op](int y) { return op( x, y ); }
захваченное окружение — x и op — параметры функции curry. суть не в том, что они перечислены явно в [] (а по хорошему необходимости перечислять их явно вообще не должно быть), а в том, что функция
[x, op](int y) { return op( x, y ); }
может обращаться к ним за пределами функции curry, после того как curry отработала.

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

>Новый стандарт, новый стандарт, это не интересно!
Многие компиляторы уже поддерживают новые вкусные плюшки. Зачем себе отказывать в сладком? ^)

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

> Чтобы компилятор понял, что это лямбда.

а программист? не судьба была ключевое слово fun ввести например. ну да ладно.

зачем тогда там параметры указываются?

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

Специфицировать там всё равно надо. Или указать конкретные переменные или указать что можно использовать любые и как(по ссылке или значению).

Booster ★★
()

Эстетический комментарий

Представленный тут С++ код страшен. Лучше трудиться проститутом в борделе для престарелых, чем видеть этот кошмар каждый день на работе.

ugoday ★★★★★
()
Ответ на: Эстетический комментарий от ugoday

>Представленный тут С++ код страшен. Лучше трудиться проститутом в борделе для престарелых, чем видеть этот кошмар каждый день на работе.
Враньё, для непосвящённых код лиспа или хаскеля ещё более ужасен.

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

Видишь ли, то, что на лиспе, а уж тем более хаскелле делается автоматом, на С++ требует заката солнца вручную, С++ код перенасыщен прыжками и ужимками вокруг компилятора, с помощью которого кодер пытается объяснить процессору чего же он от него хочет. Всё это объективные вещи и если ты не видишь кучи лишних, специфичных для С++ действий, то это можно объяснить только профессиональной деформацией твоего сознания. Возможно позднее ты сможешь перерасти себя и будешь смеяться над своим текущим состоянием.

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

>не судьба была ключевое слово fun ввести например

И поломать уже существующие программы, использующие это слово? Да и [] мне лично понятнее.

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

Кстати, я тут немного подумал и написал таки прототип сам. Надеюсь, мысль понянта :)

#include <algorithm>
#include <iostream>
#include <cmath>
#include <list>

////////////////////// MAPCAR draft implementation for C++ /////////////////////

class nil {
};

template<class ResultItem,
         class T1,
         class T2 = nil,
         class T3 = nil,
         class T4 = nil,
         class T5 = nil>
class mapcar;

template<class ResultItem, class T1>
class mapcar<ResultItem, T1, nil, nil, nil> {
    typedef ResultItem (* functor1) (const T1 &);
    typedef typename std::list<T1> list1;
    typedef typename std::list<ResultItem> rlist;

    const list1& list_;
    functor1 functor_;

public:
    mapcar (functor1 f, const list1& l) : list_(l), functor_(f) {
    }

    rlist operator()() const {
        rlist result;
        for (typename list1::const_iterator iter = list_.begin();
             iter != list_.end();
             ++iter)
            result.push_back (functor_ (*iter));
        return result;
    }
};

template<class ResultItem, class T1, class T2>
class mapcar<ResultItem, T1, T2, nil, nil> {
    typedef ResultItem (* functor1) (const T1 &, const T2 &);
    typedef typename std::list<T1> list1;
    typedef typename std::list<T2> list2;
    typedef typename std::list<ResultItem> rlist;

    const list1& list1_;
    const list2& list2_;
    functor1 functor_;

public:
    mapcar (functor1 f, const list1& l1, const list2& l2)
        : list1_(l1),
          list2_(l2),
          functor_(f) {
    }

    rlist operator()() const {
        rlist result;
        typename list1::const_iterator iter1 = list1_.begin();
        typename list2::const_iterator iter2 = list2_.begin();
        for (;
             iter1 != list1_.end() || iter2 != list2_.end();
             ++iter1, ++iter2)
            result.push_back (functor_ (*iter1, *iter2));
        return result;
    }
};

////////////////////////////////// THE END /////////////////////////////////////


int squared (const int& val) {
    return val * val;
}

double summed (const int& v1, const double &v2) {
    return v1 + v2;
}

template <typename T>
std::ostream& operator<< (std::ostream &os, const typename std::list<T> &list) {
    for (typename std::list<T>::const_iterator iter = list.begin();
         iter != list.end();
         ++iter)
        os << *iter << " ";
    return os;
}

int main (int argc, char *argv[]) {
    std::list<int> li;
    std::list<double> ld;
    for (int i = 0;
         i < 10;
         i++, li.push_back (i), ld.push_back (sqrt (i)));

    std::cout << mapcar<int, int>(squared, li)() << std::endl
              << mapcar<double, int, double> (summed, li, ld)() << std::endl;
    return 0;
}

Примерчик был бы красивее, но у меня нет буст.лямбды на рабочей машине.

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

А, ну и вывод, да

d:/work $ ./map
1 4 9 16 25 36 49 64 81 100 
2 3.41421 4.73205 6 7.23607 8.44949 9.64575 10.8284 12 13.1623

Первая строка - квадрат каждого числа от 1 до 10, вторая - сумма каждого числа от 1 до 10 с его квадратным корнем.

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

Однако

#include <iostream>
#include <cmath>
#include <list>

//------------------------------------------------------------------------------

template<class ResultItem,
         class T1>
std::list<ResultItem> mapcar (ResultItem (*func) (const T1& t1),
                              const std::list<T1> &l1) {
    std::list<ResultItem> result;
    typename std::list<T1>::const_iterator iter = l1.begin();
    for (;
         iter != l1.end();
         ++iter)
        result.push_back (func (*iter));
    return result;
}

template<class ResultItem,
         class T1,
         class T2>
std::list<ResultItem> mapcar (ResultItem (*func) (const T1& t1, const T2& t1),
                              const std::list<T1> &l1,
                              const std::list<T2> &l2) {
    std::list<ResultItem> result;
    typename std::list<T1>::const_iterator iter1 = l1.begin();
    typename std::list<T2>::const_iterator iter2 = l2.begin();
    for (;
         iter1 != l1.end() || iter2 != l2.end();
         ++iter1, ++iter2)
        result.push_back (func (*iter1, *iter2));
    return result;
}

//------------------------------------------------------------------------------


int squared (const int& val) {
    return val * val;
}

double summed (const int& v1, const double &v2) {
    return v1 + v2;
}

template <typename T>
std::ostream& operator<< (std::ostream &os, const typename std::list<T> &list) {
    for (typename std::list<T>::const_iterator iter = list.begin();
         iter != list.end();
         ++iter)
        os << *iter << " ";
    return os;
}

int main (int argc, char *argv[]) {
    std::list<int> li;
    std::list<double> ld;
    for (int i = 0;
         i < 10;
         i++, li.push_back (i), ld.push_back (sqrt (i)));

    std::cout << mapcar<int, int>(squared, li) << std::endl
              << mapcar<double, int, double> (summed, li, ld) << std::endl;
    return 0;
}
yoghurt ★★★★★
()
Ответ на: комментарий от ugoday

Да я там натупил мальца, версию по-чотче см. выше :)

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

>нечто подобное ужосу летящему на крыльях ночи
С новым стандартом всё проще. Хотя я полностью согласен, сахарку не помешает.

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

> И поломать уже существующие программы, использующие это слово? Да и [] мне лично понятнее.

auto якобы не ломает?

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

Не стоит так распинаться. Я в курсе что существуют более удобные языки чем С++.

Booster ★★
()

удивительно что никто не знает - http://doc.qt.nokia.com/4.7/qtconcurrent.html

и map и reduce, параллельные, блокирующие и неблокирующие. а вы лисп,лисп. ниче такого там нет, в этом вашем лиспе

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