resyntax icon indicating copy to clipboard operation
resyntax copied to clipboard

Suggest using the `#:with` pattern directive instead of `with-syntax`

Open jackfirth opened this issue 3 years ago • 4 comments

In uses of syntax-parse, clauses whose tail expression is a with-syntax form can be replaced with #:with pattern directives. For example, given this expression:

(syntax-parse stx
  [foo:id
   (with-syntax ([bar #'(+ 1 2 3)])
     #'(foo bar)])

Resyntax ought to suggest simplifying it to this:

(syntax-parse stx
  [foo:id
   #:with bar #'(+ 1 2 3)
   #'(foo bar)])

This can open up the door for related simplifications of syntax-parse such as #142.

jackfirth avatar Jun 11 '21 01:06 jackfirth

It appears that there are some important differences between with-syntax and #:with: https://discord.com/channels/571040468092321801/667522224823205889/870065339017330688 and following messages.

So unless there's a way to filter out the bad cases, I guess this fix can only be a suggestion and cannot be applied automatically.

Metaxal avatar Jul 31 '21 16:07 Metaxal

We could probably do it for provably-safe cases, like when the right-hand-side is a quoted syntax object.

jackfirth avatar Aug 04 '21 07:08 jackfirth

There are a few dangers in this rewriting.

  1. with-syntax and #:with support different languages of patterns. For example, with-syntax interprets a:b as a plain pattern variable, but #:with interprets it as the pattern variable a annotated with the syntax class b.

  2. If the #:with match fails, then it can cause backtracking out of the current clause, but with-syntax cannot. Here's a little example:

    (syntax-parse #'(m 1)
        [(_ x) #:with y:id #'x 1]
        [_ 2])
    ;; => 2
    

    If you add #:cut before the #:with, you can prevent this particular issue.

rmculpepper avatar Feb 28 '23 23:02 rmculpepper

Good points. The first point can be addressed by analyzing the pattern and seeing if it would have a different meaning under syntax parse. We could also just restrict it to relatively simple and obviously equivalent patterns. The second point is trickier. For 99% of cases I doubt it would cause an issue, but it's worth calling it out as a possible caveat in the suggestion's description. Also, it wouldn't matter for cases where no backtracking occurs, like syntax-parse forms with only one clause.

jackfirth avatar Mar 01 '23 00:03 jackfirth