Discussion:
[groovy-dev] groovysh display of recursive data structures
Thibault Kruse
2015-02-22 14:00:01 UTC
Permalink
Hi,

currently groovysh does not handle recursive datastructures too well.


This works:

groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, d)
===> null
groovy:000> d
[1: (this map)]


but this does not:

groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, [d])
===> null
groovy:000> d
null // or StackOverflowError displayed, depending on Groovy Version

The class https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
is responsible for the rendering of structures (since java's
toString() is not used).

There are several ways to handle this, one is to catch
StackOverFlowError (either deep in the recursion or at the top).
Another way is to leave things as they are now.

The last way is to properly detect cycles, meaning each recursive
invocation gets a List of all Objects already in the process of being
rendered, and so method calls produce a placeholder token for any
element being rendered recursively. This would mean adding a new
function like

private static String formatWithouCycles(Object arguments, boolean
verbose, int maxSize, Collection itemsInProgress) {...}
and extending all the private static methods to honor the collection.

And some placeholder token would be required '(this map)' would not do anymore.

Thoughts?

regards,
Thibault
x = {}
x[1] = x
x
{1: {...}}

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Thibault Kruse
2015-03-15 15:43:25 UTC
Permalink
Bump.

This also affects any other Groovy code that prints recursive structures.

def d = [:]
d.put(1, [d])
println(d)

So should I try to create a change of the InvokerHelper that handles
recursions in the same way python does?

On Sun, Feb 22, 2015 at 3:00 PM, Thibault Kruse
Post by Thibault Kruse
Hi,
currently groovysh does not handle recursive datastructures too well.
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, d)
===> null
groovy:000> d
[1: (this map)]
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, [d])
===> null
groovy:000> d
null // or StackOverflowError displayed, depending on Groovy Version
The class https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
is responsible for the rendering of structures (since java's
toString() is not used).
There are several ways to handle this, one is to catch
StackOverFlowError (either deep in the recursion or at the top).
Another way is to leave things as they are now.
The last way is to properly detect cycles, meaning each recursive
invocation gets a List of all Objects already in the process of being
rendered, and so method calls produce a placeholder token for any
element being rendered recursively. This would mean adding a new
function like
private static String formatWithouCycles(Object arguments, boolean
verbose, int maxSize, Collection itemsInProgress) {...}
and extending all the private static methods to honor the collection.
And some placeholder token would be required '(this map)' would not do anymore.
Thoughts?
regards,
Thibault
x = {}
x[1] = x
x
{1: {...}}
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Pascal Schumacher
2015-03-15 18:52:52 UTC
Permalink
Python like handling seems like a good idea to me.

