Wskazówki dotyczące gry w golfa w Racket / Scheme


15

Jakie masz ogólne wskazówki na temat gry w golfa w Racket / Scheme ? Szukam pomysłów, które można by zastosować do ogólnych problemów z golfem, które są przynajmniej nieco specyficzne dla Racket / Scheme (np. „Usuń komentarze” nie jest odpowiedzią).


Wiem, że Scheme i Racket (wcześniej PLT Scheme) są technicznie różnymi językami, ale są dość podobne pod wieloma względami i wiele kodu (podejrzewam) będzie działało głównie zgodnie z przeznaczeniem w obu. Jeśli wskazówka dotyczy tylko jednego z wyżej wymienionych języków, należy pamiętać o tym.

Odpowiedzi:


3

Wyrażenia 'x, `x, ,x, ,@xautomatycznie powiększy się (quote x), (quasiquote x), (unquote x), i (unquote-splicing x), odpowiednio. Jest to czysto syntaktyczna transformacja i można ją zastosować w dowolnym miejscu. Daje to wygodny zapis funkcji jednej zmiennej:

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

który rozwija się do

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

Nie jestem pewien, co to jest semantyka dla cieniowania składniowego słowa kluczowego, takiego jak quotelub quasiquoteze zmienną powiązaną, chociaż kod podobny do powyższego działał w interpretatorach, na których testowałem, i unquote-splicingjest mniej niż idealny, ponieważ ma dwuznakowy skrót, ale unquotejest składnią pomocniczą z jednoznakowym skrótem, dlatego idealnie nadaje się do tego włamania.


8

W Racket , λi lambdasą synonimicznymi słowami kluczowymi do konstruowania anonimowych funkcji, ale λsą 2 bajty, gdzie lambdajest 6.

W schemacie nie ma takiego słowa kluczowego λi utkniesz lambda.



5

Korzystając z rakiety , połącz zmienne za pomocą, λaby zgolić kilka bajtów. Na schemacielambda sprawia , że ta sztuczka nie ma zastosowania, chyba że jedna wiąże cztery lub więcej zmiennych.

Przykład: Jedna zmienna zapisuje 2 bajty ponad let/define

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

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

((λ(n)(* n n))55) ; 18 bytes

Nie nazwałbym tego wiążącym. Używasz różnych funkcji. W niektórych przypadkach użycie funkcji anonimowej jest krótsze niż powiązanie zmiennej.
Michael Vehrs,

Nie jestem pewien, co twoja opinia ma wspólnego z typową terminologią stosowaną w kręgach schematów. Mogę zapewnić, że oba sposoby wiążą zmienne z zakresem leksykalnym i letczęsto są implementowane pod względem lambda.
Winny

5

W Racket , requireformy może mieć wiele argumentów.

(require net/url net/uri-codec)

Jest o wiele krótszy niż

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

Nie wiem dużo o Schemacie , ale wydaje się, że nie ma on requirewbudowanego.


5

Używaj krótszych synonimów

W Racket istnieje wiele procedur, które mają w większości równoważne krótsze wersje. (Zwykle nie są równoważne: na przykład (car (cons 1 2))działa tam , gdzie (first (cons 1 2))zawodzi. Ale możesz dokonać zamiany, jeśli wiesz, że w twoim przypadku są to synonimy).

Ta lista jest prawdopodobnie niekompletna: prawdopodobnie nie wiem jeszcze o większości rzeczy, które mogłyby się na niej znaleźć.

  • (= a b)zamiast (equal? a b)przy porównywaniu liczb.
  • '(1 2)zamiast (list 1 2).
  • car, cadr, cdrO first, secondi rest.
  • null? zamiast empty?
  • modulozamiast remaindergdy moduł jest dodatni.
  • floorzamiast truncatekiedy jego argument jest pozytywny.

4

Pomiń niepotrzebne spacje

Można to uznać za „trywialną” wskazówkę, ale trzeba ją gdzieś wskazać.

Za każdym razem, gdy czytasz kod rakiety napisany przez zwykłych ludzi (np. W dokumentacji rakiety ), zostaną wstawione wszystkie spacje: na przykład,

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

W rzeczywistości, ponieważ (i )nie mogą być częścią nazw zmiennych, możemy usunąć wszystkie spacje wokół nich i nie stracić żadnych dwuznaczności (a co ważniejsze, nadal uzyskać poprawny kod). Zatem powyższym wyrażeniem może być:

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

2

Poniższe wskazówki dotyczą rakiety :

Domyślne argumenty

Szczególnie przydatne do tworzenia aliasów dla często używanych długich nazw funkcji.

Załóżmy, że golf pozwala napisać funkcję, która zużywa argument, i zakładamy, że trzeba reversedużo używać . Zaczniesz od czegoś takiego:

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

Zamiast tego możesz wziąć dodatkowy argument o krótszej nazwie niż reversei ustawić jego wartość domyślną na reverse:

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

Co więcej, jest to przydatne, jeśli masz funkcję pomocniczą, której używasz w wielu miejscach z tymi samymi argumentami. Pamiętaj, aby w razie potrzeby zmienić kolejność argumentów funkcji, aby można było użyć jak największej liczby argumentów domyślnych i usunąć argumenty z wielu stron wywoławczych.

match

Ten jest nieco trudniejszy do streszczenia w małym poście, więc przeczytaj go w Dokumentach dotyczących rakiet . W skrócie, matchpozwala wyodrębnić elementy i sekwencje elementów w określonej kolejności z listy, a quasi-cytatowa składnia pozwala ponownie połączyć okaleczoną listę:

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

Zapewnia również łatwy sposób pracy z wyrażeniami regularnymi i późniejszego obliczania grup wynikowych,

O imieniu let

Zobacz nazwaną składnię tutaj .let proc-id ...

Pozwala to na pisanie funkcji rekurencyjnych, które są wywoływane natychmiast bez definelub faktycznie wywołują funkcję po jej zdefiniowaniu.

Coś jak:

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

można skrócić do:

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


Ta ostatnia jest głupia, ale jak dotąd nigdzie nie byłem w stanie użyć tej małej sztuczki:
(apply map list matrix)transponuję matrix, gdzie matrixjest jakaś prostokątna lista list '((1 2 3) (a b c)).
Daj mi znać, jeśli okaże się to przydatne.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.