Racket 范围内的 [S:N] 宏 [英] Macro of [S:N] for in-range in Racket

查看:40
本文介绍了Racket 范围内的 [S:N] 宏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何创建一个宏,以便 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) 的步骤,其中 SN 是数字.

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

  1. 制作一个宏 my-top 使得 (my-top S:N) 扩展为 (range SN).
  2. 将您的宏保存在文件 my-top.rkt 中并使用 (provide (rename-out [my-top #%top])) 导出..立>
  3. 像这样使用你的新结构:
  1. Make a macro my-top such that (my-top S:N) expands to (range S N).
  2. Save your macro in file my-top.rkt and export it using (provide (rename-out [my-top #%top])).
  3. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