[Python-ideas] Re: List - append

2020-01-21 Thread Guido van Rossum
Well, mypy is often used primarily as a linter on steroids.

Anyway, agreed with your point!

On Tue, Jan 21, 2020 at 10:22 AM Andrew Barnert  wrote:

> On Jan 19, 2020, at 20:54, Guido van Rossum  wrote:
> >
> > Actually, `bar = foo` is more likely to be detected by mypy, since it is
> probably a type error (unless bar isn't used or is only used in an `Any`
> context). For mypy, flagging bare `foo` is harder, because we would have to
> introduce a fairly arbitrary rule that says "a top-level expression cannot
> have a callable type". So we haven't done this yet.
>
> Yeah, that’s a rule that makes sense for linters, but not for compilers,
> because it obviously can have false positives, it’s just that useful false
> positives are incredibly rare compared to mistakes.
>
> When I said linters and static analyzers I meant linters and linter-like
> static analyzers like clang-analyze, not linters and compiler/prover-like
> static analyzers like mypy. I can see why that was misleading, because
> Python has none of the former and a very prominent one of the latter; sorry
> for being confusing.
>
> Anyway, the point I intended to make is that it is a real cost that
> catching bare `foo` where `foo()` was meant can only be done by a linter,
> but it’s nowhere near as big as the benefit of being able to pass functions
> and methods around the most obvious way.
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/N3LXIPGVAW4N5ULA7GS4JSYGQBMNBJ7R/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-21 Thread Andrew Barnert via Python-ideas
On Jan 19, 2020, at 20:54, Guido van Rossum  wrote:
> 
> Actually, `bar = foo` is more likely to be detected by mypy, since it is 
> probably a type error (unless bar isn't used or is only used in an `Any` 
> context). For mypy, flagging bare `foo` is harder, because we would have to 
> introduce a fairly arbitrary rule that says "a top-level expression cannot 
> have a callable type". So we haven't done this yet.

Yeah, that’s a rule that makes sense for linters, but not for compilers, 
because it obviously can have false positives, it’s just that useful false 
positives are incredibly rare compared to mistakes.

When I said linters and static analyzers I meant linters and linter-like static 
analyzers like clang-analyze, not linters and compiler/prover-like static 
analyzers like mypy. I can see why that was misleading, because Python has none 
of the former and a very prominent one of the latter; sorry for being confusing.

Anyway, the point I intended to make is that it is a real cost that catching 
bare `foo` where `foo()` was meant can only be done by a linter, but it’s 
nowhere near as big as the benefit of being able to pass functions and methods 
around the most obvious way.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/LSEDW42SHHBS7GURXRLBEGQIHGHHF3U3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-20 Thread Steven D'Aprano
On Sun, Jan 19, 2020 at 04:27:30PM -0500, David Mertz wrote:

> I'm not sure what you intend here:
> 
> A fluent interface is normally implemented by using method chaining

Indeed. *Implemented by*, not "the same as".


>  to implement method
> cascading  (in languages
> that do not natively support cascading), concretely by having each method
> return this  (
> self).

If you read Fowler's post on the subject all the way to the end, you 
will see his comment:

I've also noticed a common misconception - many people seem to 
equate fluent interfaces with Method Chaining. Certainly chaining 
is a common technique to use with fluent interfaces, but true 
fluency is much more than that.

He also points out that returning self (this) is not a hard requirement:

You should choose your return type based on what you need to 
continue fluent action.

Here's the link again for anyone who missed it the first time.

https://www.martinfowler.com/bliki/FluentInterface.html

Even the Wikipedia page you linked to says:

Note that a "fluent interface" means more than just method cascading 
via chaining; it entails designing an interface that reads like a 
DSL, using other techniques like "nested functions and object 
scoping".

which is one paragraph after the bit you quoted at me.

The bottom line is that what the OP was asking for:

result = list(something).append(spam).append(eggs).append(cheese)

is not a fluent interface, it's just boring old method chaining like we 
already do with strings. Fowler's example of a fluent interface is worth 
reading: he uses it to build a compound object (an Order) using a 
lightweight DSL.

The critical part is Fowler's comment:

Probably the most important thing to notice about this style is that 
the intent is to do something along the lines of an internal 
DomainSpecificLanguage. Indeed this is why we chose the term 
'fluent' to describe it, in many ways the two terms are synonyms. 
The API is primarily designed to be readable and to flow.

If it doesn't read fluently as a domain specific language, it isn't a 
fluent interface. Merely chaining function calls or method calls or 
infix operators or statements is not sufficient.

