Tipps zum Golfen im Racket / Schema

15

Welche allgemeinen Tipps haben Sie zum Golfen in Racket / Scheme ? Ich bin auf der Suche nach Ideen, die generell auf Code-Golf-Probleme angewendet werden können, die zumindest etwas spezifisch für Racket / Scheme sind (z. B. "Kommentare entfernen" ist keine Antwort).


Ich bin mir bewusst, dass Schema und Racket (früher PLT-Schema) technisch unterschiedliche Sprachen sind, sich jedoch in vielerlei Hinsicht sehr ähnlich sind und dass viel Code (ich vermute) in beiden Fällen meistens wie vorgesehen ausgeführt wird. Wenn Ihr Tipp nur für eine der oben genannten Sprachen gilt, beachten Sie dies als solche.

Katze
quelle

Antworten:

3

Die Ausdrücke 'x, `x, ,x, ein ,@xerweitert automatisch (quote x), (quasiquote x), (unquote x), und (unquote-splicing x), respectively. Dies ist eine reine syntaktische Transformation und kann überall angewendet werden. Dies gibt eine bequeme Notation für Funktionen mit einer Variablen:

; Defining a function:
(define ,x (+ x x))
; Calling a function:
(display ,2)

das erweitert sich zu

; Defining a function:
(define (unquote x) (+ x x))
; Calling a function:
(display (unquote 2))

Ich bin nicht sicher, wie die Semantik für das Shadowing eines syntaktischen Schlüsselworts wie quoteoder quasiquotemit einer gebundenen Variablen aussieht, obwohl Code wie der oben beschriebene in den von mir getesteten Interpreten funktioniert hat und unquote-splicingnicht ideal ist, da er eine zweistellige Abkürzung hat, aber unquoteist eine Hilfssyntax mit einer einstelligen Abkürzung und ist daher ideal für diesen Hack.

Itai Bar-Natan
quelle
8

In Racket , λund lambdasind auch Schlüsselwörter für anonyme Funktionen konstruieren, sondern λsind 2 Bytes , wobei lambda6.

In Schema gibt es kein solches Schlüsselwort λund Sie bleiben dabei lambda.

Katze
quelle
6

Verwenden Sie ~adiese Option , um Zahlen und Symbole in Zeichenfolgen umzuwandeln.

Soegaard
quelle
5

Wenn Sie Racket verwenden , binden Sie Variablen mit λ, um einige Bytes zu sparen. In Schema , lambdamacht diesen Trick nicht anwendbar, es sei denn , man vier oder mehr Variablen ist verbindlich.

Beispiel: Eine Variable speichert 2 Bytes über let/define

(define n 55)(* n n) ; 20 bytes

(let([n 55])(* n n)) ; 20 bytes

((λ(n)(* n n))55) ; 18 bytes
Winny
quelle
Das würde ich nicht verbindlich nennen. Sie verwenden verschiedene Funktionen. In einigen Fällen ist die Verwendung einer anonymen Funktion kürzer als das Binden einer Variablen.
Michael Vehrs
Ich bin mir nicht sicher, was Ihre Meinung mit der typischen Terminologie in Schemakreisen zu tun hat . Ich kann Ihnen versichern, dass beide Methoden Variablen an einen lexikalischen Bereich binden und lethäufig in Bezug auf implementiert werden lambda.
Winny
5

In Racket können requireFormulare mehrere Argumente enthalten.

(require net/url net/uri-codec)

Ist viel kürzer als

(require net/url)(require net/uri-codec)

Ich weiß nicht viel über Schema , aber es scheint kein requireeingebautes zu haben .

Katze
quelle
5

Verwenden Sie kürzere Synonyme

Es gibt eine Reihe von Prozeduren in Racket, die meistens äquivalente kürzere Versionen haben. (Sie sind normalerweise nicht gleichwertig: Funktioniert beispielsweise dort, (car (cons 1 2))wo (first (cons 1 2))Fehler auftreten. Sie können die Substitution jedoch vornehmen, wenn Sie wissen, dass sie in Ihrem Fall Synonyme sind.)

