List 列表的球拍模式匹配

List 列表的球拍模式匹配,list,pattern-matching,racket,ellipsis,List,Pattern Matching,Racket,Ellipsis,我正在尝试使用列表进行模式匹配,但由于某些原因,在执行以下操作时,我得到了一个意外的匹配: > (define code '(h1 ((id an-id-here)) Some text here)) > (define code-match-expr '(pre ([class brush: python]) ...)) > (match code [code-match-expr #t] [_ #f]) #t 问题:为什么code匹配code匹配expr

我正在尝试使用列表进行模式匹配,但由于某些原因,在执行以下操作时,我得到了一个意外的匹配:

> (define code '(h1 ((id an-id-here)) Some text here))
> (define code-match-expr '(pre ([class brush: python]) ...))
> (match code
    [code-match-expr #t]
    [_ #f])
#t
问题:为什么
code
匹配
code匹配expr

实际用例 我在racketrepl中尝试了这一点,因为我实际上想解决另一个实际问题:使用pool的pygments包装函数来突出显示代码,这些代码稍后将作为HTML输出。为此,我编写了以下代码,其中出现了问题:

(define (read-post-from-file path)
  (Post-from-content (replace-code-xexprs (parse-markdown path))))

(define (replace-code-xexprs list-of-xexprs)
  ;; define known languages
  (define KNOWN-LANGUAGE-SYMBOLS
    (list 'python
          'racket
          'html
          'css
          'javascript
          'erlang
          'rust))
  ;; check if it matches for a single language's match expression
  ;; if it mathces any language, return that language's name as a symbol
  (define (get-matching-language an-xexpr)
    (define (matches-lang-match-expr? an-xexpr lang-symbol)
      (display "XEXPR:") (displayln an-xexpr)
      (match an-xexpr
        [`(pre ([class brush: ,lang-symbol]) (code () ,more ...)) lang-symbol]
        [`(pre ([class brush: ,lang-symbol]) ,more ...) lang-symbol]
        [_ #f]))

    (ormap (lambda (lang-symbol)
             ;; (display "trying to match ")
             ;; (display an-xexpr)
             ;; (display " against ")
             ;; (displayln lang-symbol)
             (matches-lang-match-expr? an-xexpr lang-symbol))
           KNOWN-LANGUAGE-SYMBOLS))

  ;; replace code in an xexpr with highlightable code
  ;; TODO: What happens if the code is in a lower level of the xexpr?
  (define (replace-code-in-single-xexpr an-xexpr)
    (let ([matching-language (get-matching-language an-xexpr)])
      (cond [matching-language (code-highlight an-xexpr matching-language)]
            [else an-xexpr])))

  ;; apply the check to all xexpr
  (map replace-code-in-single-xexpr list-of-xexprs))

(define (code-highlight language code)
  (highlight language code))
在本例中,我正在分析一个具有以下内容的标记文件:

# Code Demo

```python
def hello():
    print("Hello World!")
```
我得到了以下
xexpr
s:

一,

二,


但是,由于某种原因,这些都不匹配。

match
是语法,不计算模式。由于
code match expr
是一个符号,它将把整个表达式(计算
code
的结果)绑定到变量
code match expr
,并在模式匹配时计算其余表达式。结果总是
#t

请注意,第二个模式,即符号
,是相同的模式。它也匹配整个表达式,但是
\uuuu
的特殊之处在于它不像
code match expr
那样绑定

务必不要使用定义的变量
code match expr
,但由于
match
绑定了同名变量,因此原始绑定将隐藏在
match
的后续绑定中

按预期工作的代码可能如下所示:

(定义(测试代码)
(匹配代码
[`(pre([class-brush:python]),更多…#t]
[uf]))
(测试’(h1((这里是id))这里是一些文本)
; ==> #F
(test'(pre((类笔刷:python)))
; ==> #T
(测试(pre((类刷:python))a b c)
; ==> #T
正如您看到的模式
,more…
意味着零或更多,什么样的括号被忽略,因为在Racket
[]
中与
()
{}
相同

编辑

你还是有点落后。在此代码中:

(define (matches-lang-match-expr? an-xexpr lang-symbol)
  (display "XEXPR:") (displayln an-xexpr)
  (match an-xexpr
    [`(pre ([class brush: ,lang-symbol]) (code () ,more ...)) lang-symbol]
    [`(pre ([class brush: ,lang-symbol]) ,more ...) lang-symbol]
    [_ #f]))
当一个模式被标记时,由于
lang symbol
没有引号,它将匹配任何原子,并作为该子句中的变量绑定到该元素。它将与绑定变量(与
匹配同名)无关,因为
不使用变量,而是创建变量。返回变量。因此:

(matches-lang-match-expr? '(pre ([class brush: jiffy]) bla bla bla) 'ignored-argument)
; ==> jiffy
以下是您想要的:

 (define (get-matching-language an-xexpr)
    (define (get-language an-xexpr)
      (match an-xexpr
        [`(pre ([class brush: ,lang-symbol]) (code () ,more ...)) lang-symbol]
        [`(pre ([class brush: ,lang-symbol]) ,more ...) lang-symbol]
        [_ #f]))
    (let* ((matched-lang-symbol (get-language an-xexpr))
           (in-known-languages (memq matched-lang-symbol KNOWN-LANGUAGE-SYMBOLS)))
      (and in-known-languages (car in-known-languages))))

再一次<代码>匹配
说明与创建列表结构完全不同的内容。它使用它们来匹配文本,并捕获未量化的符号作为变量

确保你清楚你要匹配的是什么。在Racket x表达式中,属性名称是符号,但值是字符串。因此,您要匹配的表达式类似于
(pre([class“brush:js]))\uuuuuu)
——而不是
(pre([class brush:js])\uuuuu)

要匹配该字符串并提取
“笔刷:
”后面的部分,可以使用
pregexp
匹配模式:


(这里,
pygmentize
是在其他Frog源代码中定义的一个函数;它是一个包装器,将Pygments作为一个单独的进程运行,并在它之间传输文本。但是你可以用另一种方式使用Pygments或任何其他语法。这对于你关于
match
的问题来说是不适用的。我提到它只是为了避免这种情况。)让我分心的是另一个隐含的问题。:)

我有一个关于这个问题的问题:(1)当我把
`(pre([class brush:python])1
输入球拍壳时,它会打印出
'(pre((class brush:python))1
。这是因为表达式被计算了吗?否则,backtick似乎只引入了另一个列表,我不明白为什么backtick会创建一个列表以外的东西,比如单引号。(2) 例如,如何将表达式存储在
散列中?Racket告诉我,当我尝试这样做时,
more
没有定义。我想在比赛中使用
更多的
会导致它被绑定并且没有错误,但我有很多这样的方法。@Zelphir这是
#lang racket
可视化值的疯狂方式。它不显示它变成的值,而是显示一个将计算为该值的表达式。所以
`(某事物)
的计算结果是
(某事物)
,但racket会显示
”(某事物)
,因为如果你计算它应该变成相同的值
(某事物)
,当然它仍然会显示为
(某事物)
。准注释
`
'
没有区别,除非您使用unquote(
)。尝试计算
`(ab,(+12))
然后再次计算。您的代码在Racket REPL中对我有效,但当我尝试将其放入代码中时,不知何故,我仍然会得到“始终匹配”或“始终为假”,这取决于我如何尝试它。你能看一下吗?我把它作为一个实际用例的编辑放到问题中。如果你认为我应该提出一个新问题,我会接受这个答案。@Zelphir只要把它作为一个编辑添加到你问题的底部,我就会看一看。我有多种编程语言需要匹配,我正在用
,lang symbol
填充它们,而不是在那里编写
python
,其中,
lang symbol
(列出python racket css)
中的一个元素。我会将代码添加到问题中,也许这只是我忽略的问题。此答案更正了我错误的匹配大小写表达式,并显示了如何进一步处理匹配的语言,但我只能接受一个答案。然而+1:)
(matches-lang-match-expr? '(pre ([class brush: jiffy]) bla bla bla) 'ignored-argument)
; ==> jiffy
 (define (get-matching-language an-xexpr)
    (define (get-language an-xexpr)
      (match an-xexpr
        [`(pre ([class brush: ,lang-symbol]) (code () ,more ...)) lang-symbol]
        [`(pre ([class brush: ,lang-symbol]) ,more ...) lang-symbol]
        [_ #f]))
    (let* ((matched-lang-symbol (get-language an-xexpr))
           (in-known-languages (memq matched-lang-symbol KNOWN-LANGUAGE-SYMBOLS)))
      (and in-known-languages (car in-known-languages))))
(for/list ([x xs])
  (match x
    [(or `(pre ([class ,brush]) (code () ,(? string? texts) ...))
         `(pre ([class ,brush]) ,(? string? texts) ...))
     (match brush
       [(pregexp "\\s*brush:\\s*(.+?)\\s*$" (list _ lang))
        `(div ([class ,(str "brush: " lang)])
              ,@(pygmentize (apply string-append texts) lang
                            #:python-executable python-executable
                            #:line-numbers? line-numbers?
                            #:css-class css-class))]
       [_ `(pre ,@texts)])]
    [x x])))