Re: Enhanced Primitive Support Syntax

2011-01-18 Thread Stuart Sierra
Yes, very important difference that. Clojure will *not* return incorrect 
results on overflow (Java will) but it might throw an exception.

-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread nicolas.o...@gmail.com
On Mon, Jan 17, 2011 at 3:10 AM, chris cnuern...@gmail.com wrote:
 Is it insane to suggest that perhaps clojure should work with scala
 such that we can write both languages in the same file?


A lot of reasons for which it is not possible:
- it would mean coordinating two implementations/implementers.
- it would prevent to go to platform for which there is no support in
the other language.
- A type checker would not be really happy to deal with a lot of
Object - Object functions...
- it would be ugly

Having a bit of (optional) type inference for performance and
compile-time safety in Clojure could be interesting though.

-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread chris
Yeah yeah!

http://www.google.com/search?q=lisp+type+inference

Chris

On Jan 17, 5:55 am, nicolas.o...@gmail.com nicolas.o...@gmail.com
wrote:
 On Mon, Jan 17, 2011 at 3:10 AM, chris cnuern...@gmail.com wrote:
  Is it insane to suggest that perhaps clojure should work with scala
  such that we can write both languages in the same file?

 A lot of reasons for which it is not possible:
 - it would mean coordinating two implementations/implementers.
 - it would prevent to go to platform for which there is no support in
 the other language.
 - A type checker would not be really happy to deal with a lot of
 Object - Object functions...
 - it would be ugly

 Having a bit of (optional) type inference for performance and
 compile-time safety in Clojure could be interesting though.

-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread Bob Hutchison
Hi Stuart,

On 2011-01-15, at 4:06 PM, Stuart Halloway wrote:

 In my experience, errors are the problem and we should be avoiding them, 
 almost at all costs. 
 
 This debate always starts by conflating three things into two, and then goes 
 downhill from there. :-( It isn't 
 
 (a) safe/slow vs. 
 (b) unsafe/fast. 

That's how us outsiders are left to look at it.

 
 It is 
 
 (a) unsafe/incorrect value on overflow/fastest/unifiable* vs. 
 (b) safe/error on overflow/fast/unifiable vs. 
 (c) safe/promoting on overflow/slow/not-unifiable
 
 *unifiable: able to deliver same semantics for primitives and objects

This doesn't really help me understand your argument.

It looks to me as though Clojure is trying to steer itself through the middle 
of something. The trouble is that I don't know where the edges of the middle 
are.

Maybe it is just a documentation problem. But I'd also suggest that there's a 
bit of a sales job necessary here.

 
 We have thought about this quite a bit,

Nobody doubts that, certainly I don't. And I'm not trying to minimise or 
dismiss what you've done. And I'm not claiming that I've thought about it 
better or more or deeper. But I do have concerns and I don't see them being 
addressed, and I'd like it if they weren't minimised either. Maybe my concerns 
are completely addressed. Maybe not. I don't know, and I'd like to be convinced.

 and an argument from one axis only (e.g safe/unsafe) that doesn't even 
 mention some of  the other axes is not likely to be persuasive. Would be more 
 interesting to see a new axis we haven't thought of...

Numerical correctness, for some of us, is an overwhelming issue. This is purely 
from experience... bad experience... 30+ years of bad experience in my case :-) 
From my point of view, the approach Clojure is taking isn't persuasive, not to 
say it couldn't be made persuasive.

I think I did add what might be considered an additional axis. Syntax. 
Specifically what annotations are needed and for what purpose. I don't think 
this should be dismissed out of hand.

Cheers,
Bob

 
 Stu
 
 Stuart Halloway
 Clojure/core
 http://clojure.com
 
 
 -- 
 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


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread Jason Wolfe


On Jan 16, 6:18 pm, Sean Corfield seancorfi...@gmail.com wrote:
 On Sun, Jan 16, 2011 at 3:50 PM, Jason Wolfe ja...@w01fe.com wrote:
  Moreover, we do not need to redefine the class at run-time.  A simple
  way to do this: when you compile a function with arithmetic
  operations, concatenate bytecode for two versions: essentially, one
  with the unprimed (exception-throwing) ops and one with the primed
  (overflowing) ones.  Now, replace the exceptions in the first path
  with local jumps into the second path.  There are probably ways to get
  around generating two copies of the bytecode in advance, and making
  such a unilateral shift to inefficient semantics, but I don't know
  enough about JVM internals to say for sure.

 The problem is that if you have an arbitrary form that can operate
 entirely in primitives (some loop/recur perhaps) and you allow
 primitives to magically convert to Objects in that code, then the
 entire piece of code has to handle both primitives AND Objects and
 every single sub-form must be capable of handling primitives as input
 AND Objects as input and returning primitives if possible...

 You can't have automatic promotion to Object from primitive and expect
 any reasonable code to be generated that can maintain primitive
 performance across arbitrary expressions. Either everything can work
 with Objects - and you lose performance - or everything must be able
 to work within primitives (and at most throw exceptions) and remain
 performant.

I think you can.  Let me elaborate on my simplistic example.  Compile
the code for a function twice -- once where everything works within
primitives, and once where everything works with Objects -- and
concatenate the bytecode together.  Start by running the primitive
version.  On overflow, jump into the corresponding spot in the object
version (after some patching up / boxing) -- rather than throwing an
exception.  If no overflow happens, you run *exactly* the same
bytecode as the current unprimed ops.  (I'm not sure how this would
interact with JIT compared to exceptions, though).  As soon as
overflow happens, you run code as if all of the operations were
primed, until function call exit.

I believe this is related to the approach used by TraceMonkey,
Firefox's Javascript compiler:
http://hacks.mozilla.org/2009/07/tracemonkey-overview/

Anyway, I'll leave this be now; I just wanted to mention the idea
since I hadn't seen it discussed.

-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread Mark Engelberg
On Mon, Jan 17, 2011 at 1:05 PM, Bob Hutchison hutch-li...@recursive.ca wrote:
 Numerical correctness, for some of us, is an overwhelming issue. This is 
 purely from experience... bad experience... 30+ years of bad experience in my 
 case :-) From my point of view, the approach Clojure is taking isn't 
 persuasive, not to say it couldn't be made persuasive.

Under the current proposal, you should never get an incorrect answer.
You might get an error, though.  It's a subtle difference, but this is
the main reason why the developers don't see it as a correctness
issue.  If your program runs, and gives you back an answer, it will
be correct.  If it crashes, you convert to the overflow version of
arithmetic, or typecast some of your numbers to bigints, and you'll
get the right answer.  I think a lot of the argument from both sides
boils down to how much you fear runtime crashes.

-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread Brian Goslinga
On Jan 17, 3:17 pm, Jason Wolfe ja...@w01fe.com wrote:
 I think you can.  Let me elaborate on my simplistic example.  Compile
 the code for a function twice -- once where everything works within
 primitives, and once where everything works with Objects -- and
 concatenate the bytecode together.  Start by running the primitive
 version.  On overflow, jump into the corresponding spot in the object
 version (after some patching up / boxing) -- rather than throwing an
 exception.  If no overflow happens, you run *exactly* the same
 bytecode as the current unprimed ops.  (I'm not sure how this would
 interact with JIT compared to exceptions, though).  As soon as
 overflow happens, you run code as if all of the operations were
 primed, until function call exit.
I'm not sure the JVM allows methods to do that; it might be possible
though.

This doesn't address the issue that a method has to decide up front
whether it is going to return a primitive or an object. I suppose you
could compile two versions of each function, but brings up two issues:
First, there would be massive code bloat, which might hurt the ability
of the code to be JITed well. Second, if a function is hinted to
return a primitive, it would almost certainly be an error to return
something that isn't a primitive.

-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread Jason Wolfe


On Jan 17, 3:24 pm, Brian Goslinga quickbasicg...@gmail.com wrote:
 On Jan 17, 3:17 pm, Jason Wolfe ja...@w01fe.com wrote: I think you can.  
 Let me elaborate on my simplistic example.  Compile
  the code for a function twice -- once where everything works within
  primitives, and once where everything works with Objects -- and
  concatenate the bytecode together.  Start by running the primitive
  version.  On overflow, jump into the corresponding spot in the object
  version (after some patching up / boxing) -- rather than throwing an
  exception.  If no overflow happens, you run *exactly* the same
  bytecode as the current unprimed ops.  (I'm not sure how this would
  interact with JIT compared to exceptions, though).  As soon as
  overflow happens, you run code as if all of the operations were
  primed, until function call exit.

 I'm not sure the JVM allows methods to do that; it might be possible
 though.

I believe it's possible, as long as the bytecodes are combined into a
single method body (due to the local jump restriction).

 This doesn't address the issue that a method has to decide up front
 whether it is going to return a primitive or an object. I suppose you
 could compile two versions of each function, but brings up two issues:
 First, there would be massive code bloat, which might hurt the ability
 of the code to be JITed well.

This is an issue.  I believe it might be avoidable with some tricks,
but I don't know enough about JVM internals to say for sure.  (I can
elaborate on ideas if requested).

 Second, if a function is hinted to
 return a primitive, it would almost certainly be an error to return
 something that isn't a primitive.

Correct.  As I mentioned earlier, if you hint the return as long, we
would always return a long (truncating/throwing if necessary).  This
is only talking about behavior *within* a function; the external
interface of the function is not up for interpretation.  And, taking a
step back, what people seem to be concerned with is long semantics
being inferred when that's not what they want.  If the user explicitly
declares the return value to be a long, this concern would no longer
apply.


-- 
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: Enhanced Primitive Support Syntax

2011-01-17 Thread Brian Goslinga
I'll also add that type inference wouldn't solve the problem, it would
just move the pain the the design of the type system and details
relating to it. The type system would probably be at least as complex
as Java generics to be something worthwhile if you do the type
inferencing for perf primarily and type checking incidentally; if you
want type checking primarily it would most likely be even more
complicated.

The changes in 1.3 don't really make the language more complicated; in
contrast, type inferencing would.

-- 
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: Enhanced Primitive Support Syntax

2011-01-16 Thread Sam Roberton
On 16 January 2011 05:35, Jason Wolfe ja...@w01fe.com wrote:
 (a) unsafe/incorrect value on overflow/fastest/unifiable* vs.
 (b) safe/error on overflow/fast/unifiable vs.
 (c) safe/promoting on overflow/slow/not-unifiable

 If I understand correctly, the issue with auto-promotion is that we
 have to box the output of an operation even if it turns out to fit in
 a long, since the compiler must specify whether the result will be
 long or Object.

 This is probably a stupid question, but since Clojure is already
 testing for overflow in (b) to throw an exception, would it be
 possible to jump into an alternative (c)-type compilation of the
 function just-in-time to promote on overflow instead?  It seems like
 this could achieve the performance of (b) while still allowing for
 auto-promotion (albeit perhaps with a performance hit in that case,
 code bloat, compromises about how many versions to compile, etc.).

When Clojure compiles your function, it emits JVM bytecode for a new
class which is then loaded by the classloader.  That JVM bytecode
defines a function (well, a method as far as the JVM is concerned)
which returns either a primitive type or Object.  Your suggestion
would involve redifining the class while it is executing.  That's not
possible on the JVM.  Even if it were possible -- your function now
returns Object instead of long.  But the variable that the result of
your function is about to be assigned to is a long, because that's
what your function used to be defined to return, and the next bytecode
operation in the calling code is the one that subtracts a primitive
long from a primitive long.  Now what?

Fundamentally, Clojure has to contend with the fact that the JVM as a
platform distinguishes between primitives and Objects.  The bytecode
operations which the Clojure compiler emits have to differ based on
that distinction.  Essentially, the distinction cannot be magicked
away, because JVM bytecode is going to statically enforce that we're
either working with a (long or double) or a (Long or BigInt or
BigDecimal or whatever), and never the twain shall meet.  So if we
ever want to be able to access the speed of the primitive bytecode
operations, then the primitive/Object distinction has to leak into
Clojure.  (Or we have to redefine or move away from the JVM.
Obviously not really an option, but I mention it to point out that the
reason Clojure has to make this decision is that it's a hosted
language.  That has a lot of benefits;  this is one of the trade-offs
we have to contend with in return.)

