LINUX.ORG.RU
ФорумTalks

лямбды в новых язычках - PR или реальные полезняшки?

 , ,


7

7

Народ, а поясните пожалуйста, что конкретно имеется ввиду, когда некто, описывая всякие плюшки новорожденного языка восторженно заявляет «там есть лямбды!».

Ну что есть lambda в каком-нибудь lisp я представляю и даже понимаю зачем оно и как им пользоваться. В lisp'е. А что имеется ввиду под «лямбдой» например, в C#?

Хотелось бы увидеть не только цитаты из википедии, а простенькие примеры того, как эта лямбда сильно упрощает жизнь, удобство даёт и всё такое. В виде примера кода, разумеется, с пояснениями почему тут именно лямбда крута и без неё некузяво.

Только чтобы это не было аналогом перлового однострочника типа

perl -e 'print sub{ $_[0] + $_[1]; }->(1,2)."\n";'
ибо в этом никаких новшеств и преимуществ нету.

Просто сдаётся мне что «лямбда» в нынешних сишарпах это пиарное название допотопных безымянных функций которые даже в перле есть и никаких новшеств в этом на самом деле нету.

★★★★★

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

ну зачем начинать придираться к деталям, ты так себя дискредитируешь, а не его, ну написал бы он int x =10, y;, да «обнял» бы в main - ничего бы не поменялось, все (я думаю) и так в курсе как на С выглядит программа

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

Если я себя «дискредитирую», объясняя человеку, что он не знает Си (он же, видимо, уверен, что знает), то это какое-то новое значение слова «дискредитировать», не словарное.

Когда в качестве «сравнения языков» показывают с одной стороны функцию на лиспе, а с другой — какой-то однострочный огрызок кода, который является корректным только в чьих-нибудь влажных мечтах — за такое надо бить по рукам.

А когда на просьбу доопределить неопределенные символы начинается феерия про пхп — за это можно даже ногами. :}

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

показывают с одной стороны функцию на лиспе, а с другой — какой-то однострочный огрызок кода

это и есть детали, мне, например, совершенно не интересно смотреть на то, что код завернули в функцию, переменные он «урезал» - да, нехорошо, но опять же - некритично для понимания кода

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

O(N^2) вместо O(N)? Не, ну тут даже я скажу «ненужно»

С т.з. оптимальности согласен. Вот, вариант O(N):

(defn lazy-fact-list [cur i]
  (lazy-seq (cons cur (lazy-fact-list (* i cur) (inc i)))))

(defn fact-list [n m]
  (drop n (take (inc m) (lazy-fact 1 1))))

Проверяем

(fact-list 3 6)

дает

(6 24 120 720)

А товарищи с кодом на Си ни одной полной функции не предъявили, одни куски с просьбой подставить функции из glib.

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

это и есть детали

Через эти детали виновник торжества нам показывает «простоту и элегантность» Си.

Если бы мы тут алгоритмы обсуждали, это всё были бы действительно малозначимые детали.

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

это РАБОЧИЙ КОД ВЫЧИСЛЕНИЯ ФАКТОРИАЛА.

возможно, но не на языке Си

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

А товарищи с кодом на Си ни одной полной функции не предъявили

#define M 3
#define N 6

void factorials( int* a, int m, int n ) {
    for( int i=1, f=1 ; i<=n ; f*=++i )
        if( i>=m ) *a++=f;
}

int main() {
    int a[ N-M+1 ];
    factorials( a, M, N );
}
wota ★★
()
Ответ на: комментарий от tailgunner

Еще раз: то, что ты «изобрел» - это не LINQ.

LINQ это внесение в язык конструкций для упрощения решения определенного круга задач.

Я всего лишь показал на том примере то, что ново в C# и расписывается крутыми концепциями, в других языках, благодаря простому и продуманным изначально концепции и синтаксису, легко решается прикладными программистами без изменения базового языка.

Мне уже не нравится, что есть Func и есть простые методы. Т.е. нет общего понятия ФВП, а есть отдельная новая сущность Func.

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

Да, только нахрена при этом доказательстве придумывать всякие названия типа «функторы», «монады», «лямбды» и прочие чисто умозрительные сущности сходу непонятные человеку, который имеет практический, а не теоретический интерес к теме?

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

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

LINQ это внесение в язык конструкций для упрощения решения определенного круга задач.

И ведь не поспоришь - совершенно точное высказывание. И совершенно бесполезное - слишком многое можно подверстать под «внесение в язык блабла».

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

