球拍/计划中的高尔夫技巧


15

您在球拍 / 计划中打高尔夫球有哪些一般提示?我正在寻找可用于编码高尔夫问题的想法,这些想法至少在某种程度上特定于球拍/计划(例如,“删除评论”不是答案)。


我知道SchemeRacket(以前称为PLT Scheme)在技术上是不同的语言,但是在许多方面都非常相似,并且很多代码(我怀疑)都将按两种方式运行。如果您的提示仅适用于上述一种语言,请注意。

Answers:


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))

我不确定用于遮盖句法关键字(例如quotequasiquote带有绑定变量)的语义,尽管上面的代码在我测试过的解释器中起作用,并且unquote-splicing由于具有两个字符的缩写而不太理想,但是unquote是带有一个字符的缩写的辅助语法,因此非常适合该hack。


8

Racket中λlambda是用于构造匿名函数的同义词关键字,但λ为2个字节,其中lambda为6。

Scheme中,没有这样的关键字λ,您被困住了lambda



5

使用Racket时,请使用绑定变量λ以舍弃一些字节。在Scheme中lambda使此技巧不适用,除非一个绑定了四个或更多变量。

示例:一个变量在let/上保存2个字节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

Racket中require表单可以具有多个参数。

(require net/url net/uri-codec)

比...短吗

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

我对Scheme不太了解,但似乎没有require内置函数。


5

使用较短的同义词

在Racket中,有许多程序具有几乎等效的较短版本。(它们通常不是等效的:例如,(car (cons 1 2))(first (cons 1 2))失败的地方可用。但是如果您知道它们在您的情况下是同义词,则可以进行替换。)

该列表可能是不完整的:我可能还不知道该列表中可能包含的大多数内容。

  • (= a b)而不是(equal? a b)比较数字时。
  • '(1 2)代替(list 1 2)
  • carcadrcdrfirstsecond,和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

以下是有关球拍的提示:

默认参数

对于为经常使用的长函数名创建别名特别有用。

假设golf允许您编写一个使用参数的函数,并假设您需要使用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))
让我知道这是否确实有用。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.