I think everyone agrees that it's important to make the speed of the
primitive bytecode operations available in Clojure (whether or not
it's the default), so that rules out the option of always doing
auto-promotion.  I think it's probably also agreed that allowing
unchecked overflow is not good (at least, no one seems to be arguing
for it).

So we're left with option (b) and a choice about the default behaviour
of the core library functions.  If we default to boxing and treating
everything as an Object then we get the nice comfy numeric tower that
we never have to worry about, but the default case suffers in
performance.  Otherwise, we default to primitive, and accept that if
we're dealing with numbers which might get bigger than Long.MAX_VALUE,
then we might need to explicitly use a BigInt to get contagion, or use
an operator like +' which will always deal with Objects.

By choosing to make speed the default preference in the core library
functions, I suppose there's more for Clojure programmers to think
about, because whenever you're dealing with numbers, you need to have
in the back of your mind the question of whether this might ever need
to be bigger than Long.MAX_VALUE, and so whether you might need +'
instead of +.  Then again, how often do you write code that might be
doing maths with numbers that big and not realise it?  For that
matter, how often do you write code that might be doing maths with
numbers that big and not spend time thinking carefully about its
performance anyway?

-- 
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: Enhanced Primitive Support Syntax

2011-01-16 Thread Armando Blancas
 Then again, how often do you write code that might be
 doing maths with numbers that big and not realise it?  For that
 matter, how often do you write code that might be doing maths with
 numbers that big and not spend time thinking carefully about its
 performance anyway?

This reminds me of a little joke:

Cooper: Honey, will you please - what are the odds of the Russians
attacking on a Thursday night?
--The Man with One Red Shoe (1985)

Having heard from various posters how reasonable it all is, and from
Rich now necessary [1], I still have a feeling that the implications
and consequences of the new semantics aren't well understood, and if
anything, any points of real concerned are downplayed. I'll second
Mark's concerns, above. Like others, I don't like to annotate and
postquote my way to the semantics I want, but that may be the easy
part. But I hope I'm wrong; I guess we'll see.

[1] (in this thread
http://groups.google.com/group/clojure/browse_thread/thread/c8c850595c91cc11/8a4eee5ac4eab3f9?lnk=gstq=autopromotion#8a4eee5ac4eab3f9)

-- 
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: Enhanced Primitive Support Syntax

2011-01-16 Thread Jason Wolfe

  (a) unsafe/incorrect value on overflow/fastest/unifiable* vs.
  (b) safe/error on overflow/fast/unifiable vs.
  (c) safe/promoting on overflow/slow/not-unifiable

  If I understand correctly, the issue with auto-promotion is that we
  have to box the output of an operation even if it turns out to fit in
  a long, since the compiler must specify whether the result will be
  long or Object.

  This is probably a stupid question, but since Clojure is already
  testing for overflow in (b) to throw an exception, would it be
  possible to jump into an alternative (c)-type compilation of the
  function just-in-time to promote on overflow instead?  It seems like
  this could achieve the performance of (b) while still allowing for
  auto-promotion (albeit perhaps with a performance hit in that case,
  code bloat, compromises about how many versions to compile, etc.).

 When Clojure compiles your function, it emits JVM bytecode for a new
 class which is then loaded by the classloader.  That JVM bytecode
 defines a function (well, a method as far as the JVM is concerned)
 which returns either a primitive type or Object.  Your suggestion
 would involve redifining the class while it is executing.  That's not
 possible on the JVM.  Even if it were possible -- your function now
 returns Object instead of long.  

If I understand correctly, the return type of your function is not up
for interpretation.  It is Object if undeclared, and primitive only if
declared -- so that is not a problem (if you ask for long, that's what
you'll get).  I am only talking about behavior within a single
function call -- no calling code needs to change.

Moreover, we do not need to redefine the class at run-time.  A simple
way to do this: when you compile a function with arithmetic
operations, concatenate bytecode for two versions: essentially, one
with the unprimed (exception-throwing) ops and one with the primed
(overflowing) ones.  Now, replace the exceptions in the first path
with local jumps into the second path.  There are probably ways to get
around generating two copies of the bytecode in advance, and making
such a unilateral shift to inefficient semantics, but I don't know
enough about JVM internals to say for sure.

-- 
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: Enhanced Primitive Support Syntax

2011-01-16 Thread Sean Corfield
On Sun, Jan 16, 2011 at 3:50 PM, Jason Wolfe ja...@w01fe.com wrote:
 Moreover, we do not need to redefine the class at run-time.  A simple
 way to do this: when you compile a function with arithmetic
 operations, concatenate bytecode for two versions: essentially, one
 with the unprimed (exception-throwing) ops and one with the primed
 (overflowing) ones.  Now, replace the exceptions in the first path
 with local jumps into the second path.  There are probably ways to get
 around generating two copies of the bytecode in advance, and making
 such a unilateral shift to inefficient semantics, but I don't know
 enough about JVM internals to say for sure.

The problem is that if you have an arbitrary form that can operate
entirely in primitives (some loop/recur perhaps) and you allow
primitives to magically convert to Objects in that code, then the
entire piece of code has to handle both primitives AND Objects and
every single sub-form must be capable of handling primitives as input
AND Objects as input and returning primitives if possible...

You can't have automatic promotion to Object from primitive and expect
any reasonable code to be generated that can maintain primitive
performance across arbitrary expressions. Either everything can work
with Objects - and you lose performance - or everything must be able
to work within primitives (and at most throw exceptions) and remain
performant.
-- 
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/

If you're not annoying somebody, you're not really alive.
-- Margaret Atwood

-- 
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: Enhanced Primitive Support Syntax

2011-01-16 Thread chris
Is it insane to suggest that perhaps clojure should work with scala
such that we can write both languages in the same file?

Use scala to do you strongly typed work and things where you are
really concerned that auto-promotion.  Let the language made for
helping a programmer lots of information about his/her code (and
perhaps overspecify the solution a gross amount) be used where that is
necessary.

Look, annotating shit in a clojure file to ensure you don't have a
crapload of boxing and inference going in is a large PITA.  So in
areas where you know you are going to need to do lots of things like
that, why wouldn't you use scala?

Specifying the type of everything going on is obviously, for a lot of
cases, grossly overspecifying the problem.  But what if we could just
write scala code in a clojure file or vice versa?  It seems that you
would bypass a lot of the odder 'improvements' to clojure for expert
users and just be better off.

Obviously one of the answers is 'if you think it is a good idea then
you do it' and I don't have the time.  But I know this:

1.  Meta programming is an insanely powerful tool for compressing
code.
2.  Type inference is insanely powerful for producing programs that do
'exactly' what the programming said they should.
3.  Clojure-in-java is fast and thus clojure-in-scala would be fast,
no language additions required.  And probably 30-50% shorter but
perhaps not more than that.
4.  Type annotations are as bad as C programming in terms of verbosity
and to write fast code you need them.  A little inference would make a
large difference.

Types in a lisp-like language suck.  There isn't a way around it.
Lets use a powerful type-inference tool where appropriate and ditch
them completely where it is inappropriate.

You want a hover-over or tooltip to tell you what type something is
producing or taking (or to guarantee details about what you are
doing)?  Use scala.

You want to write extremely compressed code in a way that is very easy
to change and specifies as little of the answer to the problem as
possible (thus giving a lot of leeway for implementation and
extension)?  Use clojure.

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: Enhanced Primitive Support Syntax

2011-01-15 Thread Saul Hazledine
On Jan 15, 2:40 am, Armando Blancas armando_blan...@yahoo.com wrote:
 They used to give you compile switches for that kind of stuff, not
 hope and wholesome wishes. Seems like every performance improvements
 makes the language more complex, uglier or both.


I don't feel strongly about integer limits at all and am always
surprised when this comes up. I did scientific programming on a 32 bit
platform for several years and never met anyone who hit big problems
with fixed size integers. For illustration, Long.max is:

   9 223 372 036 854 775 807

which is so much bigger than I was used to. I know encryption requires
BigInteger but I have yet to see a native clojure encryption library.
It would help people like me understand the debate if some mainstream
examples of applications requiring (seamless) BigInteger support could
be identified.

Saul

-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Bob Hutchison
I'm going to re-organise this a bit…

 On Jan 14, 2:40 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote:
 Debatable it is, endlessly. ;)  So Clojure committers made a choice.
  Hopefully, they have made a choice that has:

I agree that they've made a choice, and I really don't want to be too critical 
here. However, since Clojure 1.3 is still in an alpha stage, maybe this 
discussion can still contribute something. Maybe what I'm saying is that I want 
to stay constructive and that there's maybe still time to be constructive.

 
 * a small positive effect (better performance with less effort) on a
 majority of users
 
 * a small negative effect (worse performance, extra effort) on a minority

These goals are good, but I don't know that the approach taken achieves them.

In my experience, errors are the problem and we should be avoiding them, almost 
at all costs. Numbers are confusing to people. Numbers approximated on a 
computer are far more confusing. How many times do you see threads discussing 
how a compiler is buggy because it can't divide two numbers and get the right 
answer? I've been doing this stuff for years and I can come up with an awful 
lot of amusing and/or horribly nasty examples. But I don't think this needs to 
be re-established.

Given my experience I *strongly* lean towards not making a 'mistake' due to 
compiler optimisations. In other words, I'd be very annoyed, and I'd expect 
others to be annoyed too, if a numerical error was introduced to one of my 
programs because of an unexpected, silent, compiler optimisation.

Secondly, Clojure has already established that we will use type annotations to 
signal to the compiler what's what. When we annotate, we are relaxing our 
requirements on the compiler to not make a mistake by assuming that 
responsibility ourselves.

I would suggest the following:

1) if there's type annotation on both values of, say, an addition, then the 
optimised version can be used. If there isn't, or the compiler isn't sure, then 
use safe operations.

2) if the compiler isn't cooperating (because it isn't sure what's going on) we 
should be helping it by again assuming the responsibility of being right and 
marking the operator, say with a tick.

And yes, this likely has problems too. I'm not saying that this is an issue 
with easy solutions.

We're heading for a hodgepodge of annotation purposes, some for optimisation, 
some for correctness (and one of these days I'll mention what I think of the 
@/deref thing :-) And now we're pretty much guaranteed ugly code no matter 
what. Though I'd prefer no ugliness, I'd trade ugly code for speed, but I'd 
rather not for correctness.

And there's a practical problem with mixed annotation purposes. If you want to 
track down a bug you can't just remove all annotations temporarily. You'd have 
to remove some and add others. Not looking forward to that. Maybe a macro: 
make-this-safe could be written. Hmm. Maybe a 'defn-safe' would be something to 
think about???

This is also the kind of thing that you just can't fix later. Imagine how we'll 
feel in ten or twenty years about this decision.


 
 -S
 
On 2011-01-14, at 8:40 PM, Armando Blancas wrote:

 They used to give you compile switches for that kind of stuff, not
 hope and wholesome wishes. Seems like every performance improvements
 makes the language more complex, uglier or both.
 


Compiler switches were/are problematic too, but at least they are explicit and 
have to be *added*.

Cheers,
Bob


Bob Hutchison
Recursive Design Inc.
http://www.recursive.ca/
weblog: http://xampl.com/so




-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Stefan Kamphausen
Hi,

just for the record: from what I have done in the past I wholeheartedly 
agree with Bob.  Of course the developers of Clojure have the final say on 
this.  It's just my 2ct.

Kind regards,
Stefan

-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread David Powell

Bob Hutchison said:

 In other words, I'd be very
 annoyed, and I'd expect others to be annoyed too, if a numerical
 error was introduced to one of my programs because of an unexpected, silent, 
 compiler optimisation.

Just to be clear, Clojure 1.3-alpha does not introduce numerical
errors, unless you explicitly ask for them; it throws a
RuntimeException - which I guess is analogous to it being a
dynamically-typed language and throwing RuntimeExceptions to signal
type errors.

  user= (* 1000 1000)
  ArithmeticException integer overflow  clojure.lang.Numbers.throwIntOverflow 
(Numbers.java:1583)

  user= (*' 1000 1000)
  100N

  user= (* 1000 1000N)
  100N

  user= (unchecked-multiply 1000 1000)
  1864712049423024128

-- 
Dave

-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Lee Spector

On Jan 15, 2011, at 8:29 AM, Saul Hazledine wrote:

 It would help people like me understand the debate if some mainstream
 examples of applications requiring (seamless) BigInteger support could
 be identified.


I doubt that many will consider this mainstream, but I evolve programs using 
genetic programming techniques and I've found that in this context BigIntegers 
can arise in all sorts of unexpected and weird and wonderful and sometimes 
adaptive ways. 

I still haven't figured out exactly what the 1.3 changes will mean for this 
work -- maybe it'll be fine or even better -- but I've liked not having to 
think about integer sizes much at all previously (as in Common Lisp, where the 
handling of complex numbers is also nice).

 -Lee

-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Stuart Halloway
 I think this is looking at the situation backwards. I don't want
 BigInts, why should I want *them*? Nor longs or whatever for that
 matter. What I want is a numerical tower and a language that can
 handle it correctly, without blowing up, and if possible with clean
 code. I can type 9223372036854775807 or something bigger in a
 spreadsheet and get 9.22337203685478E+018, and take it from there.
 Now, I don't know if spreadsheet programmers *want* doubles, but
 something correct (if less precise) must be done depending on what *I,
 the user* wants to do.

The spreadsheet example may be a useful one. Clojure is a language you could 
write a spreadsheet in. Would you want to use a spreadsheet written entirely in 
a JVM language that did not provide access to the primitives?

 Now we face the choice of putting limits on what our users can do, use
 a different set of operators, or decide that we want BigInts. Again,
 this isn't about wanting bigints, that's a red herring. Part of the
 problem is the complex, confusing, and sometimes quite mysterious Type
 System that's been creeping into Clojure for the sake of performance.

Clojure is not getting a type system. nor is the behavior in 1.3 complex. It 
can be confusing, because it is addressing a multifaceted problem, and it 
certainly is mysterious, because (1) we haven't spent enough effort documenting 
it, and (2) lots of people have misdocumented it.

I'll make a documentation update higher priority; hopefully that will help.

 Another is the conflicted attitude of being an untyped language: a
 kind of guilty pleasure with the remorse it brings of all those
 reflective calls and boxing/unboxing, whose negative effects on
 performance supposedly makes the language lose credibility.

The Clojure design process is not about achieving credibility, it is about 
solving problems. Credibility has followed, and will continue to follow, to the 
extent that Clojure solves problems well.

Stu

Stuart Halloway
Clojure/core
http://clojure.com


-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Mark Engelberg
On Sat, Jan 15, 2011 at 1:06 PM, Stuart Halloway
stuart.hallo...@gmail.com wrote:
 We have thought about this quite a bit, and an argument from one axis only 
 (e.g safe/unsafe) that doesn't even mention some of  the other axes is not 
 likely to be persuasive. Would be more interesting to see a new axis we 
 haven't thought of...

Here's an axis that hasn't gotten much discussion:  How evident is the
behavior of Clojure code, and what features help and hinder this
clarity?

Clojure is a dynamically typed language, which means that generally
speaking, it is not obvious what the type of a given variable is,
since there aren't annotations immediately prior to the variable
telling you what it must be.  Similarly, a Clojure IDE does not offer
any way to to hover over a variable and see what the type is.  There
is a lot of freedom that comes with this, but the cost is that a
dynamic programmer must be careful to document in some way what kinds
of things are acceptable inputs, and what kinds of promises are made
of the outputs.  The compiler can't check this, so it's up to the
programmer.  As Clojure programmers, we take on the responsibility of
tracking a certain amount of unseen information that isn't readily
evident from the code itself, but there's a limit to how much
responsibility programmers can take on before programs become brittle,
so new features should take this axis into account.

Primitives are especially problematic because there is no good way to
determine whether something is a primitive or not.  Consider the
following interactions in the 1.1 REPL:
user (type 1)
java.lang.Integer
user (type (int 1))
java.lang.Integer
Any features involving primitives should be assessed from the
standpoint that it is extremely difficult to know from looking at code
whether something is a primitive or not.  Many of the new features
(e.g., static functions can now return primitives, literals are
primitives, but numbers that get stored in collections or cross
certain kinds of function boundaries are not), means that you'll
frequently end up with a mixture of primitives and non-primitives, and
it won't always be obvious which is which.

When designing math operators that behave one way for longs and
another for bigints, one question that needs to be asked is: How
apparent will it be whether a variable represents a long or a bigint?
If it's not apparent, how will the programmer know which behavior to
expect?  Is there any tooling that can help make this more
discoverable?  One possibility is that Clojure programmers will need
to evolve ways to track this information, perhaps by explicitly
commenting in code whether a function can gracefully handle both longs
and bigints.  On the other hand, there's already a history in Clojure
and similar languages of just documenting certain vars as numbers
without needing to get more precise than that, so this could be a
painful transition for many programmers who are not used to thinking
about specifying their numeric types in greater detail than that.

Because it's difficult to do typeflow analysis within a
dynamically-typed language as Clojure, this clarity axis also comes
into play when thinking about what sorts of burdens are going to be
placed on library developers.  As a case in point, I developed the
expt function in clojure.contrib.math because I was surprised when I
first came to Clojure that no generic exponentiation operator existed
in the language.  The expt in contrib handles all of Clojure's numeric
types seamlessly.  But what am I supposed to do with expt in Clojure
1.3?  New expectations are being created with the new model -- some
people will expect expt with primitives to return primitives; some
will expect computation with longs to return bigints when necessary,
since exponentiation frequently overflows.  Do I need to provide an
expt and expt' function to make both camps happy?  (For that matter,
is there even a way to overload expt for both primitive longs and
primitive doubles, or do I need to make separate expt-long and
expt-double functions?)  Are we going to see a proliferation of
variations for all mathematical functions once we start going down
this road?

This is an axis I think about a lot, and I hope this is something that
the Clojure dev team is carefully considering as well.

-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Ken Wesson
On Sat, Jan 15, 2011 at 9:40 PM, Mark Engelberg
mark.engelb...@gmail.com wrote:
 On Sat, Jan 15, 2011 at 1:06 PM, Stuart Halloway
 stuart.hallo...@gmail.com wrote:
 We have thought about this quite a bit, and an argument from one axis only 
 (e.g safe/unsafe) that doesn't even mention some of  the other axes is not 
 likely to be persuasive. Would be more interesting to see a new axis we 
 haven't thought of...

 Here's an axis that hasn't gotten much discussion:  How evident is the
 behavior of Clojure code, and what features help and hinder this
 clarity?

[massive snip]

 This is an axis I think about a lot, and I hope this is something that
 the Clojure dev team is carefully considering as well.

+1 to all of that.

-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Michael Gardner
On Jan 15, 2011, at 4:04 PM, Stuart Halloway wrote:

 I'll make a documentation update higher priority; hopefully that will help.

This should help. I feel like the discussion is going in circles because 
there's no single, official source that summarizes exactly what is happening 
with numerics in 1.3. (I know about 
http://www.assembla.com/wiki/show/clojure/Enhanced_Primitive_Support, but it's 
terse and a bit confusing.)

-- 
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: Enhanced Primitive Support Syntax

2011-01-15 Thread Jason Wolfe
 (a) unsafe/incorrect value on overflow/fastest/unifiable* vs.
 (b) safe/error on overflow/fast/unifiable vs.
 (c) safe/promoting on overflow/slow/not-unifiable

If I understand correctly, the issue with auto-promotion is that we
have to box the output of an operation even if it turns out to fit in
a long, since the compiler must specify whether the result will be
long or Object.

This is probably a stupid question, but since Clojure is already
testing for overflow in (b) to throw an exception, would it be
possible to jump into an alternative (c)-type compilation of the
function just-in-time to promote on overflow instead?  It seems like
this could achieve the performance of (b) while still allowing for
auto-promotion (albeit perhaps with a performance hit in that case,
code bloat, compromises about how many versions to compile, etc.).

