Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java arrays are Iterable, but aren't Sequence #1252

Open
GoToLoop opened this issue Jan 1, 2025 · 3 comments
Open

Java arrays are Iterable, but aren't Sequence #1252

GoToLoop opened this issue Jan 1, 2025 · 3 comments

Comments

@GoToLoop
Copy link

GoToLoop commented Jan 1, 2025

I have this test which does some simple checks on Java's arrays and arraylists & Python's arrays and tuples:

from array import array
from typing import Iterable, Sequence

import jpype # from 'jpype1' package

# Function to check if an object is a Java array
def is_java_array(obj):
    return obj.getClass().isArray() if isinstance(obj, jpype.JObject) else False

# Start the JVM
jpype.startJVM()

# Import the Array classes
Array = jpype.JClass('java.lang.reflect.Array')
Arrays = jpype.JClass('java.util.Arrays')

# Create a Python tuple for testing
python_tuple = 10, 20, 30, 40, 50

# Create a Java ArrayList
java_list = Arrays.asList(python_tuple)

# Create a Java array
java_array = Array.newInstance(jpype.JInt, len(java_list))
for i in range(len(java_array)): java_array[i] = java_list[i].intValue()

# Create a Python array for testing
python_array = array('i', java_array)

# Test the function
print(java_array, len(java_array), is_java_array(java_array), type(java_array)) # True
print(java_list, len(java_list), is_java_array(java_list), type(java_list)) # False
print(python_tuple, len(python_tuple), is_java_array(python_tuple), type(python_tuple)) # False
print(python_array, len(python_array), is_java_array(python_array), type(python_array)) # False

print("\nJava's array is an Iterable:", isinstance(java_array, Iterable)) # True
print("Java's array is a Sequence:", isinstance(java_array, Sequence)) # False

print("\nJava's ArrayList is an Iterable:", isinstance(java_list, Iterable)) # True
print("Java's ArrayList is a Sequence:", isinstance(java_list, Sequence), '\n') # False

for int in java_array: print(int)

# Shutdown the JVM (optional)
jpype.shutdownJVM()

While an ArrayList is both an Iterable and a Sequence, a Java's array is just an Iterable, but not a Sequence!

Given a Java's array is also subscriptable and we can use Python's [] operator w/ positive integer indices, I believe a Java array should also be considered a Sequence in Python, just like an ArrayList.

@Thrameos
Copy link
Contributor

I believe that when I wrote the wrapper I attempted to make arrays and lists into sequences, but was unable to do so. The issue was that Java arrays did not satisfy certain requirements to be a sequence and we would need to add a utility class to add those additional portions of the contract.

Look at the complete contract required for sequence. It would be possible to create a large wrapper to add that much functionality but it certainly wouldn't be normal Java behaviors.

https://docs.python.org/3/library/stdtypes.html#id4

What specific behavior of Sequence do you think we need to support?

@GoToLoop
Copy link
Author

GoToLoop commented Jan 21, 2025

Look at the complete contract required for sequence.

It didn't pass on mind the need to satisfy the whole Sequence contract!

What specific behavior of Sequence do you think we need to support?

IMO, Java arrays already satisfy what's actually important to be considered a Sequence.

These few operations & methods below fail:

concatenated = python_tuple + java_array
doubled = java_array * 2

print(java_array.count(30))
print(java_array.index(20))

However, everything else works:

print(20 in java_array, 25 not in java_array) # True True

sliced = java_array[2:4]
print(sliced, type(sliced)) # [30, 40] <java class 'int[]'>

INV = slice(None, None, -1)
inverted = java_array[INV]
print(inverted, type(sliced)) # [50, 40, 30, 20, 10] <java class 'int[]'>

print(len(inverted), min(inverted), max(inverted)) # 5 10 50
True True
[30, 40] <java class 'int[]'>
[50, 40, 30, 20, 10] <java class 'int[]'>
5 10 50

I just wanna be able to declare a parameter of type Sequence which would accept many types of indexed containers, including Python lists, tuples, etc.; and Java containers such as arrays, arraylists, etc.

@Thrameos
Copy link
Contributor

I will give a shot in 1.6 to see if I can get the missing part of the contract to work and it to recognize it. It will depend a lot on whether Sequence is a duck type or just a declaration. If it is a declaration then we can satisfy without completing the contract.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants