Dicas para jogar golfe em F #


21

Que dicas gerais você tem para jogar golfe em F #? Estou procurando idéias que possam ser aplicadas aos problemas de código de golfe em geral que sejam pelo menos um pouco específicos para F # (por exemplo, "remover comentários" não é uma resposta). Poste uma dica por resposta.

Respostas:


9

Use em functionvez de matchquando possível; ele salvará 6 caracteres para variáveis ​​de 1 caractere:

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

vs

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

Também pode substituir qualquer correspondência de padrão para salvar consistentemente 1 caractere:

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

8

Precisa usar um método na variável para o qual você ainda não restringiu o tipo? Apenas compare-o com um literal do tipo que você deseja que seja e jogue fora o resultado para anotar o tipo dessa variável:

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

7

Use a notação de prefixo para operadores de infixo quando puder - isso evitará que você precise definir uma função para usá-los.

Por exemplo, você pode ativar isso:

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

nisso:

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

11
Eu uso aqui obrigado!
aloisdg diz Reinstate Monica

5

Desconstrução de tupla

Caso não consiga usar variáveis, use a desconstrução da tupla em vez de várias expressões let

let a,b ="",[]

ao invés de

let a=""
let b=[]

Lendo de stdin

A biblioteca principal do F # define um alias para System.Console.Inchamado stdin. Isso permite que você leia a entrada.

// Signature:
stdin<'T> :  TextReader

TextReader no msdn

A grande vantagem, além de ser mais curta do que Consoleé, não é necessário abrir o System

Iterando sobre String

string é basicamente um char seq, isso permite que você use Seq.mapdiretamente com strings. Também é possível usá-los em compreensões[for c in "" do]

Mutables / células de referência

O uso de células de referência nem sempre é mais curto, pois toda operação de leitura vem com um caractere adicional para apagar a célula.

Dicas gerais

  • É possível escrever a match .. withlinha completa

    function|'a'->()|'b'->()|_->()
    
  • Não há necessidade de espaço em branco antes e depois de caracteres não alfanuméricos.

    String.replicate 42" "
    if Seq.exists((<>)'@')s then
    if(Seq.exists((<>)'@')s)then
    
  • Caso você precise colocar uma string com espaços à esquerda ou à direita, você pode usar sinalizadores [s] printf [n] para isso.

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

    Módulo Core.Printf



3

Eta-conversão para funções

Muito obrigado a Laikoni por esta dica em uma das minhas soluções .

Considere uma função para, digamos, somar uma sequência com 3 para letras maiúsculas e 1 para todos os outros caracteres. Tão:

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

Por conversão eta, isso pode ser reescrito como:

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

e chamado da mesma maneira que antes:

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

O operador de composição direta da função >>

Agora, suponha que nosso desafio original seria somar uma sequência com 3 para letras maiúsculas e 1 para letras minúsculas, e todos os outros caracteres são excluídos.

Podemos escrever isso como:

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

Podemos usar o operador de composição direta ( >>) para encadear as duas funções ( Seq.filtere Seq.sumBy) juntas. Com a conversão eta, a definição da função se tornaria:

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

Chris Smith fez um ótimo artigo sobre o >>operador em seu blog do MSDN .


2

Quando possível, Seqé menor que List:

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

é um char mais curto ...





1

Use lambdas para salvar um byte. Por exemplo, isto:

let f x=x*x

Pode ser expresso como este:

fun x->x*x


1

A modulepalavra-chave pode ser usada para encurtar os nomes dos módulos quando usados ​​repetidamente. Por exemplo:

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

pode se tornar

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

Isso é mais útil para programas mais longos, em que os métodos do módulo são usados ​​repetidamente (e devem ser totalmente nomeados toda vez porque possuem o RequireQualifiedAccessmodificador) e permite reduzir alguns caracteres, especialmente quando é mais útil usar uma matriz CLR regular (por exemplo, mutabilidade ) que um F # seqou list.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.