Documenting the available .NET standard formats of .ToString(fmt) with a small F# code snippet

Inspired by ploeh’s stringf

Listing all standard formats of .ToString for DateTime with

1: 
let dateFormats = docuPrint DateTime.Now

that results in the following, where you can pick your favorite format easily.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
('M', "08 Mai")
('m', "08 Mai")
('d', "08.05.2015")
('g', "08.05.2015 19:03")
('G', "08.05.2015 19:03:24")
('t', "19:03")
('T', "19:03:24")
('u', "2015-05-08 19:03:24Z")
('s', "2015-05-08T19:03:24")
('O', "2015-05-08T19:03:24.8516093+02:00")
('o', "2015-05-08T19:03:24.8516093+02:00")
('D', "Freitag, 8. Mai 2015")
('U', "Freitag, 8. Mai 2015 17:03:24")
('f', "Freitag, 8. Mai 2015 19:03")
('F', "Freitag, 8. Mai 2015 19:03:24")
('R', "Fri, 08 May 2015 19:03:24 GMT")
('r', "Fri, 08 May 2015 19:03:24 GMT")
('Y', "Mai 2015")
('y', "Mai 2015")

The main logic is this simple, we try all single char formats on the given type.
Yes it’s a generic function, because of the inline.

1: 
2: 
3: 
let inline getAllFormatSpecifier someType =
    ['A' .. 'Z'] @ ['a' .. 'z']  
    |> List.choose (exToOption (tupleTee (string >> flip stringf someType))) 

It’s signature look like this

1: 
2: 
3: 
val inline getAllFormatSpecifier :
  someType: ^a -> (char * string) list
    when  ^a : (member ToString :  ^a * string -> string)

Here is how to read this nice function composition from left to right:

  1. List.choose keeps only Some‘s
  2. The Some comes from exToOption that converts exceptions to None and successful results to Some
  3. tupleTee keeps the input of the function togehter with the result of the function as a tuple
  4. string converts a character from the concatinated lists ['A' .. 'Z'] @ ['a' .. 'z'] to a string to fit the stringf
  5. and finally the parameter order needs to be exchanged with flip and go into stringf with the given someType

The full code

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
104: 
105: 
106: 
107: 
108: 
109: 
110: 
111: 
112: 
113: 
114: 
115: 
116: 
117: 
118: 
119: 
120: 
121: 
122: 
123: 
124: 
125: 
126: 
127: 
128: 
129: 
130: 
131: 
132: 
133: 
open System

// http://blog.ploeh.dk/2015/05/08/stringf/
let inline stringf format (x : ^a) = 
    (^a : (member ToString : string -> string) (x, format))

let flip f a b = f b a
let tupleTee f x = x, f x
let exToOption f x = try Some(f x) with _ -> None

// function composition in F# is awesome !
let inline getAllFormatSpecifier someType =
    ['A' .. 'Z'] @ ['a' .. 'z']  
    > List.choose (exToOption (tupleTee (string >> flip stringf someType))) 

// print it nice to choose one
let inline docuPrint x =
    x
    |> getAllFormatSpecifier
    |> List.sortBy snd              
    |> List.iter (printfn "%A")

let dateFormats = docuPrint DateTime.Now
(*
('M', "08 Mai")
('m', "08 Mai")
('d', "08.05.2015")
('g', "08.05.2015 19:03")
('G', "08.05.2015 19:03:24")
('t', "19:03")
('T', "19:03:24")
('u', "2015-05-08 19:03:24Z")
('s', "2015-05-08T19:03:24")
('O', "2015-05-08T19:03:24.8516093+02:00")
('o', "2015-05-08T19:03:24.8516093+02:00")
('D', "Freitag, 8. Mai 2015")
('U', "Freitag, 8. Mai 2015 17:03:24")
('f', "Freitag, 8. Mai 2015 19:03")
('F', "Freitag, 8. Mai 2015 19:03:24")
('R', "Fri, 08 May 2015 19:03:24 GMT")
('r', "Fri, 08 May 2015 19:03:24 GMT")
('Y', "Mai 2015")
('y', "Mai 2015")
*)

