> Maybe something like this would be nice: > > xdef myprop('myprop docstring') [property]: > def __get__(self): > ...body... > def __set__(self, value): > ...body... > > xdef frame1() [SunkenFrame]: > xdef button1('OK') [Button]: > def ClickEvent(): > ...body... > def GotFocus(): > ...body... > MouseoverText = 'Hello!' > xdef text1(datasource=xyz) [TextBox]: pass > > xdef klass(base1, base2) [interface1, interface2]: > ...class body... > > This is almost exactly what Arne Koewing posted: > > blockdef myprop [property]: > def __get__(self): > ... > def __set__(self, value): > ... > def __delete__(self): > ... > > Except I tried to make it look a bit more like 'def'. But why require the empty ()? It is not a function definition. I think the property docstring should go in the usual docstring position. I also think that there's not much point in requiring __get__ etc.; get works just as wel. xdef myprop [property]: "myprop docstring" def get(self): ... > Obviously, this would go hand-in-hand with 'def' being extended to > allow a list of modifiers at the end, like this: > > def name(args) [staticmethod]: > > The general syntax for 'xdef' would be something like: > > xdef name(arg1, arg2, kw_arg1=x, kw_arg2=y) [mod1, mod2]: > ...class-like body... Let's discuss evaluation order a bit. It sounds like the arguments should be evaluated first, then the modifiers. (I propose that the argument list, if present, has exactly the same syntax as a function call argument list.) Then there are two possibilities for the body: (1) it could be evaluated before the xdef statement is "executed" (just as a class body); (2 or it could be compiled into a "thunk" which is somehow passed to whatever is called to implement the xdef (like a function body). Variant (2) gives much more freedom; it would allow us to create functions that can be called later, or it could be executed on the spot to yield its dictionary. > So this would work like: > > name = mod2(mod1(name, args, kw_args, dict)) Variant (2) would have the thunk object instead of dict. I think a thunk should be a callable; upon execution it would return its dict of locals. Maybe if a thunk contains a 'return' statement it could return the return value instead. Maybe someone can find a use for a thunk containing 'yield', 'break' or 'continue'. Maybe all control flow in the thunk should raise an exception that the xdef can catch to decide what happens. Hm, if it did 'yield' you'd like to be able to call next() on it. So maybe there should be different types of thinks that one can distinguish. > I guess args and kw_args would work something like how 'bases' are > collected in class definitions before being passed to metaclass > __new__ and __init__. Sure. > 'xdef' could return a class just as well as a property: > > xdef klass(base1, base2) [interface1, interface2]: > ...class body... > > 'interface1','interface2' would have to be clever about sometimes > being passed a class and sometimes being passed the tuple (name, args, > kw_args, dict). How does xdef know whether it's a class or not? I like it better if we're definite, and choose (2) always. > In general, 'xdef' would allow metaclass-like processing on things > that are not necessarily a class. > > Problems: > > (1) The main problem is that 'xdef' makes things that are pretty close > to being classes. So why not just use classes? Because they're not classes. Let's not follow C++'s example of avoiding new keywords at all cost and stretching the meaning of some existing ones beyond the bounds of reason. > (2) Also 'xdef' is pointless without [mod1, mod2] > > xdef name(): > > would just assign the tuple (name, args, kw_args, dict) to name. Or maybe it would be illegal, or maybe there would be some default modifier. (Like class has a default metaclass.) > (3) 'xdef' isn't a great name, because > > xdef abc(xyz): > def abc(xyz): > > do completely different things. But the name should be short like > 'def' so it doesn't draw much attention to itself, just as 'def' > doesn't draw much attention to itself. So > > xdef myprop() [property]: > > the thing that sticks out is 'property' Let's just say 'xdef' is just a shorthand for a keyword we haven't picked yet. > More bad stuff: > > xdef abc(xyz): > return 7 > > would raise a 'SyntaxError: 'return' outside function' See above. > xdef name(arg1, kw_arg1=x) [mod1, mod2]: > y = arg1 + kw_arg1 > > would raise NameError. Not necessarily. Maybe the thunk can somehow keep a reference to the arguments (like nested scopes?). One think I'd like to do with extensible syntax like this (and for which xdef is a poor name) would be to define a "lock" statement, like Java's "synchronized" block. Maybe it could be written like this; I made the name after xdef optional: xdef (mylock) [synchronized]: ...block... which would mean: mylock.acquire() try: ...block... finally: mylock.release() It would be nice if control flow statements (return, break, continue) inside the block would somehow properly transfer control out of the block through the finally block, so that you could write things like def foo(): for i in sequence: xdef (mylock) [synchronized]: if ...condition...: continue ...more code... if ...condition...: break ...yet more code... if ...condition...: return 42 Only 'yield' doesn't really fit in here (like it doesn't fit in lots of places :-). Though this would look much better if synchronized came before mylock. It is also unsatisfying that you can't easily extend this to take multiple blocks. Maybe we can change the syntax back to something that started this. Instead of the xdef keyword, we'd use a colon at the end of an expression or assignment line. The grammar could be e.g. statement: (variable '=')* expression [':' suite] (Where suite is a simple statement or NEWLINE INDENT block DEDENT.) Then the locking example could be written as synchronized(mylock): ...block... This would mean synchronized(mylock)(thunk) where thunk would be a callable representing the block as before. If a variable was present it would receive the result, so that e.g. foo = property: def get(self): ... would end up meaning foo = property(thunk) which is only a very small stretch from what property currently does (it would have to do a typecheck on its argument for backwards compatibility). --Guido van Rossum (home page: http://www.python.org/~guido/)
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4