Hi Todd,

2010/12/29 Todd <t.greenwoodg...@gmail.com>

> Thanks Ken, Mark, David and Alex for your comments regarding Binary Search
> trees. I've read that thread several times, and ordered Okasaki's Purely
> Functional Data Structures, too. I'll return to this a bit later.
>
> Meanwhile, I decided to tackle learning Clojure from a different angle...in
> this case, implementing a solution for the Dining Philosopher problem.
>
> I've posted my code here:
>
> https://gist.github.com/757925
>
> General comments/questions:
>
> 1. I suppose it's from years of OO programming, but it still feels so weird
> not to be creating objects and then hanging methods off those objects. In
> fact, my first approach was to create protocols and records for each of the
> 'objects': chopsticks, philosophers, even the table. But this started to get
> painful, so I shifted gears...
>
> 2. I'm using a number of symbols (:tablestate, :seats, :chopsticks,
> :servings, etc). Shouldn't these be defined somewhere? It feels like I'm
> driving w/o a seatbelt. I'm so used to encapsulating this sort of thing in
> an enum or something, and then relying on java typing to enforce the allowed
> values.
>
> 3. Starting a thread with (future ... This couldn't be easier. Very cool.
>
> 4. I tried making the table an agent instead of a ref. Then I was sending
> methods to the table like, start-tableservice or stop-tabelservice... I'll
> investigate further, but is it idiomatic to start threads within the agent?
>
> (BTW - Chapter 6 on State Management of Practical Clojure was particularly
> helpful to me for figuring out the syntax for refs and agents.)
>
> Anyone feel like tearing my code apart? I'd like to make it as clean and
> clojure-ish as possible.
>

Not tackling the problem "at heart", here are some notes on your clojure
code :

  * print-table: its body is in a dosync. And its intent is to emit printfs.
This seems wrong. Side effects should be avoided inside transactions, since
they could be retried by the STM. One solution could be to have print-table
write in a memory location by rebinding clojure.core/*out* to a
StringWriter, and `print` the result outside the dosync.

  * (+ 1 ph-index) : can be written as (inc ph-index)

  * create-table: you could take advantage of the fact that everything is an
expression :
instead of :
(let [ch (zipmap (range seats) (map ref (take seats (repeat :table))))
        ph (zipmap (range seats) (map ref (take seats (repeat :thinking))))
        servings (zipmap (range seats) (map ref (take seats (repeat 0))))]
    {:seats seats :chopsticks ch :philosophers ph :tablestate (ref
:dinnertime) :servings servings})
you could directly have :
{:seats seats
 :chopsticks (zipmap (range seats) (map ref (take seats (repeat :table))))
 :philosophers (zipmap (range seats) (map ref (take seats (repeat
:thinking))))
 :tablestate (ref :dinnertime)
 :servings (zipmap (range seats) (map ref (take seats (repeat 0))))}

  * create-table: zipmaps  could be simplified, instead of (zipmap (range
seats) (map ref (take seats (repeat :table)))), you could just write (zipmap
(range seats) (repeat (ref :table)))

  * all functions : you're placing the docstring in the wrong place. Should
be right after the name of the function

  * consider not having, at the end of your namespace full of functions,
direct calls to the functions, but rather encapsulate it in a function named
main or -main. And let people call this main manually or via their favorite
tool.

I do not have time to deeply analyse the algorithm of your code, but some
10,000 feets notes about it:
  * lots of uses of indices. Feels weird. Maybe it's necessary, but my guess
is that there's a better solution : without indices at all, but (but maybe
not) in the function initializing the states.
  * or maybe the use of indices could be lessened by not propagating this to
helper functions (at least)

HTH,

-- 
Laurent

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to