let timespanFormats = docuPrint <| TimeSpan(1, 2, 3)
(*
('T', "01:02:03")
('c', "01:02:03")
('t', "01:02:03")
('G', "0:01:02:03.0000000")
('g', "1:02:03")
*)

// be caereful, it rounds
let floatFormats = docuPrint 0.425      
(*
('G', "0.425")
('R', "0.425")
('g', "0.425")
('r', "0.425")
('F', "0.43")
('N', "0.43")
('f', "0.43")
('n', "0.43")
('E', "4.250000E-001")
('e', "4.250000e-001")
('P', "42.50%")
('p', "42.50%")
('C', "Fr. 0.43")
('c', "Fr. 0.43")
*)

// be caereful, it rounds
let decimalFormats = docuPrint 0.425m
(*
('G', "0.425")
('g', "0.425")
('F', "0.43")
('N', "0.43")
('f', "0.43")
('n', "0.43")
('E', "4.250000E-001")
('e', "4.250000e-001")
('P', "42.50%")
('p', "42.50%")
('C', "Fr. 0.43")
('c', "Fr. 0.43")
*)


let intFormats = docuPrint 42   
(*
('X', "2A")
('x', "2a")
('P', "4'200.00%")
('p', "4'200.00%")
('E', "4.200000E+001")
('e', "4.200000e+001")
('D', "42")
('G', "42")
('d', "42")
('g', "42")
('F', "42.00")
('N', "42.00")
('f', "42.00")
('n', "42.00")
('C', "Fr. 42.00")
('c', "Fr. 42.00")
*)


let bigIntFormats = docuPrint 42I
(*
('X', "2A")
('x', "2a")
('P', "4'200.00%")
('p', "4'200.00%")
('E', "4.200000E+001")
('e', "4.200000e+001")
('D', "42")
('G', "42")
('R', "42")
('d', "42")
('g', "42")
('r', "42")
('F', "42.00")
('N', "42.00")
('f', "42.00")
('n', "42.00")
('C', "Fr. 42.00")
('c', "Fr. 42.00")
*)
val dateFormats : obj

Full name: DocumentingToString.dateFormats
val getAllFormatSpecifier : someType:'a -> 'b list

Full name: DocumentingToString.getAllFormatSpecifier
val someType : 'a
Multiple items
module List

from Microsoft.FSharp.Collections

——————–
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val choose : chooser:('T -> 'U option) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.choose
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

——————–
type string = System.String

Full name: Microsoft.FSharp.Core.string
Multiple items
val char : value:'T -> char (requires member op_Explicit)

Full name: Microsoft.FSharp.Core.Operators.char

——————–
type char = System.Char

Full name: Microsoft.FSharp.Core.char
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
namespace System
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
val sortBy : projection:('T -> 'Key) -> list:'T list -> 'T list (requires comparison)

