Поради щодо гольфу в ракетці / схемі


15

Які загальні поради щодо гольфу в ракетці / схемі ? Я шукаю ідеї, які можна застосувати до коду проблем із гольфом взагалі, які принаймні дещо специфічні для ракетки / схеми (наприклад, "видалити коментарі" - це не відповідь).


Мені відомо, що схема і ракетка (раніше PLT-схема) є технічно різними мовами, але багато в чому схожі, і багато коду (я підозрюю) працюватимуть здебільшого так, як планували в будь-якій. Якщо ваша порада стосується лише однієї з вищезгаданих мов, зверніть увагу на таке.

Відповіді:


3

Вирази 'x, `x, ,x, ,@xавтоматично розширюватися (quote x), (quasiquote x), (unquote x)і (unquote-splicing x), відповідно. Це суто синтаксична трансформація, і її можна застосувати будь-де. Це дає зручне позначення для однозмінних функцій:

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

який розширюється до

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

Я не впевнений, що таке семантика для затінення синтаксичного ключового слова, такого як quoteабо quasiquoteз прив’язаною змінною, хоча код, як описано вище, працював у інтерпретаторах, на яких я його перевіряв, і unquote-splicingє менш ідеальним, оскільки має двозначне абревіатуру, але unquote- це допоміжний синтаксис з односимвольним абревіатуром, тому ідеально підходить для цього хак.


8

У Ракетка , λі lambdaсинонімічні ключові слова для побудови анонімних функцій, але λє 2 байта , де lambdaзнаходиться 6.

У схемі такого ключового слова немає, λі ви застрягли lambda.



5

Використовуючи Ракетку , зв’яжіть змінні, використовуючи λдля гоління декількох байт. У схемі , lambdaробить цей прийом не застосовується, якщо один не є обов'язковим для чотирьох або більше змінних.

Приклад: одна змінна зберігає 2 байти на let/define

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

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

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

Я б не назвав це обов'язковим. Ви використовуєте різні функції. У деяких випадках використання анонімної функції коротше, ніж прив'язка змінної.
Michael Vehrs

Я не впевнений, що стосується вашої думки з типовою термінологією, що використовується у колах схем. Я можу запевнити, що обидва способи прив'язують змінні до лексичної сфери і letчасто реалізуються в термінах lambda.
Вінні

5

У Ракетка , requireформи можуть мати кілька аргументів.

(require net/url net/uri-codec)

Шлях коротший, ніж

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

Я не знаю багато про схему , але, здається, вона не має requireвбудованого.


5

Використовуйте коротші синоніми

У Ракетці є ряд процедур, які мають в основному еквівалентні більш короткі версії. (Вони, як правило, не рівноцінні: наприклад, (car (cons 1 2))працюють там, де (first (cons 1 2))не вдається. Але ви можете зробити заміну, якщо знаєте, що вони є синонімами у вашому випадку.)

Цей список, ймовірно, неповний: я, мабуть, ще не знаю про більшість речей, які могли б увійти до цього списку.

  • (= a b)замість (equal? a b)порівняння чисел.
  • '(1 2)замість (list 1 2).
  • car, cadr, cdrДля first, secondі rest.
  • null? замість empty?
  • moduloзамість того, remainderколи модуль позитивний.
  • floorзамість того, truncateколи його аргумент позитивний.

4

Пропустіть непотрібні місця

Це можна вважати «тривіальною» підказкою, але її треба десь вказати.

Щоразу, коли ви читаєте код ракетки, написаний звичайними людьми (наприклад, у документації на ракетку ), у ньому будуть введені всі пробіли: наприклад,

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

Насправді, оскільки (і )не може бути частиною імен змінних, ми можемо видалити всі пробіли навколо них і не втратити двозначності (і, що ще важливіше, все-таки отримати дійсний код). Отже, вищенаведеним виразом може бути:

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

2

Наступні поради щодо ракетки :

Аргументи за замовчуванням

Особливо корисно для створення псевдонімів для довгих імен функцій, які часто використовуються.

Припустимо, гольф дозволяє записати функцію, яка споживає аргументи, і припустимо, що потрібно reverseбагато використовувати . Ви почнете з чогось типу:

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

Ви можете замість цього взяти додатковий аргумент із скороченим іменем reverseта встановити його за замовчуванням reverse:

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

Крім того, це корисно, якщо у вас є допоміжна функція, яку ви використовуєте в багатьох місцях з одними і тими ж аргументами. Не забудьте змінити аргументи на функцію за необхідності, щоб ви могли використовувати якомога більше аргументів за замовчуванням та видаляти аргументи з декількох викликів.

match

Це трохи складніше узагальнити у невеликому дописі, тому читайте на Документах ракетки для цього. Коротше кажучи, matchви можете вилучити елементи та послідовності елементів у певному порядку зі списку, а синтаксис квазіцитату дозволяє зшивати зіпсований список назад разом:

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

Це також дає вам простий спосіб працювати з регулярними виразами та робити додаткові обчислення на отриманих групах згодом,

Іменований let

Дивіться названий синтаксис тут .let proc-id ...

Це дозволяє записувати рекурсивні функції, які викликаються негайно без defineабо фактично викликають функцію після того, як ви її визначили.

Щось на зразок:

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

можна скоротити до:

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


Цей останній дурний, але я поки не міг використовувати цю маленьку хитрість ніде:
(apply map list matrix)виконує перенесення matrix, де matrixє якийсь прямокутний список списків, наприклад '((1 2 3) (a b c)).
Повідомте мене, чи виявиться це корисним.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.