This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
What does this r do? (reduce (fn [r x] (+ r (* x x))) [1 2 3]) - it's from Living Clojure
Hello everyone! I was wondering if anyone might be willing to help me with a problem regarding state.
I have the following code to create a maze, or grid, and traversal functions which actually creates the maze-like passages: http://pastebin.com/A7CKCdeQ
It works except for the linkage; my
link function updates the cell, but it's not mutated. In this case I'd like to know how to mutate the cell in question defined in
link-cell so that neighboring cells get updated
hey @iae, I think that's the whole point of using clojure - whenever possible, avoid mutating state; in your case,
assoc is not updating the cell but it is creating a new map based on the given one
one way to get away from this problem would be to return
maze itself) from
link-cell function and maybe use
reduce instead of
the other way would be to use either dynamic variable or an atom but I would think twice before doing that
Thanks for the advice @andrut; I think I know what you mean and I'll try to implement it real quick
I'm using the Repl right now and am getting a rather nondescript error in the REPL:
IllegalArgumentException No value supplied for key: [email protected] clojure.lang.PersistentHashMap.create (PersistentHashMap.java:77)
Ah, I think I found the error, it's because my
traverse function uses a map and returns a list instead of my Maze defrecord type, correct?http://pastebin.com/Z9xvHVNj
Imho, it seems a little cumbersome to have to do that after every operation that wants to change something in a map
Woohoo, it seems to work now, thanks again @andrut In case you might be interested in what the code looks like now, you can find it here: http://pastebin.com/KiGD17zH
the code looks better to me, I've got one question though: do you really need to use
Maze? why not to use simple map?
In F# you usually start out creating your domain models using
type and I thought that would be a good starting point
A map was too generic for me, and from what I understand a record IS a map except it has some magic functions added to it
I'm still not entirely sure when to use records and when not; I think a good use case is when using the schema lib
iae: This blog post might be helpful for thinking about Clojure types: http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/
Hm, it tells me to use a map because I'm not using protocols or interfaces, but if I skip to the defrecord point, it says "do you want to model a domain value" which is what I wanted the Maze to be
But I think I understand its point; I'll keep the flowchart up the next time I create my model
I think most people just use maps — until they get to the point where they want to define behavior specific to a domain value, since that’s the benefit of a record (implementing a protocol).
But it’s a big change of mindset coming to Clojure, especially from strongly-typed OOP languages, so it can seem very unnatural at first.
I assume that many dynamic language functions such as groovy's method_missing are also implementable in clojure
Without objects, method_missing doesn't really make sense. Either you've got a function or you haven't.
But with protocols you can declare a function to behave in a polymorphic way, even for other existing types you didn't write.
Woohoo the first clojure program I actually finished without switching lisp/scheme dialects and ultimately succumbing to choice paralysis!
Wasn't easy, and compared to the ruby code, there is something to be said about how easy it is to just iterate over a grid and mutate the cells without having to return a new maze.
I'm not sure if I feel like I have gained anything following a more functional approach to the same problem; the ruby code is simple and easy to read, probably difficult to mess up with too
It might be a newbie problem, but switching to sets to organize a cell's traversable directions in wasnt as straightforward as I hoped. I learned that sets and maps have some pretty important differences compared to lists; functions that I expected to work the same like
flatten returned an empty list.
Structuring a clojure file is confusing at the moment, but that's because I haven't properly studied the structure of clojure files/projects. Apparently you can't put definitions under functions that need them, but unlike a language such as C++ you can't forward-declare them? This leads to the public-facing functions being interspersed with private helper functions and I find it difficulty to see which functions are part of the Cell and Maze api
Thanks for the heads up @akiva Yes, that looks exactly like what I was looking for. I'll have to give the topic a more in-depth look before continuing to expand the project
I usually put utility, higher-order, and generalist functions at the top or group them with a calling function and just comment the code around it.