В чём крутизна "функций высшего порядка"?
От: Эйнсток Файр Мухосранск Странный реагент
Дата: 13.10.19 04:45
Оценка: :)
Вон в Си тожем можно указатель на функцию передать в качестве аргумента как параметр для другой функции. Но никто это не пиарит активно, что это якобы сверхкруто.
Re: ФВП
От: Qbit86 Кипр
Дата: 13.10.19 07:21
Оценка: 7 (1) +3
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>В чём крутизна "функций высшего порядка"?


В замыкании контекста и в частичном применении.

ЭФ>Вон в Си тожем можно указатель на функцию передать в качестве аргумента как параметр для другой функции. Но никто это не пиарит активно, что это якобы сверхкруто.


Представь, у тебя есть функция f в Си, которая приминает указатель на функцию ℝ→ℝ. Ты можешь передать туда функцию sin или cos, например: f(sin) или f(cos). Но что если тебе надо передать туда функцию ℝ→ℝ, созданную из двухаргументной функции ℝ×ℝ→ℝ путём фиксации одного её параметра? Например, f( x ↦ atan2(1.0, x) ).

То же в отношении вернуть из функции функцию. Ты можешь из сишной функции вернуть указатель, но ты не можешь внутри этой функции динамически состряпать новую функцию подходящей сигнатуры, ты можешь только вернуть какую-то статически фиксированную функцию.
Глаза у меня добрые, но рубашка — смирительная!
Re: В чём крутизна "функций высшего порядка"?
От: scf  
Дата: 13.10.19 07:30
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Вон в Си тожем можно указатель на функцию передать в качестве аргумента как параметр для другой функции. Но никто это не пиарит активно, что это якобы сверхкруто.


В композиции и типизации. Например, в C есть офигенный функциональный qsort, который является функцией высшего порядка, т.к. в него передается компаратор. Но язык недостаточно выразителен, чтобы такие конструкции использовались массово для абстрагирования кода. Корявый синтаксис указателей на функции, void* вместо типа, отсутствие лямбд, что заставляет вызывающий код создавать отдельную функцию под компаратор.

Пример на тайпскрипте:
function sort<A>(array: A[], comparator: (a: A, b: A) => boolean) { 
    ...
}

const myarray: string[] = []
function sortKey(s: string): string { ... }

sort(myarray, (a, b) => sortKey(a) < sortKey(b))
Re[2]: ФВП
От: Эйнсток Файр Мухосранск Странный реагент
Дата: 13.10.19 08:16
Оценка:
Q> Что если тебе надо передать туда функцию ℝ→ℝ, созданную из двухаргументной функции ℝ×ℝ→ℝ путём фиксации одного её параметра?

Тогда я сделаю во всех функциях первый параметр void* и буду через этот параметр передавать контекст.

А функции динамически не создаются, ведь они в коде программы все заранее написаны.
Re[3]: ФВП
От: anonymouse2 Либерал Глобалист Безбожник Трансгуманист
Дата: 13.10.19 10:01
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Тогда я сделаю во всех функциях первый параметр void* и буду через этот параметр передавать контекст.

ЭФ>А функции динамически не создаются, ведь они в коде программы все заранее написаны.

Любую программу можно написать на ассемблере и даже в машинных кодах. Зачем тогда Си?
Все это делается для большей выразительности, для исключения ошибок (чем больше компилятор может проверить — тем лучше; а void* это потеря информации о типе, компилятор там ничего не может проверить)
Нет такого преступления, на которое не пошло бы суверенное родоплеменное быдло ради продления своего бессмысленного рода и распространения своего бессмысленного генома.
Re[3]: ФВП
От: Qbit86 Кипр
Дата: 13.10.19 11:21
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>А функции динамически не создаются, ведь они в коде программы все заранее написаны.


Вполне можешь их динамически комбинировать. Например, есть набор функций (некоторые из которых игнорируют ненужный параметр или фиксируют недостающий из контекста, чтобы получить ℝ→ℝ):
Func<double, double>[] s_functions = new Func<double, double>[]
{
    Math.Cos,
    _ => DateTime.UtcNow.TimeOfDay.TotalMilliseconds,
    x => Math.Atan2(DateTime.UtcNow.TimeOfDay.TotalSeconds, x)
};


