Robert McIntyre <r...@mit.edu> writes:

> So there's some sort of "boxing" going on here where the nil produced
> as the values of s-expressions are actually Objects which are nulls,
> while literal nils are actually nulls?

No, there's no boxing going on.  They're both just regular Java nulls
(and null is not an Object).  The only difference is in the byte code
generation: which constructor gets picked (if any).  It seems as if the
runtime reflection code when encountering a null will just pick the
first constructor it sees, while the compile-time code notices the
ambiguity and throws an error.

It's kind of annoying that you can't type-hint the nil too.

  (Thread. ^Runnable nil) ; error, nil can't hold metadata

and have to resort to binding it and hinting the binding.

  (let [^Runnable s nil] (Thread. s)) ; ok

> Such as in java where:
>
>               Object t = null;
>               Thread r = new Thread((String) t);
>
> is valid but
>
>               Thread r = new Thread(null);
> is not ?

In this case you've explicitly told Java the type with a string cast so
it can generate bytecode that refers the String constructor.  You can do
that directly too:

                Thread r = new Thread((String) null);

Being statically typed Java never does runtime reflection (unless you
explicitly code it) so this issue cannot actually arise in it.

> Isn't this breaking referential transparency that (Thread. ((fn [])))
> and (Thread. nil) are not the same (you can't replace a function call
> with it's value in this case)?  This is not the behaviour I would
> expect at all, as it would make any clojure function with a nil in
> it's range no longer pure.

Ambiguous code is arguably "invalid" in some sense anyway when running
on a deterministic machine model, so I'm not sure it makes sense to talk
about the purity of it.

Suppose I do this and never actually call the resulting fn, just throw
it away:

  #(Thread. nil) ; throws an error at compile time

  #(Thread. (identity nil)) ; doesn't and can't

How could they be made consistent?  I guess either:

1) Resolve the ambiguity by consistently picking one of the constructors
(perhaps the first alphabetically).

2) Delay the exception throwing in the direct nil case to runtime, so
the compiler would replace the form with:

    #(throw (java.lang.IllegalArgumentException.))

And have the reflection code in the second detect ambiguity and throw at
runtime 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

Reply via email to