Re: [racket-users] Pattern matching as computation

2019-06-27 Thread David Storrs
Oh, neat.  Thank you, Sorawee.

On Thu, Jun 27, 2019 at 7:26 PM Sorawee Porncharoenwase <
sorawee.pw...@gmail.com> wrote:

> If you want only one match, it seems what you really want is ~seq-like
> form from syntax/parse. E.g.,
>
> #lang racket
>
> (require syntax/parse)
>
> (define ->value syntax->datum)
>
> (define (apply-lift op args)
>   (datum->syntax #f (apply op (->value args
>
> (syntax-parse (vector 1 2 3 4)
>   [#(a {~and {~seq {~between b 2 2} ...}
>  {~bind [x (apply-lift + #'(b ...))]}} c)
>(->value #'(a (b ...) c x))])
> ;; => '(1 (2 3) 4 5)
>
> (struct person (name age) #:prefab)
> (struct horse (color owner) #:prefab)
>
> (syntax-parse (vector 'brown 'bob 23)
>   [#(the-color {~and {~seq args ...}
>  {~bind [the-owner (apply-lift person #'(args ...))]}})
>(->value (apply-lift horse #'(the-color the-owner)))])
> ;; => '#s(horse brown #s(person bob 23))
>
>
>
>
>
> On Thu, Jun 27, 2019 at 3:31 PM David Storrs 
> wrote:
>
>>
>>
>> On Thu, Jun 27, 2019 at 5:13 PM Eric Griffis  wrote:
>>
>>> On Thu, Jun 27, 2019 at 11:56 AM David Storrs 
>>> wrote:
>>> >
>>> > Suppose instead I wanted to have a pattern like so (this does not
>>> work):
>>> >
>>> > (match (vector 1 2 3 4)
>>> >   [(vector a (app + b ..2 x) c) (list a b c x)]
>>> > ; => '(1 (2 3) 4 5))  ;  NB:  does not work
>>>
>>> We have a few problems here.
>>>
>>> The pattern (vector a ? c) does not match the shape of the val-expr
>>> (vector 1 2 3 4).
>>>
>>> In the second sub-pattern (app + b ..2 x), Racket complains `..2' is an
>>> "incorrect use of ... in pattern" because every sub-pattern of `app' must
>>> independently match the result of (+ 2).
>>>
>>> To get the expected result '(1 (2 3) 4 5) from the actual result (list
>>> a b
>>> c x), we'd need the following bindings:
>>>
>>> a --> 1
>>> b --> '(2 3)
>>> c --> 4
>>> x --> 5
>>>
>>> At this point, I'm not sure what you're trying to do. Maybe you're trying
>>> to bind `b' to '(2 3), then `x' with the sum (+ 2 3), then `c' with 4.
>>>
>>> Here's one way to do it from within a single pattern:
>>>
>>> (match (vector 1 2 3 4)
>>>   [(and (vector a _ _ c)
>>> (app (λ (vec)
>>>(match vec
>>>  [(vector _ p q _)
>>>   (list (list p q) (+ p q))]))
>>>  (list b x)))
>>>(list a b c x)])
>>>
>>> > Less trivially, I'd like to be able to do something like this:
>>> >
>>> > #lang racket
>>> > (struct person (name age) #:prefab)
>>> > (struct horse (color owner) #:prefab)
>>> >
>>> > ; The following does not work
>>> > (match (vector 'brown 'bob 23)
>>> >   [(vector the-color (app (curry apply person) args ... the-owner))
>>> >(horse the-color the-owner)])
>>>
>>> Here's an adaptation of the above technique that works:
>>>
>>> (match (vector 'brown 'bob 23)
>>>   [(and (vector the-color _ _)
>>> (app (λ (vec)
>>>(match vec
>>>  [(vector _ name age)
>>>   (person name age)]))
>>>  the-owner))
>>>(horse the-color the-owner)])
>>>
>>
>> Makes sense -- it's two matches,  but still within one sexp.  Thanks.
>>
>>
>>> Incidentally, Algebraic Racket is designed for this:
>>>
>>> #lang algebraic/racket/base
>>>
>>> (require (prefix-in algebraic- algebraic/racket/base/forms))
>>>
>>> (algebraic-case (vector 1 2 3 4)
>>>   [#(a p q c)
>>>#:with b (list p q)
>>>#:with x (+ p q)
>>>(list a b c x)])
>>>
>>> (algebraic-case (vector 'brown 'bob 23)
>>>   [#(the-color name age)
>>>#:with the-owner (person name age)
>>>(horse the-color the-owner)])
>>>
>>> If a #:with directive fails, the overall match fails:
>>>
>>> (algebraic-case (vector 'brown 'bob 23)
>>>   [#(the-color name age)
>>>#:with the-owner #f
>>>#:with (person _ _) the-owner
>>>(horse the-color the-owner)])
>>>
>>>
>> That is drop-dead sexy.  Thanks, Eric.
>>
>>
>> Eric
>>>
>>> --
>> You received this message because you are subscribed to the Google Groups
>> "Racket Users" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to racket-users+unsubscr...@googlegroups.com.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/racket-users/CAE8gKocxGYu0vKvUzW%3Dfc1X7acXmZjCmz6mPKErDWvNmjKLmZw%40mail.gmail.com
>> 
>> .
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAE8gKocj-t%2B8WUVyZq0d6OsjtUk5XxL170RDf_xvJp%2BYhO2i8w%40mail.gmail.com.
For more options, visit 

Re: [racket-users] Pattern matching as computation

2019-06-27 Thread Sorawee Porncharoenwase
If you want only one match, it seems what you really want is ~seq-like form
from syntax/parse. E.g.,

#lang racket

(require syntax/parse)

(define ->value syntax->datum)

(define (apply-lift op args)
  (datum->syntax #f (apply op (->value args

(syntax-parse (vector 1 2 3 4)
  [#(a {~and {~seq {~between b 2 2} ...}
 {~bind [x (apply-lift + #'(b ...))]}} c)
   (->value #'(a (b ...) c x))])
;; => '(1 (2 3) 4 5)

(struct person (name age) #:prefab)
(struct horse (color owner) #:prefab)

(syntax-parse (vector 'brown 'bob 23)
  [#(the-color {~and {~seq args ...}
 {~bind [the-owner (apply-lift person #'(args ...))]}})
   (->value (apply-lift horse #'(the-color the-owner)))])
;; => '#s(horse brown #s(person bob 23))





On Thu, Jun 27, 2019 at 3:31 PM David Storrs  wrote:

>
>
> On Thu, Jun 27, 2019 at 5:13 PM Eric Griffis  wrote:
>
>> On Thu, Jun 27, 2019 at 11:56 AM David Storrs 
>> wrote:
>> >
>> > Suppose instead I wanted to have a pattern like so (this does not work):
>> >
>> > (match (vector 1 2 3 4)
>> >   [(vector a (app + b ..2 x) c) (list a b c x)]
>> > ; => '(1 (2 3) 4 5))  ;  NB:  does not work
>>
>> We have a few problems here.
>>
>> The pattern (vector a ? c) does not match the shape of the val-expr
>> (vector 1 2 3 4).
>>
>> In the second sub-pattern (app + b ..2 x), Racket complains `..2' is an
>> "incorrect use of ... in pattern" because every sub-pattern of `app' must
>> independently match the result of (+ 2).
>>
>> To get the expected result '(1 (2 3) 4 5) from the actual result (list a
>> b
>> c x), we'd need the following bindings:
>>
>> a --> 1
>> b --> '(2 3)
>> c --> 4
>> x --> 5
>>
>> At this point, I'm not sure what you're trying to do. Maybe you're trying
>> to bind `b' to '(2 3), then `x' with the sum (+ 2 3), then `c' with 4.
>>
>> Here's one way to do it from within a single pattern:
>>
>> (match (vector 1 2 3 4)
>>   [(and (vector a _ _ c)
>> (app (λ (vec)
>>(match vec
>>  [(vector _ p q _)
>>   (list (list p q) (+ p q))]))
>>  (list b x)))
>>(list a b c x)])
>>
>> > Less trivially, I'd like to be able to do something like this:
>> >
>> > #lang racket
>> > (struct person (name age) #:prefab)
>> > (struct horse (color owner) #:prefab)
>> >
>> > ; The following does not work
>> > (match (vector 'brown 'bob 23)
>> >   [(vector the-color (app (curry apply person) args ... the-owner))
>> >(horse the-color the-owner)])
>>
>> Here's an adaptation of the above technique that works:
>>
>> (match (vector 'brown 'bob 23)
>>   [(and (vector the-color _ _)
>> (app (λ (vec)
>>(match vec
>>  [(vector _ name age)
>>   (person name age)]))
>>  the-owner))
>>(horse the-color the-owner)])
>>
>
> Makes sense -- it's two matches,  but still within one sexp.  Thanks.
>
>
>> Incidentally, Algebraic Racket is designed for this:
>>
>> #lang algebraic/racket/base
>>
>> (require (prefix-in algebraic- algebraic/racket/base/forms))
>>
>> (algebraic-case (vector 1 2 3 4)
>>   [#(a p q c)
>>#:with b (list p q)
>>#:with x (+ p q)
>>(list a b c x)])
>>
>> (algebraic-case (vector 'brown 'bob 23)
>>   [#(the-color name age)
>>#:with the-owner (person name age)
>>(horse the-color the-owner)])
>>
>> If a #:with directive fails, the overall match fails:
>>
>> (algebraic-case (vector 'brown 'bob 23)
>>   [#(the-color name age)
>>#:with the-owner #f
>>#:with (person _ _) the-owner
>>(horse the-color the-owner)])
>>
>>
> That is drop-dead sexy.  Thanks, Eric.
>
>
> Eric
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/racket-users/CAE8gKocxGYu0vKvUzW%3Dfc1X7acXmZjCmz6mPKErDWvNmjKLmZw%40mail.gmail.com
> 
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CADcuegtXfWvz9n42Sa5KdWLGy5-ZDDQP7NM6gcT0ShGwKVcK5g%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Pattern matching as computation

2019-06-27 Thread David Storrs
On Thu, Jun 27, 2019 at 5:13 PM Eric Griffis  wrote:

> On Thu, Jun 27, 2019 at 11:56 AM David Storrs 
> wrote:
> >
> > Suppose instead I wanted to have a pattern like so (this does not work):
> >
> > (match (vector 1 2 3 4)
> >   [(vector a (app + b ..2 x) c) (list a b c x)]
> > ; => '(1 (2 3) 4 5))  ;  NB:  does not work
>
> We have a few problems here.
>
> The pattern (vector a ? c) does not match the shape of the val-expr
> (vector 1 2 3 4).
>
> In the second sub-pattern (app + b ..2 x), Racket complains `..2' is an
> "incorrect use of ... in pattern" because every sub-pattern of `app' must
> independently match the result of (+ 2).
>
> To get the expected result '(1 (2 3) 4 5) from the actual result (list a b
> c x), we'd need the following bindings:
>
> a --> 1
> b --> '(2 3)
> c --> 4
> x --> 5
>
> At this point, I'm not sure what you're trying to do. Maybe you're trying
> to bind `b' to '(2 3), then `x' with the sum (+ 2 3), then `c' with 4.
>
> Here's one way to do it from within a single pattern:
>
> (match (vector 1 2 3 4)
>   [(and (vector a _ _ c)
> (app (λ (vec)
>(match vec
>  [(vector _ p q _)
>   (list (list p q) (+ p q))]))
>  (list b x)))
>(list a b c x)])
>
> > Less trivially, I'd like to be able to do something like this:
> >
> > #lang racket
> > (struct person (name age) #:prefab)
> > (struct horse (color owner) #:prefab)
> >
> > ; The following does not work
> > (match (vector 'brown 'bob 23)
> >   [(vector the-color (app (curry apply person) args ... the-owner))
> >(horse the-color the-owner)])
>
> Here's an adaptation of the above technique that works:
>
> (match (vector 'brown 'bob 23)
>   [(and (vector the-color _ _)
> (app (λ (vec)
>(match vec
>  [(vector _ name age)
>   (person name age)]))
>  the-owner))
>(horse the-color the-owner)])
>

Makes sense -- it's two matches,  but still within one sexp.  Thanks.


> Incidentally, Algebraic Racket is designed for this:
>
> #lang algebraic/racket/base
>
> (require (prefix-in algebraic- algebraic/racket/base/forms))
>
> (algebraic-case (vector 1 2 3 4)
>   [#(a p q c)
>#:with b (list p q)
>#:with x (+ p q)
>(list a b c x)])
>
> (algebraic-case (vector 'brown 'bob 23)
>   [#(the-color name age)
>#:with the-owner (person name age)
>(horse the-color the-owner)])
>
> If a #:with directive fails, the overall match fails:
>
> (algebraic-case (vector 'brown 'bob 23)
>   [#(the-color name age)
>#:with the-owner #f
>#:with (person _ _) the-owner
>(horse the-color the-owner)])
>
>
That is drop-dead sexy.  Thanks, Eric.


Eric
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAE8gKocxGYu0vKvUzW%3Dfc1X7acXmZjCmz6mPKErDWvNmjKLmZw%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Pattern matching as computation

2019-06-27 Thread Eric Griffis
On Thu, Jun 27, 2019 at 11:56 AM David Storrs 
wrote:
>
> Suppose instead I wanted to have a pattern like so (this does not work):
>
> (match (vector 1 2 3 4)
>   [(vector a (app + b ..2 x) c) (list a b c x)]
> ; => '(1 (2 3) 4 5))  ;  NB:  does not work

We have a few problems here.

The pattern (vector a ? c) does not match the shape of the val-expr
(vector 1 2 3 4).

In the second sub-pattern (app + b ..2 x), Racket complains `..2' is an
"incorrect use of ... in pattern" because every sub-pattern of `app' must
independently match the result of (+ 2).

To get the expected result '(1 (2 3) 4 5) from the actual result (list a b
c x), we'd need the following bindings:

a --> 1
b --> '(2 3)
c --> 4
x --> 5

At this point, I'm not sure what you're trying to do. Maybe you're trying
to bind `b' to '(2 3), then `x' with the sum (+ 2 3), then `c' with 4.

Here's one way to do it from within a single pattern:

(match (vector 1 2 3 4)
  [(and (vector a _ _ c)
(app (λ (vec)
   (match vec
 [(vector _ p q _)
  (list (list p q) (+ p q))]))
 (list b x)))
   (list a b c x)])

> Less trivially, I'd like to be able to do something like this:
>
> #lang racket
> (struct person (name age) #:prefab)
> (struct horse (color owner) #:prefab)
>
> ; The following does not work
> (match (vector 'brown 'bob 23)
>   [(vector the-color (app (curry apply person) args ... the-owner))
>(horse the-color the-owner)])

Here's an adaptation of the above technique that works:

(match (vector 'brown 'bob 23)
  [(and (vector the-color _ _)
(app (λ (vec)
   (match vec
 [(vector _ name age)
  (person name age)]))
 the-owner))
   (horse the-color the-owner)])

Incidentally, Algebraic Racket is designed for this:

#lang algebraic/racket/base

(require (prefix-in algebraic- algebraic/racket/base/forms))

(algebraic-case (vector 1 2 3 4)
  [#(a p q c)
   #:with b (list p q)
   #:with x (+ p q)
   (list a b c x)])

(algebraic-case (vector 'brown 'bob 23)
  [#(the-color name age)
   #:with the-owner (person name age)
   (horse the-color the-owner)])

If a #:with directive fails, the overall match fails:

(algebraic-case (vector 'brown 'bob 23)
  [#(the-color name age)
   #:with the-owner #f
   #:with (person _ _) the-owner
   (horse the-color the-owner)])

Eric

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAORuSUxETFymuLMd1RQmUNdqrLug4CghXYvCDB__VYvGgP0zGA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Pattern matching as computation

2019-06-27 Thread David Storrs
This works:

(match (vector 1 2 3 4)
 [(vector a b (app add1 c) d)
  (list a b c d)])
; => '(1 2 4 4)

Suppose instead I wanted to have a pattern like so (this does not work):

(match (vector 1 2 3 4)
  [(vector a (app + b ..2 x) c) (list a b c x)]
; => '(1 (2 3) 4 5))  ;  NB:  does not work

Is there a way to do this?


Less trivially, I'd like to be able to do something like this:

#lang racket
(struct person (name age) #:prefab)
(struct horse (color owner) #:prefab)

; The following does not work
(match (vector 'brown 'bob 23)
  [(vector the-color (app (curry apply person) args ... the-owner))
   (horse the-color the-owner)])

I've been through the pattern matching docs in some detail and tried
various things, but my brain-fu is weak.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CAE8gKoeJL-YzSQ_SZ9te9OQ0HgmKiXW19624E8H6fScfFB2zpA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.