Much cleaner....
http://www.phpit.net/article/ajax-php-without-xmlhttprequest/
Monday, November 21, 2005
Sunday, November 20, 2005
Re: Generics in Java
The other thing is that unlike C++, in Java all the checks (as you said) are done at runtime. Add to this the fact that it has a unified type system where all types (except primitives) inherit from Object makes it even more complicated. Both these are the reason for things like "? extends X" and "? super Y". You don't find these in C++ templates. Everything is checked at compile time so the compiler will warn you if the parameter types don't have expected methods. There's no need to specify that you want parameter types to extend or be the super type of some class.
This generics thread is just going to get more and more complicated. In Java, the compiler checks all* generic code at compilation time.
So if I say,
List<Integer> ints = new ArrayList<Integer>();
ints.add("a String"); //Oops... compilation error
But the bytecode generated will be similar to that generated pre Java 5 with casts inserted by the compiler.
Now there are some cases where you have no option but to make an unchecked cast to make code work. In such cases the compiler is not sure that the code/cast is wrong. So compilation is allowed with an unchecked cast warning.
class UncheckedCast<E> {
private E[] arr;
public void meth() {
arr = (E[])new Object[5]; // unchecked cast
}
}
Also....
<excerpt>
Generics for Java are accompanied by a cast-iron guarantee: no cast inserted by erasure will fail, so long as there are no unchecked warnings. The above illustrates the converse: if there are unchecked warnings, then casts inserted by erasure may fail.
</excerpt>
"? extends X" and "? super Y" are Wildcards. They are used to increase the range of Types that can be put in or removed from Generic methods/classes. This is a hack to reduce the effects of Erasure. I do not think this will be there in C++ or C#.
A slight diversion..
Does C# too have primitives? I have come across a few instances where having primitives in Java has hurt. Primitives requires having to make all special conversions and stuff. I suppose SmallTalk, Ruby are pure-OOPs wrt this.
I haven't delved too deep into how C# (.NET) has handled these situations. But I think there will be differences since the two implementations are different... no erasure, so type info is preserved. There is something called a constraint which basically allows you to declare an interface you want the parameter type to implement or inherit from some base class or specify that it has a default constructor...
Java too supports Constraints and its called Bounds. So the example Mohnish mentioned for max can be written in Java as...
public static <T extends Comparable<T>> T max (T a, T b) {
if( a.compareTo(b) < 0 )
return b;
return a;
}
Btw Comparable is an interface which takes a generic type T.
I don't remember reading about Bounds/Constraints in C++... How is a similar thing done?
About the C# Constraints...
where T : new() T must have a no-parameter constructor
Java doesn't have anything similar. It seems to be an interesting constraint which should be useful in creating types of T even though the Type T is only known at runtime.
where T : class T must be reference type (a class)
where T : class_name T may be either class_name or one of its sub-classes (or is below class_name in the inheritance hierarchy)
Could you give an example of the usage of the above Constraints. To clarify; the first constraint only takes T, and the second takes T or its sub-class.
This generics thread is just going to get more and more complicated. In Java, the compiler checks all* generic code at compilation time.
So if I say,
List<Integer> ints = new ArrayList<Integer>();
ints.add("a String"); //Oops... compilation error
But the bytecode generated will be similar to that generated pre Java 5 with casts inserted by the compiler.
Now there are some cases where you have no option but to make an unchecked cast to make code work. In such cases the compiler is not sure that the code/cast is wrong. So compilation is allowed with an unchecked cast warning.
class UncheckedCast<E> {
private E[] arr;
public void meth() {
arr = (E[])new Object[5]; // unchecked cast
}
}
Also....
<excerpt>
Generics for Java are accompanied by a cast-iron guarantee: no cast inserted by erasure will fail, so long as there are no unchecked warnings. The above illustrates the converse: if there are unchecked warnings, then casts inserted by erasure may fail.
</excerpt>
"? extends X" and "? super Y" are Wildcards. They are used to increase the range of Types that can be put in or removed from Generic methods/classes. This is a hack to reduce the effects of Erasure. I do not think this will be there in C++ or C#.
A slight diversion..
Does C# too have primitives? I have come across a few instances where having primitives in Java has hurt. Primitives requires having to make all special conversions and stuff. I suppose SmallTalk, Ruby are pure-OOPs wrt this.
I haven't delved too deep into how C# (.NET) has handled these situations. But I think there will be differences since the two implementations are different... no erasure, so type info is preserved. There is something called a constraint which basically allows you to declare an interface you want the parameter type to implement or inherit from some base class or specify that it has a default constructor...
Java too supports Constraints and its called Bounds. So the example Mohnish mentioned for max can be written in Java as...
public static <T extends Comparable<T>> T max (T a, T b) {
if( a.compareTo(b) < 0 )
return b;
return a;
}
Btw Comparable is an interface which takes a generic type T.
I don't remember reading about Bounds/Constraints in C++... How is a similar thing done?
About the C# Constraints...
where T : new() T must have a no-parameter constructor
Java doesn't have anything similar. It seems to be an interesting constraint which should be useful in creating types of T even though the Type T is only known at runtime.
where T : class T must be reference type (a class)
where T : class_name T may be either class_name or one of its sub-classes (or is below class_name in the inheritance hierarchy)
Could you give an example of the usage of the above Constraints. To clarify; the first constraint only takes T, and the second takes T or its sub-class.
Saturday, November 19, 2005
Re: Generics in Java
This blog post made me realize how little I really know about Generics in Java. Conceptually, I feel generics are easy to understand but when looking at these details, it becomes interesting i.e. confusing.
But having said this, I think it's important to take some perspective. Most Java programmers are 'consumers' of APIs. Using these generic classes isn't very difficult. It actually makes better type guarantees and is more natural to use (no messing with casts). The complications of generics only occur when you write generic APIs - this burden is borne by the 'producers'. This is in a way good since there are generally more consumers than producers, so fewer people have to understand the complexities of covariants, contravariants and invariants etc... When was the last time you wrote a generic class?
The other thing is that unlike C++, in Java all the checks (as you said) are done at runtime. Add to this the fact that it has a unified type system where all types (except primitives) inherit from Object makes it even more complicated. Both these are the reason for things like "? extends X" and "? super Y". You don't find these in C++ templates (Atleast I haven't seen them - can someone confirm?). Everything is checked at compile time so the compiler will warn you if the parameter types don't have expected methods. There's no need to specify that you want parameter types to extend or be the super type of some class.
I haven't delved too deep into how C# (.NET) has handled these situations. But I think there will be differences since the two implementations are different... no erasure, so type info is preserved. There is something called a constraint which basically allows you to declare an interface you want the parameter type to implement or inherit from some base class or specify that it has a default construtor...
public T genericMethod<T>() where T : constraint
where constraints can be...
where T : struct T must be a value type (a struct)
where T : class T must be reference type (a class)
where T : new() T must have a no-parameter constructor
where T : class_name T may be either class_name or one of its
sub-classes (or is below class_name
in the inheritance hierarchy)
where T : interface_name T must implement the specified interface
Why the need for constraints? Consider this simple ex.
public static T Max<T>( T a, T b )
{
if ( a.CompareTo( b ) < 0 )
return a;
return b;
}
This will fail at compile time. The compiler doesn't know whether a and b support the CompareTo method. There needs to be a way to limit what the parameter types can be... some constraint.
public static T Max<T>( T a, T b ) where T : IComparable
{
if ( a.CompareTo( b ) < 0 )
return a;
return b;
}
This satiates the compiler since it will make sure that when you call this method, the types of objects used as parameters implement Icomparable.
This seems like a bit of a sidetrack. I'll try and read up some more on C# generics and post any differences/similarities to covariants, contravariants and invariants.
But having said this, I think it's important to take some perspective. Most Java programmers are 'consumers' of APIs. Using these generic classes isn't very difficult. It actually makes better type guarantees and is more natural to use (no messing with casts). The complications of generics only occur when you write generic APIs - this burden is borne by the 'producers'. This is in a way good since there are generally more consumers than producers, so fewer people have to understand the complexities of covariants, contravariants and invariants etc... When was the last time you wrote a generic class?
The other thing is that unlike C++, in Java all the checks (as you said) are done at runtime. Add to this the fact that it has a unified type system where all types (except primitives) inherit from Object makes it even more complicated. Both these are the reason for things like "? extends X" and "? super Y". You don't find these in C++ templates (Atleast I haven't seen them - can someone confirm?). Everything is checked at compile time so the compiler will warn you if the parameter types don't have expected methods. There's no need to specify that you want parameter types to extend or be the super type of some class.
I haven't delved too deep into how C# (.NET) has handled these situations. But I think there will be differences since the two implementations are different... no erasure, so type info is preserved. There is something called a constraint which basically allows you to declare an interface you want the parameter type to implement or inherit from some base class or specify that it has a default construtor...
public T genericMethod<T>() where T : constraint
where constraints can be...
where T : struct T must be a value type (a struct)
where T : class T must be reference type (a class)
where T : new() T must have a no-parameter constructor
where T : class_name T may be either class_name or one of its
sub-classes (or is below class_name
in the inheritance hierarchy)
where T : interface_name T must implement the specified interface
Why the need for constraints? Consider this simple ex.
public static T Max<T>( T a, T b )
{
if ( a.CompareTo( b ) < 0 )
return a;
return b;
}
This will fail at compile time. The compiler doesn't know whether a and b support the CompareTo method. There needs to be a way to limit what the parameter types can be... some constraint.
public static T Max<T>( T a, T b ) where T : IComparable
{
if ( a.CompareTo( b ) < 0 )
return a;
return b;
}
This satiates the compiler since it will make sure that when you call this method, the types of objects used as parameters implement Icomparable.
This seems like a bit of a sidetrack. I'll try and read up some more on C# generics and post any differences/similarities to covariants, contravariants and invariants.
Friday, November 18, 2005
Re: codeWord changes??
Also I was thinking of opening codeWord more. First we can allow Anyone to post comments.
We could also publish codeWord in a few blog directories.
Both are fine by me. Anybody have objections?
We could also publish codeWord in a few blog directories.
Both are fine by me. Anybody have objections?
Thursday, November 17, 2005
codeWord changes??
I added Google Analytics to codeWord. See Google Analytics. If any of you want the info let me know.
Also I was thinking of opening codeWord more. First we can allow Anyone to post comments.
We could also publish codeWord in a few blog directories.
Suggestions?
Also I was thinking of opening codeWord more. First we can allow Anyone to post comments.
We could also publish codeWord in a few blog directories.
Suggestions?
Re: Happy Birthday CodeWord
Its been 2 yrs since CodeWord was started..
Happy (Belated) Birthday indeed!
..lets try and write blogs more often.
I'm happy we've kept it up this long, but the posts have been lean and infrequent of late. I've been a big culprit myself. We should all try to get back to the ol days of having long discussions on topics of interest. There's certainly no shortage on things to talk about.
So this is my great rallying call for the troops ala Bill Gates who does it every five years.
Happy (Belated) Birthday indeed!
..lets try and write blogs more often.
I'm happy we've kept it up this long, but the posts have been lean and infrequent of late. I've been a big culprit myself. We should all try to get back to the ol days of having long discussions on topics of interest. There's certainly no shortage on things to talk about.
So this is my great rallying call for the troops ala Bill Gates who does it every five years.
Monday, November 14, 2005
Happy Birthday CodeWord
Its been 2 yrs since CodeWord was started..
..lets try and write blogs more often.
Btw. I posted the Generics blog so that I could say the above line!!
Also I suppose I made the Generics blog a bit cryptic. Ask questions incase.
..lets try and write blogs more often.
Btw. I posted the Generics blog so that I could say the above line!!
Also I suppose I made the Generics blog a bit cryptic. Ask questions incase.
Saturday, November 12, 2005
Generics in Java
I've finally started trying to learn about the new Java 5 features...
Generics is one of the most important. There is a draft book by Oreilly at java.net - Generics and Collections in Java 5. And there are quite a few do's and dont's with Java generics. Definitely makes the language more complicated but it is needed too. Thought of sharing a few interesting excerpts here...
<excerpt>
Array subtyping is covariant, meaning that type S[] is considered to be a subtype of T[] whenever S is a subtype of T. Consider the following code fragment, which allocates an array of integers, assigns it to an array of numbers, and then attempts to assign a float into the array.
Integer[] ints = new Integer[] {1,2,3};
Number[] nums = ints;
nums[2] = 3.14; // array store exception
assert Arrays.toString(ints).equals("[1, 2, 3.14]"); // uh oh!
The subtyping relation for generics is invariant, meaning that type List<S> is not considered to be a subtype of List<T> except in the trivial case where S and T are identical. Here is a code fragment analogous to the one above, with lists replacing arrays.
List<Integer> ints = Arrays.asList(1,2,3);
List<Number> nums = ints; // compile-time error
nums.put(2, 3.14);
assert ints.toString().equals("[1, 2, 3.14]"); // uh oh!
</excerpt>
It is obvious that invariant behavior in generic limits is usefulness. So wildcards can be used to introduce covariant behavior.
<excerpt>
Wildcards reintroduce covariant subtyping for generics, in that type List<S> is considered to be a subtype of List<? extends T>, when S is a subtype of T. Here is a third variant of the fragment.
List<Integer> ints = Arrays.asList(1,2,3);
List<? extends Number> nums = ints;
nums.put(2, 3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]"); // uh oh!
</excerpt>
And it gets even more interesting when...
<excerpt>
Wildcards also introduce contravariant subtyping for generics, in that type List<S> is considered to be a subtype of List<? super T>, when S is a supertype of T (as opposed to a subtype). Arrays do not support contravariant subtyping.
</excerpt>
So there are quite a few differences between Arrays and Generic Collections in Java and the author suggests using only Collections. The covariant and contravariant behavior is used to increase the range of Types that can be used by a Collection of type <T>.
The covariant behavior (<? extends T>) is used to get types from a colletion.
<excerpt>
Here is a method that takes a collection of numbers, converts each to a double, and sums them up.
public static double sum(Collection<? extends Number> nums) {
double s = 0.0;
for (Number num : nums) s += num.doubleValue();
return s;
}
Since this uses extends, all of the following calls are legal.
List<Integer> ints = Arrays.asList(1,2,3);
assert sum(ints) == 6.0;
List<Number> nums = Arrays.<Number>asList(1,2,2.78,3.14);
assert sum(nums) == 8.92;
</excerpt>
So if I have a Collection of a type which extends Number, I know I can atleast safely remove type Number. This is what the author calls the Get principle.
The contravariant behavior (<? super T>) is used to put types into a colletion; which is analogous to the above behavior.
<excerpt>
Here is a method that takes a collection of numbers and an integer n, and puts the first n integers, starting from zero, into the collection.
public static void count(Collection<? super Integer> ints, int n) {
for (int i = 0; i < n; i++) ints.add(i);
}
Since this uses super, all of the following calls are legal.
List<Integer> ints = new ArrayList<Integer>();
count(ints, 5);
assert ints.toString().equals("[0, 1, 2, 3, 4]");
List<Object> objs = new ArrayList<Object>();
count(objs, 5); objs.add("five");
assert objs.toString().equals("[0, 1, 2, 3, 4, five]");
</excerpt>
So if I have a Collection of a type which super Integer, I know I can safely add type Integer. This is what the author calls the Put principle.
Incase a method has to both Get and Put into a same Collection, then wildcards cannot be used. Btw in this blog wherever I have used interesting you can substitute confusing. Yet with a little time and practice generic in Java should not be that tough.
A lot of this is caused because generic in Java is implemented using Erasure in which the type (<T>) is basically removed and casts are added by the compiler. So at runtime there is no info of the type. There are many more quirks caused due to Erasure... but this much is scary enough for one blog.
Could you guys compare generic in C# and C++. Also Mohn what are the new features in C#??
Generics is one of the most important. There is a draft book by Oreilly at java.net - Generics and Collections in Java 5. And there are quite a few do's and dont's with Java generics. Definitely makes the language more complicated but it is needed too. Thought of sharing a few interesting excerpts here...
<excerpt>
Array subtyping is covariant, meaning that type S[] is considered to be a subtype of T[] whenever S is a subtype of T. Consider the following code fragment, which allocates an array of integers, assigns it to an array of numbers, and then attempts to assign a float into the array.
Integer[] ints = new Integer[] {1,2,3};
Number[] nums = ints;
nums[2] = 3.14; // array store exception
assert Arrays.toString(ints).equals("[1, 2, 3.14]"); // uh oh!
The subtyping relation for generics is invariant, meaning that type List<S> is not considered to be a subtype of List<T> except in the trivial case where S and T are identical. Here is a code fragment analogous to the one above, with lists replacing arrays.
List<Integer> ints = Arrays.asList(1,2,3);
List<Number> nums = ints; // compile-time error
nums.put(2, 3.14);
assert ints.toString().equals("[1, 2, 3.14]"); // uh oh!
</excerpt>
It is obvious that invariant behavior in generic limits is usefulness. So wildcards can be used to introduce covariant behavior.
<excerpt>
Wildcards reintroduce covariant subtyping for generics, in that type List<S> is considered to be a subtype of List<? extends T>, when S is a subtype of T. Here is a third variant of the fragment.
List<Integer> ints = Arrays.asList(1,2,3);
List<? extends Number> nums = ints;
nums.put(2, 3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]"); // uh oh!
</excerpt>
And it gets even more interesting when...
<excerpt>
Wildcards also introduce contravariant subtyping for generics, in that type List<S> is considered to be a subtype of List<? super T>, when S is a supertype of T (as opposed to a subtype). Arrays do not support contravariant subtyping.
</excerpt>
So there are quite a few differences between Arrays and Generic Collections in Java and the author suggests using only Collections. The covariant and contravariant behavior is used to increase the range of Types that can be used by a Collection of type <T>.
The covariant behavior (<? extends T>) is used to get types from a colletion.
<excerpt>
Here is a method that takes a collection of numbers, converts each to a double, and sums them up.
public static double sum(Collection<? extends Number> nums) {
double s = 0.0;
for (Number num : nums) s += num.doubleValue();
return s;
}
Since this uses extends, all of the following calls are legal.
List<Integer> ints = Arrays.asList(1,2,3);
assert sum(ints) == 6.0;
List<Number> nums = Arrays.<Number>asList(1,2,2.78,3.14);
assert sum(nums) == 8.92;
</excerpt>
So if I have a Collection of a type which extends Number, I know I can atleast safely remove type Number. This is what the author calls the Get principle.
The contravariant behavior (<? super T>) is used to put types into a colletion; which is analogous to the above behavior.
<excerpt>
Here is a method that takes a collection of numbers and an integer n, and puts the first n integers, starting from zero, into the collection.
public static void count(Collection<? super Integer> ints, int n) {
for (int i = 0; i < n; i++) ints.add(i);
}
Since this uses super, all of the following calls are legal.
List<Integer> ints = new ArrayList<Integer>();
count(ints, 5);
assert ints.toString().equals("[0, 1, 2, 3, 4]");
List<Object> objs = new ArrayList<Object>();
count(objs, 5); objs.add("five");
assert objs.toString().equals("[0, 1, 2, 3, 4, five]");
</excerpt>
So if I have a Collection of a type which super Integer, I know I can safely add type Integer. This is what the author calls the Put principle.
Incase a method has to both Get and Put into a same Collection, then wildcards cannot be used. Btw in this blog wherever I have used interesting you can substitute confusing. Yet with a little time and practice generic in Java should not be that tough.
A lot of this is caused because generic in Java is implemented using Erasure in which the type (<T>) is basically removed and casts are added by the compiler. So at runtime there is no info of the type. There are many more quirks caused due to Erasure... but this much is scary enough for one blog.
Could you guys compare generic in C# and C++. Also Mohn what are the new features in C#??
Monday, November 07, 2005
Subscribe to:
Posts (Atom)