Laziness and deadlocks

2010-04-26 Thread Per Vognsen
Consider:

(def as (lazy-seq (cons 1 bs)))
(def bs (lazy-seq (cons 2 cs)))
;; ...
(def zs (lazy-seq (cons 26 as)))

Suppose you start two threads concurrently. The first forces 'as' and
the second forces 'zs'. If the timing is just right, this can result
in a deadlock:

// LazySeq.java

final synchronized Object sval(){
if(fn != null)
{
try
{
sv = fn.invoke();
fn = null;
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
if(sv != null)
return sv;
return s;
}

final synchronized public ISeq seq(){
sval();
if(sv != null)
{
Object ls = sv;
sv = null;
while(ls instanceof LazySeq)
{
ls = ((LazySeq)ls).sval();
}
s = RT.seq(ls);
}
return s;
}

For this sort of reason (as well as the general overhead of locking),
GHC and other compilers for lazy languages only approximately
implement call-by-need: if two threads force an unevaluated thunk
almost simultaneously, they will both evaluate the thunk, and the
first to successfully complete the CAS at the end wins.

This is an excellent implementation strategy in a pure language.
However, in Clojure, it's common to use lazy sequences for side
effects, and evaluating the same thunk multiple times would be very
bad.

I'm not sure what of the best compromise. You could use a
non-synchronized wrapper around seq that checks a volatile variable
(maybe fn itself) to check for multiple evaluation and, in that case,
throw an error. That would amount to deadlock detection.

-Per

-- 
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: Laziness and deadlocks

2010-04-26 Thread Meikel Brandmeyer
Hi,

On 26 Apr., 11:22, Per Vognsen per.vogn...@gmail.com wrote:

 Consider:

 (def as (lazy-seq (cons 1 bs)))
 (def bs (lazy-seq (cons 2 cs)))
 ;; ...
 (def zs (lazy-seq (cons 26 as)))

 Suppose you start two threads concurrently. The first forces 'as' and
 the second forces 'zs'. If the timing is just right, this can result
 in a deadlock:

How? As far as I understand the code forcing as and zs are basically
independent tasks. seq does not recursively call into the rest. And
then you'd even need a circular structure (which is - I believe - what
you indicate with your fill the next number dots). Even a fixed
version of forcing wouldn't return anyway on such a structure, no?

But maybe I just don't understand what you mean with forcing.

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: Laziness and deadlocks

2010-04-26 Thread Per Vognsen
On Mon, Apr 26, 2010 at 5:55 PM, Meikel Brandmeyer m...@kotka.de wrote:
 Hi,

 On 26 Apr., 11:22, Per Vognsen per.vogn...@gmail.com wrote:

 Consider:

 (def as (lazy-seq (cons 1 bs)))
 (def bs (lazy-seq (cons 2 cs)))
 ;; ...
 (def zs (lazy-seq (cons 26 as)))

 Suppose you start two threads concurrently. The first forces 'as' and
 the second forces 'zs'. If the timing is just right, this can result
 in a deadlock:

 How? As far as I understand the code forcing as and zs are basically
 independent tasks. seq does not recursively call into the rest. And
 then you'd even need a circular structure (which is - I believe - what
 you indicate with your fill the next number dots). Even a fixed
 version of forcing wouldn't return anyway on such a structure, no?

The idea is to try to create a situation where a pair of LazySeqs, xs
and ys, are interlinked in a cycle such that the first thread forces
them in order xs, ys while the second thread concurrently forces them
in order ys, xs. This could happen if thread #1 evaluates (doall (take
3 xs)) and thread #2 evaluates (doall (take 3 ys)).

-Per

-- 
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: Laziness and deadlocks

2010-04-26 Thread Per Vognsen
On Mon, Apr 26, 2010 at 6:15 PM, Per Vognsen per.vogn...@gmail.com wrote:

[...]
 The idea is to try to create a situation where a pair of LazySeqs, xs
 and ys, are interlinked in a cycle such that the first thread forces
 them in order xs, ys while the second thread concurrently forces them
 in order ys, xs. This could happen if thread #1 evaluates (doall (take
 3 xs)) and thread #2 evaluates (doall (take 3 ys)).