For what it's worth, I'm personally happy with the approach of the
current alpha.

-- 
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: Enhanced Primitive Support Syntax

2011-01-14 Thread Stuart Sierra
Debatable it is, endlessly. ;)  So Clojure committers made a choice. 
 Hopefully, they have made a choice that has:

* a small positive effect (better performance with less effort) on a 
majority of users

* a small negative effect (worse performance, extra effort) on a minority

-S

-- 
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: Enhanced Primitive Support Syntax

2011-01-14 Thread Armando Blancas
They used to give you compile switches for that kind of stuff, not
hope and wholesome wishes. Seems like every performance improvements
makes the language more complex, uglier or both.

On Jan 14, 2:40 pm, Stuart Sierra the.stuart.sie...@gmail.com wrote:
 Debatable it is, endlessly. ;)  So Clojure committers made a choice.
  Hopefully, they have made a choice that has:

 * a small positive effect (better performance with less effort) on a
 majority of users

 * a small negative effect (worse performance, extra effort) on a minority

 -S

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


Enhanced Primitive Support Syntax

2011-01-13 Thread RJ Nowling
Hi all,

I've been reading about the changes to Clojure that are occurring with
regards to improving performance of arithmetic operations.  For
example, + no longer auto promotes and +' has been introduced as an
auto-promoting addition operator.

The idea of introducing additional syntax is a bit odd to me, so I had
thought that it could be solved by setting an environmental variable
for the namespace and the use of macros.  For example, maybe set
*enhanced-primitive-support* true or false will determine the behavior
of the operators (+, -, etc.) for an entire namespace.  If a user
wants a different set of behaviors for a block of code in that
namespaces, they could wrap the code in a macro called something like
enhanced-primitive-support or old-primitive-support:

(enhanced-primitive-support (+ a b) )

I was wondering why an approach like this was not taken?

Thanks,
RJ

-- 
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: Enhanced Primitive Support Syntax

2011-01-13 Thread Stuart Sierra
The goal of primitive math is better performance in the common case. The 
implementation makes the assumptions that Java long is big enough for nearly 
all cases, and that auto-promotion to BigInteger (and the resulting 
performance hit) is rarely desirable.

The + function still promotes, it just promotes everything to long or 
double. If you want BigInts or BigDecimals, just insert one of them into the 
calculation, and everything else will get promoted to BigInt or BigDecimal.

The only difference between + and +' is that +' will promote to BigInt if 
you overflow a long, whereas + will thrown an exception.

-- 
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: Enhanced Primitive Support Syntax

2011-01-13 Thread Ken Wesson
On Thu, Jan 13, 2011 at 7:28 PM, Stuart Sierra
the.stuart.sie...@gmail.com wrote:
 The goal of primitive math is better performance in the common case.

Of course, this better performance is not needed in the common case,
IMO, but only in hotspots that do number crunching, where people
already optimize using primitive locals, coercion, and unchecked-foo.

 The implementation makes the assumptions that Java long is big enough for
 nearly all cases

It also makes the assumption that the Java long is as fast as native
arithmetic. Which, on a lot of 32-bit hardware, it won't be.

 and that auto-promotion to BigInteger (and the resulting performance hit) is
 rarely desirable.

Debatable. I, for one, prefer to have unadorned arithmetic be correct
at the expense of a little speed, while still having a way to get the
speed in performance-critical parts of my code.

-- 
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: Enhanced primitive support - redux

2010-06-27 Thread Daniel
Thirded.

On Jun 25, 4:55 pm, Mark Engelberg mark.engelb...@gmail.com wrote:
 On Fri, Jun 25, 2010 at 2:39 PM, Garth Sheldon-Coulson g...@mit.edu wrote:
  Personally, I think (= 3 3M) = true and (= 3/10 0.3M) = true would be nice
  to have, given that (= 3 3N) = true. Both are currently false in equiv. I
  also think (= 3.0M 3.00M) = true would be nice. As Rich said, there's no
  particular reason to have Clojure = work exactly like Java .equals(). I
  think all it would take is a call to .stripTrailingZeros() on each =
  comparison of a BigDecimal.

 Yeah, if it's technically feasible, this definitely makes the most
 mathematical sense.

-- 
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: Enhanced primitive support - redux

2010-06-27 Thread Daniel
If there is some sort of new numeric tower on the plate, what would be
some desirable properties?

On Jun 25, 10:58 pm, Andrzej ndrwr...@googlemail.com wrote:
 On Sat, Jun 26, 2010 at 4:04 AM, Rich Hickey richhic...@gmail.com wrote:
  equiv, the revenge of num

 Has it already been decided that some sort of this new numeric tower
 will find its way into Clojure?

 Andrzej

-- 
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: Enhanced primitive support - redux

2010-06-26 Thread B Smith-Mannschott
On Sat, Jun 26, 2010 at 05:58, Andrzej ndrwr...@googlemail.com wrote:
 On Sat, Jun 26, 2010 at 4:04 AM, Rich Hickey richhic...@gmail.com wrote:
 equiv, the revenge of num

 Has it already been decided that some sort of this new numeric tower
 will find its way into Clojure?

 Personally, I think this change will open a can of worms and make
 programming in Clojure more difficult and error prone.

 I don't think there is a nice and clean solution to the numeric
 problem (Clojure is not the first language tackling it) but there are
 two possibilities that could produce an acceptable trade off:
 - using boxed math everywhere and optimizing performance by storing
 preallocated Integers in a cache,

This was suggested on the previous thread on this topic as well, but
I don't think it was pointed out that *Java already does this*.

See the inner class IntegerCache at line 608:

http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/3956cdee6712/src/share/classes/java/lang/Integer.java

And for Long as well (line 543):

http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/3956cdee6712/src/share/classes/java/lang/Long.java


 - using both boxed and primitive math but keeping the boundary between
 them as explicit as possible (different operators, no automatic
 conversion etc.). Existing operators should default to boxed math (for
 runtime safety and compatibility).

 Andrzej

 --
 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: Enhanced primitive support - redux

2010-06-26 Thread Stefan Kamphausen
Hi,

On 25 Jun., 21:04, Rich Hickey richhic...@gmail.com wrote:
 equiv, the revenge of num
[...]
 Feedback welcome,

sorry, no feedback, but one question which is rather important to me:
will this make it into Clojure 1.2?

Kind regards,
Stefan

-- 
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: Enhanced primitive support - redux

2010-06-26 Thread Nicolas Oury
I think I pointed it out, and I reiterate it will probably not improve
performance a lot (Except if you use always the 5 same numbers).

On Sat, Jun 26, 2010 at 7:59 AM, B Smith-Mannschott
bsmith.o...@gmail.comwrote:

 This was suggested on the previous thread on this topic as well, but
 I don't think it was pointed out that *Java already does this*.


-- 
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: Enhanced primitive support - redux

2010-06-26 Thread Mike Meyer
[Format recovered from top posting.]

Nicolas Oury nicolas.o...@gmail.com wrote:
On Sat, Jun 26, 2010 at 7:59 AM, B Smith-Mannschott
bsmith.o...@gmail.comwrote:

 This was suggested on the previous thread on this topic as well, but
 I don't think it was pointed out that *Java already does this*.

Doesn't matter if clojure is boxing them as well. Yes, all the boxes will point 
to the cache, but you still have different boxes, and allocating those is the 
problem.

I think I pointed it out, and I reiterate it will probably not improve
performance a lot (Except if you use always the 5 same numbers).

Reiteration won't make it true.
-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

-- 
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: Enhanced primitive support - redux

2010-06-26 Thread Andrzej
On Sat, Jun 26, 2010 at 3:59 PM, B Smith-Mannschott
bsmith.o...@gmail.com wrote:

 This was suggested on the previous thread on this topic as well, but
 I don't think it was pointed out that *Java already does this*.

 See the inner class IntegerCache at line 608:

 http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/3956cdee6712/src/share/classes/java/lang/Integer.java

Thank you. I wasn't aware of it.

It is not exactly what I meant, though. The above Java code
preallocates some low Integers, that are likely to be encountered in
actual programs. It obviously doesn't help at all when you happen to
use other numbers.

What I'd rather like to have is an array of N preallocated objects
waiting to be assigned values and used. This way an allocation cycle
could be triggered every N Integer constructor calls and all boxes
used in a single procedure would be gathered in one place.

Andrzej

-- 
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: Enhanced primitive support - redux

2010-06-26 Thread Nicolas Oury
http://tech.puredanger.com/2007/02/01/valueof/

http://tech.puredanger.com/2007/02/01/valueof/Apparently, a program that
only access 1 integer (0) is only twice as fast when caching.
We are very far from the *10/20 that occurs.

On Sat, Jun 26, 2010 at 2:04 PM, Mike Meyer 
mwm-keyword-googlegroups.620...@mired.org wrote:


 I think I pointed it out, and I reiterate it will probably not improve
 performance a lot (Except if you use always the 5 same numbers).

 Reiteration won't make it true.

-- 
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: Enhanced primitive support - redux

2010-06-26 Thread Nicolas Oury
And, by the way, after having looked into the compiler source, the current
Master already uses the valeOf function.

On Sat, Jun 26, 2010 at 2:31 PM, Nicolas Oury nicolas.o...@gmail.comwrote:

 http://tech.puredanger.com/2007/02/01/valueof/

 http://tech.puredanger.com/2007/02/01/valueof/Apparently, a program that
 only access 1 integer (0) is only twice as fast when caching.
 We are very far from the *10/20 that occurs.

 On Sat, Jun 26, 2010 at 2:04 PM, Mike Meyer 
 mwm-keyword-googlegroups.620...@mired.org wrote:


 I think I pointed it out, and I reiterate it will probably not improve
 performance a lot (Except if you use always the 5 same numbers).

 Reiteration won't make it true.




-- 
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: Enhanced primitive support - redux

2010-06-26 Thread David Powell

Hi,

Re: caching boxed ints:

I think I pointed it out, and I reiterate it will probably not improve
performance a lot (Except if you use always the 5 same numbers).

 Reiteration won't make it true.

At about 10m - 12m into this video, Cliff Click suggests that Java's
caching of Integer objects might do some harm to performance because
it prevents the JIT from being able to do inlining and escape
analysis.

http://www.infoq.com/presentations/click-fast-bytecodes-funny-languages


-- 
Dave

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


Enhanced primitive support - redux

2010-06-25 Thread Rich Hickey

equiv, the revenge of num

The latest revision of primitive support is in the equiv branch. It  
takes the approach of num, with no auto-promotion, and bigint  
contagion, and adds several things to better support contagion. I  
think contagion is the best way to continue to support polymorphic  
numeric code, something I consider important.


Contagion has several issues. First and foremost, it means that it it  
will be possible for 42 and 42N to be produced in the course of normal  
operations, so strict type-specific equality is not a good match. The  
equiv branch brings back equivalence-based =, with a slightly tighter  
notion of =, supporting only similar categories of numbers, so (= 42  
42.0) = false, but (= 42 42N) = true. == is still available.


The second problem is the use of numbers (and collections of numbers)  
as keys in hash maps and members of hash sets. We already had an issue  
here, as there wasn't completely uniform boxing, and there will always  
be the possibility of numbers from the outside. The equal branch tried  
to use consistent boxing and type-specific =, but it was still open to  
mismatch with numbers from outside. The equiv branch extends = to keys  
and set members when used from Clojure, i.e. Clojure get and contains  
will use = logic, while the Java get and containsKey will  
use .equals(). I.e. we will still satisfy the semantics of Java when  
used through the Java APIs, but nothing said the Clojure API must  
match those semantics. When combined with the new BigInt class (see  
below), this will allow you to look up (and find!) the integer 42 with  
either 42 or 42N.


The equiv branch also has a new BigInt type. This is strictly  
necessary for this scheme, as Java's BigIntegers and Longs can produce  
different hashCodes for the same values. In addition to matching  
hashCode support, the BigInt class opens the door to better  
performance when used with numbers long-or-smaller. These performance  
enhancements have not yet been made.


More details have been added to the top here:

https://www.assembla.com/wiki/show/b4-TTcvBSr3RAZeJe5aVNr/Enhanced_Primitive_Support

Code is here:

http://github.com/richhickey/clojure/commits/equiv


Feedback welcome,

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: Enhanced primitive support - redux

2010-06-25 Thread Garth Sheldon-Coulson
This looks excellent.

I'd like to re-raise a question I had a few days ago: Will this ultimately
come to affect floats, too?

In particular:

1) If there is going to be BigInt contagion, why not BigDecimal contagion?

user= (* 4 5)
20
user= (* 4 5N)
20N

but

user= (* 4.0 5.0)
20.0
user= (* 4.0 5.0M) ;no contagion
20.0
user= (* 4.0M 5.0M)
20.00M
user= (* 4.0 5.001M) ;not even when it's needed
20.0
user= (* 4.0M 5.001M)
20.0040M

2) Will the same reasoning that produced BigInt give us a BigDec with a
better hashCode() than that of BigDecimal?

user= (hash 4343434343)
48467046
user= (hash (BigInteger. 4343434343)) ;not very nice
48467078
user= (hash 4343434343N) ;nice as of equiv branch
48467046

but

user= (hash 4343.4343)
1861754824
user= (hash 4343.4343M) ;not very nice
1346464637