Оно, может, и «легко», но ты своим примитивным примером этого не продемонстрировал и ссылок на LINQ в других языках не дал.

Мне уже не нравится, что есть Func и есть простые методы

И ты, конечно, можешь объяснить, в чем их различия и почему тебе не нравятся наличие двух сущностей?

tailgunner ★★★★★
()
Ответ на: комментарий от wota
#define M 3
#define N 6

void factorials( int* a, int m, int n ) {
    for( int i=1, f=1 ; i<=n ; f*=++i )
        if( i>=m ) *a++=f;
}

int main() {
    int a[ N-M+1 ];
    factorials( a, M, N );
}

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

(defn lazy-fact-list [cur i]
  (lazy-seq (cons cur (lazy-fact-list (* i cur) (inc i)))))

можно использовать для:

;; первые n элементов последовательности n!, (n+1)!, ...
(defn first-n-fact-list [n]
  (take n (lazy-fact 1 1)))

;; последовательность n!, (n+1)!, ..., m!
(defn fact-list [n m]
  (drop n (take (inc m) (lazy-fact 1 1))))

;; сумма первых m элементов последовательности n!, (n+1)!, ...
(defn sum-fact-list [m]
  (reduce + (take m (lazy-fact 1 1))))

;; сколько элементов последовательности n! меньше числа m
(defn min-n-size-fact [m]
  (count (take-while (fn [fact] (< fact m)) (lazy-fact 1 1))))

;; какой самый максимальный факториал до числа m
(defn max-fact-befor [m]
  (last (take-while (fn [fact] (< fact m)) (lazy-fact 1 1))))

и т.д.

можешь привести эти же решения на Си (хотя бы пару) с использованием твоей реализации?

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

с использованием твоей реализации?

в ней я не выносил вычисление одного факториала, как ты делал, потому предположим, что есть отдельная функция fact, если надо - приведу код, он тривиален и похож на уже приведенный

первые n элементов последовательности n!, (n+1)!,

int a[n];
factorials( a, 1, n );

последовательность n!, (n+1)!, ..., m!

int a[m-n+1];
factorials( a, n, m );

сумма первых m элементов последовательности n!, (n+1)!

int s=0;
for( int i=1 ; i<=m ; ++i, s+=fact(m) );

сколько элементов последовательности n! меньше числа m

int c=0;
for( ; fact(c+1)<m ; ++c ); 

какой самый максимальный факториал до числа m

int mx=0;
for( int i=1 ; fact(i)<m ; mx=fact(i), ++i ); 

П.С. если я какую-то задачку понял неверно - просьба сказать, я поправлю

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

Только уж тогда для честного сравнения стоит расписать лисповские lazy-seq, take, drop, count, reduce и прочие. :)

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

Оно, может, и «легко», но ты своим примитивным примером этого не продемонстрировал и ссылок на LINQ в других языках не дал.

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

И ты, конечно, можешь объяснить, в чем их различия и почему тебе не нравятся наличие двух сущностей?

Например, я реализую на C# известный метод «map», который в качестве аргументов принимает метод-преобразователь «f» и списочный объект «col». Каким типом в «mаp» мне описать этот самый параметр «f», если я в него хочу передавать как простые методы, так и эти самые Func? Можешь написать пример реализации? Например на лиспе для фвп есть одна сущность - функция и код будет выглядеть примерно так:

(defn map* [res f col]
  (if (empty? col)
    res
    (recur (conj res (f (first col))) f (rest col))))

(defn map [f col] (map* [] f col))
Ritmik
()
Ответ на: комментарий от Ritmik

На Лиспе или на Кложуре?

Clojure является современным диалектом лиспа.

Характерная неряшливость мышления. Я не спрашивал, чем является Clojure, а «современных диалектов лиспа» чуть менее, чем дофига.

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

Я продемонстрировал, что в других языках не нужен никакой LINQ для решения задач, для которых создавался LINQ

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

И ты, конечно, можешь объяснить, в чем их различия и почему тебе не нравятся наличие двух сущностей?

Например, я реализую на C# известный метод «map»

И снова ты ушел от ответа на вопрос.

Можешь написать пример реализации?

Нет. Повторяю еще раз - я не пишу на C#.

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

Находишь нужный метод, смотришь исходник по линку «Source».

я правильно понимаю, что твой код в lisp works не заработает? (не знаток лиспа)

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

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

