Herstructureren in pure functies (LINQ naar XML)

Een belangrijk aspect van pure functionele transformaties is het leren herstructureren van code met behulp van pure functies.

Notitie

De gemeenschappelijke nomenclatuur in functionele programmering is dat u programma's herstructureert met behulp van pure functies. In Visual Basic en C++ komt dit overeen met het gebruik van functies in de respectieve talen. In C# worden functies echter methoden genoemd. Voor deze discussie wordt een zuivere functie geïmplementeerd als een methode in C#.

Zoals eerder in deze sectie is vermeld, heeft een pure functie twee nuttige kenmerken:

  • Het heeft geen bijwerkingen. De functie wijzigt geen variabelen of de gegevens van een type buiten de functie.
  • Het is consistent. Op basis van dezelfde set invoergegevens wordt altijd dezelfde uitvoerwaarde geretourneerd.

Een manier om over te stappen op functioneel programmeren is om bestaande code te herstructureren om onnodige bijwerkingen en externe afhankelijkheden te elimineren. Op deze manier kunt u pure functieversies van bestaande code maken.

In dit artikel wordt besproken wat een pure functie is en wat het niet is. De zelfstudie: Inhoud bewerken in een WordprocessingML-documentzelfstudie laat zien hoe u een WordprocessingML-document bewerkt en bevat twee voorbeelden van het herstructureren van een zuivere functie.

De volgende voorbeelden contrasteren twee niet-pure functies en een zuivere functie.

Voorbeeld: Een niet-zuivere functie implementeren waarmee een statisch klasselid wordt gewijzigd

In de volgende code is de HyphenatedConcat functie geen pure functie, omdat deze het aMember statische klasselid wijzigt:

public class Program
{
    private static string aMember = "StringOne";

    public static void HyphenatedConcat(string appendStr)
    {
        aMember += '-' + appendStr;
    }

    public static void Main()
    {
        HyphenatedConcat("StringTwo");
        Console.WriteLine(aMember);
    }
}
Module Module1
    Dim aMember As String = "StringOne"

    Public Sub HyphenatedConcat(ByVal appendStr As String)
        aMember = aMember & "-" & appendStr
    End Sub

    Sub Main()
        HyphenatedConcat("StringTwo")
        Console.WriteLine(aMember)
    End Sub
End Module

In dit voorbeeld wordt de volgende uitvoer gegenereerd:

StringOne-StringTwo

Houd er rekening mee dat het niet relevant is of de gegevens die worden gewijzigd, toegang hebben public of private lid static , shared lid of exemplaarlid zijn. Een pure functie wijzigt geen gegevens buiten de functie.

Voorbeeld: Een niet-zuivere functie implementeren die een parameter wijzigt

Bovendien is de volgende versie van dezelfde functie niet puur omdat deze de inhoud van de parameter wijzigt. sb

public class Program
{
    public static void HyphenatedConcat(StringBuilder sb, String appendStr)
    {
        sb.Append('-' + appendStr);
    }

    public static void Main()
    {
        StringBuilder sb1 = new StringBuilder("StringOne");
        HyphenatedConcat(sb1, "StringTwo");
        Console.WriteLine(sb1);
    }
}
Module Module1
    Public Sub HyphenatedConcat(ByVal sb As StringBuilder, ByVal appendStr As String)
        sb.Append("-" & appendStr)
    End Sub

    Sub Main()
        Dim sb1 As StringBuilder = New StringBuilder("StringOne")
        HyphenatedConcat(sb1, "StringTwo")
        Console.WriteLine(sb1)
    End Sub
End Module

Deze versie van het programma produceert dezelfde uitvoer als de eerste versie, omdat de HyphenatedConcat functie de waarde (status) van de eerste parameter heeft gewijzigd door de Append lidfunctie aan te roepen. Houd er rekening mee dat deze wijziging zich voordoet ondanks het feit dat HyphenatedConcat de parameter call-by-value wordt doorgegeven.

Belangrijk

Als u voor verwijzingstypen een parameter op waarde doorgeeft, resulteert dit in een kopie van de verwijzing naar een object dat wordt doorgegeven. Deze kopie is nog steeds gekoppeld aan dezelfde exemplaargegevens als de oorspronkelijke verwijzing (totdat de verwijzingsvariabele is toegewezen aan een nieuw object). Aanroepen per verwijzing is niet noodzakelijkerwijs vereist voor een functie om een parameter te wijzigen.

Voorbeeld: Een pure functie implementeren

Deze volgende versie van het programma laat zien hoe u de HyphenatedConcat functie als een pure functie implementeert.

class Program
{
    public static string HyphenatedConcat(string s, string appendStr)
    {
        return (s + '-' + appendStr);
    }

    public static void Main(string[] args)
    {
        string s1 = "StringOne";
        string s2 = HyphenatedConcat(s1, "StringTwo");
        Console.WriteLine(s2);
    }
}
Module Module1
    Public Function HyphenatedConcat(ByVal s As String, ByVal appendStr As String) As String
        Return (s & "-" & appendStr)
    End Function

    Sub Main()
        Dim s1 As String = "StringOne"
        Dim s2 As String = HyphenatedConcat(s1, "StringTwo")
        Console.WriteLine(s2)
    End Sub
End Module

Nogmaals, deze versie produceert dezelfde regel uitvoer: StringOne-StringTwo. Let op: als u de samengevoegde waarde wilt behouden, wordt deze opgeslagen in de tussenliggende variabele s2.

Een benadering die zeer nuttig kan zijn, is het schrijven van functies die lokaal onzuiver zijn (dat wil zeggen dat ze lokale variabelen declareren en wijzigen), maar globaal puur zijn. Dergelijke functies hebben veel van de gewenste samenstelbaarheidskenmerken, maar vermijd enkele van de meer convolute functionele programmeeridiomen, zoals het gebruik van recursie wanneer een eenvoudige lus hetzelfde zou bereiken.

Standaardqueryoperators

Een belangrijk kenmerk van de standaardqueryoperators is dat ze worden geïmplementeerd als pure functies.

Zie Overzicht van Standard-queryoperators (C#) en Overzicht van Standard-queryoperators (Visual Basic) voor meer informatie.

Zie ook