Of course none of the nice number-specific formatting options are
available then. If you don't mind loss of precision in
less-significant digits, you might use %f and (double the-number) to
format its coercion to double.
But according to
http://download.oracle.com/javase/6/docs/api/java/util/Formatter.html
Formatter *is* supposed to work with BigInteger with %d (and other
integer-formatting options, and with BigDecimal with %f and other
float-formatting options). So I don't know what's going wrong here,
other than that it also says IllegalFormatConversionException gets
thrown if the format symbol and the parameter are mismatched.
The JavaSE 6 Formatter works properly when invoked explicitly via interop:
=> (.format (java.util.Formatter.) "%d" (into-array Object [(bigint 2)]))
#<Formatter 2>
(2N isn't recognized as a BigInteger literal by Clojure 1.2, it seems.)
In my copy of Clojure 1.2, format also seems to work:
=> (format "%d" (bigint 2))
"2"
So this could be a bug in 1.3 the OP is running into, or else 2N is
turning into something other than what (bigint 2) evaluates to.
=> (format "%d" #=(bigint 2))
"2"
also works for me, and is more closely equivalent to what the OP is
trying to do (as the bigint is embedded directly in the code via the
reader rather than constructed on the fly at eval time).
It looks like either 2N is doing something unexpected or the format
function somehow broke in 1.3.
--
Protege: What is this seething mass of parentheses?!
Master: Your father's Lisp REPL. This is the language of a true
hacker. Not as clumsy or random as C++; a language for a more
civilized age.
In Clojure 1.2:
(type (bigint 2)) => java.math.BigInteger
In Clojure 1.3:
(type (bigint 2)) => clojure.lang.BigInt
(type 2N) => clojure.lang.BigInt
clojure.lang.BigInt != java.math.BigInteger which is why format no longer works.
You can do this:
(format "%d" (.toBigInteger 2N))
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/
Railo Technologies, Inc. -- http://www.getrailo.com/
"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)
What the devil? Why was this done? Seems like wheel reinvention to me.
And format should account for it. A simple change will do it:
(defn format
"Formats a string using java.lang.String.format, see
java.util.Formatter for format
string syntax"
{:added "1.0"
:static true}
^String [fmt & args]
(String/format fmt (to-array (map fixup args))))
where
(defn fixup [o]
(cond
(instance? clojure.lang.BigInt o) (.toBigInteger o)
...
:else o))
Of course, this suggests a generalization of condp:
(defn replace [rmap coll]
(let [s (map #(if-let [[_ v] (find rmap %)] v %) coll)]
(if (seq? coll)
s
(into (empty coll) s))))
(defmacro condx [symb expr & clauses]
(let [default (if (odd? (count clauses)) [:else (last clauses)] [])]
`(cond
~@(mapcat
(fn [[v x]]
[(replace {symb v} expr) x])
(partition 2 clauses))
~@default)))
(defn fixup [o]
(condx class (instance? class o)
clojure.lang.BigInt (.toBigInteger o)
...
o))
Of course, full flexibility might warrant a multimethod for fixup so
that format can be extended to any type. Format tends to occur in I/O
bound code so the runtime overhead of multimethods is probably
acceptable -- indeed, the pprint contrib library already employs them
in a very similar role.
>> In Clojure 1.2:
>>
>> (type (bigint 2)) => java.math.BigInteger
>>
>> In Clojure 1.3:
>>
>> (type (bigint 2)) => clojure.lang.BigInt
>> (type 2N) => clojure.lang.BigInt
>
> What the devil? Why was this done? Seems like wheel reinvention to me.
See http://dev.clojure.org/display/doc/Enhanced+Primitive+Support:
* BigInt provides hashcodes consistent with Long through the range of long
* BigInts will enable optimizations when [operations fit] in long (not yet implemented)
- Chas
Chas has already pointed you at the rationale / discussion but I'm a
bit surprised you reacted as if this was news - the numeric changes in
1.3 have been discussed at great length in a number of threads here
dating back over a year (and you, yourself, were active in at least
one such discussion back in December 2010).
> And format should account for it.
I can see arguments on both sides. format is clearly documented to be
a thin wrapper around java.lang.String.format so by that measure we
shouldn't expect it to handle Clojure's BigInt. OTOH, it's reasonable
to expect BigInt to behave "just like" any other regular numeric type
in Clojure and therefore Clojure's own format function should treat
BigInt as valid for %d.
Might be worth opening a JIRA ticket for enhancing format, yes?
Wow, I just spent the last 30 minutes reading Common Lisp the
Language, 2nd Ed, chapter 22 which describes how powerful and
mind-bending that is...
To extend Tom's point, if you really want a format that knows about all of Clojure's scalars and data structures, cl-format is what you want, and it comes with the language. If you don't want to learn about cl-format, then a local wrapper around `format` that does whatever you like re: coercions to standard Java numeric types would be ~3 lines.
- Chas
What the devil? Why was this done? Seems like wheel reinvention to me.
The draft docs are here: http://dev.clojure.org/display/doc/Documentation+for+1.3+Numerics. These should be made better and placed in a more prominent place before 1.3 goes final.
...
Discussions about primitive arithmetic, not BigInteger arithmetic.
>> And format should account for it.
>
> I can see arguments on both sides. format is clearly documented to be
> a thin wrapper around java.lang.String.format so by that measure we
> shouldn't expect it to handle Clojure's BigInt. OTOH, it's reasonable
> to expect BigInt to behave "just like" any other regular numeric type
> in Clojure and therefore Clojure's own format function should treat
> BigInt as valid for %d.
That'd be my position, yes. Also, backward compatibility: format works
in 1.2 with (* 400000000000 400000000000 400000000000) so it should
work in 1.3 with (* 400000000000 400000000000 400000000000).
> Might be worth opening a JIRA ticket for enhancing format, yes?
You go ahead. I don't have an account there.
I take it you didn't actually bother to read the page he linked to?
Let me quote the relevant part for you since I know how averse you are
to spending any time reading more than the first few lines of any
material that people link to:
* new clojure.lang.BigInt class
* BigInts do not auto-reduce, and are contagious (akin to doubles)
* BigInts will enable optimizations when fits in long
* optimzations not yet in place
* unlike BigInteger, BigInt has consistent hashcodes with Long,
through range of long
> That'd be my position, yes. Also, backward compatibility: format works
> in 1.2 with (* 400000000000 400000000000 400000000000) so it should
> work in 1.3 with (* 400000000000 400000000000 400000000000).
Kinda hard since that expression is not valid in 1.3 anyway:
ArithmeticException integer overflow
clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374)
So that code breaks explicitly in 1.3 and in many ways (format) is
then the least of your worries...
>> Might be worth opening a JIRA ticket for enhancing format, yes?
> You go ahead. I don't have an account there.
Ah, that's right... the contributor process is too much work for
you... Maybe one of the kind souls who've taken the time to go thru
that process might feel inclined to open such a ticket for you? If
they agree with your position, of course.
Sean
You take it wrong. I remember that discussion, evidently better than you do.
> I know how averse you are to spending any time reading more than
> the first few lines of any material
Wrong again. Are you quite done littering the list with pointless ad
hominem remarks?
>> That'd be my position, yes. Also, backward compatibility: format works
>> in 1.2 with (* 400000000000 400000000000 400000000000) so it should
>> work in 1.3 with (* 400000000000 400000000000 400000000000).
>
> Kinda hard since that expression is not valid in 1.3 anyway:
>
> ArithmeticException integer overflow
> clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374)
Bah. It really should work, but we've had that discussion before.
Others in this thread have also pointed out that there is a backward
compatibility problem if format used to work with bignums and then
stops doing so, so you're outvoted.
> ... too much work for you...
This is not an appropriate venue for you to vent bile about other
fellow users. If you have some kind of personal issue with me, please
take it up by private email or simply keep it to yourself. Thank you.
> On Thu, Jul 28, 2011 at 7:27 AM, Perry James <perry...@computer.org> wrote:
>> You cannot view this page
I can't think of a single good reason why any of these pages should
not be world-readable. We're an open source project. It's not as if we
have trade secrets or something.
I have no problem, of course, with restricting *edit* privileges to
those with accounts that have proven to be responsible adults.
??
> Given Stu linked to the page (and is linked in the 1.3 release notes), it's
> reasonable to assume the permission error is merely a mistake and not some
> nefarious plot to withhold information from the Clojure community.
Did I say it was a "nefarious plot"?
The very fact that the web site is set up with a "You cannot view this
page" message dependent on your cookie-login and separate from the
low-level HTTP 403 error means that it's been set up to make some
information members-only. Whether that *particular* page on numerics
was intended to be members-only or not, the fact remains that
apparently some information there *is* intended to be members-only. It
is *that* that I am questioning.
Regardless, your "that wasn't called for" doesn't make much sense
since I merely stated a fact ("I can't think of ..."), another fact
("We're an open source project"), another fact (we don't have trade
secrets), and one more fact ("I have no problem, of course, with
..."). If someone is taking mere *facts* (two of which are about *me*)
personally then I'd say there may be a problem but the problem isn't
mine. :)
I can't think of a single good reason why any of these pages should
not be world-readable. We're an open source project. It's not as if we
have trade secrets or something.
I have no problem, of course, with restricting *edit* privileges to
those with accounts that have proven to be responsible adults.
Kinda hard since that expression is not valid in 1.3 anyway:ArithmeticException integer overflow
clojure.lang.Numbers.throwIntOverflow (Numbers.java:1374)So that code breaks explicitly in 1.3 and in many ways (format) is
then the least of your worries...
Er, "fast" would be for primitive integer arithmetic to wrap rather
than throw an exception or auto-promote. Both of the latter behaviors
require every math op to be accompanied by a test of some sort and a
branch (to either the exception-throwing code or the BigInt
constructing code).
Er, "fast" would be for primitive integer arithmetic to wrap rather
than throw an exception or auto-promote. Both of the latter behaviors
require every math op to be accompanied by a test of some sort and a
branch (to either the exception-throwing code or the BigInt
constructing code).
Yes. I felt the other post may have been unintentionally misleading,
by implying that checking and maybe throwing an exception was the
fastest path.
Code that runs on 1.2 but throws an exception on 1.3 is "broken" on
1.3 by definition. The fact that it can be easily "unbroken" is good
to know but it still means working code can stop working if you move
from Clojure 1.2 to 1.3. That's what I mean by 1.3 "breaks" code.
Some people are more upset by this than others (I'm not upset by it at
all, just for the record - I think the decision is the right one for
the future of Clojure).
Besides, after what I (and many others) experienced in the Scala 2.7 /
2.8 upgrade, the incompatibilities between Clojure 1.2 and 1.3 are
positively minor by comparison :)