Actually, it occurs to me that they wouldn't have to be physically
interlinked at all. It's enough for their thunks to be mutually
referential:

(def xs (lazy-seq (first ys) nil))
(def ys (lazy-seq (first xs) nil))

-Per

-- 
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: Laziness and deadlocks

2010-04-26 Thread Per Vognsen
Okay, that is a blatant infinite loop that has nothing to do with
deadlocks. I give up. This combination of laziness and concurrency and
locking is giving me a headache. Sorry about the distraction,
everyone.

-Per

On Mon, Apr 26, 2010 at 6:23 PM, Per Vognsen per.vogn...@gmail.com wrote:
 On Mon, Apr 26, 2010 at 6:15 PM, Per Vognsen per.vogn...@gmail.com wrote:

 [...]
 The idea is to try to create a situation where a pair of LazySeqs, xs
 and ys, are interlinked in a cycle such that the first thread forces
 them in order xs, ys while the second thread concurrently forces them
 in order ys, xs. This could happen if thread #1 evaluates (doall (take
 3 xs)) and thread #2 evaluates (doall (take 3 ys)).

 Actually, it occurs to me that they wouldn't have to be physically
 interlinked at all. It's enough for their thunks to be mutually
 referential:

 (def xs (lazy-seq (first ys) nil))
 (def ys (lazy-seq (first xs) nil))

 -Per


-- 
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: TransactionalHashMap hash computation bug

2010-04-26 Thread Rich Hickey


On Apr 25, 2010, at 8:33 PM, John wrote:


I got no response since I posted the previous message. Should I be
posting bugs to assembla space instead of here ?


Yes, please create an issue.


Do I need to be a
member to do that ?



No, you can use the support tab if you are not a member.

Note that TransactionalHashMap is an unsupported experiment, so will  
not be prioritized without a patch.


Rich



On Apr 24, 7:38 pm, John jvsha...@gmail.com wrote:

Hi all,

I think I found my first bug in Clojure. It's in the
TransactionalHashMap computation of the bin at line 30.

return h % bins.length;

should be replaced by

return (h  0x7FFF) % bins.length;

to avoid array out of bound exceptions.

--
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 
athttp://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


--
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: Laziness and deadlocks

2010-04-26 Thread Meikel Brandmeyer
Hi,

On 26 Apr., 13:27, Per Vognsen per.vogn...@gmail.com wrote:

 Okay, that is a blatant infinite loop that has nothing to do with
 deadlocks. I give up. This combination of laziness and concurrency and
 locking is giving me a headache. Sorry about the distraction,
 everyone.

Well, we can step through the code and see whether this sheds some
light on the issue.

Calling .seq on zs, which is meant by forcing, I believe.

  zs.seq()
sval()
  ; fn != null since zs was not forced before.
  sv = fn.invoke()
  ; sv is a Cons, namely (cons 26 as)
  fn = null
  return sv
; Up to now no chance of deadlock. Back to seq()
; sv != null
ls = sv
sv = null
; a Cons is not an instance of LazySeq
s = RT.seq(ls)
; s == ls since .seq is the identity on a Cons
return s
; Still no chance of deadlock.

There is no other way to force a sequence in Clojure than traversing
it
via next/rest, which implicitely call seq on the rest. So even in the
circular case there is no chance of deadlock.

The recursive .sval() call is for lazy-seq evaluating to lazy-seqs.
ie. (lazy-seq (lazy-seq ...)). Here - again - is no chance of
deadlock.

Does this make sense?

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 update

2010-04-26 Thread Rich Hickey


On Apr 23, 2010, at 11:48 PM, Mark Engelberg wrote:


A few meandering observations:

I like the latest change to include a this argument.  It makes the
number of arguments line up which is a good thing.

