Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #84297 > unrolled thread

Python Sanity Proposal: Type Hinting Solution

Started byRick Johnson <rantingrickjohnson@gmail.com>
First post2015-01-22 17:15 -0800
Last post2015-01-23 16:31 +1100
Articles 20 on this page of 48 — 16 participants

Back to article view | Back to comp.lang.python


Contents

  Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-22 17:15 -0800
    Re: Python Sanity Proposal: Type Hinting Solution MRAB <python@mrabarnett.plus.com> - 2015-01-23 03:22 +0000
    Re: Python Sanity Proposal: Type Hinting Solution Terry Reedy <tjreedy@udel.edu> - 2015-01-22 22:22 -0500
      Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 11:23 -0800
        Re: Python Sanity Proposal: Type Hinting Solution Christian Gollwitzer <auriocus@gmx.de> - 2015-01-24 22:14 +0100
    Re: Python Sanity Proposal: Type Hinting Solution Rustom Mody <rustompmody@gmail.com> - 2015-01-22 19:23 -0800
      Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 11:36 -0800
    Re: Python Sanity Proposal: Type Hinting Solution Chris Angelico <rosuav@gmail.com> - 2015-01-23 14:59 +1100
      Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 11:48 -0800
        Re: Python Sanity Proposal: Type Hinting Solution Chris Angelico <rosuav@gmail.com> - 2015-01-24 06:59 +1100
          Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 12:59 -0800
        Re: Python Sanity Proposal: Type Hinting Solution Mario Figueiredo <marfig@gmail.com> - 2015-01-23 22:02 +0100
          Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 13:59 -0800
            Re: Python Sanity Proposal: Type Hinting Solution Mario Figueiredo <marfig@gmail.com> - 2015-01-23 23:42 +0100
              Re: Python Sanity Proposal: Type Hinting Solution Mario Figueiredo <marfig@gmail.com> - 2015-01-23 23:45 +0100
                Re: Python Sanity Proposal: Type Hinting Solution sohcahtoa82@gmail.com - 2015-01-23 14:52 -0800
                  Re: Python Sanity Proposal: Type Hinting Solution Mario Figueiredo <marfig@gmail.com> - 2015-01-24 00:14 +0100
                Re: Python Sanity Proposal: Type Hinting Solution Marko Rauhamaa <marko@pacujo.net> - 2015-01-24 01:52 +0200
                  Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-24 16:29 +1100
                    Re: Python Sanity Proposal: Type Hinting Solution Chris Angelico <rosuav@gmail.com> - 2015-01-24 16:38 +1100
                      Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-24 17:36 +1100
                        Re: Python Sanity Proposal: Type Hinting Solution Chris Angelico <rosuav@gmail.com> - 2015-01-24 17:47 +1100
                    Re: Python Sanity Proposal: Type Hinting Solution Marko Rauhamaa <marko@pacujo.net> - 2015-01-24 11:27 +0200
              Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 15:39 -0800
              Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-25 00:29 +1100
                Re: Python Sanity Proposal: Type Hinting Solution Mario Figueiredo <marfig@gmail.com> - 2015-01-24 15:09 +0100
                  Re: Python Sanity Proposal: Type Hinting Solution Mario Figueiredo <marfig@gmail.com> - 2015-01-24 15:32 +0100
                  Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-25 03:05 +1100
                  Re: Python Sanity Proposal: Type Hinting Solution Marco Buttu <marco.buttu@gmail.com> - 2015-01-24 15:25 +0100
                Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-24 08:41 -0800
                  Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-25 04:26 +1100
                    Re: Python Sanity Proposal: Type Hinting Solution Mark Lawrence <breamoreboy@yahoo.co.uk> - 2015-01-24 17:36 +0000
                    Re: Python Sanity Proposal: Type Hinting Solution Paul Rubin <no.email@nospam.invalid> - 2015-01-24 09:37 -0800
                      Re: Python Sanity Proposal: Type Hinting Solution Chris Angelico <rosuav@gmail.com> - 2015-01-25 06:59 +1100
    Re: Python Sanity Proposal: Type Hinting Solution Terry Reedy <tjreedy@udel.edu> - 2015-01-23 00:03 -0500
      Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-23 16:59 +1100
        Re: Python Sanity Proposal: Type Hinting Solution "Fetchinson ." <fetchinson@googlemail.com> - 2015-01-23 14:23 +0100
          Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 12:21 -0800
            Re: Python Sanity Proposal: Type Hinting Solution Mario Figueiredo <marfig@gmail.com> - 2015-01-23 22:12 +0100
              Re: Python Sanity Proposal: Type Hinting Solution Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-23 14:26 -0800
          Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-24 17:21 +1100
            Re: Python Sanity Proposal: Type Hinting Solution Tim Chase <python.list@tim.thechases.com> - 2015-01-24 06:47 -0600
              Re: Python Sanity Proposal: Type Hinting Solution Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-01-25 00:40 +1100
                Re: Python Sanity Proposal: Type Hinting Solution Roy Smith <roy@panix.com> - 2015-01-24 09:06 -0500
            Re: Python Sanity Proposal: Type Hinting Solution "Fetchinson ." <fetchinson@googlemail.com> - 2015-01-24 22:01 +0100
        Re: Python Sanity Proposal: Type Hinting Solution Chris Angelico <rosuav@gmail.com> - 2015-01-24 04:11 +1100
        Re: Python Sanity Proposal: Type Hinting Solution "Fetchinson ." <fetchinson@googlemail.com> - 2015-01-23 22:07 +0100
    Re: Python Sanity Proposal: Type Hinting Solution Chris Angelico <rosuav@gmail.com> - 2015-01-23 16:31 +1100

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#84443

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-24 17:36 +1100
Message-ID<54c33d8c$0$13011$c3e8da3$5496439d@news.astraweb.com>
In reply to#84437
Chris Angelico wrote:

