Re: Translating simple path finding problem from prolog to core.logic

2013-06-30 Thread Craig Ching
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

2013-06-30 Thread Craig Ching
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

2013-06-08 Thread Craig Ching
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

2013-06-08 Thread Craig Ching
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

2013-03-11 Thread Craig Ching


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

2013-03-11 Thread Craig Ching
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

2013-03-10 Thread Craig Ching
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

2013-03-09 Thread Craig Ching
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

2012-04-20 Thread Craig Ching


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

2012-04-20 Thread Craig Ching
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

2012-04-20 Thread Craig Ching


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

2012-04-20 Thread Craig Ching
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

2012-04-19 Thread Craig Ching
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