Consejos para jugar al golf en Racket / Scheme

15

¿Qué consejos generales tienes para jugar al golf en Racket / Scheme ? Estoy buscando ideas que puedan aplicarse a los problemas de golf de código en general que sean al menos algo específicos para Racket / Scheme (por ejemplo, "eliminar comentarios" no es una respuesta).


Sé que Scheme and Racket (anteriormente PLT Scheme) son lenguajes técnicamente diferentes, pero son bastante similares en muchos aspectos y sospecho que mucho código se ejecutará principalmente según lo previsto. Si su sugerencia solo se aplica a uno de los idiomas mencionados anteriormente, tenga en cuenta como tal.

gato
fuente

Respuestas:

3

Las expresiones 'x, `x, ,x, un ,@xexpanden automáticamente a (quote x), (quasiquote x), (unquote x), y (unquote-splicing x), respectivamente. Esto es puramente una transformación sintáctica, y se puede aplicar en cualquier lugar. Esto proporciona una notación conveniente para funciones de una variable:

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

que se expande a

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

No estoy seguro de cuál es la semántica para sombrear una palabra clave sintáctica como quoteo quasiquotecon una variable enlazada, aunque un código como el anterior funcionó en los intérpretes en los que lo probé, y unquote-splicinges menos que ideal ya que tiene una abreviatura de dos caracteres, pero unquotees una sintaxis auxiliar con una abreviatura de un carácter, por lo que es ideal para este truco.

Itai Bar-Natan
fuente
8

En Racket , λy lambdason palabras clave sinónimas para construir funciones anónimas, pero λes de 2 bytes, donde lambdaes 6.

En Scheme , no existe esa palabra clave λy estás atrapado lambda.

gato
fuente
6

Se usa ~apara convertir números y símbolos en cadenas.

soegaard
fuente
5

Cuando se usa Racket , se unen las variables que se usan λpara reducir algunos bytes. En el esquema ,lambda hace que este truco no sea aplicable, a menos que uno enlace cuatro o más variables.

Ejemplo: una variable guarda 2 bytes sobre let/define

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

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

((λ(n)(* n n))55) ; 18 bytes
Winny
fuente
No llamaría a eso vinculante. Estás usando diferentes funciones. En algunos casos, usar una función anónima es más corto que vincular una variable.
Michael Vehrs
No estoy seguro de qué tiene que ver su opinión con la terminología típica utilizada en los círculos de esquemas. Les puedo asegurar que ambas formas son variables vinculantes para un ámbito léxico, y que a menudo se implementa en términos de . letlambda
Winny
5

En raqueta , los requireformularios pueden tener múltiples argumentos.

(require net/url net/uri-codec)

Es mucho más corto que

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

No sé mucho acerca de Scheme , pero no parece tener una función requireincorporada.

gato
fuente
5

Usa sinónimos más cortos

Hay una serie de procedimientos en Racket que tienen versiones más cortas en su mayoría equivalentes. (Por lo general, no son equivalentes: por ejemplo, (car (cons 1 2))funciona donde (first (cons 1 2))falla. Pero puede hacer la sustitución si sabe que son sinónimos en su caso).

Esta lista probablemente esté incompleta: probablemente todavía no conozco la mayoría de las cosas que podrían incluirse en esta lista.

  • (= a b)en lugar de (equal? a b)al comparar números.
  • '(1 2)en lugar de (list 1 2).
  • car, cadr, cdrPara first, second, y rest.
  • null? en lugar de empty?
  • moduloen lugar de remaindercuando el módulo es positivo.
  • flooren lugar de truncatecuando su argumento es positivo.
Misha Lavrov
fuente
4

Omitir espacios innecesarios

Esto puede considerarse un consejo "trivial", pero debe señalarse en alguna parte.

Cada vez que lea el código de Racket escrito por personas normales (por ejemplo, en la documentación de Racket ) tendrá todos los espacios puestos: por ejemplo,

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

De hecho, desde (y )no puede ser parte de nombres de variables, podemos eliminar todos los espacios alrededor de ellos y no perder ninguna ambigüedad (y, más importante, aún así obtener un código válido). Entonces, la expresión anterior puede ser:

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

Los siguientes consejos son para Racket :

Argumentos predeterminados

Especialmente útil para crear alias para nombres largos de funciones que se usan con frecuencia.

Suponga que el golf le permite escribir una función que consume el argumento, y suponga que necesita usar reversemucho. Comenzarás con algo como:

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

En su lugar, puede tomar un argumento adicional, con un nombre más corto que reverse, y establecer su valor predeterminado en reverse:

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

Además, es útil si tiene una función auxiliar que usa en muchos lugares con algunos de los mismos argumentos. Recuerde reordenar los argumentos a la función según sea necesario, para que pueda usar tantos argumentos predeterminados como sea posible y eliminar los argumentos de múltiples sitios de llamadas.

match

Este es un poco más difícil de resumir en una publicación pequeña, así que lea sobre Racket Docs para este. En pocas palabras, le matchpermite extraer elementos y secuencias de elementos en un cierto orden de una lista, y la sintaxis de cuasiquote le permite volver a unir la lista mutilada:

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

También le brinda una manera fácil de trabajar con expresiones regulares y realizar cálculos adicionales en los grupos resultantes después,

Llamado let

Vea la sintaxis nombrada aquí .let proc-id ...

Esto le permite escribir funciones recursivas que se llaman inmediatamente sin defineo realmente llamando a la función después de haberla definido.

Algo como:

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

se puede acortar a:

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


Este último es una tontería, pero hasta ahora no he podido usar este pequeño truco en ninguna parte:
(apply map list matrix)toma una transposición de matrix, donde matrixhay una lista rectangular de listas, como '((1 2 3) (a b c)).
Avíseme si esto resulta útil.

waf9000
fuente
1

Como señaló Winny , #!generalmente se puede usar en lugar de #langahorrar cuatro bytes.

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