Сделай let over lambda и будет тебе аллокация нового замыкания в куче с «кодогенерацией» (кавычки, так как это не значит, что обязательно будет дёргаться компилятор, можно аллоцировать новое на основе заранее сформированного машинного кода):

* (lambda (x) (+ x 1))

#<FUNCTION (LAMBDA (X)) {1002D942D9}>
* (defun get-closure (x) (let ((z x)) (lambda (y) (incf z y) z)))

GET-CLOSURE
* (defvar *first-closure* (get-closure 0))

*FIRST-CLOSURE*
* (defvar *second-closure* (get-closure 0))

*SECOND-CLOSURE*
* *first-closure*

#<CLOSURE (LAMBDA (Y)) {1002AE7AF9}>
* *second-closure*

#<CLOSURE (LAMBDA (Y)) {1002B48C29}>
* (funcall *first-closure* 1)

1
* (funcall *first-closure* 1)

2
* (funcall *first-closure* 1)

3
* (funcall *second-closure* 1)

1
* (funcall *second-closure* 1)

2
* (funcall *second-closure* 1)

3
* 

видим, что создаются два новых и разных (1002AE7AF9 и 1002B48C29) замыкания в куче (то есть собираемых GC). Для такого вот поведения они и должны быть разные и новые. В хаскеле, например, с иммутабельностью весь чистый код подвергается lambda liftingу и интенсивному inliningу, так что до рантайма не доживают ни лямбды (т.к. нет fixpoint оператора), ни замыкания (которых в чистом коде вообще нет) - только CAFs которые довольно легко статически компилировать. Реальные замыкания как в лиспе (= новые, каждый раз разные, в куче, собираемые GC) там возникнут только если их явно сделать через IO (с лямбдами с мутабельностью и IO lambda liftingу уже не справиться).

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

Радоваться же надо, что код лишний раз в рантайме не генерируется (нет зависимости от компилятора, накладных расходов на тяжёлую генерацию и т.п.).

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 2)
Ответ на: комментарий от Stanson

Хоть одна лямбда в каком-нибудь языке возвращает ли реально _функцию_?

Вопрос в каком языке не возвращает. Ну в си. В С++ что-то мутят потихоньку в новых стандартах на тему настоящих замыканий. Про функциональщину даже говорить не приходится.

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

На Лиспе или на Кложуре?

Clojure является современным диалектом лиспа.

Характерная неряшливость мышления. Я не спрашивал, чем является Clojure, а «современных диалектов лиспа» чуть менее, чем дофига.

Какой вопрос, такой ответ. Если расписать твой оригинальный вопрос, то он будет звучать так: На семействе языков лисп или на представителе данного семейства? Четкость мышления безупречная, неправда ли?

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

Например, я реализую на C# известный метод «map», который в качестве аргументов принимает метод-преобразователь «f» и списочный объект «col». Каким типом в «mаp» мне описать этот самый параметр «f», если я в него хочу передавать как простые методы, так и эти самые Func? Можешь написать пример реализации?

Можно передавать любой метод с сигнатурой, совпадающей с Func.

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var list1 = Enumerable.Range(1, 10).ToList();

            var list2 = MyMap(x => x.ToString(), list1);
            var list3 = MyMap(MyToString, list1);

            Console.WriteLine("list2:");
            foreach(var i in list2)
                Console.Write("{0} ", i);

            Console.WriteLine(Environment.NewLine + "list3:");
            foreach(var i in list3)
                Console.Write("{0} ", i);

            Console.ReadKey();
        }

        private static IList<TOut> MyMap<TIn, TOut>(Func<TIn, TOut> f, IList<TIn> list)
        {
            var result = new List<TOut>(list.Count);
            foreach(var i in list)
                result.Add(f(i));
            return result;
        }

        private static string MyToString(int elem)
        {
            return elem.ToString();
        }
    }
}

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

нахрена при этом доказательстве придумывать всякие названия типа «функторы», «монады», «лямбды» и прочие чисто умозрительные сущности сходу непонятные человеку

Тут я полностью поддержу тебя, настоящие мужики понимают «вот та херовина ебашит эту и срет в стек» без всякой этой метросексуальщины.

Постой, я сказал метро... OSHI~!

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

Я не спрашивал, чем является Clojure, а «современных диалектов лиспа» чуть менее, чем дофига.

Какой вопрос, такой ответ

Не, вопрос был нормальный... а вот ответ - говно.

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