Regards,
Pascal
Post by Thibault Kruse
Bump.
This also affects any other Groovy code that prints recursive structures.
def d = [:]
d.put(1, [d])
println(d)
So should I try to create a change of the InvokerHelper that handles
recursions in the same way python does?
On Sun, Feb 22, 2015 at 3:00 PM, Thibault Kruse
Post by Thibault Kruse
Hi,
currently groovysh does not handle recursive datastructures too well.
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, d)
===> null
groovy:000> d
[1: (this map)]
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, [d])
===> null
groovy:000> d
null // or StackOverflowError displayed, depending on Groovy Version
The class https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
is responsible for the rendering of structures (since java's
toString() is not used).
There are several ways to handle this, one is to catch
StackOverFlowError (either deep in the recursion or at the top).
Another way is to leave things as they are now.
The last way is to properly detect cycles, meaning each recursive
invocation gets a List of all Objects already in the process of being
rendered, and so method calls produce a placeholder token for any
element being rendered recursively. This would mean adding a new
function like
private static String formatWithouCycles(Object arguments, boolean
verbose, int maxSize, Collection itemsInProgress) {...}
and extending all the private static methods to honor the collection.
And some placeholder token would be required '(this map)' would not do anymore.
Thoughts?
regards,
Thibault
x = {}
x[1] = x
x
{1: {...}}
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Cédric Champeau
2015-03-15 19:42:08 UTC
Permalink
I think having a new method that pretty prints recursive structures is less
dangerous than modifying an existing one. First it would make sure we don't
break existing code (because relying on a hashset for example is unreliable
in the general case) and for performance. Hence I would prefer a new method
that makes it clear it is for debugging only.
Post by Pascal Schumacher
Python like handling seems like a good idea to me.
Regards,
Pascal
Bump.
Post by Thibault Kruse
This also affects any other Groovy code that prints recursive structures.
def d = [:]
d.put(1, [d])
println(d)
So should I try to create a change of the InvokerHelper that handles
recursions in the same way python does?
On Sun, Feb 22, 2015 at 3:00 PM, Thibault Kruse
Post by Thibault Kruse
Hi,
currently groovysh does not handle recursive datastructures too well.
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, d)
===> null
groovy:000> d
[1: (this map)]
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, [d])
===> null
groovy:000> d
null // or StackOverflowError displayed, depending on Groovy Version
The class https://github.com/groovy/groovy-core/blob/master/src/
main/org/codehaus/groovy/runtime/InvokerHelper.java
is responsible for the rendering of structures (since java's
toString() is not used).
There are several ways to handle this, one is to catch
StackOverFlowError (either deep in the recursion or at the top).
Another way is to leave things as they are now.
The last way is to properly detect cycles, meaning each recursive
invocation gets a List of all Objects already in the process of being
rendered, and so method calls produce a placeholder token for any
element being rendered recursively. This would mean adding a new
function like
private static String formatWithouCycles(Object arguments, boolean
verbose, int maxSize, Collection itemsInProgress) {...}
and extending all the private static methods to honor the collection.
And some placeholder token would be required '(this map)' would not do anymore.
Thoughts?
regards,
Thibault
x = {}
Post by Thibault Kruse
x[1] = x
x
{1: {...}}
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
Thibault Kruse
2015-03-15 20:11:52 UTC
Permalink
That works for me as well, though changing the default behavior could
be something for Groovy3...
Would you want such a method inside InvokerHelper?

On Sun, Mar 15, 2015 at 8:42 PM, Cédric Champeau
Post by Cédric Champeau
I think having a new method that pretty prints recursive structures is less
dangerous than modifying an existing one. First it would make sure we don't
break existing code (because relying on a hashset for example is unreliable
in the general case) and for performance. Hence I would prefer a new method
that makes it clear it is for debugging only.
Post by Pascal Schumacher
Python like handling seems like a good idea to me.
Regards,
Pascal
Post by Thibault Kruse
Bump.
This also affects any other Groovy code that prints recursive structures.
def d = [:]
d.put(1, [d])
println(d)
So should I try to create a change of the InvokerHelper that handles
recursions in the same way python does?
On Sun, Feb 22, 2015 at 3:00 PM, Thibault Kruse
Post by Thibault Kruse
Hi,
currently groovysh does not handle recursive datastructures too well.
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, d)
===> null
groovy:000> d
[1: (this map)]
groovy:000> d = [:]
===> [:]
groovy:000> d.put(1, [d])
===> null
groovy:000> d
null // or StackOverflowError displayed, depending on Groovy Version
The class
https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/InvokerHelper.java
is responsible for the rendering of structures (since java's
toString() is not used).
There are several ways to handle this, one is to catch
StackOverFlowError (either deep in the recursion or at the top).
Another way is to leave things as they are now.
The last way is to properly detect cycles, meaning each recursive
invocation gets a List of all Objects already in the process of being
rendered, and so method calls produce a placeholder token for any
element being rendered recursively. This would mean adding a new
function like
private static String formatWithouCycles(Object arguments, boolean
verbose, int maxSize, Collection itemsInProgress) {...}
and extending all the private static methods to honor the collection.
And some placeholder token would be required '(this map)' would not do anymore.
Thoughts?
regards,
Thibault
x = {}
x[1] = x
x
{1: {...}}
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Loading...