Re: Datatypes and Protocols - early experience program

2009-11-24 Thread Allen Rohner


On Nov 12, 6:10 am, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich
>
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
> [2]http://www.assembla.com/wiki/show/clojure/Protocols
> [3]http://github.com/richhickey/clojure/tree/new
> [4]http://build.clojure.org/



On Nov 12, 6:10 am, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich
>
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
> [2]http://www.assembla.com/wiki/show/clojure/Protocols
> [3]http://github.com/richhickey/clojure/tree/new
> [4]http://build.clojure.org/

And a feature request: Validators on deftypes. Currently, I have a
bunch of refs that point at maps, with validator functions. The ref
validators mainly validate the contents of the map, i.e. that certain
keys are present and have sane values. It seems to make more sense to
do the checking on the type validator, and then the ref's validator
would just check that the ref's value is the correct type.

Allen

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


Re: Datatypes and Protocols - early experience program

2009-11-24 Thread Meikel Brandmeyer
Hi,

On Nov 23, 3:29 pm, Krukow  wrote:

> Two comments.
>
> First is a bug.
> Using newest commit of new: 75cd05080f7260c54007d7728fb280ae53b56f63

Same here: 
http://groups.google.com/group/clojure-dev/browse_thread/thread/6d5cf269b18c4540
but no feedback so far. :(

Sincerely
Meikel

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


Re: Datatypes and Protocols - early experience program

2009-11-24 Thread Chouser
On Tue, Nov 24, 2009 at 1:19 AM, Krukow  wrote:
>
>
> On Nov 24, 4:55 am, Allen Rohner  wrote:
>> The first stumbling point I reached is that deftypes provide an
>> automatic implementation for IPersistentMap, but not IFn. I attempted
>> to write (instance key), which exploded, but (key instance) works just
>> fine. My existing code uses (instance key) almost universally. Should
>> I get used to this, or are there plans to provide a default IFn
>> implementation?
>
> I agree that it would be nice with an automatic IFn implementation if
> you specify the interface.

If you use a (:k x) where :k is a literal keyword for
a pre-defined field of x (that is, not an entry you added to that
object using 'assoc'), Clojure will tweak that particular call
site to be very fast.  On the other hand, if you do (x :k) or
have a non-literal key such as a keyword stored in a local or
var, it will not do those extra performance tweaks.

I don't know if it would be possible to make (x :k) as fast as
(:k x), but I sorta doubt it will happen.

--Chouser

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


Re: Datatypes and Protocols - early experience program

2009-11-23 Thread Krukow


On Nov 24, 4:55 am, Allen Rohner  wrote:
> The first stumbling point I reached is that deftypes provide an
> automatic implementation for IPersistentMap, but not IFn. I attempted
> to write (instance key), which exploded, but (key instance) works just
> fine. My existing code uses (instance key) almost universally. Should
> I get used to this, or are there plans to provide a default IFn
> implementation?

I agree that it would be nice with an automatic IFn implementation if
you specify the interface. As an alternative, you could use

user> (deftype F[x] [clojure.lang.IPersistentMap clojure.lang.IFn]
 (.invoke [k] (k this)))
#'user/F
user> ((F 42) :x)
42
user>

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


Re: Datatypes and Protocols - early experience program

2009-11-23 Thread Allen Rohner


On Nov 12, 6:10 am, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich
>
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
> [2]http://www.assembla.com/wiki/show/clojure/Protocols
> [3]http://github.com/richhickey/clojure/tree/new
> [4]http://build.clojure.org/

The first stumbling point I reached is that deftypes provide an
automatic implementation for IPersistentMap, but not IFn. I attempted
to write (instance key), which exploded, but (key instance) works just
fine. My existing code uses (instance key) almost universally. Should
I get used to this, or are there plans to provide a default IFn
implementation?

Allen

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


Re: Datatypes and Protocols - early experience program

2009-11-23 Thread Krukow


On Nov 12, 1:10 pm, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich

I've had very good experiences so far - I really like the modeling
aspects of this.

Two comments.

First is a bug.
Using newest commit of new: 75cd05080f7260c54007d7728fb280ae53b56f63

Clojure 1.1.0-alpha-SNAPSHOT
user=> (deftype Foo [x])
#'user/Foo
user=> (defprotocol P (fun [x]))
P
user=> (extend ::Foo P {:fun (fn [x] x)})
nil
user=> (fun (Foo 42))
#:Foo{:x 42}
user=> (def f1 (Foo 42))
#'user/f1
user=> f1
#:Foo{:x 42}
user=> (def f2 (fun f1))
java.lang.IllegalAccessError (NO_SOURCE_FILE:7)
user=>

The error occurs if I try to bind the result of a protocol function to
a var.

Second is a feature request:

Map-based initializers and Default values for deftype.

Example:
user=> (deftype TransitionPolicy [fail-count timeout])
#'user/TransitionPolicy
user=> (def p (TransitionPolicy {:fail-count 5 :timeout 5000}))

;; I'd like

'user/p
user=> p
#:TransitionPolicy{:fail-count 5, :timeout 5000}
user=>

Now defaults:
user=> (deftype TransitionPolicy [fail-count :def 5 timeout :def
5000])

;;I'd like
#'user/TransitionPolicy
user=> (TransitionPolicy :fail-count 5)
#:TransitionPolicy{:fail-count {:fail-count 10}, :timeout 5000}
user=> (TransitionPolicy)
#:TransitionPolicy{:fail-count 5, :timeout 5000}

I know I can easily construct functions that realize these maps and
default initializers, but it would be nice to have Out-of-the-box if
it doesn't complicate the design.

Cheers,
/Karl

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


Re: Datatypes and Protocols - early experience program

2009-11-23 Thread Krukow


On Nov 20, 5:24 pm, Rich Hickey  wrote:
> Yup. The fixed field access to deftypes via keyword literal lookup is
> the fastest offered by any Clojure data structure.
>
> Rich

While we are talking performance. Is there a simple way to explain the
performance characteristics of protocols versus interfaces?

/Karl

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


Re: Datatypes and Protocols - early experience program

2009-11-23 Thread Rich Hickey
On Thu, Nov 19, 2009 at 12:39 PM, Krukow  wrote:
> On Nov 19, 12:01 am, samppi  wrote:
>> Question: are the general mechanisms for accessing and setting fields
>> their keywords and assoc respectively:
>>   (deftype Bar [a b c d e])
>>   (def b (Bar 1 2 3 4 5))
>>   (:c b)
>>   (def c (assoc b :e 2))
>> Does (:c b) and (assoc b :e 2) take advantage of Bar's field
>> information? Is it any faster than using an array map? Are there any
>> equivalents to struct maps' accessor functions?
>
> I've been wondering about this myself. I think you'd often want a
> "persistent" types in the sense of the persistent datastructure.
>
> You can use the ability to implement interfaces, specifically
> automatic support for IPersistentMap:
>
> ser=> (deftype Bar [a b] [clojure.lang.IPersistentMap])
> #'user/Bar
> user=> (assoc (Bar 1 2) :a 42)
> #:Bar{:a 42, :b 2}
> user=>
>
> I have a question here, though: what is this?
>
> ser=> (assoc (Bar 1 2) :c 42)
> #:Bar{:a 1, :b 2, :c 42}
> user=> #:Bar{:a 1, :b 2, :c 42}
>
> Is it a "Bar" with field-speed access to :a and :b and map-speed
> access to :c?

Yes.

>
> Also can I assume that
>
> (assoc (Bar 1 2) :a 42)
> #:Bar{:a 42, :b 2}
>
> will share structure with the (Bar 1 2) and still has fast access
> to :a? Is the assoc function using that :a is a field?
>

Shared structure only kicks in when data structures become large
enough for it to be a performance advantage. That's not the case for
small maps or the fixed fields of a deftype.


> I guess I am just asking if the performance guarantees are those I
> would expect of Clojure (i.e., "too fast" ;-))
>

Yup. The fixed field access to deftypes via keyword literal lookup is
the fastest offered by any Clojure data structure.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-20 Thread Krukow


On Nov 20, 8:51 pm, Chouser  wrote:
> On Thu, Nov 19, 2009 at 12:39 PM, Krukow  wrote:
[snip]
> > I guess I am just asking if the performance guarantees are those I
> > would expect of Clojure (i.e., "too fast" ;-))
>
> This is definitely still too fast.  In fact, it keeps getting worse.
>
> --Chouser

We gotta stop him ;-)

No, more seriously, I really like these new features. Not just for the
speed, but for the modeling support.

I'm wondering if I could get some feed-back on a defprotocol/deftype
example. I am wondering if I am thinking "too object oriented" here
and misusing the features, or if I am inline with the intended use of
protocols and types.

The example code is a "Circuit Breaker" (the stability pattern
mentioned in Michael Nygaard's "Release It!").

Code:
Circuit breaker states and transitions
http://gist.github.com/239797


Circuit breaker
http://gist.github.com/239798

Git repository:
http://github.com/krukow/clojure-circuit-breaker

The circuit breaker has a wrap function that takes another function
and returns a wrapped version of that function that uses the circuit
breaker. Right now there is only one circuit breaker instance, but
that's easy to generalize.

Feedback very welcome!

/Karl

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


Re: Datatypes and Protocols - early experience program

2009-11-20 Thread Chouser
On Thu, Nov 19, 2009 at 12:39 PM, Krukow  wrote:
> On Nov 19, 12:01 am, samppi  wrote:
>> Question: are the general mechanisms for accessing and setting fields
>> their keywords and assoc respectively:
>>   (deftype Bar [a b c d e])
>>   (def b (Bar 1 2 3 4 5))
>>   (:c b)
>>   (def c (assoc b :e 2))
>> Does (:c b) and (assoc b :e 2) take advantage of Bar's field
>> information? Is it any faster than using an array map? Are there any
>> equivalents to struct maps' accessor functions?

My understanding is that if you have (:c b) somewhere in your
code, and "b" is always an object of the same deftype with
a field "c", you're getting Java field-speed access (once hotspot
has done what it does).  Yes, that's faster than array map
lookup.  It's even faster than struct map accessor function lookup.

> You can use the ability to implement interfaces, specifically
> automatic support for IPersistentMap:
>
> ser=> (deftype Bar [a b] [clojure.lang.IPersistentMap])
> #'user/Bar
> user=> (assoc (Bar 1 2) :a 42)
> #:Bar{:a 42, :b 2}
> user=>
>
> I have a question here, though: what is this?
>
> ser=> (assoc (Bar 1 2) :c 42)
> #:Bar{:a 1, :b 2, :c 42}
> user=> #:Bar{:a 1, :b 2, :c 42}
>
> Is it a "Bar" with field-speed access to :a and :b and map-speed
> access to :c?

Yes, I think that's correct.

> Also can I assume that
>
> (assoc (Bar 1 2) :a 42)
> #:Bar{:a 42, :b 2}
>
> will share structure with the (Bar 1 2) and still has fast access
> to :a? Is the assoc function using that :a is a field?

There will be no shared structure between your two Bar object.
That is, the reference to 2 (or the value 2 itself if it were
a primitive) will be copied to the new object.

> I guess I am just asking if the performance guarantees are those I
> would expect of Clojure (i.e., "too fast" ;-))