I like the idea of defrecord for the common case, rather than having
to request default implementations of various interfaces within
deftype.  Still, I think the splitting of deftype and defrecord has
merely delayed, not eliminated, the need to eventually find a
convenient, general scheme for layering in default implementations of
interfaces.  I look forward to seeing how this evolves.

I like Rich's description of Clojure's datatypes/protocols as
opinionated, and mostly agree with his manifesto.  The one opinion I
have the most difficulty with is:
It has always been an unfortunate characteristic of using classes for
application domain information that it resulted in information being
hidden behind class-specific micro-languages, e.g. even the seemingly
harmless employee.getName() is a custom interface to data. Putting
information in such classes is a problem, much like having every book
being written in a different language would be a problem. You can no
longer take a generic approach to information processing. This results
in an explosion of needless specificity, and a dearth of reuse.

OO programmers write employee.getName() methods to preserve the option
of doing something more sophisticated later, which isn't readily
possible once all your clients start using employee.name everywhere.
So if you really want to create a generic approach to information
processing, it seems like the best approach is to address the
underlying reason that these custom interfaces are needed.

For this reason, I've always found appealing languages which let you
optionally write getter/setter methods that hook into the standard
field access syntax.  This lets you start out with your fields public,
and let your clients use the standard field access interface.
Later, if you realize you need to do something special, you can easily
add a custom getter without breaking your clients.

As far as I know, Clojure doesn't currently make any attempt to
address this problem of allowing a standard way to access public data
from an object, while preserving the option of doing something more
sophisticated later.  So a programmer is still forced to choose
between the convenience of keyword lookup of data, versus a protocol
filled with get-name functions to preserve future flexibility.

Ideally, I'd like to see a way to allow me to write a program using
(:name employee), and later, if I need to, customize the employee
datatype so that (:name employee) actually dispatches to some other
function.  Ditto with (assoc employee :name Mark) (for example, to
validate the data in some way?).

If I'm off-base, and these issues are easy to currently workaround in
Clojure, I'd love to hear more about how others are handling this in
their own programs.





You can use functions if you don't like unencapsulated data.

Weren't you also advocating for serialization? Such things become much  
simpler when one knows they are dealing with just data, and not the  
results of some (possibly irreversible) function, of some other  
possibly uninitialized dependents etc.


You need a level that is the data (even under some 'property' system).  
The keyword-accessible, constructor-mapped fields are that layer. You  
can always build functions on top of that.


Calculated getters/setters are one of those rich sources of incidental  
complexity, with little real-world benefit IMO.


That said, defrecord is simply implemented in terms of deftype. People  
can easily prototype alternatives for consideration.


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 update

2010-04-26 Thread Rich Hickey


On Apr 24, 2010, at 1:11 PM, Richard Newman wrote:


Neither of those attributes reveal information about the
implementation of the objects in question. They both reveal
information about the state that some client could find useful. They
are both values that, if not directly available from the object  
should

be calculated by the object, as calculating the value requires
knowledge about the implementation.


This approach still isn't 'good' OO -- it might not leak  
implementation details, but it supports asking, not telling.


http://pragprog.com/articles/tell-dont-ask

That is, you should endeavor to tell objects what you want them to  
do; do not ask them questions about their state, make a decision,  
and then tell them what to do.





To the extent OO tries to make information into objects, it isn't  
'good', IMO. That article is a good example of how goofy things get  
when you try to turn information into objects. Information is data.  
Records are for information.


Why ever would I want to try to 'tell' a piece of information anything?

The datatype and protocol system is there to support the polymorphic  
manipulation of data by functions, not for recreating OO rabbit holes.


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


ClojureCLR multiple .dll files

2010-04-26 Thread lucidquiet
Hello,

I'm using ClojureCLR, at the moment I've created a couple of files
that each have a (ns .. :gen-class .. ) in them.  I then compiled both
clj and the result is a [name].clj.dll for each file.  The question I
have: is there a way to create just a single dll as a result of
compilation.  I'm aware that in the Java version of Clojure each
function produces a single .class file, and in the end all of
the .class files can be packaged as part of a .jar file.  In .NET
there really isn't such a thing as a .class file (as far as I know).

