Re: Translating simple path finding problem from prolog to core.logic
Thanks Norman! Not sure how I didn't realize that was happening, but it's working exactly as you describe. Thanks much for your help! Cheers, Craig On Sunday, June 30, 2013 2:40:48 PM UTC-5, Norman Richards wrote: > > Just like the prolog, you are generating an infinite number of solutions. > run* will try and give you all of them. You can use clojure's lazy seq > operations (first, take, etc...) or just ask for however many you want: > > > (run 10 [q] (path2 1 7 q)) > > ((1 4 3 7) > > > (1 2 4 3 7) > > > (1 4 5 7) > > > (1 2 4 5 7) > > > (1 4 3 6 5 7) > > > (1 2 4 3 6 5 7) > > > (1 4 5 6 5 7) > > > (1 2 4 5 6 5 7) > > > (1 4 3 7 5 7) > > > (1 2 4 3 7 5 7)) > > -- -- 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.
Translating simple path finding problem from prolog to core.logic
Hello fellow logicians! I'm trying to translate the following prolog problem to core.logic: >From http://tjeyamy.blogspot.com/2011/02/path-finding-in-prolog.html edge(1,2). edge(1,4). edge(2,4). edge(3,6). edge(3,7). edge(4,3). edge(4,5). edge(5,6). edge(5,7). edge(6,5). edge(7,5). edge(8,6). edge(8,7). path(X,Y,[X,Y]):- edge(X,Y). path(X,Y,[X|Xs]):- edge(X,W), path(W,Y,Xs). path(1, 7, P). %Results Z = [1, 2, 4, 3, 6, 5, 7]; Z = [1, 2, 4, 3, 6, 5, 6, 5, 7]; Here are a couple of my own attempts using core.logic: (defrel edge x y) (fact edge 1 2) (fact edge 1 4) (fact edge 2 4) (fact edge 3 6) (fact edge 3 7) (fact edge 4 3) (fact edge 4 5) (fact edge 5 6) (fact edge 5 7) (fact edge 6 5) (fact edge 7 5) (fact edge 8 6) (fact edge 8 7) (defn path2 [x y p] (conde [(fresh [] (conso x [y] p) (edge x y))] [(fresh [w r] (conso x r p) (edge x w) (path2 w y r))])) (defne path3 [x y p] ([ x y [x . [y] ] ] (edge x y)) ([ x y [x . r] ] (fresh [w] (edge x w) (path3 w y r Hopefully I've understood enough that path3 is just the pattern matching version of path2 ;-) What happens, though, is that both of these end up in an infinite loop. Any hints about what I'm doing wrong? I'm sure I'm missing something fundamental here. Is there some sort of debugging I can do to figure this out? Or some way to trace execution? Thanks for any help! Cheers, Craig -- -- 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.
Re: David Nolen's logic programming readling list
Thanks David! -- -- 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.
David Nolen's logic programming readling list
I was looking for David Nolen's old blog at posterous where he had posted a reading list for logic programming, but that blog is no longer available. Does anyone have that list? Or, David, if you could repost it on your new blog, I'm sure others would appreciate it too! Cheers, Craig -- -- 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.
Re: Newbie requesting review
On Monday, March 11, 2013 6:35:09 AM UTC-5, Marko Topolnik wrote: > > > This kind if formatting hurts readability for people used to the style > that most Clojure code adopts, which would look something like this: > > (defn- make-student [teacher-name student-name age] > {:id (str teacher-name "!" student-name) >:TeacherName teacher-name >:StudentName student-name >:age age}) > > Placing the arguments vector on its own line is also an option, but you > shouldn't start the body in the same line. > > Ok, thanks Marko, I've been playing around a bit with my formatting and looking at a lot of clojure code, but you're right, I don't think I've seen anyone do it the way I've done here ;-) -- -- 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.
Re: Newbie requesting review
Hi Gary, On Monday, March 11, 2013 6:02:12 AM UTC-5, Gary Verhaegen wrote: > > For the sake of nitpicking, you are still using camelCase instead of > hyphenation in make-student. > > This part? {:id (str teacher-name "!" student-name) :TeacherName teacher-name :StudentName student-name :age age} That's what the web ui expects (I'm not really using teachers and students, but the actual data we do use is camel case) and there's actually a really good reason it uses what it uses. I'll make sure I didn't miss any others though, thanks! -- -- 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.
Re: Newbie requesting review
Alright, thanks Gary and Marko, I really appreciate the advice! On Sunday, March 10, 2013 8:26:47 AM UTC-5, Marko Topolnik wrote: > > Several comments: > > 1. camelCase is not idiomatic for Clojure. Prefer lowercase-dashed-style. > > 2. use :keywords for map keys and, more generally, for any > enumeration-type values (coming from a closed set of options). If you want > JSON output, transform these into camelCased strings only at the "checkout > desk". > Ugh, I *do* actually know better than that, thanks for pointing it out! > > 3. make-student-factory is what you'd call a *curried* function. You'd > have an easier time with it if you declared it as a regular two-argument > function and then used either clojure.core/partial or a literal > #(make-student > teacher-name %). That would allow you to use the function either directly > as a student factory, or as a factory of student factories. Note that > your approach to use a closure *is *idiomatic, I'm just advising a more > idiomatic way to get it. > > Ok, I *think* I understand what you're saying. I did try an anonymous function at one point, but gave it up, I don't know why I did because it ended up working pretty well after reading your advice. How's this then? (ns teachers.core (:require [clj-json.core :as json])) (defn- gen-items-json [students] (json/generate-string {:timestamp 5000 :items students :identifier "id" :label "id" :rc 200 :msg "Data retrieved successfully."})) (defn- make-student [teacher-name student-name age] {:id (str teacher-name "!" student-name) :TeacherName teacher-name :StudentName student-name :age age}) (defn- make-name [prefix n] (str prefix n)) (defn- make-teacher-name [n] (make-name "TEACHER" n)) (defn- make-student-name [n] (make-name "STUDENT" n)) (defn- make-students [teacher-name n] (map #(make-student teacher-name (make-student-name %) 0) (range n))) (defn- spit-json [teacher-name n] (println "Creating " n " students for teacher: " teacher-name) (spit (str teacher-name ".json") (gen-items-json (make-students teacher-name n (defn gen [num-teachers num-students] (doseq [teacher-name (map make-teacher-name (range num-teachers))] (spit-json teacher-name num-students))) Thanks a ton for your time, this list is really a great place and I appreciate being able to come here with questions! Cheers, Craig -- -- 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.
Newbie requesting review
Hi all, I wrote some code to generate some example data for a web ui that I'm working on and I was wondering if I could get some advice about it to ensure I'm on the right track in my clojure learning. Basically its a very simple program that generates a number of JSON files that contain information, I've modeled the problem as a teacher-student relationship where each teacher is a file that contains data about a number of students. The inputs to the main function (gen) takes the number of teachers and the number of students per teacher and generates sample data that can be consumed by the web ui. What I'm looking for is: 1. Am I doing things the "clojure way", is my program idiomatic? If not, advice is appreciated. 2. Specifically the main function in the program (make-student-factory) I've modeled as a closure and I feel like there is probably a better way to do it, what are your thoughts on that? Here is the code: (ns teachers.core (:require [clj-json.core :as json])) (defn- gen-items-json [students] (json/generate-string {"timestamp" 5000 "items" students "identifier" "id" "label" "id" "rc" 200 "msg" "Data retrieved successfully."})) (defn- make-student [teacherName studentName age] {"id" (str teacherName "!" studentName) "TeacherName" teacherName "StudentName" studentName "age" age}) (defn- make-name [prefix n] (str prefix n)) (defn- make-teacher-name [n] (make-name "TEACHER" n)) (defn- make-student-name [n] (make-name "STUDENT" n)) (defn- make-student-factory "Returns a function allowing you to create a number of student definitions for the given teacher." [teacherName] (fn [n] (make-student teacherName (make-student-name n) 0))) (defn- make-students [teacherName n] (let [fac (make-student-factory teacherName)] (map fac (range n (defn- spit-json [teacherName n] (println "Creating " n " students for teacher: " teacherName) (spit (str teacherName ".json") (gen-items-json (make-students teacherName n (defn gen [numTeachers numStudents] (doseq [teacherName (map make-teacher-name (range numTeachers))] (spit-json teacherName numStudents))) Thanks for any comments! Cheers, Craig -- -- 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.
Re: Newbie question about rebinding local variables
On Friday, April 20, 2012 1:15:11 PM UTC-5, kurtharriger wrote: > > > Game state does not have to be a map, it could be any datastructure > you want, perhaps a protocol that is implemented by a concrete class > in another JVM language. However, I avoid encapsulation unless there > is a compelling reason reason to add it. More often then not the > result of encapsulation is that the entire library of useful functions > like map, reduce, get-in, update-in, etc... are no longer useable with > this custom data structure. > > It is also not strictly required that all your functions be pure, you > could load or save game state to a database or external service as > necessary. There are very few applications that are strictly pure. > However, it is recommended that you make as much of your program pure > as possible. If each time you made a game move the state was written > to a database then you might have difficulty trying to run multiple > solver strategies in parallel as these side-effects would continuously > clobber the others database state. > > The general idea is that pure functions are easily composed and easy > to test, so use them whenever possible. Impure functions that write > to external services are often much more difficult to compose and > test, so keep them as small as possible. Think twice about calling an > impure function from a pure function as this makes it impure... main > will almost certainly be impure, but that does not mean that > everything else also needs to be impure. > I think that gives me a lot to ruminate on. Thanks, I appreciate the detailed advice. -- 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
Re: Newbie question about rebinding local variables
Thanks for your input, I appreciate it. On Friday, April 20, 2012 10:16:51 AM UTC-5, kurtharriger wrote: > > And you just need to keep the resulting state, no need to reapply the > moves. > Your main method might use a reduce or loop recur. > > (loop [game (new-game)] > (if-not (complete? game) > (recur (make-random-move game))) > The problem I have with this is that it does encapsulate game state completely, including input (the moves), but I want to just encapsulate board state. Imagine that the moves come from an external source, i.e. the web, my game state can't be stuck down in a function somewhere, the move is sent from the web, the game state is retrieved from somewhere (a session? a database?), and updated with the incoming move. I wasn't clear in stating my problem, but I want to decouple game state and board state for this reason. And because that's where I'm headed, it might make sense for me to approach this using atoms as others have suggested. I appreciate the different perspectives though, it's helping me understand! -- 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
Re: Newbie question about rebinding local variables
On Friday, April 20, 2012 9:07:49 AM UTC-5, Walter van der Laan wrote: > > You could start with pure functions to handle the game logic, e.g.: > > (defn new-game [] > [[\- \- \-] >[\- \- \-] >[\- \- \-]]) > > (defn print-game [game] > (doseq [row game] > (println (apply str row > > (defn move [game mark pos] > (assoc-in game pos mark)) > > (print-game (new-game)) > (print-game (move (new-game) \x [1 1])) > (print-game (-> (new-game) (move \x [1 1]) (move \o [0 2]))) > Right, but then I'm having to keep track of the moves and reapply them on every game update, right? I guess my question is more conceptual (so that I can gain an understanding of Clojure), I don't really care about tic tac toe, what I really care about is how to maintain mutable state. > -- 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
Re: Newbie question about rebinding local variables
Thanks for the help to both of you! Question, does it seem heavy handed to do it this way? I mean, atoms are more for thread-safety, aren't they? I don't have threads so it seems a bit much to use atoms for this. Am I better off using recur and trying to loop? Or is this considered an idiomatic way to handle mutable data in Clojure? I always found wrapping up mutable data in a closure as we did in Scheme to be pretty elegant, but maybe something like that goes against the desire of Clojure to protect against concurrent modification, is that about right? Thanks again! On Thursday, April 19, 2012 10:01:23 PM UTC-5, Gaz wrote: > > to answer your question directly, you would need to do something like > this to make it work the way your example is set up: > > (defn new-game [] > (let [board (atom (into [] (repeat 9 nil)))] > (fn [n & [i]] > (cond >(= n :x) (swap! board assoc i 'x) >(= n :o) (swap! board assoc i 'o) >(= n :print) (println @board) > > (def g1 (new-game)) > > (g1 :x 0) > (g1 :print) > > On Thu, Apr 19, 2012 at 9:58 PM, Armando Blancas > wrote: > > You could keep the board in an atom so it can mutate; then try to find > maybe > > two good places for mutation to happen, your move and the program's. With > > the rest being functional you'll avoid the problems of global state while > > not being forced to fit your logic into a loop of some re-binding that > > simulates mutation. > > > > > > On Thursday, April 19, 2012 3:21:56 PM UTC-7, Craig Ching wrote: > >> > >> Ok, I've read that what I want to do is a no no. But this is the sort > of > >> thing I did in Scheme about 20 years ago (and because of that I'm > probably > >> misremembering ;-)). > >> > >> Basically I'm learning clojure and thought I'd write a tic tac toe game. > >> But not any tic tac toe, I want to write one where I can have multiple > >> games going simultaneously. Something like: > >> > >> (def g1 (new-game)) > >> (def g2 (new-game)) > >> > >> (g1 :x 0) > >> (g1 :print) > >> (g2 :x 5) > >> (g2 :print) > >> > >> So the schemer in me (and probably the imperative programmer as well) > >> thought I could return a clojure that encapsulates the board value, > >> something like this: > >> > >> (defn new-game [] > >> > >> (let [board (into [] (repeat 9 nil))] > >> > >> (fn [n i] > >> > >> (cond > >> > >> (= n :x)(set! board (assoc board i 'x)) > >> > >> (= n :o)(set! board (assoc board i 'o)) > >> > >> (= n :print) (println board) > >> > >> > >> Of course I get an error saying I can't bind to the non-mutable board. > >> > >> I'm really new to Clojure, so apologies if this is really basic for this > >> list. Can I do what I want or can someone point me in the right > direction? > >> I've seen some other tic tac toe implementations on github, but they > use > >> recur to track state and I was hoping there was a cleaner idiomatic way > than > >> that. > >> > >> Thanks! > >> > > -- > > 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 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
Newbie question about rebinding local variables
Ok, I've read that what I want to do is a no no. But this is the sort of thing I did in Scheme about 20 years ago (and because of that I'm probably misremembering ;-)). Basically I'm learning clojure and thought I'd write a tic tac toe game. But not any tic tac toe, I want to write one where I can have multiple games going simultaneously. Something like: (def g1 (new-game)) (def g2 (new-game)) (g1 :x 0) (g1 :print) (g2 :x 5) (g2 :print) So the schemer in me (and probably the imperative programmer as well) thought I could return a clojure that encapsulates the board value, something like this: (defn new-game [] (let [board (into [] (repeat 9 nil))] (fn [n i] (cond (= n :x)(set! board (assoc board i 'x)) (= n :o)(set! board (assoc board i 'o)) (= n :print) (println board) Of course I get an error saying I can't bind to the non-mutable board. I'm really new to Clojure, so apologies if this is really basic for this list. Can I do what I want or can someone point me in the right direction? I've seen some other tic tac toe implementations on github, but they use recur to track state and I was hoping there was a cleaner idiomatic way than that. Thanks! -- 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