On 19 April 2010 20:34, Kevin Livingston <kevinlivingston.pub...@gmail.com> wrote: > I ported the unifier posted by Norvig in Common Lisp to Clojure...
Cool! Before I comment on a few specific points you make / questions you ask, here are the results of a few minutes I spent playing with / rewriting your code: http://gist.github.com/373303 > major questions > 1. this is ugly: (and (seq? x) (not (empty? x))) in common lisp you > just use consp is there no equivalent in clojure? there is (seq x) > but that barfs if it's given a symbol. The loss of the cleanness of > iterating/recursing until you hit nil is unfortunate (it made for some > elegant lisp code) I can't think of a direct equivalent now, but it's straightforward enough to supply your own equivalent, like my compound? function (basically #(and (seq? %) (seq %))). This won't work on arrays and other things which seq can operate upon, but which respond with a false to seq?, though. If that could be a problem, you can just use seq and for non-seqables catch the exception and return false. > 2. there are self calls and mutual calls throughout - which could > create a stack problem. advice for how to get around this? > specifically calls like the following seem hard to fix, or at least I > don't know the "duh" way to do it (I always just let my lisp compiler > do all the work for me) You could perform a CPS transform by hand (which I haven't (yet) done with the code in the Gist). For occurs-check this would mean having an extra to-do argument (or maybe just [... & to-do]); whenever false would normally be returned, you'd first check if to-do is empty, returning false if so and doing (recur <args taken from (first to-do)> (rest to-do)) otherwise. true should short-circuit and disregard to-do, of course. Finally, whenever occurs-check would normally branch on first / rest, it would recur with first *and* an extended to-do including rest. > 2'. I'm to understand that next is now preferred to rest? (which is an > unfortunate name at least for my lisp mind, since it seems like it > should be returning an element instead of rest - but I'll learn > eventually) Not at all. next is basically #(seq (rest %)); you might want to use it when the extra bit of strictness is beneficial to your code and you shouldn't use it when it isn't. > minor questions: > a. what's the preferred indenting style for cond? Good question. I really prefer the fully parenthesised cond clauses from Scheme / CL / elisp, in good part because of the nicer indentation without particularly elaborate rules... :-( > b. is def the correct way to introduce constants and thread safe > places to bind over? > c. is that the correct / best / preferred way to set default values > for the optional parameter in unify? If you expect to want / need to replace the default occasionally, then sure, you could do it with a Var and (binding [...] ...). On the other hand, unify already accepts a "bindings" parameter, so you could just as well pass in an explicit starting value when you need to. I think that your code would benefit from direct use of Clojure data structure literals and such facilities as the IFn implementation available on maps; see my gist for examples of what I have in mind. Sincerely, Michał -- 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