I have attempted to merge them using the ILMerge program found at
MSDN.  It appears that __Init__, __InternalDynamicExpressionInit, and
__REPL__ would wind up being duplicate types.  My guess is that
individually it makes sense for these classes to exist per dll, but in
a single dll perhaps only 1 of these type definition(s) should be
generated.  I have used the /allowDup flag to turn off errors, but I
am not certain of the consequences, and perhaps the better solution is
to create a common type only once when outputting these dlls based on
parameters to compile, or a *flag* of some kind.

Any thoughts or suggestions welcome.

Thanks,
L-

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

2010-04-26 Thread Konrad Hinsen
On 24.04.2010, at 05:48, Mark Engelberg wrote:

 As far as I know, Clojure doesn't currently make any attempt to
 address this problem of allowing a standard way to access public data
 from an object, while preserving the option of doing something more
 sophisticated later.  So a programmer is still forced to choose
 between the convenience of keyword lookup of data, versus a protocol
 filled with get-name functions to preserve future flexibility.

This is basically a question of how you choose your abstractions (the 
documented interfaces) and your implementations (the data structures), and in 
particular on where you draw the boundaries. That is a design issue, so I don't 
expect any language feature to remove the necessity to think about this 
carefully.

 For this reason, I've always found appealing languages which let you
 optionally write getter/setter methods that hook into the standard
 field access syntax.

That's little more than syntactic sugar, considering that field access is 
equivalent to calling a method with no arguments.

The closest equivalent in Clojure would be to define a functional accessor API 
for all access to your data. A first implementation would simply set the 
accessor to be a field-name keyword:

(defrecord foo [bar baz])
(def get-bar :bar)
(def get-baz :baz)

If necessary you can then replace the accessor functions by something more 
complicated, or turn them into prototype functions to allow multiple 
implementations. Client code won't see the difference.

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: Questions about program design

2010-04-26 Thread Paul Drummond
Hi Andrew,

It's getting old now but you mind find this helpful:

http://groups.google.com/group/clojure/browse_thread/thread/6333791e49fbca7f/c724f1681dac3102?lnk=gstq=drummond#c724f1681dac3102

and this:

http://clojure.org/state

Cheers,
Paul Drummond

On 25 April 2010 18:45, Andrew Brookins a.m.brook...@gmail.com wrote:

 Hey, all,

 Writing in a functional language and using a REPL for the first time,
 I feel like I'm playing with awesome magic.  However, I'm a little
 confused.

 I have about two years of experience working with object-oriented
 scripting languages and C.  I am somewhat familiar with thinking in
 terms of object-oriented design -- organizing functionality and state
 within classes, etc.

 I am trying to keep my mind fluid, though, especially as I look for a
 language and a platform that supports concurrency well.  While a lot
 of Clojure really hits home with me, a nagging voice in my head says,
 These are just blobs of functions divided by namespaces...

 So, for people like me, can any of you suggest some transcribed
 lectures, screencasts, books, blog posts, or other errata that discuss
 the difference between program design in a language like Clojure and
 an OO language like Ruby or Java?

 Andrew

 --
 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.comclojure%2bunsubscr...@googlegroups.com
 For more options, visit this group at
 http://groups.google.com/group/clojure?hl=en




-- 
Iode Software Ltd, registered in England No. 6299803.

Registered Office Address: 12 Sancroft Drive, Houghton-le-Spring, Tyne 
Wear, DH5 8NE

This message is intended only for the use of the person(s) (the intended
recipient(s)) to whom it is addressed. It may contain information which is
privileged and confidential within the meaning of applicable law. If you are
not the intended recipient, please contact the sender as soon as possible.
The views expressed in this communication may not necessarily be the views
held by The Company.

-- 
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: Questions about program design

