On Nov 14, 2008, at 10:17 AM, Robert Bradshaw wrote:
> On Nov 14, 2008, at 7:05 AM, Jason Grout wrote:
>
>> Mike Hansen wrote:
>>> Hello,
>>>
>>> On Nov 14, 12:26 am, Jason Grout <[EMAIL PROTECTED]>
>>> wrote:
>>>> Franco Saliola wrote:
>>>>
>>>>>> Any comments or objections?
>>>>> What about list comprehensions? Something like the following.
>>>>> sage: var('i,n')
>>>>> (i, n)
>>>>> sage: sum(2^i for i in range(n+1))
>>>>> 2^(n+1) - 1
>>>>> I ask because this seems like the natural/first thing a user
>>>>> would try.
>>>> It's consistent:
>>>>
>>>> sage: sum(i for i in range(10))
>>>> 45
>>>>
>>>> However, range would have to also be overridden here, since range
>>>> only
>>>> accepts integers.
>>>>
>>>> Or we could override the ellipsis notation:
>>>>
>>>> sum(i for i in (1..oo))
>>>>
>>>> sum(i for i in (1..n+1))
>>>
>>> I don't think any of these are even feasible or what we want since
>>> they create a "black box" generator which gets passed into sum.
>>
>>
>> I agree that they probably aren't feasible. I was throwing them
>> out for
>> the purposes of brainstorming for interfaces.
>
Check out the (still not 100% robust) code below.
sage: get_sum_components(n for n in range(10))
(n, None, <listiterator object at 0xd1b0cd0>)
sage: get_sum_components(n^2 for n in [1..10] if n != 3)
(n^2, n != 3, <listiterator object at 0xd1b0ff0>)
sage: get_sum_components(1/n^2 for n in (1..))
(1/n^2, None, <generator object at 0xd1abe18>)
sage: get_sum_components(n^2 for n in [1..100] if n != 10)
(n^2, n != 10, <listiterator object at 0xd1afef0>)
---------------------------------------------
import dis
def chop_code(c):
i = 0
all = []
while i < len(c):
if ord(c[i]) < dis.HAVE_ARGUMENT:
all.append(c[i])
else:
all.append(c[i:i+3])
i += len(all[-1])
return all
def get_sum_components(g):
frame = g.gi_frame
code = frame.f_code
ops = chop_code(code.co_code)
if (dis.opname[ord(ops[0][0])] != 'SETUP_LOOP'
or dis.opname[ord(ops[1][0])] != 'LOAD_FAST'
or dis.opname[ord(ops[2][0])] != 'FOR_ITER'):
raise TypeError, "Not a valid generator."
index_name = code.co_varnames[ord(ops[3][1])]
range_name = code.co_varnames[ord(ops[1][1])]
range_value = frame.f_locals[range_name]
cond = []
expr = []
for op in ops[4:]:
if dis.opname[ord(op[0])] == 'YIELD_VALUE':
break
elif dis.opname[ord(op[0])] == 'JUMP_IF_FALSE' and not cond:
cond = expr
expr = []
else:
expr.append(op)
if cond:
# there's an extra pop
expr = expr[1:]
index_var = var(index_name)
expr += [chr(dis.opmap['RETURN_VALUE'])]
def func(arg): pass
expr_code = type(code)(2, code.co_nlocals, code.co_stacksize,
32832, ''.join(expr),
code.co_consts, code.co_names,
code.co_varnames, code.co_filename, 'sum_expr', code.co_firstlineno,
'', code.co_freevars, code.co_cellvars)
func.func_code = expr_code
expr = func(None, index_var)
if cond:
cond += [chr(dis.opmap['RETURN_VALUE'])]
cond_code = type(code)(2, code.co_nlocals,
code.co_stacksize, 32832, ''.join(cond),
code.co_consts, code.co_names,
code.co_varnames, code.co_filename, 'sum_cond', code.co_firstlineno,
'', code.co_freevars, code.co_cellvars)
func.func_code = cond_code
cond = func(None, index_var)
else:
cond = None
return expr, cond, range_value
--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---