lisp works --- это только CL.

я понимаю, потому и спросил - т.к. он до этого посчитал использование glib недопустимым, получается, что он считает написание кода под Clojure более «каноничным» и переносимым чем простое использование библиотеки под стандартный С

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

Да я знаю где смотреть. Просто пример на С - самодостаточен, а в примере на lisp используются заранее написанные функции.

Это я не к тому, что lisp плохой, а к тому, что далеко не всё так радужно как выглядит :)

На сях тоже запросто можно написать что-то типа

reduce( "+", (take(m, fact(n+m)));
Но функциональщик тут же начнёт вопить «а распиши код reduce!!!». :)

Тащемта lisp офигенный язык для мелких однокристалок и всякого такого простого embedded, например. Был бы, если бы его не маргинализировали функциональщики со своими понятиями и матаном. В результате мы лишились замечательного простого и удобного ширпотребного языка.

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

П.С. если я какую-то задачку понял неверно - просьба сказать, я поправлю

Если ты распишешь как функцию каждое решение, как ты сделал для предыдущей задачи, то будет видно, что нет повторно используемого кода и в каждой функции будет дублирование кода, отвечающего за алгоритм генерации последовательности n!

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

«возвращаемая функция» - это новый код для процессора, которого не существовало в при старте программы ни в каком виде или всякая хренота типа указателей, как обычно?

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

написание кода под Clojure более «каноничным»

Не очень понимаю твою позицию. Есть языковое семейство: Lisp. У него есть разные диалекты, в частности: CL и Clojure. Оба эти дилекта совершенно равноправны. И ни один не каноничнее другого.

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

Не, вопрос был нормальный... а вот ответ - говно.

Значит, вопрос "(Написано) на семействе языков лисп или на представителе данного семейства?" является нормальным. Ок.

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

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

и что? Ты же вроде не веруешь в Святого Патрега или в Святого Марка?

После чего ты съехал с темы и начал что-то беспомощно лепетать про пхп.

почему «беспомощно», если я предоставил РАБОЧИЙ код?

С чего бы это вдруг? Неужели так сложно привести полный исходник на си? Может ты чего-то опасаешься? О чем-то подозреваешь, да?

да. Опасаюсь. Потому-как задача была изначально «посчитать факториал». А вы мне 100500 условий поставили. Списки какие-то, функции... Хрен его знает, что вам ещё захочется? Факториал считается. Факториалы от 2х до 5и - тоже. Что вам ещё надо-то?

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

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

там просто будет добавлен заголовок функции + return результата, мне очень лень это делать )

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

Неужели не компилируется? Видимо, что-то случилось, да?

ясное дело - не компилируется. А ты что хотел? Ну вот тебе вот так вот:

$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
x=10
for(y=1;x;x--)y*=x
y
3628800
ещё вопросы?

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

Слушай, а ты кем работаешь? Если программистом, то твои работодатели в курсе, что ты ни ухом, ни рылом в предмете?

А ты? Ты думаешь,что строчки типа int main(void){ return 0; } что-то ВЫЧИСЛЯЮТ? Редкий образчик погромиста-ГСМ...

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

Есть языковое семейство: Lisp. У него есть разные диалекты, в частности: CL и Clojure. Оба эти дилекта совершенно равноправны. И ни один не каноничнее другого.

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

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

Когда в качестве «сравнения языков» показывают с одной стороны функцию на лиспе, а с другой — какой-то однострочный огрызок кода, который является корректным только в чьих-нибудь влажных мечтах

вообще-то этот «огрызок» вырезал из вполне рабочего кода. Только кроме этих двух строк ВСЁ остальное в нём и так очевидно, может тебе полный текст <stdio.h> предоставить?

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

Значит, вопрос "(Написано) на семействе языков лисп или на конкретном представителе данного семейства?" является нормальным. Ок.

fixed

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

Можно передавать любой метод с сигнатурой, совпадающей с Func.

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var list1 = Enumerable.Range(1, 10).ToList();

            var list2 = MyMap(x => x.ToString(), list1);
            var list3 = MyMap(MyToString, list1);

            Console.WriteLine("list2:");
            foreach(var i in list2)
                Console.Write("{0} ", i);

            Console.WriteLine(Environment.NewLine + "list3:");
            foreach(var i in list3)
                Console.Write("{0} ", i);

            Console.ReadKey();
        }

        private static IList<TOut> MyMap<TIn, TOut>(Func<TIn, TOut> f, IList<TIn> list)
        {
            var result = new List<TOut>(list.Count);
            foreach(var i in list)
                result.Add(f(i));
            return result;
        }

        private static string MyToString(int elem)
        {
            return elem.ToString();
        }
    }
}

