Awesome! I've been re-factoring my code but I am having difficulty figuring out how to deal with state without manipulating global state; my first thought was to create a binding form within a doseq in a function that executed each instruction and mutated the cells when necessary--but that didn't work out. I like your usage of multimethods to deal with each instruction, although as a beginner some parts of your code are difficult for me to follow. This is shaping up to be a pretty good learning experience for me! I think my mind is still stuck in an imperative mode of thinking, and it's helpful to look at the code of a more seasoned clojure programmer.
On Sunday, April 7, 2013 10:06:26 PM UTC-4, Michał Marczyk wrote: > > Incidentally, this thread made me feel a sudden desire to write my own > bf interpreter. Feel free to take a look at > > https://github.com/michalmarczyk/bf.clj > > if you'd like. :-) > > Cheers, > Michał > > > On 7 April 2013 05:23, Sean Corfield <seanco...@gmail.com <javascript:>> > wrote: > > I agree. I see nothing that sets the code pointer back to the start of > the loop. > > > > I also agree with Michał's suggestion that getting rid of global state > > and making this more functional in style will make it much easier to > > read, debug and maintain - as it stands it not very idiomatic for > > Clojure. > > > > Sean > > > > On Sat, Apr 6, 2013 at 5:16 PM, Michał Marczyk > > <michal....@gmail.com<javascript:>> > wrote: > >> Not sure why you're using (- end-index 2) in the printed message. > >> Also, you can use (dec end-index) in your termination condition. > >> > >> As for the main problem, I haven't studied your program very closely, > >> but it seems to me that your program counter may never get reset to > >> the beginning of the loop, in which case the next call to > >> (exec-instruction end-loop) would start executing instructions just > >> past the end of the loop body. > >> > >> Cheers, > >> Michał > >> > >> > >> On 7 April 2013 01:49, Andrew Spano <werdn...@gmail.com <javascript:>> > wrote: > >>> Hello, I'm a new clojure programmer--but after learning a bit of > clojure > >>> including iteration, some core high order functions, and a little bit > about > >>> state management I decided to try my hand on a brainfuck interpreter. > >>> > >>> Located here: > >>> > https://github.com/recursor94/brainfuck.clj/blob/master/brainfuck/src/brainfuck/fuck.clj > > >>> > >>> Handling looping complicated things. And the way I chose to deal with > >>> looping resulted in some pretty ugly functions. I hope to clean that > up in > >>> the future and refractor the code into a more functional style after > I've > >>> finished the first draft. > >>> > >>> The issue is in a particular function which never stops recuring even > when > >>> the condition for recuring is false: > >>> > >>> (defn exec-instruction > >>> "executes each function in the codemap vector in sequential order" > >>> > >>> > >>> ([end-index] > >>> (inc-code-pos) ;;side affect function that moves the code > pointer (I > >>> have both a code pointer and a data pointer in my interpreter) > >>> (loop [index (:index @codemap)] > >>> (let [codevec (@codemap :struct) > >>> instruct (get codevec index)] > >>> (println "index:" index > >>> "instruct" instruct > >>> "minus one index:" (- end-index 2)) > >>> (instruct)) > >>> (when-not (= index (- end-index 1)) > >>> (println "yeah you are") > >>> (inc-code-pos) > >>> (recur (inc index))))) > >>> ;;end problem > >>> ([] > >>> (doseq [instruct (@codemap :struct)] > >>> (instruct) ;;higher order functions ftw > >>> (inc-code-pos)))) > >>> > >>> > >>> And here is the function that triggers this function: > >>> > >>> (defn begin-loop > >>> "run through a loop until current cell drops to zero" > >>> [] > >>> (loop [loop-counter (@cells @pointer) > >>> end-loop (find-end (@codemap :index)) ;;find-end returns an > integer > >>> pos (@codemap :index)] > >>> (println "cell counter:" loop-counter > >>> "other:" (@cells @pointer) > >>> "at 0:" (@cells @pointer) > >>> "also:" end-loop) ;;debug output > >>> (exec-instruction end-loop) > >>> (when-not (= loop-counter 0) > >>> (recur (@cells @pointer) end-loop pos)))) > >>> > >>> > >>> The program is supposed to stop when it reaches a closing end brace > and jump > >>> back to the opening brace in the code. But the output indicates that > the > >>> program never gets passed the first iteration. > >>> > >>> For example, given this hello world brainfuck program: > >>> > >>> > >>> > ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. > > > >>> > >>> The program outputs the following: > >>> index: 11 instruct #'brainfuck.fuck/+pointer minus one index: 39 > >>> yeah you are > >>> index: 12 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 13 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 14 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 15 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 16 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 17 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 18 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 19 instruct #'brainfuck.fuck/+pointer minus one index: 39 > >>> yeah you are > >>> index: 20 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 21 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 22 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 23 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 24 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 25 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 26 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 27 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 28 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 29 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 30 instruct #'brainfuck.fuck/+pointer minus one index: 39 > >>> yeah you are > >>> index: 31 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 32 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 33 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 34 instruct #'brainfuck.fuck/+pointer minus one index: 39 > >>> yeah you are > >>> index: 35 instruct #'brainfuck.fuck/plus minus one index: 39 > >>> yeah you are > >>> index: 36 instruct #'brainfuck.fuck/-pointer minus one index: 39 > >>> yeah you are > >>> index: 37 instruct #'brainfuck.fuck/-pointer minus one index: 39 > >>> yeah you are > >>> index: 38 instruct #'brainfuck.fuck/-pointer minus one index: 39 > >>> yeah you are > >>> index: 39 instruct #'brainfuck.fuck/-pointer minus one index: 39 > >>> yeah you are > >>> index: 40 instruct #'brainfuck.fuck/minus minus one index: 39 > >>> cell counter: 9 other: 9 at 0: 9 also: 41 > >>> index: 41 instruct #'brainfuck.fuck/end-loop minus one index: 39 > >>> Exception in thread "main" java.lang.IllegalStateException: Attempting > to > >>> call unbound fn: #'brainfuck.fuck/end-loop > >>> at clojure.lang.Var$Unbound.throwArity(Var.java:43) > >>> at clojure.lang.AFn.invoke(AFn.java:35) > >>> at clojure.lang.Var.invoke(Var.java:411) > >>> at brainfuck.fuck$exec_instruction.invoke(fuck.clj:142) > >>> at brainfuck.fuck$begin_loop.invoke(fuck.clj:94) > >>> at clojure.lang.Var.invoke(Var.java:411) > >>> at brainfuck.fuck$exec_instruction.invoke(fuck.clj:149) > >>> at brainfuck.fuck$_main.invoke(fuck.clj:165) > >>> at clojure.lang.Var.invoke(Var.java:411) > >>> at user$eval218.invoke(NO_SOURCE_FILE:1) > >>> at clojure.lang.Compiler.eval(Compiler.java:6511) > >>> at clojure.lang.Compiler.eval(Compiler.java:6501) > >>> at clojure.lang.Compiler.eval(Compiler.java:6477) > >>> at clojure.core$eval.invoke(core.clj:2797) > >>> at clojure.main$eval_opt.invoke(main.clj:297) > >>> at clojure.main$initialize.invoke(main.clj:316) > >>> at clojure.main$null_opt.invoke(main.clj:349) > >>> at clojure.main$main.doInvoke(main.clj:427) > >>> at clojure.lang.RestFn.invoke(RestFn.java:421) > >>> at clojure.lang.Var.invoke(Var.java:419) > >>> at clojure.lang.AFn.applyToHelper(AFn.java:163) > >>> at clojure.lang.Var.applyTo(Var.java:532) > >>> at clojure.main.main(main.java:37) > >>> > >>> > >>> Aside from too much incidental complexity, I can't figure out what I > did > >>> wrong here and why the loop never seems to stop iterating when it > clearly > >>> should. Any help at all is sincerely appreciated. In fact, I'd love > any > >>> pointers about the program structure itself if you care to take a look > at my > >>> github. > >>> > >>> Thanks, > >>> > >>> --Andrew > >>> > >>> -- > >>> -- > >>> You received this message because you are subscribed to the Google > >>> Groups "Clojure" group. > >>> To post to this group, send email to clo...@googlegroups.com<javascript:> > >>> Note that posts from new members are moderated - please be patient > with your > >>> first post. > >>> To unsubscribe from this group, send email to > >>> clojure+u...@googlegroups.com <javascript:> > >>> 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+u...@googlegroups.com <javascript:>. > >>> 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 clo...@googlegroups.com<javascript:> > >> Note that posts from new members are moderated - please be patient with > your first post. > >> To unsubscribe from this group, send email to > >> clojure+u...@googlegroups.com <javascript:> > >> 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+u...@googlegroups.com <javascript:>. > >> For more options, visit https://groups.google.com/groups/opt_out. > >> > >> > > > > > > > > -- > > Sean A Corfield -- (904) 302-SEAN > > An Architect's View -- http://corfield.org/ > > World Singles, LLC. -- http://worldsingles.com/ > > > > "Perfection is the enemy of the good." > > -- Gustave Flaubert, French realist novelist (1821-1880) > > > > -- > > -- > > You received this message because you are subscribed to the Google > > Groups "Clojure" group. > > To post to this group, send email to clo...@googlegroups.com<javascript:> > > Note that posts from new members are moderated - please be patient with > your first post. > > To unsubscribe from this group, send email to > > clojure+u...@googlegroups.com <javascript:> > > 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+u...@googlegroups.com <javascript:>. > > 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.