2010-04-26 Thread Andrew Brookins
On Mon, Apr 26, 2010 at 5:49 AM, Paul Drummond paul.drumm...@iode.co.uk wrote:
 Hi Andrew,

 It's getting old now but you mind find this helpful:

 http://groups.google.com/group/clojure/browse_thread/thread/6333791e49fbca7f/c724f1681dac3102?lnk=gstq=drummond#c724f1681dac3102

 and this:

 http://clojure.org/state

 Cheers,
 Paul Drummond


Thanks, Paul!  Those links do help.

Best,
Andrew

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


tutorial on clojure protocols 1.2

2010-04-26 Thread Stuart Halloway
I have created a short (30 min) tutorial on clojure protocols at http://vimeo.com/11236603 
. Hope some of you will find it useful.


Feedback welcome!

Stu

--
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: Conflicting definition for IPersistentVector

2010-04-26 Thread Dan
Bumping.

Let me emphasize this paragraph, which is really the crux of the
problem:

 Put another way, the problem is that if I have an Associative which I
 know maps integers to strings, and I invoke seq(), I don't know what
 kind of values I'm going to get.

Is this expected behavior or a bug?  What's the appropriate place to
submit bug reports?


On Apr 13, 9:37 am, Dan dansmit...@gmail.com wrote:
 I'm a Java developer; I work on a project that has adopted Clojure's
 data structures as a convenient implementation of immutable sets,
 maps, etc.  In attempting to add type parameters to the Clojure
 interfaces, I noticed a conflict in the definition of
 IPersistentVector.  I assume the problem exists when programming in
 Clojure, too.

 IPersistentVector implements both Associative and IPersistentStack.
 These, in turn, both implement Seqable.  But the element type in the
 two cases is different: if I have a vector of Strings,
 IPersistentStack says that seq() should enumerate the strings;
 Associative says that seq() should enumerate Map.Entries.  The
 APersistentVector implementation resolves this conflict by going with
 the first: seq() gives you a list of strings.

 Put another way, the problem is that if I have an Associative which I
 know maps integers to strings, and I invoke seq(), I don't know what
 kind of values I'm going to get.

 When I say an interface says something, there's not actually much
 documentation, so that's based on what I think is the natural
 interpretation of the interface.  The page at http://clojure.org/
 data_structures does say this about IPersistentMap: seq returns a
 sequence of map entries, which are key/value pairs.  There is no such
 assertion made about Associatives, but since IPersistentMap implements
 Seqable through Associative, it would be odd to specify the contract
 for Associative differently.

 It looks to me like the best way to handle this would be to eliminate
 the connection between Associative and IPersistentCollection, leaving
 that connection to the subtypes.  But I don't know what kind of impact
 that would have on existing code (if it breaks something, does that
 code behave well when given an IPersistentVector?)

-- 
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: tutorial on clojure protocols 1.2

2010-04-26 Thread Tim Harper
On Mon, Apr 26, 2010 at 10:20 AM, Stuart Halloway stuart.hallo...@gmail.com
 wrote:

 I have created a short (30 min) tutorial on clojure protocols at
 http://vimeo.com/11236603. Hope some of you will find it useful.

 Feedback welcome!

 Stu


Watched it today during lunch, it was great! Thanks Stuart.

-- 
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: Conflicting definition for IPersistentVector

2010-04-26 Thread Rich Hickey


On Apr 13, 2010, at 9:37 AM, Dan wrote:


I'm a Java developer; I work on a project that has adopted Clojure's
data structures as a convenient implementation of immutable sets,
maps, etc.  In attempting to add type parameters to the Clojure
interfaces, I noticed a conflict in the definition of
IPersistentVector.  I assume the problem exists when programming in
Clojure, too.



You should note that by doing so you are superimposing homogeneity on  
collections that are otherwise heterogeneous.



IPersistentVector implements both Associative and IPersistentStack.
These, in turn, both implement Seqable.  But the element type in the
two cases is different: if I have a vector of Strings,
IPersistentStack says that seq() should enumerate the strings;
Associative says that seq() should enumerate Map.Entries.


As you note below, they don't say any such thing.


The
APersistentVector implementation resolves this conflict by going with
the first: seq() gives you a list of strings.

