|
[
Permalink
| « Hide
]
Jim White added a comment - 25/Dec/08 03:50 PM
Converted to a GroovyTestCase.
groovy -v
Groovy Version: 1.6-RC-1 JVM: 1.6.0_11 groovy Groovy3237Bug.groovy at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:373) and .E at org.codehaus.groovy.runtime.InvokerHelper.assertFailed(InvokerHelper.java:393)
PrintWriter#print(ln) does not go through the DGM whereas other Writers do. So PrintWriter output does not respect the InvokerHelper#toString() The trouble is that Groovy is not actually calling String.valueOf(Object) when the parameter is a BigInteger. Don't know why. I'll open a separate issue for that specifically because I want to keep this issue on bringing order to println.
String.valueOf() in the above test case is used to mimic the behaviour of PrintWriter to ensure that PrintWriter and other Writers produce the same output.
It is questionable if String.valueOf() should actually be used to implement print(ln) methods in the GDK since it bypasses the MOP and hence does not respect the possibly dynamic nature of Groovy objects. However, to be consistent Writer#print(ln) must produce the same output as PrintWriter#print(ln). I'm not sure if the special handling of PrintWriter could be turned off easily. See also Yes, it acts like there is a MOP override of String.valueOf(BigInteger) although I don't know where that code is. And if there is such an override, that is a bug because Groovy has no business making incompatible changes in that fundamental Java API. One of the reasons such a change can't/shouldn't be done is that there is no way to get Java code (like PrintWriter) to use it.
But I don't think it is actually an intentional override, like i just commented in Oh, and the current implementation of DGM print(ln) uses InvokerHelper.toString which does a bunch of Groovy-specific formatting stuff that is different than the toString for those classes. That is part of the helter-skelter state of Groovy formatting and means that we're unlikely to get PrintWriter and String.valueOf doing exactly what they're supposed to do any time soon. After the fix of
The last remaining thing that is failing in the given test is following call: doTest(["foo" : "bar", "true": true, "int": new Integer(1234)]) and the reason this is failing is because of the map param's formatting done by groovy, as in the code below def map = ["foo" : "bar", "true": true, "int": new Integer(1234)] // output of the following produced by java.lang.String.valueOf(Object) is {foo=bar, true=true, int=1234} println String.valueOf(map) // output of the following produced by groovy's InvokerHelper.formatMap is [foo:bar, true:true, int:1234] println map Why does Groovy have its own logic for formatting maps? Couldn't it simply delegate to java's implementation to be consistent in such formatting? Groovy likes to display them it's own way. This (along with arrays) has been an area being cleaned up. I've found additional issues related to this but haven't had time to detail them here yet.
I don't think Groovy is going to give up on it's special output formatting, but I think we can get to a more consistent approach. The short version of what I think we need to do is define a GroovyPrintWriter which will work the same way as our non-PrintWriter print methods. A plain PrintWriter is not going to be able to do the same thing as Groovy does when it converts things to strings. I have committed a first attempt at bringing order to this printing situation (cs14792). There are several decisions that are somewhat arbitrary, and several difficult ones that I have deferred until you folks weigh in on these changes.
There are three significant new features:
So the idea here is that whatever you print with GroovyPrintWriter or DGM.print will be the same as the String you get from Object as String. That is very much like the relationship PrintWriter and String.valueOf(Object) have. It is also consistent with as doing "groovy" formatting. So we have a some consistent rules now and they can be seen in PrintTest.groovy. Probably the most significant remaining issue is that arrays of primitives are not displayed the same way as arrays of objects. The arrays of primitives are coerced to lists and are displayed that way with square brackets. Arrays of objects are displayed with curly braces. If we want the curly braces to signify "array", then it should apply to array of primitive too.
In that same vein, while char[] is now displayed like a string, Character[] is not. I think that it should display the same as char[] and the PrintWriter.print(char[]) style (like a string) is the way to go. OTOH, there are cases where you may want to display individual characters as an array, so perhaps leaving Character[] the way it is now is better. A summary of the current (trunk) state of affairs:
Once this settles down, an optimization in the DGM.print methods will be to convert directly to strings and use the Writer rather than constructing GroovyPrintWriters. And finally I haven't addressed PrintStream, but it probably needs GroovyPrintStream in order to match what the DGM.print methods do when they don't get a Writer (which is to format as string and print to System.out). Committed to trunk (cs14863) what seems to be most of the changes and a test case that demonstrates what I think the API is supposed to be.
A key difference btw Groovy print and Java print is that Groovy is defined in terms of Object.toString() rather than String.valueOf(Object). That is a necessary difference because Groovy can't override a static method. And this works out OK because in Groovy null.toString() results in "null" (rather than a NPE) which is one of the key virtues of valueOf. Furthermore Groovy code that wants the Java string for an object rather than the Groovy style can still call String.valueOf. That would also be necessary for large and/or recursive structures which Groovy will currently do poorly with (for another JIRA). There are now DGM for PrintStream.print and PrintStream.println so that Groovy code that does a System.out.println(Object) will work just like println(Object). |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||