Full name: Microsoft.FSharp.Collections.List.sortBy
val snd : tuple:('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd
val iter : action:('T -> unit) -> list:'T list -> unit

Full name: Microsoft.FSharp.Collections.List.iter
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn

Sie wenden Flow Design in C# an?

Flow Design entspricht  eigentlich der Denkweise von Funktionaler Programmierung, es gibt Funktionen mit Input und Output, die Anzahl von Input und Output kann beliebig sein und damit man kann die Funktionen verbinden. Am besten stellt man sich das als eine Elektrische Verdrahtung vor. Die Daten fließen durch die Funktionen, werden also transformiert und nicht in einer Objekt-Daten-Kapsel mutiert, was es einfacher macht gedanklich den Überblick zu behalten, einfacher zu Testen ist und auch die Skalierbarkeit (Stichwort Multicore) ist so einfach möglich (ohne die Gefahr von Deadlocks). In F# wird ihnen auffallen, dass die ganzen Objekt-Konstrukte die man für Flow Design aufbauen muss, hinfällig werden und im Code am ehesten den Diagrammen entspricht. Die Verdrahtung (wiring) kann viel eleganter mit dem F# Pipe Operator (|>) gemacht werden.
Daten |> Validierung |> Auswertung
Der Datenfluss erfolgt in Pfeil |> Richtung. Man kann den Flow auch untereinander schreiben.
Daten
|> Validierung
|> Auswertung
So fließen die Daten durch die Funktion Validierung dann die Funktion Auswertung. Und ob alles auch zusammen passt, das sagt ihnen der Compiler bevor es evtl. zu Laufzeitfehlern kommt. Eine Cheat-Sheet zu Flow-Design findet sich hier.

Fazit

Wer Flow Design anwendet, kann sich viel Arbeit in der Codierung ersparen und gleichzeitig die Qualität (Korrektheit, Lesbarkeit, Wartbarkeit) des Codes erhöhen, wenn man diesen mit F# implementiert.

Die Strukturierung von F# Quellcode

F# Code ist sehr kompakt, weil unnötiges und redundantes entfällt. Kurz gesagt, keine ; { } und keine Typen Deklaration. So, nun im Detail alles der Reihe nach:

Keine ;

Das Ende einer Code-Zeile mit ; abzuschliessen ist in F# nicht nötig. Man kann, sieht dann aber aus wie umgewandelter C# oder C++ Code. ; werden verwendet um Aufzählungen von Records, Listen, Arrays etc. zu trennen. Wobei man auch hier, bei nur einem Element pro Zeile den ; nicht zu schreiben braucht.
1: 
2: 
3: 
4: 
5: 
6: 
7: 
let xs = [ 1; 2; 3 ] 
let xs = 
       [ 
        1
        2
        3
       ]

Keine {}

F# Code kommt ohne Code Blöcke aus die in geschweifte Klammern { } gefasst sind. Die Struktur ergibt sich aus der sauberen Einrückungen mittels Tab oder Space (white-space aware code). Die meisten Codierrichtlinen geben ja heutzutage genau eine solche Code Formatierung vor, zusätzlich zu den {} Klammern was redundant ist. Also wieso nicht die Klammer weglassen. Mag sein, dass das für manchen am Anfang etwas komisch aussieht, aber man gewöhnt sich so schnell daran. Kommen in F# doch { } vor, dann handelt sich um einen Record Type oder Computation Expressions

Wie geht denn das ohne { } Code-Blocks ?

Bei gut gestaltetem Code achtet man darauf, dass die Code-Blocks korrekt eingerückt sind. Also z.B.
 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
// C#
void Bar()
{
    bool b = Foo();
    if b 
    {
        FooTrue1();
        FooTrue2();
    }
    else
    {
        FooFalse();
    }
}
Das selbe in F# ist durch weglassen von ; und { } zu erreichen, bei Einhaltung der korrekten Einrückungen.
1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
// F#   
let bar() =
    let b = foo()
    if b then
        FooTrue1()  // Die Einrückung gilt für mehrere Code Zeilen. 
        FooTrue2()       
    else
        FooFalse()
 

Keine Typen Deklaration

Es ist sicher schon aufgefallen, dass bei Funktionen keine Typen angegeben wurden.

Fehlt da dann nicht etwas, wenn im Code die Typen fehlen?

Wie geht das ohne Typen zu deklarieren? Die sogenannte Type-Inferenz findet selbst heraus um welchen Type es sich handeln muss. Man stelle sich vor, man ruft eine API-Funktion auf die data als Parameter entgegennimmt. Diese Funktion verarbeitet int array, somit ist data vom Type int array, also muss man data nicht extra deklarieren. In Visual-Studio oder auch im Blog Code hier, zeigt ein Tooltip über dem jeweiligen Wert oder Funktion dessen Type an, wenn man überprüfen will was es denn nun ist.
Der Code wird dadurch schlanker zu lesen und auch zu schreiben. Wobei Code ja mehr gelesen (Code Review) als geschrieben wird, ist das sehr nützlich, denn Kompakter Code ist schneller zu verstehen!
Kompakter Code, nicht im Sinne von alles auf eine Zeile quetschen, ist schneller zu verstehen, als wenn man Seitenweise lesen muss und sich immer die Typen Deklaration mitdenken muss. Überlassen wir die Typen dem “Compiler”, der prüft diese, und zwar schon vor dem Compilieren, die TypeInference die das erledigt läuft im Editor mit. Passt etwas nicht, wird die Stelle mit der bekannten rote Wellenlinie unterstrichen. Im Tooltip dazu wird erklärt was da nicht passt und was das Problem lösen kann.
Wir kümmern uns darum WAS gemacht wird. Ob alles passt, darum kümmert sich die TypeInference. Es ermöglicht ein abstrakteres Denken, wenn man sich nicht um die Typen Details kümmern muss und spart Entwicklungszeit.
Dies führt zum oft erwähnten positiven Effekt, den man dabei erlebt, dass wenn alles passt, der Code auch gleich erfolgreich kompiliert und meist auch prompt funktioniert. Diese Erfolge motivieren und man will TypeInference nicht mehr missen.

Generische Typen

Selber denkt man eher generisch, also mit generischen Datentypen. Es ist in F# so:
Wenn die Type-Inferenz nicht herausfindet, was es für ein Type sein muss, dann ist der Code automatisch generisch!
Super, man muss also dafür nicht extra überall <T> hinschreiben, das ist dann automatisch so!
1: 
2: 
3: 
4: 
5: 
// C#
void Swap<T>(List<T> list1, List<T> list2)
{
    // code to swap items
}
Und das equivalente generische swap in F#:
1: 
2: 
// F#
let swap (x,y) = (y,x)  // val swap : x:'a * y:'b -> 'b * 'a
und das funktioniert dann auch z.B. mit int List
1: 
2: 
3: 
4: 
let xs = [1; 3]
let ys = [4; 5; 6]
swap (xs,ys)
//val it : int list * int list = ([4; 5], [1; 3])
Auch das Refactoring wird dadurch vereinfacht, man muss die Typen nicht mitschleppen, also lesen und schreiben, umkopieren.
Weil es so einfach ist, braucht man dazu auch keine Refactoringtools! Viele glauben es zu beginn nicht, aber es ist so! Ihr werdet es merken ;-)
Etwas krass ausgedrückt werden Refactoringtool vielfach dazu verwendet, die “nebensächlichen” Teile des Codes zu erzeugen, die man nicht schreiben will. Steht der Code und man muss umbauen, dann müssen all die “nebensächlichen” Teile syntaktisch korrekt verpflanzt werden (Code-Plumbing wie man es auch nennt). Man kann es so sehen:
Die F# Syntax ist so ausgelegt, dass vieles nebensächliche gar nicht vorkommt und so das WAS gemacht wird sofort und klar ersichtlich ist.
Wie z.B.
  • keine “;” am Ende der Codezeile
  • keine { } Code-Blocks
  • keine Typen Deklaration
  • keine Generische Typen Deklaration
Positives Fazit:
Wer weniger schreibt, macht weniger Fehler. Wer weniger lesen muss, findet Fehler eher. Wer weniger lesen muss, arbeitet sich schneller ein. Weniger Code, weniger Bugs. Weniger Code, weniger Code Review. Weniger Code, Entwickler schneller eingearbeitet.
Ja und es geht nicht hauptsächlich darum : “Wer weniger schreibt, ist schneller fertig.” … es ist nett wenn das auch noch so ist ;-)
val xs : int listFull name: StrukturierungvonFQuellcode.xs
type bool = System.BooleanFull name: Microsoft.FSharp.Core.bool
Multiple items module Listfrom Microsoft.FSharp.Collections——————– type List<‘T> = | ( [] ) | ( :: ) of Head: ‘T * Tail: ‘T list interface IEnumerable interface IEnumerable<‘T> member Head : ‘T member IsEmpty : bool member Item : index:int -> ‘T with get member Length : int member Tail : ‘T list static member Cons : head:’T * tail:’T list -> ‘T list static member Empty : ‘T listFull name: Microsoft.FSharp.Collections.List<_>