If it were sufficient, then everything is a fluent interface and the 
term is meaningless.


> > A fluent interface is built on top of method chaining: you can't
> > (easily?) have a fluent interface without chaining, but you can have
> > chaining without a fluent interface. See Fowler, who came up with the
> > term and ought to know what he meant by it :-)
> >
> 
> I don't really see what you mean in Fowler that would allow "non-fluent"
> method chaining,

Are you arguing that *any* time you chain two method call in a single 
expression, that's a fluent interface? If not, then you can answer that 
question yourself: think of a case where chained methods aren't 
sufficient, and you have your answer:

string.strip().split().count("spam")

That's just a mechanical rearrangement of postfix or prefix functional 
syntax with no additional DSL features.

string strip split "spam" count

count(split(strip(string)))("spam")

It's not a DSL and it's not "fluent" in any meaningful sense, only in 
the trivial sense that we can read source code in languages we can read.

Mutability is also a side-issue. Being written in Java, Fowler's "Order" 
example would probably mutate a Customer object and an Order object, but 
one could use a fluent interface with Haskell where each call created a 
new object and disgarded the previous one.

The aim of fluent interfaces is to create a domain-specific interface, 
not just to squeeze things into a single expression by chaining dots. 
The *mechanism* they use to implement that DSL is method chaining 
together with objects designed to cooperate together to give the 
semantics needed in your domain.

For example, in Fowler's example, the "with" method knows about 
products, and can create an order line and add it to an order.

In the same way that people mistakenly think that the Rule of Demeter is 
about "never put two dots in the one expression", people are mistaken if 
they think fluent interfaces are *merely* about chaining methods.

It's like arguing that Python's command line and REPL is a GUI, because 
the terminal window is displayed using pixels. Well yes it is, but 
that's not sufficient to make a GUI.


> but I'll stipulate there's some sentence I missed or read
> wrong.  Nowadays, the term is in more widespread use, and exactly what
> Fowler meant in 2005 isn't really essential.

The DSL part gets to the core of what distinguishes a fluent interface 
from merely chaining methods (or pipes, or function calls). If there's 
no difference between "fluent interface" and "method chaining" then why 
do we 

[Python-ideas] Re: List - append

2020-01-19 Thread Guido van Rossum
On Sun, Jan 19, 2020 at 8:16 PM Andrew Barnert  wrote:

> On Jan 19, 2020, at 15:20, Guido van Rossum  wrote:
>
>
> On Sun, Jan 19, 2020 at 3:10 PM Tim Peters  wrote:
>
>> [Guido, on Pythons before 1.0.2 always printing non-None expression
>>  statement results]
>> > Heh. That was such a misfeature that I had thoroughly suppressed any
>> > memory of its existence. -k indeed. :-)
>>
>> I prefer to think of it as a bit of genius :-)
>>
>> The natural desire to avoid mounds of useless output taught all of us,
>> core developers and end users, to code mutating methods as procedures
>> (always return None) rather than functions.
>>
>> The thing that amazed me at the time (and still does with hindsight!)
>> is how very few complaints that attracted!  Because it really was a
>> horrible misfeature ;-)
>>
>
> My guess is that method chaining wasn't in widespread use, and languages
> that made a distinction between functions and procedures (a la Pascal and
> Fortran) were more common than they are now.
>
> One thing that we lost when we dropped this: the bug where a user wrote
> `foo` rather than `foo()` was caught more reliably then. Similarly, in the
> async world, there's a common mistake where users write `foo()` rather than
> `await foo()`, and that behavior would have caught such bugs.
>
> Now we can't even flag such things statically (e.g. in mypy) because
> people might complain that they *meant* to write what they wrote (since it
> works).
>
>
> Personally, I love the fact that in Python, the way to reference a
> function foo or a method baz on bar is just `foo` or `bar.baz`, and the way
> to call that thing later is just parens. There’s no ``, much less `bar`
> and `::baz` as separate arguments or passing the method name as a
> string (or inventing a new symbol or selector type that’s almost the same
> as a string but not) or wrapping it in a useless lambda or block, etc. as
> in Ruby, Smalltalk, JS, C++, etc.
>
> Sure, it means you can’t have no-parens calling syntax (unless you curry
> all functions a la Haskell, but then it’s very hard to have
> variable-signature functions) or flag accidental no-parens calls as errors.
> But being able to refer to all things, even functions and methods, with the
> one and only one obvious spelling for each thing is nice.
>

