Dicas para jogar golfe em Dotty

Sep 03 2020

Que dicas gerais você daria para jogar golfe no Dotty ? Estou procurando por ideias que possam ser aplicadas a problemas de golfe de código em geral que sejam pelo menos um pouco específicos para Dotty (por exemplo, "remover comentários" não é uma resposta). Por favor, poste uma dica por resposta.

Veja também dicas para jogar golfe no Scala

Respostas

1 user Sep 03 2020 at 05:33

Use parâmetro untupling

A untupling de parâmetro permite que você escreva funções aceitando uma única tupla como entrada, como se fossem funções que aceitam 2 parâmetros. Basicamente, você pode substituir esses

list.map{case(a,b)=>a+b}
//and
list.map{case(a,b)=>Seq(a,b)}
//or
list.map(t=>t._1+t._2)
//and
list.map(t=>Seq(t._1,t._2))

com isso, que é mais curto e mais bonito.

list.map(_+_)
//and
list.map(Seq(_,_))
1 user Sep 03 2020 at 23:37

Use as funções @main e toplevel

Se você precisar fazer um programa completo, use a @mainanotação em um método principal de nível superior.

@main def main={code}

É muito mais curto do que essas 2 abordagens:

object M extends App{code}
object M{def main(a:Array[String])={code}}
1 user Sep 08 2020 at 02:00

Literais Numéricos

Agora você pode escrever um literal de número para qualquer tipo definido pelo usuário com uma determinada instância / implícita da FromDigitscaracterística, como BigInte BigDecimal.

No Scala 2, para passar o número 9.999.999.999.999.999 para uma função que aceita BigInts, você teria que usar BigInt("9999999999999999"), mas agora você pode apenas dizer diretamente, 9999999999999999sem usar o método ou construtor apply explicitamente.

Você também pode usar sublinhados, notação científica, hexadecimal, etc., assim como qualquer literal de número normal, desde que a FromDigitsinstância desse tipo suporte essa notação, é claro. Ambos BigInte BigDecimalestão bem com sublinhados, mas BigIntpermitem apenas hexadecimais e apenas BigDecimalnotação científica (com decimais).

1 user Sep 04 2020 at 00:44

Chaves opcionais

Em expressões de correspondência, pelo menos, você pode salvar um byte usando a sintaxe baseada em indentação.

a match
case b=>c
case d=>e

tem 27 bytes, enquanto o código abaixo é 28.

a match{case b=>c case d=>e}

Como observação lateral, matchtambém recebe tratamento especial no que diz respeito ao encadeamento. O seguinte código Scala 2:

("foo"match{case x=>x})match{case x=>x}

agora pode ser escrito sem os parênteses:

"foo"match{case x=>x}match{case x=>x}
1 user Sep 04 2020 at 00:56

Deixe de fora newcom aplicativos de criadores

Você pode chamar construtores sem usar new(como Kotlin), tratando todas as classes como se elas tivessem applymétodos em seus companheiros. Isso economiza 4 bytes cada vez que você instancia algo, desde que new Foo()se torne justo Foo().

Isso também se aplica a dados (embora você raramente precise deles para o código de golfe):

given foo as Foo=new Foo() //bad
given foo as Foo=Foo()     //better
given foo as Foo           //great
user Sep 21 2020 at 21:32

Use tipos de correspondência para funções recursivas que correspondem a padrões

Fazer um typealias com um tipo de correspondência às vezes é mais curto do que usar uma função adequada. Por exemplo, tome esta implementação do cálculo KI (não é uma coisa real). O tipo não precisa :Any, então você economiza 7 bytes no total ( typeé 1 byte a mais def).

//A normal function
def r(t:Any):Any=t match{case(('K',x),y)=>r(x)case('I',x)=>r(x)case t=>t}
//With match types
type R[T]=T match{case(('K',x),y)=>R[x]case('I',x)=>R[x]case _=>T}

Reconhecidamente, neste exemplo particular, você poderia usar tuplagem automática,, ->literais de função de correspondência de padrões, etc. para tornar o def mais curto, mas este é apenas um caso. Quando você não está lidando com tuplas, ou o tipo de retorno é mais complexo do que apenas Any, ou você tem vários parâmetros, esta dica se torna mais útil.

user Nov 21 2020 at 06:41

Nova sintaxe de controle

Na maioria dos casos, a nova sintaxe de controle não encurta o código (e é, na verdade, mais detalhada), ela é útil para compreensão. Se sua expressão ou padrão termina ou começa com parênteses ou aspas duplas, você pode salvar um byte ou dois:

for((x,y,z)<-Seq((1,2,3),(3,4,5));y<-"foo")yield y+x  //Old-style syntax
for(x,y,z)<-Seq((1,2,3),(3,4,5));y<-"foo"yield y+x    //New control syntax

Não é tão útil quanto algumas outras coisas, como untupling de parâmetro, mas muitas vezes me encontro usando para compreensões para chamadas de função como f(foo)ou Seq(1,2), que terminam entre parênteses.

Veja-o rodar no Scastie .