[racket] Rosetta Sokoban Solution
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