Wskazówki do gry w golfa w F #


21

Jakie masz ogólne wskazówki na temat gry w golfa w F #? Szukam pomysłów, które można by zastosować do problemów z golfem w kodzie, które są przynajmniej nieco specyficzne dla F # (np. „Usuń komentarze” nie jest odpowiedzią). Proszę zamieścić jedną wskazówkę na odpowiedź.

Odpowiedzi:


9

Użyj functionzamiast, matchgdy to możliwe; zapisze 6 znaków dla zmiennych 1-znakowych:

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

vs

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

Może również zastąpić dowolne dopasowanie wzorca, aby konsekwentnie zapisywać 1 znak:

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

8

Potrzebujesz użyć metody na zmiennej, dla której nie ograniczyłeś jeszcze typu? Po prostu porównaj go z literałem typu, który chcesz, a następnie wyrzuć wynik, aby opisać typ tej zmiennej:

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

7

Jeśli to możliwe, używaj notacji prefiksowej dla operatorów infix - pozwoli to uniknąć konieczności definiowania funkcji, aby z nich korzystać.

Na przykład możesz to zmienić:

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

zaangażowany w to:

List.map((+)2)[1;1;2;3;5;8]

1
Używam go tutaj, dziękuję!
aloisdg mówi Przywróć Monikę

5

Dekonstrukcja krotkowa

Jeśli nie możesz przejść do korzystania ze zmiennych, użyj dekonstrukcji krotek zamiast wielu wyrażeń let

let a,b ="",[]

zamiast

let a=""
let b=[]

Czytanie ze standardowego

Biblioteka podstawowa F # definiuje alias dla System.Console.Inwywoływanej stdin. Umożliwiają one odczytywanie danych wejściowych.

// Signature:
stdin<'T> :  TextReader

TextReader na msdn

Dużą zaletą jest to, że jest krótszy niż Consoleobecnie, nie trzeba też otwierać Systemu

Iterowanie po sznurku

string jest w zasadzie a char seq, to pozwala ci używać Seq.mapbezpośrednio z stringami. Można je również wykorzystać w zrozumieniu[for c in "" do]

Zmienne / komórki referencyjne

Korzystanie z komórek referencyjnych nie zawsze jest krótsze, ponieważ każda operacja odczytu wiąże się z dodatkowym znakiem wykreślającym komórkę.

Ogólne wskazówki

  • Można napisać cały match .. withwiersz

    function|'a'->()|'b'->()|_->()
    
  • Nie ma potrzeby używania białych znaków przed i po znakach nie alfanumerycznych.

    String.replicate 42" "
    if Seq.exists((<>)'@')s then
    if(Seq.exists((<>)'@')s)then
    
  • W przypadku, gdy chcesz wstawić lewy lub prawy ciąg znaków ze spacjami, możesz użyć do tego flag [s] printf [n].

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

    Moduł Core.Printf



3

Eta-konwersja funkcji

Ogromne podziękowania dla Laikoni za tę wskazówkę w jednym z moich rozwiązań .

Rozważ funkcję, powiedzmy, sumowania ciągu 3 dla wielkich liter i 1 dla wszystkich innych znaków. Więc:

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

Przez eta-konwersję można to zapisać ponownie jako:

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

i wywoływane w taki sam sposób jak poprzednio:

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

Funkcja operatora kompozycji do przodu >>

Załóżmy teraz, że naszym pierwotnym wyzwaniem byłoby zsumowanie ciągu 3 dla wielkich liter i 1 dla małych liter, a wszystkie inne znaki są wykluczone.

Możemy to napisać jako:

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

Możemy użyć operatora kompozycji do przodu ( >>), aby połączyć dwie funkcje ( Seq.filteri Seq.sumBy) razem. W przypadku konwersji eta definicja funkcji wyglądałaby następująco:

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

Chris Smith napisał świetną recenzję dla >>operatora na swoim blogu MSDN .


2

Jeśli Seqto możliwe, jest krótszy niż List:

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

jest o jeden char krótszy ...





1

Użyj lambdas, aby zapisać bajt. Na przykład:

let f x=x*x

Można to wyrazić następująco:

fun x->x*x


1

Słowo modulekluczowe może być użyte do skrócenia nazw modułów, gdy są używane wielokrotnie. Na przykład:

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

może zostać

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

Jest to bardziej przydatne w przypadku dłuższych programów, w których metody modułowe są używane wielokrotnie (i muszą być za każdym razem pełne nazwy, ponieważ mają RequireQualifiedAccessmodyfikator), i pozwala na wyłączenie kilku znaków, szczególnie gdy bardziej użyteczne jest użycie zwykłej tablicy CLR (np. Zmienność ) niż F # seqlub list.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.