Mailing List Archives
Authenticated access
|
|
|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [HTCondor-users] list(ExprTree) infinite loop
- Date: Thu, 20 Nov 2014 15:05:27 -0600
- From: Brian Bockelman <bbockelm@xxxxxxxxxxx>
- Subject: Re: [HTCondor-users] list(ExprTree) infinite loop
> On Nov 20, 2014, at 2:27 PM, Brian Candler <b.candler@xxxxxxxxx> wrote:
>
> On 19/11/2014 22:09, Brian Bockelman wrote:
>> It's a really interesting one; I'm not sure of the way to solve this. Stumped the expert!
>>
>> Basically, when you call list(classad.ExprTree("2+2")), the python starts putting together a list. It notes that ExprTree provides "__getitem__" and begins building a list like this:
>>
>> [classad.ExprTree("2+2")[0], classad.ExprTree("2+2")[1], ... ]
>>
>> I think it continues to do that until an IndexError is thrown.
>>
>> So, what's the problem here?
>>
>> The expression tree is lazily-evaluated. classad.ExprTree("2+2")[0] is equivalent to "(2+2)[0]". This is a perfectly valid expression - which is obviously going to end in error when you evaluate it. However, without evaluating it, we've got no way to know it'll end in tears.
> Hmm. It doesn't seem the __getitem__ call is lazy for all types of ExprTree, because in the case of a list ExprTree, it appears to evaluate immediately:
>
> >>> import classad
> >>> a = classad.ExprTree('{"foo","bar"}')
> >>> a[0]
> 'foo'
> >>> a[1]
> 'bar'
> >>> type(a[0])
> <type 'str'>
>
> It doesn't return expression {"foo","bar"}[0]
>
> Also, 2[0] does not have any meaning:
>
> >>> a = classad.ExprTree('2')
> >>> a[0]
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> TypeError: 'long' object has no attribute '__getitem__'
Correct - in the case of a list or literal expression (boolean, string, long), the current code immediately evaluates.
Non-trivial expressions like (2+2) are lazy-evaluated.
>
> So what is 2+(2[0]) or (2+2)[0] supposed to mean?
>
> >>> a = classad.ExprTree('2+2')
> >>> a[0]
> 2 + 2[0]
>
> Is the issue that + is lazy, and so a+b is also lazy?
>
Yup, more-or-less. "a+b" is an operand expression; as it's not list or literal, it is lazy-evaluated. Of course, (2+2)[0] is not a very useful expression (as it evaluates to Error)!
I think the proposed semantics (subscript operator always evaluates) is the most "pythonic" way to proceed.
>>> import classad
>>> classad.ExprTree("2+2")[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ClassAd expression is unsubscriptable.
>>> classad.ExprTree("{1,2,3}")[0]
1L
>>> classad.ExprTree('"ABC"')[0]
'A'
>>> def listAdd(a, b): return a+b
...
>>> classad.register(listAdd)
>>> classad.ExprTree("listAdd({1,2,3}, {4,5,6})")[1]
2L
Brian