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 -~----------~----~----~----~------~----~------~--~---