Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 18, средняя оценка - 4.78
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
#1

Каррирование или карринг - C++

23.02.2012, 00:38. Просмотров 2484. Ответов 12
Метки нет (Все метки)

Определение с вики какое-то мутное, кто может объясните пожалуйста поподробнее - что это, для чего и когда применять.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.02.2012, 00:38
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Каррирование или карринг (C++):

For_each, итераторы, каррирование, шаблоны - C++
Прошу объяснить доступным языком либо дать ссылку на соответствующий материал. 1. Как реализовать алгоритм for_each? 2. Как написать...

каррирование - Lisp
Читаю про каррирование. Почему не работает код из Википедии?: CL-USER 11 > (defun curry(x) (lambda (y) (+ x y))) CURRY...

Для чего нужно каррирование? - F#
Добрый день. Я начал изучать язык F#, дошел до такой фишки как каррирование, вроде понял, что это такое - применение аргументов по одному....

Каррирование, как запомнить предыдущий результат - JavaScript
function sum(a) { var currentSum = a; function f(b) { currentSum += b; return f; } f.toString =...

Каррирование: что дает, как применять, где использовать? - Haskell
Здравствуйте! Начал изучать Haskell. С одной стороны формулировку каррирования я понял. f : (x,y) -> z эквивалентно f: x->y->z...

Для чего применяется Каррирование в языках высокого уровня? - Haskell
Добрый день, гуру функционального программирования! Ввиду большого интереса к теории компиляции и в своё время(на 2ом курсе) утраченной...

12
Евгений М.
1036 / 977 / 54
Регистрация: 28.02.2010
Сообщений: 2,829
Завершенные тесты: 2
23.02.2012, 08:49 #2
Насколько я понял по википедии - это функция внутри функции.
1
samdavydov
60 / 21 / 2
Регистрация: 23.02.2012
Сообщений: 36
23.02.2012, 09:12 #3
Есть функция с n аргументами.
Карринг - преобразание одного вызова с n аргументами в n вызовов с одним аргументом.

Карринг популярен в динамических языках, где функция является присваиваемым объектом.

Функция является присваиваемым объектом, если я могу записать нечто вроде a = x*x, потом вызвать a(5) и получить 25.

Каррингом можно "замораживать" аргументы.

Пусть есть функция inc(a, b), которая увеличивает a на b.

Я могу сделать так (пример на python):

Python
1
2
3
4
5
def binary(f, arg): # f - функция от двух аргументов, arg - число
    return lambda x : f(x, arg) # вернуть функцию, где вместо второго аргумента всегда стоит число
 
a = binary(lambda x, y : x + y, 5) # в функции x + y забить на место второго аргумента число 5 
print a(7) # Теперь а - функция, увеличивающая чило на 5. x + 5 -> 7 + 5 == 12
Запись "lambda x : ..." означает, что я определяю функцию, принимающую x.
lambda x, y : x + y -> функция, принимающая x и y, и складывающая их.

____________
zmartzoft.ru
2
diagon
Higher
1930 / 1196 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
23.02.2012, 09:19 #4
Тоже наткнулся на эту статью в вики. Единственное применение, которое я ей нашел - Написать программу чтобы выводила надпись Hello world
Ну и насколько я понял, это просто способ писать вместо
C++
1
foo(1, 2, 3)
более извращенный вариант
C++
1
foo(1)(2)(3);
1
Nameless One
Эксперт С++
5775 / 3425 / 255
Регистрация: 08.02.2010
Сообщений: 7,448
23.02.2012, 09:57 #5
Каррирование — это практика, которая позволяет (в основном, в функциональных ЯП) на основе более общих функций строить их частные версии, фиксируя значения части их аргументов. Основное использование — для передачи в функции высшего порядка. Можно использовать в языках с полноценными замыканиями (т.е. в С не получится, но в C++ можно использовать для этих целей лямбды), либо с помощью костылей (функциональные адаптеры в C++).
1
Nameless One
Эксперт С++
5775 / 3425 / 255
Регистрация: 08.02.2010
Сообщений: 7,448
23.02.2012, 10:40 #6
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Возьмем такой гипотетический пример: у нас есть функция map_list, которая принимает список (массив) и одноместную функцию и применяет эту функцию к каждому элементу массива. Есть функция plus, которая возвращает сумму двух чисел. Определить функцию, которая будет увеличивать каждый элемент списка на 3, с использованием вышеопределенных функций.
Решение с C (без каррирования):
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#include <stdlib.h>
 
void map_list(int* array, size_t size, int (*pfunc) (int))
{
    size_t i;
 
    for(i = 0; i < size; ++i)
    array[i] = pfunc(array[i]);
}
 
int plus(int a, int b)
{
    return a + b;
}
 
int plus_3(int a)
{
    return plus(a, 3);
}
 
int main(void)
{
    size_t i;
    int array[5] = {1,2,3,4,5};
            
    map_list(array, 5, plus_3);
 
    for(i = 0; i < 5; ++i)
    printf("%d\n", array[i]);
 
    exit(0);
}
Решение на C++ (каррирование через лямбды):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
void map_list(int* arr, size_t size, int (*pfunc) (int))
{
    size_t i;
 
    for(i = 0; i < size; ++i)
    arr[i] = pfunc(arr[i]);
}
 
int plus(int a, int b)
{
    return a + b;
}
 
int main()
{
    int arr[5] = {1,2,3,4,5};
    
    map_list(arr, 5, [=](int a){return plus(a, 3);});
    
    for(size_t i = 0; i < 5; ++i)
    std::cout << arr[i] << std::endl;
}
Решение на C++ («каррирование» через функциональные адаптеры):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <functional>
 
template <typename PFUNC>
void map_list(int* arr, size_t size, PFUNC pfunc)
{
    size_t i;
 
    for(i = 0; i < size; ++i)
    arr[i] = pfunc(arr[i]);
}
 
int plus(int a, int b)
{
    return a + b;
}
 
int main()
{
    int arr[5] = {1,2,3,4,5};
    
    map_list(arr, 5, std::bind1st(std::ptr_fun(plus), 3));
    
    for(size_t i = 0; i < 5; ++i)
    std::cout << arr[i] << std::endl;
}
Common Lisp:
Lisp
1
2
3
4
5
6
7
8
(defun map_list (fun list)
  (reduce (lambda (item acc)
        (cons (funcall fun item) acc))
      list :from-end t :initial-value nil))
 
(defun plus (a b) (+ a b))
 
(format t "~{~d~%~}" (map_list (lambda (a) (plus a 3)) '(1 2 3 4 5)))
Haskell (все функции уже автоматически каррированы, т.е. для того, чтобы получить специализированную версию функции, нужно просто передать ей первые несколько аргументов):
Код
import System.IO (print)
import Control.Monad (mapM_)

map_list :: (a -> b) -> [a] -> [b]
map_list f = foldr (\item acc -> f item : acc) []

plus :: Integral a => a -> a -> a
plus = (+)

main :: IO ()
main = mapM_ print $ map_list (plus 3) [1,2,3,4,5]
Питон:
Python
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python3
 
def map_list(fun, lst):
    for i in range(len(lst)):
        lst[i] = fun(lst[i])
    return lst
 
def plus(a, b):
    return a + b
 
print(*map_list(lambda a: plus(a, 3), [1,2,3,4,5]), sep='\n')
PS. в C++, CL, Haskell, Python уже есть функции, аналогичные map_list
6
Mayonez
380 / 272 / 21
Регистрация: 26.12.2009
Сообщений: 875
23.02.2012, 11:09 #7
[

Не по теме:

b]Nameless One[/b], вы сами написали все эти примеры?

0
Nameless One
23.02.2012, 11:09
  #8

Не по теме:

Mayonez, да, а что такое?

0
Mayonez
23.02.2012, 11:11
  #9

Не по теме:

круто, знать на таком уровне столько языков

0
Nameless One
23.02.2012, 11:12
  #10

Не по теме:

Mayonez, это уровень Helloworld'ов

0
Mayonez
23.02.2012, 11:20
  #11

Не по теме:

Nameless One, я понимаю вашу иронию: чем дольше изучаю с++, тем больше понимаю, что знаю я очень мало, но согласитесь, надпись у вас в статусе "Эксперт C++" все же о чем то говорит (не просто об умении написать hello world)

0
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
23.02.2012, 11:52  [ТС] #12
То есть, как я понял, каррирование это использование функции с несколькими аргументами(часть которых мы задаём заранее не переделывая основную функцию, но задавая её частную версию), как аргумента функции высшего порядка?
0
Nameless One
Эксперт С++
5775 / 3425 / 255
Регистрация: 08.02.2010
Сообщений: 7,448
23.02.2012, 11:56 #13
Whiteha, можно сказать и так, правда, не обязательно "как аргумента функции высшего порядка" (хотя это и наиболее частый случай использования каррированных функций).
1
23.02.2012, 11:56
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.02.2012, 11:56
Привет! Вот еще темы с ответами:

Intel или AMD? R9-290 GAMING 4G или N780 или SLI? Комп за овер 50к - Игровой компьютер
Комп нужен для ИГР на 5лет примерно! 1) Смысл поста в том чтобы собрать системник чтоб каждая запчасть работала на все 100%, то есть...

Можно ли по названию платы,или по чипу,или по соккету,определить,поддерживает плата ХР или нет? - Материнские платы
Добрый день всем.Уважаемые знатоки,я заранее прошу у Вас прощенья,если заданный мной вопрос,тупой или глупый. Но поверьте,я уже замучился...

Получить из строки всё до пробела или запятой или точки или восклицательного знака - C#
Match m_ = Regex.Match(вопрос, @&quot;Кто такой.(.{5})&quot;, RegexOptions.IgnoreCase | RegexOptions.Multiline); ...

По введённой букве определить её характеристики: большая или маленькая, гласная или согласная, звонкая или глухая и т.д - VBA
По введённой букве определить её характеристики: боль-шая или маленькая, гласная или согласная, звонкая или глухая и т.д.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru