1. C++ / Говнокод #24791

    +2

    1. 1
    2. 2
    3. 3
    4. 4
    template <class F, class G>
    auto operator*(F&& f, G&& g) -> decltype(auto) {
    	return [=](auto ...args) { return f(g(args...)); };
    }

    Композиция функций

    Запостил: IBets, 21 Сентября 2018

    Комментарии (45) RSS

    • Я жду.
      Ответить
      • Чего?
        Ответить
      • Ты поосторожней со своим PHP SJW. Ато еще станешь очередными Sage Sharp (прежде известно как Sarah Sharp).
        Ответить
        • Погуглил "PHP SJW". Мне предложили поменять филиппинское песо на SJWCoin.
          Ответить
          • Гугли SJW
            Ответить
            • Так это про гламурных пиндосских пидоров? Чего ещё можно ожидать от потомков ублюдочных англосаксов...
              Ответить
          • > SJWCoin
            Итить, ита у них шо, даже валюта своя есть?
            Ответить
      • <?php
        
        function O($f, $g) {
            return function () use ($f, $g) {
                $args = func_get_args();
                return $f(call_user_func_array($g, $args));
            };
        }


        https://ideone.com/cSGHW3
        Ответить
    • Да оно даже работает: https://wandbox.org/permlink/f9kpgfqHQd5zoSIC
      Ответить
    • Хули:
      #include <stdio.h>
      
      int (*compose(int(*f)(), int(*g)()))() {
          int h(int x) { /* памагите много оргументов */
              return f(g(x));
          }
          return h;
      }
      
      int dbl(int x) {
          return x * 2;
      }
      
      int sqr(int x) {
          return x * x;
      }
      
      int main() {
      	printf("%d", compose(dbl, sqr)(5));
      	return 0;
      }

      Хули на идеоне не роботает?
      https://ideone.com/Ffcjmq
      Ответить
      • Потому что ссылаться на внутреннюю функцию снаружи — это царский метод. Функция compose возвращает указатель на трамплин, созданный в собственном стеке. После выхода из compose этот стек может повреждаться кем угодно. Ideone использует патч к компилятору типа propolice для обнаружения UB, который как раз ловит обращения к чужому стеку.
        Ответить
        • В этой статье упомянуты методы защиты от ненормативного использования стека:
          https://en.wikipedia.org/wiki/Buffer_overflow_protection
          Ответить
        • Чтобы это обойти, придётся писа́ть функцию compose, которая создаёт трамплин не в собственном стеке, а где-то ещё (в куче, но тогда после использования compose придётся кучу чистить вилкой, либо в стеке родительского контекста, в данном случае main), при этом придётся со страницы, в которой расположен трамплин, снимать защиту от исполнения кода, чтобы не сработал DEP. Будет гора некрасивого платформозависимого кода.
          Ответить
          • Ах! Какая грустная история! А в Форте я просто нопесал слово, который сконпелировал новую подпрограмму и всё. :)
            Ответить
    • Use Forth, Luke!
      https://ideone.com/Nv1RTy
      Ответить
    • Э-эх... А вот тут фрипаскаль меня расстроил:
      https://ideone.com/NBk0Re
      Ответить
      • В таком режиме даже трамплина не будет. Будет ссылка на внутреннюю функцию, которая захватит случайный аргумент из внешней функции.

        Надо компилировать с директивой {$modeswitch nestedprocvars}, тогда всё будет работать, в отличие от сишки:
        https://ideone.com/ZMFpW7

        Да, у указателя на функцию должен быть модификатор "is nested".
        Ответить
        • О! Крута! А могешь хуйнуть апиратор? А то у меня не получаиса:(
          Ответить
          • Фрипаскаль не хочет перегружать арифметические операторы для процедурных типов.

            Пытался задурить его с помощью class operator и дженериков, но что-то пока не получилось.
            Ответить
            • Подозреваю, что это ограничение ввели, чтобы не сломать операции с указателями. Нужно попытаться завернуть функции в классы.
              Ответить
              • Ну йопамать! Что же это за программирование, когда вместо того, чтобы просто что-то запрограммировать в удобном для себя виде, приходится мутить какую-то хуйню чтобы "обмануть" компилятор? Почему бы не позволить отключать все эти проверки по желанию?
                Ответить
          • Рано радовался. Пытался перекомпилировать у себя, не работает. Результат зависит от calling conventions и от состояния стека. Царский метод, короче.

            В общем, нельзя просто взять и вытащить наружу вложенную функцию. Нужно мастерить для неё окружение.

            Искать решение задачи нужно в одном из двух направлений:
            1. Городить огород из асмовставок и всего такого.
            2. Оборачивать всё в классы и решать через ООП.

            В текущей версии fpc сделать проще вряд ли получится.
            Ответить
    • def compose( f, g ):
      	return lambda x: f( g( x ) )
      
      def f(x):
      	return x + 1
      
      def g(l):
      	return len( l )
      
      compose( f, g )([1,2,3])
      Ответить
      • Ау-ууу...
        Ответить
        • Переведи на "PHP".
          Ответить
        • Нет смысла переводить. Выше уже один гость написал реализацию композиции на "PHP". Ну хотя могу попробовать перевести и эту, если интересно.
          <?php
              function compose($f, $g) {
                  return function() use($f, $g) { return $f(call_user_func_array($g, func_get_args())); };
              }
               
              $f = function($x) { return $x + 1; };
              $g = function($l) { return count($l); };
               
              echo compose($f, $g)([1,2,3]);


          https://ideone.com/gJG1aD

          Или так:

          https://ideone.com/YPq4FL
          Ответить
      • А теперь тоже самое, но f и g могут брать много аргументов.

        Можно, конечно,
        def compose2(f, g):
            return lambda *a, **kw: f(g(*a, **kw))
        но так только в g все аргументы передадутся, а f в пролёте.

        В отличие от хаскеля или даже C++, где компилятор типы проверяет, пользоваться этим говном можно только в примитивных случаях.
        Ответить
        • А вообще есть определение композиции функций нескольких аргументов?
          Ответить
        • Чому в пролёте? В пролёте только цивилизация кваргов:
          def compose2(f, g):
              return lambda *a, **kw: f(*g(*a, **kw))
          Ответить
          • > f(*g(*a, **kw))

            А теперь представим, что g возвращает список, и f принимает один аргумент — список.
            Ты всё сломал.
            Ответить
    • Эй, собака! Я засунул функцию в твою функцию, чтобы ты мог вызывать функцию, пока вызываешь функцию.
      Ответить

    Добавить комментарий