unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Fwd: regex-case
       [not found]   ` <CAGua6m1_gbvJk_XPzg95NTRYwZAXO_wKJyKyfjOT-vFirn3Vcg@mail.gmail.com>
@ 2016-02-08 15:40     ` Stefan Israelsson Tampe
  2016-02-08 16:04       ` regex-case Matt Wette
  2016-02-08 16:15       ` regex-case Stefan Israelsson Tampe
  0 siblings, 2 replies; 4+ messages in thread
From: Stefan Israelsson Tampe @ 2016-02-08 15:40 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 3650 bytes --]

---------- Forwarded message ----------
From: Stefan Israelsson Tampe <stefan.itampe@gmail.com>
Date: Mon, Feb 8, 2016 at 4:31 PM
Subject: Re: regex-case
To: Ludovic Courtès <ludo@gnu.org>


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 <ludo@gnu.org> wrote:

> Matt Wette <matthew.wette@verizon.net> 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’.
>
>
>

[-- Attachment #2: Type: text/html, Size: 8860 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: regex-case
  2016-02-08 15:40     ` Fwd: regex-case Stefan Israelsson Tampe
@ 2016-02-08 16:04       ` Matt Wette
  2016-02-08 16:15       ` regex-case Stefan Israelsson Tampe
  1 sibling, 0 replies; 4+ messages in thread
From: Matt Wette @ 2016-02-08 16:04 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 1731 bytes --]



Matt Wette
matthew.wette@verizon.net



> On Feb 8, 2016, at 7:40 AM, Stefan Israelsson Tampe <stefan.itampe@gmail.com> wrote:
> ---------- Forwarded message ----------
> From: Stefan Israelsson Tampe <stefan.itampe@gmail.com <mailto:stefan.itampe@gmail.com>>
> Date: Mon, Feb 8, 2016 at 4:31 PM
> Subject: Re: regex-case
> To: Ludovic Courtès <ludo@gnu.org <mailto:ludo@gnu.org>>
> 
> 
> An interesting question is what can be done by ice-9/match

To provide background to the guile-devel list my prototype implementation for regex-case is as follows (w/ error messages suggested by Ludo now included):

;; helper macro for regex-case
;; (rx-let m (v ...) exp ...) => (let ((v (match:substring m 1)) ...) exp ...)
(define-syntax rx-let
  (lambda (x)
    (syntax-case x ()
      ((_ m (v ...) exp ...)
       (with-syntax (((i ...)
		      (let f ((n 1) (vl #'(v ...))) ; fold (v ...) to (1 ...)
			(if (null? vl) '() (cons n (f (1+ n) (cdr vl)))))))
	 #'(let ((v (match:substring m i)) ...) exp ...))))))

(define-syntax regex-case
  (lambda (x)
    (syntax-case x (else)
      ((_ str ((pat v ...) exp ...) ...)
       (with-syntax (((id ...) (generate-temporaries #'(pat ...))))
	 #'(let ((id (make-regexp pat)) ...)
	     (cond
	      ((regexp-exec id str) =>
	       (lambda (m) (rx-let m (v ...) exp ...)))
	      ...
	      (else (error "regex-case: no match"))))))
      ((_ str ((pat v ...) exp ...) ... (else else-exp ...))
       (with-syntax (((id ...) (generate-temporaries #'(pat ...))))
	 #'(let ((id (make-regexp pat)) ...)
	     (cond
	      ((regexp-exec id str) =>
	       (lambda (m) (rx-let m (v ...) exp ...)))
	      ...
	     (else else-exp ...))))))))


[-- Attachment #2: Type: text/html, Size: 5719 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: regex-case
  2016-02-08 15:40     ` Fwd: regex-case Stefan Israelsson Tampe
  2016-02-08 16:04       ` regex-case Matt Wette
@ 2016-02-08 16:15       ` Stefan Israelsson Tampe
  2016-02-08 16:50         ` regex-case Stefan Israelsson Tampe
  1 sibling, 1 reply; 4+ messages in thread
From: Stefan Israelsson Tampe @ 2016-02-08 16:15 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 6501 bytes --]

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 <
stefan.itampe@gmail.com> wrote:

>
> ---------- Forwarded message ----------
> From: Stefan Israelsson Tampe <stefan.itampe@gmail.com>
> Date: Mon, Feb 8, 2016 at 4:31 PM
> Subject: Re: regex-case
> To: Ludovic Courtès <ludo@gnu.org>
>
>
> 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 <ludo@gnu.org> wrote:
>
>> Matt Wette <matthew.wette@verizon.net> 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’.
>>
>>
>>
>
>

[-- Attachment #2: Type: text/html, Size: 16476 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: regex-case
  2016-02-08 16:15       ` regex-case Stefan Israelsson Tampe
@ 2016-02-08 16:50         ` Stefan Israelsson Tampe
  0 siblings, 0 replies; 4+ messages in thread
From: Stefan Israelsson Tampe @ 2016-02-08 16:50 UTC (permalink / raw)
  To: guile-devel

[-- Attachment #1: Type: text/plain, Size: 7722 bytes --]

Ahh it is possible to get a nice regexp interface for ice-9/match. Consider
(define (r1 x) (lambda (s) (regexp-exec (make-regexp x) s)))
(define (r4 x)
   (lambda (s)
     (let ((res ((r1 x) s)))
       (if res
            (let lp ((out '()) (i 1))
                (catch #t
                    (lambda ()
                       (lp (cons (match:substring res i) out) (+ i 1)))
                    (lambda x (reverse out))))
            #f))))

This will produce a list of matchers or #f in case it fails.

Testing this (notice i corrected a few bugs from before) we get
scheme@(guile-user) [1]> (match "a(9)"
                                             ((= (r4
 "^([a-z]+)\\(([0-9]+)\\)$") (v i))
                                              (list v i)))
$12 = ("a" "9")

/Stefan


On Mon, Feb 8, 2016 at 5:15 PM, Stefan Israelsson Tampe <
stefan.itampe@gmail.com> wrote:

> 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 <
> stefan.itampe@gmail.com> wrote:
>
>>
>> ---------- Forwarded message ----------
>> From: Stefan Israelsson Tampe <stefan.itampe@gmail.com>
>> Date: Mon, Feb 8, 2016 at 4:31 PM
>> Subject: Re: regex-case
>> To: Ludovic Courtès <ludo@gnu.org>
>>
>>
>> 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 <ludo@gnu.org> wrote:
>>
>>> Matt Wette <matthew.wette@verizon.net> 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’.
>>>
>>>
>>>
>>
>>
>

[-- Attachment #2: Type: text/html, Size: 19240 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-02-08 16:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <61E420AD-70B6-4DEA-A7DD-EB123E22EFD0@verizon.net>
     [not found] ` <87oabrgtrg.fsf@gnu.org>
     [not found]   ` <CAGua6m1_gbvJk_XPzg95NTRYwZAXO_wKJyKyfjOT-vFirn3Vcg@mail.gmail.com>
2016-02-08 15:40     ` Fwd: regex-case Stefan Israelsson Tampe
2016-02-08 16:04       ` regex-case Matt Wette
2016-02-08 16:15       ` regex-case Stefan Israelsson Tampe
2016-02-08 16:50         ` regex-case Stefan Israelsson Tampe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).