Golftipps in Kotlin

22

Angesichts der kürzlich von Google angekündigten offiziellen Kotlin- Unterstützung für die Android-Entwicklung hielt ich es für angebracht, die Community nach einigen großartigen Golftipps für diese relativ neue JVM-Sprache zu befragen.

Kotlin bietet eine einzigartige Kombination von Merkmalen unter seinen JVM-Geschwistern, die es potenziell attraktiv für das Golfen macht:

Wie quetsche ich die letzten Bytes aus meinem Kotlin-Programm? Ein Tipp pro Antwort, bitte.

Tyler MacDonell
quelle
2
Würde es Interesse an einer Golfsprache geben, die einige von Kotlins längeren Namen verkürzt, aber nicht viele Extras hinzufügt (zumindest anfangs)? Ich denke darüber nach, einen gemeinsamen Buchstaben zu machen, die Anzahl der Zeichen in Strings zu verringern und einzelne Buchstaben mit nur 1 Anführungszeichen hinzuzufügen.
Jrtapsell
* Gemeinsame Funktionen
jrtapsell
Das Golfinteresse von Kotlin scheint nicht so hoch zu sein :( data.stackexchange.com/codegolf/query/793250/top-kotlin-golfers
jrtapsell
Ich plane, mehr Kotlin-Lösungen einzureichen! Ich muss auch Ihr Projekt überprüfen.
Tyler MacDonell

Antworten:

4

Erweiterungsfunktionen

Erweiterungsfunktionen können wirklich dazu beitragen, die Namen der eingebauten Methoden und ihrer Ketten zu reduzieren. Ein Beispiel könnte sein:

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

das hilft aber nur wenn:

A) Der Anruf ist lang genug, um die Definition aufzuheben

B) Der Anruf wird wiederholt

Verwendung von Lambdas anstelle von Methoden

Lambdas können zurückkehren, ohne das Schlüsselwort return zu verwenden, wodurch Bytes gespart werden

KotlinGolfer

Ein Projekt, das ich hier gestartet habe und das hübschen Kotlin-Code nimmt und automatisch Beiträge mit Tests und TIO-Links erstellt

jrtapsell
quelle
4

Verwenden Sie +anstelle vontoString

Wie zu erwarten ist, wird Stringder +Operator für die Verkettung von Zeichenfolgen wie folgt überlastet .

print("Hel" + "lo")

Das Überprüfen der Dokumente zeigt uns jedoch, dass dies Any?nicht nur akzeptiert wird String. Wie angegeben:

Gibt eine Zeichenfolge zurück, die durch Verketten dieser Zeichenfolge mit der Zeichenfolgendarstellung des angegebenen anderen Objekts erhalten wurde.

Stellen Sie also String + anythingsicher, dass Sie .toString()vor dem Verketten auf der rechten Seite aufrufen . Dies ermöglicht uns eine Verkürzung it.toString()auf ""+itmassive 8-Byte-Einsparungen im besten Fall und 6-Byte-Einsparungen im schlechtesten Fall.


Verwenden Sie foldanstelle vonjoinToString

Im Zusammenhang mit dem oben, wenn Sie anrufen mapund dann joinToStringkönnen Sie , dass verkürzen , indem Sie foldstatt.

list.map{it.repeat(3)}.joinToString("")
list.fold(""){a,v->a+v.repeat(3)}
Schnecke_
quelle
Bis Fold ist eine Sache, nett
Quinn
1

Int's in params definieren

Dies wird wahrscheinlich einige ziemlich spezifische Anwendungsfälle haben, in denen es sich lohnt, aber in der letzten Frage, die ich gestellt habe, konnte ich ein paar Bytes einsparen, indem ich meine Variable als optionale Parameter definierte, anstatt sie in der Funktion zu definieren.

Beispiel aus meiner Antwort auf diese Frage:

Variable in der Funktion definieren:

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

Variablen als Parameter definieren:

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

weil var a=es die gleiche Länge hat, wie a:Int=es die gleiche Anzahl von Bytes ist, um sie zu definieren (dies ist jedoch nur der Fall Int), da ich jetzt nur eine Zeile in der Funktion habe, kann ich die löschen {}und ich lösche auch eine einzelne ;(die andere ist) ersetzt durch a ,)

Wenn es also Funktionen gibt, für die ein Int definiert werden muss, und wenn Sie das Int in der Funktion nicht definiert haben, ist dies ein 1-Liner. Wenn Sie dies als Parameter tun, sparen Sie ein paar Bytes

Quinn
quelle
0

Die toInfix-Funktion

Es gibt eine Standard-Infix-Funktion to, die Pairs aus zwei Werten erstellt. Es wird häufig mapOf()für die Definition von Maps verwendet, kann aber möglicherweise viel kürzer als der Pair()Konstruktor sein.

Pair(foo,bar)   //constructor
foo to bar      //best case 
(foo)to(bar)
((foo)to(bar))  //worst case
Schnecke_
quelle
0

Zerstörung in Lambda-Argumenten

Angenommen, Sie möchten ein Pair<*,*>in einem Lambda akzeptieren . Normalerweise wäre der Umgang damit ärgerlich. Als Beispiel ist hier ein Lambda, das ein Pairund prüft, ob die beiden Werte gleich sind:

{it.first==it.second}

Das ist langatmig und ungeschickt. Glücklicherweise Kotlin kann Sie jeden zerstörbaren Typen destrukturiert (jede Art , dass Geräte componentN()Methoden, wie zum Beispiel Pair, Tripleetc.) als Argument an ein Lambda. Wir können dies also folgendermaßen umschreiben:

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

Es sieht ähnlich aus wie die Mustererkennung für ein Tupel in so etwas wie F #, und es ist in vielen Fällen. Aber eine Vielzahl von Typen in Kotlin unterstützen die Destrukturierung ( MatchResultist nützlich).

Sie können jedoch weitere Argumente verwenden. Angenommen, Ihr Lambda musste einen Pairund einen zusätzlichen Wert annehmen . Sie schreiben die Lambda-Signatur einfach so:

(a,b),c->  // pair first
a,(b,c)->  // pair second
Schnecke_
quelle