Советы по игре в гольф в Ракетке / Схеме


15

Какие общие советы у вас есть для игры в гольф в Racket / Scheme ? Я ищу идеи, которые могут быть применены к задачам по коду для гольфа в целом, которые, по крайней мере, несколько специфичны для Racket / Scheme (например, «удалить комментарии» - это не ответ).


Я знаю, что Scheme и Racket (ранее PLT Scheme) были технически разными языками, но во многих отношениях они очень похожи, и большая часть кода (я подозреваю) будет работать в основном так, как задумано. Если ваш совет относится только к одному из вышеупомянутых языков, обратите внимание как таковое.

Ответы:


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.


6

Используйте ~aдля преобразования чисел и символов в строки.


5

При использовании Racket , связывайте переменные, используя, λчтобы сбрить несколько байтов. В схеме ,lambda делает этот прием не применяется, если один не является обязательным для четырех или более переменных.

Пример: одна переменная сохраняет на 2 байта больше let/define

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

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

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

Я бы не назвал это обязательным. Вы используете разные функции. В некоторых случаях использование анонимной функции короче, чем привязка переменной.
Майкл Vehrs

Я не уверен, что ваше мнение связано с типичной терминологией, используемой в кругах схемы. Я могу заверить вас, что оба способа привязывают переменные к лексической области и letчасто реализуются в терминах lambda.
Винни

5

В Ракетка , requireформы могут иметь несколько аргументов.

(require net/url net/uri-codec)

Это намного короче, чем

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

Я не знаю много о Схеме , но, похоже, в ней нет requireвстроенной функции.


5

Используйте более короткие синонимы

В Racket есть ряд процедур, которые имеют в основном эквивалентные более короткие версии. (Они обычно не эквивалентны: например, (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

Пропустить ненужные пробелы

Это может считаться «тривиальным» отзывом, но на него нужно что-то указывать.

Каждый раз, когда вы читаете код Racket, написанный обычными людьми (например, в документации по Racket ), в него будут вставлены все пробелы: например,

(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

Это немного сложнее подвести итог в небольшом посте, так что читайте на Racket Docs для этого. В двух словах, 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.