[racket] Fwd: Pattern matching define macro
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
>>
>>
>