user= (defn -hashCode [this]
  (let [dv (.doubleValue this)]
(if (== this dv)
  (.hashCode dv)
  (.hashCode this
#'user/-hashCode

user= (hash 4343.4343)
1861754824
user= (-hashCode 4343.4343M) ;nicer
1861754824

Garth


On Fri, Jun 25, 2010 at 3:04 PM, Rich Hickey richhic...@gmail.com wrote:

 equiv, the revenge of num

 The latest revision of primitive support is in the equiv branch. It takes
 the approach of num, with no auto-promotion, and bigint contagion, and adds
 several things to better support contagion. I think contagion is the best
 way to continue to support polymorphic numeric code, something I consider
 important.

 Contagion has several issues. First and foremost, it means that it it will
 be possible for 42 and 42N to be produced in the course of normal
 operations, so strict type-specific equality is not a good match. The equiv
 branch brings back equivalence-based =, with a slightly tighter notion of =,
 supporting only similar categories of numbers, so (= 42 42.0) = false, but
 (= 42 42N) = true. == is still available.

 The second problem is the use of numbers (and collections of numbers) as
 keys in hash maps and members of hash sets. We already had an issue here, as
 there wasn't completely uniform boxing, and there will always be the
 possibility of numbers from the outside. The equal branch tried to use
 consistent boxing and type-specific =, but it was still open to mismatch
 with numbers from outside. The equiv branch extends = to keys and set
 members when used from Clojure, i.e. Clojure get and contains will use =
 logic, while the Java get and containsKey will use .equals(). I.e. we will
 still satisfy the semantics of Java when used through the Java APIs, but
 nothing said the Clojure API must match those semantics. When combined with
 the new BigInt class (see below), this will allow you to look up (and find!)
 the integer 42 with either 42 or 42N.

 The equiv branch also has a new BigInt type. This is strictly necessary for
 this scheme, as Java's BigIntegers and Longs can produce different hashCodes
 for the same values. In addition to matching hashCode support, the BigInt
 class opens the door to better performance when used with numbers
 long-or-smaller. These performance enhancements have not yet been made.

 More details have been added to the top here:


 https://www.assembla.com/wiki/show/b4-TTcvBSr3RAZeJe5aVNr/Enhanced_Primitive_Support

 Code is here:

 http://github.com/richhickey/clojure/commits/equiv


 Feedback welcome,

 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.comclojure%2bunsubscr...@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: Enhanced primitive support - redux

2010-06-25 Thread Nicolas Oury
Amazingly good ideas.
Will try it tomorrow.

On Fri, Jun 25, 2010 at 8:04 PM, Rich Hickey richhic...@gmail.com wrote:

 equiv, the revenge of num

 The latest revision of primitive support is in the equiv branch. It takes
 the approach of num, with no auto-promotion, and bigint contagion, and adds
 several things to better support contagion. I think contagion is the best
 way to continue to support polymorphic numeric code, something I consider
 important.

 Contagion has several issues. First and foremost, it means that it it will
 be possible for 42 and 42N to be produced in the course of normal
 operations, so strict type-specific equality is not a good match. The equiv
 branch brings back equivalence-based =, with a slightly tighter notion of =,
 supporting only similar categories of numbers, so (= 42 42.0) = false, but
 (= 42 42N) = true. == is still available.

 The second problem is the use of numbers (and collections of numbers) as
 keys in hash maps and members of hash sets. We already had an issue here, as
 there wasn't completely uniform boxing, and there will always be the
 possibility of numbers from the outside. The equal branch tried to use
 consistent boxing and type-specific =, but it was still open to mismatch
 with numbers from outside. The equiv branch extends = to keys and set
 members when used from Clojure, i.e. Clojure get and contains will use =
 logic, while the Java get and containsKey will use .equals(). I.e. we will
 still satisfy the semantics of Java when used through the Java APIs, but
 nothing said the Clojure API must match those semantics. When combined with
 the new BigInt class (see below), this will allow you to look up (and find!)
 the integer 42 with either 42 or 42N.

 The equiv branch also has a new BigInt type. This is strictly necessary for
 this scheme, as Java's BigIntegers and Longs can produce different hashCodes
 for the same values. In addition to matching hashCode support, the BigInt
 class opens the door to better performance when used with numbers
 long-or-smaller. These performance enhancements have not yet been made.

 More details have been added to the top here:


 https://www.assembla.com/wiki/show/b4-TTcvBSr3RAZeJe5aVNr/Enhanced_Primitive_Support

 Code is here:

 http://github.com/richhickey/clojure/commits/equiv


 Feedback welcome,

 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.comclojure%2bunsubscr...@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: Enhanced primitive support - redux

2010-06-25 Thread Garth Sheldon-Coulson
Following up, point (2) in my previous message would be helpful only if =
were changed so that it looked at the stripTrailingZeros() value of
BigDecimals. I would advocate this in any case, because the following
behavior appears silly to me (is it useful to anyone?):

user= (== 434343.00M 434343.0M) ;BigDecimal works this way, apparently
false
user= (= 434343.00M 434343.0M) ;odd, however
false
user= (= 434343.00M 434343.0)
false
user= (== 434343.00M 434343.0) ;even odder, in my opinion, given the above
true
user= (= (.stripTrailingZeros 434343.00M) (.stripTrailingZeros 434343.0M))
;shouldn't = default to this?
true

Garth

On Fri, Jun 25, 2010 at 4:18 PM, Garth Sheldon-Coulson g...@mit.edu wrote:

 This looks excellent.

 I'd like to re-raise a question I had a few days ago: Will this ultimately
 come to affect floats, too?

 In particular:

 1) If there is going to be BigInt contagion, why not BigDecimal contagion?

 user= (* 4 5)
 20
 user= (* 4 5N)
 20N

 but

 user= (* 4.0 5.0)
 20.0
 user= (* 4.0 5.0M) ;no contagion
 20.0
 user= (* 4.0M 5.0M)
 20.00M
 user= (* 4.0 5.001M) ;not even when it's needed
 20.0
 user= (* 4.0M 5.001M)
 20.0040M

 2) Will the same reasoning that produced BigInt give us a BigDec with a
 better hashCode() than that of BigDecimal?

 user= (hash 4343434343)
 48467046
 user= (hash (BigInteger. 4343434343)) ;not very nice
 48467078
 user= (hash 4343434343N) ;nice as of equiv branch
 48467046

 but

 user= (hash 4343.4343)
 1861754824
 user= (hash 4343.4343M) ;not very nice
 1346464637

 user= (defn -hashCode [this]
   (let [dv (.doubleValue this)]
 (if (== this dv)
   (.hashCode dv)
   (.hashCode this
 #'user/-hashCode

 user= (hash 4343.4343)
 1861754824
 user= (-hashCode 4343.4343M) ;nicer
 1861754824

 Garth



 On Fri, Jun 25, 2010 at 3:04 PM, Rich Hickey richhic...@gmail.com wrote:

 equiv, the revenge of num

 The latest revision of primitive support is in the equiv branch. It takes
 the approach of num, with no auto-promotion, and bigint contagion, and adds
 several things to better support contagion. I think contagion is the best
 way to continue to support polymorphic numeric code, something I consider
 important.

 Contagion has several issues. First and foremost, it means that it it will
 be possible for 42 and 42N to be produced in the course of normal
 operations, so strict type-specific equality is not a good match. The equiv
 branch brings back equivalence-based =, with a slightly tighter notion of =,
 supporting only similar categories of numbers, so (= 42 42.0) = false, but
 (= 42 42N) = true. == is still available.

 The second problem is the use of numbers (and collections of numbers) as
 keys in hash maps and members of hash sets. We already had an issue here, as
 there wasn't completely uniform boxing, and there will always be the
 possibility of numbers from the outside. The equal branch tried to use
 consistent boxing and type-specific =, but it was still open to mismatch
 with numbers from outside. The equiv branch extends = to keys and set
 members when used from Clojure, i.e. Clojure get and contains will use =
 logic, while the Java get and containsKey will use .equals(). I.e. we will
 still satisfy the semantics of Java when used through the Java APIs, but
 nothing said the Clojure API must match those semantics. When combined with
 the new BigInt class (see below), this will allow you to look up (and find!)
 the integer 42 with either 42 or 42N.

 The equiv branch also has a new BigInt type. This is strictly necessary
 for this scheme, as Java's BigIntegers and Longs can produce different
 hashCodes for the same values. In addition to matching hashCode support, the
 BigInt class opens the door to better performance when used with numbers
 long-or-smaller. These performance enhancements have not yet been made.

 More details have been added to the top here:


 https://www.assembla.com/wiki/show/b4-TTcvBSr3RAZeJe5aVNr/Enhanced_Primitive_Support

 Code is here:

 http://github.com/richhickey/clojure/commits/equiv


 Feedback welcome,

 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.comclojure%2bunsubscr...@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

Re: Enhanced primitive support - redux

2010-06-25 Thread Mark Engelberg
floats and doubles are inexact numbers and ratios, ints, longs,
bigints, and bigdecimals are exact numbers.
The expected behavior is that inexact things contaminate exact things,
because now the result is inexact.  This is what Clojure does.

On Fri, Jun 25, 2010 at 1:18 PM, Garth Sheldon-Coulson g...@mit.edu wrote:
 1) If there is going to be BigInt contagion, why not BigDecimal contagion?

doubles contaminate bigdecimals, not the other way around.  That's how
it should be.

 2) Will the same reasoning that produced BigInt give us a BigDec with a
 better hashCode() than that of BigDecimal?

You don't want the hashCode of bigdecimal to match the corresponding
double.  They aren't equal, so they shouldn't have the same hashcode.
They aren't equal because one is exact and one is inexact.

Now, one interesting question is whether the hashCode of 40.0M should
match the hashCode for 40N, because they are two exact numbers that
represent the same value.

-- 
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: Enhanced primitive support - redux

2010-06-25 Thread Mark Engelberg
A couple points of clarification:

On Fri, Jun 25, 2010 at 1:35 PM, Mark Engelberg
mark.engelb...@gmail.com wrote:
 You don't want the hashCode of bigdecimal to match the corresponding
 double.  They aren't equal, so they shouldn't have the same hashcode.
 They aren't equal because one is exact and one is inexact.

I should have said they shouldn't be equal based on Rich Hickey's
explanation that from now on (= 1 1.0) will return false.  I think by
this logic (= 1.0M 1.0) should also be false.  I have no idea what the
current branch actually does though -- haven't tried it yet.


 Now, one interesting question is whether the hashCode of 40.0M should
 match the hashCode for 40N, because they are two exact numbers that
 represent the same value.


The more I think about it, the more I think that big decimals are sort
of their own universe and we really wouldn't want the hashCodes of an
integral bigdecimal to match the integer hashcode.  I mean, if 40.0M
and 40.00M are considered different by Java, it seems fruitless to try
to unify these with their integer counterparts.

-- 
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: Enhanced primitive support - redux

2010-06-25 Thread Garth Sheldon-Coulson
 I should have said they shouldn't be equal based on Rich Hickey's
 explanation that from now on (= 1 1.0) will return false.  I think by
 this logic (= 1.0M 1.0) should also be false.  I have no idea what the
 current branch actually does though -- haven't tried it yet.


Ah, yeah, fair enough. I would merely like to have floating point hash codes
that match floating point equality.

In other words, if we were to stick with the status quo where (= 0.3 0.3M)
= true and (= 3/10 0.3) = true, then it would be nice to get BigDec hash
codes that match Double hash codes.

But you're right that Rich's message suggests we're moving to a world where
(= 0.3 0.3M) = false. I hadn't realized the (good) consequences for
floating point equality. In that world, you're right about hash codes. I
also see what you mean about contagion.

Personally, I think (= 3 3M) = true and (= 3/10 0.3M) = true would be nice
to have, given that (= 3 3N) = true. Both are currently false in equiv. I
also think (= 3.0M 3.00M) = true would be nice. As Rich said, there's no
particular reason to have Clojure = work exactly like Java .equals(). I
think all it would take is a call to .stripTrailingZeros() on each =
comparison of a BigDecimal.

Garth

-- 
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: Enhanced primitive support - redux

2010-06-25 Thread Mark Engelberg
On Fri, Jun 25, 2010 at 2:39 PM, Garth Sheldon-Coulson g...@mit.edu wrote:
 Personally, I think (= 3 3M) = true and (= 3/10 0.3M) = true would be nice
 to have, given that (= 3 3N) = true. Both are currently false in equiv. I
 also think (= 3.0M 3.00M) = true would be nice. As Rich said, there's no
 particular reason to have Clojure = work exactly like Java .equals(). I
 think all it would take is a call to .stripTrailingZeros() on each =
 comparison of a BigDecimal.

Yeah, if it's technically feasible, this definitely makes the most
mathematical sense.

-- 
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: Enhanced primitive support - redux

2010-06-25 Thread Mike Meyer
I'll reiterate a question I asked a while back, but was never answered:

Are the bit-bashing operators (bit-*) going to get the same treatment
as the arithmetic operators? I would expect that many of the fields
that benefit if the latter to be fast would also benefit from the former
being fast, and I know that fast algorithms in combinatorics and crypto
tend to make use of them.

mike
-- 
Mike Meyer m...@mired.org http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O ascii ribbon campaign - stop html mail - www.asciiribbon.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: Enhanced primitive support - redux

2010-06-25 Thread Andrzej
On Sat, Jun 26, 2010 at 4:04 AM, Rich Hickey richhic...@gmail.com wrote:
 equiv, the revenge of num

Has it already been decided that some sort of this new numeric tower
will find its way into Clojure?

Personally, I think this change will open a can of worms and make
programming in Clojure more difficult and error prone.

I don't think there is a nice and clean solution to the numeric
problem (Clojure is not the first language tackling it) but there are
two possibilities that could produce an acceptable trade off:
- using boxed math everywhere and optimizing performance by storing
preallocated Integers in a cache,
- using both boxed and primitive math but keeping the boundary between
them as explicit as possible (different operators, no automatic
conversion etc.). Existing operators should default to boxed math (for
runtime safety and compatibility).

Andrzej

-- 
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: Enhanced Primitive Support

2010-06-24 Thread Heinz N. Gies
Another thing I noticed, clojures array functions are using int's as index, so 
to get best performance from them you currently need to cast every counter you 
use to a int by hand so you have (loop [i (int 0)] ... since otherwise there 
will be a lot of type casting when accessing arrays. So a good course of 
action, in regards of this changes might be to change aget and aset to use long 
indices.

Regards,
Heinz

-- 
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: Enhanced Primitive Support

2010-06-24 Thread Mike Meyer
[Not really about enhanced primitive support - more about optimization
 on the jvm.]

On Tue, 22 Jun 2010 01:47:26 -0400
David Nolen dnolen.li...@gmail.com wrote:
 Yet consider this, If I'm writing OpenGL code in Penumbra I will have quite
 a bit of code that amounts to the following:
 
 ; 630 msecs
 (dotimes [_ 10]
   (time
(dotimes [_ 10]
  (+ 1 2
 
 Yes. With Rich's primitive work we can get to *1 billion arithmetic
 operations* in  2/3 of a second on commodity hardware.

Which begs the question - why are you mucking about with SISD
algorithms if you need that kind of thing to be fast? IIUC, recent
versions of the JVM can access the SIMD instructions that have been
available on most commodity hardware for the last couple of years. Why
aren't you trying to get to those to get a serious performance boost?
Better yet, given that you're using OpenGL and presumably have real
graphics hardware available, why aren't you trying to push this stuff
out to the vector processor on the GPU where it will really fly?

mike
-- 
Mike Meyer m...@mired.org http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O ascii ribbon campaign - stop html mail - www.asciiribbon.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: Enhanced Primitive Support

2010-06-23 Thread Heinz N. Gies
Other math functions as max, min and so on should behave the same as +, - I 
think it is kind of confusing if you've a loop with a max and have to cast it 
to long by hand :)

Regards, heinz.

-- 
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: Enhanced Primitive Support

2010-06-23 Thread Heinz N. Gies
Hmm yesterday Rick said that the new changes give clojure a chance to put down 
the 'scala is faster then clojure' argument. So I figured I give it a try and 
implemented some of the shootouts: fannkucken-redux and the regexdna example. I 
found some interesting things especially once I got carried away with hoeck's 
question how it looks when you benchmark ideomatic clojure 1.2-master vs 
1.2-equal.

As a foreword:
1) I most likely suck at optimizing so I very much welcome any suggestions and 
changes.
1.1) As a result of that please don't take the results I got as abseluts so 
they still are interesting
2) The benchmarks I did are flawed and unfair since I did not do warmup runs 
nor did I remove the JVM startup time, BUT they are unfair for everyone in the 
same manner so I hope that evens things out a bit.
3) The idiomatic code is NOT optimized at all, it is the nicest way I found to 
write the code, or at least the one that seemed most natural to me.


My findings:

A) Comparison to Scala
So first of all it seems clojure is still slower then scale (at least in this 
particular benchmark and with my very limited skills in optimization), the 
optimization was done but there are still things to improve and I know that but 
we're coming closer :)

B) The process of optimization
During the process of optimization I sadly did not feel big relieve brought by 
the equal branch, optimizing code feels still horrible and painful. And the 
code that I got looks more like java with different parenthethes then clojure  
to me - I personally feel ashamed to have written it :(

C) ideomatic clojure master vs. equal
I know again this is just a one piece observeration but I am torn. Over all 
execution time for the fannkuchen example has degraded nearly 20% with the 
equal branch (using same code) yet in profiling it looked faster. I am not 
certain why it seems that equal adds some overhead, hoeck had the same finding 
when not benchmakring JVM execution speed but using criterium to benchmark and 
even in code benchmarking (using time) indiceates equal to be slower in this 
case. I'm not sure how to explain this to be frank, my guess is that some 
optimization hurt the list speed or that the profiler makes odd things.


Code can be found here:

http://github.com/Licenser/clj-shootout

screenshots of some profiling results:

http://grab.by/55po (euqual branch)

http://grab.by/55pp (master branch)

Regards,
Heinz 

-- 
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: Enhanced Primitive Support

2010-06-23 Thread John Williams
On Sat, Jun 19, 2010 at 5:41 AM, Heinz N. Gies he...@licenser.net wrote:

 Lets get away from the argument already cast and bring a new one. It is an
 impossible situation that the literal 1 in one place has a different meaning
 and behavior then in another place. This is in fact a show stopper, I'm
 serious, this would be worst then java.

 (* 1 0.2) - works fine

 but

 (loop [n 1 r 1](if (zero? n) r (recur (dec n) (* r 0.2

 does not because the 1 there is not the 1 in the upper example, that is so
 utterly wrong and horrible please think about it and think about how you'd
 sell someone he has to know where a literal means what, I can guarantee you
 this will keep many people from this wonderful language :(.


I think you're misinterpreting what's going on here. There's no trickery
with the type of 1 or r, and the expression (* r 0.2) will correctly return
0.2. The problem is that when 0.2 is passed into recur, it's coerced to a
long, so it becomes 0.

I do agree that the end result is unfortunate. I would be much happier if
types of loop variables were based not just on their initializers, but also
on the types of the arguments to recur. This would certainly result in some
needless boxing, but the compiler would still be able to use primitives in a
lot of cases. In particular, it could use primitives whenever the loop
variable's new value is computed using only arithmetic operators or other
:static functions that return primitives. The only possible harm would come
from a very particular set of circumstances: (1) the loop variable is
initialized with a primitive, (2) the performance of the loop depends in the
variable being primitive, (3) a the compiler can't prove that the variable
is re-bound with a primitive in a recur form, and (4) the actual value used
to re-bind the variable is a boxed primitive of same type as the
variable's initializer. If (1) is not true, the variable would not be
primitive anyway; if (2) is not true, there may be some unnecessary boxing,
but it doesn't hurt anything; if (3) is not true, the compiler can use
primitives just as it does now; and if (4) is not true, the compiler is
correctly forced to use a boxed type for the variable, whereas today it
incorrectly tries to unbox the value, resulting in either a
ClassCastException or a numeric conversion that silently loses precision.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Heinz N. Gies
I'd like to ask something, is there an (open source) project that really got a 
speed boost from the move to primitive +,-  Co. and is testable / 
benchmarkable fairly easy? I sadly don't have any of those :( to do it all on 
my own.

I'm not asking to mock, what I'd like to do (for myself) is look how the impact 
actually (in the real world) is and how much the effort would be to do it by 
hand. On the matter of speed I've just seen abstract claims by now so I'd love 
to test it myself. 

I think a real test might help a lot to settle this matter (in one or the other 
direction) :)

What I plan to do is:

1) run code in equal branch and take time).

2) replace all +,-,*,/ ... with the ' equivalents to 'slow it down'

3) run code again and take another timing.

4) See how long it takes me (without in depth knowledge of the code so I've an 
disadvantage here) to figure out where the sweet spots are that need the non ' 
variant to get back speed that is close to the run with all primitives.

Why? Because I argue for the + be boxing and say 'it should be fairly simple to 
identify the sweet spots' and I want to see if I am right or wrong or rather 
how simple it is and I think this will be a very interesting case study for our 
current discussion.

What I don't need are projects/problems that are especially designed for this 
discussions (either the one or the other way) since that would be defeating the 
point.

Regards,
Heinz

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Luc Préfontaine


++1 for auto promotion, average code
is complex enough, lets not add
more incertainty with overflow
exceptions.

Data changes overtime and
discovering it in production with
an overflow exception is less than
elegant.

Degraded performance is much more
acceptable in production than a crash
over an unhandled exception 

Again, if performance is critical for
a library or an application then it's up
to its designer to take action.

For the other folks, they will get
the best implementation according
to the number size they crunch in
their data. No need for them to pay
the price for control they do not
need yet.

Luc P

Sent from my iPod

On 2010-06-22, at 12:44 AM, Mark Engelberg mark.engelb...@gmail.com  
wrote:



The new uber-loop is fantastic.

So I guess the main point still to be finalized is whether the default
arithmetic ops will auto-promote or error when long addition
overflows.

Playing around with the latest equals branch:

user= (def n 9223372036854775810)
#'user/n

user= (* (/ n 3) 3)
9223372036854775810N

user= (* (/ n 2) 2)
java.lang.ArithmeticException: integer overflow

user= (def x (/ n 4))
#'user/x

user= (+ x x x x)
9223372036854775810N

user= (+ (+ x x) (+ x x))
java.lang.ArithmeticException: integer overflow

user= (range (- n 2) n)
(9223372036854775808N 9223372036854775809N)

user= (range (- n 3) n)
java.lang.ArithmeticException: integer overflow


I understand exactly why some of these work and some of these don't.
My main point here is to illustrate that without the full numeric
tower supported by the default ops, there can certainly be some
surprises.  There is a pathway with the standard ops from longs to
rational numbers to bigints, but you can't cross directly from longs
to bigints.  Similarly, you can roundtrip from bigints to rationals
and back, but can't roundtrip from bigints to longs and back.  So the
results of computations depends on the path you follow.  Maybe we can
live with these idiosyncrasies for the speed benefits, but this is
worth being aware of.

The range example is something that is easily enough fixed.  Probably
if this branch becomes the standard, range should be modified so that
if the *upper bound* is a bigint, inc' is used rather than inc to
generate the range.  But I think this illustrates the kinds of issues
we're headed towards, regardless of which default is chosen -- people
who write libraries will be choosing between overflow and auto-boxing
primitives, and it might not always be clear from documentation what
the consequences are.  In the current implementation of range, it
works perfectly fine with longs, and it works perfectly fine with
bigints, but it breaks when your lower and upper bounds cross the
boundary.  This is exactly the kind of thing that might not be thought
of when making test cases, so errors like this could lurk for quite a
while without being spotted.

The people on the side of overflow-error-as-default feel that these
sorts of runtime errors are no more problematic than the many other
sorts of runtime errors that can result in Clojure, such as an
out-of-bounds exception when accessing a vector.  But I see these
types of errors as very different.  An out-of-bounds exception is easy
enough to prevent -- there is a simple test you can include in your
code to make sure your index is in bounds before you access your
vector.  But I think it's much harder to determine in advance whether
a sequence of computations will cross the long boundary for all the
possible inputs.

This is probably the main reason I continue to advocate for
auto-promoting ops as the default.  Error-upon-overflow adds an
element of run-time risk, and requires careful thought and additional
testing to achieve the same level of reliability.  I *want*
error-upon-overflow operations to be slightly harder to use so that
library writers will use them judiciously and consciously, and be very
aware of the extra effort they need to go to test their functions for
all numbers, clearly documenting any restrictions on the kinds of
numbers that are permitted.

Like I said before, Clojure's built-in range can easily be adjusted to
work well for speed *and* handle both longs and bigints gracefully.
But it serves as a good example of how the two defaults will affect
library writers.  If auto-promotion is the default, most library
writers will just use the +,*,-,inc,dec operators and it would work
for all numbers right out of the box.  A library writer who wants to
optimize for speed would have to go to a bit of extra effort to add
the apostrophes, and would hopefully at that point give some careful
thought as to what the consequences will be, catching the fact that
this will break ranges that span from longs to bigints, and adjusting
the code accordingly.  On the other hand, if overflow-on-error is the
default, this is what most people will use, and we'll end up with a
lot of code that breaks when crossing the long boundary.

I don't use any bigints, or anything even close to 

Re: Enhanced Primitive Support

2010-06-22 Thread Nicolas Oury
On Tue, Jun 22, 2010 at 12:45 PM, Luc Préfontaine 
lprefonta...@softaddicts.ca wrote:


 Data changes overtime and
 discovering it in production with
 an overflow exception is less than
 elegant.

 Degraded performance is much more
 acceptable in production than a crash
 over an unhandled exception 


Depends in which production.
That's why I defend a way to choose default.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Tim Daly

Boxing and unboxing can be very confusing.
The rules need to be clearly stated somewhere.


It might help if we introduced an explicit syntax,
which might compile away, such as:

(box i)
(unbox i)
(with-unboxed [i 7] ...)

etc. I know Rich doesn't like syntactic overhead
but source languages are intended to communicate with
people, not machines, so it is vital to be clear.

Even Common Lisp struggles with this issue when people
leave the ranch and use ffi.
(I know most people here are not common lispers and some
do not know the ffi (foreign function interface) but
think of it as calling Java code from Clojure)

In the SBCL development list I just got this comment
(by Tobias Rittweiler)
==

In

(declaim (inline call-with-ptr*))
(defun call-with-ptr* (vector function arg1 arg2)
 (cffi-sys:with-pointer-to-vector-data (ptr vector)
   (funcall function ptr arg1 arg2)))

(defun test* (vector i j)
 (declare (optimize speed))
 (flet ((frob (ptr i j)
  (+ (sb-sys:sap-ref-8 ptr i)
 (sb-sys:sap-ref-8 ptr j
   (declare (inline frob))
   (call-with-ptr* vector #'frob i j)))

(defun test** (vector i j)
 (declare (optimize speed))
 (flet ((frob (ptr i j)
  (+ (sb-sys:sap-ref-8 ptr i)
 (sb-sys:sap-ref-8 ptr j
   (cffi-sys:with-pointer-to-vector-data (ptr vector)
 (funcall #'frob ptr i j

I get a note about boxing up a SAP in TEST* but not in TEST**.

Well, why?

My actually use case involves APPLY  rest lists like:

(declaim (inline call-with-ptr))
(defun call-with-ptr (vector function rest args)
 (cffi-sys:with-pointer-to-vector-data (ptr vector)
   (apply function ptr args)))

but it seems that sbcl does not even optimize (APPLY F (LIST X Y))
into (FUNCALL F X Y). What would it take to optimize this to the
same code as TEST** compiles down too?

==

Luc Préfontaine wrote:


++1 for auto promotion, average code
is complex enough, lets not add
more incertainty with overflow
exceptions.

Data changes overtime and
discovering it in production with
an overflow exception is less than
elegant.

Degraded performance is much more
acceptable in production than a crash
over an unhandled exception 

Again, if performance is critical for
a library or an application then it's up
to its designer to take action.

For the other folks, they will get
the best implementation according
to the number size they crunch in
their data. No need for them to pay
the price for control they do not
need yet.

Luc P

Sent from my iPod

On 2010-06-22, at 12:44 AM, Mark Engelberg mark.engelb...@gmail.com 
wrote:



The new uber-loop is fantastic.

So I guess the main point still to be finalized is whether the default
arithmetic ops will auto-promote or error when long addition
overflows.

Playing around with the latest equals branch:

user= (def n 9223372036854775810)
#'user/n

user= (* (/ n 3) 3)
9223372036854775810N

user= (* (/ n 2) 2)
java.lang.ArithmeticException: integer overflow

user= (def x (/ n 4))
#'user/x

user= (+ x x x x)
9223372036854775810N

user= (+ (+ x x) (+ x x))
java.lang.ArithmeticException: integer overflow

user= (range (- n 2) n)
(9223372036854775808N 9223372036854775809N)

user= (range (- n 3) n)
java.lang.ArithmeticException: integer overflow


I understand exactly why some of these work and some of these don't.
My main point here is to illustrate that without the full numeric
tower supported by the default ops, there can certainly be some
surprises.  There is a pathway with the standard ops from longs to
rational numbers to bigints, but you can't cross directly from longs
to bigints.  Similarly, you can roundtrip from bigints to rationals
and back, but can't roundtrip from bigints to longs and back.  So the
results of computations depends on the path you follow.  Maybe we can
live with these idiosyncrasies for the speed benefits, but this is
worth being aware of.

The range example is something that is easily enough fixed.  Probably
if this branch becomes the standard, range should be modified so that
if the *upper bound* is a bigint, inc' is used rather than inc to
generate the range.  But I think this illustrates the kinds of issues
we're headed towards, regardless of which default is chosen -- people
who write libraries will be choosing between overflow and auto-boxing
primitives, and it might not always be clear from documentation what
the consequences are.  In the current implementation of range, it
works perfectly fine with longs, and it works perfectly fine with
bigints, but it breaks when your lower and upper bounds cross the
boundary.  This is exactly the kind of thing that might not be thought
of when making test cases, so errors like this could lurk for quite a
while without being spotted.

The people on the side of overflow-error-as-default feel that these
sorts of runtime errors are no more problematic than the many other
sorts of runtime errors 

Re: Enhanced Primitive Support

2010-06-22 Thread David Nolen
On Tue, Jun 22, 2010 at 6:04 AM, Heinz N. Gies he...@licenser.net wrote:


  Yes. With Rich's primitive work we can get to *1 billion arithmetic
 operations* in  2/3 of a second on commodity hardware.

 Which is absolutely great since I always wanted to do that :P sarcasm/,
 meaning the example is kind of far fetched even compared to fact (which is
 working code with useful results).


Perhaps you aren't interested in using Clojure for graphics or audio work.

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: Enhanced Primitive Support

2010-06-22 Thread Luc Préfontaine

If the maintenance cost of
keeping both options in the Clojure run
 time is reasonnable it's fine with me.
Rich is the best person to answer this.

Otherwise, auto promotion should be
the winner... And the default ...

The vast majority of apps these days
are not gravitating around high
performance numeric computations.

Forcing people to deal with this in mundane code would be insane
in the long run.

Reminds me of C in the early days when we needed to keep and eye on
what was a byte, a short, an int
or a long on the different hardware platforms...

If we want Clojure to remain a viable
option lets keep some usage simplicity
a primary goal.

When I want to scratch every bit of
performance, I expect to kick my butt
out to get it but after I have some
working code running, not while I scratch my head about getting it done.

Proposals up to know regarding
specific operators for various
implementations provide plenty of
options to attain the nirvana of
high performance.  That's good.

Lets just make things easy for the
average guy..,

Luc P

Sent from my iPod


On 2010-06-22, at 7:53 AM, Nicolas Oury nicolas.o...@gmail.com wrote:

On Tue, Jun 22, 2010 at 12:45 PM, Luc Préfontaine lprefonta...@softaddicts.c 
a wrote:


Data changes overtime and
discovering it in production with
an overflow exception is less than
elegant.

Degraded performance is much more
acceptable in production than a crash
over an unhandled exception 

Depends in which production.
That's why I defend a way to choose default.


--
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: Enhanced Primitive Support

2010-06-22 Thread Daniel Gagnon

 Lets just make things easy for the
 average guy..,


If we base the decision on the average guy not writing high performance
numeric apps, then we should also base it on the fact that he does not need
more than a long in 99% of cases either as Rich points out. And longs are a
much simpler concept to grok.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Nicolas Oury
On Tue, Jun 22, 2010 at 2:00 PM, Daniel Gagnon redalas...@gmail.com wrote:

 If we base the decision on the average guy not writing high performance
 numeric apps, then we should also base it on the fact that he does not need
 more than a long in 99% of cases either as Rich points out. And longs are a
 much simpler concept to grok.


+1. The average guy understands that big numbers are something special.
The average guy also want to have close to native speed when he first tries
a language, not * 10 or * 20 that.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Joost
On Jun 22, 3:00 pm, Daniel Gagnon redalas...@gmail.com wrote:
  Lets just make things easy for the
  average guy..,

 If we base the decision on the average guy not writing high performance
 numeric apps, then we should also base it on the fact that he does not need
 more than a long in 99% of cases either as Rich points out. And longs are a
 much simpler concept to grok.

My work depends. I've written some audio code in different languages
and that needs to be fast. But writing fast math-heavy code is not
just a case of no auto-promotion or primitives only. You'll have
to be very careful about float - int conversions too (so, for
instance, you want to multiply floats only or ints only wherever
possible) and you also need to be very careful about how your
algorithm is structured.

My point is, I expect all code that isn't written with performance in
mind to be slow. But for almost all non-audio work, I really don't
care all that much, as long as I can get better performance in the few
pieces of code that need it.

For that reason, I really dislike having to use the ugly *' variants
to get the correct math ops. To me, a 10 to 20% slowdown (or
rather, less accelleration compared to the current 1.1 branch) is
worth it if it guarantees that unbounded data can still be handled
by naive code, and it encourages use of correct math in code where
speed isn't that important.

Really speed-intensive code will need to be documented as using
specific input types. I.e. for audio code, you generally use floats or
doubles for all data, and any deviation from that will cause problems.
For this kind of code, there is no reason at all to support extra-wide
numbers. But for most code, I expect to be able to just cram in a
bunch of untyped numbers and get the correct answer even if it's a
bit slower.

I do see the argument that ''longs and doubles should be enough for
everybody'' and it's generally true. But making them the default will
mean that in the longer run you won't be able to use your bigints with
any library, since they'll all default to using the exception-throwing
math.

I may have misinterpreted the current proposals somewhere, so please
correct me if I'm wrong. Keeping up with this thread is kinda hard.

Just my 2 cnts.
Joost.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread lprefontaine
I never said we should not provides ways to tune code and get higher throughput
or arbitrary sized numbers. There has to be a path to satisfies those needs.
The stuff that was proposed on this thread (specialized ops, ...) should allow
people to tune their code if they require to do so.

I said that the default approach had to be simple and should not be made
solely on the basis of numeric intensive apps.

If Rich finds auto promotion too costly to implement (and maintain) versus
using longs that's reasonable, (he's the best placed to take that decision),
then lets use longs and throw overflow exceptions.

The default will still remain simple, if your numbers don't fit in a long it 
will bump. Anyway the long size as we know it will increase in size in the 
future so it may become a mood point.

Auto promotion if doable can just enlarge the number of apps not having to care
about huge number limits.

Simplicity is not equivalent to a lack of sophisticated approaches when
required.

Caring about which numeric implementation to choose is not my first concern
when it comes to design, it comes later if it ever comes up as an issue.
I saw such needs in 30 years a number of times mostly in
real time systems with limited hardware resources. Not a common
need in apps in general these days.

Today numeric performance is needed by some specific and narrow
needs (heavy graphics, ,,,). If you really want max. numeric performance,
work on a bridge to submit computations to your graphic card there will
be greater payoffs than staying within the JVM.



Luc P.



Daniel Gagnon redalas...@gmail.com wrote ..
 
  Lets just make things easy for the
  average guy..,
 
 
 If we base the decision on the average guy not writing high performance
 numeric apps, then we should also base it on the fact that he does not need
 more than a long in 99% of cases either as Rich points out. And longs are a
 much simpler concept to grok.
 
 -- 
 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: Enhanced Primitive Support

2010-06-22 Thread Lee Spector

All of this talk about the average guy is ungrounded. Average over what set 
and how are you getting the data? It may (or may not) be true that that the 
average *programmer* understands that big numbers (how big?) are something 
special, but IMHO that (if true) would probably be because the average 
programmer was first exposed to bad languages.

 -Lee

On Jun 22, 2010, at 9:34 AM, Nicolas Oury wrote:

 +1. The average guy understands that big numbers are something special. The 
 average guy also want to have close to native speed when he first tries a 
 language, not * 10 or * 20 that.
 

--
Lee Spector, Professor of Computer Science
School of Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359
lspec...@hampshire.edu, http://hampshire.edu/lspector/
Phone: 413-559-5352, Fax: 413-559-5438

Check out Genetic Programming and Evolvable Machines:
http://www.springer.com/10710 - http://gpemjournal.blogspot.com/

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Rich Hickey


On Jun 22, 2010, at 12:44 AM, Mark Engelberg wrote:


The new uber-loop is fantastic.

So I guess the main point still to be finalized is whether the default
arithmetic ops will auto-promote or error when long addition
overflows.

Playing around with the latest equals branch:

user= (def n 9223372036854775810)
#'user/n

user= (* (/ n 3) 3)
9223372036854775810N

user= (* (/ n 2) 2)
java.lang.ArithmeticException: integer overflow

user= (def x (/ n 4))
#'user/x

user= (+ x x x x)
9223372036854775810N

user= (+ (+ x x) (+ x x))
java.lang.ArithmeticException: integer overflow

user= (range (- n 2) n)
(9223372036854775808N 9223372036854775809N)

user= (range (- n 3) n)
java.lang.ArithmeticException: integer overflow


I understand exactly why some of these work and some of these don't.
My main point here is to illustrate that without the full numeric
tower supported by the default ops, there can certainly be some
surprises.  There is a pathway with the standard ops from longs to
rational numbers to bigints, but you can't cross directly from longs
to bigints.  Similarly, you can roundtrip from bigints to rationals
and back, but can't roundtrip from bigints to longs and back.  So the
results of computations depends on the path you follow.  Maybe we can
live with these idiosyncrasies for the speed benefits, but this is
worth being aware of.

The range example is something that is easily enough fixed.  Probably
if this branch becomes the standard, range should be modified so that
if the *upper bound* is a bigint, inc' is used rather than inc to
generate the range.  But I think this illustrates the kinds of issues
we're headed towards, regardless of which default is chosen -- people
who write libraries will be choosing between overflow and auto-boxing
primitives, and it might not always be clear from documentation what
the consequences are.  In the current implementation of range, it
works perfectly fine with longs, and it works perfectly fine with
bigints, but it breaks when your lower and upper bounds cross the
boundary.  This is exactly the kind of thing that might not be thought
of when making test cases, so errors like this could lurk for quite a
while without being spotted.

The people on the side of overflow-error-as-default feel that these
sorts of runtime errors are no more problematic than the many other
sorts of runtime errors that can result in Clojure, such as an
out-of-bounds exception when accessing a vector.  But I see these
types of errors as very different.  An out-of-bounds exception is easy
enough to prevent -- there is a simple test you can include in your
code to make sure your index is in bounds before you access your
vector.  But I think it's much harder to determine in advance whether
a sequence of computations will cross the long boundary for all the
possible inputs.

This is probably the main reason I continue to advocate for
auto-promoting ops as the default.  Error-upon-overflow adds an
element of run-time risk, and requires careful thought and additional
testing to achieve the same level of reliability.  I *want*
error-upon-overflow operations to be slightly harder to use so that
library writers will use them judiciously and consciously, and be very
aware of the extra effort they need to go to test their functions for
all numbers, clearly documenting any restrictions on the kinds of
numbers that are permitted.

Like I said before, Clojure's built-in range can easily be adjusted to
work well for speed *and* handle both longs and bigints gracefully.
But it serves as a good example of how the two defaults will affect
library writers.  If auto-promotion is the default, most library
writers will just use the +,*,-,inc,dec operators and it would work
for all numbers right out of the box.  A library writer who wants to
optimize for speed would have to go to a bit of extra effort to add
the apostrophes, and would hopefully at that point give some careful
thought as to what the consequences will be, catching the fact that
this will break ranges that span from longs to bigints, and adjusting
the code accordingly.  On the other hand, if overflow-on-error is the
default, this is what most people will use, and we'll end up with a
lot of code that breaks when crossing the long boundary.

I don't use any bigints, or anything even close to overflowing a long,
in the kind of code that I write for work.  If error-upon-overflow
wins as the default, I'll gain performance benefits with no immediate
downside.  But ultimately, I feel that anything that helps me reason
about and trust my code, and helps me trust the robustness of code
written by others that I rely upon, is a principle worth fighting for.



It is precisely for these reasons that the first iteration was based  
upon BigInteger contagion. Everyone has to understand this is not a  
black and white, preference based decision. It is a multi-dimensional  
problem involving promotion, reduction, contagion, loop types,  
literals, boxing types, 

Re: Enhanced Primitive Support

2010-06-22 Thread Luc Préfontaine

As the implementor Rich, it's your
call as I said :))
If auto promotion brings in chaos
then lets drop it entirely.

If people want to eat elephants they can still choose to use directly  
big number

implementations.

Luc P

Sent from my iPod

On 2010-06-22, at 10:46 AM, Rich Hickey richhic...@gmail.com wrote:



---
The claim that this primitive stuff is just for numeric-intensive  
applications is outrageous and false, and ignores the implementation  
of Clojure itself to an embarrassing degree. I've worked my tail off  
to reduce the number of allocations inside things like sequences etc  
to the absolute minimum. Now down to 1 per step, and with chunks  
1/32 per step. Moving from 1 to 2 or 3 per step would result in a 2x  
to 3x slowdown for every consumer of these fns.


Everyone has to realize the math you are advocating for the default,  
on non-tagged architectures like the JVM and CLR, *must* do an  
allocation on every +/-/* etc operation. And such ops are littered  
throughout non-numeric data structure code, for indexes, offsets,  
bounds etc. Allocating on every math op in something like the  
persistent vector would make it completely unusably slow.


The languages being pointed to (Ruby, Python, Mathematica) write  
their hard bits in C, or, for the J versions, Java.


Well, guess what, all of the things I've written in my career have  
been hard bits. Those languages were unusable for any of my  
production work, for performance reasons. I wrote Clojure so I could  
stop writing Java and C#, not Ruby, because I couldn't have used  
Ruby in the first place.


And, I think some people are considering moving from Ruby to  
Clojure, for the hard bits of their systems, in part *because*  
Clojure has a better performance profile, their alternatives being  
Java or Scala, not Python or Groovy.


Now you're all sitting on the end of the food chain, eating gazelles  
and saying, 'who needs photosynthesis to be easy'?


;-)

I do. And so do you if you appreciate fast gazelles. You wouldn't be  
able to use a Clojure written in the default Clojure you are  
advocating.


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: Enhanced Primitive Support

2010-06-22 Thread Mike Meyer
On Tue, 22 Jun 2010 14:34:44 +0100
Nicolas Oury nicolas.o...@gmail.com wrote:

 On Tue, Jun 22, 2010 at 2:00 PM, Daniel Gagnon redalas...@gmail.com wrote:
 
  If we base the decision on the average guy not writing high performance
  numeric apps, then we should also base it on the fact that he does not need
  more than a long in 99% of cases either as Rich points out. And longs are a
  much simpler concept to grok.
 
 +1. The average guy understands that big numbers are something special.
 The average guy also want to have close to native speed when he first tries
 a language, not * 10 or * 20 that.

Yes, but we've as yet to see that having auto-promotion as the default
buys the average app *10 or *20. The best we've seen is 10-20%, which
isn't really enough to justify the reduces range for what just
works.

  mike
-- 
Mike Meyer m...@mired.org http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O ascii ribbon campaign - stop html mail - www.asciiribbon.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: Enhanced Primitive Support

2010-06-22 Thread Chas Emerick
There are places where regular folks can be helped (e.g. perhaps  
supporting contagious bigs for the normal/fast ops so that the  
potentially foreign op-prime notation can be ignored if that's  
desirable), but handicapping capability or semantics in any direction  
based on vague appeals to average or regular programmers can't  
happen.


Clojure has a core feature called, of all things, 'reify', so I think  
the cat is somewhat out of the bag in terms of placating morts.   
There's a virtuous cycle at work here: Clojure demands that you raise  
your game, and pays you back for doing so.


- Chas

On Jun 22, 2010, at 10:25 AM, Lee Spector wrote:



All of this talk about the average guy is ungrounded. Average over  
what set and how are you getting the data? It may (or may not) be  
true that that the average *programmer* understands that big numbers  
(how big?) are something special, but IMHO that (if true) would  
probably be because the average programmer was first exposed to bad  
languages.


-Lee

On Jun 22, 2010, at 9:34 AM, Nicolas Oury wrote:

+1. The average guy understands that big numbers are something  
special. The average guy also want to have close to native speed  
when he first tries a language, not * 10 or * 20 that.




--
Lee Spector, Professor of Computer Science
School of Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359
lspec...@hampshire.edu, http://hampshire.edu/lspector/
Phone: 413-559-5352, Fax: 413-559-5438

Check out Genetic Programming and Evolvable Machines:
http://www.springer.com/10710 - http://gpemjournal.blogspot.com/


--
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: Enhanced Primitive Support

2010-06-22 Thread Fogus
One of our reviewers made a fantastic comment on the book and I
thought I would share it for public consumption:

I know that you Lisp guys are incredibly proud of arbitrary-precision
arithmetic, but I can't help but think that it is entirely missing the
point: infinite precision is infinitely slow; no underlying math
library is going to support it (so you are stuck with the four basic
math operations); and lastly, infinite precision is almost always the
wrong approach. If you really need to evaluate the binomial
coefficient of 117-take-31 (you probably don't, to begin with), then
the right way to do this is to work with logarithms and Stirling's
approximation, not with infinite precision.

Agree with him or not, this is the view of a non-Clojure programmer
and (I think) adds a thoughtful perspective.
:f

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Garth Sheldon-Coulson
 Everyone has to realize the math you are advocating for the default, on
 non-tagged architectures like the JVM and CLR, *must* do an allocation on
 every +/-/* etc operation. And such ops are littered throughout non-numeric
 data structure code, for indexes, offsets, bounds etc. Allocating on every
 math op in something like the persistent vector would make it completely
 unusably slow.


I think my understanding of the trade-offs is stuck on this question: If the
auto-promoting ops were chosen as the default, why couldn't
Clojure-in-Clojure use the fast ops rather than the default ops? Couldn't
the implementation of PersistentVector use primitives on the inside without
anyone on the outside ever knowing? (I guess the answer is no, but I'm not
understanding why. Sorry for being behind the curve.)

A second question: I see why the uber-loop requires ops that return
primitives, but what would be the problem with simply having a loop and a
loop'? Is the problem that then we go down the road of bifurcating all
functions into fast and slow?

I like easy photosynthesis and I'm all for raising my game, but I'd like a
better understanding of why I can't have my gazelle in this case and eat it
too.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Heinz N. Gies
We always talk about auto promoting ops, is there a way, and I guess the answer 
will be no, to have auto demoting ops? as in they get (+ (num 1) (num 1)) and 
return (long 2) if the calling side desires so? As in the function promises to 
return a Number or better.

I know this might die on the fact that we need to head with the JVM but 
technically this should be possible right?

it is like caller of + says: I'd like one of those: long, double, Integer, 
Number (in this order) and the the functions satisfies it to it's best 
capabilities, here it would be long.

Not sure if that would make any sense or is even possible within the JVM but it 
sounds kind of cool doesn't it?

Regards,
Heinz

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Mike Meyer
On Mon, 21 Jun 2010 21:44:04 -0700
Mark Engelberg mark.engelb...@gmail.com wrote:

 The new uber-loop is fantastic.
 
 So I guess the main point still to be finalized is whether the default
 arithmetic ops will auto-promote or error when long addition
 overflows.

I think calling them default gives the wrong idea here. We have two
behaviors for the math operators, so we need two sets of names. When
the existing set auto-promoted and the other set worked with
primitives, then calling them op' was a mnemonic (PRIMe implying
PRIMitive math).

But if it's going to be the other way 'round, then the new names
don't work as well. I propose (again, since nobody commented on it the
first time) that the two sets of ops be:

non-autopromoting math: +, -, *, /, ++, -- (if you want to muck with
the rules for symbols, the last two could be drawn from [+-]?1[-+]?
instead).

autopromoting math: add, sub, mul, div, inc, dec

No mucking about with namespaces, no settings to toggle behaviors -
you use the set you want. When teaching the language, you can use the
words and not have to worry about explaining about primitive types,
boxing, or anything else.

While I'm at it, do we still need the postfix N on bignums? Since both
the reader and humans do the right thing even if it's not there, we
shouldn't need it for output any more, even there might be times when
it's handy for input.

 mike
-- 
Mike Meyer m...@mired.org http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O ascii ribbon campaign - stop html mail - www.asciiribbon.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: Enhanced Primitive Support

2010-06-22 Thread Mark Engelberg
On Tue, Jun 22, 2010 at 7:46 AM, Rich Hickey richhic...@gmail.com wrote:
 It is precisely for these reasons that the first iteration was based upon
 BigInteger contagion.

Yeah, I still don't like BigInteger contagion, and I believe I would
vastly prefer the current equals branch, even with its idiosyncrasies,
versus BigInteger contagion.  I just think it makes things so much
simpler when there is one standard type representation for each
number.  Perhaps there are sides to this I haven't yet considered, but
based on my current understanding of the tradeoffs, that's how I feel.

 It would be easy, and is likely, to have bigint literals require the N
 suffix, in that way there is no hiding the use of bigints as you have.

One of my points was that you can create a hidden bigint through a
chain of non-auto-promoting operations that begin with longs, divide
to get fractions, and multiply the fractions to get a bigint.  So it
is possible to get a bigint without ever using an N and without ever
using one of the primed operators.

I can't believe I'm saying this, but if you're going to try to orient
Clojure around primitive math, I almost wonder if it would be cleaner
to rip out *more* pieces of the numeric tower.  Make Clojure math only
work on longs and doubles.  Make it so the default ops error if they
receive anything other than longs or doubles as inputs, or would
produce anything other than longs or doubles as the output.  Make it
so only the primed operators will do math with bigints, rationals,
or bigdecimals.

In my own code, numbers are generally generated by range, and then end
up getting stored in and retrieved from collections.  I assume that
under all the scenarios on the table, numbers in collections will
still have to be boxed?  Will they be automatically converted to
primitives as math is done to them so that further computations will
reap the benefits, or is boxing contagious?

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Tim Daly

We could always take the FORTRAN approach and make
identifiers that start with I through N default to
contagious behavior :-)

Rich Hickey wrote:


On Jun 22, 2010, at 12:44 AM, Mark Engelberg wrote:


The new uber-loop is fantastic.

So I guess the main point still to be finalized is whether the default
arithmetic ops will auto-promote or error when long addition
overflows.

Playing around with the latest equals branch:

user= (def n 9223372036854775810)
#'user/n

user= (* (/ n 3) 3)
9223372036854775810N

user= (* (/ n 2) 2)
java.lang.ArithmeticException: integer overflow

user= (def x (/ n 4))
#'user/x

user= (+ x x x x)
9223372036854775810N

user= (+ (+ x x) (+ x x))
java.lang.ArithmeticException: integer overflow

user= (range (- n 2) n)
(9223372036854775808N 9223372036854775809N)

user= (range (- n 3) n)
java.lang.ArithmeticException: integer overflow


I understand exactly why some of these work and some of these don't.
My main point here is to illustrate that without the full numeric
tower supported by the default ops, there can certainly be some
surprises.  There is a pathway with the standard ops from longs to
rational numbers to bigints, but you can't cross directly from longs
to bigints.  Similarly, you can roundtrip from bigints to rationals
and back, but can't roundtrip from bigints to longs and back.  So the
results of computations depends on the path you follow.  Maybe we can
live with these idiosyncrasies for the speed benefits, but this is
worth being aware of.

The range example is something that is easily enough fixed.  Probably
if this branch becomes the standard, range should be modified so that
if the *upper bound* is a bigint, inc' is used rather than inc to
generate the range.  But I think this illustrates the kinds of issues
we're headed towards, regardless of which default is chosen -- people
who write libraries will be choosing between overflow and auto-boxing
primitives, and it might not always be clear from documentation what
the consequences are.  In the current implementation of range, it
works perfectly fine with longs, and it works perfectly fine with
bigints, but it breaks when your lower and upper bounds cross the
boundary.  This is exactly the kind of thing that might not be thought
of when making test cases, so errors like this could lurk for quite a
while without being spotted.

The people on the side of overflow-error-as-default feel that these
sorts of runtime errors are no more problematic than the many other
sorts of runtime errors that can result in Clojure, such as an
out-of-bounds exception when accessing a vector.  But I see these
types of errors as very different.  An out-of-bounds exception is easy
enough to prevent -- there is a simple test you can include in your
code to make sure your index is in bounds before you access your
vector.  But I think it's much harder to determine in advance whether
a sequence of computations will cross the long boundary for all the
possible inputs.

This is probably the main reason I continue to advocate for
auto-promoting ops as the default.  Error-upon-overflow adds an
element of run-time risk, and requires careful thought and additional
testing to achieve the same level of reliability.  I *want*
error-upon-overflow operations to be slightly harder to use so that
library writers will use them judiciously and consciously, and be very
aware of the extra effort they need to go to test their functions for
all numbers, clearly documenting any restrictions on the kinds of
numbers that are permitted.

Like I said before, Clojure's built-in range can easily be adjusted to
work well for speed *and* handle both longs and bigints gracefully.
But it serves as a good example of how the two defaults will affect
library writers.  If auto-promotion is the default, most library
writers will just use the +,*,-,inc,dec operators and it would work
for all numbers right out of the box.  A library writer who wants to
optimize for speed would have to go to a bit of extra effort to add
the apostrophes, and would hopefully at that point give some careful
thought as to what the consequences will be, catching the fact that
this will break ranges that span from longs to bigints, and adjusting
the code accordingly.  On the other hand, if overflow-on-error is the
default, this is what most people will use, and we'll end up with a
lot of code that breaks when crossing the long boundary.

I don't use any bigints, or anything even close to overflowing a long,
in the kind of code that I write for work.  If error-upon-overflow
wins as the default, I'll gain performance benefits with no immediate
downside.  But ultimately, I feel that anything that helps me reason
about and trust my code, and helps me trust the robustness of code
written by others that I rely upon, is a principle worth fighting for.



It is precisely for these reasons that the first iteration was based 
upon BigInteger contagion. Everyone has to understand this is not a 
black and white, 

Re: Enhanced Primitive Support

2010-06-22 Thread Mike Meyer
On Tue, 22 Jun 2010 10:46:05 -0400
Rich Hickey richhic...@gmail.com wrote:
 ---
 The claim that this primitive stuff is just for numeric-intensive  
 applications is outrageous and false, and ignores the implementation  
 of Clojure itself to an embarrassing degree. I've worked my tail off  
 to reduce the number of allocations inside things like sequences etc  
 to the absolute minimum. Now down to 1 per step, and with chunks 1/32  
 per step. Moving from 1 to 2 or 3 per step would result in a 2x to 3x  
 slowdown for every consumer of these fns.

Actually, I've acknowledged that for a while. What I've been trying to
get (and that git clone from github fails for me has made hard to
measure myself) is some measurements of how much this costs real - but
non-numeric - applications. The one measurement posted was - IIRC -
10-20%.

 Everyone has to realize the math you are advocating for the default,  
 on non-tagged architectures like the JVM and CLR, *must* do an  
 allocation on every +/-/* etc operation. And such ops are littered  
 throughout non-numeric data structure code, for indexes, offsets,  
 bounds etc. Allocating on every math op in something like the  
 persistent vector would make it completely unusably slow.

I disagree with that first statement, and will point to python as the
counterexample. Like Clojure, it has immutable integers. It avoids the
issue of having to allocate for those ops some of the time by keeping
a table of the first N (tunable at interpreter build time) integers
that *all* instances of small integers point to. So 5 + 5 doesn't
allocate a new object, it returns a pointer to the pre-allocated 10 in
that table.

 Well, guess what, all of the things I've written in my career have  
 been hard bits. Those languages were unusable for any of my production  
 work, for performance reasons. I wrote Clojure so I could stop writing  
 Java and C#, not Ruby, because I couldn't have used Ruby in the first  
 place.

Which merely means that the language you're writing may not be the
language I want. No problem. Personally, given that the default is 64
bits, it's not nearly the issue it was when Python changed (when most
of the world used 32 bit ints). I just don't want to get stuck having
to use obviously second class names (or having to put up with errors
about rebinding core functions) to get the math I want.

 Now you're all sitting on the end of the food chain, eating gazelles  
 and saying, 'who needs photosynthesis to be easy'?
 
 ;-)
 
 I do. And so do you if you appreciate fast gazelles. You wouldn't be  
 able to use a Clojure written in the default Clojure you are advocating.

Would it be Clojure if it didn't run on the JVM? Personally, I could
live without the JVM. And the more I learn about the JVM, the more I
could live without it!

On the other hand, the PyPy folks don't seem to be making much noise
either.

  mike
-- 
Mike Meyer m...@mired.org http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O ascii ribbon campaign - stop html mail - www.asciiribbon.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: Enhanced Primitive Support

2010-06-22 Thread Nicolas Oury
On Tue, Jun 22, 2010 at 6:43 PM, Mike Meyer 
mwm-keyword-googlegroups.620...@mired.org wrote:


  Everyone has to realize the math you are advocating for the default,
  on non-tagged architectures like the JVM and CLR, *must* do an
  allocation on every +/-/* etc operation. And such ops are littered
  throughout non-numeric data structure code, for indexes, offsets,
  bounds etc. Allocating on every math op in something like the
  persistent vector would make it completely unusably slow.

 I disagree with that first statement, and will point to python as the
 counterexample. Like Clojure, it has immutable integers. It avoids the
 issue of having to allocate for those ops some of the time by keeping
 a table of the first N (tunable at interpreter build time) integers
 that *all* instances of small integers point to. So 5 + 5 doesn't
 allocate a new object, it returns a pointer to the pre-allocated 10 in
 that table.


The JVM can do that for you, if you want. It may have issues with
concurrency though, depending of the way it is implemented.
However, it does not solve the problem of performance of boxed nums, though.
1. It is only helps for small numbers
2.It only help GC. And GC is not the main issue, imho.
(pointer dereference, including cache misses, and filling the cache with
garbage is more annoying than GCs, imho. But I am not an expert).

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Mike Meyer
On Tue, 22 Jun 2010 18:56:30 +0100
Nicolas Oury nicolas.o...@gmail.com wrote:

 On Tue, Jun 22, 2010 at 6:43 PM, Mike Meyer 
 mwm-keyword-googlegroups.620...@mired.org wrote:
 
 
   Everyone has to realize the math you are advocating for the default,
   on non-tagged architectures like the JVM and CLR, *must* do an
   allocation on every +/-/* etc operation. And such ops are littered
   throughout non-numeric data structure code, for indexes, offsets,
   bounds etc. Allocating on every math op in something like the
   persistent vector would make it completely unusably slow.
 
  I disagree with that first statement, and will point to python as the
  counterexample. Like Clojure, it has immutable integers. It avoids the
  issue of having to allocate for those ops some of the time by keeping
  a table of the first N (tunable at interpreter build time) integers
  that *all* instances of small integers point to. So 5 + 5 doesn't
  allocate a new object, it returns a pointer to the pre-allocated 10 in
  that table.
 
 The JVM can do that for you, if you want. It may have issues with
 concurrency though, depending of the way it is implemented.
 However, it does not solve the problem of performance of boxed nums, though.
 1. It is only helps for small numbers

Don't I recall someone saying that small numbers are the most common
ones? *Especially* if you're doing things like vector arithmetic.

 2.It only help GC. And GC is not the main issue, imho.
 (pointer dereference, including cache misses, and filling the cache with
 garbage is more annoying than GCs, imho. But I am not an expert).

Um, it helps avoid some GC by *not doing an allocation*. According to
what Rich said, doing the allocation is the performance problem - at
least in the internals of clojure. Personally, I believe what Rich
wrote. Not only does he have more experience than anyone else with the
insides of clojure, but this matches my experience with adding GO-FAST
to LISP systems.

   mike
-- 
Mike Meyer m...@mired.org http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O ascii ribbon campaign - stop html mail - www.asciiribbon.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: Enhanced Primitive Support

2010-06-22 Thread Sean Corfield
On Tue, Jun 22, 2010 at 10:43 AM, Mike Meyer
mwm-keyword-googlegroups.620...@mired.org wrote:
 Would it be Clojure if it didn't run on the JVM? Personally, I could
 live without the JVM. And the more I learn about the JVM, the more I
 could live without it!

For my work, languages are only useful if they run on the JVM *and*
can interoperate so I can mix libraries written in multiple languages
and choose the best language for each part of the system. It's why
I've been mixing Groovy and Scala into projects over the last 2-3
years and it's why I want to be able to mix Clojure in as well. It's
why people bothered to create JRuby and Jython etc. It's why I didn't
pursue Erlang (although I'm keeping an eye on Erjang...).

We're all different and have different needs in languages.
-- 
Sean A Corfield -- (904) 302-SEAN
Railo Technologies, Inc. -- http://getrailo.com/
An Architect's View -- http://corfield.org/

If you're not annoying somebody, you're not really alive.
-- Margaret Atwood

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Wilson MacGyver
On Tue, Jun 22, 2010 at 1:43 PM, Mike Meyer
mwm-keyword-googlegroups.620...@mired.org wrote:
 Would it be Clojure if it didn't run on the JVM? Personally, I could
 live without the JVM. And the more I learn about the JVM, the more I
 could live without it!

I just want to add my two cents here. I don't think we would've ever used
clojure if it wasn't on the JVM. Also, I think JVM plays a bit part
of the current good press clojure is getting.

-- 
Omnem crede diem tibi diluxisse supremum.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Mike Anderson
On Jun 22, 1:27 pm, David Nolen dnolen.li...@gmail.com wrote:
 On Tue, Jun 22, 2010 at 6:04 AM, Heinz N. Gies he...@licenser.net wrote:



   Yes. With Rich's primitive work we can get to *1 billion arithmetic
  operations* in  2/3 of a second on commodity hardware.

  Which is absolutely great since I always wanted to do that :P sarcasm/,
  meaning the example is kind of far fetched even compared to fact (which is
  working code with useful results).

 Perhaps you aren't interested in using Clojure for graphics or audio work.

 David

Most of my code does fairly intensive graphics work. I'd love to be
able to write
it all in Clojure but currently (sadly) it is often easier for me to
write the processing
code in Java and use on the Java interop to call it.

Also if anyone is interested in real-time performance (games,
animation etc.) then
lots of small boxing allocations can be unhelpful in terms of
increasing the number
and severity of GC pauses - to some extent that's even worse than the
overall
performance hit.

Aside from my personal utility and preferences (which are compelling
for me!)
I'm in the primitive by default camp for a few reasons:

1. The pay for what you use argument is very convincing
2. It's more conceptually close to what Java/C# developers are used to
so it helps
 with the learning curve
3. Primitive by default is going to work much better for non-
mathematical uses
of numbers (array indexes, simple loops, counts of collection sizes
etc. ) which
I believe is the common case rather than heavy-duty mathematics with
huge integer ranges
4. It minimises the risk of a Clojure is slow reputation developing.
Which you are
likely to get if people start comparing micro-benchmarks of non-hinted
code against
languages with static / primitive support.

-- 
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: Enhanced Primitive Support

2010-06-22 Thread Garth Sheldon-Coulson
I'm just one voice on the side that's been advocating for auto-promotion by
default. For what it's worth, I completely see where the other side is
coming from, and if Rich sees primitive math by default as important to
Clojure's future, then so be it. It sounds like he's given it a lot of
though and has a pretty strongly held opinion at this point. That is, unless
he's just playing devil's advocate.

I would, however, like to throw some support behind Mike Meyer's suggestion
that the arbitrary precision numeric tower use names like add, sub, mul,
div, inc, dec, while the default ops keep the symbolic names. I think it
was Luke who suggested, and I agree, that it would be unfortunate to have to
teach new Clojurians about machine math just to allow them to understand
Clojure math. For new users, and also for people like me, it would be nice
to having names for the arbitrary precision numeric tower that don't sound
subordinated or second-class.

I also think Mark's idea of removing support for bigints and bigdecimals
from the default ops is worth discussing. It seems cleaner to me than
overloading the default ops and thereby making people complacent.

Garth

On Tue, Jun 22, 2010 at 1:13 PM, Mike Anderson
mike_r_ander...@yahoo.co.ukwrote:

 On Jun 22, 1:27 pm, David Nolen dnolen.li...@gmail.com wrote:
  On Tue, Jun 22, 2010 at 6:04 AM, Heinz N. Gies he...@licenser.net
 wrote:
 
 
 
Yes. With Rich's primitive work we can get to *1 billion arithmetic
   operations* in  2/3 of a second on commodity hardware.
 
   Which is absolutely great since I always wanted to do that :P
 sarcasm/,
   meaning the example is kind of far fetched even compared to fact (which
 is
   working code with useful results).
 
  Perhaps you aren't interested in using Clojure for graphics or audio
 work.
 
  David

 Most of my code does fairly intensive graphics work. I'd love to be
 able to write
 it all in Clojure but currently (sadly) it is often easier for me to
 write the processing
 code in Java and use on the Java interop to call it.

 Also if anyone is interested in real-time performance (games,
 animation etc.) then
 lots of small boxing allocations can be unhelpful in terms of
 increasing the number
 and severity of GC pauses - to some extent that's even worse than the
 overall
 performance hit.

 Aside from my personal utility and preferences (which are compelling
 for me!)
 I'm in the primitive by default camp for a few reasons:

 1. The pay for what you use argument is very convincing
 2. It's more conceptually close to what Java/C# developers are used to
 so it helps
  with the learning curve
 3. Primitive by default is going to work much better for non-
 mathematical uses
 of numbers (array indexes, simple loops, counts of collection sizes
 etc. ) which
 I believe is the common case rather than heavy-duty mathematics with
 huge integer ranges
 4. It minimises the risk of a Clojure is slow reputation developing.
 Which you are
 likely to get if people start comparing micro-benchmarks of non-hinted
 code against
 languages with static / primitive support.

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


-- 
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: Enhanced Primitive Support

2010-06-22 Thread Mike Meyer
On Tue, 22 Jun 2010 21:07:39 -0400
Garth Sheldon-Coulson g...@mit.edu wrote:

 I would, however, like to throw some support behind Mike Meyer's suggestion
 that the arbitrary precision numeric tower use names like add, sub, mul,
 div, inc, dec, while the default ops keep the symbolic names. I think it
 was Luke who suggested, and I agree, that it would be unfortunate to have to
 teach new Clojurians about machine math just to allow them to understand
 Clojure math. For new users, and also for people like me, it would be nice
 to having names for the arbitrary precision numeric tower that don't sound
 subordinated or second-class.

That's the point.

 I also think Mark's idea of removing support for bigints and bigdecimals
 from the default ops is worth discussing. It seems cleaner to me than
 overloading the default ops and thereby making people complacent.

Did you leave ratios out of the list of things it should support?

I'm not so sure about this one. With things as they are, if I pass a
bigint to a library routine that does arithmetic on it, it will just
work. Yes, if I start with a boxed int and it overflows, I still lose,
but we can reduce the lossage a little here. We might even be able to
tweak things to make it even better.

   mike
-- 
Mike Meyer m...@mired.org http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O ascii ribbon campaign - stop html mail - www.asciiribbon.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: Enhanced Primitive Support

2010-06-21 Thread Nicolas Oury
That's not true. primitive loop is one of the key of the java-like
performance of clojure, once there are a few annotations.

On Mon, Jun 21, 2010 at 1:19 AM, Mark Engelberg mark.engelb...@gmail.comwrote:

 [Note that
 changing loop to auto-boxing behavior shouldn't hurt performance
 because currently, almost all numbers are boxed unless otherwise
 specified with an explicit primitive typecast, so we're already seeing
 what boxed speed looks like].


-- 
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: Enhanced Primitive Support

2010-06-21 Thread Nicolas Oury
On Mon, Jun 21, 2010 at 1:19 AM, Mark Engelberg mark.engelb...@gmail.comwrote:

 The arguments seem to be winding down, so I thought this would be a
 good time to summarize my thoughts.


I will do that too.
The two sides of the arguments have both good points and won't change their
position.
So, my proposal:
- a different set of labeled operators +', +#  per family of return value.
(boxed, long, maybe more to come...)
- the default for the non-labeled operators +,-... can be choose either by a
flag or by a ns trickery. ( I have to say I advocate the flag)
- the flag also change the default for literals.
- Default for the the non-labeled operator is boxed. It removes the problem
for loop/recur, and gives back the problems are they are now.
- People that don't know use the default operators
- people that explicitly knows their code has some interesting properties
(always small int,
can produce a big int with very small inputs) specifies it by using
explicitly the specialised operators.

The flag *use-primitive-as-default* is a big help for optimization. Most of
the performance hits of boxing do not show in profiling.
(It slows down a lot of functions, by memory access and - more importantly -
filling the cache with garbage,  that do not seem to be arithmetic-heavy)

The do-not-worry default allows an easy learning curve.

The specialized operators in both directions allows to explicit some
semantic differences in the meaning of the operations. It is good to give a
way to people to
specify, if they want to, what they know about their program.

-- 
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: Enhanced Primitive Support

2010-06-21 Thread Nicolas Oury
On Mon, Jun 21, 2010 at 9:06 AM, Nicolas Oury nicolas.o...@gmail.comwrote:

 - Default for the the non-labeled operator is boxed. It removes the problem
 for loop/recur, and gives back the problems are they are now.



oups. Not really awake. Monday morning :(
I meant:

- Default for the the non-labeled operator is boxed. It removes the problem
for loop/recur without annotations, and gives back the problems as they are
now with annotations.

-- 
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: Enhanced Primitive Support

2010-06-21 Thread Mark Engelberg
On Mon, Jun 21, 2010 at 12:32 AM, Nicolas Oury nicolas.o...@gmail.com wrote:
 That's not true. primitive loop is one of the key of the java-like
 performance of clojure, once there are a few annotations.

Right, the key words here are once there are a few annotations.
Those who aren't making those annotations will see the same
performance they saw before.  Those who have been making annotations
will simply use loop', which would trigger the primitive bindings and
give the java-like performance with much less annotation than before.

-- 
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: Enhanced Primitive Support

2010-06-21 Thread Tim Daly

This debate happened many years ago for common lisp.
The flag *use-primitive-as-default* is a big help for optimization. 
Most of the performance hits of boxing do not show in profiling.
(It slows down a lot of functions, by memory access and - more 
importantly - filling the cache with garbage,  that do not seem to be 
arithmetic-heavy)

Except for renaming this appears to be the common lisp
(proclaim (safety 0) (speed 3))


The do-not-worry default allows an easy learning curve.


Except for renaming this appears to be the common lisp
(proclaim (safety 3) (speed 0))

Rich explicitly said he did not want this solution.

Tim Daly



--
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: Enhanced Primitive Support

2010-06-21 Thread Heinz N. Gies

On Jun 21, 2010, at 13:40 , Tim Daly wrote:

 This debate happened many years ago for common lisp.
...
 Rich explicitly said he did not want this solution.
 
 Tim Daly


it would be more or less trivial to make a macro that switches between non 
promoting + primitive loop and promoting and boxed loop:

(defmacro fast [body]
  `(let [+# +, *# *, -# -, loop# loop ...]
 (binding [+ +', * *', - -', loop loop' ...
  +' +#, *' *#,-' +#, loop' loop# ...]
  ~...@body)))
;; NOT TESTED! Just a brainstorming

And of cause it would just work the same when the defaults were the other way 
round only would need to rename fast to safe or just-working or whatever is 
fitting.

It does not has to be part of c.core or c.contrib if Rich does not like it but 
it might very well be in every code if someone likes it for their little realm 
as I would.

Regards,
Heinz

-- 
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: Enhanced Primitive Support

2010-06-21 Thread Konrad Hinsen
On 21.06.2010, at 02:19, Mark Engelberg wrote:

 The arguments seem to be winding down, so I thought this would be a
 good time to summarize my thoughts.
 
 My favorite option of those proposed is:
 +, *, -, inc, dec auto-promote.
 loop/recur is changed so that primitive bindings are boxed.
 +',*',-',inc',dec' give error upon overflow.
 A new construct, loop', is introduced that doesn't box primitives and
 enforces recur with primitive upon penalty of error.

My preference is the same, for pretty much the same reasons.

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: Enhanced Primitive Support

2010-06-21 Thread Nicolas Oury
On Mon, Jun 21, 2010 at 12:40 PM, Tim Daly d...@axiom-developer.org wrote:

 This debate happened many years ago for common lisp.

  The flag *use-primitive-as-default* is a big help for optimization. Most
 of the performance hits of boxing do not show in profiling.
 (It slows down a lot of functions, by memory access and - more importantly
 - filling the cache with garbage,  that do not seem to be arithmetic-heavy)

 Except for renaming this appears to be the common lisp
 (proclaim (safety 0) (speed 3))


 The do-not-worry default allows an easy learning curve.

  Except for renaming this appears to be the common lisp
 (proclaim (safety 3) (speed 0))

 Rich explicitly said he did not want this solution.

 Tim Daly


I though his concern was mainly readability, but maybe I misread. Anyway
(set! *default-integers* :boxed)

or

(set! *default-integers* :long) seems easier to understand.

-- 
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: Enhanced Primitive Support

2010-06-21 Thread Lee Spector

On Jun 21, 2010, at 8:23 AM, Heinz N. Gies wrote:
 it would be more or less trivial to make a macro that switches between non 
 promoting + primitive loop and promoting and boxed loop:
 
 (defmacro fast [body]
   `(let [+# +, *# *, -# -, loop# loop ...]
  (binding [+ +', * *', - -', loop loop' ...
   +' +#, *' *#,-' +#, loop' loop# ...]
   ~...@body)))
 ;; NOT TESTED! Just a brainstorming


If the body does anything in new threads, e.g. in a pmap, then they won't be 
fast (or correct, if you reverse the defaults).

I guess this a somewhat unrelated newbie question: aren't there often cases 
like this where one wants to temporarily rebind something, but across all 
children threads? Is there some straightforward way to do this that I've 
missed? 

 -Lee

--
Lee Spector, Professor of Computer Science
School of Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359
lspec...@hampshire.edu, http://hampshire.edu/lspector/
Phone: 413-559-5352, Fax: 413-559-5438

Check out Genetic Programming and Evolvable Machines:
http://www.springer.com/10710 - http://gpemjournal.blogspot.com/

-- 
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: Enhanced Primitive Support

2010-06-21 Thread Meikel Brandmeyer
Hi,

On Jun 21, 4:04 pm, Lee Spector lspec...@hampshire.edu wrote:

 I guess this a somewhat unrelated newbie question: aren't there often cases 
 like this where one wants to temporarily rebind something, but across all 
 children threads? Is there some straightforward way to do this that I've 
 missed?

See: 
http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/bound-fn

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: Enhanced Primitive Support

2010-06-21 Thread Rich Hickey


On Jun 20, 2010, at 12:57 PM, Luke VanderHart wrote:


I've been reading this thread, and there's good arguments being made
both ways - I've just been reading with interest. But after seeing the
factorial function that won't compile without hints/casts, I feel I
have to speak up.

I wrote a book on Clojure. It's a short book. That's because Clojure
is simple. It's dynamically typed, and everything just works. In the
current version of Clojure, you can use numbers all day long without
worrying about types. Type hinting and casting is an advanced topic -
I think it should stay that way.

It seems evident that some sort of compromise will be made on this
question. That's fine. I genuinely could go either way. But whatever
combination of features makes it into the final decision, they should
absolutely, vehemently not *require* knowing how to type hint or cast
just to get something basic to compile (as in the factorial example).
That is antithetical to the whole concept of dynamic typing. Having
exceptions thrown on overflow is ok with me - that's something
programmers are used to putting up with, I think, as long as the rules
are clear. I don't care what the rules are, as long as they're simple
to understand and based on a few axioms. If integers are bounded,
that's fine, if they automatically promote, that's fine, as long as
the rules are clear. If there's a separate set of math functions which
do or don't promote, that's fine.   But don't, please don't, do
anything that would mean I'd have to explain the intricacies of
primitives, boxing, hinting and casting in an Intro to Clojure
course. As much as humanely possible, that should be reserved for the
Performance coding in Clojure sequel.



I've added the speculative analysis required to detect when recur  
arguments fail to match the type of primitive loop locals, and  
recompile the loop with those loop args boxed. When *warn-on- 
reflection* is true it will issue a report that this is happening and  
why.


This code is in commit 0df995dc6d31a9f4d0fe199bc63c4abfac7c86b1 on the  
equal branch:


http://github.com/richhickey/clojure/commits/equal

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: Enhanced Primitive Support

2010-06-21 Thread Heinz N. Gies

On Jun 21, 2010, at 16:52 , Rich Hickey wrote:

 I've added the speculative analysis required to detect when recur arguments 
 fail to match the type of primitive loop locals, and recompile the loop with 
 those loop args boxed. When *warn-on-reflection* is true it will issue a 
 report that this is happening and why.
 
 This code is in commit 0df995dc6d31a9f4d0fe199bc63c4abfac7c86b1 on the equal 
 branch:
 
 http://github.com/richhickey/clojure/commits/equal
 
 Rich
Awsome :)

Regards,
Heinz

-- 
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: Enhanced Primitive Support

2010-06-21 Thread ka
 My favorite option of those proposed is:
 +, *, -, inc, dec auto-promote.
 loop/recur is changed so that primitive bindings are boxed.
 +',*',-',inc',dec' give error upon overflow.
 A new construct, loop', is introduced that doesn't box primitives and
 enforces recur with primitive upon penalty of error.

+ 1.  This seems the least of all evils.  Think 15 years down the line
when we have 1024 procs to program on.

Is it time for a vote? :)

-- 
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: Enhanced Primitive Support

2010-06-21 Thread David Nolen
On Mon, Jun 21, 2010 at 10:52 AM, Rich Hickey richhic...@gmail.com wrote:

 I've added the speculative analysis required to detect when recur arguments
 fail to match the type of primitive loop locals, and recompile the loop with
 those loop args boxed. When *warn-on-reflection* is true it will issue a
 report that this is happening and why.

 This code is in commit 0df995dc6d31a9f4d0fe199bc63c4abfac7c86b1 on the
 equal branch:

 http://github.com/richhickey/clojure/commits/equal

 Rich


Brilliant!

-- 
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: Enhanced Primitive Support

2010-06-21 Thread Michał Marczyk
On 21 June 2010 16:52, Rich Hickey richhic...@gmail.com wrote:
 I've added the speculative analysis required to detect when recur arguments
 fail to match the type of primitive loop locals, and recompile the loop with
 those loop args boxed. When *warn-on-reflection* is true it will issue a
 report that this is happening and why.

Ah, this is absolutely fantastic!

I find my general stance on the issue matches Mark's summary pretty
much exactly and to be totally blissfully happy, I'd prefer the primes
to be moved over to the non-promoting ops (which I realise would cause
autoboxing to appear wherever any of the non-primed ops appear -- but
now there's the warning and thus no inexplicable slowdowns). In fact,
my understanding is that any locals participating in arithmetic which
directly or indirectly (i.e. because of interaction with other locals)
involves an unhinted parameter to the function the local is declared
in will now be autoboxed; does using the non-promoting operators by
default have any intrinsic benefits in this situation?

Note that after this commit I think I'm guaranteed to be extremely
happy about Clojure's new arithmetic. Thanks!

Sincerely,
Michał

-- 
You received this message because you are subscribed to the Google
Groups Clojure group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en


Re: Enhanced Primitive Support

2010-06-21 Thread Daniel
If this is half the genius it sounds like then bravo! :D

On Jun 21, 9:52 am, Rich Hickey richhic...@gmail.com wrote:
 I've added the speculative analysis required to detect when recur  
 arguments fail to match the type of primitive loop locals, and  
 recompile the loop with those loop args boxed. When *warn-on-
 reflection* is true it will issue a report that this is happening and  
 why.

 This code is in commit 0df995dc6d31a9f4d0fe199bc63c4abfac7c86b1 on the  
 equal branch:

 http://github.com/richhickey/clojure/commits/equal

 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: Enhanced Primitive Support

2010-06-21 Thread Daniel
user= (set! *warn-on-reflection* true)
true
user= (defn fac [n] (loop [n n r 1] (if (= n 1) r (recur (dec' n) (*'
r n)
NO_SOURCE_FILE:5 recur arg for primitive local: r is not matching
primitive, had: Object, needed: long
Auto-boxing loop arg: r
#'user/fac
user= (fac 40)
8159152832478977343456112695961158942720N


Yes!!  Genius!  :D

On Jun 21, 9:55 am, Heinz N. Gies he...@licenser.net wrote:
 On Jun 21, 2010, at 16:52 , Rich Hickey wrote:

  I've added the speculative analysis required to detect when recur arguments 
  fail to match the type of primitive loop locals, and recompile the loop 
  with those loop args boxed. When *warn-on-reflection* is true it will issue 
  a report that this is happening and why.

  This code is in commit 0df995dc6d31a9f4d0fe199bc63c4abfac7c86b1 on the 
  equal branch:

 http://github.com/richhickey/clojure/commits/equal

  Rich

 Awsome :)

 Regards,
 Heinz

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


  1   2   3   >