Starten mit F#

Um zu starten und reinzuschnuppern braucht man nichts zu installieren. Entwicklungsumgebung also Code Editor und Compiler als Webseite gibt es gratis und ohne Anmeldung hier: Dieser läuft auf allen Systemen, auch für Apple iOS (iPad ohne Silverlight) Diese benötigen einen Web-Browser mit installiertem Microsoft Silverlight

Probiert aus, was euch am meisten zusagt. Unten sind zwei kurze Code Schnipsel zum Ausprobieren. Diese können einfach in die obigen Editoren kopiert werden um sie auszuführen.

Update: Gute Neuigkeiten, seit 12. Nov. 2014 ist von Microsoft das Visual Studio Community 2013 with Update 4 gratis hier erhältlich, die Installation oder das ISO Image hat einen Grösse von 6.9 GB. Mehr dazu  “Visual Studio Community 2013 – A Full-Featured IDE – FREE – Start coding the app of your dreams for Windows, Android, and iOS.” und “Opening up Visual Studio and .NET to Every Developer, Any Application”


Update: F# für Linux, Mac, Windows

Free Monodevelop wie hier beschrieben  http://www.monodevelop.com/download heisst dann (etwas verwirrend weil es umgetauft wurde) XamarinStudio.

Installation auf Windows 8.1 (Für andere F# Installationen empfiehlt sich http://fsharp.org/use/ )
Stand: 27.6.2015
Mit total ca. 100 MB download ist man dabei und die Installationszeit ist freundlich kurz, jedoch in 4 Schritten, aber alles ohne Windows zu booten.
1. .NET Framework 4.5:
    Download  http://go.microsoft.com/fwlink/p/?LinkId=397703
2. Install the free Visual F# Tools 3.1.2 from Microsoft
    Download (ca. 28 MB) http://www.microsoft.com/download/details.aspx?id=44011
3. GTK# for .NET 2.12.25:
    Download (ca. 25 MB) http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.25.msi
4. Xamarin Studio:
    Download (ca. 45 MB) http://download.xamarin.com/studio/Windows/XamarinStudio-5.9.2.4-0.msi

Im Xamarin Studio erstes F# Projekt erstellen (danach merkt er sich das)
Xamarin Studio F# Einstellungen
Selektierten F# Code im Editor ausführen mit Ctrl + Enter (nicht Alt + Enter wie in Visual Studio).


F# Beispiele

Auflistung .NET Assemblies

1: 
2: 
3: 
4: 
let methods =
    System.AppDomain.CurrentDomain.GetAssemblies()
    |> Seq.map (fun asm -> asm.GetTypes())
printfn "%A" methods
Die Ausgabe (gekürzt)
seq [[|System.Object; System.Runtime.Serialization.ISerializable; System.Runtime.InteropServices.Exception; System.Exception; System.Exception+_RestrictedErrorObject; System.ValueType; System.IComparable; System.IFormattable; System.IConvertible; …

Gray-Code Erzeugung

1: 
2: 
3: 
let (&) x = List.map((+)x)
let g x = ("0" & x) @ ("1" & (List.rev x))
printf "%A" ([""] |> g |> g |> g)
Gibt die 3-stelligen Gray-Codes aus. Für jedes |> g eine Stelle. Die Gray-Codes sind so angeordnet, dass immer nur ein Bit wechselt.
[“000″; “001”; “011”; “010”; “110”; “111”; “101”; “100”]
Tipp : Es ist klar das man als F# Neuling dies nicht gleich verstehen kann. Bitte nicht abschrecken lassen. Das Ergebnis soll etwas zum Staunen anregen. Es ist schon etwas kryptisch, aber es soll zeigen wie elegant und kompakt man Funktionen verknüpfen kann. Wenn man überhaupt nicht verstehen kann wie es funktionieren könnte, dann implementiere man den Gray-Code in seiner aktuell verwendeten Programmiersprache. Und pausiere das Lesen hier. STOP! nicht weiterlesen. Auflösung : Man wird erkennen, dass der Algorithmus auf Zeile 2 implementiert ist. D.h. es ist eher eine Spezifikation des Algorithmus, als eine imperative Abhandlung. Auf Zeile 1 wird ein Hilfsoperator & definiert der ein String mit einer String Liste verbindet. Der @ Operator verbindet zwei Listen. Und [ ] definiert eine Liste gefüllt mit einem leeren "" String. Der Pipe-Operator |> schiebt die Werte in die Funktion g, die der Generator für die nächste Stufe des Gray-Codes ist. Man könnte auch g(g(g([""]))) schreiben anstatt [""]|>g|>g|>g aber letzteres zeigt den Daten-Fluss viel intuitiver an. List.rev kehrt eine Liste um. Das printf macht die Ausagbe und mit "%A" als alles Formatierer.

F# Sprach Konstrukte

Wer schon eine Programmiersprache kennt, für den ist es sowieso einfach. Die vier wesentlichen Sprach Konstrukte sind
  • let : Zuweisung von Values und Funktionen
  • fun : Anonyme Funktion
  • type : Type Definition (Record, Class, Discriminated Union (DU))
  • match : Fallunterscheidung (das machtige “if” und “switch” in einem)
Zur Sprache F# selbst wird hier keine detaillierte Schritt für Schritt Abhandlung der kompletten Syntax gezeigt. Man findet die komplette F# Sprach Referenz “The F# Specification Language” als Nachschlagewerk gratis hier als PDF oder als Webseite .

Ausblick

Was macht F# so anderst?

Es sind die Kleinen, meist unterschätzten, Unterschiede und deren Konzepte in der Basis die, die Möglichkeiten in Höheren Ebenen wie Abstraktion und Komposition erst ermöglichen. Z.B. dass alle Values immutable sind, immer zugewiesen sind und es darum keine null (NULL) Referenzen vorkommen, dazu später mehr. Ich nenne sie Micro Patterns (Mikro Muster), es sind winzige Patterns mit wenig Code, die im Zusammenspiel, also der Komposition die wahre Funktion entfalten. Im Gegensatz zu den bekannten Objektorientierten Entwurfsmuster (Design Patterns), die aus mehreren zusammen agierenden Klassen bestehen, mit einigen Zeilen an Code, die sich pro Klasse über mehrere Files erstrecken können, so dass man, um den Zusammenhang zu erkennen, meist zu visuellen Darstellungen mittels UML Diagrammen greift.
Jetzt nehme ich etwas vorweg, der Clou an diesen Micro Patterns ist, dass diese das selbe wie die “riesigen” GoF Design Patterns, aber mit viel viel weniger Code (und ohne Klassen) bewerkstelligen können und somit überschaubar bleiben. Die Muster sind manchmal so klein, dass sie gleich als Sprachbestandteil von F# aufgehen.
Weiter geht’s dann im nächsten Blog.
val methods : seq<System.Type []>Full name: StartenvonF.methods
namespace System
type AppDomain = inherit MarshalByRefObject member ActivationContext : ActivationContext member AppendPrivatePath : path:string -> unit member ApplicationIdentity : ApplicationIdentity member ApplicationTrust : ApplicationTrust member ApplyPolicy : assemblyName:string -> string member BaseDirectory : string member ClearPrivatePath : unit -> unit member ClearShadowCopyPath : unit -> unit member CreateComInstanceFrom : assemblyName:string * typeName:string -> ObjectHandle + 1 overload member CreateInstance : assemblyName:string * typeName:string -> ObjectHandle + 3 overloads …Full name: System.AppDomain
property System.AppDomain.CurrentDomain: System.AppDomain
System.AppDomain.GetAssemblies() : System.Reflection.Assembly []
module Seqfrom Microsoft.FSharp.Collections
val map : mapping:(‘T -> ‘U) -> source:seq<‘T> -> seq<‘U>Full name: Microsoft.FSharp.Collections.Seq.map
val asm : System.Reflection.Assembly
System.Reflection.Assembly.GetTypes() : System.Type []
val printfn : format:Printf.TextWriterFormat<‘T> -> ‘TFull name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val x : string
Multiple items module Listfrom Microsoft.FSharp.Collections ——————– type List<‘T> = | ( [] ) | ( :: ) of Head: ‘T * Tail: ‘T list interface IEnumerable interface IEnumerable<‘T> member Head : ‘T member IsEmpty : bool member Item : index:int -> ‘T with get member Length : int member Tail : ‘T list static member Cons : head:’T * tail:’T list -> ‘T list static member Empty : ‘T list Full name: Microsoft.FSharp.Collections.List<_>
val map : mapping:(‘T -> ‘U) -> list:’T list -> ‘U listFull name: Microsoft.FSharp.Collections.List.map
val g : x:string list -> string listFull name: StartenvonF.g
val x : string list
val rev : list:’T list -> ‘T listFull name: Microsoft.FSharp.Collections.List.rev
val printf : format:Printf.TextWriterFormat<‘T> -> ‘TFull name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf

Über den Blog

Funktionale Software Entwicklung mit F# und .Net

Willkommen auf einer der wenigen deutschsprachigen Webseiten über die Programmiersprache F# (F-Sharp, FSharp, #fsharp, .fs, .fsx, #F, FScharp, F-Scharf).

Worum geht es hier?

Wer sich für Funktionale Programmierung interessiert wird auf Aussagen treffen wie, es ist sehr mathematisch, abstrakt und komplex (Kategorientheorie). Dies wirkt meist abschreckend. Das muss aber nicht sein.

Dieser Blog will anhand der Programmiersprache F# zeigen, dass es bei Funktionaler Programmierung (FP) um mehr geht, also auch im Kleineren, die einfachen Dinge wie die Bausteine für Muster und Wiederverwendung und übergeordnet in der funktionalen Denkweise Probleme zu lösen, grossartige Möglichkeiten und Vorteile vorhanden sind.

Jeder der denkt, dass Funktionale Programmierung nur das herumreichen von Anonymen Funktionen (Lambda-Funktion) ist, die es auch in anderen Sprachen gibt, der irrt. Es ist nicht nur die Programmierung (Syntax) die funktional erfolgt, es geht auch um den Funktionalen Design, der ganz andere Denkmuster enthält als ein Objektorientierter (OO) Design.

Und weil hier eine Mehrzweck (Multi-Purpose) Programmiersprache wie F# verwendet wird, es nicht nur einzig um Funktional geht, sondern gezeigt wird, das ein guter Mix aus FP und OO Techniken einfach möglich ist. Der Nutzen von beiden Welten (FP, OO) soll in der Praxis, also basierend auf .Net (oder Mono) gezeigt werden.

Der Blog ist gedacht als eine Ein- und Weiterführung in die Funktionale Programmierung mit F#, für C#, VB.Net, C++ oder Java Entwickler, etc.

Bitte klickt doch im Fragebogen rechts Eure Programmiersprache(n) an, so könnt ihr das aktuelle Ergebnis der Umfrage sehen, Danke.
1: 
printf "HalloF#" // Die Code Beispiele werden unterstützt durch Tooltips 

Warum in Deutsch?

  • Weil man es auch automatisch übersetzen lassen kann (translate to English).
  • Weil sich Wissen und Erfahrungen besser in der Muttersprache weitergeben lassen.
  • Weil es schon genügend englischsprachige Webseiten und Literatur zum Thema F# gibt.

Was nicht?

  • Es wird hier nicht das F# Referenz Handbuch auf Deutsch übersetzt zu lesen geben.
  • Es werden hier nicht alle Fachbegriffe stur eingedeutscht.
  • Dies ist keine Microsoft Seite, denn F# ist Open Source!
val printf : format:Printf.TextWriterFormat<‘T> -> ‘TFull name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printf