<offtopic>Во-первых, спасибо огромное за пример. Очень интересно было посмотреть в независимости от сабжа разговора.</offtopic>

Возникают два вопроса, которые показывают недостатки, про которые я упоминал здесь лямбды в новых язычках - PR или реальные полезняшки? (комментарий)

1. Я не могу в твою реализацию мапа (MyMap) передать, простой метод, например метод класса String «length()» для подсчета строк в списке слов? Согласись, это большой недостаток.

2. Не находишь, что реализация немного длиннее, чем это

(defn map* [res f col]
  (if (empty? col)
    res
    (recur (conj res (f (first col))) f (rest col))))

(defn map [f col] (map* [] f col))

Который к тому же не делает исключений для функций, т.к. функции в языке не разделены искусственно на функторы и прочие.

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

видим, что создаются два новых и разных (1002AE7AF9 и 1002B48C29) замыкания в куче

Вопрос что именно в куче лежит - код получившийся (по замыслу) новой функции или же некий стандартный код для реализации нужного поведения который в итоге обращается к коду в 1002D942D9.

Радоваться же надо, что код лишний раз в рантайме не генерируется (нет зависимости от компилятора, накладных расходов на тяжёлую генерацию и т.п.).

Согласен, возможно это была бы тяжёлая фишка, но потенциальные возможности оной могли бы быть полезными.

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

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

переменные он «урезал» - да, нехорошо, но опять же - некритично для понимания кода

не урезал. код работает с любыми переменными в заданном диапазоне. (с FP зависнет на дробных, но факториал и не определён для дробных. Это не гамма-функция). x - это входная переменная, а y выходная. Разве это так сложно понять?

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

Если бы мы тут алгоритмы обсуждали, это всё были бы действительно малозначимые детали.

а что мы тут обсуждаем? я думал «простоту и элегантность ИП по сравнению с ФП». Точнее кривизну ИП в окружении ФП и наоборот (см. сабж и первый пост). А сишечку я взял ТОЛЬКО потому, что её все знают.

Ты хочешь поговорить именно о C vs CL? так и скажи.

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

я понимаю, потому и спросил - т.к. он до этого посчитал использование glib недопустимым, получается, что он считает написание кода под Clojure более «каноничным» и переносимым чем простое использование библиотеки под стандартный С

Мимо. Все приведенные примеры на clojure переносимы и по-умолчанию будут компилиться и работать и под маком, и под линуксом, и под виндой. В отличии.

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

1. Я не могу в твою реализацию мапа (MyMap) передать, простой метод, например метод класса String «length()» для подсчета строк в списке слов? Согласись, это большой недостаток.

Нет в C# метода String.length(), Length - это Property. А так, любой метод можно передать без проблем:

var list4 = MyMap(string.IsNullOrEmpty, list); // список bool

2. Не находишь, что реализация немного длиннее, чем это

(defn map* [res f col]
  (if (empty? col)
    res
    (recur (conj res (f (first col))) f (rest col))))

(defn map [f col] (map* [] f col))

Реализация непосредственно map - это те же 6 строк:

private static IList<TOut> MyMap<TIn, TOut>(Func<TIn, TOut> f, IList<TIn> list)
{
     var result = new List<TOut>(list.Count);
     foreach(var i in list)
         result.Add(f(i));
     return result;
}
К тому же C# - статически типизированный язык, здесь много место занимает описание сигнатур. Для протокола: факт что в функциональных языках объем кода, как правило, меньше чем в императивных я не оспариваю.

Который к тому же не делает исключений для функций, т.к. функции в языке не разделены искусственно на функторы и прочие.

В C# есть делегаты, все операции где функции передаются как параметры или возвращаются как результат работы другой функции, оперируют делегатами.

// определение типов которые можно использовать в качестве сигнатур аргуметов функций
delegate TOut MyFunc<TIn, TOut>(TIn x);
delegate void MyAction<TIn>(TIn x);
Func, Action - это просто предопределенные в библиотеке делегаты, для удобства. Во всех случаях где используются делегаты можно передавать любой метод с совпадающей сигнатурой.

encyrtid ★★★★★
()
Последнее исправление: encyrtid (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.