Sending changed parameters into nested generators

John O'Hagan research at johnohagan.com
Sat Nov 13 07:52:00 CET 2010


On Sat, 13 Nov 2010, Steven D'Aprano wrote:
> On Fri, 12 Nov 2010 09:47:26 +0000, John O'Hagan wrote:
> > I have a generator function which takes as arguments another generator
> > and a dictionary of other generators like this:
> > 
> > def modgen(gen, gendict):
> >     for item in gen():
> > 	for k, v in gendict:
> > 		do_something_called_k(item, v.next())
> > 	
> > 	yield item
> 
> [snip]
> 
> > If anyone's still reading :) , how can I send new values to arbitrary
> > sub- generators?
> 
> I have a headache after reading your problem :(
> 
> I think it's a good time to point you at the Zen, particularly these five
> maxims:
> 
> Beautiful is better than ugly.
> Simple is better than complex.
> Complex is better than complicated.
> Flat is better than nested.
> If the implementation is hard to explain, it's a bad idea.
> 
> 
> I'm afraid that your nested generators inside another generator idea
> fails all of those... it's not elegant (beautiful), it's complicated,
> it's nested, and the implementation is hard to explain.
> 
> You could probably replace generators with full-blown iterators, but I
> wonder what you're trying to accomplish that is so complicated that it
> needs such complexity to solve it. What are you actually trying to
> accomplish? Can you give a simple example of what practical task you hope
> to perform? I suspect there's probably a more elegant way to solve the
> problem.

I hope there is! 

The project not practical but artistic; it's a real-time musical composition 
program. 

A (simplified) description: one module contains number-list generating 
functions, others contain functions designed to filter and modify the number 
lists produced, according to various parameters. Each such stream of number 
lists is assigned a musical meaning (e.g. pitch, rhythm, volume, etc) and they 
are combined to produce representations of musical phrases, which are sent to 
a backend which plays the music as it is produced, and makes PDF scores. Each 
such "instrument" runs as a separate thread, so several can play together in a 
coordinated fashion. 

All the compositional interest lies in the selection of number-list generators 
and how their output is modified. For example, if I say "Play every third note 
up an octave" it's not very interesting, compared to "Play every nth note up 
an interval of m", where n and m vary according to some pattern. It gets even 
more interesting when that pattern is a function of x and y, which also vary 
according to another pattern, and so on.

To that end, I have each parameter of each modifier set by another generator, 
such that the value may change with each iteration. This may continue 
recursively, until at some level we give a parameter a simple value.

That's all working, but I also want it to be interactive. Each thread opens a 
terminal where new options can be entered, but so far it only works, as I 
mentioned, for changing the values in a top-level mutable object. 

I agree that as a piece of code this is complicated, nested and hard to 
explain, but I don't agree that it's ugly. In fact, it was my existing 
interest in a "patterns within patterns" style of composition that got me 
learning python in the first place, as the patterns got too hard to keep track 
of manually.

I'm not attached to using nested generators, and would be happy with any 
solution which enables me to do what I've described. It seems to me that the 
concept is inherently nested, but I'd be glad to be proved wrong.

Regards,

John



More information about the Python-list mailing list