如何创建宏以使S:N或[S:N]返回以S开头并以N结尾的数字范围(步骤1)。基本上,它应该能够用它来代替范围内的'。我尝试创建类似Curly brackets {} to replace 'begin' in Racket的东西,但不能。
编辑:我尝试按照@soegaard的建议:
my-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)
但它没有运行。错误是:
#%top: use does not match pattern: (#%top S:N) in: (#%top . 1:42)
[1:42]和1:42也不起作用。
答案 0 :(得分:5)
Here are the steps to make S:N
expand to (range S N)
where S
and N
are numbers.
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
such that (my-top S:N)
expands to (range S N)
.my-top.rkt
and export it using (provide (rename-out [my-top #%top]))
..
#lang racket
(require "my-top.rkt")
1:42
Step 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
答案 1 :(得分:5)
@ soegaard的回答提供了一个基于#%top
的解决方案,当S:N
和S
是字面整数且N
未定义为S:N
时,该解决方案会展开[
标识符。但是,也可以使用阅读器宏来完成此操作。
我有两个版本:一个只适用于文字整数的简单版本,另一个适用于任意表达式的版本,包括变量。
此简单版本会覆盖[S:N]
以开始范围表达式,例如S
,其中N
和[
是字面整数。在:
之后,它会读取数字字符,直到找到]
,然后它会读取更多数字字符,直到找到range
。它将数字字符串转换为整数,并将这些整数放入表示#lang colon-range
;; simple range by itself
[1:42]
;; using a range within a more complicated expression
(for/list ((i [2:42])
#:when
(for/and ((j [2:41]) #:when (< j i))
(not (= 0 (remainder i j)))))
i)
函数调用的列表中。
它会像这样使用:
((i ....))
请注意,我使用的是([i ....])
而不是更常见的[
,因为我暂时无法使用]
和#lang colon-range
。
要实现colon-range/lang/reader.rkt
语言,您应该将阅读器实现放在colon-range
中,其中;; s-exp syntax/module-reader is a language for defining new languages.
#lang s-exp syntax/module-reader
racket
#:wrapper1 (lambda (th)
(parameterize ([current-readtable
(make-colon-range-readtable (current-readtable))])
(th)))
;; This extends the orig-readtable with an entry for `[` to convert
;; `[1:42]` to `(range 1 42)`. In this simplistic implementation, they
;; have to be literal numbers, so it can't refer to a variable.
(define (make-colon-range-readtable orig-readtable)
(make-readtable orig-readtable
#\[ 'terminating-macro colon-range-proc))
;; This is the function that the new readtable will use when in encounters a `[`
(define (colon-range-proc char in src ln col pos)
(define S (read-int-until #\: in src))
(define N (read-int-until #\] in src))
(list 'range S N))
;; This reads until it finds the given char (consuming it),
;; and returns an exact integer
(define (read-int-until char in src)
(define str (list->string (read-numeric-chars-until char in src)))
(define i (string->number str))
(unless (exact-integer? i)
(error 'read "expected an exact integer, given `~a`" str))
i)
;; This reads until it finds the given char (consuming it), and returns a list
;; of characters. Each char it reads before that needs to be a numeric char,
;; otherwise it throws an error.
(define (read-numeric-chars-until char in src)
(define c (read-char in))
(cond [(eof-object? c)
(error 'read "end-of-file: expected either a number or a `~a`, given `~a`"
char c)]
[(char=? char c)
(list)]
[(char-numeric? c)
(cons c (read-numeric-chars-until char in src))]
[else
(error 'read "expected either a number or a `~a`, given `~a`"
char c)]))
作为单一集合包安装。
[
此版本会覆盖:
和:
。它将a:b
定义为分隔符,以便a : b
读取与[
相同的内容,并将[a : b]
定义为读取器宏,读取正常列表并在之后对其进行处理。因此,它会首先将(range a b)
作为三个元素的列表,然后将其翻译为#lang colon-range
;; simple range by itself
[1:42]
;; using a range within a more complicated expression
(for/list ([i [2:42]]
#:when
(for/and ([j [2:i]]) ; can refer to a variable
(not (= 0 (remainder i j)))))
i)
(define two 2)
(for/list ([i [two:42]] ; can refer to a variable for the start
#:when
(for/and ([j [two:(+ 1 (exact-floor (sqrt i)))]]) ; can use arbitrary expressions
(not (= 0 (remainder i j)))))
i)
。
可以像这样使用:
colon-range/lang/reader.rkt
实现看起来像这样(再次在;; s-exp syntax/module-reader is a language for defining new languages.
#lang s-exp syntax/module-reader
racket
#:wrapper1 (lambda (th)
(parameterize ([current-readtable
(make-colon-range-readtable (current-readtable))])
(th)))
;; This extends the orig-readtable with entries for `[` and `:` to convert
;; `[S:N]` to `(range S N)`.
(define (make-colon-range-readtable orig-readtable)
(make-readtable orig-readtable
#\[ 'terminating-macro colon-range-proc
#\: 'terminating-macro separator-proc))
;; This is the function that the new readtable will use when in encounters a `[`
(define (colon-range-proc char in src ln col pos)
;; This reads the list of things ending with the character that closes `char`
;; The #f means it uses the racket reader for the first step, so that `[`
;; uses the normal behavior, grouping expressions into a reader-level list
(define lst (read-syntax/recursive src in char #f))
;; This matches on that list to determine whether it has the shape `[S : N]`
(syntax-case lst (:)
[[S : N]
;; if it is, translate it to `(range S N)`
(list 'range #'S #'N)]
[_
;; otherwise leave it alone
lst]))
;; This doesn't read any further and simply returns an identifier containing char,
;; so that it can act like a separator
(define (separator-proc char in src ln col pos)
(char->identifier char (list src ln col pos 1)))
(define (char->identifier char srcloc)
(datum->syntax #f (string->symbol (string char)) srcloc))
中)。这些评论解释了它正在做的一些事情。
XPCollection coll = new XPCollection(uow, typeof(HataBildirim), CriteriaOperator.Parse("[HataTespitYeri] = ? and [Tarih] > ? and ([CreatedOn] > ? OR [LastModifiedOn] > ?)",hatatespityeri, convservertarih, senkdate, senkdate));