Есть ФВП, которая как получает функции, так и возвращает:
private static Func<double, double> Combine(Func<double, double> g, Func<double, double> h)
{
    return x => g(h(x));
}


Возвращает не значение скомбинированной функции в некоторой точке, а саму скомбинированную функцию. Значение для конкретного аргумента можно посчитать позже:
DateTime now = DateTime.UtcNow;
int count = s_functions.Length;
Func<double, double> g = s_functions[now.Day % count];
Func<double, double> h = s_functions[now.Hour % count];
Func<double, double> f = Combine(g, h);

Console.WriteLine(f(1729.0));


Попробуй сделать подобное на Си через указатели на функции ℝ→ℝ.

ЭФ>В чём крутизна "функций высшего порядка"?

ЭФ>Вон в Си тожем можно указатель на функцию передать в качестве аргумента как параметр для другой функции.
ЭФ>Тогда я сделаю во всех функциях первый параметр void* и буду через этот параметр передавать контекст.

В Си тоже можно динамический полиморфизм через ручные таблички виртуальных функций, в чём крутизна ООП...
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: ФВП
От: Эйнсток Файр Мухосранск Странный реагент
Дата: 13.10.19 11:26
Оценка:
Q>В Си тоже можно динамический полиморфизм через ручные таблички виртуальных функций, в чём крутизна ООП...

Gtk+ так и делает, и всё у них хорошо.
Re[5]: У Gtk+ всё хорошо
От: Qbit86 Кипр
Дата: 13.10.19 11:35
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

Q>>В Си тоже можно динамический полиморфизм через ручные таблички виртуальных функций, в чём крутизна ООП...


ЭФ>Gtk+ так и делает, и всё у них хорошо.


Поэтому можешь считать, что Си — это ООП язык с поддержкой ФВП. Я же не стремлюсь убедить лично тебя, просто привожу аргументацию в публичном обсуждении.
Глаза у меня добрые, но рубашка — смирительная!
Re[4]: ФВП
От: AlexRK  
Дата: 13.10.19 11:58
Оценка:
Здравствуйте, Qbit86, Вы писали:

Q>Например, есть набор функций (некоторые из которых игнорируют ненужный параметр или фиксируют недостающий из контекста, чтобы получить ℝ→ℝ):

Q>Попробуй сделать подобное на Си через указатели на функции ℝ→ℝ.

"Func<double, double>" — это не "ℝ→ℝ". Это "double -> double".
Re: В чём крутизна "функций высшего порядка"?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.10.19 16:05
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Вон в Си тожем можно указатель на функцию передать в качестве аргумента как параметр для другой функции. Но никто это не пиарит активно, что это якобы сверхкруто.


Как сделать на C вот это: http://blog.gandjustas.ru/2011/11/21/blog-post/ ?

Круто это когда язык позволяет такое писать.
Re: В чём крутизна "функций высшего порядка"?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 15.10.19 11:02
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Вон в Си тожем можно указатель на функцию передать в качестве аргумента как параметр для другой функции. Но никто это не пиарит активно, что это якобы сверхкруто.


Все изобретенные парадигмы программирования есть управление сложностью определенных аспектов решения.
В данном случае мы
1. конструируем функцию — параметризуем некий шаблон внешними зависимостями. При этом шаблон — это функция, параметр — снова функция.
2. абстрагируемся от этих подробностей, то есть, концентрируемся на важном с нашей точки зрения
Re[2]: В чём крутизна "функций высшего порядка"?
От: AlexRK  
Дата: 15.10.19 11:15
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>Как сделать на C вот это: http://blog.gandjustas.ru/2011/11/21/blog-post/ ?


G>Круто это когда язык позволяет такое писать.


Это нечитаемый говнокод и круто, когда язык не позволяет такое писать.
Re[3]: В чём крутизна "функций высшего порядка"?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.10.19 12:32
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, gandjustas, Вы писали:


G>>Как сделать на C вот это: http://blog.gandjustas.ru/2011/11/21/blog-post/ ?


G>>Круто это когда язык позволяет такое писать.


