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.

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.


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.


6

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


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

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 .


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.

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))

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.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.