[racket] Rosetta Sokoban Solution

From: Sean Kanaley (skanaley at gmail.com)
Date: Tue Jun 11 11:43:30 EDT 2013

Hi Jens,

I like the idea of using an object that dispatches on number of 
arguments instead of requiring explicit function names, something I'm 
embarrassed to say I hadn't thought of, so I'm grateful for being shown 
this technique.

I shall go about experimenting with a shorter solution.  I'll be using a 
less "only people that know everything about Racket" object however ;) 
shown here:

(define (level ss)
   (define h (hash-copy (for*/hash ([(s i) (in-indexed ss)]
                                    [(x j) (in-indexed s)])
                          (values (list i j) x))))
   (case-lambda
     [(p) (hash-ref h p)]
     [(p x) (hash-set! h p x) x]
     [else (error "level: too many arguments")]))

I didn't even know structures could be procedure-ified.

On 06/11/2013 05:06 AM, Jens Axel Søgaard wrote:
> Hi Sean
>
> 2013/6/10 Sean Kanaley <skanaley at gmail.com>
>
>> Also, for some reason Racket doesn't return values from mutations.  Why on earth (set! x 3) is void instead of 3 is a mystery, but it leads to things like:
>>
>> (define-match (x ...) (heap-min heap))
>> (now-remove-it!)
>>
>> and, in addition to verbose naming:
>>
>> (vector-set! v i 4)
>> v
>>
>> which should ideally be:
>>
>> (vec! v i 3)
>
> Here is an alternative representation of levels using that allows you to
> write (l p) to get the value of position p in level l. Also (l p x) sets the
> character at position p in level l to x.
>
> #lang racket
> (struct level (h get/set)
>    #:property prop:procedure (struct-field-index get/set))
>
> (define (make-level strings)
>    (define h (hash-copy
>               (for*/hash ([(row i) (in-indexed strings)]
>                           [(x j)   (in-indexed row)])
>                 (values (list i j) x))))
>    (define (get p) (hash-ref h p))
>    (define (set p x) (hash-set! h p x) x)
>    (define get/set (case-lambda [(p) (get p)] [(p x) (set p x)]))
>    (level h get/set))
>
> (define l (make-level (list "########"
>                              "#      #"
>                              "#  . @ #"
>                              "########")))
>
> (l '(0 0))
> (l '(0 0) #\.)
> (l '(0 0))
>
>   --
> Jens Axel Søgaard


Posted on the users mailing list.