[Python-Dev] Re: RFC on Callable Syntax PEP
This is such a great idea that I think it deserves its own PEP (to compete with this one?) Let me explain. PEP 677 was created for the sole purpose of replacing typing.Callable, but there are still some other areas where function metadata is required. What if we instead introduced a function prototype that allows you to "declare" a "function" without a body. typing example: import typing @typing.Callable def IntToIntFunc(a: int) -> int def flat_map( l: list[int], func: IntToIntFunc ) -> list[int]: ... ctypes example: import ctypes @ctypes.CFUNCTYPE def f(x: int) -> bool But of course this comes with a few issues: should it be an expression and if so, should the name be optional? How can ParamSpec be handled? ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/XPPZZZWVVW6KRBKYXJKXHPTECRDIOFUE/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: RFC on Callable Syntax PEP
My proposal wasn't to make the body optional based on the presence of a decorator, but rather to return a "function prototype" iff the body does not exist (I probably should have made my made my own reply instead of piggybacking on his proposal). I also mentioned some form of expression to represent this, similar to lambda. Maybe a friendly error message telling the user to use a function when this thing is called would alleviate some confusion? I'm not sure how one would forget to add the function body anyway. ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/3HJY6VGLIWRJ7F4BZBNGNCSJJTXH3CVM/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Function Prototypes
Hello In thread about PEP 677, I (with the help of another proposal) came up with an alternative to typing.Callable called function prototypes. The basic concept is to create a function prototype object when the body of a function is omitted. The thread can be found here: https://mail.python.org/archives/list/python-dev@python.org/thread/OGACYN2X7RX2GHAUP2AKRPT6DP432VCN/ Mark Shannon initially proposed that functions be used as types and provided this example: @Callable def IntToIntFunc(a:int)->int: pass def flat_map( l: list[int], func: IntToIntFunc ) -> list[int]: I further proposed that we make the body of a function non-mandatory and create a function prototype if it is omitted. I provided these examples: import typing @typing.Callable def IntToIntFunc(a: int) -> int def flat_map( l: list[int], func: IntToIntFunc ) -> list[int]: ... import ctypes @ctypes.CFUNCTYPE def f(x: int) -> bool I have since taken it upon myself to implement this in a fork of cpython: https://github.com/asleep-cult/cpython To remain consistent with function definitions, I have also added an alternative lambda syntax that allows you to annotate arguments and the return type. The syntax requires you to parenthesize the argument list: lambda (a: int, b: int) -> int: ... This new lambda syntax also allows you to create a function prototype by omitting the body. The original example can be rewritten as follows: def flat_map( l: list[int], func: lambda (a: int) -> int ) -> list[int]: ... Problems: - It is not possible to use ParamSpec with this - The lambda prototype syntax might be jarring - Some people might accidentally forget the function body Here is some feedback that I have already collected: "Yeah, making the body optional (without looking at decorators) is not acceptable either. Too easy to do by mistake (I still do this All. The. Time. :-)" - Guido van Rossum "i would strongly prefer this over the existing pep" - Ronny Pfannschmidt "I find this unnecessary and unreadable. Python isn't C or Java." - BundleOfJoysticks (Reddit) ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/B6VKYV5TKD2VSK6D2CUN77Q6MI5VIBU5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Function Prototypes
Hello and thank you for the much needed feedback. One thing that you must consider is that function prototypes have a few implications beyond typing but it seems like you're only looking at it as a tool for type hinting. The interpreter will create a function prototype object regardless of if you forget your decorator, it needs to pass something to the decorator after all. After reading through your reply, I am seeing that the main concern is the bloat added by the lambda keyword. My decision to use lambda instead of introducing a special syntax was one that required heavy deliberation. I ultimately decided to stick with lambda because it was consistent with the prototype statement form. The fact that lambda is hard to type has been felt by almost everyone who has ever used Python, this isn't just a problem that would be introduced by function prototypes. PEP 677 has taken the lazy approach to solving this issue and has prioritized type hinting over functionality. PEP 667 also suggests the usage of => for lambdas which would likely never be accepted because of the confusion it would cause. As someone who has used typing with Python, I do think that a new callable syntax is needed, but I truly believe that PEP 677 is taking the wrong approach. So what if we broke every Python program in existence by creating a new lambda syntax, how would it look? This question is particularly hard to answer because the body and annotations both need to be optional. Our best bet is an augmented form of the PEP 677 syntax that allows you to add a body. Here is an example: (a: int) -> int: a ** 2 But of course this causes ambiguity when the return annotation and body are both omitted. One thing that I did consider is simply treating it like a tuple if there is no return annotation AND there is no body, but that might lead to confusion. Another thing that I considered is a different prefix than lambda: $(a: int) -> int: a ** 2 ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/JJZGZ6EK5CY4RADPSQPRDWOB6GXQSSJ3/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Function Prototypes
> Just to be clear, by "function prototype", do you mean what PEP 677 > calls a Callable Type? A "function prototype" would be a concrete type that exists alongside the function type. The objects would hold the arguments, defaults, annotations and name of a function. > What sort of implications beyond typing? Here are a few places where "function prototypes" would be useful: import ctypes @ctypes.CFUNCTYPE def f(a: ctypes.c_int) -> ctypes.c_int import abc class Model(abc.ABC): def get_id(self) -> int By returning a concrete object, I leave it up to the implementation to define its meaning. > What kind of object does `def Func(a:int)->int` create, if you leave > out the decorator? Is that what you are calling a "function prototype > object"? Yes, it would create a "function prototype" object. > What does it need the @Callable decorator for? The @Callable decorator is not needed, it's just something leftover from Mark Shannon's proposal. Interpretation is entirely up to type checkers. > What happens if you leave out the annotations and just say > `def Func(a)` alone? The same thing that happens when you create a function with no annotations. > Do you have any response to my other criticisms about this syntax? Maybe I'm misinterpreting your reply, but I don't see any other criticisms about the syntax besides the one I addressed. The rest seem to be geared towards Mark Shannon's proposal. > What does that mean? What is lazy about it? I called it lazy because it fixes the callable syntax with little to no care about how it affects the future (if any) of the lambda syntax. I firmly believe that fixing the callable syntax and revising the lambda syntax should be done at the same time, or at least done in a way that doesn't make a new lambda syntax impractical. > Creating new syntax is backwards compatible: it doesn't break existing > code that is syntactically correct. I meant this in the context of my proposal where the lambda syntax and "callable" syntax are tightly coupled. Apologies if that wasn't clear. ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/4NIP24ZM4SKQVE3KCJA3B2GXMN2SKW43/ Code of Conduct: http://python.org/psf/codeofconduct/