Put another way, the problem is that if I have an Associative which I
know maps integers to strings, and I invoke seq(), I don't know what
kind of values I'm going to get.



Objects


When I say an interface says something, there's not actually much
documentation, so that's based on what I think is the natural
interpretation of the interface.  The page at http://clojure.org/
data_structures does say this about IPersistentMap: seq returns a
sequence of map entries, which are key/value pairs.  There is no such
assertion made about Associatives, but since IPersistentMap implements
Seqable through Associative, it would be odd to specify the contract
for Associative differently.

It looks to me like the best way to handle this would be to eliminate
the connection between Associative and IPersistentCollection, leaving
that connection to the subtypes.  But I don't know what kind of impact
that would have on existing code (if it breaks something, does that
code behave well when given an IPersistentVector?)



One way to look at the Seqable in high-level interfaces is just as  
specifying a sequence of whatever the value type is for the ultimate  
concrete implementation. Java supports return type covariance, so you  
could put a more specific signature on seq for IPersistentMap.


In any case, Associative shouldn't constrain the seq or value type of  
the collection. All it specifies is that, given keys you can get items.


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: tutorial on clojure protocols 1.2

2010-04-26 Thread DmitriKo
Yeah, Stuart, well done !


On Apr 26, 10:44 pm, Tim Harper timchar...@gmail.com wrote:
 On Mon, Apr 26, 2010 at 10:20 AM, Stuart Halloway stuart.hallo...@gmail.com

  wrote:
  I have created a short (30 min) tutorial on clojure protocols at
 http://vimeo.com/11236603. Hope some of you will find it useful.

  Feedback welcome!

  Stu

 Watched it today during lunch, it was great! Thanks Stuart.

 --
 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 
 athttp://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: tutorial on clojure protocols 1.2

2010-04-26 Thread Ryan Waters
From the perspective of a clojure beginner, it was good information
and I grokked almost everything.  Specifically, any lack of
comprehension on my part has more to do with the topic and my lack of
clojure expertise than with your presentation.  ; )

I wasn't aware of all the resources at the end so I'm glad those items
were included, too.

Thank you!

- Ryan


On Apr 26, 11:20 am, Stuart Halloway stuart.hallo...@gmail.com
wrote:
 I have created a short (30 min) tutorial on clojure protocols 
 athttp://vimeo.com/11236603
 . Hope some of you will find it useful.

 Feedback welcome!

 Stu

 --
 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 
 athttp://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


Any window user familiar with clojure-contrib development ?

2010-04-26 Thread gary ng
Hi,

I am wondering if there is any windows user who is familiar with
clojure-contrib project.

The reason I asked is that I encountered quite some issues when trying to
build my own copy of clojure-contrib(on windows). That includes:

