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

Reply via email to