This is definitely still too fast.  In fact, it keeps getting worse.

--Chouser

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


Re: Datatypes and Protocols - early experience program

2009-11-19 Thread Krukow
On Nov 19, 12:01 am, samppi  wrote:
> Question: are the general mechanisms for accessing and setting fields
> their keywords and assoc respectively:
>   (deftype Bar [a b c d e])
>   (def b (Bar 1 2 3 4 5))
>   (:c b)
>   (def c (assoc b :e 2))
> Does (:c b) and (assoc b :e 2) take advantage of Bar's field
> information? Is it any faster than using an array map? Are there any
> equivalents to struct maps' accessor functions?

I've been wondering about this myself. I think you'd often want a
"persistent" types in the sense of the persistent datastructure.

You can use the ability to implement interfaces, specifically
automatic support for IPersistentMap:

ser=> (deftype Bar [a b] [clojure.lang.IPersistentMap])
#'user/Bar
user=> (assoc (Bar 1 2) :a 42)
#:Bar{:a 42, :b 2}
user=>

I have a question here, though: what is this?

ser=> (assoc (Bar 1 2) :c 42)
#:Bar{:a 1, :b 2, :c 42}
user=> #:Bar{:a 1, :b 2, :c 42}

Is it a "Bar" with field-speed access to :a and :b and map-speed
access to :c?

Also can I assume that

(assoc (Bar 1 2) :a 42)
#:Bar{:a 42, :b 2}

will share structure with the (Bar 1 2) and still has fast access
to :a? Is the assoc function using that :a is a field?

I guess I am just asking if the performance guarantees are those I
would expect of Clojure (i.e., "too fast" ;-))

/Karl

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


Re: Datatypes and Protocols - early experience program

2009-11-18 Thread samppi
This is wonderful, wonderful, wonderful. It makes my work with FnParse
so much easier.

Question: are the general mechanisms for accessing and setting fields
their keywords and assoc respectively:
  (deftype Bar [a b c d e])
  (def b (Bar 1 2 3 4 5))
  (:c b)
  (def c (assoc b :e 2))
Does (:c b) and (assoc b :e 2) take advantage of Bar's field
information? Is it any faster than using an array map? Are there any
equivalents to struct maps' accessor functions?

On Nov 12, 5:10 am, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich
>
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
> [2]http://www.assembla.com/wiki/show/clojure/Protocols
> [3]http://github.com/richhickey/clojure/tree/new
> [4]http://build.clojure.org/

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


Re: Datatypes and Protocols - early experience program

2009-11-17 Thread harrison clarke
can anyone explain why this doesn't work?

(defprotocol arrow
  (>>> ([f g] [f g & fs]) "compose left to right"))

