1 Punkte von GN⁺ 2024-11-11 | 1 Kommentare | Auf WhatsApp teilen

-.NET 9 enthaltene F# 9 reduziert mit Nullable Reference Types und verbesserten Compiler-Diagnosen Sicherheitsprobleme bei der C#/.NET-Interoperabilität

  • Mit .Is*-Eigenschaften für Discriminated Unions, partiellen aktiven Mustern mit bool-Rückgabe und leeren Computation Expressions wird die alltägliche F#-Syntax kompakter
  • FSharp.Core ergänzt zufallsbasierte Funktionen für Collections und Unterstützung für C#-Collection-Expressions, sodass sich immutable F#-Collections auch in anderem .NET-Code leichter verwenden lassen
  • Der Compiler macht Probleme wie falsche Attributverwendung, IL-Methoden mit mehr als 65.520 Einträgen und die Sichtbarkeit von private members früher sichtbar
  • Durch Optimierungen bei Gleichheitsprüfungen, Integer-Bereichen und List-/Array-Comprehensions werden einige Schleifen um 1,25× bis 8×, manche Array-Comprehensions um bis zu 10× schneller

F# 9 in .NET 9

  • F# 9 enthält Änderungen, die Programme sicherer, robuster und leistungsfähiger machen sollen
  • Es ist mit .NET 9 verfügbar, und das aktuelle .NET SDK kann auf der .NET-Downloadseite heruntergeladen werden
  • Die wichtigsten Änderungen wurden im F# open source code repository entwickelt

Änderungen bei den Sprachfunktionen

  • Nullable Reference Types

    • F# wurde so entworfen, dass null vermieden wird, aber bei der Nutzung mit in C# geschriebenen .NET-Bibliotheken kann null hereinkommen
    • F# 9 stellt Referenztypen, für die null zulässig ist, typsicher dar, etwa string | null
    • Wenn null in einen string eingefügt wird oder bei einem Wert vom Typ string | null direkt auf .Length zugegriffen wird, erscheint eine Warnung zur möglichen Nullbarkeit
    • Wird im Pattern Matching zuerst der null-Fall behandelt, werden spätere Bindungen als Nicht-Null-Werte behandelt
    • Um in generischem Code null zurückzugeben, ist eine Referenztyp-Einschränkung wie 'T : not struct nötig
    • Mehr dazu steht in Nullable Reference Types in F# 9
  • .Is*-Eigenschaften für Discriminated Unions

    • Discriminated Unions erhalten für jeden Fall automatisch generierte .Is*-Eigenschaften
    • Hat der Typ Contact zum Beispiel die Fälle Email und Phone, kann mit person.contact.IsEmail geprüft werden, ob ein bestimmter Fall vorliegt
    • Bisher musste man dafür Code wie match-Ausdrücke mit Email _ -> true | _ -> false schreiben
  • bool-Rückgabe bei partiellen aktiven Mustern

    • Partielle aktive Muster mussten bisher bei erfolgreichem Match Some () und bei Misserfolg None zurückgeben
    • In F# 9 ist auch eine bool-Rückgabe erlaubt
    • Im Beispiel für case-insensitive String-Matches kann das Ergebnis von String.Equals(..., StringComparison.OrdinalIgnoreCase) direkt zurückgegeben werden
  • Erweiterungsmethoden mit Argumenten werden bevorzugt

    • Einige .NET-Bibliotheken definieren Erweiterungsmethoden mit demselben Namen wie eingebaute Eigenschaften eines Typs
    • F# 9 folgt diesem Muster und wertet bei übergebenen Argumenten statt eines fehlgeschlagenen Typtests die Erweiterungsmethode aus
    • Im Beispiel kann die Erweiterungsmethode X(f: Foo, i: int) mit demselben Namen wie die Eigenschaft X von Foo in der Form f.X(1) aufgerufen werden, um Eigenschaftssetzung und Call Chaining zu kombinieren
  • Leere Computation Expressions

    • F# 9 unterstützt leere computation expressions
    • seq { } erzeugt eine leere Sequenz, und in Code wie HTML-DSLs lassen sich leere Blöcke wie p { } ausdrücken
    • Eine leere Computation Expression führt zu einem Aufruf der Zero-Methode des Builders
    • Das ist natürlicher als die bisherige Syntax builder { () }

