Dicas para jogar golfe em Kotlin

22

Dado o recente anúncio do Google do suporte oficial da Kotlin para o desenvolvimento do Android, achei que seria oportuno pesquisar na comunidade algumas dicas impressionantes de golfe para esse relativamente novo idioma da JVM.

O Kotlin inclui uma combinação única de recursos entre os irmãos da JVM, o que o torna potencialmente atraente para o golfe:

Então, como espremer os últimos bytes do meu programa Kotlin? Uma dica por resposta, por favor.

Tyler MacDonell
fonte
2
Haveria interesse em um idioma para o golfe que encurte alguns dos nomes mais longos de Kotlin, mas não adicione muitos extras (pelo menos inicialmente)? Estou pensando em fazer uma letra comum, diminuir as contagens de caracteres e adicionar cadeias de uma única letra com apenas 1 aspas?
jrtapsell
* Funções comuns
jrtapsell
Parece Kotlin interesse golfe não é que :( altos data.stackexchange.com/codegolf/query/793250/top-kotlin-golfers
jrtapsell
Pretendo começar a enviar mais soluções Kotlin! Vou ter que verificar esse seu projeto também.
Tyler MacDonell

Respostas:

4

Funções de extensão

As funções de extensão podem realmente ajudar a reduzir os nomes dos métodos incorporados e as cadeias deles, um exemplo pode ser:

fun String.c() = this.split("").groupingBy{it}.eachCount()

mas isso só ajuda se:

A) A chamada é longa o suficiente para cancelar a definição

B) A chamada é repetida

Uso de lambdas em vez de métodos

Lambdas pode retornar sem usar a palavra-chave return, salvando bytes

KotlinGolfer

Um projeto que eu comecei aqui, que pega bastante o código Kotlin e fornece postagens com testes e links TIO automaticamente

jrtapsell
fonte
4

Use em +vez detoString

Como seria de esperar, Stringsobrecarrega o +operador para concatenação de cadeias de caracteres, assim.

print("Hel" + "lo")

No entanto, verificar os documentos nos diz que aceita Any?, não apenas String. Como declarado:

Retorna uma string obtida concatenando essa string com a representação de string do outro objeto fornecido.

Em outras palavras, String + anythingcertifique-se de ligar .toString()do lado direito antes de concatenar. Isso nos permite reduzir it.toString()para ""+ituma economia massiva de 8 bytes na melhor das hipóteses e 6 bytes na pior.


Use em foldvez dejoinToString

Relacionado ao acima, se você estiver ligando mape joinToString, em seguida , poderá reduzi-lo usando fold.

list.map{it.repeat(3)}.joinToString("")
list.fold(""){a,v->a+v.repeat(3)}
Caracol_
fonte
TIL fold é uma coisa legal
Quinn
1

Definindo Int's em params

Isso provavelmente terá alguns casos de uso bastante específicos, nos quais pode valer a pena, mas na pergunta recente que joguei, descobri que poderia salvar alguns bytes definindo minha variável como parâmetros opcionais em vez de defini-los na função.

Exemplo da minha resposta a esta pergunta:

variável definidora na função:

fun String.j()={var b=count{'-'==it}/2;var a=count{'/'==it};listOf(count{'o'==it}-a,a-b,b)}

definindo variáveis ​​como parâmetros:

fun String.j(b:Int=count{'-'==it}/2,a:Int=count{'/'==it})=listOf(count{'o'==it}-a,a-b,b)

porque var a=tem o mesmo comprimento, a:Int=pois será o mesmo número de bytes para defini-los (este é apenas o caso Int), no entanto, como agora tenho apenas 1 linha na função, posso soltar o {}e solto também um ;(o outro é substituído por a ,)

Portanto, se houver alguma função que exija a definição de um Int e um liner 1 se você não definir o int na função - fazê-lo como um parâmetro economizará alguns bytes

Quinn
fonte
0

A tofunção infix

Existe uma função infix padrão denominada toque cria Pairs de dois valores. É comumente usado com mapOf()para definir Maps, mas pode ser muito mais curto que o Pair()construtor.

Pair(foo,bar)   //constructor
foo to bar      //best case 
(foo)to(bar)
((foo)to(bar))  //worst case
Caracol_
fonte
0

Reestruturação em argumentos lambda

Digamos que você queira aceitar um Pair<*,*>em um lambda. Normalmente, lidar com isso seria irritante. Como exemplo, aqui está um lambda que pega ae Pairverifica se os dois valores são iguais:

{it.first==it.second}

Isso é longo e desajeitado. Felizmente, Kotlin permite desestruturar qualquer tipo destructable (qualquer tipo que implementa componentN()métodos, tais como Pair, Tripleetc.) como argumentos para um lambda. Portanto, podemos reescrever isso da seguinte maneira:

{(a,b)->a==b}

É semelhante ao padrão que corresponde a uma tupla em algo como F # e, em muitos casos, é. Mas uma grande variedade de tipos no Kotlin suporta a desestruturação ( MatchResulté útil).

Você pode ter mais argumentos, no entanto. Digamos que o seu lambda teve que assumir um Pairvalor adicional. Você simplesmente escreveria a assinatura lambda assim:

(a,b),c->  // pair first
a,(b,c)->  // pair second
Caracol_
fonte