> But having just watched a PyCon talk about PyPy and RPython
> and type inference

Ooh! Got a link?


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#84444

FromChris Angelico <rosuav@gmail.com>
Date2015-01-24 17:47 +1100
Message-ID<mailman.18077.1422082082.18130.python-list@python.org>
In reply to#84443
On Sat, Jan 24, 2015 at 5:36 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Chris Angelico wrote:
>
>> But having just watched a PyCon talk about PyPy and RPython
>> and type inference
>
> Ooh! Got a link?

Well, it's not primarily about type inference, but the matter is
mentioned. It's mainly about PyPy, RPython, and what a VW Beetle would
look like if python-ideas got to it:

http://youtu.be/6_-5XZzJyt0

ChrisA

[toc] | [prev] | [next] | [standalone]


#84450

FromMarko Rauhamaa <marko@pacujo.net>
Date2015-01-24 11:27 +0200
Message-ID<87ppa434wf.fsf@elektro.pacujo.net>
In reply to#84436
Steven D'Aprano <steve+comp.lang.python@pearwood.info>:

> Marko Rauhamaa wrote:
>
>>    def weekday(day):
>>        assert isinstance(day, int) and 0 <= day <= 6
>>        ...
>
> [...]
>
> Requiring the type-checker to parse and understand arbitrarily complex
> assertions would require the type-checker to be as complex as Python
> itself:

The static type checker / optimizer would of course be limited to a set
of known fixed expression patterns. More complex expressions would
simply be ignored by it.

Moreover, the type checker would probably operate in a compile-time
environment where you assume "isinstance" and "int" retain their usual
meanings. 

Scheme already employs somewhat analogous dirty tricks like that in its
macro preprocessing.

> Assertions also have the problem that they execute arbitrarily complex
> code at runtime.

Assertions don't *have* to execute anything, anywhere, any time. The
static analysis can decide when executing assertions is worth the
trouble. All of the above can also be done JIT.

> Lastly, this use of assertions clashes with "best practice" for
> assertions. Since assertions may be disabled, you should not use them
> for testing user-supplied arguments. So that means you have to write:
>
> def func(arg):
>     assert isinstance(arg, int)  # satisfy the type checker
>     if isinstance(arg, int):  # support times when assert is disabled
>         ...

I think that's a silly argument. You never second-guess assertions.

> This doesn't apply to annotations:
>
> def func(arg:int):
>     # since this is a public function, not private, we cannot assume the
>     # caller will run the type-checker
>     if isinstance(arg, int):
>         ...

I think that usage is plainly bad style as well. Reminds me of the old
adage:

   Dad is always right, and even when he isn't, he's never wrong.


Marko

[toc] | [prev] | [next] | [standalone]


#84420

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2015-01-23 15:39 -0800
Message-ID<9ba02184-0138-49dd-bbc5-6881fc0fb4af@googlegroups.com>
In reply to#84409
On Friday, January 23, 2015 at 4:42:51 PM UTC-6, Mario Figueiredo wrote:
> I'd rather it'd be a docstring parameter.
>
> - Decorators are transformation tools. Which type hints
> are not.

Valid point.

> - keywords should be few and used only for language
> features. Static analysis isn't and should never be a
> language feature. It's an extension, perhaps.

Indeed. I've always been fond of Python's relatively small
set of keywords, and avoiding additions is a noble goal. It
seems like we've entered an era of increasing feature creep.

> - Same with built-in functions... although a case could be
> made for a static analysis package, hmmm.
>
> So I'd rather see:
>
>      def myfunction(arg1, arg2):
>      """
>      Normal docstring.
>      """
>      "@typehint: (str, int) -> bool"
>          return True
>

I think extending the doc-string syntax is good idea since
there is nothing going on in there anyway. It's sort of like
a treasure just waiting to be plundered. Plus, I find i can
easily ignore doc-strings, whereas, adding a new syntax is
going to be a syntactical distraction no matter how "clean"
it may be. Heck, even after years of reading Python source,
function decorators still jump out at me like lions from
behind a bush!

And although i think one could make a good argument that
decorators *ought-to-be* obvious because of the resulting
unavoidable implications of them, i don't believe the same
argument applies to a feature which simply serves as an
"optional hook" for static analysis tools -- for which the
implications are entirely dependent on purposeful actions by
a programmer -- any other time it's just dead code.

> Alternatively, because dangling strings are always
> considered documentation and completely ignored by the
> interpreter (PEP 258), one could also do:
>
>      "@typehint: (str, int) -> bool"
>      def myfunction(arg1, arg2):
>      """
>      Normal docstring.
>      """
>          return True
>

Ha, well one of the more wonderful aspects of being an
"opposer" (as opposed to a "proposer") is that you can omit
yourself from the headaches of the implementation details
O:-). I say: they wanted type hints, fine, let them suffer
the headaches of hacking the interpreter.

My only goal (at this point) is ensuring that their little
intellectual "problem child" does not walk on my wonderfully
lush and finely manicured lawn.

    KEEP OFF MY GRASS!!!

[toc] | [prev] | [next] | [standalone]


#84463

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-25 00:29 +1100
Message-ID<54c39e48$0$12996$c3e8da3$5496439d@news.astraweb.com>
In reply to#84409
Mario Figueiredo wrote:

> In article <4b3b498a-c9b0-443d-8514-87ccd8e98f43@googlegroups.com>,
> rantingrickjohnson@gmail.com says...
>> 
>>     (Example modified for PEP8 compliance ;-)
>> 
>>     @typehint(arg1:str, arg2:int, returns:bool)
>>     def myfunction(arg1, arg2):
>>         return True
>>         
>> Of course "@typehint" could be an extension of the decorator
>> syntax, a keyword, a build-in function or whatever, i don't
>> care.
> 
> I'd rather it'd be a docstring parameter.
> 
> - Decorators are transformation tools. Which type hints are not.

But they can be. Python annotations are available at runtime, they are not
mere declarations for the compiler like in Pascal or C:

py> def spam(x:int, y:float)->float:
...     return x+y
...
py> spam.__annotations__
{'x': <class 'int'>, 'y': <class 'float'>, 'return': <class 'float'>}


They're writable too:

py> def eggs(x, y):
...     return x + y
...
py> eggs.__annotations__ = spam.__annotations__
py> eggs.__annotations__['x']
<class 'int'>


So we can write a transformation tool which adds, modifies or deletes
annotations:

@annotate(x=int, y=float)  # return is a little tricky...
def eggs(x, y):
    return x+y

eggs.__annotations__['x']
# returns int


Except we don't need such a tool. Python 3 already has syntax for it, and it
supports annotating the return result too. Annotation syntax is just
syntactic sugar for a transformation.


> - keywords should be few and used only for language features. Static
> analysis isn't and should never be a language feature. It's an
> extension, perhaps.

I'm not sure if you're making a general observation or one which is specific
to Python. Plenty of languages have static analysis as a language feature.
Are you arguing they are wrong to do so?

In the case of Python, there are no plans for CPython to include static
analysis, or for it to be general language feature. Other implementations,
such as MyPy, and other tools, are intended to perform the analysis, not
the CPython reference implementation.


> - Same with built-in functions... although a case could be made for a
> static analysis package, hmmm.

I'm not sure what you mean here.



> So I'd rather see:
> 
>      def myfunction(arg1, arg2):
>      """
>      Normal docstring.
>      """
>      "@typehint: (str, int) -> bool"
>          return True

By the rules of implicit (compile-time) concatenation of string literals,
that is equivalent to:

def myfunction(arg1, arg2):
    """
    Normal docstring.
    @typehint: (str, int) -> bool"""
    return True

One of the problems with this is that it put the information about
parameters far away from the parameter list itself. Most docstrings are
considerable more than a single line:

py> from random import sample
py> len(sample.__doc__.split('\n'))
16


I consider 16 lines a short docstring! I've written docstrings which are 40
or 50 lines long, so potentially the annotations are almost a full page
away from the function signature.

The usual convention among document generator tools is that parameter
metadata is at the start of the docstring, not the end:

def myfunction(arg1, arg2):
    """
    One line summary.

    @param arg1: str
    @param arg2: int
    @returns bool

    Longer discussion of the function.
    """
    return True

I'm not keen on that, but at least it puts the types close to the function
signature, and it's a defacto standard.


> I removed the arguments names on purpose. They are only necessary on the
> PEP because type hinting is a part of the function header there.
> However, when using a documentation like pattern as above (or as in your
> own example), they can be safely removed, with the added benefit of
> making the syntax simpler.

Only at the cost of making it hard to read. I go to look up a function which
I am unfamiliar with, and find the function signature:

