Perché non è comune hackerare l'applicazione di funzioni parziali in C #?

0

In molti modi C # supporta la programmazione funzionale, ma esiste una (restringente) lista di caratteristiche che si trovano comunemente in linguaggi funzionali tipicamente staticamente mancanti, come ricorsione della coda, applicazione di funzioni parziali, ecc. Di queste funzionalità mancanti, parziali l'applicazione è "inaffidabile" utilizzando le funzionalità del linguaggio esistenti, sebbene sia un po 'prolisso.

Ad esempio,

public static class Program {

    public static Func<T2, TResult> PartialApply(
        this Func<T1, T2, TResult> function, T1 arg1) {

        return t2 => function(arg1, t2);
    }

    static void Main() {

        Func<int, int, int> add = (x, y) => x + y;

        var add10 = add.PartialApply(10);

        var sum = add10(3); //Result is 13
    }
}

Funziona, anche se la mancanza di inferenza di tipo sui delegati lo rende un po 'prolisso. Tuttavia, non ricordo di aver mai visto il codice sorgente in cui C # è usato in questo modo. Ero piuttosto sorpreso che fosse assente nel il libro di Tomas Petricek , che tratta molti modi di usare C # come F #.

C'è una ragione (diversa dalla convenzione) che nessuno stia facendo questo?

Se qualcuno è interessato, qui ho creato un modello T4 in grado di generare funzioni PartialApply -type per tutti gli argomenti come è necessario semplicemente modificando un numero.

    
posta JamesFaix 28.03.2017 - 02:43
fonte

1 risposta

2

This works, although lack of type inference on delegates makes it a bit wordy.

Questo è fondamentalmente. L'applicazione parziale è meravigliosa per rendere più leggibili le espressioni che coinvolgono funzioni di ordine superiore. Ad esempio

 list.Filter(IsResident("Florida")).Map(YearsResidedIn("UnitedStates")).Sum()

Leggerebbe piuttosto bene. Al contrario

list.Filter(PartiallyApply((Func<String, Customer, bool>)IsResident, "Florida").Map(PartiallyApply((Func<String, Customer, int>)YearsResidedIn, "UnitedStates").Sum()

legge terribilmente, anzi molto peggio di

list.Filter(c => IsResident("Florida", c).Map(c => YearsResidedIn("UnitedStates", c)).Sum()

Inoltre in C # ci sono molti tipi di delegati. Quindi oltre a quello che hai definito avresti bisogno di

Func<T2, T3, TResult> PartiallyApply<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg)
Func<T3, TResult> PartiallyApply<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> func, T1 arg1, T2 arg2)

Fino a molti che puoi addormentare per scrivere più un intero set di loro per Action<> .

Fondamentalmente, C # non è stato progettato per un'applicazione parziale. Non presenta l'uso di funzioni di ordine superiore quasi così pesantemente come un linguaggio funzionale completo, non ha alcuna applicazione parziale di sintassi incorporata, ha un ampio set di tipi delegati che rende la definizione e l'uso di applicazioni parziali un dolore, e anche dopo hai definito i tuoi metodi per l'applicazione parziale, avrai qualcosa di più sintatticamente pesante e meno leggibile di una semplice espressione lambda vecchia.

    
risposta data 28.03.2017 - 06:52
fonte

Leggi altre domande sui tag