(extend clojure.lang.Fn
  arrow
  {:>>> (fn
  ([f g] #(g (f %)))
  ([f g & fs] (apply >>> (>>> f g) fs)))})

(>>> inc inc inc)

; gives this error:
; java.lang.IllegalArgumentException: Wrong number of args passed to:
user$eval--21$fn--23$G--10 (test.clj:3)

this does work, however:
(>>> inc inc)
(>>> inc inc inc)

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


Re: Datatypes and Protocols - early experience program

2009-11-17 Thread Sean Devlin
A quick aside about matrices.  Every dense matrix algorithm is
measured by the number of rows (n).  LU factorization is O(n^3), as is
QR.  If memory serves, Eigenvalues are usually O(n^2).  Determinants
are O(n^3), too.  These estimates change if the matrix is banded, they
usually become O(n).

The point is, mathematicians care about the number of rows.  I'd
recommend that.

Sean

On Nov 17, 10:09 am, Stuart Sierra 
wrote:
> On Nov 16, 11:57 am, Jonas Enlund  wrote:
>
> > I made count return the number of rows because that way (count
> > a-matrix) == (count (seq a-matrix)). I don't know if it's the right
> > thing to do, maybe rows*cols would make more sense.
>
> Good point.  I don't know which is better.
> -SS

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


Re: Datatypes and Protocols - early experience program

2009-11-17 Thread Stuart Sierra
On Nov 16, 11:57 am, Jonas Enlund  wrote:
> I made count return the number of rows because that way (count
> a-matrix) == (count (seq a-matrix)). I don't know if it's the right
> thing to do, maybe rows*cols would make more sense.

Good point.  I don't know which is better.
-SS

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


Re: Datatypes and Protocols - early experience program

2009-11-16 Thread Jonas Enlund
On Mon, Nov 16, 2009 at 6:27 PM, Stuart Sierra
 wrote:
> On Nov 14, 8:28 am, Jonas Enlund  wrote:
>> I have built a simple Matrix datatype with defprotocol and deftype.
>> You can take a look at it athttp://gist.github.com/234535
>> (constructive criticism welcome!).
>
> Small thing: I would expect (count a-matrix) to return rows*columns,
> not the number of rows.

I made count return the number of rows because that way (count
a-matrix) == (count (seq a-matrix)). I don't know if it's the right
thing to do, maybe rows*cols would make more sense.

/Jonas

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


Re: Datatypes and Protocols - early experience program

2009-11-16 Thread Stuart Sierra
On Nov 14, 8:28 am, Jonas Enlund  wrote:
> I have built a simple Matrix datatype with defprotocol and deftype.
> You can take a look at it athttp://gist.github.com/234535
> (constructive criticism welcome!).

Small thing: I would expect (count a-matrix) to return rows*columns,
not the number of rows.

-SS

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


Re: Datatypes and Protocols - early experience program

2009-11-16 Thread Sean Devlin
Enclojure users:

I was able to confirm John's problem in Enclojure.  I found a work
around.  Read more here:

http://groups.google.com/group/enclojure/browse_thread/thread/6bddd3153ece02f2

On Nov 16, 12:12 am, John Harrop  wrote:
> On Sun, Nov 15, 2009 at 8:17 PM, David Brown  wrote:
> > On Sun, Nov 15, 2009 at 04:20:19PM -0500, John Harrop wrote:
>
> > >That's weird. It's not documented anywhere on the site. And it seems to
> > hang
> > >the REPL:
>
> > >user=> nil #!foo
>
> > >and nothing. Enter doesn't print "nil" and a fresh user=> prompt as it
> > >should and nothing else apparently works either. The REPL is either wedged
> > >or interpreting everything as comment from then on.
>
> > >Weirdly enough, ; hangs the REPL likewise.
>
> > How's the data getting to the REPL?  jline, or ide?
>
> Enclojure IDE.

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


Re: Datatypes and Protocols - early experience program

2009-11-16 Thread Michael Wood
2009/11/16 John Harrop :
> On Mon, Nov 16, 2009 at 2:16 AM, Michael Wood  wrote:
>>
>> This is what I get with or without rlwrap from the command line.  No
>> IDE or anything like that:
>>
>> Clojure 1.1.0-alpha-SNAPSHOT
>> user=> ; some comment
>> user=> #! something
>> (println "blah")
>> blah
>> nil
>> user=>
>>
>> i.e. the same as David.
>
> Well, that's odd. I get a hang no matter what. I can enter as many lines of
> random crap as I like and never get back a user=> prompt. Sometimes I also
> can't enter blank lines -- enter does nothing at start of line, and starts a
> new line (w/o prompt) otherwise.

Well, I suppose that's an enclojure bug, unless you mean you get the
same thing w/o enclojure too.

-- 
Michael Wood 

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


Re: Datatypes and Protocols - early experience program

2009-11-16 Thread John Harrop
On Mon, Nov 16, 2009 at 2:16 AM, Michael Wood  wrote:

> This is what I get with or without rlwrap from the command line.  No
> IDE or anything like that:
>
> Clojure 1.1.0-alpha-SNAPSHOT
> user=> ; some comment
> user=> #! something
> (println "blah")
> blah
> nil
> user=>
>
> i.e. the same as David.


Well, that's odd. I get a hang no matter what. I can enter as many lines of
random crap as I like and never get back a user=> prompt. Sometimes I also
can't enter blank lines -- enter does nothing at start of line, and starts a
new line (w/o prompt) otherwise.

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

Re: Datatypes and Protocols - early experience program

2009-11-15 Thread Michael Wood
2009/11/16 John Harrop :
> On Sun, Nov 15, 2009 at 8:17 PM, David Brown  wrote:
>>
>> On Sun, Nov 15, 2009 at 04:20:19PM -0500, John Harrop wrote:
>>
>> >That's weird. It's not documented anywhere on the site. And it seems to
>> > hang
>> >the REPL:
>> >
>> >user=> nil #!foo
>> >
>> >and nothing. Enter doesn't print "nil" and a fresh user=> prompt as it
>> >should and nothing else apparently works either. The REPL is either
>> > wedged
>> >or interpreting everything as comment from then on.
>> >
>> >Weirdly enough, ; hangs the REPL likewise.
>>
>> How's the data getting to the REPL?  jline, or ide?
>
> Enclojure IDE.

This is what I get with or without rlwrap from the command line.  No
IDE or anything like that:

Clojure 1.1.0-alpha-SNAPSHOT
user=> ; some comment
user=> #! something
(println "blah")
blah
nil
user=>

i.e. the same as David.

-- 
Michael Wood 

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


Re: Datatypes and Protocols - early experience program

2009-11-15 Thread John Harrop
On Sun, Nov 15, 2009 at 8:17 PM, David Brown  wrote:

> On Sun, Nov 15, 2009 at 04:20:19PM -0500, John Harrop wrote:
>
> >That's weird. It's not documented anywhere on the site. And it seems to
> hang
> >the REPL:
> >
> >user=> nil #!foo
> >
> >and nothing. Enter doesn't print "nil" and a fresh user=> prompt as it
> >should and nothing else apparently works either. The REPL is either wedged
> >or interpreting everything as comment from then on.
> >
> >Weirdly enough, ; hangs the REPL likewise.
>
> How's the data getting to the REPL?  jline, or ide?


Enclojure IDE.

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

Re: Datatypes and Protocols - early experience program

2009-11-15 Thread David Brown
On Sun, Nov 15, 2009 at 04:20:19PM -0500, John Harrop wrote:

>That's weird. It's not documented anywhere on the site. And it seems to hang
>the REPL:
>
>user=> nil #!foo
>
>and nothing. Enter doesn't print "nil" and a fresh user=> prompt as it
>should and nothing else apparently works either. The REPL is either wedged
>or interpreting everything as comment from then on.
>
>Weirdly enough, ; hangs the REPL likewise.

How's the data getting to the REPL?  jline, or ide?  I'm using rlwrap
at the console, and netierh seems to cause problems.  However, #! eats
everything, and doesn't prompt again, but does after the next line.
The ; prints a new prompt, so they are definitely treated differently.

David

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


Re: Datatypes and Protocols - early experience program

2009-11-15 Thread John Harrop
On Sun, Nov 15, 2009 at 8:45 AM, Michael Wood  wrote:

> 2009/11/14 John Harrop :
> > On Sat, Nov 14, 2009 at 1:42 PM, Richard Newman 
> wrote:
> >>
> >> I like CL's package support for this kind of situation, where
> >> unexported symbols can still be reached via foo::bar, at the cost of
> >> an obvious "code smell".
> >
> > This suggests an alternate fix for the private functions in macros
> problem:
> > 1. Keep the throw when dereferencing another ns's private vars.
> > 2. Add a way to override that throw when dereferencing -- a
> >"deref-private" that always works.
> > 3. Add a reader macro, say #!, with the property that #!foo expands
> >to (deref-private #'foo).
>
> Except you'll have to find another reader macro.  #! is already taken.
>  It's a comment-to-end-of-line reader macro to support Unix scripts.


That's weird. It's not documented anywhere on the site. And it seems to hang
the REPL:

user=> nil #!foo

and nothing. Enter doesn't print "nil" and a fresh user=> prompt as it
should and nothing else apparently works either. The REPL is either wedged
or interpreting everything as comment from then on.

Weirdly enough, ; hangs the REPL likewise.

Maybe use @!? That's closer to @ and the ! is still there to suggest
something perilous, as it does with the mutable-state fns.

It would prevent using normal deref-@ with symbols that start with !, but
does anyone actually use symbols that start with ! at this time? Even not=
is not= instead of !=.

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

Re: Datatypes and Protocols - early experience program

2009-11-15 Thread Michael Wood
2009/11/14 John Harrop :
> On Sat, Nov 14, 2009 at 1:42 PM, Richard Newman  wrote:
>>
>> I like CL's package support for this kind of situation, where
>> unexported symbols can still be reached via foo::bar, at the cost of
>> an obvious "code smell".
>
> This suggests an alternate fix for the private functions in macros problem:
> 1. Keep the throw when dereferencing another ns's private vars.
> 2. Add a way to override that throw when dereferencing -- a
>    "deref-private" that always works.
> 3. Add a reader macro, say #!, with the property that #!foo expands
>    to (deref-private #'foo).

Except you'll have to find another reader macro.  #! is already taken.
 It's a comment-to-end-of-line reader macro to support Unix scripts.

A quick search of clojure.org didn't find it, but it's mentioned in
the Clojure Programming wikibook:

http://en.wikibooks.org/wiki/Clojure_Programming/Tutorials_and_Tips#Shebang_Scripting_in_Clojure

-- 
Michael Wood 

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 1:42 PM, Richard Newman  wrote:

> I like CL's package support for this kind of situation, where
> unexported symbols can still be reached via foo::bar, at the cost of
> an obvious "code smell".


This suggests an alternate fix for the private functions in macros problem:

1. Keep the throw when dereferencing another ns's private vars.
2. Add a way to override that throw when dereferencing -- a
   "deref-private" that always works.
3. Add a reader macro, say #!, with the property that #!foo expands
   to (deref-private #'foo).
4. Macros can use #!priv-fn in their expansions to produce an
   expansion that calls a private function without issues.
5. #! outside of this circumstance would be a code smell.
6. Optionally, syntax-quote, when resolving symbols into fully
   qualified ones, might auto-#! all that reference private vars IN
   THE CURRENT NAMESPACE. Then no explicit #! is needed on the
   hypothetical priv-fn in the macro: `(priv-fn foo ~bar) instead of
   `(#!priv-fn foo ~bar). At the same time, referencing a *foreign*
   private function in a macro still needs the #!.Then #! is ALWAYS a
   smell.

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

Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Richard Newman
> I don't really care how strictly the language *enforces* that
> separation, but I think the ability to specify that separation is a
> good thing.

I'd go so far as to request that it does not enforce separation. I'm  
sure anyone who's spent enough time using Other People's Libraries has  
hit instances where the only way to get things to work is to use the  
(lower-level, undocumented) API because the high-level API doesn't  
allow you to pass some crucial parameter, or where you need to reuse  
some internal function or spend the time to rewrite it yourself.

In an ideal world (read: fantasy land) you can just fix the library  
and send a push request on GitHub, but we rarely live in that place.

Similarly, I'm sure lots of people have had tons of 'fun' with final  
classes, private and protected members, and so on in Java... "if I  
could just call that method...". I recall several experiences where if  
I could have called a protected method I could have worked around a  
bug in an application server. Instead, I had to patch their runtime  
libraries, and wait a few weeks for the change to roll upstream.

> As a longtime Python programmer, I guess that's the level of privacy  
> I like.

As a Common Lisper and Python programmer, I'm quite fond of this  
too... "there but hidden".

I like CL's package support for this kind of situation, where  
unexported symbols can still be reached via foo::bar, at the cost of  
an obvious "code smell".

To *really* enforce hiding, you can actually unintern symbols,  
rendering the things they named unreachable. Unusual, but possible.

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Rich Hickey


On Nov 14, 8:28 am, Jonas Enlund  wrote:
> Hi there!
>
> I have built a simple Matrix datatype with defprotocol and deftype.
> You can take a look at it athttp://gist.github.com/234535
> (constructive criticism welcome!). Some simple examples are provided
> at the end of the file.
>
> I have a few questions.
>
> - Why must i write (matrix/Matrix ...) instead of (Matrix ...) inside
> the deftype body? Is this a bug? I didn't have to write it that way in
> earlier versions of the new-branch.

Inside the method bodies, the type name (Matrix) now designates the
class, so you can use it to call the ctor instead of the factory fn:

;change all (Matrix a b c) to (Matrix. a b c)

(Matrix. 1 (count v) (into [] v))


> - Am I supposed to have all the interface implementations inside the
> deftype body?

Yes.

> I didn't figure out how to move the implementation of
> the clojure.lang.* interfaces to (extends ...).
>

Interface methods have nothing to do with protocol fns. They go in
separate places.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Rich Hickey


On Nov 14, 1:32 am, cody koeninger  wrote:
> On Nov 13, 9:42 am, Sean Devlin  wrote:
>
> > In this case, you provide the docs for each method after parameters.
> > Would the following be possible:
>
> > (defprotocol AProtocol :on AnInterface
> >   "A doc string for AProtocol abstraction"
> >   (bar "bar docs" [a b] :on barMethod)
> >   (baz "baz docs" ([a] [a b] [a b & c])))
>
> > This matches the rhythm of the rest of the language.
>
> > Sean
>
> +1 for docstring position that matches the rest of the language.  I
> actually think this is a big deal.
>
> Other issue regarding docstrings:
>
> user=> (doc AProtocol)
> -
> user/AProtocol
> nil
>   protocol doc
> nil
> user=> (doc bar)
> -
> user/bar
> ([a b])
>   bar doc
> nil
>
> doc gives no indication of any relationship between bar and AProtocol,
> other than the shared namespace.  

Making the doc refer to the protocol is on the todo list.

> Is the idea to use a convention of
> max 1 protocol per namespace?

No. But all functions of protocols in the same ns live in the ns, so
you must have unique function names across protocols on the same ns.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Konrad Hinsen
On 14 Nov 2009, at 09:45, Mark Engelberg wrote:

> In general, I really hate it when it's difficult to tell what parts of
> an API are the things that the end-user is really supposed to call,
> and what part of the data you're supposed to access directly versus an
> accessor method.  It bugs me when I call (:real complex) to extract

I agree. The distinction should be clear, even though not enforced by  
the language.

A privacy indication that would fit well with the rest of Clojure is  
to tag the field name in the deftype with the "private" metadata  
field. The question is just how to make this information accessible to  
IDEs and documentation tools. In fact, the first question is how an  
IDE can get any information about the fields of a type. There doesn't  
seem to be a documented way to do it. One source would be the doc  
string of the constructor function.

Konrad.

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Jonas Enlund
Hi there!

I have built a simple Matrix datatype with defprotocol and deftype.
You can take a look at it at http://gist.github.com/234535
(constructive criticism welcome!). Some simple examples are provided
at the end of the file.

I have a few questions.

- Why must i write (matrix/Matrix ...) instead of (Matrix ...) inside
the deftype body? Is this a bug? I didn't have to write it that way in
earlier versions of the new-branch.
- Am I supposed to have all the interface implementations inside the
deftype body? I didn't figure out how to move the implementation of
the clojure.lang.* interfaces to (extends ...).

/Jonas

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Konrad Hinsen
On 14 Nov 2009, at 02:50, Mark Engelberg wrote:

> together.  So would it make sense for multimethods to be included as
> part of protocols, or should there be some similar grouping system for
> multimethods?

The "old ideas/scratchpad" section of

http://www.assembla.com/wiki/show/clojure/Protocols

mentions multiprotocols, which are about what you describe.

> basically gives you partial implementation.  But it seems to me that a
> lot of times, several interface functions will share some sort of
> local state, using closures.


The shared state would normally be stored in the object that the  
dispatching acts on.

> If I'm visualizing this correctly, these sorts of partial  
> implementations couldn't possibly be mixed-in,
> because there would be no way to share that state.

They could still all reference a common var, just like any set of  
functions can. But...

> Off the top of my head, I don't yet have a concrete example of this  
> -- has anyone
> encountered this yet in their experiments with protocols?

... me neither, so it seems premature to discuss the details.

Konrad.

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Konrad Hinsen
On 13 Nov 2009, at 23:03, Stuart Sierra wrote:

>> This example has maybe a problem : doesn't the symmetry of these
>> Arithmetic operators seems to be crying for type multiple dispatch in
>> this particular case ? :-)
>
> Yes, in the general case, arithmetic requires multimethods.  But
> multimethods -- or any dynamic type dispatch -- are too slow for math-
> heavy code anyway.

That depends on how it is used and on what types.  
clojure.contrib.complex has a multimethod-based implementation which  
moreover does a multimethod dispatch on the real/imaginary parts,  
making it possible to use any numeric type, built-in or not, inside  
the complex type. That's about as inefficient as it can get, but also  
very flexible. You can do symbolic computing with that kind of  
framework, and then the overhead is tolerable, but for number  
crunching it is not.

I think arithmetic is a bad "first example" for just about any  
implementation technique. Doing it well is very hard, and as far as I  
know no one has yet come up with any technique that is fully  
satisfying for all applications.

Konrad.

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


Re: Datatypes and Protocols - early experience program

2009-11-14 Thread John Harrop
On Sat, Nov 14, 2009 at 3:45 AM, Mark Engelberg wrote:

> On Fri, Nov 13, 2009 at 12:58 AM, Konrad Hinsen
>  wrote:
> > Coming from a Python background, I don't think access restrictions are
> > necessary. However, flagging fields as "not meant for use by
> > outsiders" could be of interest for documentation tools, to make it
> > clear what client code can safely rely on.
>
> Even Python has the ability to mangle names so that they are
> effectively private.  They aren't truly hidden, but there's no way
> you'll misunderstand and call a private thing by accident.
>
> As a longtime Python programmer, I guess that's the level of privacy I
> like.
>
> In general, I really hate it when it's difficult to tell what parts of
> an API are the things that the end-user is really supposed to call,
> and what part of the data you're supposed to access directly versus an
> accessor method.  It bugs me when I call (:real complex) to extract
> the real part out of a complex number, only to discover later that I
> was supposed to call (get-real complex) because the accessor is the
> only "safe way" to get the value I want.
>
> I think anything in datatypes or protocols that help library designers
> separate the data that's safe to access directly from the data that's
> not, or the functions that are safe to call versus those that are not
> -- I think that's a good thing.
>
> I don't really care how strictly the language *enforces* that
> separation, but I think the ability to specify that separation is a
> good thing.


+1 for ability to specify, especially if it's recognized by tools such as
IDEs and they filter private stuff from other namespaces from what they use
as possible completions, etc.

Particularly, I'm in favor of removing the exception throw when a private
var is dereferenced from outside its namespace, particularly as it will
solve the macro-expansion-uses-private-implementation-function issue (making
the expansion generate the function as a local function or anonymous
function seems messy to me when the function's own content does not depend
on the macro arguments). Let :private true in a var's metadata influence
tools like IDEs and documentation generators, so they don't show as part of
the API, and let IDEs give warnings if they see a symbol that resolves to an
external private var in your code (though not in the expansions of
non-private macros you call). That should suffice to prevent accidental
self-inflicted gunshot wounds to the foot, while preserving maximum
flexibility.

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

Re: Datatypes and Protocols - early experience program

2009-11-14 Thread Mark Engelberg
On Fri, Nov 13, 2009 at 12:58 AM, Konrad Hinsen
 wrote:
> Coming from a Python background, I don't think access restrictions are
> necessary. However, flagging fields as "not meant for use by
> outsiders" could be of interest for documentation tools, to make it
> clear what client code can safely rely on.

Even Python has the ability to mangle names so that they are
effectively private.  They aren't truly hidden, but there's no way
you'll misunderstand and call a private thing by accident.

As a longtime Python programmer, I guess that's the level of privacy I like.

In general, I really hate it when it's difficult to tell what parts of
an API are the things that the end-user is really supposed to call,
and what part of the data you're supposed to access directly versus an
accessor method.  It bugs me when I call (:real complex) to extract
the real part out of a complex number, only to discover later that I
was supposed to call (get-real complex) because the accessor is the
only "safe way" to get the value I want.

I think anything in datatypes or protocols that help library designers
separate the data that's safe to access directly from the data that's
not, or the functions that are safe to call versus those that are not
-- I think that's a good thing.

I don't really care how strictly the language *enforces* that
separation, but I think the ability to specify that separation is a
good thing.

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread cody koeninger

On Nov 13, 9:42 am, Sean Devlin  wrote:
> In this case, you provide the docs for each method after parameters.
> Would the following be possible:
>
> (defprotocol AProtocol :on AnInterface
>   "A doc string for AProtocol abstraction"
>   (bar "bar docs" [a b] :on barMethod)
>   (baz "baz docs" ([a] [a b] [a b & c])))
>
> This matches the rhythm of the rest of the language.
>
> Sean


+1 for docstring position that matches the rest of the language.  I
actually think this is a big deal.

Other issue regarding docstrings:

user=> (doc AProtocol)
-
user/AProtocol
nil
  protocol doc
nil
user=> (doc bar)
-
user/bar
([a b])
  bar doc
nil


doc gives no indication of any relationship between bar and AProtocol,
other than the shared namespace.  Is the idea to use a convention of
max 1 protocol per namespace?

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread John Harrop
On Fri, Nov 13, 2009 at 8:50 PM, Mark Engelberg wrote:

> Rich, thanks for the extended explanation of the overlap between the
> old and new constructs; I found this explanation much clearer than
> what is currently on the wiki.  Basically, the key for me was
> realizing that these new constructs are all you're likely to need as
> long as you are just programming "in Clojure" and not worrying about
> Java interop.
>
> A related question I have is to better understand the
> overlap/relationship between multimethods and the new protocols.  At
> first glance, they seem fairly orthogonal.  If you have something that
> dispatches only on type, or corresponds to a Java interface, use a
> protocol, otherwise use multimethods.  However, I notice that one
> thing protocols give you is the ability to batch function requirements
> and say, "these functions need to be implemented together".  It seems
> to me like there is just as much value to being able to include
> multimethods as part of such a requirement of things to implement
> together.  So would it make sense for multimethods to be included as
> part of protocols, or should there be some similar grouping system for
> multimethods?


Since a multimethod maybe used where any Clojure function may be used, and a
Clojure function may be used to implement a protocol, can't multimethods be
used to implement (part or all of) a protocol?

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

Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Mark Engelberg
Rich, thanks for the extended explanation of the overlap between the
old and new constructs; I found this explanation much clearer than
what is currently on the wiki.  Basically, the key for me was
realizing that these new constructs are all you're likely to need as
long as you are just programming "in Clojure" and not worrying about
Java interop.

A related question I have is to better understand the
overlap/relationship between multimethods and the new protocols.  At
first glance, they seem fairly orthogonal.  If you have something that
dispatches only on type, or corresponds to a Java interface, use a
protocol, otherwise use multimethods.  However, I notice that one
thing protocols give you is the ability to batch function requirements
and say, "these functions need to be implemented together".  It seems
to me like there is just as much value to being able to include
multimethods as part of such a requirement of things to implement
together.  So would it make sense for multimethods to be included as
part of protocols, or should there be some similar grouping system for
multimethods?

Regarding partial implementation, Rich and a couple others have
suggested that the ability to merge together maps of implementations
basically gives you partial implementation.  But it seems to me that a
lot of times, several interface functions will share some sort of
local state, using closures.  If I'm visualizing this correctly, these
sorts of partial implementations couldn't possibly be mixed-in,
because there would be no way to share that state.  Off the top of my
head, I don't yet have a concrete example of this -- has anyone
encountered this yet in their experiments with protocols?

--Mark

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Stuart Sierra
On Nov 13, 3:42 pm, Laurent PETIT  wrote:
> > Very simple example here:http://paste.lisp.org/display/90329
>
> Why not have used add/sub/... instead of +/-/... in the extension of
> Arithmetic for ::Complex ? :-p

Just a little simpler, that's all.

> This example has maybe a problem : doesn't the symmetry of these
> Arithmetic operators seems to be crying for type multiple dispatch in
> this particular case ? :-)

Yes, in the general case, arithmetic requires multimethods.  But
multimethods -- or any dynamic type dispatch -- are too slow for math-
heavy code anyway.  So, for that reason, it's not a great example.
But it was the first thing I thought of.

-SS

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Stuart Halloway
Initial gut reaction: would like a shortcut syntax for opting in(or  
out), as this will be a very common use case. Suspect that most  
classes would rather have it than not, but that may be the Ruby  
programmer in me.

Stu

> On Nov 13, 1:01 pm, Constantine Vetoshev  wrote:
>> On Nov 12, 7:10 am, Rich Hickey  wrote:
>>
>>> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
>>
>> Could you please elaborate on why you chose to make IPersistentMap an
>> optional interface for deftype'd types, rather than making it
>> automatic?
>>
>
> Because we want to be able to use deftype to implement
> PersistentHashMap and datatypes like it.
>
>> I'm asking because I found the automatic defstruct-map equivalence
>> convenient in writing the Cupboard database library (http://github.com/
>> gcv/cupboard). It guaranteed that any reading Clojure code could read
>> back any map or any struct written by any other Clojure program
>> (unless the map contains closures, of course), without any other
>> knowledge of the writing program. It allows for data-centric designs
>> when thinking about storing objects to a database, i.e., the data can
>> be used without the type definitions which originally produced it.
>>
>> I can, of course, require that any deftype'd types saved in Cupboard
>> databases implement IPersistentMap, but I'm curious about the
>> reasoning for not making maps part of the default nature of deftype.
>> Making IPersistentMap the default could also make deftype a nearly
>> drop-in replacement for defstruct.
>>
>
> Making it default, and having some way to opt out, is another
> possibility. This is still an open question, as well as how to make
> these default implementations more extensible.
>
> Rich
>
> -- 
> 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 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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 1:01 pm, Constantine Vetoshev  wrote:
> On Nov 12, 7:10 am, Rich Hickey  wrote:
>
> > [1]http://www.assembla.com/wiki/show/clojure/Datatypes
>
> Could you please elaborate on why you chose to make IPersistentMap an
> optional interface for deftype'd types, rather than making it
> automatic?
>

Because we want to be able to use deftype to implement
PersistentHashMap and datatypes like it.

> I'm asking because I found the automatic defstruct-map equivalence
> convenient in writing the Cupboard database library (http://github.com/
> gcv/cupboard). It guaranteed that any reading Clojure code could read
> back any map or any struct written by any other Clojure program
> (unless the map contains closures, of course), without any other
> knowledge of the writing program. It allows for data-centric designs
> when thinking about storing objects to a database, i.e., the data can
> be used without the type definitions which originally produced it.
>
> I can, of course, require that any deftype'd types saved in Cupboard
> databases implement IPersistentMap, but I'm curious about the
> reasoning for not making maps part of the default nature of deftype.
> Making IPersistentMap the default could also make deftype a nearly
> drop-in replacement for defstruct.
>

Making it default, and having some way to opt out, is another
possibility. This is still an open question, as well as how to make
these default implementations more extensible.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Laurent PETIT
Hi,

2009/11/13 Stuart Sierra :
> On Nov 12, 7:10 am, Rich Hickey  wrote:
>> An early version of the code for a few important new language
>> features, datatypes[1] and protocols[2]
>
> Very simple example here: http://paste.lisp.org/display/90329
>
> This shows how to do arithmetic with complex numbers using deftype and
> defprotocol.  It does not support mixing complex and real numbers; not
> sure how that would work.

Why not have used add/sub/... instead of +/-/... in the extension of
Arithmetic for ::Complex ? :-p

This example has maybe a problem : doesn't the symmetry of these
Arithmetic operators seems to be crying for type multiple dispatch in
this particular case ? :-)

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Stuart Sierra
On Nov 12, 7:10 am, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2]

Very simple example here: http://paste.lisp.org/display/90329

This shows how to do arithmetic with complex numbers using deftype and
defprotocol.  It does not support mixing complex and real numbers; not
sure how that would work.

-SS

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread AlexK


On 13 Nov., 17:07, Rich Hickey  wrote:
> This kind of do-nothing microbenchmarking demonstrates nothing.
> Protocol dispatching is significantly faster than multimethod
> dispatching, and I haven't even looked into call-site optimization.
> Protocol dispatch is not as fast as interface dispatch, and may or may
> not become so with call-site caching. But, protocols :on interfaces
> are precisely as fast when called with instances of the :on interface
> as calls to the :on interface.

Forget what I said about Performance, I didn't realize that the
functions could be mapped to interface-methods. When mapped to an
interface they get JITed to awesome speeds :-)

