strange typecheck error

2 views
Skip to first unread message

Alex Ott

unread,
Dec 30, 2009, 12:53:07 PM12/30/09
to Clojure ML
Hello all

I have strange problem with type inference in Clojure. I have following
code (simplified version of real code),


(defn- process-char [#^InputStream istream]
(let [ch (.read istream)]
(if (= ch 10)
"AAA"
ch)))

(defn- process-text [#^InputStream istream]
(loop [char (.read istream)]
(let [result (process-char istream)]
(cond
;; .. some additional conditions
(string? result) (loop (.read istream))
(number? result) (loop result)
...))))

Main idea, that in some function, i read characters in sequence, and check
their values, and in some conditions, i need to re-submit already readed
character into loop, but when i use code above, i get following error:

java.lang.IllegalArgumentException: recur arg for primitive local: char must be matching primitive
[Thrown class java.lang.RuntimeException]


but if i replace (loop result) with (.read istream), then it works without
any problems

I checked type of result, and it's Integer - same type, that 'char' var in
loop will get after reading from stream.

If need, i can submit somebody full test case

--
With best wishes, Alex Ott, MBA
http://alexott.blogspot.com/ http://xtalk.msk.su/~ott/
http://alexott-ru.blogspot.com/

Nikolay Petrov

unread,
Dec 30, 2009, 1:13:13 PM12/30/09
to clo...@googlegroups.com
Is process char returns char or String?
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Sent from my BlackBerry® wireless device

.Bill Smith

unread,
Dec 30, 2009, 2:28:54 PM12/30/09
to Clojure
Sorry, I'm confused by the code sample. I see several loops but no
corresponding recurs.

rzez...@gmail.com

unread,
Dec 30, 2009, 6:53:55 PM12/30/09
to Clojure

On Dec 30, 12:53 pm, Alex Ott <alex...@gmail.com> wrote:
>
> If need, i can submit somebody full test case


I think this might help because it's hard to tell what you are trying
to do without a little more context.

Some odd things that stand out to me:

1) You call loop, but you should be calling recur. E.g. (loop result)
2) Why are the arguments streams and not readers?
3) You do nothing with the 'char' variable binding.

My guess is you just made some typos while trying to create a simple
example.

Alex Ott

unread,
Dec 31, 2009, 4:25:45 AM12/31/09
to clo...@googlegroups.com

Nikolay Petrov at "Wed, 30 Dec 2009 18:13:13 +0000" wrote:
NP> Is process char returns char or String?

I want to return either String, either Integer, depending on condition...

Alex Ott

unread,
Dec 31, 2009, 4:34:31 AM12/31/09
to clo...@googlegroups.com
Hello

I'm sorry, i tried to prepare shorter example, and mixed loops & recurs.
Full example is attached. This is code, that implements something like
'strings' command on Unixes, but for UTF-8 encoding

The problem is, that i need to return from function 'read-utf-char', either
String, either Integer, depending on condition. Or this is not allowed by
Clojure? I mostly programming in Scheme, that allows such tricks

.Bill Smith at "Wed, 30 Dec 2009 11:28:54 -0800 (PST)" wrote:
.S> Sorry, I'm confused by the code sample. I see several loops but no
.S> corresponding recurs.

test1.clj

.Bill Smith

unread,
Dec 31, 2009, 12:20:16 PM12/31/09
to Clojure
I tried out your example with a couple of files and it appeared to
work. Is it supposed to fail, or is this an example of what you had
to do to work around the problem you mentioned?

It's certainly ok for a function to return different data types. I
guess the simplest example of that would be the identity function.

user=> (identity 5)
5
user=> (identity "x")
"x"

Here is another one:

user=> (defn return-string-or-num [flag] (if flag "x" 0))
#'user/return-string-or-num
user=> (return-string-or-num :t)
"x"
user=> (return-string-or-num nil)
0

Here is an example of using that function with recur:

user=> (loop [x 0
count 0]
(println "x=" x "x is a" (class x) "count=" count)
(if (< count 10)
(recur (return-string-or-num (even? count))
(inc count))))
x= 0 x is a java.lang.Integer count= 0
x= x x is a java.lang.String count= 1
x= 0 x is a java.lang.Integer count= 2
x= x x is a java.lang.String count= 3
x= 0 x is a java.lang.Integer count= 4
x= x x is a java.lang.String count= 5
x= 0 x is a java.lang.Integer count= 6
x= x x is a java.lang.String count= 7
x= 0 x is a java.lang.Integer count= 8
x= x x is a java.lang.String count= 9
x= 0 x is a java.lang.Integer count= 10
nil
user=>

Alex Ott

unread,
Dec 31, 2009, 1:45:40 PM12/31/09
to clo...@googlegroups.com
Hello Bill

.Bill Smith at "Thu, 31 Dec 2009 09:20:16 -0800 (PST)" wrote:
.S> I tried out your example with a couple of files and it appeared to
.S> work. Is it supposed to fail, or is this an example of what you had
.S> to do to work around the problem you mentioned?

Yes, this is working variant

if you'll replace '(.read ireader)' in 'recur' on line 80 with 'res', then
it will fail.

.S> It's certainly ok for a function to return different data types. I
.S> guess the simplest example of that would be the identity function.

thanks for identity example, i'll look to it

P.S. Happy New Year to you, and rest of clojure community

--

.Bill Smith

unread,
Jan 1, 2010, 1:44:37 PM1/1/10
to Clojure
Happy New Year to you, Alex.

I reproduced the problem as follows:

user=> (loop [x (byte 0) count 0]
(if (< count 10) (recur 0 (inc count))))
java.lang.RuntimeException: java.lang.IllegalArgumentException: recur
arg for primitive local: x must be matching primitive (NO_SOURCE_FILE:
57)
user=>

If the compiler detects that a loop binding evaluates to a primitive,
it insists that the corresponding recur argument be a reducible to a
primitive as well. You can short-circuit that logic with a type hint,
like this:

user=> (loop [x #^Object (byte 0)]
(if (< x 10) (recur (inc x))))
nil
user=>

It's ugly but it works. If you change line 65 in your example from
"char (.read ireader)]" to "char #^Object (.read ireader)]", the
compile error should go away. The example in my previous posting
didn't have that problem because 0 by itself is an Integer object, not
an int primitive.

On Dec 31 2009, 12:45 pm, Alex Ott <alex...@gmail.com> wrote:
> Hello Bill
>
> .Bill Smith  at "Thu, 31 Dec 2009 09:20:16 -0800 (PST)" wrote:
>  .S> I tried out your example with a couple of files and it appeared to
>  .S> work.  Is it supposed to fail, or is this an example of what you had
>  .S> to do to work around the problem you mentioned?
>
> Yes, this is working variant
>
> if you'll replace '(.read ireader)' in 'recur' on line 80 with 'res', then
> it will fail.
>
>  .S> It's certainly ok for a function to return different data types.  I
>  .S> guess the simplest example of that would be the identity function.
>
> thanks for identity example, i'll look to it
>
> P.S. Happy New Year to you, and rest of clojure community
>
> --

Alex Ott

unread,
Jan 2, 2010, 8:58:47 AM1/2/10
to clo...@googlegroups.com
Many thanks to you Bill - it works!

.Bill Smith at "Fri, 1 Jan 2010 10:44:37 -0800 (PST)" wrote:
.S> Happy New Year to you, Alex.

.S> I reproduced the problem as follows:

.S> user=> (loop [x (byte 0) count 0]
.S> (if (< count 10) (recur 0 (inc count))))
.S> java.lang.RuntimeException: java.lang.IllegalArgumentException: recur
.S> arg for primitive local: x must be matching primitive (NO_SOURCE_FILE:
.S> 57)
.S> user=>

.S> If the compiler detects that a loop binding evaluates to a primitive,
.S> it insists that the corresponding recur argument be a reducible to a
.S> primitive as well. You can short-circuit that logic with a type hint,
.S> like this:

.S> user=> (loop [x #^Object (byte 0)]
.S> (if (< x 10) (recur (inc x))))
.S> nil
.S> user=>

.S> It's ugly but it works. If you change line 65 in your example from
.S> "char (.read ireader)]" to "char #^Object (.read ireader)]", the
.S> compile error should go away. The example in my previous posting
.S> didn't have that problem because 0 by itself is an Integer object, not
.S> an int primitive.

--

Reply all
Reply to author
Forward
0 new messages