Поради щодо гольфу в F #


21

Які загальні поради щодо гольфу у F #? Я шукаю ідеї, які можна застосувати до коду проблем із гольфом взагалі, які принаймні дещо специфічні для F # (наприклад, "видалити коментарі" - це не відповідь). Будь ласка, опублікуйте одну пораду за кожну відповідь.

Відповіді:


9

Використовуйте functionзамість випадків, matchколи це можливо; це збереже 6 символів для змінних з одним символом:

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

проти

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

Він також може замінити будь-яку відповідність шаблону, щоб послідовно зберегти 1 символ:

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

8

Вам потрібно використовувати метод для змінної, для якої ви ще не обмежили тип? Просто порівняйте його з буквальним типом, який ви хочете, щоб він був, а потім відкиньте результат, щоб анотувати тип цієї змінної:

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

7

Коли ви можете використовувати позначення префіксу для операторів інфікування - це позбавить вас від необхідності визначати функцію для їх використання.

Наприклад, ви можете перетворити це:

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

в це:

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

1
Я використовую його тут дякую!
aloisdg повідомляє Відновити Моніку

5

Деконструкція кортежів

Якщо ви не можете обійтись із використанням змінних, використовуйте кортежну деконструкцію замість декількох виразів дозволу

let a,b ="",[]

замість

let a=""
let b=[]

Читання з stdin

Основна бібліотека F # визначає псевдонім для System.Console.Inвиклику stdin. Вони дозволяють читати дані.

// Signature:
stdin<'T> :  TextReader

TextReader у msdn

Велика перевага, окрім того, що він коротший, ніж Consoleце, вам також не потрібно відкривати Систему

Ітерація над рядком

рядок в основному є char seq, це дозволяє використовувати Seq.mapбезпосередньо з рядками. Можна також використовувати їх у розуміннях[for c in "" do]

Мутації / Довідкові комірки

Використання опорних комірок не завжди коротше, оскільки кожна операція читання надходить із додатковим символом, щоб знешкодити осередок.

Загальні поради

  • Можна написати повний match .. withрядок

    function|'a'->()|'b'->()|_->()
    
  • Немає необхідності у пробілі до і після буквено-цифрових символів.

    String.replicate 42" "
    if Seq.exists((<>)'@')s then
    if(Seq.exists((<>)'@')s)then
    
  • Якщо вам потрібно ліворуч або праворуч прокладати рядок з пробілами, ви можете використовувати для цього прапорці [s] printf [n].

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

    Модуль Core.Printf



3

Ета-перетворення для функцій

Велике спасибі Лайконі за цю пораду в одному з моїх рішень .

Розглянемо функцію, скажімо, підсумовувати рядок з 3 для великих літер та 1 для всіх інших символів. Так:

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

За допомогою ета-перетворення це можна переписати як:

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

і називається так само, як і раніше:

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

Функція оператора прямого складу >>

Тепер припустимо, що нашим початковим завданням було б скласти рядок з 3 для великих літер та 1 для малих літер, а всі інші символи виключені.

Ми можемо написати це так:

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

Ми можемо використовувати оператор прямої композиції ( >>) для з'єднання двох функцій ( Seq.filterі Seq.sumBy) разом. З ета-перетворенням визначення функції стане:

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

Кріс Сміт чудово написав >>оператора на своєму блозі MSDN .



2

Уникайте дужок при використанні одного параметра та кортежу

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

можна написати

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

1
Вам також не потрібно () навколо кортежів: нехай f = [0,1; 1,4] |> Seq.map fst
подумайте передкодування


2

Віддайте перевагу новій рядку рядка над "\ n"

Це почне окупатися навіть одним новим символом рядка у вашому коді. Одним із випадків використання може бути:

(18 байт)

string.Concat"\n"

(17 байт)

string.Concat"
"

Натхненний відповіддю Чиру для es6 .

Використовується тут


1

Використовуйте .NET

.NET пропонує багато приємних вбудованих. F # може використовувати їх, тому не забувайте їх!

Приклад:

open System.Linq

Це може бути корисно!


1

Використовуйте лямбдаси, щоб зберегти байт. Наприклад, це:

let f x=x*x

Можна виразити так:

fun x->x*x


1

moduleКлючове слово може бути використано для скорочення імен модулів при використанні повторно. Наприклад:

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

може стати

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

Це корисніше для більш тривалих програм, де модульні методи використовуються повторно (і їх потрібно повністю іменувати кожен раз, оскільки вони мають RequireQualifiedAccessмодифікатор), і дозволяє голити кілька символів, особливо коли корисніше використовувати звичайний масив CLR (наприклад, мутабельність ), ніж F # seqабо list.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.