> I wouldn't want to key anything off of fn identity. It would make
> mixins quite difficult.

This was just a minor thought of mine, if it impedes with this awesome
literal mixin concept then I gladly take those mixins.

(def composed-mixin (merge mixin-a mixin-b mixin-c))
seems absolutely logical and natural

>
> ...
>
> Admittedly, it is a difference from multimethods. With protocols, both
> protocols and their functions/methods are immutable. Redefining or
> extending a protocol modifies only the protocol and fn vars. I prefer
> that, and don't consider the above behavior a problem. What do others
> think?
>
> Rich

that was a bad Example probably...
hypothetical example for impementing the type function as a
Protocolfn:


(defprotocol Typed (my-type [obj] "Doc.."))
Typed
(extend Object Typed {:my-type (fn [obj] (.getClass obj))})
nil
(defmulti foo my-type)
#'user/foo
(extend clojure.lang.IObj Typed {:my-type (fn [obj] (if (:type ^obj)
(:type ^obj) (.getClass obj)))})

now our foo multifn woudn't work as expected (by me at least).
I just didn't expect that (extend   ) would
redefine some Vars.
extend has to mutate something, but I think that redefining some Vars
is wierder (and thus should be explicit via a visible (def ...))
 than mutating the "generic function" (I may be biased by CLOS of
course)

