Sorry about the mangled formatting... like i said, first time on Usenet Suggestions, comments, replies, etc most welcome.
This definitely includes replies of the form: "This is stupid, because..." provided it isnt followed with "youre a jerk who knows nothing. Period." Heres a follow up rant in the form of a Q&A, trying to answer what I think are likely or interesting questions: ---------------------------------------------------- Q: Is this idea even remotely feasible to actually implement? A: No Idea Q: Are you volunteering to implement it? A: Not really. I'd have no clue where to start. I probably don't even have enough C experience to begin to understand the Python source. But if some real Python dev (or devs)actually wants to implement this, and is willing to humour an undergraduate by somehow utilising assistance in form a very limited set of programming skills, well, then I'd be highly flattered and more than happy to help :) Q: The whole document is full of half-formed ideas, hundredth-formed ideas, mistakes(conceptual/typograhpcial/stylistic/grammatical/terminological/programming/...), inconsistencies, random nonsense...... A: Firstly, thats not a question, its a statment. Secondly, see the very first paragraph. Thirdly, the whole document, from initial attempts to code the original for loop (yes, it is a real program I'm trying to write here), to thinking of Acceptors, refining the model to something vaguely coherent, coming up with examples, and typing it all out, was produced on the fly, in the space of 5 hours or so. I attempted to give it a semblance of coherent structure at first, but soon gave up. Its basically stream of conciousness production. The bit where the first, nonsensical example is given, is literally where I first tried to forumlate the idea in code, saw the massive holes, stopped, thought about it for a few minutes, and came backed and typed out the much improved second version. The whole thing is totally unedited.Oh, and I had virtually no sleep last night. A real answer, with respect to the issue of terminology: If I use technical terms loosely, e.g., if I improperly use 'method' for 'function' or vice versa (a hang up from dealing with languages that only have one e.g. Java, or the other, e.g. C) , please forgive me. I hope what I'm trying to say is still clear enough. And as for coding style, Python itself is inconsistent (or to be more diplomatic, not obsessively concerned with the relatively minor issue of) using underscore_seperated_words or mixedCaseInstead, etc. And again, I cry the nefarious influence of Java.... Q: Did you steal this from somewhere else? A: No, its entirely something I thought of, by myself, in the last 5 hours. Thats not to say something like it (or more likely, better than it) hasnt been thought of somewhere else by someone else. But if it has, I havent seen it. To give credit where due though: I was motivated by the various examples, from sources like www.python.org, of how Generators can be used to do things really elegantly. Also, I'm still tossing around ideas in the back of my mind from a great talk given at my university by Rob Pike, of Google, about a language he helped devise and implement called sawzall (or something close). Its used to do processing with Google's massive data sets and highly parallel computing architecture, yet its incredibly simple to understand and very efficient. I guess it was only tenuously related to the idea presented here. But it was certainly very inspiring in a general computer-science-enthusiasm kind of way. Q: Why did you go to all this trouble thinking up this feature when you could have solved the original problem in so many other, simpler ways? A: I honestly can't give a decent justification :-) Whenever I've needed to do things like: line = readline from file if (line is some sort of 'extra' data) do something with line line = readline from file # get the 'regular' data ... in the past, in Pascal, Java and the like, it always irked me. Don't ask why, it just did. I thought I could get around it with generator in Python, but I couldnt. In trying to think of a generator solution, I more or less randomly thought of extending the generator concept somehow, and I decided to see where it took me. I thought it took me to somewhere interesting, and possibly worthy of further investigation. Q: What about using some sort of 'sequential data sink' that doesn't use 'pretending to be a function' syntax, e.g. a simple Class of some sort? A: Maybe. You can have Iterators without Generators. Maybe you can have "inverse Iterators" without "inverse Generators", I havent thought about it. I love the 'pretending to be a function' syntax, its part of what makes Generators so elegant. So I tried to emulate it. Q: What could be some of the benefits of introducing this feature? What could it be used for? A: Again, I don't really know. Past the examples I've given, I havent really thought about possible applications. Potentially there might be efficiency gains using an Acceptor in place of a regular function that just processes a sequence, in the same way that using a Generator can be more efficient than using an actual sequence like a list. Then again, there might not. Q: ....So you've put forward this idea without really stopping to think if its actually useful? A: The idea seems *potentially* powerful and useful to me. Once more, for emphasis - I'm most definitely NOT trying to assert this is a great idea. I'm saying that maybe its a good idea, so lets put it on the table. That way, if it is really bad, lots of really smart people can shoot it down really quickly and save me wasting any more time thinking about it. Q: Maybe you should have put a bit more personal though/research into the idea before putting it out into the public domain? Or at least waited until you had more experience in Python? A: I'm not an academic or a professional, I don't have any reputation worth preserving. I tried not to suggest this in a forum where it'd distract the people who are responsible for developing Python from doing their very important work. Anyone could choose to ignore the post if they so desired - I havent wasted anyone's time, unless they've conciously chosen to waste it. And you read far enough to get to this question, so I assume you were at least vaguely interested. Q: Why not make a smaller, more tenuous suggestion, get some feedback, and go from there, rather than making one big ranting post? A: I suppose I just wanted to get all the ideas out while they were stll in my head. Its the kind of chaotically creative approach I often apply (though not intentionally) to programming, with results that are occasionally great and often disastrous. Q: In Python, there were list comprehensions, and then generator comprehensions. So what about Acceptor comprehensions? A: Yeah, sure, maybe. It sounds like a cool idea at least. Havent thought about it. Q: Why did you choose this particular syntax and naming? A: I just used what seemed the most obvious way to do things. I'm sure better versions could be thought of. Some advantages: its simple. The use of accept parallels the use of yield in generators. Its, arguably, pretty intutiitive. Disadvantages: It could be a bit too verbose, having to type accept for each magic argument. Perhaps an abbreviated sytax might be good e.g. accept arg1, arg2 in place of accept arg1 accept arg2 so long as it didn't conflict/confuse with existing syntax, for tuple assigment, etc. Another possible variant: the 'magic sequence' could be explicitly named in an Acceptor's argument list. I kind of like the way the Acceptor is 'bound' to its magic sequence by the call, with the sequence itself disappering from the argument list... its sort of vaguely similar to how x magically appears in the argument list when making the method call x.someMethod(otherArgs) Q: Why do you keep using the word magic everywhere? A: "Any sufficiently advanced techonology is indistinguishable from magic." Seems like a good enough term for a language feature that I can conceive, and can think in a limited fashion about some of its effects, but have no real understanding of its possible mechanisms. Or just for stuff that seems cool, powerful and slightly mysterious. :) Besides, once I'd started using it, I think it helped to be consistent. Q: Can't you already achieve this precise effect very easily with existing syntax (filter, list comprehensions, simple recursion, something)? A: Maybe, I don't know. If you can think of how, I'd like to hear it. Q: What about backwards compatibility issues? A: The only obvious one I can think of is the use of accept as a keyword, which would conflict with any variables called accept. Im sure one exists in some code somewhere. Hopefully, not too much code would be broken. Possibly a different syntax wouldnt even have to use a new keyword, or could use one that wouldnt cause much disruption to code. I imagine the issue would not be significantly worse than the introduction of yield for generators was. Or any other new language feature for that matter. Note, this is one of the reasons I'd be reluctant to see other special keywords/functions aside from accept used in the mechanism. Q: Why don't you want Acceptors to be able to know when the magic sequence ends? A: I don't know, I just don't like it. My intuition is you'd end up writing loops in acceptor functions that could have just been written in more or less exactly the same way without an acceptor, instead of writing Acceptor focused code. There's already an implict loop iterating through the sequence. Adding an additional loop with something like while accepting: accept .... is complicating things. Note neither of the two finished examples had any loops in them at all. As usual, I could be completely wrong. A possible compromise: Have an optional finally block at the end of the method, that executes when the magic sequence runs out of elements. This could serve much the same function as while accepting: without reintroducing banished loopiness. And maybe a similar thing, but prior to accepting. A 'first' block. So: def combineIntoRecord(): # This is an acceptor function first: recordList = [] optionalline = None # We may not get given a value for this line accept firstline accept secondline if condition(secondline): accept optionalline accept lastline recordList.append(createRecord(firstline, secondline, lastline, optionalline)) finally: return recordList Of course, thats another new keyword, plus an existing one overloaded.... again, I'm not a big fan..... Basically, I can summarise my views on what should and shouldn't be included in the mechanism thusly: Iwant to be able to 'accept' in an arbitrarily (or at least very) complicated way within an Acceptor. I reckon that is what would give them their power, and could lead to cool applications. But conversely I don't want Acceptors to 'need to do everything', burdening them with extra syntax to allow them to behave like regular functions. They're not intended as a super technique that solves every problem, they're intended to find and fill a particular programming niche. Better that niche be small, but Acceptors be a perfect fit for it - obviously the right answer for some problems, and equally, obviously the wrong answer for others. For comparison, think about lambda functions in Python allowed to contain arbitrary sequences of statements, not just single expressions. Anything that can't fit easily in a lambda, doesnt belong there. The same goes for Acceptors. Most imporant of all, the motivation of the whole exercise is to make things simpler and more elegant, not more complex and ugly. Q: Isn't it just perverse to want to code algorithms that are inherently suited to looping in syntax that does not explicitly loop? A: Perhaps. The lack of looping wasn't actually how I originally envisioned the final result. But you need to think long and hard about what is meant by an "algorithm inherently suited to looping." Try using a purely functional language (e.g. Haskell) and you might see what I mean. As far as my limited understanding of these things go, from a theoretical viewpoint, looping is actually only a special case of recursion. Its just that in structured, low-level, imperative languages, looping is the standard technique for solving a certain class of problems. So if like most people you learn to program in such a language, you'll naturally tend to think 'loops.' Hence the issue is really something inherent to your way of thinking about programs, and not to the actual problem. Q: You don't need to use yield, or a loop, or first/finally blocks, to make the final example work. Just pass in an empty list, and append it at the end of the method; return nothing. A: Yeah, I just now realised that. In fact possibly all the benefits of both the while Accepting and the first/finally ideas could be realised by preparing and passing in any nessecary intial state, and using callback on the passed objects instead of return. That way of implementing things seems cleaner and more in line with the 'Acceptor feel', in fact. This is definitely a line of thought that needs to be explored further.... For what its worth, conceptually, that solution pretty much works the same as using yield. But I like the idea of an Acceptor/Generator, so I'll let it stand in its own right. Needs a better name name though :-) Q: What's the project you were working on when you thought of this? A: Nothing particularily interesting or important ;-) Q: Have you got anything more to add? A: Yeah, I'm tired, and going to bed now. I'll be interested to see if this actually generates a substantial discussion of any sort. And I do apologise for the length of this rant. I hope that by reading it, you've at the very least gained some sort of amusement and sense of overwhelming superiority in light of my outrageously stupid thoughts..... -- http://mail.python.org/mailman/listinfo/python-list