Dicas para jogar golfe em raquete / esquema


15

Que dicas gerais você tem para jogar golfe no Racket / Scheme ? Estou procurando idéias que possam ser aplicadas aos problemas de código de golfe em geral, que sejam pelo menos um pouco específicos para a raquete / esquema (por exemplo, "remover comentários" não é uma resposta).


Estou ciente de que Scheme e Racket (anteriormente PLT Scheme) são linguagens tecnicamente diferentes, mas são bastante similares em muitos aspectos e muito código (suspeito) será executado principalmente como pretendido. Se sua dica se aplicar apenas a um dos idiomas mencionados acima, observe como tal.

Respostas:


3

As expressões 'x, `x, ,x, um ,@xexpandir automaticamente para (quote x), (quasiquote x), (unquote x)e (unquote-splicing x), respectivamente. Isso é puramente uma transformação sintática e pode ser aplicada em qualquer lugar. Isso fornece uma notação conveniente para funções de uma variável:

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

que se expande para

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

Não sei ao certo qual é a semântica para sombrear uma palavra-chave sintática como quoteou quasiquotecom uma variável vinculada, embora um código como o acima tenha funcionado nos intérpretes em que o testei e unquote-splicingseja menos do que o ideal, pois possui uma abreviação de dois caracteres, mas unquoteé uma sintaxe auxiliar com uma abreviação de um caractere e, portanto, é ideal para esse hack.


8

Em Raquete , λe lambdasão palavras-chave sinônimas para a construção de funções anônimas, mas λsão 2 bytes lambdae 6.

No esquema , não existe tal palavra λ- chave e você está preso lambda.


6

Use ~apara converter números e símbolos em seqüências de caracteres.


5

Ao usar o Raquete , vincule variáveis ​​usando λpara reduzir alguns bytes. No esquema , lambdatorna esse truque não aplicável, a menos que um esteja vinculando quatro ou mais variáveis.

Exemplo: Uma variável salva 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

Eu não chamaria isso de ligação. Você está usando funções diferentes. Em alguns casos, o uso de uma função anônima é mais curto que a ligação de uma variável.
Michael Vehrs 17/03/19

Não tenho certeza do que sua opinião tem a ver com a terminologia típica usada nos círculos de esquema. Posso garantir que as duas maneiras são variáveis ​​vinculativas a um escopo lexical e são frequentemente implementadas em termos de . letlambda
Winny

5

No Raquete , os requireformulários podem ter vários argumentos.

(require net/url net/uri-codec)

É bem menor que

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

Eu não sei muito sobre o Scheme , mas ele não parece ter um requirebuiltin.


5

Use sinônimos mais curtos

Existem vários procedimentos no Racket que têm versões mais curtas equivalentes. (Eles geralmente não são equivalentes: por exemplo, (car (cons 1 2))funciona onde (first (cons 1 2))falha. Mas você pode fazer a substituição se souber que são sinônimos no seu caso.)

Essa lista provavelmente está incompleta: eu provavelmente ainda não conheço a maioria das coisas que poderiam estar nessa lista.

  • (= a b)em vez de (equal? a b)comparar números.
  • '(1 2)em vez de (list 1 2).
  • car, cadr, cdrPara first, second, e rest.
  • null? ao invés de empty?
  • moduloem vez de remainderquando o módulo é positivo.
  • floorem vez de truncatequando seu argumento é positivo.

4

Omita espaços desnecessários

Isso pode ser considerado uma dica "trivial", mas precisa ser apontada em algum lugar.

Sempre que você ler o código do Racket escrito por pessoas normais (por exemplo, na documentação do Racket ), todos os espaços serão inseridos: por exemplo,

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

Na verdade, uma vez (e )não pode ser parte de nomes de variáveis, podemos eliminar todos os espaços em torno deles e não perder qualquer ambiguidade (e, mais importante, ainda obter um código válido). Portanto, a expressão acima pode ser:

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

2

As dicas a seguir são para o Racket :

Argumentos padrão

Especialmente útil para criar aliases para nomes longos de funções usados ​​com freqüência.

Suponha que o golfe permita escrever uma função que consome o argumento e suponha que você precise usar reversemuito. Você começará com algo como:

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

Em vez disso, você pode reverseusar um argumento adicional, com um nome menor que , e definir seu valor padrão para reverse:

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

Além disso, é útil se você tiver uma função auxiliar usada em muitos lugares com alguns dos mesmos argumentos. Lembre-se de reordenar os argumentos para a função, conforme necessário, para que você possa usar o maior número possível de argumentos padrão e remover os argumentos de vários callites.

match

Este é um pouco mais difícil de resumir em um pequeno post, então leia os Documentos da Raquete para este. Em poucas palavras, matchpermite extrair elementos e seqüências de elementos em uma determinada ordem de uma lista, e a sintaxe de quaseiquote permite costurar a lista mutilada novamente:

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

Também oferece uma maneira fácil de trabalhar com expressões regulares e fazer cálculos adicionais nos grupos resultantes posteriormente,

Nomeado let

Veja a sintaxe nomeada aquilet proc-id ... .

Isso permite que você escreva funções recursivas chamadas imediatamente sem define ou realmente chame a função depois que você a definir.

Algo como:

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

pode ser reduzido para:

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


Este último é bobo, mas não pude usar esse pequeno truque em nenhum lugar até agora:
(apply map list matrix)faz uma transposição de matrix, onde matrixestá uma lista retangular de listas, como '((1 2 3) (a b c)).
Deixe-me saber se isso é útil.


1

Como Winny apontou , #!geralmente pode ser usado em vez de #lang, economizando quatro bytes.

#lang racket ;12 bytes
#!racket ;8 bytes
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.