Alex


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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Sean Devlin
I agree w/ Constantine.  This would be very, very useful.

Sean

On Nov 13, 1:01 pm, Constantine Vetoshev  wrote:
> On Nov 12, 7:10 am, Rich Hickey  wrote:
>
> > [1]http://www.assembla.com/wiki/show/clojure/Datatypes
>
> Could you please elaborate on why you chose to make IPersistentMap an
> optional interface for deftype'd types, rather than making it
> automatic?
>
> I'm asking because I found the automatic defstruct-map equivalence
> convenient in writing the Cupboard database library (http://github.com/
> gcv/cupboard). It guaranteed that any reading Clojure code could read
> back any map or any struct written by any other Clojure program
> (unless the map contains closures, of course), without any other
> knowledge of the writing program. It allows for data-centric designs
> when thinking about storing objects to a database, i.e., the data can
> be used without the type definitions which originally produced it.
>
> I can, of course, require that any deftype'd types saved in Cupboard
> databases implement IPersistentMap, but I'm curious about the
> reasoning for not making maps part of the default nature of deftype.
> Making IPersistentMap the default could also make deftype a nearly
> drop-in replacement for defstruct.
>
> Thanks,
> Constantine Vetoshev

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Konrad Hinsen
On 13.11.2009, at 17:11, Rich Hickey wrote:

> On Nov 13, 10:42 am, Sean Devlin  wrote:
>> Would the following be possible:
>>
>> (defprotocol AProtocol :on AnInterface
>>   "A doc string for AProtocol abstraction"
>>   (bar "bar docs" [a b] :on barMethod)
>>   (baz "baz docs" ([a] [a b] [a b & c])))
>>
>> This matches the rhythm of the rest of the language.
>
> It does. I'm still on the fence about it. What do others think?

I'd prefer the doc string right after the function name, as in other  
situations, but it's not important enough that I'd argue for it at any  
length.

Konrad.

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Constantine Vetoshev
On Nov 12, 7:10 am, Rich Hickey  wrote:
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes

Could you please elaborate on why you chose to make IPersistentMap an
optional interface for deftype'd types, rather than making it
automatic?

I'm asking because I found the automatic defstruct-map equivalence
convenient in writing the Cupboard database library (http://github.com/
gcv/cupboard). It guaranteed that any reading Clojure code could read
back any map or any struct written by any other Clojure program
(unless the map contains closures, of course), without any other
knowledge of the writing program. It allows for data-centric designs
when thinking about storing objects to a database, i.e., the data can
be used without the type definitions which originally produced it.

I can, of course, require that any deftype'd types saved in Cupboard
databases implement IPersistentMap, but I'm curious about the
reasoning for not making maps part of the default nature of deftype.
Making IPersistentMap the default could also make deftype a nearly
drop-in replacement for defstruct.

Thanks,
Constantine Vetoshev

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Konrad Hinsen
On 13.11.2009, at 17:07, Rich Hickey wrote:

> Admittedly, it is a difference from multimethods. With protocols, both
> protocols and their functions/methods are immutable. Redefining or
> extending a protocol modifies only the protocol and fn vars. I prefer
> that, and don't consider the above behavior a problem. What do others
> think?

For most applications the difference doesn't matter. Having protocols  
as immutable values bound to vars that change with every extend could  
lead to both interesting use cases and undesirable surprises when used  
with threads. Threads can have thread-local implementations of  
protocols, intentionally or by mistake.

What makes this behaviour a bit disturbing is the fact that a var in a  
namespace that refers to a protocol or a method is changed from code  
in another namespace. This is of course possible otherwise as well,  
but highly unusual. Consider this example:

(defprotocol Foo
   (bar [x]))

(def bar nil)

Now in some other namespace, at some later time:

(extend Object
   Foo
   {:bar (fn [x] x)})

This will redefine bar in the first namespace to a method of Foo.  
While I don't expect such a situation to be frequent, it is certainly  
highly unexpected. All the more so since the code in the second  
namespace doesn't even mention the symbol bar that it changes.

Konrad.

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 9:24 am, James Reeves  wrote:
> Are there any plans to use protocols to define polymorphic functions
> like conj and get? Perhaps with an "untype" function to remove type
> metadata so one could always get at the datastructures hidden by the
> protocol. e.g.
>
> (defn sql-get [table key]
>   (sql-query
>     (str "select * from " table " where " (get (untype table) :primary-
> key) " = ?")
>     key))
>
> (extend ::sql-table Gettable
>   {:get sql-get})
>
> Then 'get' could be used in a more generic fashion:
>
> user=> (def accounts (sql-table accounts))
>
> user=> (get accounts 10)
> {:id 10, :login "jsmith", :password "1234"}
>

I'll have to think about that. Your 'untype' above is really just a
specialization of type aliasing:

(as-type nil table)

where (as-type ::Foo x) would create a view of x with dynamic type
Foo.

I'm still thinking about such aliasing and its implications.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread David Nolen
Is there an argument for putting it after the argument list? :)

On Fri, Nov 13, 2009 at 11:11 AM, Rich Hickey  wrote:

>
>
> On Nov 13, 10:42 am, Sean Devlin  wrote:
> > Rich,
> > I was wondering something about defprotocol.
> >
> > Here's your example:
> >
> > (defprotocol AProtocol :on AnInterface
> >   "A doc string for AProtocol abstraction"
> >   (bar [a b] "bar docs" :on barMethod)
> >   (baz ([a] [a b] [a b & c]) "baz docs"))
> >
> > In this case, you provide the docs for each method after parameters.
> > Would the following be possible:
> >
> > (defprotocol AProtocol :on AnInterface
> >   "A doc string for AProtocol abstraction"
> >   (bar "bar docs" [a b] :on barMethod)
> >   (baz "baz docs" ([a] [a b] [a b & c])))
> >
> > This matches the rhythm of the rest of the language.
> >
>
> It does. I'm still on the fence about it. What do others think?
>
> Rich
>
> --
> 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 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

Re: Datatypes and Protocols - early experience program

2009-11-13 Thread David Nolen
I place my vote for no data hiding.

On Fri, Nov 13, 2009 at 10:48 AM, Stuart Halloway  wrote:

> >>  But do
> >> people feel that some degree of data hiding is worthwhile?
> >
> > I don't.
>
>
> Hooray for benevolent dictators!
>
> --
> 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 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

Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 10:48 am, Stuart Halloway 
wrote:
> >>  But do
> >> people feel that some degree of data hiding is worthwhile?
>
> > I don't.
>
> Hooray for benevolent dictators!

I was just putting in my vote :)

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 9:26 am, AlexK  wrote:
> Hi everybody,
>
> after playing around with protocols & datatypes, I found them very fun
> to use.
> Some questions:
> Performance
> I don't see (with my limited benchmarking) any significant difference
> between multifns and protocolfns:
>
...
> This is what I have been expecting of course (Fn < Protocolfn <
> Multifn), but i was thinking that with Protocols dispatching would be
> significantly faster than with Multimethods. Am I missing something?
> Because they don't seem to provide the speed for implementing the core
> abstractions (like (seq )).
>

This kind of do-nothing microbenchmarking demonstrates nothing.
Protocol dispatching is significantly faster than multimethod
dispatching, and I haven't even looked into call-site optimization.
Protocol dispatch is not as fast as interface dispatch, and may or may
not become so with call-site caching. But, protocols :on interfaces
are precisely as fast when called with instances of the :on interface
as calls to the :on interface.

> Syntax
> With protocols you define the protocols using symbols and extend types
> by using the keywordized name
> eg.
>
> (defprotocol Test (protocol-fn [it] "Protocol-fn"))
> (extend Object Test {:protocol-fn (fn [it] nil)})
>
> i understand that extend is a function and evaluates its arguments,
> and that {:protocol-fn (fn [it] nil)} is a real map, but wouldn't it
> be possible just to use a { } map instead?
> The protocol should know its generic functions, so that wouldn't be
> ambiguous.
> {protocol-fn (fn [it] nil)}) ; seems a lot clearer to me

I wouldn't want to key anything off of fn identity. It would make
mixins quite difficult.

>
> Extensibility
> I've noticed that extending a protocol-fn redefines it:
>
> (def old-fn protocol-fn) ; from above
> (extend Number Test {:protocol-fn (fn [it] :a-number)})
> (def new-fn protocol-fn)
>
> (= old-fn new-fn)
> false
>
> this worries me, because the semantics are differing from MultiFns and
> are less dynamic.

They are no less dynamic, they just work differently.

> Especially coupled with dynamic development this
> could lead to some gotchas.
>
> Clojure 1.1.0-alpha-SNAPSHOT
> user=> (defprotocol Test (prtcfn [it]))
> Test
> user=> (extend Object Test {:prtcfn (fn [it] :object)})
> nil
> user=> (prtcfn (Object.))
> :object
> user=> (def old-fn prtcfn)
> #'user/old-fn
> user=> (old-fn (Object.))
> :object
> user=> (extend Number Test {:prtcfn (fn [it] :number)})
> nil
> user=> (prtcfn (Object.))
> :object
> user=> (prtcfn 1)
> :number
> user=> (def new-fn prtcfn)
> #'user/new-fn
> user=> (new-fn 1)
> :number
> user=> (old-fn 1)
> :object
>

This is no different from ordinary functions:

