One caveat is that because this works by transforming the code into
Continuation Passing Style, it's dog slow, like 2 orders of magnitude for
regular Clojure code. This is not really much of an issue for user interface
related code (which is what I'm using it for), but unrealistic for pretty
much anything else.
However, with some quick testing I note that using Exceptions for flow
control might be even 2x slower than clj-cont.

On Mon, Apr 13, 2009 at 1:54 PM, David Nolen <dnolen.li...@gmail.com> wrote:

> Using try-catch for control flow is probably not a good idea. Shameless
> plug, do you think you could get this to work with clj-cont? clj-cont is a
> port I did of cl-cont. It has some limitations, but because Clojure has so
> few special forms (compared to Common Lisp), it has the chance to achieve
> pretty good coverage.
> I'm trying to get it working with compojure and enlive for web development
> a la Seaside and Weblocks- it would be interesting to see what other uses it
> might have.
>
> 2009/4/10 André Ferreira <greis...@gmail.com>
>
>
>> So, I was wondering if anyone had implemented the amb operator in
>> Clojure, so I decided to give it a try. This is my first Clojure
>> program bigger then 5 lines, the code still needs ALOT of work, it is
>> ugly as hell atm, but I think it kind of works. (Yes, I know, it's
>> very easy to bug it, its just a sketch). Notice that unlike most
>> continuation based amb operators, the amount of backtracking this
>> implementation has to do depends on the order of the requires, not the
>> amb assignments.
>> If anyone wants to clear or improve the code, go ahead.
>> I also would like to know how to be able to write @baker instead of
>> the current (myderef baker), I tried using a proxy and implementing
>> IDeref, but then I couldn't acess the amb-struct private data. Since
>> Clojure doesn't have continuations I had to use a try catch block to
>> do the stack unwinding, and some redundant calculations might be done
>> because of it.
>>
>> Here is the code:
>>
>> (defstruct amb-struct :instance :orig :possible)
>>
>> (def amb-stack nil)
>> (defn amb [choices]
>>  (struct-map amb-struct :instance false :orig choices  :possible
>> choices))
>>
>> (defn myderef [a]
>>  (if (:instance @a)
>>    (:value @a)
>>    (do
>>      (set! amb-stack (cons a amb-stack))
>>      (let
>>          [oldpos (:possible @a)]
>>        (var-set a (assoc @a
>>                         :value (first oldpos)
>>                         :instance true
>>                         :possible (rest oldpos))))
>>      (:value @a))))
>>
>> (defn amb-require [condition]
>>  (if condition
>>    nil
>>    (do
>>      (throw (.Exception "nothing")))))
>>
>> (defn bindnext []
>>  (if (empty? amb-stack)
>>    'nomatchfound
>>    (let [lastbind (first amb-stack)
>>          oldpos (:possible @lastbind)]
>>      (if (empty? oldpos)
>>        (do
>>          (var-set lastbind (assoc @lastbind :instance false :possible
>> (:orig
>> @lastbind)))
>>          (set! amb-stack (rest amb-stack))
>>          (recur))
>>        (do
>>          (var-set lastbind (assoc @lastbind :value (first oldpos)
>> :possible
>> (rest oldpos)))
>>          'recur)))))
>>
>>
>> (defmacro amb-let [declarations & body]
>>  `(with-local-vars
>>        ~declarations
>>      (binding [amb-stack nil]
>>        (loop []
>>          (let [retvalue#
>>                (try
>>                 (do ~...@body)
>>                 (catch Exception ~'except
>>                   (bindnext)))]
>>            (cond
>>              (= retvalue# 'recur) (recur)
>>              true retvalue#))))))
>>
>> (defn distinct-seq? [s]
>>  (cond
>>    (empty? (rest s)) true
>>    (= (first s) (second s)) false
>>    true (and (distinct-seq? (cons (first s) (rest (rest s))))
>>              (distinct-seq? (rest s)))))
>>
>> (amb-let [baker (amb [1 2 3 4 5])
>>          cooper (amb [1 2 3 4 5])
>>          fletcher (amb [1 2 3 4 5])
>>          miller (amb [1 2 3 4 5])
>>          smith (amb [1 2 3 4 5])]
>>  (amb-require (distinct-seq? (map myderef (list baker cooper fletcher
>> miller smith))))
>>  (amb-require (not (= (myderef baker) 5)))
>>  (amb-require (not (= (myderef cooper) 1)))
>>  (amb-require (not (= (myderef fletcher) 1)))
>>  (amb-require (not (= (myderef fletcher) 5)))
>>  (amb-require (> (myderef miller) (myderef cooper)))
>>  (amb-require (not (= 1 (. java.lang.Math abs (- (myderef smith)
>> (myderef fletcher))))))
>>  (amb-require (not (= 1 (. java.lang.Math abs (- (myderef fletcher)
>> (myderef cooper))))))
>>  [['baker (myderef baker)]
>>   ['cooper (myderef cooper)]
>>   ['fletcher (myderef fletcher)]
>>   ['miller (myderef miller)]
>>   ['smith (myderef smith)]])
>>
>> Running it returns [[baker 3] [cooper 2] [fletcher 4] [miller 5]
>> [smith 1]]
>>
>> >>
>>
>

--~--~---------~--~----~------------~-------~--~----~
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
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