Racket 范围内的 [S:N] 宏 [英] Macro of [S:N] for in-range in Racket
问题描述
我如何创建一个宏,以便 S:N 或 [S:N] 返回一系列以 S 开头并以 N 结尾的数字(步骤 1).基本上,它应该能够使用它代替范围内".我尝试创建类似于 花括号 {} 来替换 Racket 中的开始" 但不能.
How can I create a macro so that S:N or [S:N] returns a range of numbers starting with S and ending with N (step 1). Basically, it should be able to use it in place of 'in-range'. I tried to create something similar to Curly brackets {} to replace 'begin' in Racket but could not.
我尝试按照@soegaard 的建议进行操作:
I tried following as suggested by @soegaard :
我的top.rkt:
#lang racket
(define-syntax-rule (my-top S:N)
(range S N) )
(provide (rename-out [my-top #%top]))
test.rkt:
#lang racket
(require "my-top.rkt")
(1:42)
但是它没有运行.错误是:
But it does not run. The error is:
#%top: use does not match pattern: (#%top S:N) in: (#%top . 1:42)
[1:42] 和 1:42 也不起作用.
[1:42] and 1:42 also do not work.
推荐答案
以下是使 S:N
扩展为 (range SN)
的步骤,其中 S
和 N
是数字.
Here are the steps to make S:N
expand to (range S N)
where S
and N
are numbers.
请注意,S:N
是一个标识符.因此,未绑定的 S:N
是未绑定的标识符.对未绑定标识符的引用 n
扩展为 (#%top . n)
.因此 1:42
扩展为 (#%top 1:42)
.
Note that S:N
is an identifier. Therefore an unbound S:N
is an unbound identifier. An reference to an unbound identifiers n
expand to (#%top . n)
.
Therefore 1:42
expands into (#%top 1:42)
.
- 制作一个宏
my-top
使得(my-top S:N)
扩展为(range SN)
. - 将您的宏保存在文件
my-top.rkt
中并使用(provide (rename-out [my-top #%top]))
导出..立> - 像这样使用你的新结构:
- Make a macro
my-top
such that(my-top S:N)
expands to(range S N)
. - Save your macro in file
my-top.rkt
and export it using(provide (rename-out [my-top #%top]))
. - Use your new construct like this:
.
#lang racket
(require "my-top.rkt")
1:42
第 1 步:
#lang racket
(require syntax/parse (for-syntax racket/match syntax/parse))
(begin-for-syntax
; contains-colon? : string -> boolean
; does the string str contain a colon?
(define (contains-colon? str)
(regexp-match ".*:.*" str))
; split-colon-string-into-numbers : string -> (list number number)
; for a string of the form N:S return a list consisting of the
; numbers corresponsing to the substrings N and S
(define (split-colon-string-into-numbers str)
(match (regexp-match "(.*):(.*)" str)
[(list _ S-str N-str)
(list (string->number S-str) (string->number N-str))]
[_else
(error 'split-colon-string-into-numbers
"expected string of the number <number>:<number>")])))
; SYNTAX (my-top . id)
; (my-top . id) behaves the same as (#%top . id)
; except when id has the form N:S in which case
; (my-top . id) behaves as (range N S)
(define-syntax (my-top stx)
(syntax-parse stx
[(_my-top . identifier:id)
(define str (symbol->string (syntax-e #'identifier)))
(cond
[(contains-colon? str)
(with-syntax ([(S N) (split-colon-string-into-numbers str)])
(syntax/loc stx
(range S N)))]
[else
#'(#%top . identifier)])]))
;;; Tests
(my-top . 1:5) ; evaluates to (1 2 3 4)
(define foo 42)
(my-top . foo) ; evaluates to 42
这篇关于Racket 范围内的 [S:N] 宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!