ARK>Это нечитаемый говнокод и круто, когда язык не позволяет такое писать.

Проблема в том, что все альтернативы "нечитаемому говнокоду" оказываются еще более нечитаемым говнокодом.
Re[4]: В чём крутизна "функций высшего порядка"?
От: AlexRK  
Дата: 15.10.19 12:37
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

G>>>Как сделать на C вот это: http://blog.gandjustas.ru/2011/11/21/blog-post/ ?


G>>>Круто это когда язык позволяет такое писать.


ARK>>Это нечитаемый говнокод и круто, когда язык не позволяет такое писать.

G>Проблема в том, что все альтернативы "нечитаемому говнокоду" оказываются еще более нечитаемым говнокодом.

Ну хз. Как по мне, вот это

void fact{int x)
{
    if (x > 1)
        return x * fact(x - 1);
    else
        return 1;
}


гораздо читаемее, чем это

var fact = Y<int>(f => x => x > 1 ? x * f(x - 1) : 1);


Re: В чём крутизна "функций высшего порядка"?
От: vsb Казахстан  
Дата: 15.10.19 12:43
Оценка:
Здравствуйте, Эйнсток Файр, Вы писали:

ЭФ>Вон в Си тожем можно указатель на функцию передать в качестве аргумента как параметр для другой функции. Но никто это не пиарит активно, что это якобы сверхкруто.


В C это неудобно. Но да, это тоже функция высшего порядка. А в чём тут пиар? Просто одна их техник функционального программирования.
Re[5]: В чём крутизна "функций высшего порядка"?
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.10.19 12:50
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, gandjustas, Вы писали:


G>>>>Как сделать на C вот это: http://blog.gandjustas.ru/2011/11/21/blog-post/ ?


G>>>>Круто это когда язык позволяет такое писать.


ARK>>>Это нечитаемый говнокод и круто, когда язык не позволяет такое писать.

G>>Проблема в том, что все альтернативы "нечитаемому говнокоду" оказываются еще более нечитаемым говнокодом.

ARK>Ну хз. Как по мне, вот это


ARK>
ARK>void fact{int x)
ARK>{
ARK>    if (x > 1)
ARK>        return x * fact(x - 1);
ARK>    else
ARK>        return 1;
ARK>}
ARK>


ARK>гораздо читаемее, чем это


ARK>
ARK>var fact = Y<int>(f => x => x > 1 ? x * f(x - 1) : 1);
ARK>


ARK>


Как ни удивительно, но сейчас можно писать даже так:
int fact{int x) => x > 1 ? x * fact(x - 1) : 1;

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

А еще можно написать так:
static void Main(string[] args)
{
  int fact (int x) => x > 1 ? x* fact(x - 1) : 1; //ОМГ Функция внутри функции, нечитаемый говнокод
  Console.WriteLine(fact(5));
}




Или создатели языка C# стремятся к повышению объема нечитаемого говнокода, или твоя оценка ситуации неверна.
Re[6]: В чём крутизна "функций высшего порядка"?
От: AlexRK  
Дата: 15.10.19 13:00
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

G>Как ни удивительно, но сейчас можно писать даже так:

G>
G>int fact{int x) => x > 1 ? x * fact(x - 1) : 1;
G>


Это гораздо лучше, чем первоначальный вариант с комбинаторами и вложенными функциями. Хотя я все равно написал бы в несколько строк.

G>Более того, такой способ написания коротких функций является рекомендуемым.


Без уточнения, что понимается под "короткой функцией", это довольно вредная рекомендация. Впрочем, чего еще ожидать от индусской компании.

G>А еще можно написать так:

G>
G>static void Main(string[] args)
G>{
G>  int fact (int x) => x > 1 ? x* fact(x - 1) : 1; //ОМГ Функция внутри функции, нечитаемый говнокод
G>  Console.WriteLine(fact(5));
G>}
G>


Функция внутри функции — это не говнокод сам по себе. А вот упакованная в 1 квадратный сантиметр не самая простая логика — это говнокод, ящетаю.

G>Или создатели языка C# стремятся к повышению объема нечитаемого говнокода, или твоя оценка ситуации неверна.


Это не все возможные варианты.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.