andrewducker: (Engineering like maths but louder)
[personal profile] andrewducker
In C# I can create a dictionary that has ints as keys and strings as the values. I can then look up the value of any string using the int key. Dead simple. If I want an array I can use something like myDictionary.Values.ToArray() and I get all of the values in a string[], because it knows what type everything is. That's what generics are _for_.

Providing I am using Java correctly, I'm creating a HashMap<long,string> (and it has to be a Long, because you can't use primitive types, for some bizarre reason), and then the "put" method does, indeed, mandate that I'm using a Long and a String, but the "get" takes an object, and the toArray returns an array of _objects_. What the fuck? What is the point of specifying types if the compiler is going to just ignore them?

I feel terribly spoiled by working with a language which does what you bloody well tell it to, rather than being a half-assed job to give you the appearance of doing something useful without finishing the job.

Date: 2012-01-30 02:11 am (UTC)
From: [personal profile] j_v_lynch
So, after reading this, I had to go and verify it for myself.

That is pretty silly. I'm sure it has something to do with backwards compatibility as that was a feature that didn't even exist until 1.5, but yeah.

Now I am really curious why it was done that way.

Date: 2012-01-30 05:44 am (UTC)
From: [identity profile] sarahs-muse.livejournal.com
Sorry I'm not much help - perhaps there's something key the reference manual misses?

I know you're going to hate this - but if you implemented a small class that does what you want, it'll get Java more C# like, and you wont need to write it again - but I know the answer would be "I shouldn't have to!" =)

Date: 2012-01-30 07:28 am (UTC)
From: [identity profile] johnbobshaun.livejournal.com
Hmm.

Surely you can use HashMap
[Error: Irreparable invalid markup ('<integer,string>') in entry. Owner must fix manually. Raw contents below.]

Hmm.

Surely you can use HashMap<Integer,String> instead of <HashMap int,String>?

And don't you need to be using getKey() and getValue()?

I would have expected that array of objects to be set entries where you could get the values by going andysArray[0].getValue() -> Returns string.

Depends what you're trying to do on the array side, but if you wanted the values of the Hashmap in an array I guess it would be something like andysHashMap.getValues().toArray(); I would *hope* that would give you an array of Strings.

Date: 2012-01-30 09:24 am (UTC)
From: [identity profile] johnbobshaun.livejournal.com
...and the Collection< string > you get from values() is no use to you?

The primitives not being objects is... a quirk. And I agree, it's pretty freaking dumb.

/J
Edited Date: 2012-01-30 09:27 am (UTC)

Date: 2012-01-30 12:17 pm (UTC)
From: [identity profile] johnbobshaun.livejournal.com
Let me put it this way: C# is Java with hindsight :-)

Date: 2012-01-30 02:08 pm (UTC)
simont: A picture of me in 2016 (Default)
From: [personal profile] simont
OK, this may be a stupid question, since I'm mostly a C/C++ programmer, my Java is minimal and out of date and my C# more or less nonexistent, and I haven't read the JVM or CLR specs or the full detail of what Java generics do. So perhaps anyone minimally educated on the subject would find this obvious and I should just go away and come back when I've done some reading.

But ... how on earth did they manage to set things up so that the virtual machine had to have specific support for this sort of detail in the high-level language's type system?

I can see that the JVM has to be at least a little higher-level than anything looking like a real CPU architecture, since it has to implement bounds checking and garbage collection and so on and hence has to retain at least some semantic information about what is and isn't a pointer and what size objects are and so forth. And I'm prepared to accept that there might be some other constraint along the same sort of lines that requires the JVM to know about and collude in details of the language(s) being compiled to it.

But even so ... surely any feature of a type system to make it implement parametrised types could be completely desugared at compile time, by converting every referred-to instance of such a type (e.g. HashMap<thistype,thattype>) into a separate concrete type (say, __AutoGeneratedHashMapType312), and likewise for methods taking an incompletely specified type argument? More or less the same way C++ compilers do it. I don't see why the JVM should need to know that a bunch of __AutoGeneratedTypeX things all originally stemmed from the same twenty lines of the source code; as long as it can execute it, that's surely enough?

Date: 2012-01-30 02:22 pm (UTC)
simont: A picture of me in 2016 (Default)
From: [personal profile] simont
However, having it in the underlying bytecode/IL means that when you are calling things written in one language from something written in another language, they both understand.

Ah, I see. It wasn't obvious to me from your original post that you were trying to use multiple JVM-targeted languages, so that might be what I missed.

