[racket] Fwd: Pattern matching define macro

From: Brian Adkins (racketusers at lojic.com)
Date: Sat Jul 12 16:16:50 EDT 2014

I'm not used to the reply-to begin set to the individual vs. the list for racketusers, so I'll forward a few replies...
Begin forwarded message:

> From: Brian Adkins <racketusers at lojic.com>
> On Jul 12, 2014, at 1:17 PM, Matthias Felleisen wrote:
>> On Jul 12, 2014, at 12:53 PM, Brian Adkins wrote:
>> 
>>> I'm porting more Haskell code to Racket as a learning exercise. When I got to this line:
>>> 
>>> isPos (r,c) = elem r [0..4] && elem c [0..r]
>>> 
>>> I first wrote this:
>>> 
>>> (define (is-pos r c) (and (member r (lgen 0 4))
>>>                        (member c (lgen 0 r))))
>>> 
>>> where lgen is:
>>> 
>>> (define (lgen m n) (build-list (+ 1 (- n m)) (λ (x) (+ x m))))
>>> 
>> 
>> 
>> Have you considered turning your Haskell code into prefix and leaving it otherwise alone (mostly): 
> 
> Not until now :)
> 
>> 
>> #lang racket
>> 
>> ;; -----------------------------------------------------------------------------
>> ;; prelude 
>> 
>> (module+ test (require rackunit))
>> 
>> (define-syntax-rule
>> (= (f x ...) expression)
>> (define (f x ...) expression))
>> 
>> (define (.. low high) (range low high))
>> (define (elem r rng) (cons? (member r rng)))
>> 
>> ;; -----------------------------------------------------------------------------
>> ;; Haskell to Racket 
>> ;; isPos (r,c) = elem r [0..4] && elem c [0..r]
>> 
>> ((isPos r c) . = . (and (elem r [.. 0 4]) (elem c [.. 0 r])))
> 
> Wow, interesting idea. I wasn't sure what ". = ." was, so I just tried '(7 . 8 . 9) in the repl and got '(8 7 9); apparently the above gets converted to:
> 
> (= (isPos r c) (and (elem r [.. 0 4]) (elem c [.. 0 r])))
> 
> It took a while to find:
> 
> "Such a pair triggers a reader conversion that moves the element between .s to the front of the list. The conversion enables a kind of general infix notation:" on:
> 
> http://docs.racket-lang.org/guide/Pairs__Lists__and_Racket_Syntax.html
> 
> searching about . is challenging.
> 
> Thanks for the "range" tip. I did some googling and didn't find anything so I resorted to lgen; I should've known that Racket would provide a decent built-in.
> 
> Not sure how I feel about [.. 0 4] yet vs. (range 0 5). My goal isn't to get my code to the concise level that Haskell provides, just to get rid of extra fluff at times.
> 
> Also (lgen m n) is (range m (add1 n)). It seems odd to me that (range 2 4) generates '(2 3). Is that an historical artifact?
> 
> The Haskell version of isPos accepts a single 2-tuple argument, so I think a list or struct is closer to the original than separate args. I've modified my code to use a struct for now, I'll see how that works. The defpat macro accepts a struct constructor as is, so that's handy.
> 
> 
>> 
>> ;; -----------------------------------------------------------------------------
>> ;; some tests
>> 
>> (module+ test
>> (check-true (isPos 1 0))
>> (check-true (isPos 2 1))
>> (check-false (isPos 1 2))
>> (check-false (isPos 5 1)))
>> 
>> 
>> 
>> Okay, the line is still a bit wider but that's because of extra spaces -- Matthias
>> 
>> 
> 



Posted on the users mailing list.