Diese Liste ist wahrscheinlich unvollständig: Ich weiß wahrscheinlich noch nichts über die meisten Dinge, die in dieser Liste enthalten sein könnten.

  • (= a b)anstatt (equal? a b)beim Vergleichen von Zahlen.
  • '(1 2)statt (list 1 2).
  • car, cadr, cdrFür first, second, und rest.
  • null? Anstatt von empty?
  • modulostatt remainderwenn der Modul positiv ist.
  • floorstatt truncatewenn sein Argument positiv ist.
Mischa Lawrow
quelle
4

Lass unnötige Leerzeichen weg

Dies kann als "trivialer" Tipp angesehen werden, auf den man jedoch irgendwo hinweisen muss.

Jedes Mal, wenn Sie den von normalen Leuten geschriebenen Schlägercode lesen (z. B. in der Schlägerdokumentation ), werden alle Leerzeichen eingefügt:

(append (list 1 2) (list 3 4) (list 5 6) (list 7 8))

In der Tat, da (und )kann nicht Teil von Variablennamen, können wir alle Räume um sie löschen und nicht verlieren jede Zweideutigkeit (und, was noch wichtiger ist , nach wie vor gültigen Code bekommen). Der obige Ausdruck kann also stattdessen sein:

(append(list 1 2)(list 3 4)(list 5 6)(list 7 8))
Mischa Lawrow
quelle
2

Die folgenden Tipps gelten für Schläger :

Standardargumente

Besonders nützlich zum Erstellen von Aliasnamen für lange Funktionsnamen, die häufig verwendet werden.

Angenommen, Sie können mit Golf eine Funktion schreiben, die das Argument aufnimmt, und Sie müssen reverseviel verwenden. Sie beginnen mit etwas wie:

(λ(x) ... reverse ... reverse ... reverse ...

Sie können stattdessen ein zusätzliches Argument mit einem kürzeren Namen als reverseeingeben und den Standardwert auf Folgendes festlegen reverse:

(λ(x[r reverse]) ... r ... r ... r ...

Darüber hinaus ist es nützlich, wenn Sie eine Hilfsfunktion haben, die Sie an vielen Stellen mit einigen der gleichen Argumente verwenden. Denken Sie daran, die Argumente für die Funktion nach Bedarf neu anzuordnen, damit Sie so viele Standardargumente wie möglich verwenden und die Argumente von mehreren Aufrufseiten entfernen können.

match

Dieser ist etwas schwieriger in einem kleinen Beitrag zusammenzufassen, lesen Sie die Racket-Dokumentation für diesen. matchKurz gesagt: Ermöglicht das Extrahieren von Elementen und Elementsequenzen in einer bestimmten Reihenfolge aus einer Liste. Mit der Quasiquote-Syntax können Sie die verstümmelte Liste wieder zusammenfügen:

(match (range 10)
 [`(,xs ... 3 ,ys ... 6 ,zs ...)
  `(,@(map f xs) 3 ,@(map f ys) 6 ,@(map f sz))]
 ...

Außerdem können Sie auf einfache Weise mit regulären Ausdrücken arbeiten und anschließend zusätzliche Berechnungen für die resultierenden Gruppen durchführen.

Genannt let

Die angegebene Syntax finden Sie hier .let proc-id ...

Auf diese Weise können Sie rekursive Funktionen schreiben, die sofort aufgerufen werden, ohne definedie Funktion aufzurufen oder tatsächlich aufzurufen, nachdem Sie sie definiert haben.

Etwas wie:

(define (fib i)
  (if (< i 2) i
      (+ (fib (- i 1)) (fib (- i 2)))))
(fib 10)

kann gekürzt werden auf:

(let fib {[i 10]}
  (if (< i 2) i
      (+ (fib (- i 1)) (fib (- i 2)))))


Letzteres ist albern, aber ich habe diesen kleinen Trick bisher nirgends anwenden können:
(apply map list matrix)Nimmt eine Transponierung von matrix, wo matrixeine rechteckige Liste von Listen ist, wie '((1 2 3) (a b c)).
Lassen Sie mich wissen, ob dies nützlich ist.

waf9000
quelle
1

Wie Winny hervorhob , #!kann in der Regel anstelle von #langvier Bytes gespart werden.

#lang racket ;12 bytes
#!racket ;8 bytes
dfeuer
quelle