0

So I was trying this:

user=> (Integer/toBinaryString ^int (.charValue \c))
"1100011"
user=> 

And I thought... Well, that looks promising, so let's try this now:

user=> (map #(Integer/toBinaryString ^int (.charValue %)) "some")

ClassCastException java.lang.Character cannot be cast to java.lang.Number  user/eval1209/fn--1210 (form-init3852254868488042860.clj:1)
user=> ; Tried this as well. But without luck:
user=> (map #(Integer/toBinaryString ^int (.charValue %)) (.toCharArray "some"))

ClassCastException java.lang.Character cannot be cast to java.lang.Number  user/eval1249/fn--1250 (form-init3852254868488042860.clj:1)
user=> 

oops! WTF is going on?

I have the thing working after introducing a hack:

user=> (map #(Integer/toBinaryString ^int (.charValue (Character/valueOf %))) "some")
("1110011" "1101111" "1101101" "1100101")
user=> ; Or alternatively:
user=> (map (fn [^Character c] (Integer/toBinaryString ^int (.charValue c))) "some")
("1110011" "1101111" "1101101" "1100101")
user=> ; Or:
user=> (map #(Integer/toBinaryString ^int (.charValue ^Character %)) "some")
("1110011" "1101111" "1101101" "1100101")
user=> 

So, does anyone know why this just won't work without calling Character/valueOf or explicitly casting?

1
  • trying your very first statement in web.clojurerepl.com gives the same ClassCastException as your map version. ^int is not a cast. your type hint isn't converting to int. I'm not sure why you're getting a result for this at all on your first statement Commented May 16, 2015 at 10:46

1 Answer 1

1

Type hints aren't meant to change a program's semantics. The supposed way to convert a character to a number in Clojure is the int function.

Example:

user=> (map #(-> % int Integer/toBinaryString) "some")
("1110011" "1101111" "1101101" "1100101")

So to be clear, in Clojure, chars are supposed to always be autoboxed into Characters which aren't numbers. The weird part in your code is therefore not when treating chars as numbers doesn't work, but when it does, because in those cases the type hints change the semantics of your code which they aren't supposed to.

Sign up to request clarification or add additional context in comments.

6 Comments

Exactly my question. Why is it I have to cast a Character to a Character in order for it to work as I posted it? (Also, I like your solution a lot better. Thanks :)
@dsm: Like I said, type hints are not casts, they aren't supposed to change behaviour but rather exclusively support compiler optimizations. In this case though, you were sometimes able to trigger what is basically implementation-dependant behaviour, i.e. to use the toBinaryString method on the result of .charValue, even though in Clojure the result of .charValue isn't supposed to be a number.
The problem is not there. I knew I had to coerce it in that place as toBinaryString is a java.lang.Number static method, hence the cast/type-hint. The exception arises when the anonymous function takes a Character as an argument to .charValue. This is what I am finding really hard to get my head around. Looks like a bug, TBH.
Continued: But it only happens when the call is nested, hence the slightly convoluted example. If you try plain old (map #(.charValue %) "some") you get the expected result.
Either that or I'm misreading the exception, which is a real possibility as it says cannot cast from Character to Number...
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.