codon icon indicating copy to clipboard operation
codon copied to clipboard

list.insert() causes inconsistent error messages

Open xiaxinmeng opened this issue 3 years ago • 3 comments

In the following we define two function-equivalent code snippets, i.e., test1.py and test2.py. "if 'abc' in a:pass" uses the same value of a, i.e., None, while the error messages are different for the two test programs. I think the output of test2.py is the expected behavior.

test1.py

l = [None]
l[0] = {'abc': 5}
l.insert(0, None) 
a = l[0]
print(a) # None
if 'abc' in a:pass

The output of test1.py

None
ValueError: optional is None
Raised from: std.internal.types.optional.unwrap:0
/home/xxm/Desktop/Codon/codon-linux-x86_64/codon-deploy/lib/codon/stdlib/internal/types/optional.codon:80:5
Aborted (core dumped)

test2.py

l = [None]
#l[0] = {'abc': 5}
#l.insert(0, None) 
a = l[0]
print(a) # None
if 'abc' in a:pass

The output of test2.py: test.py:355:4-14: error: 'NoneType' object has no attribute '__contains__'

Reproduce step:

download the Pre-built binaries for Linux Type " codon run --release test.py" in the console.

Environment: Ubuntu 18.04 Codon v0.16.0

xiaxinmeng avatar Apr 17 '23 02:04 xiaxinmeng

The output of l in codon is reasonable because it has the type List[Optional[Dict[str, int]]] under codon's auto type deduction rule. However, this can be confusing because the type is implicit.

learnforpractice avatar Apr 17 '23 04:04 learnforpractice

@xiaxinmeng As @learnforpractice noted, that is the expected behavior.

There are two different lists: the first is of type List[Optional[Dict[str, int]]] and the second is of type List[Optional].

a: List[Optional] = [None]
n = a[0]
print(type(n) is Optional)  # True


temp = {'abc': 5}
a: List[Optional[Dict[str, int]]] = []
a.append(None)
a.append(temp)
n = a[0]  # None
d = a[1]  # {'abc': 5}

print(type(n) is Optional)  # False
print(type(n) is Optional[Dict[str, int]])  # True
print(type(d) is Optional)  # False
print(type(d) is Optional[Dict[str, int]])  # True


l = [None]
l[0] = {'abc': 5}  # List[Optional[Dict[str, int]]]
l.insert(0, None)
n = l[0]  # None
d = l[1]  # {'abc': 5}

print(type(n) is Optional)  # False
print(type(n) is Optional[Dict[str, int]])  # True
print(type(d) is Optional)  # False
print(type(d) is Optional[Dict[str, int]])  # True

elisbyberi avatar Apr 17 '23 13:04 elisbyberi

Yes, this is the expected behaviour as 'abc' in a checks for the presence of 'abc' in None (which is of type Optional[Dict[str, int]]. As None has no data, it throws optional is None.

Better error messaging is added to #604.

inumanag avatar Nov 09 '24 20:11 inumanag