def open(file, mode='r', buffering=-1, encoding=None,
        errors=None, newline=None, closefd=True, opener=None):
    """Open a file.

    blah blah blah blah...
    thirty lines of documentation...


My documentation view shows only the first thirty lines, so I hit the Page
Down key and see:

    blah blah blah blah...
    thirty lines of documentation...
    
I page down again:

    blah blah blah...
    @typehint: (str, str, int, Optional[str], Optional[str], 
                Optional[str], bool, Callable)


Well that's rather less than useful. Which argument is newline again? Number
3 or 4 or 5?

Syntax which appears reasonable with toy examples (one-line docstring, two
arguments) is less reasonable with real-world cases (docstrings can be a
page or more in length, there may be five or a dozen arguments to a
function).


> Alternatively, because dangling strings are always considered
> documentation and completely ignored by the interpreter (PEP 258), one
> could also do:
> 
>      "@typehint: (str, int) -> bool"
>      def myfunction(arg1, arg2):

That's somewhat better, in that at least the hint is close to the function
signature. But it has a lot of disadvantages: it is compile-time only, the
type hints aren't available at runtime. It requires extra complexity to the
parser, so that decorators may be separated from the function by a hint:

@decorate
"@typehint: (str, int) -> bool"
def myfunction(arg1, arg2):


No doubt some people will get them the wrong way around, and the type
checker may silently ignore their hints:

"@typehint: (str, int) -> bool"
@decorate
def myfunction(arg1, arg2):

And others will write:

@decorate
@typehint(str, int) -> bool
def myfunction(arg1, arg2):


and be annoyed or perplexed by the syntax error.

Some syntax will be a bug magnet. This is one.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#84467

FromMario Figueiredo <marfig@gmail.com>
Date2015-01-24 15:09 +0100
Message-ID<MPG.2f2dc5f7f281009b98968f@nntp.aioe.org>
In reply to#84463
In article <54c39e48$0$12996$c3e8da3$5496439d@news.astraweb.com>, 
steve+comp.lang.python@pearwood.info says...
> 
> I'm not sure if you're making a general observation or one which is
> specific
> to Python. Plenty of languages have static analysis as a language feature.
> Are you arguing they are wrong to do so?
> 

No. I'm arguing static analysis should not consume a programming 
language keyword space. Static analysis is just a development tool.

> 
> def myfunction(arg1, arg2):
>     """
>     Normal docstring.
>     @typehint: (str, int) -> bool"""
>     return True
> 
> One of the problems with this is that it put the information about
> parameters far away from the parameter list itself.

Then move it to the first line of the docstring...


> > I removed the arguments names on purpose. They are only necessary on 
> > the
> > PEP because type hinting is a part of the function header there.
> > However, when using a documentation like pattern as above (or as in your
> > own example), they can be safely removed, with the added benefit of
> > making the syntax simpler.
> 
> Only at the cost of making it hard to read.

If you want the redundancy and a potential source of new bugs by having 
a type hint in a docstring include argument names... You see, there's 
always a downside to everything.

Meanwhile, object names have nothing to do with type analsys, which 
makes arguments names rather irrelevant in the context of static 
analysis. I'd rather promote types than names. Remove names and you 
will.

> > 
> >      "@typehint: (str, int) -> bool"
> >      def myfunction(arg1, arg2):
> 
> That's somewhat better, in that at least the hint is close to the function
> signature. But it has a lot of disadvantages: it is compile-time only, the
> type hints aren't available at runtime.

It's static analysis. You don't need runtime execution.

> It requires extra complexity to the
> parser, so that decorators may be separated from the function by a hint:
> 
> @decorate
> "@typehint: (str, int) -> bool"
> def myfunction(arg1, arg2):
> 
> No doubt some people will get them the wrong way around, and the type
> checker may silently ignore their hints:
> 
> "@typehint: (str, int) -> bool"
> @decorate
> def myfunction(arg1, arg2):
> 
> And others will write:
> 
> @decorate
> @typehint(str, int) -> bool
> def myfunction(arg1, arg2):
> 

That seems like you are fishing. What is exactly your point? That people 
will not be able to understand the rules of type hinting? And that 
somehow is going to be an universal problem?

> Some syntax will be a bug magnet. This is one.

You think?

[toc] | [prev] | [next] | [standalone]


#84469

FromMario Figueiredo <marfig@gmail.com>
Date2015-01-24 15:32 +0100
Message-ID<MPG.2f2dcb7d6f032c56989690@nntp.aioe.org>
In reply to#84467
In article <MPG.2f2dc5f7f281009b98968f@nntp.aioe.org>, marfig@gmail.com 
says...
> 
> In article <54c39e48$0$12996$c3e8da3$5496439d@news.astraweb.com>, 
> steve+comp.lang.python@pearwood.info says...
> > 
> > def myfunction(arg1, arg2):
> >     """
> >     Normal docstring.
> >     @typehint: (str, int) -> bool"""
> >     return True
> > 
> > One of the problems with this is that it put the information about
> > parameters far away from the parameter list itself.
> 
> Then move it to the first line of the docstring...

Here's a more concrete example of what can be done in the docstring, 
taken from one of the examples in PEP 484. (Remember, we just moving the 
whole structure of type hinting to a new docstring parameter, instead of 
having it in the function header.

"PEP 484"
def handle_employees(e: Union[Employee, Sequence[Employee]]):
    if isinstance(e, Employee):
        e = [e]
    ...

"My proposal:"

def handle_employees(e):
    """
    Handles an employee or list of employees by firing the whole
    bunch of 'em lazy sods.

    @hint: Union[Employee, Sequence[Employee]]
    :param e: A single employee or a list of employees 
    :return: None
    """
    if isinstance(e, Employee):
        e = [e]
    ...

If you find that hard to read or feel you still can't match type hints 
to their respective arguments in the function header... then, yeah, 
there's no convincing you.

My only pet peevee with this is that @int: becomes part of __doc__ and 
some pundits may argue against that inclusion. I don't have a real 
answer to that problem. I personally see that as a minor consequence, 
but can understand static analysis isn't really a part of a function 
documentation.

[toc] | [prev] | [next] | [standalone]


#84474

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-25 03:05 +1100
Message-ID<54c3c2ce$0$13011$c3e8da3$5496439d@news.astraweb.com>
In reply to#84467
Mario Figueiredo wrote:

> In article <54c39e48$0$12996$c3e8da3$5496439d@news.astraweb.com>,
> steve+comp.lang.python@pearwood.info says...
>> 
>> I'm not sure if you're making a general observation or one which is
>> specific
>> to Python. Plenty of languages have static analysis as a language
>> feature. Are you arguing they are wrong to do so?
>> 
> 
> No. I'm arguing static analysis should not consume a programming
> language keyword space. Static analysis is just a development tool.

Hmmm. I don't see how that could possible work in practice. Let's take C
syntax for example:

int i;

declares i to be an int. How is this supposed to work without making int a
reserved word? Likewise for Pascal:

i: Integer;

In Python, built-in functions aren't reserved words, but we surely don't
expect a lexical type-checker to evaluate arbitrary code in order to check
whether int has been shadowed:

import random
if random.random() < 0.5:
    int = str

def spam(n:int):
    """Or if you prefer docstrings:
    @param n: int
    """

Even though int is not actually reserved, the type-checker is permitted to
behave as if it were, and it is difficult to see how it could possibly work
in practice if it did not behave that way.

At least it is difficult for me.


>> def myfunction(arg1, arg2):
>>     """
>>     Normal docstring.
>>     @typehint: (str, int) -> bool"""
>>     return True
>> 
>> One of the problems with this is that it put the information about
>> parameters far away from the parameter list itself.
> 
> Then move it to the first line of the docstring...

Which is close to the current convention used by document generators.


>> > I removed the arguments names on purpose. They are only necessary on
>> > the
>> > PEP because type hinting is a part of the function header there.
>> > However, when using a documentation like pattern as above (or as in
>> > your own example), they can be safely removed, with the added benefit
>> > of making the syntax simpler.
>> 
>> Only at the cost of making it hard to read.
> 
> If you want the redundancy and a potential source of new bugs by having
> a type hint in a docstring include argument names... You see, there's
> always a downside to everything.

True, true.

But you can't really avoid duplicating the name in the documentation, just
as you can't avoid duplicating the name in the body of the function. How
can you talk about the parameter if you don't refer to it by name? Such
unavoidable duplication of names is not what most people call "redundancy".


> Meanwhile, object names have nothing to do with type analsys, which
> makes arguments names rather irrelevant in the context of static
> analysis. I'd rather promote types than names. Remove names and you
> will.

How can type analyse avoid dealing with names?

def function(arg: int):
    x = arg + 1
    arg.append(None)


How does the type checker know that "x = arg + 1" is legal, but arg.append
is not? It has to know that since arg has not been rebinded yet, arg is an
int, not a list. It cannot do that unless it knows the name arg.

Type analysis has to deal with more than *just* names. Ideally, it should be
able to infer the type of a whole expression. But it *must* be able to deal
with names -- it would be a pretty poor type-checker that couldn't warn
about this:

    n = 1
    n.sort()


>> >      "@typehint: (str, int) -> bool"
>> >      def myfunction(arg1, arg2):
>> 
>> That's somewhat better, in that at least the hint is close to the
>> function signature. But it has a lot of disadvantages: it is compile-time
>> only, the type hints aren't available at runtime.
> 
> It's static analysis. You don't need runtime execution.

You don't "need" it, but Python has it, so that's what any alternative has
to target. If an alternative fails to met that target, that doesn't
necessarily rule the alternative out, but it is a point against it.

If you want to talk about programming languages in their full generality,
please say so, otherwise I'll assume you're referring to Python. Python
offers rich and powerful introspection abilities, and annotations are
available at runtime, which enables runtime access to the type hints. Any
alternative which does not offer that same runtime introspection is missing
an important piece of functionality.


>> It requires extra complexity to the
>> parser, so that decorators may be separated from the function by a hint:
>> 
>> @decorate
>> "@typehint: (str, int) -> bool"
>> def myfunction(arg1, arg2):
>> 
>> No doubt some people will get them the wrong way around, and the type
>> checker may silently ignore their hints:
>> 
>> "@typehint: (str, int) -> bool"
>> @decorate
>> def myfunction(arg1, arg2):
>> 
>> And others will write:
>> 
>> @decorate
>> @typehint(str, int) -> bool
>> def myfunction(arg1, arg2):
>> 
> 
> That seems like you are fishing. What is exactly your point? That people
> will not be able to understand the rules of type hinting?

No. My point was in the next sentence of my post:

"Some syntax will be a bug magnet. This is one."

I believe that your suggestion of a magic string that looks like a decorator
but isn't would be a bug magnet. You have no help from the compiler. If you
get the syntax of an annotation wrong, you get a syntax error:

py> def spam(x int):
  File "<stdin>", line 1
    def spam(x int):
                 ^
SyntaxError: invalid syntax


but if you get one of your magic strings wrong, nothing happens because it's
just a string and the compiler ignores it. The type-checker, on the other
hand, is caught between two bad alternatives:

- complain about every string it doesn't know how to parse, which 
  will annoy anyone who uses bare strings for any other purpose; or

- silently ignore any such string with an error.

Both alternatives are bad. There is no good way to deal with this, either
annoy the user with false positives, or fail silently. 

Not all alternatives are equally good. There are at least five choices for
where to put type hints/declarations:

- in the function signature (annotations);
- in the docstring;
- applied using a decorator;
- using a specially formatted string (other than the docstring);
- using a stub file.

These are not equally as good, and the choice between them is not merely a
matter of personal preference of what looks nicer. There is about 60 years
worth of prior art on type declarations, going back to Fortran in the
1950s, and we can be certain that putting the type declaration in the
signature is the least likely to go wrong. We may need (e.g.) stub files as
a fallback for when we can't use the function signature, but that doesn't
mean we should forgo the best solution when it is available.


> And that 
> somehow is going to be an universal problem?
> 
>> Some syntax will be a bug magnet. This is one.
> 
> You think?

Yes I do.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#84594

FromMarco Buttu <marco.buttu@gmail.com>
Date2015-01-24 15:25 +0100
Message-ID<mailman.18143.1422260120.18130.python-list@python.org>
In reply to#84467
On 24/01/2015 15:09, Mario Figueiredo wrote:

>> >def myfunction(arg1, arg2):
>> >     """
>> >     Normal docstring.
>> >     @typehint: (str, int) -> bool"""
>> >     return True
>> >
>> >One of the problems with this is that it put the information about
>> >parameters far away from the parameter list itself.
> Then move it to the first line of the docstring...

I like this idea, because nevertheless the type hinting is optional, the 
mypy syntax affects every Python programmer who has to read other code 
that will use this syntax, while the docstring one does not.

-- 
Marco Buttu

INAF-Osservatorio Astronomico di Cagliari
Via della Scienza n. 5, 09047 Selargius (CA)
Phone: 070 711 80 217
Email: mbuttu@oa-cagliari.inaf.it

[toc] | [prev] | [next] | [standalone]


#84477

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2015-01-24 08:41 -0800
Message-ID<7db16477-1dd6-4f93-adfe-54f7b7a690b2@googlegroups.com>
In reply to#84463
On Saturday, January 24, 2015 at 7:30:02 AM UTC-6, Steven D'Aprano wrote:
> [...] It requires extra complexity to the parser, so that
> decorators may be separated from the function by a hint:
> 
> @decorate
> "@typehint: (str, int) -> bool"
> def myfunction(arg1, arg2):
> 
> No doubt some people will get them the wrong way around,
> and the type checker may silently ignore their hints:
> 
> "@typehint: (str, int) -> bool"
> @decorate
> def myfunction(arg1, arg2):
> 
> And others will write:
> 
> @decorate
> @typehint(str, int) -> bool
> def myfunction(arg1, arg2):
> 
> 
> and be annoyed or perplexed by the syntax error.
> 
> Some syntax will be a bug magnet. This is one.

Your argument is weak here. If the interpreter cannot
distinguish between "@typehint ..." and "@ ..." then those
who defined the logic need to go back to CS-101. Secondly,
why set *ANY* rules as to the order of typehints -vs-
decorators? Who cares about the "syntactical order", when
they can be parsed and then applied in *ANY* order.
Syntactical order need not *ALWAYS* be significant. In fact,
in this case, syntactic ordering rules are superfluously 
onerous on the human.

And that is how you kill two birds with one stone.

[toc] | [prev] | [next] | [standalone]


#84478

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-25 04:26 +1100
Message-ID<54c3d5d0$0$12977$c3e8da3$5496439d@news.astraweb.com>
In reply to#84477
Rick Johnson wrote:

> On Saturday, January 24, 2015 at 7:30:02 AM UTC-6, Steven D'Aprano wrote:
>> [...] It requires extra complexity to the parser, so that
>> decorators may be separated from the function by a hint:
>> 
>> @decorate
>> "@typehint: (str, int) -> bool"
>> def myfunction(arg1, arg2):
>> 
>> No doubt some people will get them the wrong way around,
>> and the type checker may silently ignore their hints:
>> 
>> "@typehint: (str, int) -> bool"
>> @decorate
>> def myfunction(arg1, arg2):
>> 
>> And others will write:
>> 
>> @decorate
>> @typehint(str, int) -> bool
>> def myfunction(arg1, arg2):
>> 
>> 
>> and be annoyed or perplexed by the syntax error.
>> 
>> Some syntax will be a bug magnet. This is one.
> 
> Your argument is weak here. If the interpreter cannot
> distinguish between "@typehint ..." and "@ ..." 

Thank you for demonstrating my point for me.

The difference is not

@typehint(...)
def func(...): 

versus any other decorator, but the STRING:

"@typehint(...)"

being used where a decorator would normally be expected.

If a genius of the degree like Rick can be fooled, what hope do ordinary
mortals have?



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#84480

FromMark Lawrence <breamoreboy@yahoo.co.uk>
Date2015-01-24 17:36 +0000
Message-ID<mailman.18090.1422120987.18130.python-list@python.org>
In reply to#84478
On 24/01/2015 17:26, Steven D'Aprano wrote:
> Rick Johnson wrote:
>
>> On Saturday, January 24, 2015 at 7:30:02 AM UTC-6, Steven D'Aprano wrote:
>>> [...] It requires extra complexity to the parser, so that
>>> decorators may be separated from the function by a hint:
>>>
>>> @decorate
>>> "@typehint: (str, int) -> bool"
>>> def myfunction(arg1, arg2):
>>>
>>> No doubt some people will get them the wrong way around,
>>> and the type checker may silently ignore their hints:
>>>
>>> "@typehint: (str, int) -> bool"
>>> @decorate
>>> def myfunction(arg1, arg2):
>>>
>>> And others will write:
>>>
>>> @decorate
>>> @typehint(str, int) -> bool
>>> def myfunction(arg1, arg2):
>>>
>>>
>>> and be annoyed or perplexed by the syntax error.
>>>
>>> Some syntax will be a bug magnet. This is one.
>>
>> Your argument is weak here. If the interpreter cannot
>> distinguish between "@typehint ..." and "@ ..."
>
> Thank you for demonstrating my point for me.
>
> The difference is not
>
> @typehint(...)
> def func(...):
>
> versus any other decorator, but the STRING:
>
> "@typehint(...)"
>
> being used where a decorator would normally be expected.
>
> If a genius of the degree like Rick can be fooled, what hope do ordinary
> mortals have?
>

So Rick is having a bad hair day, hence using fuzzy logic?  Ooh, that 
one is so bad even my stomach hurts :)

-- 
My fellow Pythonistas, ask not what our language can do for you, ask
what you can do for our language.

Mark Lawrence

[toc] | [prev] | [next] | [standalone]


#84481

FromPaul Rubin <no.email@nospam.invalid>
Date2015-01-24 09:37 -0800
Message-ID<87bnlo5bbz.fsf@jester.gateway.sonic.net>
In reply to#84478
Steven D'Aprano <steve+comp.lang.python@pearwood.info> writes:
> versus any other decorator, but the STRING:
> "@typehint(...)"
> being used where a decorator would normally be expected.

I didn't catch that either.  I think if hints are to go in decorators,
then it's best to extend the decorator mechanism to allow arbitrary
syntax, e.g.

@-typehint (str, int) -> bool

The @- would signify that the typehint function is to receive an AST as
its argument, rather than its callable.  The AST would be the parse tree
for the rest of the line.  Alternatively, it could get the line as a
string and parse it with appropriate functions from the ast module.

[toc] | [prev] | [next] | [standalone]


#84488

FromChris Angelico <rosuav@gmail.com>
Date2015-01-25 06:59 +1100
Message-ID<mailman.18095.1422129558.18130.python-list@python.org>
In reply to#84481
On Sun, Jan 25, 2015 at 4:37 AM, Paul Rubin <no.email@nospam.invalid> wrote:
> Steven D'Aprano <steve+comp.lang.python@pearwood.info> writes:
>> versus any other decorator, but the STRING:
>> "@typehint(...)"
>> being used where a decorator would normally be expected.
>
> I didn't catch that either.  I think if hints are to go in decorators,
> then it's best to extend the decorator mechanism to allow arbitrary
> syntax, e.g.
>
> @-typehint (str, int) -> bool
>
> The @- would signify that the typehint function is to receive an AST as
> its argument, rather than its callable.  The AST would be the parse tree
> for the rest of the line.  Alternatively, it could get the line as a
> string and parse it with appropriate functions from the ast module.

That seems extremely messy. Why not use what can already be done?
Since you talk about getting the line as a string...

@typehint("(str, int) -> bool")

ChrisA

[toc] | [prev] | [next] | [standalone]


#84315

FromTerry Reedy <tjreedy@udel.edu>
Date2015-01-23 00:03 -0500
Message-ID<mailman.18018.1421989508.18130.python-list@python.org>
In reply to#84297
On 1/22/2015 10:59 PM, Chris Angelico wrote:
> On Fri, Jan 23, 2015 at 2:22 PM, Terry Reedy <tjreedy@udel.edu> wrote:
>> This idea is so brilliant that it is already an option in mypy and is part
>> of the new type-hint proposal.  The separate type-hint files are called
>> 'stub files'.
>
> It's worth pointing out, too, that the idea isn't panaceaic - it's
> just another tool in the box. Any time you break related things into
> separate places, especially separate files, the tendency for them to
> get out of sync grows dramatically.

The same could be said of putting tests in a separate file.

 > Use of stub files for something
> that's only occasionally run (the type-checking linter) increases the
> potential time delay between the error and the fix.

Projects that view type-checks as tests that must pass will probably run 
them much more often.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#84323

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-01-23 16:59 +1100
Message-ID<54c1e349$0$12975$c3e8da3$5496439d@news.astraweb.com>
In reply to#84315
Terry Reedy wrote:

> On 1/22/2015 10:59 PM, Chris Angelico wrote:
>> On Fri, Jan 23, 2015 at 2:22 PM, Terry Reedy <tjreedy@udel.edu> wrote:
>>> This idea is so brilliant that it is already an option in mypy and is
>>> part
>>> of the new type-hint proposal.  The separate type-hint files are called
>>> 'stub files'.
>>
>> It's worth pointing out, too, that the idea isn't panaceaic - it's
>> just another tool in the box. Any time you break related things into
>> separate places, especially separate files, the tendency for them to
>> get out of sync grows dramatically.
> 
> The same could be said of putting tests in a separate file.

I agree!

Python has doctests, which live right there with the function. It also has
assertions, which can be considered a form of continuous testing.

Eiffel has syntax for design-by-contract (testing pre-conditions,
post-conditions and invariants) there in the body of the function or
method:

https://docs.eiffel.com/book/method/et-design-contract-tm-assertions-and-exceptions#Expressing_assertions


Contracts are a form of testing, since they are designed to be disabled in
production. Other languages with syntactic support for Design By Contract
include Clojure, Cobra, D, Mercury, Perl6 and Racket.

Cobra is especially close to Python-like syntax, and supports unit tests as
well:


    def sqroot(i as int) as float
        require 
           i > 0
        ensure
           result > 0
        tests
           assert sqroot(25) == 5.0
        body
            ...


It would be nice to be able to include at least *some* tests right there in
the code rather than in a separate file.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#84343

From"Fetchinson ." <fetchinson@googlemail.com>
Date2015-01-23 14:23 +0100
Message-ID<mailman.18034.1422019400.18130.python-list@python.org>
In reply to#84323
On 1/23/15, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
> Terry Reedy wrote:
>
>> On 1/22/2015 10:59 PM, Chris Angelico wrote:
>>> On Fri, Jan 23, 2015 at 2:22 PM, Terry Reedy <tjreedy@udel.edu> wrote:
>>>> This idea is so brilliant that it is already an option in mypy and is
>>>> part
>>>> of the new type-hint proposal.  The separate type-hint files are called
>>>> 'stub files'.
>>>
>>> It's worth pointing out, too, that the idea isn't panaceaic - it's
>>> just another tool in the box. Any time you break related things into
>>> separate places, especially separate files, the tendency for them to
>>> get out of sync grows dramatically.
>>
>> The same could be said of putting tests in a separate file.
>
> I agree!
>
> Python has doctests, which live right there with the function. It also has
> assertions, which can be considered a form of continuous testing.
>
> Eiffel has syntax for design-by-contract (testing pre-conditions,
> post-conditions and invariants) there in the body of the function or
> method:
>
> https://docs.eiffel.com/book/method/et-design-contract-tm-assertions-and-exceptions#Expressing_assertions
>
>
> Contracts are a form of testing, since they are designed to be disabled in
> production. Other languages with syntactic support for Design By Contract
> include Clojure, Cobra, D, Mercury, Perl6 and Racket.
>
> Cobra is especially close to Python-like syntax, and supports unit tests as
> well:
>
>
>     def sqroot(i as int) as float
>         require
>            i > 0
>         ensure
>            result > 0
>         tests
>            assert sqroot(25) == 5.0
>         body
>             ...
>
> It would be nice to be able to include at least *some* tests right there in
> the code rather than in a separate file.

I completely agree. A cobra-style type hinting implementation would
satisfy everyone who doesn't want to make function signatures noisy
(including me) and would also satisfy those who advocate for the
actual feature (type hinting) without worrying much about the
implementation detail. These two groups are overlapping by the way :)

In any case, I'm pretty sure it was said before, but I can't really
find it anywhere, can someone tell me what the rationale is for
*function signature* type hinting?

I totally get type hinting in general, but why does it have to be in
the function signature? Any reason for that specifically?

Are there lots of folks who actually insist on the type hints being in
the function signature and definitely want to see it there and not
somewhere else?

I'd say cobra-style type hinting would be great, but also something
which is property looking:

@official_type_hinting_by_the_psf( arg1: str, arg2: int, returns: bool )
def myfunction( arg1, arg2 ):
    return True

I really like the idea that in python I don't have lots of choices in
many areas, certain things are dictated. The big advantage is that
when I read other people's code I know what to expect so me being
restricted is a small price to pay that is totally worth it. So I'd
come down on the side of the complainers in this case, the type
hinting pep introduces noisy and not so readable features (I
understand these are optional) which if used will make readability
suffer. If there is a pep for it, people will use it, so the fact that
it is optional is irrelevant, it will be used, so people will be faced
with it when reading other people's code, whether they like it or not.

Cheers,
Daniel




-- 
Psss, psss, put it down! - http://www.cafepress.com/putitdown

[toc] | [prev] | [next] | [standalone]


#84396

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2015-01-23 12:21 -0800
Message-ID<12d74fb6-f7d7-4ff0-88d3-6076a5dc7b57@googlegroups.com>
In reply to#84343
On Friday, January 23, 2015 at 7:23:34 AM UTC-6, Fetchinson . wrote:
> I really like the idea that in python I don't have lots of
> choices in many areas, certain things are dictated. The
> big advantage is that when I read other people's code I
> know what to expect so me being restricted is a small
> price to pay that is totally worth it. So I'd come down on
> the side of the complainers in this case,

"the complainers"??? O:-) 

Intentional or not, your word choice paints a negative
connotation of the "opposition". We are not "complainers",
we merely hold a contradictory view to that of the
"proposers".

Injecting polarity into debates is dangerous, because, then
we get off into the emotional weeds and a solution may never
be found -- just observe the polarization of American
politics if you don't believe me --> *PUKE*
    
Rational people understand that both sides of any argument
deserve objective consideration, and when a unanimous
solution cannot be found, a compromise must be made on both
sides.

    Even if that means cutting the baby in half.

Sorry to pick on you. Everything else you said was very
rational and articulate!

[toc] | [prev] | [next] | [standalone]


#84403

FromMario Figueiredo <marfig@gmail.com>
Date2015-01-23 22:12 +0100
Message-ID<MPG.2f2cd7a8eb1d5f1798968b@nntp.aioe.org>
In reply to#84396
In article <12d74fb6-f7d7-4ff0-88d3-6076a5dc7b57@googlegroups.com>, 
rantingrickjohnson@gmail.com says...
> 
> Injecting polarity into debates is dangerous, because, then
> we get off into the emotional weeds and a solution may never
> be found -- just observe the polarization of American
> politics if you don't believe me --> *PUKE*

I agree entirely. But you have to excuse me... weren't you the one 
calling Guido lapdog (you used worse names) to anyone who agreed with 
the PEP? ;)

Don't been an hypocrit also, when Rantingrick is good enough.

[toc] | [prev] | [next] | [standalone]


#84406

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2015-01-23 14:26 -0800
Message-ID<72dec946-b6c9-4572-9427-e887c8bb60dc@googlegroups.com>
In reply to#84403
On Friday, January 23, 2015 at 3:13:12 PM UTC-6, Mario Figueiredo wrote:
> In article <12d74fb6-f7d7-4ff0-88d3-6076a5dc7b57@googlegroups.com>, 
> Sir Richard Johnson The First says...
> > 
> > Injecting polarity into debates is dangerous, because,
> > then we get off into the emotional weeds and a solution
> > may never be found -- just observe the polarization of
> > American politics if you don't believe me --> *PUKE*
> 
> I agree entirely. But you have to excuse me... weren't you
> the one calling Guido lapdog (you used worse names) to
> anyone who agreed with the PEP? ;)

I was not calling *ANYONE* who agreed with the PEP "a
lapdog", my statement was more specific. I called Chris a
"lapdog of" and a "rabbid fanboy" -- Guido was merely the
"implied Satan".

Of course i'm not suggesting that Guido is a malevolent
godlike being, his inclusion in the expression is merely a
incidental result of Chris's idol worship of "everything Guido".
Although, to be fair, I guess i may have embellished a bit
by using the word "rabbid", and for that i apologize.

But to respond to your assertion that i'm being
hypocritical: nonsense. Stating facts is *NEVER*
hypocritical. Just because a fact happens to be an
"inconvenient truth" does not invalidate it's truthfulness.

Chris (or anybody for that matter) can choose to be a free
thinking individual, or a brainwashed disciple, the choice is
his. Even intelligent people (like Chris) can fall under the
spell of a "implicit cult of personality". 

[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.python


csiph-web