Not all of your application can be purely functional, because it
inevitably needs to interact with the outside world at some point.

Purely functional code is easier to reason about, so the pragmatic
approach of Clojure is to encourage you to have most of your
application be purely functional, while not getting too much in the
way when you actually need mutation (and trying to provide a sane way
to control these mutations via its reference types).

Your state will/should be an immutable data structure, and the
evolutions of this state across time (or in reaction to user input)
should be controlled by purely functional transformations. The
boundaries of the system, however, will not be functional.

One way to approach MVC in Clojure would be to have a pure function
that transforms your model into the "next" one based on external
input, and another function which, taking your model as a parameter,
creates or updates the view. This can be implemented with watchers :
Clojure reference types can have watchers associated to them, which
are called every time the reference changes. Depending on your
concurrency needs, you could potentially implement a sort-of MVC
pattern with a single atom to control the whole state of your
application.

On 9 March 2013 15:30, Jim - FooBar(); <jimpil1...@gmail.com> wrote:
> also see this for a discussion about why the need for design patterns almost
> disappears in Clojure:
> http://stackoverflow.com/questions/8902113/clojure-model-view-controller-mvc-design
>
> Jim
>
>
> On 09/03/13 14:24, Jim - FooBar(); wrote:
>
> You need to store your model in a ref-type (atom,agent,or ref), and attach a
> watcher on it (a fn which is responsible for updating the view). Now,
> 'mutating' your model will trigger a View update...piece of cake :)
>
> example:
>
> (def board-history
> "Log of the state of a game."
> (atom []))
>
> (defn log-board
> "The logging function for the board ref. Will conj every new board-state
> into a vector."
> [dest k r old n]
>  (when-not (= n old)
>   (swap! dest conj n)))
>
> (def current-chessItems
> "This is list that keeps track of moving chess pieces. Is governed by an
> atom and it changes after every move.
>  All changes are being logged to 'board-history'. Starts off as nil but we
> can always get the initial board arrangement from core."
>  (-> (atom nil)
>    (add-watch  :log (partial core/log-board core/board-history)))))
>
> HTH,
>
> Jim
>
> ps: my example does not involve GUI, but you get the idea...it it trivial to
> change the code so that it 'repaints' the canvas with the new board instead
> of conjing it....
>
>
> On 09/03/13 14:11, edw...@kenworthy.info wrote:
>
> So I understand that Clojure's data structures are immutable but I am not
> clear how that works with MVC.
>
> So I have a view that displays a model. Other processes change that model
> and the View presents those changes.
>
> However it's not clear to me how that would work with an immutable model.
>
> Obviously I can't pass the model into the View, have the view store a
> reference to it and each time it's called on to render the model, do so. The
> model is immutable.
>
> So I could have a global variable which points to the model, and whenever I
> 'change' the model I re-point it to the updated version. Obviously the view
> would have to reference that global. This just smells bad. And would get
> worse for each model and view you needed in your application.
>
> I suppose you could maintain some global map of models, but that doesn't
> look nice either, it's not that much different from having a pile of global
> models.
>
> This must be a solved problem surely? Could someone point me to the solution
> please? Swing or Quil based would be fine but I assume it must be generally
> applicable.
> --
> --
> 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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
>
>
> --
> --
> 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
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

-- 
-- 
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
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to