Yes of course. :-)

And linters and analyzers do already flag the most common error case, where
> you just put `foo` instead of `foo()` on a like by itself (because it’s an
> expression that has no side effects but you don’t use its value). It’s only
> when you accidentally do something like `bar = foo` instead of `bar =
> foo()` (and then don’t use `bar` in a way that would detectably cause a
> TypeError) that can’t be detected.
>

Actually, `bar = foo` is more likely to be detected by mypy, since it is
probably a type error (unless bar isn't used or is only used in an `Any`
context). For mypy, flagging bare `foo` is harder, because we would have to
introduce a fairly arbitrary rule that says "a top-level expression cannot
have a callable type". So we haven't done this yet. (Ditto for omitting
`await`, for which we would have to have a rule "a top-level expression
cannot have an awaitable type".)

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FMQ767VQRU6KEQYLKPVVC2JQB6VGQ5A5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Andrew Barnert via Python-ideas
On Jan 19, 2020, at 15:20, Guido van Rossum  wrote:
> 
>> On Sun, Jan 19, 2020 at 3:10 PM Tim Peters  wrote:
>> [Guido, on Pythons before 1.0.2 always printing non-None expression
>>  statement results]
>> > Heh. That was such a misfeature that I had thoroughly suppressed any
>> > memory of its existence. -k indeed. :-)
>> 
>> I prefer to think of it as a bit of genius :-)
>> 
>> The natural desire to avoid mounds of useless output taught all of us,
>> core developers and end users, to code mutating methods as procedures
>> (always return None) rather than functions.
>> 
>> The thing that amazed me at the time (and still does with hindsight!)
>> is how very few complaints that attracted!  Because it really was a
>> horrible misfeature ;-)
> 
> My guess is that method chaining wasn't in widespread use, and languages that 
> made a distinction between functions and procedures (a la Pascal and Fortran) 
> were more common than they are now.
> 
> One thing that we lost when we dropped this: the bug where a user wrote `foo` 
> rather than `foo()` was caught more reliably then. Similarly, in the async 
> world, there's a common mistake where users write `foo()` rather than `await 
> foo()`, and that behavior would have caught such bugs.
> 
> Now we can't even flag such things statically (e.g. in mypy) because people 
> might complain that they *meant* to write what they wrote (since it works).

Personally, I love the fact that in Python, the way to reference a function foo 
or a method baz on bar is just `foo` or `bar.baz`, and the way to call that 
thing later is just parens. There’s no ``, much less `bar` and `::baz` 
as separate arguments or passing the method name as a string (or inventing a 
new symbol or selector type that’s almost the same as a string but not) or 
wrapping it in a useless lambda or block, etc. as in Ruby, Smalltalk, JS, C++, 
etc.

Sure, it means you can’t have no-parens calling syntax (unless you curry all 
functions a la Haskell, but then it’s very hard to have variable-signature 
functions) or flag accidental no-parens calls as errors. But being able to 
refer to all things, even functions and methods, with the one and only one 
obvious spelling for each thing is nice.

And linters and analyzers do already flag the most common error case, where you 
just put `foo` instead of `foo()` on a like by itself (because it’s an 
expression that has no side effects but you don’t use its value). It’s only 
when you accidentally do something like `bar = foo` instead of `bar = foo()` 
(and then don’t use `bar` in a way that would detectably cause a TypeError) 
that can’t be detected.


___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/X2XIG26TKJAHYXCFXNOM4U7GIFU55PF2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Christopher Barker
By the way, if anyone is actually interested in this other than for
nostalgia , there have been a number of lengthy discussion on this list
about "Fluent" interfaces for Python. LIke this one for instance:

https://groups.google.com/forum/#!searchin/python-ideas/Method$20Chaining%7Csort:date/python-ideas/F_C8ZfxjV20/wXZSs5KwBAAJ

-CHB




On Sun, Jan 19, 2020 at 5:29 PM Christopher Barker 
wrote:

> On Sun, Jan 19, 2020 at 11:59 AM Tim Peters  wrote:
>
>> For a bit of history that I may have made up (heh - memory fades over
>> time!), as I recall, the very first Python pre-releases echoed to
>> stdout every non-None statement result.
>
>
> which is what MATLAB does, if you don't put a semi-colon at the end of the
> line (or somethign like that it's been a LONG time)
>
> I always found it mostly annoying, though it did make "print debugging"
> really easy.
>
> - CHB
>
> Python Language Consulting
>   - Teaching
>   - Scientific Software Development
>   - Desktop GUI and Web Development
>   - wxPython, numpy, scipy, Cython
>


-- 
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/4OQ6BK3QFZ32HIAJRTWGXMXXWWHIHWU7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Christopher Barker
On Sun, Jan 19, 2020 at 11:59 AM Tim Peters  wrote:

> For a bit of history that I may have made up (heh - memory fades over
> time!), as I recall, the very first Python pre-releases echoed to
> stdout every non-None statement result.


which is what MATLAB does, if you don't put a semi-colon at the end of the
line (or somethign like that it's been a LONG time)

I always found it mostly annoying, though it did make "print debugging"
really easy.

- CHB

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/GMCW7TSW2TSFOKXMTW6PUH23VTSPRCR4/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Guido van Rossum
On Sun, Jan 19, 2020 at 3:10 PM Tim Peters  wrote:

> [Guido, on Pythons before 1.0.2 always printing non-None expression
>  statement results]
> > Heh. That was such a misfeature that I had thoroughly suppressed any
> > memory of its existence. -k indeed. :-)
>
> I prefer to think of it as a bit of genius :-)
>
> The natural desire to avoid mounds of useless output taught all of us,
> core developers and end users, to code mutating methods as procedures
> (always return None) rather than functions.
>
> The thing that amazed me at the time (and still does with hindsight!)
> is how very few complaints that attracted!  Because it really was a
> horrible misfeature ;-)
>

My guess is that method chaining wasn't in widespread use, and languages
that made a distinction between functions and procedures (a la Pascal and
Fortran) were more common than they are now.

One thing that we lost when we dropped this: the bug where a user wrote
`foo` rather than `foo()` was caught more reliably then. Similarly, in the
async world, there's a common mistake where users write `foo()` rather than
`await foo()`, and that behavior would have caught such bugs.

Now we can't even flag such things statically (e.g. in mypy) because people
might complain that they *meant* to write what they wrote (since it works).

-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/BU73K4F4H3H4HOE5TZQF6MKADRRLPD23/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Tim Peters
[Guido, on Pythons before 1.0.2 always printing non-None expression
 statement results]
> Heh. That was such a misfeature that I had thoroughly suppressed any
> memory of its existence. -k indeed. :-)

I prefer to think of it as a bit of genius :-)

The natural desire to avoid mounds of useless output taught all of us,
core developers and end users, to code mutating methods as procedures
(always return None) rather than functions.

The thing that amazed me at the time (and still does with hindsight!)
is how very few complaints that attracted!  Because it really was a
horrible misfeature ;-)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/CJBEHWZAHEM5EPXFN4DLSNIKCXL3BF4E/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Guido van Rossum
Heh. That was such a misfeature that I had thoroughly suppressed any memory
of its existence. -k indeed. :-)

On Sun, Jan 19, 2020 at 1:33 PM Tim Peters  wrote:

> [Guido]
> > Sounds like a hallucination or fabrication.
>
> Nope!  Turns out my memory was right :-)
>
> > The behavior of `for i in range(10): i` in the REPL exists
> > to this day, and list.append() never returned a value.
>
> Sure, but those weren't the claims.  The claim was that the result of
> an expression statement was automatically printed unless it was None.
> `for i in range(10): i` _used_ to print 10 values _even when run from
> a program_ instead of from a shell.  I wasn't clear about that
> distinction before.
>
> From Misc/HISTORY:
>
> """
> ==> Release 1.0.2 (4 May 1994) <==
> ...
> * The result of a statement-level expression is no longer printed,
> except_ for expressions entered interactively.  Consequently, the -k
> command line option is gone.
> """
>
> Going back more:
>
> """
> ==> Release 0.9.9 (29 Jul 1993) <==
>  ...
> * New option -k raises an exception when an expression statement
> yields a value other than None.
> """
>
> Now I even recall the name of the early method-chaining user whose
> complaints triggered those changes - but will let the past rest in
> peace ;-)
>
>
> > The only thing I'm only 90% sure of is whether the REPL always ignored
> None values.
>
> I'm sure of that:  it never showed None values.  Because, if it had, I
> would have remembered bitching about the endless annoyance ;-)
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/WCLMDJQ6K7ZYG3JQCPAAT3AZOJARHF2I/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread David Mertz
I should really upgrade to 1.02!

% python
Python 1.0.1 (Jul 15 2016)
Copyright 1991-1994 Stichting Mathematisch Centrum, Amsterdam
>>> def f():
... for i in range(5): i
...
>>> f()
0
1
2
3
4

On Sun, Jan 19, 2020 at 4:33 PM Tim Peters  wrote:

> [Guido]
> > Sounds like a hallucination or fabrication.
>
> Nope!  Turns out my memory was right :-)
>
> > The behavior of `for i in range(10): i` in the REPL exists
> > to this day, and list.append() never returned a value.
>
> Sure, but those weren't the claims.  The claim was that the result of
> an expression statement was automatically printed unless it was None.
> `for i in range(10): i` _used_ to print 10 values _even when run from
> a program_ instead of from a shell.  I wasn't clear about that
> distinction before.
>
> From Misc/HISTORY:
>
> """
> ==> Release 1.0.2 (4 May 1994) <==
> ...
> * The result of a statement-level expression is no longer printed,
> except_ for expressions entered interactively.  Consequently, the -k
> command line option is gone.
> """
>
> Going back more:
>
> """
> ==> Release 0.9.9 (29 Jul 1993) <==
>  ...
> * New option -k raises an exception when an expression statement
> yields a value other than None.
> """
>
> Now I even recall the name of the early method-chaining user whose
> complaints triggered those changes - but will let the past rest in
> peace ;-)
>
>
> > The only thing I'm only 90% sure of is whether the REPL always ignored
> None values.
>
> I'm sure of that:  it never showed None values.  Because, if it had, I
> would have remembered bitching about the endless annoyance ;-)
>


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ODF4ZSJM2NQPLJ627PLX6XRZUNHHJHHQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Tim Peters
[Guido]
> Sounds like a hallucination or fabrication.

Nope!  Turns out my memory was right :-)

> The behavior of `for i in range(10): i` in the REPL exists
> to this day, and list.append() never returned a value.

Sure, but those weren't the claims.  The claim was that the result of
an expression statement was automatically printed unless it was None.
`for i in range(10): i` _used_ to print 10 values _even when run from
a program_ instead of from a shell.  I wasn't clear about that
distinction before.

>From Misc/HISTORY:

"""
==> Release 1.0.2 (4 May 1994) <==
...
* The result of a statement-level expression is no longer printed,
except_ for expressions entered interactively.  Consequently, the -k
command line option is gone.
"""

Going back more:

"""
==> Release 0.9.9 (29 Jul 1993) <==
 ...
* New option -k raises an exception when an expression statement
yields a value other than None.
"""

Now I even recall the name of the early method-chaining user whose
complaints triggered those changes - but will let the past rest in
peace ;-)


> The only thing I'm only 90% sure of is whether the REPL always ignored None 
> values.

I'm sure of that:  it never showed None values.  Because, if it had, I
would have remembered bitching about the endless annoyance ;-)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/SHAYU47H5OKPRD7JNFEHHCGFN3UMHKQY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread David Mertz
On Sun, Jan 19, 2020 at 3:56 PM Steven D'Aprano  wrote:

> > The "fluent interface" (https://en.wikipedia.org/wiki/Fluent_interface)
> is
> > popular in many programming languages, including in the sort of
> > "mini-language" Pandas, within portion.
>
> I can't speak about Pandas, but what the OP is expecting to do is not a
> fluent interface. It's just method chaining.


I'm not sure what you intend here:

A fluent interface is normally implemented by using method chaining
 to implement method
cascading  (in languages
that do not natively support cascading), concretely by having each method
return this  (
self).

While there are other things that might make a fluent interface, method
chaining is by far the most commonly used approach.


> result = mystring.upper().strip().center(width).encode('utf-8')
>

But yes, there are places in Python where "fluency" is the normal style.  I
was careful to say "collections" and "mutate" in my prior comments.  A
string is a kinda-sorta collection, but it's definitely not mutable.


> A fluent interface is built on top of method chaining: you can't
> (easily?) have a fluent interface without chaining, but you can have
> chaining without a fluent interface. See Fowler, who came up with the
> term and ought to know what he meant by it :-)
>

I don't really see what you mean in Fowler that would allow "non-fluent"
method chaining, but I'll stipulate there's some sentence I missed or read
wrong.  Nowadays, the term is in more widespread use, and exactly what
Fowler meant in 2005 isn't really essential.

For example, I definitely think of pipes between Unix commands using the
shell as a "fluent interface" (that I like very much).  That's not method
calls, but it is absolutely *chaining*.


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/TZJCHW3IKQ4THTYGK3MJEVCOGMXPTFZW/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Andrew Barnert via Python-ideas
On Jan 19, 2020, at 12:15, David Mertz  wrote:
> 
> In contrast, in pure Python, most of that you do is in loops over the 
> elements of collections.  In that case is does a good job of drawing your eye 
> to the fact that a method is called but not assigned to anything.  When I see 
> `mylist.append(foo)` on a line by itself, the absence of an assigned variable 
> drives home "this is basically a statement, called for side-effects" (yes, I 
> know in the syntax it is an expression not a statement; but my looser 
> cognitive model works that way).

But it is an expression statement. And that works just as well without having 
to be mildly incorrect, and it extends even further from there.

Most statements in most Python code mutate one thing. Most of them explicitly 
mutate the first thing mentioned (and any expressions within them are usually 
nonmutating). Expression statements dont explicitly mutate anything, but 
usually at the top level they’re usually either a method call that mutates its 
self, or a function call that mutates something implicit in the function, and 
subexpressions are usually nonmutating. So, most statements in most Python code 
mutate the first thing:

# the only mutation is (probably) to spam:
spam = eggs(cheese)
spam += eggs
spam[eggs] = cheese
spam.eggs(cheese)

# the only mutation is (probably) to the stdout implicit in print:
print(spam)
print(spam.eggs(cheese))
print(spam(eggs))

There are of course exceptions. A from … import statement creates the names at 
the end of the statement rather than the start. Mutating methods are only 
encouraged to return None, not required. And so on. But the rough guideline 
works well enough for skimming most Python code to see “where does x get 
changed” in a way that doesn’t work for languages that encourage fluent 
mutating style, like JS or Ruby or C++.

What about the walrus operator? The fact that it clearly breaks this is, I 
think, a big part of the reason that so many people were against it. But the 
fact that it’s usually used only to mutate something that’s only relevant 
within the statement is a big part of the reason people actually like it once 
they see real examples.

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/2QVSANBME72UBSPOXVAQDIYIXDI6BHXR/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Steven D'Aprano
On Sun, Jan 19, 2020 at 02:37:14PM -0500, David Mertz wrote:
> The "fluent interface" (https://en.wikipedia.org/wiki/Fluent_interface) is
> popular in many programming languages, including in the sort of
> "mini-language" Pandas, within portion.

I can't speak about Pandas, but what the OP is expecting to do is not a 
fluent interface. It's just method chaining. We do method chaining all 
the time with immutable "value objects" like strings:

result = mystring.upper().strip().center(width).encode('utf-8')

and nobody blinks an eye or calls it unpythonic.

A fluent interface is built on top of method chaining: you can't 
(easily?) have a fluent interface without chaining, but you can have 
chaining without a fluent interface. See Fowler, who came up with the 
term and ought to know what he meant by it :-)

https://www.martinfowler.com/bliki/FluentInterface.html

In other words: merely returning "self" from your mutating methods does 
not make a fluent interface.


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/BTFBHHUX2JATQOWKK2ALO7ATCIQSKB2H/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Steven D'Aprano
On Sun, Jan 19, 2020 at 08:32:43AM -0800, Guido van Rossum wrote:
> I'm not excited about suggesting the walrus operator when people want to
> chain mutating method calls like this. It results in ugly code with way too
> many parentheses and a distinctly un-Pythonic flavor. I hope the OP doesn't
> go off and infect a whole subcommunity with this idiom.

It is worse than that: it doesn't even solve the OP's problem of wanting 
to chain method calls.

py> (xs := list(range(10))).append(42)  # seems to work
py> xs
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42]
py> (xs := list(range(10))).append(42).append(999)
Traceback (most recent call last):
File "", line 1, in 
AttributeError: 'NoneType' object has no attribute 'append'


-- 
Steven
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/WVRCOQL27PEL7HXWCECR56ML6O24SBRP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Guido van Rossum
Sounds like a hallucination or fabrication. The behavior of `for i in
range(10): i` in the REPL exists to this day, and list.append() never
returned a value.
The only thing I'm only 90% sure of is whether the REPL always ignored None
values.


On Sun, Jan 19, 2020 at 11:58 AM Tim Peters  wrote:

> [David Mertz ]
> > ...
> > What we get instead is a clear divide between mutating methods
> > on collections that (almost)  always return None, and functions
> > like sorted() and reversed() that return copies of the underlying
> > collection/iterable. Of course, there are many methods that don't
> > have functions matching them. Python could have been designed
> > differently, but using the consistency it follows is best.
>
> For a bit of history that I may have made up (heh - memory fades over
> time!), as I recall, the very first Python pre-releases echoed to
> stdout every non-None statement result.  So, e.g.,
>
> for i in range(5):
> i
>
> displayed the same as the current
>
> for i in range(5):
> print(i)
>
> But one prolific early user loved chaining mutating method calls, each
> returning `self`, and so their output was littered with crap they
> didn't want to see.  They didn't want to prefix every computational
> statement with, e.g., "ignore = ", so Guido stopped the magical
> output.
>
> Perhaps surprisingly, few people noticed the difference.  But that may
> in large part be due to that there were few people, period.
>
> Or I'm just hallucinating again :-)
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/WOKUBTEZEXCX5HE4TKJ5GG73ILVO6LMK/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/44PYQUNSPIWVWORFTSVX4EO3QBWI7NN6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Tim Peters
[David Mertz ]
> ...
> What we get instead is a clear divide between mutating methods
> on collections that (almost)  always return None, and functions
> like sorted() and reversed() that return copies of the underlying
> collection/iterable. Of course, there are many methods that don't
> have functions matching them. Python could have been designed
> differently, but using the consistency it follows is best.

For a bit of history that I may have made up (heh - memory fades over
time!), as I recall, the very first Python pre-releases echoed to
stdout every non-None statement result.  So, e.g.,

for i in range(5):
i

displayed the same as the current

for i in range(5):
print(i)

But one prolific early user loved chaining mutating method calls, each
returning `self`, and so their output was littered with crap they
didn't want to see.  They didn't want to prefix every computational
statement with, e.g., "ignore = ", so Guido stopped the magical
output.

Perhaps surprisingly, few people noticed the difference.  But that may
in large part be due to that there were few people, period.

Or I'm just hallucinating again :-)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/WOKUBTEZEXCX5HE4TKJ5GG73ILVO6LMK/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread David Mertz
The "fluent interface" (https://en.wikipedia.org/wiki/Fluent_interface) is
popular in many programming languages, including in the sort of
"mini-language" Pandas, within portion.

But it is definitely not Pythonic. The Wikipedia article even shows how you
*could* do it in Python, but mentions that Guido discourages it.

What we get instead is a clear divide between mutating methods on
collections that (almost)  always return None, and functions like sorted()
and reversed() that return copies of the underlying collection/iterable. Of
course, there are many methods that don't have functions matching them.
Python could have been designed differently, but using the consistency it
follows is best.

On Sun, Jan 19, 2020, 1:17 PM Siddharth Prajosh  wrote:

>
>
> On Sun, Jan 19, 2020 at 10:03 PM Guido van Rossum 
> wrote:
>
>> I'm not excited about suggesting the walrus operator when people want to
>> chain mutating method calls like this. It results in ugly code with way too
>> many parentheses and a distinctly un-Pythonic flavor. I hope the OP doesn't
>> go off and infect a whole subcommunity with this idiom.
>>
>
> Not a huge fan the walrus operator, yet. I don't think I'll use it unless
> necessary.
>
> I'll stick to a = list() and then a.append() in this case
>
>
>> On Sat, Jan 18, 2020 at 10:05 PM Inada Naoki 
>> wrote:
>>
>>> On Sun, Jan 19, 2020 at 2:45 PM Siddharth Prajosh 
>>> wrote:
>>> >
>>> > Moreover, shouldn't it work?
>>> > How do I add that feature in Python?
>>>
>>> How you can do it with warus operator.
>>>
>>> >>> (xs := list(range(10))).append(42)
>>> >>> xs
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42]
>>>
>>> Regards,
>>>
>>> --
>>> Inada Naoki  
>>> ___
>>> Python-ideas mailing list -- python-ideas@python.org
>>> To unsubscribe send an email to python-ideas-le...@python.org
>>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>>> Message archived at
>>> https://mail.python.org/archives/list/python-ideas@python.org/message/24YMTGYKCNFHS2JROYSNSP6MUPZAFUCV/
>>> Code of Conduct: http://python.org/psf/codeofconduct/
>>>
>>
>>
>> --
>> --Guido van Rossum (python.org/~guido)
>> *Pronouns: he/him **(why is my pronoun here?)*
>> 
>>
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/HEG7CAAG7KMFO2G6I4SOCG4QS7ZJTST2/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/42EZZ3Q7SF7N2GW3W3LBCHXNYWM5TQT2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Siddharth Prajosh
On Sun, Jan 19, 2020 at 10:03 PM Guido van Rossum  wrote:

> I'm not excited about suggesting the walrus operator when people want to
> chain mutating method calls like this. It results in ugly code with way too
> many parentheses and a distinctly un-Pythonic flavor. I hope the OP doesn't
> go off and infect a whole subcommunity with this idiom.
>

Not a huge fan the walrus operator, yet. I don't think I'll use it unless
necessary.

I'll stick to a = list() and then a.append() in this case


> On Sat, Jan 18, 2020 at 10:05 PM Inada Naoki 
> wrote:
>
>> On Sun, Jan 19, 2020 at 2:45 PM Siddharth Prajosh 
>> wrote:
>> >
>> > Moreover, shouldn't it work?
>> > How do I add that feature in Python?
>>
>> How you can do it with warus operator.
>>
>> >>> (xs := list(range(10))).append(42)
>> >>> xs
>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42]
>>
>> Regards,
>>
>> --
>> Inada Naoki  
>> ___
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/24YMTGYKCNFHS2JROYSNSP6MUPZAFUCV/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
>
> --
> --Guido van Rossum (python.org/~guido)
> *Pronouns: he/him **(why is my pronoun here?)*
> 
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/HEG7CAAG7KMFO2G6I4SOCG4QS7ZJTST2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Guido van Rossum
I'm not excited about suggesting the walrus operator when people want to
chain mutating method calls like this. It results in ugly code with way too
many parentheses and a distinctly un-Pythonic flavor. I hope the OP doesn't
go off and infect a whole subcommunity with this idiom.

On Sat, Jan 18, 2020 at 10:05 PM Inada Naoki  wrote:

> On Sun, Jan 19, 2020 at 2:45 PM Siddharth Prajosh 
> wrote:
> >
> > Moreover, shouldn't it work?
> > How do I add that feature in Python?
>
> How you can do it with warus operator.
>
> >>> (xs := list(range(10))).append(42)
> >>> xs
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42]
>
> Regards,
>
> --
> Inada Naoki  
> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/24YMTGYKCNFHS2JROYSNSP6MUPZAFUCV/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--Guido van Rossum (python.org/~guido)
*Pronouns: he/him **(why is my pronoun here?)*

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/EE2JUYAEWY5HOQGG564VVUEEXBCZXE5F/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-19 Thread Siddharth Prajosh
On Sun, 19 Jan, 2020, 11:35 Inada Naoki,  wrote:

> On Sun, Jan 19, 2020 at 2:45 PM Siddharth Prajosh 
> wrote:
> >
> > Moreover, shouldn't it work?
> > How do I add that feature in Python?
>
> How you can do it with warus operator.
>
> >>> (xs := list(range(10))).append(42)
> >>> xs
> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42]
>

Great. This should do the trick! Thanks :-)

>
> Regards,
>
> --
> Inada Naoki  
>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/S5YBMGF3PN3GPZFSSGTGIXNQ5UH5KBFG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-18 Thread Inada Naoki
On Sun, Jan 19, 2020 at 2:45 PM Siddharth Prajosh  wrote:
>
> Moreover, shouldn't it work?
> How do I add that feature in Python?

How you can do it with warus operator.

>>> (xs := list(range(10))).append(42)
>>> xs
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 42]

Regards,

-- 
Inada Naoki  
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/24YMTGYKCNFHS2JROYSNSP6MUPZAFUCV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: List - append

2020-01-18 Thread Tim Peters
[M Siddharth Prajosh ]
> This is more of a doubt than a new idea. Python has always worked
> intuitively but this was a bummer.
>
> A list has an append method. So I can do list.append(value).
> I tried doing list(range(10)).append(10) and it returns None.

Yes.  Most methods that mutate an object return None.

> I'd usually assume list(range(10)) returns a list,

It does.

> to which I can append whatever I want.

And you can.

> I tried this with List comprehension also. Doesn't work there either.
> Why doesn't this work?

It does work :-)  list(range(10)) created an anonymous list, then
.append(10) appended 10 to that anonymous list, and list.append
_always_ returns None.  Since the list wasn't bound to any name, it
became trash (unreachable garbage) as soon as the .append() ended, so
the list was thrown away.

Give it a name for clarity:

>>> xs = list(range(10))
>>> print(xs.append(10))  # demonstrating that it does return None
None
>>> xs  # and the append worked fine
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]


> Moreover, shouldn't it work?
> How do I add that feature in Python?

Better instead to learn how Python works here - it's not broken :-)
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/FSTS5AIWZN4OIXOBKQGORTM2ZI3FTBNV/
Code of Conduct: http://python.org/psf/codeofconduct/