guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: regex-case


From: Stefan Israelsson Tampe
Subject: Re: regex-case
Date: Mon, 8 Feb 2016 17:15:14 +0100

Because forwarded mail get hidden in modern mail clients I paste it here as well. Sorry for the spam
An interesting question is what can be done by ice-9/match

Consider
(define (r1 x) (regexp-exec (make-regexp x)))

Then simple matching can be done like

(match x
   ((? (r1 "a+"))  'matche_a_lot_of_as)
   ((? (r1 "b+"))  'matche_a_lot_of_bs)
    ...)

If we assume that the match = clause catches exceptiones we could use
(define (r2 x)
   (let ((res (r1 x)))
       (if r1
           r1
           (throw match-error))))

Then defining

(define (nth i)
    (lambda (x) (match:substring x i)))

we can then do

(match x
   ((= (r2 "^([a-z]+)\\(([0-9]+)\\$")) (and (= (nth 1) v) (= (nth 2) i)))
    (list v i))
    ...)

Not as elegant as match-case but it is well composable.

Another posibility is to define, i make this as simple as possible (the n argument can be removed)
(define (r3 x n)
   (let ((res (r1 x)))
       (if res
            (let lp ((out '()) (i n))
                (if (> n 0) 
                    (lp (cons (match:substring res i) out) (- i 1))
                    (reverse out)))
            (throw match-error))))

Then this should enable a quite nice match as

(match x
   ((= (r3  "^([a-z]+)\\(([0-9]+)\\$" 2) (v i))
    (list v i))
   ...)

which is not too bad. Now ice-9 match does not do the nessesary checks on throw and there is quite a bit of over head in the exception mechanisms but
in principle we should be able to design an ice-9 match and an inlinable r1, r2, r3 so that the code shoulud be effective compilied and the exceptions transformed
into goto's. I would like to, like for records, add support in upstream for catching a designated exception which shouled mean fail. What we could ask for is
for foof to have customable macros like for slot-ref etc. e.g.

(catch-error-object var thunk sucess-code failure-code)

with default definition beeing
(let ((var (thunk) sucees-code)

and our definition could be something like
(let ((res (catch match-error
                     (lambda () (thunk))
                     (lambda x err-obj))))
    (if (eq? res err-obj)
        failure-code
        (let ((var res))
            success-code))))

It is not clean, but we can clobber the default macro definition previously defined in upstream to introduce our macro without changing upstream.
When this is ready we could think about improving the compiler to expand regexp matches effectively.

WDYT


On Mon, Feb 8, 2016 at 4:40 PM, Stefan Israelsson Tampe <address@hidden> wrote:

---------- Forwarded message ----------
From: Stefan Israelsson Tampe <address@hidden>
Date: Mon, Feb 8, 2016 at 4:31 PM
Subject: Re: regex-case
To: Ludovic Courtès <address@hidden>


An interesting question is what can be done by ice-9/match

Consider
(define (r1 x) (regexp-exec (make-regexp x)))

Then simple matching can be done like

(match x
   ((? (r1 "a+"))  'matche_a_lot_of_as)
   ((? (r1 "b+"))  'matche_a_lot_of_bs)
    ...)

If we assume that the match = clause catches exceptiones we could use
(define (r2 x)
   (let ((res (r1 x)))
       (if r1
           r1
           (throw match-error))))

Then defining

(define (nth i)
    (lambda (x) (match:substring x i)))

we can then do

(match x
   ((= (r2 "^([a-z]+)\\(([0-9]+)\\$")) (and (= (nth 1) v) (= (nth 2) i)))
    (list v i))
    ...)

Not as elegant as match-case but it is well composable.

Another posibility is to define, i make this as simple as possible (the n argument can be removed)
(define (r3 x n)
   (let ((res (r1 x)))
       (if res
            (let lp ((out '()) (i n))
                (if (> n 0) 
                    (lp (cons (match:substring res i) out) (- i 1))
                    (reverse out)))
            (throw match-error))))

Then this should enable a quite nice match as

(match x
   ((= (r3  "^([a-z]+)\\(([0-9]+)\\$" 2) (v i))
    (list v i))
   ...)

which is not too bad. Now ice-9 match does not do the nessesary checks on throw and there is quite a bit of over head in the exception mechanisms but
in principle we should be able to design an ice-9 match and an inlinable r1, r2, r3 so that the code shoulud be effective compilied and the exceptions transformed
into goto's. I would like to, like for records, add support in upstream for catching a designated exception which shouled mean fail. What we could ask for is
for foof to have customable macros like for slot-ref etc. e.g.

(catch-error-object var thunk sucess-code failure-code)

with default definition beeing
(let ((var (thunk) sucees-code)

and our definition could be something like
(let ((res (catch match-error
                     (lambda () (thunk))
                     (lambda x err-obj))))
    (if (eq? res err-obj)
        failure-code
        (let ((var res))
            success-code))))

It is not clean, but we can clobber the default macro definition previously defined in upstream to introduce our macro without changing upstream.
When this is ready we could think about improving the compiler to expand regexp matches effectively.

WDYT


















  












On Mon, Feb 8, 2016 at 3:29 PM, Ludovic Courtès <address@hidden> wrote:
Matt Wette <address@hidden> skribis:

>  (regex-case str
>    (("^([a-z]+)\\(([0-9]+)\\)$" v i)
>     (list v i))
>    (("^([a-z]+)$" v)
>     (list v "1”)))

Sounds useful and convenient!

> (let ((t-292 (make-regexp "^([a-z]+)\\(([0-9]+)\\)$"))
>       (t-293 (make-regexp "^([a-z]+)$")))
>   (cond ((regexp-exec t-292 str)
>          =>
>          (lambda (m)
>            (let ((v (match:substring m 1))
>                  (i (match:substring m 2)))
>              (list v i))))
>         ((regexp-exec t-293 str)
>          =>
>          (lambda (m)
>            (let ((v (match:substring m 1))) (list v "1"))))))

When the ‘else’ clause is missing, I think it would be best to throw an
error like ‘match’ does—it’s rarely helpful to return #unspecified in
those cases.

Ludo’.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]