Tipps zum Golfen in F #

21

Welche allgemeinen Tipps haben Sie zum Golfen in F #? Ich bin auf der Suche nach Ideen, die sich auf Code-Golf-Probleme im Allgemeinen anwenden lassen, die zumindest etwas spezifisch für F # sind (z. B. "Kommentare entfernen" ist keine Antwort). Bitte posten Sie einen Tipp pro Antwort.

ProgramFOX
quelle

Antworten:

9

Verwenden Sie functionanstelle von, matchwenn möglich; Es werden 6 Zeichen für 1-Zeichen-Variablen gespeichert:

let f=function // ... (14 chars)

vs

let f x=match x with // ... (20 chars)

Es kann auch jede Musterübereinstimmung ersetzen, um 1 Zeichen konsistent zu speichern:

match a with|          // ... (13 chars)
a|>function|           // ... (12 chars)
(function| (* ... *))a // (12 chars)
Jwosty
quelle
8

Müssen Sie eine Methode für Variablen verwenden, für die Sie den Typ noch nicht eingeschränkt haben? Vergleichen Sie es einfach mit einem Literal des gewünschten Typs und werfen Sie dann das Ergebnis weg, um den Typ dieser Variablen mit Anmerkungen zu versehen:

let f (x:string)=x.Length
let f x=x="";x.Length
Jwosty
quelle
7

Verwenden Sie die Präfixnotation für Infix-Operatoren, wenn Sie können - Sie müssen keine Funktion definieren, um sie zu verwenden.

Zum Beispiel können Sie dies drehen:

List.map(fun i->i+2)[1;1;2;3;5;8]

das mögen:

List.map((+)2)[1;1;2;3;5;8]
Roujo
quelle
1
Ich benutze es hier, danke!
aloisdg sagt Reinstate Monica
5

Tupel-Dekonstruktion

Wenn Sie nicht mit Variablen umgehen können, verwenden Sie die Tupel-Dekonstruktion anstelle mehrerer let-Ausdrücke

let a,b ="",[]

anstatt

let a=""
let b=[]

Lesen von stdin

Die F # -Kernbibliothek definiert einen Alias ​​für die System.Console.Inaufgerufenen stdin. Mit diesen können Sie Eingaben lesen.

// Signature:
stdin<'T> :  TextReader

TextReader auf msdn

Abgesehen von dem großen Vorteil, dass es kürzer als Consoleist, müssen Sie System auch nicht öffnen

Über einen String iterieren

Zeichenfolge ist im Grunde genommen eine Zeichenfolge char seq, mit der Sie Seq.mapdirekt Zeichenfolgen verwenden können. Es ist auch möglich, sie in Begriffen zu verwenden[for c in "" do]

Mutables / Referenzzellen

Die Verwendung von Referenzzellen ist nicht immer kürzer, da jeder Lesevorgang ein zusätzliches Zeichen enthält, um die Zelle deref zu machen.

Allgemeine Hinweise

  • Es ist möglich, die komplette match .. withInline zu schreiben

    function|'a'->()|'b'->()|_->()
    
  • Leerzeichen vor und nach nicht alphanumerischen Zeichen sind nicht erforderlich.

    String.replicate 42" "
    if Seq.exists((<>)'@')s then
    if(Seq.exists((<>)'@')s)then
    
  • Wenn Sie eine Zeichenfolge mit Leerzeichen links oder rechts auffüllen müssen, können Sie dafür die Flags [s] printf [n] verwenden.

    > sprintf "%20s" "Hello, World!";;
    val it : string = "       Hello, World!"
    

    Core.Printf-Modul

Brunner
quelle
4

Verwenden Sie id anstelle von x-> x

id ist ein Operator, der für die Identitätsfunktion steht.

let u x=x|>Seq.countBy (fun x->x)

kann geschrieben werden

let u x=x|>Seq.countBy id

Quelle

Ich benutze es hier

aloisdg sagt Reinstate Monica
quelle
3

Eta-Konvertierung für Funktionen

Vielen Dank an Laikoni für diesen Tipp in einer meiner Lösungen .