#'user/foo
user=> (def old-foo foo)
#'user/old-foo
user=> (def foov #'foo)
#'user/foov
user=> (old-foo)
:old-foo
user=> (foov)
:old-foo
user=> (defn foo [] :new-foo)
#'user/foo
user=> (foo)
:new-foo
user=> (old-foo)
:old-foo
user=> (foov)
:new-foo

> When some protocol-fns get bound in a closure this could hurt a lot.
>

That claim is not supported by your example. In general, when making a
long-term relationship with a function, you do so with its var, as
above. A closure referencing a var closes over the var itself, not its
current value:

user=> (def f (future (dotimes [_ 10] (prn (foo)) (Thread/sleep
1000
#'user/f
user=> :new-foo
:new-foo
:new-foo
:new-foo
:new-foo
:new-foo
:new-foo
;;;while that is going
(defn foo [] :newer-foo)
#'user/foo
:newer-foo
:newer-foo
:newer-foo

Admittedly, it is a difference from multimethods. With protocols, both
protocols and their functions/methods are immutable. Redefining or
extending a protocol modifies only the protocol and fn vars. I prefer
that, and don't consider the above behavior a problem. What do others
think?

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 10:42 am, Sean Devlin  wrote:
> Rich,
> I was wondering something about defprotocol.
>
> Here's your example:
>
> (defprotocol AProtocol :on AnInterface
>   "A doc string for AProtocol abstraction"
>   (bar [a b] "bar docs" :on barMethod)
>   (baz ([a] [a b] [a b & c]) "baz docs"))
>
> In this case, you provide the docs for each method after parameters.
> Would the following be possible:
>
> (defprotocol AProtocol :on AnInterface
>   "A doc string for AProtocol abstraction"
>   (bar "bar docs" [a b] :on barMethod)
>   (baz "baz docs" ([a] [a b] [a b & c])))
>
> This matches the rhythm of the rest of the language.
>

It does. I'm still on the fence about it. What do others think?

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Stuart Halloway
>>  But do
>> people feel that some degree of data hiding is worthwhile?
>
> I don't.


Hooray for benevolent dictators!

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Sean Devlin
Rich,
I was wondering something about defprotocol.

Here's your example:

(defprotocol AProtocol :on AnInterface
  "A doc string for AProtocol abstraction"
  (bar [a b] "bar docs" :on barMethod)
  (baz ([a] [a b] [a b & c]) "baz docs"))

In this case, you provide the docs for each method after parameters.
Would the following be possible:

(defprotocol AProtocol :on AnInterface
  "A doc string for AProtocol abstraction"
  (bar "bar docs" [a b] :on barMethod)
  (baz "baz docs" ([a] [a b] [a b & c])))

This matches the rhythm of the rest of the language.

Sean

On Nov 12, 7:10 am, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich
>
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
> [2]http://www.assembla.com/wiki/show/clojure/Protocols
> [3]http://github.com/richhickey/clojure/tree/new
> [4]http://build.clojure.org/

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 9:03 am, MikeM  wrote:
> > (deftype Foo [a b c])
>
> > (defprotocol P (bar [x] "bar docs"))
>
> > (extend ::Foo P {:bar (fn [afoo] :foo-thing)})
>
> A common error may be to:
>
> (extend Foo P {:bar (fn [afoo] :foo-thing)})
>
> when (extend ::Foo ... is intended. I notice that (extend Foo...
> doesn't throw - should extend check that it is supplied a class,
> intfc, or keyword and throw if something else is supplied?

Yes it could.

> Alternately, could extend be changed to allow (extend Foo ... and do
> the right thing ? ie determine that Foo is the constructor function
> for a type and do the extension for the type Foo.

Dunno yet - there isn't a path from the factory fn value to its name
or deftype.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 4:55 am, Alex Osborne  wrote:
> Mark Engelberg wrote:
> > Protocols:
>
> > I don't understand whether there's any way to provide a partial
> > implementation or default implementation of a given
> > protocol/interface, and I believe this to be an important issue.
>
> > For example, a protocol for < and > that provides a default
> > implementation of > in terms of < and a default implementation of < in
> > terms of >, so that you only need to implement one and you get the
> > other for free.
>
> How about this?
>
> (defprotocol MyComparable
>    (comparinate [x y] "Returns a negative integer if x < y, zero if they
>                    are equal and a positive integer if x > y.")
>    (equal-to [x y]     "True if x is equal to y.")
>    (less-than [x y]    "True if x is smaller than y.")
>    (greater-than [x y] "True if x is greater than y."))
>
> (defn mixin-comparable [type compare-fn]
>    (extend type
>       MyComparable
>       {:comparinate compare-fn
>        :equal-to     (fn [x y] (zero? (comparinate x y)))
>        :less-than    (fn [x y] (neg?  (comparinate x y)))
>        :greater-than (fn [x y] (neg?  (comparinate x y)))}))
>
> (mixin-comparable Integer -)
> (mixin-comparable String #(- (count %1) (count %2)))
>
> (less-than 8 2)        ; => false
> (less-than "x" "") ; => true
>
> > I'm also thinking about the relationship in Clojure's source between
> > ISeq and ASeq.  ASeq provides the partial, default implementation of
> > more in terms of next, for example.  How does this kind of thing look
> > with the new protocol system?
>
> See above.  But another way would just be to define ASeq as a map and
> then merge with it:
>
> (def aseq-impl {:more  (fn [obj] (if-let [s (next obj)] s '() ))
>                  :count (fn [obj] ...)})
>
> (extend MyList
>    ISeq
>    (merge
>      aseq-impl
>      {:next (fn [lst] ...)
>       :count (fn [lst] ...) ; overrides the count from aseq-impl
>       :cons (fn [lst x] ...)}))
>
> Code is data. :-)
>
> I don't know whether doing things this way is a good idea or not, but
> protocols are new: lets experiment and find out what works and what doesn't.

Yes, the latter (mixin maps) is preferred.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 5:27 am, Chris Kent  wrote:
> Mark Engelberg  gmail.com> writes:
>
> > I'm a little worried about the strong overlap between reify/proxy,
> > deftype/defstruct, and defclass/gen-class.  I can just imagine the
> > questions a year from now when people join the Clojure community and
> > want to understand how they differ.  So I think that eventually, there
> > needs to be a very clear "story" as to why you'd choose one over the
> > other.  Or better yet, maybe some of the older constructs can be
> > phased out completely.
>
> What are the plans for the future of proxy?  I assume it won't go away because
> reify's inability to extend an existing class is a show-stopper for some Java
> interop scenarios.  Will the syntax be brought in line with reify so dots will
> be needed in front of method names?  As things stand it's a potential source 
> of
> confusion to have two such similar features with subtly different syntax.
>

Yes. Right now the priority is to get these new features out, without
breaking anyone's code.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 3:58 am, Konrad Hinsen  wrote:
> On 13 Nov 2009, at 08:13, Mark Engelberg wrote:
>

> > Protocols:
>
> > I don't understand whether there's any way to provide a partial
> > implementation or default implementation of a given
> > protocol/interface, and I believe this to be an important issue.
>
> I don't think that partial implementations are possible at the moment,
> but I agree that it would be useful.

Yes, just create mixin maps and use them in your extends.

> A default implementation can be
> provided as an implementation of Object. It's not quite the same as a
> default implementation for a multimethod, as it doesn't apply to types
> identified by a metadata type tag, but in practice it can be good
> enough or even better.
>

That's not true for protocols. Make sure to leave any preconceptions
from multimethods and type tags behind. In particular, protocols do
not, and will not, utilize the isa/hierarchy system. Right now, the
dispatch code routes through (type x), but the intention is to support
through type only classes and deftype types. The use of type metadata
should be deprecated once this in place. At that point, Object does
serve as the default for everything other than nil.

***But*** one should generally avoid using hierarchy for
implementation inheritance! You may encounter it in interop
situations, but otherwise use mixins.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread AlexK
Hi everybody,

after playing around with protocols & datatypes, I found them very fun
to use.
Some questions:
Performance
I don't see (with my limited benchmarking) any significant difference
between multifns and protocolfns:

user=> (defprotocol Test (protocol-fn [it] "Protocol-fn"))
Test
user=> (extend Object Test {:protocol-fn (fn [it] nil)})
nil
user=> (defmulti multi-fn type)
#'user/multi-fn
user=> (defmethod multi-fn Object [it] nil)
#
user=> (defn simple-fn [it] nil)
#'user/simple-fn

user=> (dotimes [_ 10] (time (dotimes [_ 10] (protocol-fn :it
"Elapsed time: 105.532562 msecs"
"Elapsed time: 57.0031 msecs"
"Elapsed time: 33.210602 msecs"
"Elapsed time: 30.47827 msecs"
"Elapsed time: 26.326202 msecs"
"Elapsed time: 27.764654 msecs"
"Elapsed time: 28.381284 msecs"
"Elapsed time: 28.741735 msecs"
"Elapsed time: 28.697525 msecs"
"Elapsed time: 25.894514 msecs"

user=> (dotimes [_ 10] (time (dotimes [_ 10] (multi-fn :it
"Elapsed time: 372.338313 msecs"
"Elapsed time: 73.104641 msecs"
"Elapsed time: 58.832009 msecs"
"Elapsed time: 60.312924 msecs"
"Elapsed time: 58.626328 msecs"
"Elapsed time: 57.005242 msecs"
"Elapsed time: 54.493328 msecs"
"Elapsed time: 56.283221 msecs"
"Elapsed time: 54.575182 msecs"
"Elapsed time: 54.939474 msecs"

user=> (dotimes [_ 10] (time (dotimes [_ 10] (simple-fn :it
"Elapsed time: 28.504607 msecs"
"Elapsed time: 17.564177 msecs"
"Elapsed time: 1.877194 msecs"
"Elapsed time: 2.340661 msecs"
"Elapsed time: 1.581906 msecs"
"Elapsed time: 1.792407 msecs"
"Elapsed time: 1.878591 msecs"
"Elapsed time: 1.919937 msecs"
"Elapsed time: 2.367759 msecs"
"Elapsed time: 1.90555 msecs"

This is what I have been expecting of course (Fn < Protocolfn <
Multifn), but i was thinking that with Protocols dispatching would be
significantly faster than with Multimethods. Am I missing something?
Because they don't seem to provide the speed for implementing the core
abstractions (like (seq )).

Syntax
With protocols you define the protocols using symbols and extend types
by using the keywordized name
eg.

(defprotocol Test (protocol-fn [it] "Protocol-fn"))
(extend Object Test {:protocol-fn (fn [it] nil)})

i understand that extend is a function and evaluates its arguments,
and that {:protocol-fn (fn [it] nil)} is a real map, but wouldn't it
be possible just to use a { } map instead?
The protocol should know its generic functions, so that wouldn't be
ambiguous.
{protocol-fn (fn [it] nil)}) ; seems a lot clearer to me


Extensibility
I've noticed that extending a protocol-fn redefines it:

(def old-fn protocol-fn) ; from above
(extend Number Test {:protocol-fn (fn [it] :a-number)})
(def new-fn protocol-fn)

(= old-fn new-fn)
false

this worries me, because the semantics are differing from MultiFns and
are less dynamic. Especially coupled with dynamic development this
could lead to some gotchas.

Clojure 1.1.0-alpha-SNAPSHOT
user=> (defprotocol Test (prtcfn [it]))
Test
user=> (extend Object Test {:prtcfn (fn [it] :object)})
nil
user=> (prtcfn (Object.))
:object
user=> (def old-fn prtcfn)
#'user/old-fn
user=> (old-fn (Object.))
:object
user=> (extend Number Test {:prtcfn (fn [it] :number)})
nil
user=> (prtcfn (Object.))
:object
user=> (prtcfn 1)
:number
user=> (def new-fn prtcfn)
#'user/new-fn
user=> (new-fn 1)
:number
user=> (old-fn 1)
:object

When some protocol-fns get bound in a closure this could hurt a lot.


Sorry if this seems like nitpicking, but this is just what I noticed
while experimenting

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey


On Nov 13, 2:13 am, Mark Engelberg  wrote:
> I'm still trying to get my head around the new features.  Seeing more
> code examples will definitely help.  In the meantime, here is some
> stream-of-consciousness thoughts and questions.
>
> Datatypes:
>
> I'm a little worried about the strong overlap between reify/proxy,
> deftype/defstruct, and defclass/gen-class.  I can just imagine the
> questions a year from now when people join the Clojure community and
> want to understand how they differ.  So I think that eventually, there
> needs to be a very clear "story" as to why you'd choose one over the
> other.  Or better yet, maybe some of the older constructs can be
> phased out completely.
>

Yes, but there will be a transition period. I certainly tried to
explain the decision points on the wiki.

A big part of the design thinking behind these features went like
this:

Clojure is built on a set of abstractions, and leverages/requires that
the host platform provide some sort of high-performance polymorphism
construct in order to make that viable. That said, Clojure was
bootstrapped on the host language and didn't really provide similar
constructs itself (multimethods are more powerful but slower), leaving
people that wanted to do things similar to what I did, in order to
write Clojure and its data structures, to either write Java or use
Clojure interop to, effectively, write Java in Clojure clothing.

So I took a step back and said, what part of Java did I *need* in
order to implement Clojure and its data structures, what could I do
without, and what semantics was I willing to support - for Clojure -
i.e. not in terms of interop. What I ended up with was - a high-
performance way to define and implement interfaces. What I explicitly
left out was - concrete derivation and implementation inheritance.

reify is Clojure semantics and proxy is Java/host semantics. Why
doesn't it replace proxy? Because proxy can derive from concrete
classes with constructors that take arguments. Supporting that
actually brings in a ton of semantics from Java, things I don't want
in Clojure's semantics. reify should be possible and portable in any
port of Clojure, proxy may not.  Will the performance improvements of
reify make it into proxy? Probably at some point, not a priority now.

*** Prefer reify to proxy unless some interop API forces you to use
proxy. You shouldn't be creating things in Clojure that would require
you to use proxy. ***

defstruct is likely to be completely replaced by deftype, and at some
point could be deprecated/removed.

*** Prefer deftype to defstruct, unconditionally. ***

AOT deftype vs gen-class touches on the same Clojure semantics vs Java/
host semantics, with the objectives from before - support implementing
interfaces but not concrete derivation. So, no concrete base classes,
no super calls, self-ctor calls, statics, methods not implementing
interface methods etc. Will the performance improvements of deftype
make it into gen-class? Probably at some point, not a priority now.

Like proxy, gen-class will remain as an interop feature.

*** Prefer deftype to gen-class unless some interop API forces you to
use gen-class. ***

There will be a definterface similar to and probably replacing gen-
interface, with an API to match deftype.

So, with definterface, deftype, and reify you have a very clean way to
specify and implement a subset of the Java/C# polymorphism model, that
subset which I find clean and reasonable, with an expectation of
portability, and performance exactly equivalent to the same features
on the host.

I could have stopped there, and almost did. But there are three
aspects of that polymorphism model that aren't sufficient for Clojure:

 - It is insufficiently dynamic. There is a static component - named
interfaces, that must be AOT compiled.

 - Client code must use the interop style (.method x), and type hints,
in order to tap into the performance

 - It is 'closed' polymorphism, i.e. the set of things a type can do
is fixed at the definition time of the type. This results in the
'expression problem', in this case the inability to extend types with
new capabilities/functions.

We've all experienced the expression problem - sometimes you simply
can't request/require that some type implement YourInterface in order
to play nicely with your design. You can see this in Clojure's
implementation as well - RT.count/seq/get etc all try to use Clojure's
abstraction interface first, but then have hand-written clauses for
types (e.g. String) that couldn't be retrofitted with the interface.

Multimethods, OTOH, don't suffer from this problem. But it is
difficult to get something as generic as Clojure's multimethods to
compete with interface dispatch in Java. Also, multimethods are kind
of atomic, often you need a set of them to completely specify an
abstraction. Finally, multimethods are a good story for the Clojure
side of an abstraction, but should you define a valuable abstraction
and useful cod

Re: Datatypes and Protocols - early experience program

2009-11-13 Thread James Reeves
Are there any plans to use protocols to define polymorphic functions
like conj and get? Perhaps with an "untype" function to remove type
metadata so one could always get at the datastructures hidden by the
protocol. e.g.

(defn sql-get [table key]
  (sql-query
(str "select * from " table " where " (get (untype table) :primary-
key) " = ?")
key))

(extend ::sql-table Gettable
  {:get sql-get})

Then 'get' could be used in a more generic fashion:

user=> (def accounts (sql-table accounts))

user=> (get accounts 10)
{:id 10, :login "jsmith", :password "1234"}

- James

On Nov 12, 12:10 pm, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich
>
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
> [2]http://www.assembla.com/wiki/show/clojure/Protocols
> [3]http://github.com/richhickey/clojure/tree/new
> [4]http://build.clojure.org/

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread MikeM

> (deftype Foo [a b c])
>
> (defprotocol P (bar [x] "bar docs"))
>
> (extend ::Foo P {:bar (fn [afoo] :foo-thing)})
>

A common error may be to:

(extend Foo P {:bar (fn [afoo] :foo-thing)})

when (extend ::Foo ... is intended. I notice that (extend Foo...
doesn't throw - should extend check that it is supplied a class,
intfc, or keyword and throw if something else is supplied?
Alternately, could extend be changed to allow (extend Foo ... and do
the right thing ? ie determine that Foo is the constructor function
for a type and do the extension for the type Foo.

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Rich Hickey
On Fri, Nov 13, 2009 at 2:13 AM, Krukow  wrote:
>
>
> On Nov 12, 1:10 pm, Rich Hickey  wrote:
>> An early version of the code for a few important new language
>> features, datatypes[1] and protocols[2] is now available in the 'new'
>> branch[3]. Note also that the build system[4] has builds of the new
>> branch, and that the new branch works with current contrib.
>>
>> If you have the time and inclination, please try them out. Feedback is
>> particularly welcome as they are being refined.
>
> I really like the semantics of your constructs. I have a comment about
> regularity of syntax:
>
> The way to specify method names in reify and deftype vs. function
> names defprotocol and extend are different.

That's because methods and functions *are* different. I think making
them look the same only makes it more confusing since:

 - methods can only be defined by the definer of a type, protocol
extension fns can be defined by anyone anywhere

 - methods have class scope - direct use of fields as locals,
functions must use (:field self)

- functions are first class values and can be put in maps etc, methods can't

- methods have implicit this, functions don't

- functions can be closures, methods, other than in reify, can't

> It looks like when dealing
> with interface-method implementations one uses .methodName (i.e., with
> the dot), but when dealing with protocol functions one uses no dot.
> Further, extend uses maps (the docs says why this is the case).
>
> I was thinking this may make syntax irregular. I suspect this is a
> deliberate design choice to distinguish clojure protocols from java
> interfaces? Is this the case?

Yes.

>
> A stupid example:
>
> ;;uses dot
> (deftype Sometype [x]
>   [java.lang.Comparable]
>   (.compareTo [o] ...))
>
> ::uses no dot
> (defprotocol RSeqable :on clojure.lang.Seqable
>  "Seqable and reverse seqable"
>  (rseq [s] "reverse seq"))
>
> ;;do I mix dot and not?
> (extend ::Sometype
>  :RSeqable
>   {:rseq (fn [a]...))
>    :.seq (fn [a] ...)} ;; do I write :.seq here or :seq?
>

You don't mix methods and protocol functions, so once that is clear I
don't think this will be a question.

In a sense, deftypes and protocols are bridging two polymorphism
systems. As long as one doesn't conflate the two, it becomes clearer.

For instance, you could use deftype and protocols in complete
ignorance/avoidance of Java and interfaces:

(deftype Foo [a b c])

(defprotocol P (bar [x] "bar docs"))

(extend ::Foo P {:bar (fn [afoo] :foo-thing)})

(bar (Foo 1 2 3))
:foo-thing

This is a simple, powerful, flexible and dynamic system, leveraging
one's understanding of Clojure functions.

If and only if there is some requirement that instances of Foo
implement some Java interfaces, then you will need to understand Java
interfaces and methods. And there will be a clear mechanism  and place
to put them - in your deftype, just like methods have to be put inside
class definitions in Java. You have similar class scope for fields and
access to this, etc. One thing you do not have is implicit scope for
methods, the leading dot helps remind you that in order to call
someMethod, even in the body of another method in the same deftype,
you will have to use (.someMethod this ...). People have argued
against implicit this for similar reasons, and I am starting to come
around :)

The documentation is comprehensive in mentioning everything you can
do. But one doesn't need to use everything.

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Meikel Brandmeyer
Hi,

On Nov 13, 8:13 am, Mark Engelberg  wrote:

> Is there a way to customize the way that types defined by deftype
> print in the REPL?

One can add a method to print-method for the type.

> While these datatype and protocol constructs are taking shape, maybe
> now is the time to discuss what kind of "privacy" settings are
> worthwhile in a language like Clojure.  I think Java's system of
> private/public/protected is probably overkill for Clojure.  But do
> people feel that some degree of data hiding is worthwhile?  For
> example, might you want to hide some deftype fields from keyword
> lookup?

I for now don't care for privacy settings. Everything is public. The
docstrings explain the contract. Period.

> I'm also thinking about the relationship in Clojure's source between
> ISeq and ASeq.  ASeq provides the partial, default implementation of
> more in terms of next, for example.  How does this kind of thing look
> with the new protocol system?

A pretty simple solution is (.more [] (lazy-seq (next this))), no? But
I stumbled over this, too. APersistentMap does a lot like implementing
the IFn invokes for key lookup or the IPersistentCollection equiv.
Giving up on this will create a lot of more work.

Sincerely
Meikel

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Chris Kent
Mark Engelberg  gmail.com> writes:

> I'm a little worried about the strong overlap between reify/proxy,
> deftype/defstruct, and defclass/gen-class.  I can just imagine the
> questions a year from now when people join the Clojure community and
> want to understand how they differ.  So I think that eventually, there
> needs to be a very clear "story" as to why you'd choose one over the
> other.  Or better yet, maybe some of the older constructs can be
> phased out completely.

What are the plans for the future of proxy?  I assume it won't go away because
reify's inability to extend an existing class is a show-stopper for some Java
interop scenarios.  Will the syntax be brought in line with reify so dots will
be needed in front of method names?  As things stand it's a potential source of
confusion to have two such similar features with subtly different syntax.

Chris


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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Jarkko Oranen
On Nov 13, 9:13 am, Krukow  wrote:
> I was thinking this may make syntax irregular. I suspect this is a
> deliberate design choice to distinguish clojure protocols from java
> interfaces? Is this the case?
>

As far as I understand it, in defprotocol's case, I suspect there is
no dot because the specified operations will be available as normal
Clojure functions, whereas in deftype's case you'll need to use Java
interop or keywords. For example, after

(defprotocol Someproto
  (foo [x] "do stuff"))

you will be able to call (foo something-implementing-someproto), but
with deftype, you need to use (.field instance) or, if the type uses
the default ILookup implementation, (:field instance).

The extend example should just use :seq, as defprotocol will create a
function "seq" matching the .seq method in the Seqable interface.
(Because no explicit mapping is provided)

I hope I got my details right here. I haven't actually tried these
things yet. :)

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Alex Osborne
Mark Engelberg wrote:
> Protocols:
> 
> I don't understand whether there's any way to provide a partial
> implementation or default implementation of a given
> protocol/interface, and I believe this to be an important issue.
> 
> For example, a protocol for < and > that provides a default
> implementation of > in terms of < and a default implementation of < in
> terms of >, so that you only need to implement one and you get the
> other for free.
> 

How about this?

(defprotocol MyComparable
   (comparinate [x y] "Returns a negative integer if x < y, zero if they
   are equal and a positive integer if x > y.")
   (equal-to [x y] "True if x is equal to y.")
   (less-than [x y]"True if x is smaller than y.")
   (greater-than [x y] "True if x is greater than y."))

(defn mixin-comparable [type compare-fn]
   (extend type
  MyComparable
  {:comparinate compare-fn
   :equal-to (fn [x y] (zero? (comparinate x y)))
   :less-than(fn [x y] (neg?  (comparinate x y)))
   :greater-than (fn [x y] (neg?  (comparinate x y)))}))

(mixin-comparable Integer -)
(mixin-comparable String #(- (count %1) (count %2)))

(less-than 8 2); => false
(less-than "x" "") ; => true

> I'm also thinking about the relationship in Clojure's source between
> ISeq and ASeq.  ASeq provides the partial, default implementation of
> more in terms of next, for example.  How does this kind of thing look
> with the new protocol system?

See above.  But another way would just be to define ASeq as a map and 
then merge with it:

(def aseq-impl {:more  (fn [obj] (if-let [s (next obj)] s '() ))
 :count (fn [obj] ...)})

(extend MyList
   ISeq
   (merge
 aseq-impl
 {:next (fn [lst] ...)
  :count (fn [lst] ...) ; overrides the count from aseq-impl
  :cons (fn [lst x] ...)}))

Code is data. :-)

I don't know whether doing things this way is a good idea or not, but 
protocols are new: lets experiment and find out what works and what doesn't.

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


Re: Datatypes and Protocols - early experience program

2009-11-13 Thread Konrad Hinsen
On 13 Nov 2009, at 08:13, Mark Engelberg wrote:

> Is there a way to customize the way that types defined by deftype
> print in the REPL?

Implement the multimethod clojure.core/print-method for the associated  
type tag:

(deftype Foo ...)

(defmethod clojure.core/print-method ::Foo [x] ...)

> While these datatype and protocol constructs are taking shape, maybe
> now is the time to discuss what kind of "privacy" settings are
> worthwhile in a language like Clojure.  I think Java's system of
> private/public/protected is probably overkill for Clojure.  But do
> people feel that some degree of data hiding is worthwhile?  For
> example, might you want to hide some deftype fields from keyword
> lookup?

Coming from a Python background, I don't think access restrictions are  
necessary. However, flagging fields as "not meant for use by  
outsiders" could be of interest for documentation tools, to make it  
clear what client code can safely rely on.

Note also that you can always make the deftype private (it's a var  
like any other) and restrict all use of it to public functions defined  
in the same namespace. That doesn't exclude defining protocols and  
multimethods on this type elsewhere, because its type tag is a  
namespace-qualified symbol that can be used anywhere.

> Protocols:
>
> I don't understand whether there's any way to provide a partial
> implementation or default implementation of a given
> protocol/interface, and I believe this to be an important issue.

I don't think that partial implementations are possible at the moment,  
but I agree that it would be useful. A default implementation can be  
provided as an implementation of Object. It's not quite the same as a  
default implementation for a multimethod, as it doesn't apply to types  
identified by a metadata type tag, but in practice it can be good  
enough or even better.

> For example, a protocol for < and > that provides a default
> implementation of > in terms of < and a default implementation of < in
> terms of >, so that you only need to implement one and you get the
> other for free.

Right. I have such a case in my test implementation for multiarrays  
(soon to be put on Google Code...), where I'd want to define a default  
implementation for "rank" as "length of the shape vector".

Konrad.

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


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Mark Engelberg
I'm still trying to get my head around the new features.  Seeing more
code examples will definitely help.  In the meantime, here is some
stream-of-consciousness thoughts and questions.

Datatypes:

I'm a little worried about the strong overlap between reify/proxy,
deftype/defstruct, and defclass/gen-class.  I can just imagine the
questions a year from now when people join the Clojure community and
want to understand how they differ.  So I think that eventually, there
needs to be a very clear "story" as to why you'd choose one over the
other.  Or better yet, maybe some of the older constructs can be
phased out completely.

Is there a way to customize the way that types defined by deftype
print in the REPL?

While these datatype and protocol constructs are taking shape, maybe
now is the time to discuss what kind of "privacy" settings are
worthwhile in a language like Clojure.  I think Java's system of
private/public/protected is probably overkill for Clojure.  But do
people feel that some degree of data hiding is worthwhile?  For
example, might you want to hide some deftype fields from keyword
lookup?

Protocols:

I don't understand whether there's any way to provide a partial
implementation or default implementation of a given
protocol/interface, and I believe this to be an important issue.

For example, a protocol for < and > that provides a default
implementation of > in terms of < and a default implementation of < in
terms of >, so that you only need to implement one and you get the
other for free.

I'm also thinking about the relationship in Clojure's source between
ISeq and ASeq.  ASeq provides the partial, default implementation of
more in terms of next, for example.  How does this kind of thing look
with the new protocol system?

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


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Krukow


On Nov 12, 1:10 pm, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.

I really like the semantics of your constructs. I have a comment about
regularity of syntax:

The way to specify method names in reify and deftype vs. function
names defprotocol and extend are different. It looks like when dealing
with interface-method implementations one uses .methodName (i.e., with
the dot), but when dealing with protocol functions one uses no dot.
Further, extend uses maps (the docs says why this is the case).

I was thinking this may make syntax irregular. I suspect this is a
deliberate design choice to distinguish clojure protocols from java
interfaces? Is this the case?

A stupid example:

;;uses dot
(deftype Sometype [x]
   [java.lang.Comparable]
   (.compareTo [o] ...))

::uses no dot
(defprotocol RSeqable :on clojure.lang.Seqable
  "Seqable and reverse seqable"
  (rseq [s] "reverse seq"))

;;do I mix dot and not?
(extend ::Sometype
  :RSeqable
   {:rseq (fn [a]...))
:.seq (fn [a] ...)} ;; do I write :.seq here or :seq?

I guess one can reintroduce the regularity using the :on feature of
protocol functions.

Any thoughts?
/Karl

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


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Chouser
On Thu, Nov 12, 2009 at 7:59 PM, Chouser  wrote:
> On Thu, Nov 12, 2009 at 7:10 AM, Rich Hickey  wrote:
>>
>> If you have the time and inclination, please try them out. Feedback is
>> particularly welcome as they are being refined.
>
> For what it's worth, here are 2-3 finger trees implemented using
> defprotocol and deftype.
>
> http://tinyurl.com/yeh5fgg/finger_tree.clj

I should have noted that this is a very early version and doesn't
yet take advantage of some features now available like reusing
the same protocol function in multiple protocols, or using 'case'
instead of 'cond' or 'condp'.

--Chouser

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


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Chouser
On Thu, Nov 12, 2009 at 7:10 AM, Rich Hickey  wrote:
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.

For what it's worth, here are 2-3 finger trees implemented using
defprotocol and deftype.

http://tinyurl.com/yeh5fgg/finger_tree.clj

Here's an earlier version that's almost idectical except its
implemented using def-interface and reify instead:

http://tinyurl.com/y9jned5/finger_tree.clj

--Chouser

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


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Meikel Brandmeyer

Hi,

Am 12.11.2009 um 13:10 schrieb Rich Hickey:


An early version of the code for a few important new language
features, datatypes[1] and protocols[2] is now available in the 'new'
branch[3]. Note also that the build system[4] has builds of the new
branch, and that the new branch works with current contrib.

If you have the time and inclination, please try them out. Feedback is
particularly welcome as they are being refined.


I implemented my lazymap library in terms reify where gen-class was  
required before. Seems to work smoothly, but it is also only a simple  
lib. Should ISeqs still extend ASeq? Is this a case where we still  
need gen-class?


Otherwise I hadn't much chance to test... http://bitbucket.org/kotarak/lazymap/

Sincerely
Meikel



smime.p7s
Description: S/MIME cryptographic signature


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Michael Jaaka
Oh its looks like Google Go (http://golang.org) and Nice Interfaces 
(http://nice.sourceforge.net/).
Good! It sounds better than overrated polyphormism and class hierarchy.

Wiadomość napisana przez Rich Hickey w dniu 2009-11-12, o godz. 15:39:

> 
> 
> On Nov 12, 8:29 am, Sean Devlin  wrote:
>> Rich,
>> Just read the section on reify.  I'm not quite sure what this new
>> mechanism lets me do.  Could you provide an example of the problem it
>> solves?  I personally would benefit from seeing the "Old, painful way"
>> contrasted to the "New, awesome way".  This would probably help with
>> the other features too.
>> 
> 
> reify is the most subtle, as it is a subset of proxy, limited to
> implementing interfaces only, and less dynamic (no equivalent to
> update-proxy). What you get in return is a construct with fewer host
> implications, and much better performance, as stated in the wiki doc:
> 
> "The result is better performance than proxy, both in construction
> (proxy creates the instance and a fn instance for each method), and
> invocation. reify is preferable to proxy in all cases where its
> limitations are not prohibitive."
> 
> Rich
> 
> -- 
> 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 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


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Rich Hickey


On Nov 12, 8:29 am, Sean Devlin  wrote:
> Rich,
> Just read the section on reify.  I'm not quite sure what this new
> mechanism lets me do.  Could you provide an example of the problem it
> solves?  I personally would benefit from seeing the "Old, painful way"
> contrasted to the "New, awesome way".  This would probably help with
> the other features too.
>

reify is the most subtle, as it is a subset of proxy, limited to
implementing interfaces only, and less dynamic (no equivalent to
update-proxy). What you get in return is a construct with fewer host
implications, and much better performance, as stated in the wiki doc:

"The result is better performance than proxy, both in construction
(proxy creates the instance and a fn instance for each method), and
invocation. reify is preferable to proxy in all cases where its
limitations are not prohibitive."

Rich

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


Re: Datatypes and Protocols - early experience program

2009-11-12 Thread Sean Devlin
Rich,
Just read the section on reify.  I'm not quite sure what this new
mechanism lets me do.  Could you provide an example of the problem it
solves?  I personally would benefit from seeing the "Old, painful way"
contrasted to the "New, awesome way".  This would probably help with
the other features too.

Thanks,
Sean

On Nov 12, 7:10 am, Rich Hickey  wrote:
> An early version of the code for a few important new language
> features, datatypes[1] and protocols[2] is now available in the 'new'
> branch[3]. Note also that the build system[4] has builds of the new
> branch, and that the new branch works with current contrib.
>
> If you have the time and inclination, please try them out. Feedback is
> particularly welcome as they are being refined.
>
> Thanks,
>
> Rich
>
> [1]http://www.assembla.com/wiki/show/clojure/Datatypes
> [2]http://www.assembla.com/wiki/show/clojure/Protocols
> [3]http://github.com/richhickey/clojure/tree/new
> [4]http://build.clojure.org/

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


Datatypes and Protocols - early experience program

2009-11-12 Thread Rich Hickey
An early version of the code for a few important new language
features, datatypes[1] and protocols[2] is now available in the 'new'
branch[3]. Note also that the build system[4] has builds of the new
branch, and that the new branch works with current contrib.

If you have the time and inclination, please try them out. Feedback is
particularly welcome as they are being refined.

Thanks,

Rich

[1] http://www.assembla.com/wiki/show/clojure/Datatypes
[2] http://www.assembla.com/wiki/show/clojure/Protocols
[3] http://github.com/richhickey/clojure/tree/new
[4] http://build.clojure.org/

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