Verbesserungen bei Hash-Direktiven und F# Interactive

  • Nicht-String-Argumente für Hash-Direktiven

    • Compiler-Hash-Direktiven erlaubten bisher nur String-Argumente in Anführungszeichen
    • In F# 9 können Argumente beliebigen Typs übergeben werden
    • So lässt sich etwa #nowarn "0070" statt #nowarn 0070 und #time "on" statt #time on schreiben
  • Erweitertes #help in F# Interactive

    • Die Direktive #help in F# Interactive zeigt im REPL Dokumentation für Objekte oder Funktionen an
    • Argumente können ohne Anführungszeichen übergeben werden
    • Zum Beispiel zeigt #help List.map;; Beschreibung, Parameter, Rückgabewert, Beispiele, den vollständigen Namen und Assembly-Informationen an
    • Mehr dazu steht im Blogbeitrag Enhancing #help in F# Interactive blog post
  • FS-Präfix bei #nowarn erlaubt

    • Bisher führte #nowarn "FS0057" trotz korrekter Warnungsnummer zum Fehler Invalid warning number 'FS0057'
    • In F# 9 wird die Warnungsnummer auch mit FS-Präfix akzeptiert
    • #nowarn 57, #nowarn 0057, #nowarn FS0057 sowie die String-Formen "57", "0057", "FS0057" funktionieren alle
    • Innerhalb eines Projekts ist es sinnvoll, denselben Stil beizubehalten

Verbesserungen bei Compiler-Sicherheit und Diagnosen

  • Warnung bei falscher Position von [<TailCall>]

    • F# 9 gibt eine Warnung aus, wenn das Attribut [<TailCall>] an einer ungeeigneten Stelle verwendet wird
    • Beispiele sind nichtrekursive Funktionen, let-gebundene Werte und rekursive let-gebundene Werte
    • Solche Attribute beeinflussen das Laufzeitverhalten zwar nicht, können Leser aber verwirren
  • Strengere Anwendung von AttributeTargets

    • Der Compiler erzwingt AttributeTargets nun korrekt für let-Werte, Funktionen, Union-Case-Deklarationen, implizite Konstruktoren, struct und class
    • Damit lassen sich unauffällige Bugs verhindern, etwa wenn in Xunit-Tests ein unit-Argument vergessen wird
    • Bisher wurde [<Fact>] let ``this test always fails`` = Assert.True(false) vom Test-Runner ignoriert, weil es keine echte Funktion war, und dotnet test lief dadurch erfolgreich durch
    • Jetzt erscheint der Fehler error FS0842: This attribute is not valid for use on this language element
  • Parser-Recovery

    • Durch Verbesserungen bei der Parser-Recovery funktionieren Werkzeuge wie Syntax Highlighting auch bei syntaktisch noch unvollständigem Code während der Bearbeitung weiter
    • Betroffen sind unter anderem unvollständige as-Muster, Object Expressions, Enum-Case-Deklarationen, Record-Deklarationen, komplexe Primary-Constructor-Muster, unresolved long identifier, leere match-Zweige sowie fehlende Union-Case-Felder und Feldtypen
  • Genauere Diagnosemeldungen und Positionen

    • F# 9 ergänzt neue Diagnosemeldungen und präzisere Diagnosepositionen
    • Dazu gehören mehrdeutige Override-Methoden in Object Expressions, abstract members in nicht-abstrakten Klassen, Eigenschaften mit demselben Namen wie Cases einer Discriminated Union, falsche Argumentanzahl bei aktiven Mustern, Unions mit doppelten Feldern sowie die gemeinsame Verwendung von use! und and! in Computation Expressions
    • Für Klassen mit mehr als 65.520 Methoden im erzeugten IL gibt es jetzt einen neuen Compile-Time-Fehler
    • Solche Klassen können von der CLR nicht geladen werden und würden sonst zu Laufzeitfehlern führen
  • Option für echte Sichtbarkeit

    • F# schreibt private members im IL traditionell als internal, sodass Nicht-F#-Projekte mit InternalsVisibleTo unangemessen auf private members in F#-Projekten zugreifen konnten
    • F# 9 bietet zur Korrektur dieses Verhaltens das Opt-in-Compiler-Flag --realsig+
    • In .fsproj kann dafür <RealSig>true</RealSig> ergänzt werden
    • So lässt sich prüfen, ob eine Lösung vom bisherigen Verhalten abhängt

