Conseils pour jouer au golf en F #

21

Quels conseils généraux avez-vous pour jouer au golf en F #? Je recherche des idées qui peuvent être appliquées aux problèmes de golf de code en général qui sont au moins quelque peu spécifiques à F # (par exemple, "supprimer les commentaires" n'est pas une réponse). Veuillez poster un pourboire par réponse.

ProgramFOX
la source

Réponses:

9

Utilisez functionplutôt matchque possible; cela économisera 6 caractères pour les variables à 1 caractère:

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

contre

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

Il peut également remplacer n'importe quelle correspondance de motif pour enregistrer de manière cohérente 1 caractère:

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

Besoin d'utiliser une méthode sur variable dont vous n'avez pas encore contraint le type? Il suffit de le comparer à un littéral du type que vous souhaitez qu'il soit, puis de jeter le résultat pour annoter le type de cette variable:

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

Utilisez la notation de préfixe pour les opérateurs d'infixe lorsque vous le pouvez - cela vous évitera de devoir définir une fonction pour les utiliser.

Par exemple, vous pouvez activer ceci:

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

en cela:

List.map((+)2)[1;1;2;3;5;8]
Roujo
la source
1
Je l'utilise ici merci!
aloisdg dit Réintégrer Monica
5

Déconstruction de tuple

Si vous ne parvenez pas à utiliser des variables, utilisez la déconstruction de tuple au lieu de plusieurs expressions let

let a,b ="",[]

au lieu de

let a=""
let b=[]

Lecture de stdin

La bibliothèque F # core définit un alias pour System.Console.Inappelé stdin. Ceux-ci vous permettent de lire l'entrée.

// Signature:
stdin<'T> :  TextReader

TextReader sur msdn

Le gros avantage mis à part le fait qu'il est plus court que Consolevous ne l'avez pas non plus à ouvrir le système

Itération sur chaîne

chaîne est fondamentalement un char seq, cela vous permet d'utiliser Seq.mapdirectement avec des chaînes. Il est également possible de les utiliser dans les compréhensions[for c in "" do]

Mutables / Cellules de référence

L'utilisation de cellules de référence n'est pas toujours plus courte, car chaque opération de lecture est accompagnée d'un caractère supplémentaire pour déréférencer la cellule.

Conseils généraux

  • Il est possible d'écrire l'intégralité en match .. withligne

    function|'a'->()|'b'->()|_->()
    
  • Aucun espace blanc n'est nécessaire avant et après les caractères non alphanumériques.

    String.replicate 42" "
    if Seq.exists((<>)'@')s then
    if(Seq.exists((<>)'@')s)then
    
  • Dans le cas où vous devez remplir à gauche ou à droite une chaîne avec des espaces, vous pouvez utiliser les drapeaux [s] printf [n] pour cela.

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

    Module Core.Printf

Brunner
la source
4

Utilisez id au lieu de x-> x

id est un opérateur représentant la fonction d'identité.

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

peut être écrit

let u x=x|>Seq.countBy id

la source

Je l'utilise ici

aloisdg dit Réintégrer Monica
la source
3

Eta-conversion pour les fonctions

Un grand merci à Laikoni pour cette astuce dans l'une de mes solutions .

Considérons une fonction pour, disons, additionner une chaîne avec 3 pour les lettres majuscules et 1 pour tous les autres caractères. Donc:

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

Par eta-conversion cela peut être réécrit comme:

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

et appelé de la même manière que précédemment:

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

L'opérateur de fonction de composition vers l'avant >>

Supposons maintenant que notre défi initial consiste à additionner une chaîne avec 3 pour les lettres majuscules et 1 pour les lettres minuscules, et tous les autres caractères sont exclus.

Nous pourrions écrire ceci comme:

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

Nous pouvons utiliser l'opérateur de composition directe ( >>) pour enchaîner les deux fonctions ( Seq.filteret Seq.sumBy) ensemble. Avec eta-conversion, la définition de la fonction deviendrait:

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

Chris Smith a fait un excellent article sur l' >>opérateur sur son blog MSDN .

Ciaran_McCarthy
la source
2

Lorsque cela Seqest possible est plus court que List:

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

est un caractère plus court ...

thinkbeforecoding
la source
2

Évitez les parenthèses lors de l'utilisation d'un paramètre et sur un tuple

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

peut être écrit

let f = [0,1;1,4]|>Seq.map fst
printfn "%A" f
aloisdg dit Réintégrer Monica
la source
1
Vous n'avez pas non plus besoin de () autour des tuples: let f = [0,1; 1,4] |> Seq.map fst
thinkbeforecoding
1
Merci. mis à jour.
aloisdg dit Réintégrer Monica le
2

Préférez la nouvelle chaîne de ligne à "\ n"

Cela commencera à porter ses fruits même à un seul nouveau caractère de ligne dans votre code. Un cas d'utilisation pourrait être:

(18 octets)

string.Concat"\n"

(17 octets)

string.Concat"
"

Inspiré de la réponse de Chiru pour es6 .

Utilisé ici

aloisdg dit Réintégrer Monica
la source
1

Utilisez .NET

.NET propose de nombreuses fonctionnalités intéressantes. F # peut les utiliser, alors ne les oubliez pas!

Exemple:

open System.Linq

Ça peut être utile!

aloisdg dit Réintégrer Monica
la source
1

Utilisez lambdas pour enregistrer un octet. Par exemple, ceci:

let f x=x*x

Peut être exprimé comme ceci:

fun x->x*x
dana
la source
1

Utilisez pour ... à au lieu de pour ... dans pour parcourir une plage

for i in[0..2]
for i=0 to 2
aloisdg dit Réintégrer Monica
la source
1

Le modulemot-clé peut être utilisé pour raccourcir les noms de modules lorsqu'il est utilisé à plusieurs reprises. Par exemple:

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

peut devenir

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

Ceci est plus utile pour les programmes plus longs où les méthodes de module sont utilisées à plusieurs reprises (et doivent être entièrement nommées à chaque fois car elles ont le RequireQualifiedAccessmodificateur), et permet de supprimer quelques caractères, en particulier lorsqu'il est plus utile d'utiliser un tableau CLR normal (par exemple, la mutabilité ) qu'un F # seqou list.

LSM07
la source