Stellen Sie sich eine Funktion vor, um beispielsweise eine Zeichenfolge mit 3 für Großbuchstaben und 1 für alle anderen Zeichen zu summieren. So:

let counter input = Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1) input

Durch Eta-Konvertierung kann dies wie folgt umgeschrieben werden:

let counter = Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1)

und wie zuvor angerufen:

counter "Hello world!" |> printfn "%i"

Die Funktion zum Weiterleiten der Komposition >>

Angenommen, unsere ursprüngliche Herausforderung besteht darin, eine Zeichenfolge mit 3 für Großbuchstaben und 1 für Kleinbuchstaben zu summieren, und alle anderen Zeichen sind ausgeschlossen.

Wir könnten dies schreiben als:

let counter input = Seq.filter Char.IsLetter input |> Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1)

Wir können den Forward-Composition-Operator ( >>) verwenden, um die beiden Funktionen ( Seq.filterund Seq.sumBy) miteinander zu verketten. Bei der eta-Konvertierung würde die Funktionsdefinition folgendermaßen aussehen:

let counter = Seq.filter Char.IsLetter >> Seq.sumBy (fun x -> if Char.IsUpper x then 3 else 1)

Chris Smith hat >>in seinem MSDN-Blog einen tollen Bericht über den Betreiber verfasst .

Ciaran_McCarthy
quelle
2

Wenn möglich Seqist kürzer als List:

[[1];[2;3];[4];[5]|>List.collect
[[1];[2;3];[4];[5]|>Seq.collect

ist ein char kürzer ...

Denken Sie vor der Kodierung
quelle
2

Vermeiden Sie Klammern, wenn Sie einen Parameter und ein Tupel verwenden

let f = [(0,1);(1,4)]|>Seq.map(fst)
printfn "%A" f

kann geschrieben werden

let f = [0,1;1,4]|>Seq.map fst
printfn "%A" f
aloisdg sagt Reinstate Monica
quelle
1
Sie brauchen () auch nicht um Tupel: let f = [0,1; 1,4] |> Seq.map fst
thinkbeforecoding
1
Vielen Dank. aktualisiert.
Aloisdg sagt Reinstate Monica
2

Neue Zeilenfolge vor "\ n" bevorzugen

Dies macht sich bereits bei einem einzelnen neuen Zeilenzeichen in Ihrem Code bezahlt. Ein Anwendungsfall könnte sein:

(18 Bytes)

string.Concat"\n"

(17 Bytes)

string.Concat"
"

Inspiriert von Chirus Antwort für es6 .

Gebrauchte hier

aloisdg sagt Reinstate Monica
quelle
1

Verwenden Sie .NET

.NET bietet viele nette Builtins. F # kann sie benutzen, also vergiss sie nicht!

Beispiel:

open System.Linq

Es kann hilfreich sein!

aloisdg sagt Reinstate Monica
quelle
1

Verwenden Sie Lambdas, um ein Byte zu speichern. Zum Beispiel das:

let f x=x*x

Kann wie folgt ausgedrückt werden:

fun x->x*x
Dana
quelle
1

Verwenden Sie für ... um statt für ... um einen Bereich zu betreten

for i in[0..2]
for i=0 to 2
aloisdg sagt Reinstate Monica
quelle
1

Das moduleSchlüsselwort kann verwendet werden, um Modulnamen bei wiederholter Verwendung zu verkürzen. Beispielsweise:

Array.fold ...
Seq.iter ...
List.map ...

kann werden

module A=Array
A.fold ...
module S=Seq
S.iter ...
module L=List
L.map ...

Dies ist nützlicher für längere Programme, bei denen Modulmethoden wiederholt verwendet werden (und jedes Mal vollständig benannt werden müssen, weil sie den RequireQualifiedAccessModifikator haben), und ermöglicht das Absparen einiger Zeichen, insbesondere, wenn es nützlicher ist, ein reguläres CLR-Array zu verwenden (z. B. Mutabilität) ) als ein F # seqoder list.

LSM07
quelle