Änderungen in der Standardbibliothek FSharp.Core

  • Zufallsfunktionen für Collections

    • Zu den Modulen List, Array und Seq kommen Funktionen für zufälliges Sampling und Mischen hinzu
    • Das erleichtert die Nutzung von F# in typischen Szenarien mit Zufälligkeit wie Data Science, Machine Learning oder Game Development
    • Alle Funktionen gibt es in drei Varianten
      • eine Variante mit einer impliziten, threadsicheren gemeinsamen Random-Instanz
      • eine Variante, die eine Random-Instanz als Argument annimmt
      • eine Variante, die eine benutzerdefinierte randomizer-Funktion annimmt, die float-Werte ab 0.0 und kleiner als 1.0 zurückgeben muss
    • Verfügbar sind die vier Funktionen Shuffle, Choice, Choices und Sample, jeweils in drei Varianten
    • Die vollständige Liste der Funktionen und Varianten steht in RFC #1135
  • Verhalten der einzelnen Zufallsfunktionen

    • Shuffle gibt eine neue Collection mit demselben Typ und derselben Größe zurück, deren Elemente gleichmäßig über die Länge der Collection verteilt gemischt werden
    • Für Arrays gibt es zusätzlich eine InPlace-Variante, die Elemente innerhalb des bestehenden Arrays mischt
    • Choice gibt ein einzelnes zufälliges Element mit gleichmäßiger Gewichtung über die Größe der Collection zurück
    • Choices wählt N Elemente in zufälliger Reihenfolge aus der Eingabe-Collection, wobei dasselbe Element mehrfach ausgewählt werden kann
    • Sample wählt N Elemente in zufälliger Reihenfolge aus der Eingabe-Collection aus, ohne dass dasselbe Element zweimal gewählt wird
    • Bei Sample darf N nicht größer als die Länge der Collection sein
  • Parameterloser Konstruktor für CustomOperationAttribute

    • CustomOperationAttribute erhält einen parameterlosen Konstruktor, wodurch sich benutzerdefinierte Operationen für Computation-Expression-Builder leichter erstellen lassen
    • Da der explizite Name meist ohnehin dem Methodennamen entspricht, kann statt [<CustomOperation("bar")>] nun [<CustomOperation>] verwendet werden
  • Unterstützung für C#-Collection-Expressions

    • F#-Listen und -Sets lassen sich in C# mit Collection Expressions initialisieren
    • Statt SetModule.FromArray([1, 2, 3]) kann zum Beispiel FSharpSet<int> mySet = [ 1, 2, 3 ]; geschrieben werden
    • Immutable F#-Collections sind nützlich, wenn strukturelle Gleichheit benötigt wird, die System.Collections.Immutable-Collections nicht bieten

