Re: Generic functions: things, models, and protocols revisited
> > > > Seems like this kind of dispatch and the Datalog project might meet up > soon? > > Or am I totally wrong? > > I have given it zero thought. Perhaps interesting to pursue? Rich had brought it up in conversations about predicate dispatch. Could greatly help from the performance side of things? --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Re: Generic functions: things, models, and protocols revisited
On Feb 12, 1:27 pm, David Nolen wrote: > Neat! You've removed the need to even define a dispatch-fn. Maybe; maybe not. The built-in dispatch mechanism uses a selection scheme that applies a sequence of increasingly restrictive, but also increasingly costly, tests; basically, the tests in order are: (1) identity; (2) isa? (3) model? (is this value a map and are all its keys members of one or more test maps) (4) = (5) an arbitrary user- supplied test. A fuller implementation should probably provide the option of replacing that dispatch algorithm with one of your own choosing, probably as an option to make-generic-function. > Seems like this kind of dispatch and the Datalog project might meet up soon? > Or am I totally wrong? I have given it zero thought. --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Re: Generic functions: things, models, and protocols revisited
Neat! You've removed the need to even define a dispatch-fn. I'll need to chew on this for a bit (I'm a little slow :) I'm still working on my attempt at implementing protocols, but I'm not totally clear on where it will go or how useful it will be. Seems like this kind of dispatch and the Datalog project might meet up soon? Or am I totally wrong? On Thu, Feb 12, 2009 at 12:02 PM, mikel wrote: > > David Nolen and I were recently discussing CLOS and method dispatch. I > implemented such a scheme for my own use. This post is an FYI for > David and anyone else who might be interested in generic functions and > predicate dispatch. > > Here's a transcript of a sample session in which I exercise the > dispatch cases: > > (def $gf (make-generic-function)) > > (add-gf-method $gf [nil] (fn [x] (str "found value: " (.toString x) " > of type: " (.toString (class x) > > (add-gf-method $gf [java.lang.Number] (fn [x] (+ x 1))) > > (add-gf-method $gf [java.lang.String] (fn [x] (str "Found string: " > x))) > > (add-gf-method $gf [{:equals 5}] (fn [x] (str "Found 5!"))) > > (add-gf-method $gf [{:model {:name nil}}] (fn [x] (str "Found a thing > whose name is " (:name x > > (add-gf-method $gf [java.lang.Number java.lang.Number] (fn [x y] (+ x > y))) > > (add-gf-method $gf [java.lang.String java.lang.String] (fn [x y] (str > x " " y))) > > (add-gf-method $gf [java.lang.String java.lang.Integer] (fn [s i] > (apply str (take i (cycle [s]) > > (add-gf-method $gf [{:test (fn [x] (= x "swordfish"))}] (fn [s] (str > "You said the secret word, you win a hundred dollars!"))) > > user> ($gf "hello" "world") > "hello world" > user> ($gf 2 3) > 5 > user> ($gf {:name "Barney"}) > "Found a thing whose name is Barney" > user> ($gf 5) > "Found 5!" > user> ($gf "bananas") > "Found string: bananas" > user> ($gf 100) > 101 > user> ($gf 'some-symbol) > "found value: some-symbol of type: class clojure.lang.Symbol" > user> ($gf "foo" 5) > "foofoofoofoofoo" > user> ($gf "swordfish") > "You said the secret word, you win a hundred dollars!" > > > It works well enough to produce that transcript, but is very > preliminary. I'm sure there are bugs I haven't noticed yet, and no > doubt it's terribly slow. For one thing, I know it's doing a lot of > redundant comparisons at the moment. > > It's missing a number of amenities and at least one important feature: > next-method is not yet implemented. > > When called, a generic function matches the arguments it received > against formal parameters in its dispatch table. Matching of a formal > parameter works like so: > > nil: match any value passed in this position > > a Java class: match any value that is an instance of the class (or of > a subclass of it) > > a Map of the form: {:model m}: match any value v for which (model? v > m) returns true > > a Map of the form {:equals x}: match any value v for which (= v x) > returns true > > a Map of the form {:test f}: match any value for which (f x) returns > true > > > Calling ($gf 2 3) or whatever works because the object in $gf is a > closure: > > (defn make-generic-function [& [dispatch-table]] > (let [dt-ref (or dispatch-table (ref {}))] >(fn [& args] (apply-generic-function dt-ref args > > There's a little trickery with sentinel values and metadata to enable > me to provide an API for adding and removing methods, which are stored > in the dispatch-table created in make-generic-function. It would be > nice to make that code a little less clever, but that would require a > convenient way to create a new kind of callable object; I'd need to be > able to define what happens when it's applied. > > Now we'll see if this thing is useful enough to make it better. > > > --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---
Generic functions: things, models, and protocols revisited
David Nolen and I were recently discussing CLOS and method dispatch. I implemented such a scheme for my own use. This post is an FYI for David and anyone else who might be interested in generic functions and predicate dispatch. Here's a transcript of a sample session in which I exercise the dispatch cases: (def $gf (make-generic-function)) (add-gf-method $gf [nil] (fn [x] (str "found value: " (.toString x) " of type: " (.toString (class x) (add-gf-method $gf [java.lang.Number] (fn [x] (+ x 1))) (add-gf-method $gf [java.lang.String] (fn [x] (str "Found string: " x))) (add-gf-method $gf [{:equals 5}] (fn [x] (str "Found 5!"))) (add-gf-method $gf [{:model {:name nil}}] (fn [x] (str "Found a thing whose name is " (:name x (add-gf-method $gf [java.lang.Number java.lang.Number] (fn [x y] (+ x y))) (add-gf-method $gf [java.lang.String java.lang.String] (fn [x y] (str x " " y))) (add-gf-method $gf [java.lang.String java.lang.Integer] (fn [s i] (apply str (take i (cycle [s]) (add-gf-method $gf [{:test (fn [x] (= x "swordfish"))}] (fn [s] (str "You said the secret word, you win a hundred dollars!"))) user> ($gf "hello" "world") "hello world" user> ($gf 2 3) 5 user> ($gf {:name "Barney"}) "Found a thing whose name is Barney" user> ($gf 5) "Found 5!" user> ($gf "bananas") "Found string: bananas" user> ($gf 100) 101 user> ($gf 'some-symbol) "found value: some-symbol of type: class clojure.lang.Symbol" user> ($gf "foo" 5) "foofoofoofoofoo" user> ($gf "swordfish") "You said the secret word, you win a hundred dollars!" It works well enough to produce that transcript, but is very preliminary. I'm sure there are bugs I haven't noticed yet, and no doubt it's terribly slow. For one thing, I know it's doing a lot of redundant comparisons at the moment. It's missing a number of amenities and at least one important feature: next-method is not yet implemented. When called, a generic function matches the arguments it received against formal parameters in its dispatch table. Matching of a formal parameter works like so: nil: match any value passed in this position a Java class: match any value that is an instance of the class (or of a subclass of it) a Map of the form: {:model m}: match any value v for which (model? v m) returns true a Map of the form {:equals x}: match any value v for which (= v x) returns true a Map of the form {:test f}: match any value for which (f x) returns true Calling ($gf 2 3) or whatever works because the object in $gf is a closure: (defn make-generic-function [& [dispatch-table]] (let [dt-ref (or dispatch-table (ref {}))] (fn [& args] (apply-generic-function dt-ref args There's a little trickery with sentinel values and metadata to enable me to provide an API for adding and removing methods, which are stored in the dispatch-table created in make-generic-function. It would be nice to make that code a little less clever, but that would require a convenient way to create a new kind of callable object; I'd need to be able to define what happens when it's applied. Now we'll see if this thing is useful enough to make it better. --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---