1. I cannot clone http://github.com/richhickey/clojure-contrib.git as it
would die in the middle for some item(i.e. certain git hash object) not
found. I have to use git:// instead
2. Even after successful cloning, certain files seems to be suffering from
the CRLF/LF conversion issue, I have to turn off git's CRLF auto conversion
or else the newly cloned tree would already been showing changes(while the
diff shows lines deleted then added with no noticeable difference, which I
traced to the CRLF).
3. Then while building clojure-contrib, certain tests failed which based on
the test log is again about the odd case of file system naming(file:/foo 
'file://C:/foo) and CRLF  LF

-- 
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: clojure.contrib.logging and Google App Engine

2010-04-26 Thread gary ng
On Sun, Apr 25, 2010 at 4:47 PM, ataggart alex.tagg...@gmail.com wrote:

 Yeah, the fix-patch was submitted prior to the final release of 1.1.0,
 but alas none of those with the power to actually commit the patch got
 around to it until it was too late.


I have built the 1.2.0-snapshot which seems to be even worse  as it is now
throwing exception during the build process.

BUILD FAILED
java.lang.ExceptionInInitializerError
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.loadClassForName(RT.java:1550)
at clojure.lang.RT.load(RT.java:379)
at clojure.lang.RT.load(RT.java:361)
at clojure.core$load__5214$fn__5221.invoke(core.clj:4394)
at clojure.core$load__5214.doInvoke(core.clj:4393)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.core$load_one__5155.invoke(core.clj:4222)
at clojure.core$load_lib__5170.doInvoke(core.clj:4259)
at clojure.lang.RestFn.applyTo(RestFn.java:143)
at clojure.core$apply__3699.invoke(core.clj:480)
at clojure.core$load_libs__5186.doInvoke(core.clj:4293)
at clojure.lang.RestFn.applyTo(RestFn.java:138)
at clojure.core$apply__3699.invoke(core.clj:482)
at clojure.core$use__5210.doInvoke(core.clj:4371)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at guestbook.xmppc$loading__5103__auto8.invoke(xmppc.clj:1)
at guestbook.xmppc__init.load(Unknown Source)
at guestbook.xmppc__init.clinit(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:247)
at clojure.lang.RT.loadClassForName(RT.java:1550)
at clojure.lang.RT.load(RT.java:379)
at clojure.lang.RT.load(RT.java:361)
at clojure.core$load__5214$fn__5221.invoke(core.clj:4394)
at clojure.core$load__5214.doInvoke(core.clj:4393)
at clojure.lang.RestFn.invoke(RestFn.java:409)
at clojure.core$load_one__5155.invoke(core.clj:4222)
at clojure.core$compile__5226$fn__5227.invoke(core.clj:4404)
at clojure.core$compile__5226.invoke(core.clj:4403)
at clojure.lang.Var.invoke(Var.java:365)
at clojure.lang.Compile.main(Compile.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:217)
at
org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:152)
at org.apache.tools.ant.taskdefs.Java.run(Java.java:764)
at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:218)
at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:132)
at org.apache.tools.ant.taskdefs.Java.execute(Java.java:105)
at
org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at
org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
at
org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
at org.apache.tools.ant.Main.runBuild(Main.java:758)
at org.apache.tools.ant.Main.startAnt(Main.java:217)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: java.lang.RuntimeException: Valid logging implementation could
not be found.
at clojure.contrib.logging$fn__37.invoke(logging.clj:188)
at clojure.contrib.logging__init.load(Unknown Source)
at clojure.contrib.logging__init.clinit(Unknown Source)

-- 
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: Any window user familiar with clojure-contrib development ?

2010-04-26 Thread Armando Blancas
I build on Windows and it's fine most of the time. I didn't deal with
(1) and (2) as my initial clone was OK; I avoid (3) with -
Dmaven.test.skip=true

But sometimes I get these errors even though I don't change any files.
I work around this by deleting the files and repeating the pull. I
don't know if that's a good practice but I get the update.

git pull
...
Updating 2938997..db3466e
error: Entry 'src/jvm/clojure/lang/APersistentMap.java' not uptodate.
Cannot merge.

Updating 2938997..db3466e
error: Entry 'src/jvm/clojure/lang/ASeq.java' not uptodate. Cannot
merge.

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


ClassCastException using let

2010-04-26 Thread borgees
I'm a clojure newbie, trying to automate a script at work and running
into an issue.

Given a function