Performance-Verbesserungen

  • Optimierung von Gleichheitsprüfungen

    • Gleichheitsprüfungen sind schneller geworden und verursachen weniger Speicherallokationen
    • Im Beispiel für die Suche eines nicht vorhandenen Werts mit Array.contains in einem Array von struct-Typen kam es bisher zu 1.000 Boxings, jetzt zu keinem mehr
    • In Benchmarks für Array-Funktionen mit einem struct mit 2 Members sank die durchschnittliche Zeit für ArrayContainsNonexisting von 5.190,95 ns auf 766,005 ns, und die Allokationen gingen von 24.000 B auf 0 zurück
    • ArrayTryFindNonexisting sank von 5.139,58 ns auf 1.140,515 ns, die Allokationen von 24.024 B auf 24 B
    • Mehr dazu steht in F# Developer Stories: How we’ve finally fixed a 9-year-old performance issue
  • Gemeinsame Feldnutzung bei struct-Discriminated-Unions

    • Wenn mehrere Cases einer struct-Discriminated Union denselben Feldnamen und denselben Typ haben, können sie denselben Speicherbereich teilen
    • Dadurch sinkt der Speicherverbrauch des struct
    • Im Beispiel ist eine struct-Discriminated Union mit gemeinsam genutzten int64-basierten Feldern 16 Byte groß
    • Eine Version im bisherigen Stil, bei der jeder Case einen eigenen Feldnamen haben musste, war 60 Byte groß
    • Da gleiche Feldnamen früher nicht erlaubt waren, gibt es keine Probleme bei der Binärkompatibilität
  • Optimierung von Integer-Bereichen

    • Der Compiler erzeugt nun in mehr Fällen optimierten Code für Ausdrücke der Form start..finish und start..step..finish
    • Bisher wurde nur optimiert, wenn der Typ int/int32 war und der Schritt den konstanten Wert 1 oder -1 hatte
    • Andere Integer-Typen und andere Schrittwerte verwendeten eine ineffiziente IEnumerable-basierte Implementierung
    • Jetzt werden all diese Fälle optimiert
    • In for … in start..finish do …, [start..step..finish] und [for n in start..finish -> f n] ergeben sich Geschwindigkeitsgewinne von 1,25× bis 8×
  • Optimierung von List- und Array-Comprehensions

    • In List- und Array-Comprehensions wird die Form for x in xs -> … optimiert
    • Besonders deutlich fällt die Verbesserung bei Arrays aus
    • Die Geschwindigkeit steigt um bis zu 10×, und die Allokationsgröße sinkt auf die Hälfte bis ein Viertel

Verbesserungen der Visual-Studio-Tools

  • Live Buffers standardmäßig aktiviert

    • Die Funktion Live Buffers in Visual Studio war zuvor optional, ist nach ausreichenden Tests nun aber standardmäßig aktiviert
    • Der Hintergrund-Compiler, der die IDE antreibt, verwendet nicht gespeicherte Dateipuffer
    • Änderungen werden damit übernommen, auch wenn die Datei noch nicht auf die Festplatte gespeichert wurde
    • Zuvor konnte es zu unerwartetem Verhalten kommen, wenn Symbole in bearbeiteten, aber noch nicht gespeicherten Dateien umbenannt wurden
  • Code Fix zum Entfernen unnötiger Klammern

    • Für unnötige Klammern bietet Visual Studio nun einen Code Fix zum Entfernen an
    • So kann etwa let f (x) = x zu let f x = x und let _ = (2 * 2) + 3 zu let _ = 2 * 2 + 3 geändert werden
    • Ziel ist es, Klammern zu reduzieren, die eher Rauschen als Klarheit erzeugen
  • Unterstützung für benutzerdefinierte Visualisierungen in F#-Projekten

    • Visual-Studio-Debugger-Visualisierungen funktionieren jetzt auch in F#-Projekten
  • Signature-Tooltip in der Mitte von Pipelines

    • Bisher wurde keine Signature Help angeboten, wenn bei einer Funktion mitten in einer Pipeline bereits komplexe curried Parameter angewendet worden waren
    • Jetzt wird ein Signature-Tooltip für den nächsten Parameter angezeigt