(Though if you enshrine your type system in the VM, that may improve interoperability between languages targeting the VM, but I'm guessing it also limits the languages that can target that VM? Particularly excitingly cutting-edge functional languages with really advanced and weird type systems...)

C# does not generate a separate class for List<String>, List<int> and List<Doggie> - they are all the same class, with a type annotation.

This probably is where I should go and read up more carefully, but ... is there a visible consequence within C# itself of drawing that distinction, or is it only relevant when you're looking at the compiled bytecode?
Edited Date: 2012-01-30 02:23 pm (UTC)

Date: 2012-01-30 02:31 pm (UTC)
simont: A picture of me in 2016 (Default)
From: [personal profile] simont
Drawing which distinction?

The distinction between Foo<bar> and Foo<quux> being different classes and the same class with an annotation. Surely even in the latter case I'd want my language to ensure they were assignment-incompatible, for instance.

(Or is there some exciting case involving asymmetric type compatibility, such as being able to assign only one way between Foo<SomeBaseClass> and Foo<SomeSubclass>?)
Edited Date: 2012-01-30 02:32 pm (UTC)

Date: 2012-01-30 07:41 pm (UTC)
From: [identity profile] danmilburn.livejournal.com
If I create a Vector in two different libraries, how does it allow me to assign one to the other?

Not sure what you mean here. If you instantiate a std::vector templated on the same type, it's the same type in both libraries.

There is no automatic way of assigning a vector of one type to a vector of a different type.

Date: 2012-01-30 07:54 pm (UTC)
From: [identity profile] danmilburn.livejournal.com
Yes it does, but, say, vector<double>, is the same type wherever it's instantiated. If you have different libraries then the generated code will be duplicated, but I guess the system is clever enough to deal with that.
Edited Date: 2012-01-30 07:55 pm (UTC)

Date: 2012-01-31 08:44 am (UTC)
From: [identity profile] danmilburn.livejournal.com
Where things can get fun is if the libraries were built with different compiler options or preprocessor defines. The generated code for the same template might well be different in that case, and who knows what might happen. Best case is generally that linking against the libraries fails completely. Worst case is weird runtime behaviour and hard to find bugs. Unfortunately the worst case is all too common when it comes to C++ - the standard specifies 'undefined behaviour' for a ridiculous number of cases.

I like being a C++ programmer, but I certainly don't recommend it. :)

Date: 2012-01-31 11:25 am (UTC)
From: [identity profile] cartesiandaemon.livejournal.com
If I create a Vector in two different libraries, how does it allow me to assign one to the other?

I program in C++, but I'm still distressingly ignorant of this sort of compiler stuff. I think we may, here, have hit the inter-cultural misunderstanding...

I'm not sure you can automatically do that in C++. Trying to think it through, it seems like, if you want Library A and Library B to make function calls to each other then they need to be the same in all sorts of little binary things like "when you make a function call, what order do things go on the stack" and "how many bytes is an int" and "what name does the compiler use internally for this user function" let alone "how a vector of ints is normally stored in memory" etc, etc. And in Java and .NET this just automatically works, because all of those things are specified in the standard (or not even needed because everything is bytecode). But in C and C++, the language makes no guarantees whatsoever about those things, it's all agreed (or not) by conventions between compiler vendors, but it's not part of the language standard. And I don't know how wide those agreements are, though it's the sort of thing you need to know if you write libraries.

If so, the advantage of java is that you CAN use a library produced by someone else and it will Just Work. But the advantage of C++ is that if you DO manage to get it to compile, you have a higher chance that the vector of ints will produce no code whatsoever -- it will be compiler optimised to a pointer and an array offset used directly by each place that accesses it. However, this only works when everything is compiled by the same compiler (and often not even then, because it's hard to do that sort of optimisation across lots of different files), so there IS a need standards between different libraries -- they're just not universal, or easy...

Date: 2012-01-30 01:00 pm (UTC)
From: [identity profile] johnbobshaun.livejournal.com
I *am* puzzled as to why you would need an array specifically, not a Collection though.

I have no idea what arrays are like in C# but I honestly can't recall ever using one directly in Java. Always an ArrayList, Vector, Set or whatever instead.

Maybe that's just me.

Date: 2012-01-30 01:36 pm (UTC)
From: [identity profile] johnbobshaun.livejournal.com
You just want the first element in a HashMap?

List vals = new ArrayList(myDictionary.getValues());
value = vals.get(0);

I guess. Or maybe:

value = myDictionary.getValues().Iterator().next() ?

The problem is that the getValues() returns a Collection which is just a bunch of stuff that you can iterate through rather than a List.

That's just off the top of my head though: sorry if any of it's no right.





Date: 2012-01-30 01:41 pm (UTC)
From: [identity profile] johnbobshaun.livejournal.com
Also, I've never used it myself, but you might find something a bit more to your liking in Guava:

http://code.google.com/p/guava-libraries/wiki/GuavaExplained?tm=6

Date: 2012-01-30 07:37 pm (UTC)
From: [identity profile] danmilburn.livejournal.com
The problem is that the getValues() returns a Collection which is just a bunch of stuff that you can iterate through rather than a List.

I don't really see that this is a problem. The returned collection is unordered (and is probably a reference to the map's internal data structures, the docs say the returned collection changes if the map does), so there is no 'first element' to access.

You might find it inconvenient, but it's conceptually correct and more efficient than turning into a list/array automatically.

Date: 2012-01-30 09:52 pm (UTC)
From: [identity profile] thaxor.livejournal.com
http://stackoverflow.com/questions/857420/what-are-the-reasons-why-map-getobject-key-is-not-fully-generic

Mind you, I'm not convinced that this is a good example of "conservative in what you do, liberal in what you expect from others", and one of the posters claims.

March 2026

S M T W T F S
1 2 3 4 56 7
891011121314
15161718192021
22232425262728
293031    

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Mar. 9th, 2026 09:25 am
Powered by Dreamwidth Studios