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 sage-devel@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to