(defn diffCommonOrders
  For each order, checks the two execs maps
  for the entries and reports the differences
  [orders1 orders2 execs1 execs2]
  (for [order (vals orders1) :when (not-empty (get execs1
(order :receiving_order_id )))]
 (let [order2 (orders2 (order :cl_ord_id))
   recOrdId1 (get order :receiving_order_id)
   recOrdId2 (get order2 :receiving_order_id)]
  (difference (set (get execs1 recFirmOrdId1)) (set (get execs2
recFirmOrdId2))

with orders1 and orders2 defined as a map of String to Map with keys
{:receiving_order_id :cl_ord_id }
and execs1 and execs2 defined as maps of String to Vector, when I try
to execute this function in the REPL, I get:

java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be
cast to java.util.Map$Entry

I believe the error is occurring on the last line.  Why is it
expecting a Map Entry?  Why can I not return whatever I want from the
let?

-- 
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: clojure.contrib.logging and Google App Engine

2010-04-26 Thread gary ng
On Mon, Apr 26, 2010 at 6:26 PM, gary ng garyng2...@gmail.com wrote:



 On Sun, Apr 25, 2010 at 4:47 PM, ataggart alex.tagg...@gmail.com wrote:

 Yeah, the fix-patch was submitted prior to the final release of 1.1.0,
 but alas none of those with the power to actually commit the patch got
 around to it until it was too late.


 I have built the 1.2.0-snapshot which seems to be even worse  as it is now
 throwing exception during the build process.

 BUILD FAILED
 java.lang.ExceptionInInitializerError
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:247)
 at clojure.lang.RT.loadClassForName(RT.java:1550)
 at clojure.lang.RT.load(RT.java:379)
 at clojure.lang.RT.load(RT.java:361)
 at clojure.core$load__5214$fn__5221.invoke(core.clj:4394)
 at clojure.core$load__5214.doInvoke(core.clj:4393)
 at clojure.lang.RestFn.invoke(RestFn.java:409)
 at clojure.core$load_one__5155.invoke(core.clj:4222)
 at clojure.core$load_lib__5170.doInvoke(core.clj:4259)
 at clojure.lang.RestFn.applyTo(RestFn.java:143)
 at clojure.core$apply__3699.invoke(core.clj:480)
 at clojure.core$load_libs__5186.doInvoke(core.clj:4293)
 at clojure.lang.RestFn.applyTo(RestFn.java:138)
 at clojure.core$apply__3699.invoke(core.clj:482)
 at clojure.core$use__5210.doInvoke(core.clj:4371)
 at clojure.lang.RestFn.invoke(RestFn.java:409)
 at guestbook.xmppc$loading__5103__auto8.invoke(xmppc.clj:1)
 at guestbook.xmppc__init.load(Unknown Source)
 at guestbook.xmppc__init.clinit(Unknown Source)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:247)
 at clojure.lang.RT.loadClassForName(RT.java:1550)
 at clojure.lang.RT.load(RT.java:379)
 at clojure.lang.RT.load(RT.java:361)
 at clojure.core$load__5214$fn__5221.invoke(core.clj:4394)
 at clojure.core$load__5214.doInvoke(core.clj:4393)
 at clojure.lang.RestFn.invoke(RestFn.java:409)
 at clojure.core$load_one__5155.invoke(core.clj:4222)
 at clojure.core$compile__5226$fn__5227.invoke(core.clj:4404)
 at clojure.core$compile__5226.invoke(core.clj:4403)
 at clojure.lang.Var.invoke(Var.java:365)
 at clojure.lang.Compile.main(Compile.java:56)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at
 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at
 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at
 org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:217)
 at
 org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:152)
 at org.apache.tools.ant.taskdefs.Java.run(Java.java:764)
 at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:218)
 at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:132)
 at org.apache.tools.ant.taskdefs.Java.execute(Java.java:105)
 at
 org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
 at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
 at
 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at
 org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
 at org.apache.tools.ant.Task.perform(Task.java:348)
 at org.apache.tools.ant.Target.execute(Target.java:357)
 at org.apache.tools.ant.Target.performTasks(Target.java:385)
 at
 org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
 at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
 at
 org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
 at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
 at org.apache.tools.ant.Main.runBuild(Main.java:758)
 at org.apache.tools.ant.Main.startAnt(Main.java:217)
 at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
 at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
 Caused by: java.lang.RuntimeException: Valid logging implementation could
 not be found.
 at clojure.contrib.logging$fn__37.invoke(logging.clj:188)
 at clojure.contrib.logging__init.load(Unknown Source)
 at clojure.contrib.logging__init.clinit(Unknown Source)


Seems that the problem is deeper(well into the clojure compiler). I took out
the catch_all and let the exception shows up

Caused by: java.io.IOException: The system cannot find the path specified
(NO_SOURCE_FILE:0)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:5285)
at clojure.lang.Compiler.analyze(Compiler.java:5099)