1 Kommentare

 
GN⁺ 2024-11-11
Hacker-News-Kommentare
  • F# war seit meiner ersten Begegnung damit an der Universität immer meine Lieblingssprache
    Bei Funktionen wie Unions, Null-Sicherheit, Pattern Matching, Records, stärkerer Typinferenz und generischen Constraints war sie C# weit voraus
    Es ist gut, dass C# diese Funktionen im Lauf der Zeit ebenfalls eingeführt hat, aber schade, dass sie auf zueinander inkompatible Weise hineingekommen sind
    Da die Investitionen in F# viel kleiner sind als in C#, ist es beim Innovationstempo zwar etwas zurückgefallen, aber es ist immer noch eine großartige Sprache, weitgehend mit dem .NET-Ökosystem kompatibel und kann dieselbe Performance wie C# mit deutlich weniger Boilerplate liefern

    • Die meisten Inkompatibilitäten lassen sich auf Source Generators und andere auf Codegenerierung basierende Tools zurückführen
      Wenn man ein zusätzliches C#-Projekt mit dem nötigen „Glue Code“ schreibt, lässt sich das ziemlich einfach handhaben
      Ich frage mich, ob es darüber hinaus konkrete Probleme gibt, die du im Sinn hast
      F# 9 unterstützt auch die Verwendung von ref struct als generische Argumente, die kürzlich zu C# hinzugefügt wurde, und soweit ich weiß, ist auch geplant, entsprechende Funktionen einzuführen, die in F# selbst definiert werden
      Bisher hat F# beim Aufholen beeindruckend gute Arbeit geleistet und verdient deutlich mehr Anerkennung
  • Die Passage „Klassen mit mehr als 65.520 Methoden im erzeugten IL führen jetzt zu einem neuen Compile-Time-Fehler. Solche Klassen können vom CLR nicht geladen werden und verursachen daher einen Runtime-Fehler“ ist kaum vorstellbar
    Wie auch immer: F# ist eine großartige Sprache
    Nach Excel scheint es mir das Zweitbeste zu sein, was Microsoft hervorgebracht hat, und es macht .NET zu einer vernünftigen Plattform

    • Ich habe das Gefühl, dass C# ziemlich unterschätzt wird
      Es ist relativ leicht Menschen beizubringen, die bereits mit JS oder TS vertraut sind, und ist eine sehr produktive Sprache
      Sie wird in vielen Kontexten eingesetzt, von Game-Engines über Enterprise-Backends bis zu Desktop-Apps
      Ich denke, Microsoft hat sich anfangs ein paar Fehltritte geleistet und dadurch das Wachstum gebremst, aber als Allzwecksprache ist sie wirklich gut und vergleichsweise leicht zu lernen
    • Ich frage mich, was du als Nachteile von F# siehst
      Ich habe vor einigen Jahren kurz mit einer leichtgewichtigen IDE namens LINQPad damit herumgespielt, aber seitdem die Vor- und Nachteile oder die Weiterentwicklung nicht weiter verfolgt
      https://www.linqpad.net/
  • Bei Phosphor haben wir über mehrere Jahre hinweg eine große Entscheidung getroffen, die Firma und die technische Richtung auf F# aufzubauen
    Nach mehr als einem Jahr des Ausprobierens haben wir die Anwendung vollständig in TypeScript und Rust neu geschrieben
    Das Produkt, das wir bauen, ist ein End-User-Programming-Tool, wodurch die traditionellen Frontend-/Backend-Grenzen verschwimmen, und das .NET-Ökosystem passte dafür nicht gut
    Ursprünglich wollten wir mit Fable F#-Code nach JS, Rust, .NET usw. kompilieren, um Typsicherheit über mehrere Technologien hinweg zu erhalten und die nötige Interoperabilität zu ermöglichen
    In der Praxis war die Interoperabilität zwischen verschiedenen Libraries viel schwieriger als erwartet, und das Verwalten und Aktualisieren der vielen Abhängigkeiten und Bindings war wirklich schmerzhaft
    Ich denke weiterhin, dass die Prämisse stimmt, dass F# schönen und effizienten Code erzeugt, aber aufgrund seines Ökosystems und Designs passt es meiner Ansicht nach nur gut zu Anwendungen mit klaren traditionellen Frontend-/Backend-Grenzen
    In so einem Fall würde man F# nur im Backend einsetzen
    Die Technologien, auf die ich mich derzeit am meisten freue, sind Effect und Moonbit, die wir intern verwenden
    Effects Schema-Library schließt viele Lücken im TS-Typsystem, und Moonbit wirkt wie ein modernes F#, das von der MS/.NET-Abhängigkeit befreit ist
    Moonbit wurde vom Erfinder von ReScript entworfen, das man als Fable für OCaml bezeichnen kann, ist sehr gut designt und kompiliert direkt zu optimiertem JS, WASM und nativer Ausgabe
    Effect nutzen wir in Produktionsumgebungen, Moonbit noch nicht, aber sein Potenzial als Sprache, die für eine AI-first-Welt entwickelt wurde, ist ziemlich beeindruckend

    • F#-Code als TypeScript-Module zu kompilieren und bereitzustellen war eine gute Erfahrung
      Die zentrale Geschäftslogik und die Validatoren haben wir in F# geschrieben, den Rest der Frontend-App in TypeScript und das Backend in C#
      Mit anderen Worten: Nur Kernlogik und Validierung lagen in F#, sämtliche Ein- und Ausgabe übernahmen TS und C#
    • Ich frage mich, ob das Unternehmen vielleicht etwas mit Darklang zu tun hat
      Ich erinnere mich, dass es ein ähnliches Produkt war und in F# geschrieben wurde, habe die jüngste Entwicklung aber nicht verfolgt
      Effect ist ziemlich gut, und ich wünschte, es gäbe so etwas auch für andere Sprachen als TypeScript
      MoonBit sieht wie eine eigene proprietäre Programmiersprache aus, daher zögere ich, statt einer bekannten Sprache dorthin zu wechseln; mich würde interessieren, wie du diesen Punkt siehst
  • Ich hatte einen Kryptografie-Kurs, in dem man jede Sprache wählen konnte, die .NET nutzt, und die Aufgabe, die ich in F# gelöst habe, war viel lesbarer als die der anderen
    Ich würde es gern häufiger verwenden, aber Data-Science-Arbeit ist fast zu 100 % Python

  • Auch F# 9 profitiert von fast allen Performance-Verbesserungen von .NET 9 selbst
    Besonders groß sind die Verbesserungen bei der Objekt-Escape-Analyse (object escape analysis)
    https://devblogs.microsoft.com/dotnet/performance-improvemen...

  • Ich vermisse die Zeit, in der ich mit F# gearbeitet habe, wirklich
    Es ist eine produktive Sprache, daher macht es schon Spaß, einfach die Updates weiterzuverfolgen
    Angesichts der Größe der Community und der gelegentlichen Gleichgültigkeit von Microsoft fand ich die Tool-Unterstützung ziemlich gut
    Das größte Ärgernis war die Genauigkeit der Code-Test-Coverage

  • Ich habe kürzlich ein wenig mit F# herumgespielt, und aus der Perspektive von jemandem, der von Python kommt, gefällt mir wirklich sehr, dass man im REPL alles Mögliche ausprobieren kann.
    Ich frage mich, ob erfahrene F#-Entwickler das auch so nutzen.
    Diesen Winter möchte ich ein kleines Web-Backend-Projekt bauen, um die Sprache und das Ökosystem besser kennenzulernen.
    Für HTTP habe ich gehört, dass Oxpecker gut sein soll; ich frage mich, ob es Empfehlungen für PostgreSQL-Clients oder -Treiber gibt.
    ORMs mag ich nicht.
    https://lanayx.github.io/Oxpecker/

    • Es gibt zwei Möglichkeiten.
      https://monazita.gitlab.io/monazita/ wurde beim Lernen von F# für persönliche Projekte erstellt; es funktioniert grundsätzlich, hat aber noch Raum für Feinschliff und ist ausschließlich für PostgreSQL gedacht.
      https://github.com/jacentino/DbFun ist ausgereifter als das erstgenannte Projekt und unterstützt mehrere Datenbanken.
    • Npgsql ist ein beliebter C#-Treiber, und es gibt auch einen F#-Wrapper.
      Dort anzufangen wäre wohl sinnvoll.
    • Als Entwickler, der mehrere Sprachen nutzt, habe ich gelegentlich Gelegenheit, F# zu verwenden, und die meisten Proofs of Concept mache ich im REPL.
      Wenn mir eine API nicht klar ist, drücke ich auch innerhalb der eigentlichen Codebasis „Send to F# interactive“, um sie im Modul auszuführen und damit zu experimentieren.
      Ich nutze es auch, um neue Libraries auszuprobieren, schnelle Benchmarks zu machen oder als Ersatz für PowerShell-Skripte.
      Mit dem Shebang #!/usr/bin/env -S dotnet fsi kann man F#-Skripte ausführbar machen; daher nutze ich es häufig als Alternative zu bash/Python für Skripte rund um .NET-Projekte, in denen das dotnet-sdk ohnehin schon installiert ist.
      Meist läuft es schneller und ist im Allgemeinen ebenso knapp.
      Mein persönlicher Eindruck ist, dass Syntax und Idiome von F# besser als C# zu REPL-Programmierung passen, bei der man kleine Code-Stücke zusammensetzt.
      C# braucht normalerweise mehr objektorientierte Struktur.
  • Ich frage mich, wie die Versionierung von F# gehandhabt wird.
    Es gibt viele Verbesserungen der Lebensqualität, die gut aussehen, aber aus Sicht von Semantic Versioning gibt es keine Breaking Changes, sodass ein Major-Version-Sprung nicht gerechtfertigt wirkt; und für ein Projekt, das kein Semantic Versioning nutzt, scheint es auch kein so großer Sprung bei den Sprachfeatures zu sein, dass man von 8 auf 9 gehen müsste.
    In einem anderen Kommentar wurde das kürzlich erschienene .NET 9 erwähnt; ich frage mich, ob es darum geht, mit den .NET-Versionsnummern Schritt zu halten.

    • .NET und C# sind seit einiger Zeit auf Releases umgestiegen, die jährlich um eine Zahl erhöht werden, und F# scheint demselben Muster zu folgen.
      Ob der Wechsel absichtlich zu dem Zeitpunkt erfolgte, an dem es mit der .NET-Version zusammenpasste, oder ob das Zufall war, weiß ich nicht.
      Zum Beispiel wurde passend zu .NET 9 C# 13 veröffentlicht.
    • Sowohl bei C# als auch bei F# bezeichnet die .NET-Version die Version der Build-Tools, die beim Ausführen von dotnet build verwendet werden.
      Dazu gehören msbuild, Compiler, NuGet-Pakete usw.
      Das F#-Team hätte zum Beispiel zwischen 8 und 9 Sprachänderungen veröffentlichen können; selbst wenn es das nicht getan hätte, hätte es aus irgendeinem Grund Compiler-Änderungen oder msbuild-Änderungen veröffentlichen können, die .NET 9 erfordern.
      Entwickler können ihren Code normalerweise einfach auf die neueste Runtime-Version anheben, sofern sie nicht darauf warten müssen, dass in der Deployment-Umgebung das neueste .NET installiert ist.
      Heutzutage ist das dank MSBuild-Änderungen zur Erstellung von self-contained Deployments seltener nötig, aber es ist gut, das zu wissen.
    • Jedes Jahr erscheint eine neue .NET-Version, und die Versionen von C# und F# werden an diese jährlichen Releases angepasst.
      C# liegt allerdings um 4 voraus.
      Ich halte Semantic Versioning ohnehin für überbewertet.
  • Ich frage mich, wie der Stand von F# als Alternative zu C# für die Entwicklung von GUI-Apps unter Windows ist.
    Außerdem interessiert mich, ob es Unternehmen gibt, die F# für solche Zwecke einsetzen.

  • Ich habe F# selbst noch nie ausprobiert, aber beim Stöbern wirkte diese Ressource hervorragend: https://fsharpforfunandprofit.com/

    • Für Leute, die F# zum ersten Mal kennenlernen, ist das tatsächlich eine der besten Websites.
      Sie ist sowohl für erfahrene C#-Entwickler als auch für Leute gut, die Programmieren noch relativ neu lernen.
      Heutzutage wird sie kaum noch aktualisiert, daher findet man dort nur schwer Diskussionen zu den neuen Features von F# 9, aber die bestehenden Artikel sind ausgezeichnet, um Konzepte wie apply und bind zu verstehen.