Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Dan Sommers
On Wed, 02 May 2018 05:08:41 +1000, Steven D'Aprano wrote:

> The difference was that when Windows users used the mouse, even though
> they were *objectively* faster to complete the task compared to using
> the arrow keys, subjectively they swore that they were slower, and
> were *very confident* about their subjective experience.

Another driving analogy:  when I get stuck at a stoplight, sometimes I
take advantage of turn on red or a protected turn, even though I know
that it's going to take longer to get where I'm going.  But I feel
better because I'm not just sitting there at the stoplight.  Call it
cognitive dissonance, I guess.

Some of my coworkers claim that using vi is objectively faster or
requires fewer keystrokes than using emacs.  I counter that I've been
using emacs since before they were born, and that I now do so with the
reptilian part of my brain, which means that I can keep thinking about
the problem at hand rather than about editing the source code.

Who remembers the One True Brace Style holy wars?  If we agreed on
anything, it was to conform to existing code rather than to write new
code in a different style.  Reading a mixture of styles was harder, no
matter which particular style you thought was better or why you thought
it was better.

> Athletes are not great judges of what training works for themselves.

Wax on, wax off?  ;-)

Dan

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Tim Peters
[MRAB]
>>> Would/should it be possible to inject a name into a local scope? You can't
>>> inject into a function scope, and names in a function scope can be
>>> determined statically (they are allocated slots), so could the same kind of
>>> thing be done for names in a local scope?

...

[Steven D'Aprano ]
> I don't know what MRAB means by "inject", but I know what *I* mean, and
> I have a real use-case for it.
>
> There is a long-running micro-optimization, often championed by Raymond,
> for avoiding slow global lookups (and even slower builtin lookups, since
> they require a global lookup to fail first) by turning them in local
> lookups at function-definition time.

Before nested scopes, it was also used to help nested functions call
each other; e.g.,

def f():
def g():
   ...

 # h needs to call g, but can't see f's locals
 def h(g=g):  # but default arg expressions can see f's locals
 g()  # works great :-)


> E.g. some methods from the random.Random class:
>
> def randrange(self, start, stop=None, step=1, _int=int):
> ...
> def _randbelow(self, n, int=int, maxsize=1<Method=_MethodType, BuiltinMethod=_BuiltinMethodType):
> ...
>
> (copied from 3.5, I don't know what the most recent version looks like)

Doesn't matter; code like that has been in the std lib since the
start, although Raymond is inordinately fond of it ;-)


> That's a nice way to make the binding:
>
> _int = int
>
> occur once only, instead of putting it inside the function body which
> then needs to be executed on ever call. Effectively it's a static
> variable for the method, one which persists from one call to the next
> without requiring re-initialisation.
>
> But it's ugly :-(

Error-prone too, because absolutely nothing stops a user from calling
these things with more positional arguments than are intended.  I
don't want to bother looking now, but there was _some_ "bug report"
complaining that one of these "default arguments" went away somewhere,
which a user was specifying intentionally to override some accidental
implementation detail.

However, while it's dead obviously "error prone" in theory, it's
remarkable how few times I've heard of anyone getting burned by it in
practice.


> The function signature is full of *implementation details* instead of
> the parameters needed for the method's interface. Look at _randbelow
> which takes one actual parameter, n, plus FIVE fake parameters, int,
> maxsize, type, Method and BuiltinMethod, none of which should ever be
> passed arguments.
>
> So when I talk about injecting values into a function, that is the sort
> of thing I'm referring to: at function definition time, push or inject a
> reference to a known value (say, the builtin int) into something which
> behaves as a static variable.
>
> It would be nice if we could do that without polluting the function
> signature.

I'm surprised that hasn't already been done.


> I'll admit that the name "inject" came to me when I was
> thinking of some hypothetical decorator:
>
> @inject(int=int, maxsize=1< def _randbelow(self, n):
> ...
>
> that somehow pushed, or *injected*, those bindings into the function,
> turning them into locals, but in an alternative universe where Guido
> loved making new keywords, I'd use a static initialisation block and
> stick it inside the def:
>
> def _randbelow(self, n):
> static:
> # this gets executed once only, at function definition time
> int=int
> maxsize=1< type=type
> # body of _randbelow

Blame computer scientists.  I started my paying career working on Cray
Research's Fortran compiler, a language in which NO words were
reserved.  The syntax was such that it was always possible to
determine whether a language keyword or a user-supplied name was
intended.  That worked out great.

But it seemed to require ad hoc parsing tricks.  Computer scientists
invented "general" parser generators, and then every new language
started declaring that some words were reserved for the language's
use.  That was just to make things easier for parser-generator
authors, not for users ;-)

Maybe we could steal a trick from the way the async statements ("async
def", "async for", "async with") were added without making "async" a
reserved word?  Even if user code already uses the name "static", just
as in Fortran the only way to parse

static:

that makes sense is that it's introducing a block;

USER_NAME:

as a statement has no meaning.  In any other context, the
block-opening meaning of "static" makes no sense, so it must mean a
user-defined name then.  We could also add, e.g.,

MRAB local a, b, c:

and

 Uncle Timmy not really local at all a, b, c:

without introducing any actual ambiguity in code already using any of
the leading words on those lines.

It would be fun to 

Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Mikhail V
On Wed, May 2, 2018 at 4:03 AM, Matt Arcidy  wrote:
> On Tue, May 1, 2018 at 5:35 PM, Mikhail V  wrote:
>
>> to be pedantic - ReallyLongDescriptiveIdentifierNames
>> has also an issue with "I" which might confuse because it
>> looks same as little L. Just to illustrate that choice of
>> comparison samples is very sensitive thing.
>> In such a way an experienced guy can even scam
>> the experimental subjects by making samples which
>> will show what he wants in result.
>
> I love this discussion, but I think anything that isn't included in a
> .py file would have to be outside the scope, at least of the alpha
> version :).  I am really interested in these factors in general,
> however.  Now I'm surprised no one asks which font each other are
> using when determining readability.
>
> "serif?  are you mad?  no wonder!"
> "+1 on PEP conditional on mandatory yellow (#FFEF00) keyword syntax
> highlighting in vim"
>

Well, I am asking.
Looking at online PEPs I am under impression everyone
should use huge-sized Consolas and no syntax highlighting at all.

Just as with "=" and "==". Making samples without highlighting
will show a similarity issue. Making it with different
highlighting/font style will show
that there is no issue.

Or, ":=" looks ok with Times New Roman, but with Consolas -
it looks like Dr. Zoidberg's face.



Mikhail
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread CFK
Matt, you took the words right out of my mouth!  The fonts that are being
used will have a big difference in readability, as will font size,
foreground and background coloring, etc.  It would be interesting to see if
anyone has done a serious study of this type though, especially if they
studied it over the course of several hours (I'm getting older, and I've
noticed that after about 8-10 hours of coding it doesn't matter what I'm
looking at, I can't focus enough to read it, but I don't know when I start
to degrade, nor do I know if different fonts would help me degrade more
slowly)

Thanks,
Cem Karan


On Tue, May 1, 2018 at 9:03 PM, Matt Arcidy  wrote:

> On Tue, May 1, 2018 at 5:35 PM, Mikhail V  wrote:
>
> > to be pedantic - ReallyLongDescriptiveIdentifierNames
> > has also an issue with "I" which might confuse because it
> > looks same as little L. Just to illustrate that choice of
> > comparison samples is very sensitive thing.
> > In such a way an experienced guy can even scam
> > the experimental subjects by making samples which
> > will show what he wants in result.
>
> I love this discussion, but I think anything that isn't included in a
> .py file would have to be outside the scope, at least of the alpha
> version :).  I am really interested in these factors in general,
> however.  Now I'm surprised no one asks which font each other are
> using when determining readability.
>
> "serif?  are you mad?  no wonder!"
> "+1 on PEP conditional on mandatory yellow (#FFEF00) keyword syntax
> highlighting in vim"
>
> -Matt
>
> >
> >
> > Mikhail
> > ___
> > Python-ideas mailing list
> > Python-ideas@python.org
> > https://mail.python.org/mailman/listinfo/python-ideas
> > Code of Conduct: http://python.org/psf/codeofconduct/
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Matt Arcidy
On Tue, May 1, 2018 at 5:35 PM, Mikhail V  wrote:

> to be pedantic - ReallyLongDescriptiveIdentifierNames
> has also an issue with "I" which might confuse because it
> looks same as little L. Just to illustrate that choice of
> comparison samples is very sensitive thing.
> In such a way an experienced guy can even scam
> the experimental subjects by making samples which
> will show what he wants in result.

I love this discussion, but I think anything that isn't included in a
.py file would have to be outside the scope, at least of the alpha
version :).  I am really interested in these factors in general,
however.  Now I'm surprised no one asks which font each other are
using when determining readability.

"serif?  are you mad?  no wonder!"
"+1 on PEP conditional on mandatory yellow (#FFEF00) keyword syntax
highlighting in vim"

-Matt

>
>
> Mikhail
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Mikhail V
On Tue, May 1, 2018 at 6:04 PM, Jacco van Dorp  wrote:
> 2018-05-01 14:54 GMT+02:00 Greg Ewing :
>> Rhodri James wrote:
>>>
>>> I'd be interested to know if there is a readability difference between
>>> really_long_descriptive_identifier_name and
>>> ReallyLongDescriptiveIdentifierNames.
>>
>>
>> As one data point on that, jerking my eyes quickly across
>> that line I found it much easier to pick out the component
>> words in the one with underscores.
>>
>> --
>> Greg
>
>
> Which is funny, because I had the exact opposite.
>
> Might it be that we've had different conditioning ?
>
> Jacco

The one with underscores reads fairly better though.
Might it be that it does read better?
Ok, that's not scientific enough. But the scores 2:1 so far ;-)

to be pedantic - ReallyLongDescriptiveIdentifierNames
has also an issue with "I" which might confuse because it
looks same as little L. Just to illustrate that choice of
comparison samples is very sensitive thing.
In such a way an experienced guy can even scam
the experimental subjects by making samples which
will show what he wants in result.


Mikhail
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Tim Peters
[MRAB]
>>> Imagine renaming the specified names that are declared 'local'
>>> throughout the nested portion:
>>>
>>> def f():
>>> a = 10
>>> local local_a:
>>> def showa():
>>> print("a is", local_a)
>>> showa() # Raises NameError in showa because nothing bound to
>>> local_a yet.
>>> local_a = 20
>>> showa() # 20
>>> local_a = 30
>>> showa() # Raises NameError in f because local_a not defined.

[Tim]
>> In a later message I showed executable-today Python code that I
>> believe models your intent.  That code does indeed display "30" for
>> the last call, and while I myself don't see that it's _useful_ yet,
>> the model is incomprehensible if it doesn't.
>>
>> It doesn't matter that local_a isn't defined at function scope,
>> because showa() refers to the locals _in_ the "local a:" scope.  The
>> last value bound to local_a was 30, so that's what showa() needs to
>> show.  That the name `showa` is _bound_ in f's locals has nothing to
>> do with whose locals showa() _uses_.  Other current messages about
>> "closures" go on more about that.

[MRAB]
> Ah, yes. I see what you mean.
>
> There's another question that hasn't been asked yet: what should locals()
> and globals() return?

Under my meaning, the same answer as always:  exactly the same as if
"local a:' were replaced by "if True:" ;-)

Under yours, you're not going to like the answer.  It seems obvious
that since globals() refers to the module dict, nothing about that
would change.  You can add prints to my
workalike-code-under-current-Python snippet to see what locals()
_does_ return in various places.

It's not what you'd expect (that locals() inside the `local a:` block
is a dict with only key "local_a"), because of what I believe are
undocumented implementation details.  This is much easier to see in a
bare-bones example:

def f():
b = 12
def g():
nonlocal b
b = 17
a = 42
print("inner", locals())
g()
print("outer", locals())
f()

The output:

inner {'a': 42, 'b': 17}
outer {'g': .g at 0x024E28C44AE8>, 'b': 17}

That is, despite that `b` is explicitly declared as `nonlocal` in the
inner function, and does in fact belong to the outer scope, it
nevertheless shows up inside the inner function's locals().

The compiler isn't confused, but `locals()` existed long before nested
scopes were added, and, e.g., no "nonlocals()` builtin was added
later.  PEP 227 (which introduced nested scopes) explicitly declined
to add one, and said "it will not be possible to gain dictionary-style
access to all visible scopes".  I was quite surprised to see "b" as a
key in the inner locals() above!

But so long as it is, any new gimmick building on the current
implementation would inherit that behavior.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread MRAB

On 2018-05-01 19:12, Tim Peters wrote:

[MRAB]
> Imagine renaming the specified names that are declared 'local' throughout
> the nested portion:
>
> def f():
> a = 10
> local local_a:
> def showa():
> print("a is", local_a)
> showa() # Raises NameError in showa because nothing bound to local_a 
yet.
> local_a = 20
> showa() # 20
> local_a = 30
> showa() # Raises NameError in f because local_a not defined.

In a later message I showed executable-today Python code that I
believe models your intent.  That code does indeed display "30" for
the last call, and while I myself don't see that it's _useful_ yet,
the model is incomprehensible if it doesn't.

It doesn't matter that local_a isn't defined at function scope,
because showa() refers to the locals _in_ the "local a:" scope.  The
last value bound to local_a was 30, so that's what showa() needs to
show.  That the name `showa` is _bound_ in f's locals has nothing to
do with whose locals showa() _uses_.  Other current messages about
"closures" go on more about that.


Ah, yes. I see what you mean.

There's another question that hasn't been asked yet: what should 
locals() and globals() return?

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Mikhail V
On Tue, May 1, 2018 at 3:42 AM, Steven D'Aprano  wrote:
> On Mon, Apr 30, 2018 at 11:28:17AM -0700, Matt Arcidy wrote:
>
> - people are not good judges of readability;

People are the only judges of readability.
Just need the right people.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Steven D'Aprano
On Tue, May 01, 2018 at 03:02:27PM +, Dan Sommers wrote:

> >> I happen to be an excellent judge of whether a given block of code is
> >> readable to me.
> 
> > In the same way that 93% of people say that they are an above-average
> > driver, I'm sure that most people think that they are an excellent
> > judge of readability. Including myself in *both* of those.
> 
> Are you claiming that I'm not an excellent judge of whether a given
> block of code is readable to me?

Of course not. I don't know you. I wouldn't dream of making *specific* 
claims about you. I speak only in broad generalities which apply to 
people in general.

I'm reminded that in the 1990s during the UI wars between Apple and 
Microsoft, people had *really strong* opinions about the useability of 
the two OSes' GUIs. Macs required the user to use the mouse to navigate 
menus, while Windows also allowed the use to navigate them using the Alt 
key and arrow keys.

Not surprisingly, *both* Mac users and Windows users were absolutely 
convinced that they were much more efficient using the method they were 
familiar with, and could justify their judgement. For example, Windows 
users typically said that having to move their hand from the keyboard to 
grab the mouse was slow and inefficient, and using the Alt key and 
arrows was much faster.

But when researchers observed users in action, and timed how long it 
took them to perform simple tasks requiring navigating the menus, they 
found that using the mouse was significantly faster for *both* groups of 
users, both Windows and Mac users.

The difference was that when Windows users used the mouse, even though 
they were *objectively* faster to complete the task compared to using 
the arrow keys, subjectively they swore that they were slower, and were 
*very confident* about their subjective experience.

This is a good example of the overconfidence effect:

https://en.wikipedia.org/wiki/Overconfidence_effect

This shouldn't be read as a tale about Mac users being superior. One of 
the two methods had to be faster, and it happened to be Macs. My point 
is not about Macs versus Windows, but that people in general are not 
good at this sort of self-reflection.

Another example of this is the way that the best professional athletes 
no longer rely on their own self-judgement about the best training 
methods to use, because the training techniques that athletes think are 
effective, and those which actually are effective, are not strongly 
correlated.

Athletes are not great judges of what training works for themselves.

The psychological processes that lead to these cognitive biases apply to 
us all, to some degree or another.

Aside from you and me, of course.



-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Should __builtins__ have some kind of pass-through print function, for debugging?

2018-05-01 Thread Pradyun Gedam
On Fri, Apr 27, 2018 at 6:24 PM Nick Coghlan  wrote:

> On 27 April 2018 at 21:27, Steven D'Aprano  wrote:
>
>> Obviously dp() would have to be magic. There's no way that I know of for
>> a Python function to see the source code of its own arguments. I have no
>> idea what sort of deep voodoo would be required to make this work. But
>> if it could work, wow, that would really be useful. And not just for
>> beginners.
>>
>
> If you relax the enhancement to just noting the line where the debug print
> came from, it doesn't need to be deep compiler magic - the same kind of
> stack introspection that warnings and tracebacks use would suffice. (Stack
> introspection to find the caller's module, filename and line number,
> linecache to actually retrieve the line if we want to print that).
>

I​ spent a bit of time and now there's a dprint 
project on PyPI. It uses stack introspection to print out some details. If
someone wants to take it for a spin and provide feedback on how it feels,
this thread is as good a place as any, I suppose. :)

Cheers,
Pradyun


> Cheers,
> Nick.
>
> P.S. While super() is a *little* magic, it isn't *that* magic - it gets
> converted from "super()" to "super(name_of_first_param, __class__)". And
> even that limited bit of magic has proven quirky enough to be a recurring
> source of irritation when it comes to interpreter maintenance.
>
> --
> Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
--

Pradyun
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Nathaniel Smith
On Tue, May 1, 2018, 02:55 Matt Arcidy  wrote:

>
> I am not inferring causality when creating a measure.


No, but when you assume that you can use that measure to *make* code more
readable, then you're assuming causality.

Measuring the
> temperature of a steak doesn't infer why people like it medium rare.
> It just quantifies it.
>

Imagine aliens who have no idea how cooking works decide to do a study of
steak rareness. They go to lots of restaurants, order steak, ask people to
judge how rare it was, and then look for features that could predict these
judgements.

They publish a paper with an interesting finding: it turns out that
restaurant decor is highly correlated with steak rareness. Places with
expensive leather seats and chandeliers tend to serve steak rare, while
cheap diners with sticky table tops tend to serve it well done.

(I haven't done this study, but I bet if you did then you would find this
correlation is actually true in real life!)

Now, should we conclude based on this that if we want to get rare steak,
the key is to *redecorate the dining room*? Of course not, because we
happen to know that the key thing that changes the rareness of steak is how
it's exposed to heat.

But for code readability, we don't have this background knowledge; we're
like the aliens. Maybe the readability metric in this study is like
quantifying temperature; maybe it's like quantifying how expensive the
decor is. We don't know.

(This stuff is extremely non-obvious; that's why we force
scientists-in-training to take graduate courses on statistics and
experimental design, and it still doesn't always take.)


> > And yeah, it doesn't help that they're only looking at 3 line blocks
> > of code and asking random students to judge readability – hard to say
> > how that generalizes to real code being read by working developers.
>
> Respectfully, this is practical application and not a PhD defense,  so
> it will be generated by practical coding.
>

Well, that's the problem. In a PhD defense, you can get away with this kind
of stuff; but in a practical application it has to actually work :-). And
generalizability is a huge issue.

People without statistical training tend to look at studies and worry about
how big the sample size is, but that's usually not the biggest concern; we
have ways to quantify how big your sample needs to be. There bigger problem
is whether your sample is *representative*. If you're trying to guess who
will become governor of California, then if you had some way to pick voters
totally uniformly at random, you'd only need to ask 50 or 100 of them how
they're voting to get an actually pretty good idea of what all the millions
of real votes will do. But if you only talk to Republicans, it doesn't
matter how many you talk to, you'll get a totally useless answer. Same if
you only talk to people of the same age, or who all live in the same town,
or who all have land-line phones, or... This is what makes political
polling difficult, is getting a representative sample.

Similarly, if we only look at out-of-context Java read by students, that
may or may not "vote the same way" as in-context Python read by the average
user. Science is hard :-(.

-n

>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Tim Peters
[MRAB]
> By "inject" I mean putting a name into a namespace:
>
> import my_module
> my_module.foo = 'FOO'
>
> You can't insert a name into a function's body to make a new local variable.

So you do mean at runtime, I think.  Then as before, you can do that
with module and the builtin namespaces now, but all function locals
need to be identifiable at compile time now.  People often get
confused about that when they read that "it's a binding" that makes a
name local to a scope, but it's not "_doing_ a binding" that makes it
local, merely that the name _syntactically_ appears as a target in a
binding construct.  That analysis is entirely done at compile time.

In Python's very early days, all namespaces could be dynamically
altered at any time in any way.  As time went on, more & more
restrictions were placed on runtime alteration of local scopes.  I
don't believe that, in current Python 3, dynamic alteration of local
scopes is supported in any case anymore.  Perhaps the last to go was
runtime alteration of locals via `exec`.  This still works in Python
2:

>>> def f():
... exec 'i = 1+2'
... print i
>>> f()
3
>>> i  # showing that it was function-local `i`, not global
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'i' is not defined

`exec` was a statement type in Python 2, so the compiler could
recognize that and generate radically different name-lookup code in a
scope containing an `exec` statement.  But in Python 3, `exec` is just
another builtin function, and the compiler knows nothing about what it
does.  Similar code run in Python 3 has no effect on f's locals.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread MRAB

On 2018-05-01 16:23, Steven D'Aprano wrote:

On Mon, Apr 30, 2018 at 08:52:13PM -0500, Tim Peters wrote:


> Would/should it be possible to inject a name into a local scope? You can't
> inject into a function scope, and names in a function scope can be
> determined statically (they are allocated slots), so could the same kind of
> thing be done for names in a local scope?

Sorry, I'm unclear on what "inject a name into a local scope" means.
Do you mean at runtime?


I don't know what MRAB means by "inject", but I know what *I* mean, and
I have a real use-case for it.


By "inject" I mean putting a name into a namespace:

import my_module
my_module.foo = 'FOO'

You can't insert a name into a function's body to make a new local variable.

[snip]
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Steven D'Aprano
On Tue, May 01, 2018 at 09:26:09PM +1200, Greg Ewing wrote:
> Steven D'Aprano wrote:
> >So what was the closure? If the surrounding function was still running, 
> >there was no need to capture the running environment in a closure?
> 
> You seem to be interpreting the word "closure" a bit
> differently from most people. It doesn't imply anything
> about whether a surrounding function is still running or
> not.
> 
> A closure is just a piece of code together with a runtime
> environment.

That's not *all* it is, because obviously *every* function has both a 
piece of code and a runtime environment.

y = 1
def func():
x = 2
return x+y

Here, there's a local environment as well as an implicit global one. 
Surely we don't want to call this a closure? If we do, then all 
functions are closures and the term is just a synonym for function.

Wikipedia gives a definition:

a closure (also lexical closure or function closure) is a 
technique for implementing lexically scoped name binding
in a language with first-class functions. Operationally,
a closure is a record storing a function together with an
environment.

https://en.wikipedia.org/wiki/Closure_%28computer_programming%29

but also warns 

As different languages do not always have a common definition
of the lexical environment, their definitions of closure may
vary also

and explicitly says that Pascal (at least standard Pascal) didn't do 
closures:

Traditional imperative languages such as Algol, C and Pascal
either do not support nested functions (C) or do not support
calling nested functions after the enclosing function has
exited (GNU C, Pascal), thus avoiding the need to use closures.


Neal Gafter gives what I believe is *the* standard definition of 
closures, at least in academic and functional programming circles, 
probably taken from Guy Steele and Scheme:

A closure is a function that captures the bindings of free
variables in its lexical context.

http://gafter.blogspot.com.au/2007/01/definition-of-closures.html

Since Steele basically wrote the book on closures, I think we ought to 
take his definition seriously :-)

(That's also the definition I was thinking of.)

By this definition, if there are no free variables, or no captured 
bindings, then its not a closure. func() above isn't a closure, since 
"x" isn't a free variable, and while "y" is, the value of it isn't 
captured.

Unfortunately, the terminology has become a real mess, especially since 
the technique has moved into languages like Ruby and Javascript. Martin 
Fowler declares that closures, lambdas and blocks are the same thing:

https://martinfowler.com/bliki/Lambda.html

although he does admit that technically you can have lambdas that aren't 
closures. I think Fowler is abusing the terminology since all three of 
his terms are orthogonal:

- closures can be created with def or lambda and are not 
  necessarily anonymous;

- lambda comes from the lambda calculus, where it refers to 
  anonymous function expressions, not specifically whether
  they capture the value of free variables in their environment;

- "block" typically refers to the structure of the source code; 
  in Ruby it also refers to a kind of first-class anonymous
  callable object. Such blocks may, or may not, contain free
  variables.


At least I don't use this definition of closure:

"a closure is a callback that Just Works."

https://reprog.wordpress.com/2010/02/27/closures-finally-explained/

*wink*



> In typical Pascal implementations, a closure
> is represented by a (code_address, frame_pointer) pair,
> where the frame_pointer points to a chain of lexically
> enclosing stack frames. The language rules make it possible
> to manage the frames strictly stack-wise, which simplifies
> the memory management, but that doesn't make the closure
> any less of a closure.

Well... it's a pretty feeble closure, since Pascal doesn't support 
functions as first-class values. More like second-class.

The c2 wiki describes Pascal:

However, when a function is passed to another function
and later called, it will execute in the lexical context
it was defined in, so it is, IN SOME SENSE [emphasis
added], "closed over" that context.

http://wiki.c2.com/?LexicalClosure

but I think that sense is the same sense that func() above is "closed 
over" the free value y. The loosest possible sense.

If we accept that "Pascal has closures", they're pretty crap closures, 
since they don't let you do any of the interesting and useful things you 
can do in languages with "real" closures like Scheme and Python.

And because it is based on an implementation detail (as you say, it is 
only *typical*, not mandatory, for Pascal inner functions to be 
implemented this way), we have to consider what happens if we come 
across a Pascal implementation which *doesn't* use a (code_address, 
frame_pointer) pair. Is that no longer Pascal?

This is the interesting, and 

Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread MRAB

On 2018-05-01 04:40, Tim Peters wrote:


[MRAB]
>> Any binding that's not specified as local is bound in the parent scope:

[Tim]
> Reverse-engineering the example following, is this a fair way of
> making that more precise?
>
> Given a binding-target name N in scope S, N is bound in scope T, where
> T is the closest-containing scope (which may be S itself) for which T
> is either
>
> 1. established by a "local:" block that declares name N
>
> or
>
> 2. not established by a "local: block

Here's an example where I don't know what the consequences of "the
rules" should be:

def f():
 a = 10
 local a:
 def showa():
 print("a is", a)
 showa() # 10
 a = 20
 showa() # 20
 a = 30
 showa() # 10
The body of "showa" is lexically nested in 'local', so its name "a" is 
the local scope's "a", not the function scope's "a".


Imagine renaming the specified names that are declared 'local' 
throughout the nested portion:


def f():
    a = 10
    local local_a:
    def showa():
    print("a is", local_a)
    showa() # Raises NameError in showa because nothing bound to 
local_a yet.

    local_a = 20
    showa() # 20
    local_a = 30
    showa() # Raises NameError in f because local_a not defined.


The comments show what the output would be under the "nothing about
scope rules change" meaning.  They're all obvious (since there is is
no new scope then - it's all function-local).

But under the other meaning ...?

The twist here is that `def` is an executable statement in Python, and
is a "binding site" for the name of the function being defined.  So
despite that `showa` appears to be defined in a new nested lexical
scope, it's _actually_ bound as a function-local name.  That's bound
to be surprising to people from other languages:  "I defined it in a
nested lexical scope, but the name is still visible after that scope
ends?".

I don't know what the first `showa()` is intended to do.  Presumably
`a` is unbound at the start of the new nested scope?  So raises
NameError?  If so, comment that line out so we can make progress ;-)

It seems clear that the second `showa()` will display 20 under any reading.

But the third?  Now we're out of the `local a:` scope, but call a
function whose textual definition was inside that scope.  What does
`showa()` do now to find a's value?  f's local `a` had nothing to do
with the `a` in the nested scope, so presumably it shouldn't display
10 now.  What should it do?
Does the final state of the nested scope's locals need to preserved so
that showa() can display 30 instead?  Or ...?

Not necessarily complaining  - just fleshing out a bit my earlier
claim that a world of semantics need to be defined if anything akin to
a "real scope" is desired.



___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread MRAB

On 2018-05-01 02:52, Tim Peters wrote:

[MRAB ]
> ...
> The intention is that only the specified names are local.
>
> After all, what's the point of specifying names after the 'local' if _any_
> binding in the local scope was local?

Don't look at me ;-)  In the absence of use cases, I don't know which
problem(s) you're trying to solve.  All the use cases I've looked at
are adequately addressed by having some spelling of "local:" change
nothing at all about Python's current scope rules.  If you have uses
in mind that require more than just that, I'd need to see them.

>> ...
>> If you agree that makes the feature probably unusable, you don't get
>> off the hook by saying "no, unlike current Python scopes, binding
>> sites have nothing to do with what's local to a new lexical scope
>> introduced by 'local:'".  The same question raised in the example
>> above doesn't go away:  in which scope(s) are 'r1' and 'r2' to be
>> bound?

> Any binding that's not specified as local is bound in the parent scope:

Reverse-engineering the example following, is this a fair way of
making that more precise?

Given a binding-target name N in scope S, N is bound in scope T, where
T is the closest-containing scope (which may be S itself) for which T
is either

1. established by a "local:" block that declares name N

or

2. not established by a "local: block

By "parent scope" I meant the function or global scope, a scope that's 
not a "local:" scope. I couldn't think of a good name for it.


[snip]

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Tim Peters
[Tim]
> ...
> Here's an example where I don't know what the consequences of "the
> rules" should be:
>
> def f():
> a = 10
> local a:
> def showa():
> print("a is", a)
> showa() # 10
> a = 20
> showa() # 20
> a = 30
> showa() # 10
>
> The comments show what the output would be under the "nothing about
> scope rules change" meaning.  They're all obvious (since there is is
> no new scope then - it's all function-local).
>
> But under the other meaning ...?
>
> The twist here is that `def` is an executable statement in Python, and
> is a "binding site" for the name of the function being defined.  So
> despite that `showa` appears to be defined in a new nested lexical
> scope, it's _actually_ bound as a function-local name.  That's bound
> to be surprising to people from other languages:  "I defined it in a
> nested lexical scope, but the name is still visible after that scope
> ends?".
>
> I don't know what the first `showa()` is intended to do.  Presumably
> `a` is unbound at the start of the new nested scope?  So raises
> NameError?  If so, comment that line out so we can make progress ;-)
>
> It seems clear that the second `showa()` will display 20 under any reading.
>
> But the third?  Now we're out of the `local a:` scope, but call a
> function whose textual definition was inside that scope.  What does
> `showa()` do now to find a's value?  f's local `a` had nothing to do
> with the `a` in the nested scope, so presumably it shouldn't display
> 10 now.  What should it do?
> Does the final state of the nested scope's locals need to preserved so
> that showa() can display 30 instead?  Or ...?

Just noting that a sane way to answer such questions is to model the
intent with nested functions in current Python.  It's annoying because
you have to explicitly declare the _non_-local names instead, and also
make dummy assignments to those names to tell Python in which scope
they _should_ be bound.

So, e.g., for the above you can write this:


def f():
a = 10

# Have to give `showa` _some_ binding in its intended scope,
# else the "nonlocal showa" below is a compile-time error
showa = None
def local_a():
nonlocal showa
def showa():
print("a", a)
#showa() # raises NameError
a = 20
showa() # 20
a = 30
local_a()
del local_a

showa() # 30
print("but f's a is", a) # 10

The comments show what happens when you call `f()`, matching the
guesses in the original message.

One thing to note:  if this does model the intent, it's essentially
proof that it's implementable without intractable effort; e.g., the
machinery needed to implement funky closures already exists.

But another:  since I've never seen code anything like this before,
that casts doubt on whether the semantics are actually useful in real
life.

That's why I always ask for real use cases ;-)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A way to subscript a single integer from bytes

2018-05-01 Thread Elazar
I think this method is easy to miss, since people look at the docs for
bytes (e.g. using dir(bytes)). It might be worthwhile to either add a
`bytes.to_int(...)` method (better, IMHO), or to point to int.from_bytes on
the relevant part of the docs.

Elazar

On Tue, May 1, 2018 at 5:09 PM Ken Hilton  wrote:

> Whoops! Never seen that before. Nothing I searched up pointed me to it.
> Sorry for wasting your time!
>
> Ken;
> --
> Sincerely,
> Ken;
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Eric Fahlgren
On Tue, May 1, 2018 at 8:04 AM, Jacco van Dorp  wrote:

> 2018-05-01 14:54 GMT+02:00 Greg Ewing :
> > Rhodri James wrote:
> >>
> >> I'd be interested to know if there is a readability difference between
> >> really_long_descriptive_identifier_name and
> >> ReallyLongDescriptiveIdentifierNames.
> >
> >
> > As one data point on that, jerking my eyes quickly across
> > that line I found it much easier to pick out the component
> > words in the one with underscores.
>
> Which is funny, because I had the exact opposite.
>
> Might it be that we've had different conditioning ?


​Almost certainly.  I started using CamelCase in the mid-'80s and it seems
very natural to me, since we still use it for (as you mention) GUI packages
derived from C extension modules with that convention.  On the other hand,
I've also written a lot of snake_form identifiers in non-GUI Python, so
that seems fairly natural to me, too.​
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Steven D'Aprano
On Mon, Apr 30, 2018 at 08:52:13PM -0500, Tim Peters wrote:

> > Would/should it be possible to inject a name into a local scope? You can't
> > inject into a function scope, and names in a function scope can be
> > determined statically (they are allocated slots), so could the same kind of
> > thing be done for names in a local scope?
> 
> Sorry, I'm unclear on what "inject a name into a local scope" means.
> Do you mean at runtime?

I don't know what MRAB means by "inject", but I know what *I* mean, and 
I have a real use-case for it.

There is a long-running micro-optimization, often championed by Raymond, 
for avoiding slow global lookups (and even slower builtin lookups, since 
they require a global lookup to fail first) by turning them in local 
lookups at function-definition time. E.g. some methods from the 
random.Random class:

def randrange(self, start, stop=None, step=1, _int=int):
...
def _randbelow(self, n, int=int, maxsize=1<

Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Jacco van Dorp
2018-05-01 14:54 GMT+02:00 Greg Ewing :
> Rhodri James wrote:
>>
>> I'd be interested to know if there is a readability difference between
>> really_long_descriptive_identifier_name and
>> ReallyLongDescriptiveIdentifierNames.
>
>
> As one data point on that, jerking my eyes quickly across
> that line I found it much easier to pick out the component
> words in the one with underscores.
>
> --
> Greg


Which is funny, because I had the exact opposite.

Might it be that we've had different conditioning ?

Jacco
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Dan Sommers
On Tue, 01 May 2018 22:37:11 +1000, Steven D'Aprano wrote:

> On Tue, May 01, 2018 at 04:50:05AM +, Dan Sommers wrote:
>> On Tue, 01 May 2018 10:42:53 +1000, Steven D'Aprano wrote:
>> 
>> > - people are not good judges of readability;

>> I happen to be an excellent judge of whether a given block of code is
>> readable to me.

> In the same way that 93% of people say that they are an above-average
> driver, I'm sure that most people think that they are an excellent
> judge of readability. Including myself in *both* of those.

Are you claiming that I'm not an excellent judge of whether a given
block of code is readable to me?

> 2. Anecdotally, we all know that many programmers are just awful.

No argument here!  :-)

> https://thedailywtf.com/

Readability is only one criterion by which to judge code.  Most code on
thedailywtf is bad due to varieties of bugs, inefficiencies,
misunderstandings, or unnecessary complexities, regardless of how
readable it is.

> And presumably most of them think they are writing readable code ...

Why would you presume that?  I haved worked with plenty programmers who
didn't consider readability.  If it passes the tests, then it's good
code.  If I have difficulty reading it, then that's my problem.

Also, when I write code, I put down my text editor to review it myself
before I submit it for formal review.  My authoring criteria for good
code is different from my reviewing criteria for good code; the latter
includes more readability than the former.

> ... I have known many people who swear black and blue that they work
> best with their editor configured to show code in a tiny, 8pt font,
> and I've watched them peering closely at the screen struggling to read
> the text and making typo after typo which they failed to notice.

> In other words, people are often not even a great judge of what is 
> readable to *themselves*.

On that level, aesthetics definitely count (typographers have known this
for centuries), but in an entirely different way.  Is their code better
when their editor shows it at 14.4pt?  At 17.3pt?

When we first started with color displays and syntax coloring editors,
it was popular to make a language's keywords really stand out.  But the
keywords usually aren't the important part of the code (have you ever
programmed in lisp?), and I find it easier to read algol-like code when
the keywords are lowlighted rather than highlighted.  In Python, for
example, the word "import" is far less important than the name of the
module being imported, especially when all the imports are grouped
together near the top of the source file.

Dan

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A way to subscript a single integer from bytes

2018-05-01 Thread Ken Hilton
Whoops! Never seen that before. Nothing I searched up pointed me to it.
Sorry for wasting your time!

Ken;
-- 
Sincerely,
Ken;
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A way to subscript a single integer from bytes

2018-05-01 Thread Steven D'Aprano
On Tue, May 01, 2018 at 07:22:52PM +0800, Ken Hilton wrote:

> The only way to get 493182234161465432041076 out of b'hovercraft'

You seem to be using a bytes object as a base-256 number. Under what 
circumstances is this desirable?


> in a single expression is as follows:

What's so special about this operation that it needs to be a single 
expression? The easy way to do this is:

from functools import reduce  # not needed in Python 2
reduce(lambda m, n: m*256 + n, b'hovercraft', 0)

Do the import once at the top of your module, and then you can call 
reduce as many times as you like.

If you really, really, really want to make it a one-liner, perhaps to 
win a bet, or because the Enter key on your keyboard is broken, then you 
can use the __import__('functools') trick.

__import__('functools').reduce(lambda m, n: m*256 + n, b'hovercraft', 0)

But don't do that.


> list(__import__('itertools').accumulate((i for i in a), lambda x, y: (x
> << 8) + y))[-1]

'(i for i in a)' is best written as 'iter(a)' if you must have an 
iterator, or just 'a' if you don't care what sort of iterable it is.


> Now, I'm not proposing changing the 1-dimensional subscripting syntax to
> return an integer - that would be backwards incompatible, tsk tsk! No,
> instead, I'm simply suggesting a method of bytes objects, which would do
> something like this (assume the method is called "subint"):
> 
> >>> a = b'hovercraft'
> >>> a.subint(0, -1) # -1 is equivalent to len(a)
> 493182234161465432041076
> 
> Much as I would think that such subscripting would deserve special syntax
> (perhaps bytes{idx1:idx2}), I don't think this special case is special
> enough to break the rules. So I'm sticking with the method idea.
> 
> What are your thoughts?

I don't even know why you would want to do it in the first place, let 
alone why you think it is special enough to dedicate syntax to doing it.




-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Greg Ewing

Rhodri James wrote:
I'd be interested to know if there is a readability difference between 
really_long_descriptive_identifier_name and 
ReallyLongDescriptiveIdentifierNames.


As one data point on that, jerking my eyes quickly across
that line I found it much easier to pick out the component
words in the one with underscores.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A way to subscript a single integer from bytes

2018-05-01 Thread Antoine Pitrou

Hi Ken,

On Tue, 1 May 2018 19:22:52 +0800
Ken Hilton  wrote:
> 
> So I'm pretty sure everyone here is familiar with how the "bytes" object
> works in Python 3. It acts mostly like a string, with the exception that
> 0-dimensional subscripting (var[idx]) returns an integer, not a bytes
> object - the integer being the ordinal number of the corresponding
> character.
> However, 1-dimensional subscripting (var[idx1:idx2]) returns a bytes
> object. Example:
> 
> >>> a = b'hovercraft'
> >>> a[0]  
> 104
> >>> a[4:8]  
> b'rcra'
> 
> Though this isn't exactly unexpected behavior (it's not possible to
> accidentally do 1-dimensional subscripting and expect an integer it's a
> different syntax), it's still a shame that it isn't possible to quickly and
> easily subscript an integer out of it. Following up from the previous
> example, The only way to get 493182234161465432041076 out of b'hovercraft'
> in a single expression is as follows:
> 
> list(__import__('itertools').accumulate((i for i in a), lambda x, y: (x
> << 8) + y))[-1]

Let's see:

>>> a = b'hovercraft'
>>> int.from_bytes(a, 'big')
493182234161465432041076

Regards

Antoine.


___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] A way to subscript a single integer from bytes

2018-05-01 Thread Ken Hilton
Hi all,

So I'm pretty sure everyone here is familiar with how the "bytes" object
works in Python 3. It acts mostly like a string, with the exception that
0-dimensional subscripting (var[idx]) returns an integer, not a bytes
object - the integer being the ordinal number of the corresponding
character.
However, 1-dimensional subscripting (var[idx1:idx2]) returns a bytes
object. Example:

>>> a = b'hovercraft'
>>> a[0]
104
>>> a[4:8]
b'rcra'

Though this isn't exactly unexpected behavior (it's not possible to
accidentally do 1-dimensional subscripting and expect an integer it's a
different syntax), it's still a shame that it isn't possible to quickly and
easily subscript an integer out of it. Following up from the previous
example, The only way to get 493182234161465432041076 out of b'hovercraft'
in a single expression is as follows:

list(__import__('itertools').accumulate((i for i in a), lambda x, y: (x
<< 8) + y))[-1]

Now, I'm not proposing changing the 1-dimensional subscripting syntax to
return an integer - that would be backwards incompatible, tsk tsk! No,
instead, I'm simply suggesting a method of bytes objects, which would do
something like this (assume the method is called "subint"):

>>> a = b'hovercraft'
>>> a.subint(0, -1) # -1 is equivalent to len(a)
493182234161465432041076

Much as I would think that such subscripting would deserve special syntax
(perhaps bytes{idx1:idx2}), I don't think this special case is special
enough to break the rules. So I'm sticking with the method idea.

What are your thoughts?

Sincerely,
Ken;
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Matt Arcidy
On Tue, May 1, 2018 at 1:29 AM, Nathaniel Smith  wrote:
> On Mon, Apr 30, 2018 at 8:46 PM, Matt Arcidy  wrote:
>> On Mon, Apr 30, 2018 at 5:42 PM, Steven D'Aprano  wrote:
>>> (If we know that, let's say, really_long_descriptive_identifier_names
>>> hurt readability, how does that help us judge whether adding a new kind
>>> of expression will hurt or help readability?)
>>
>> A new feature can remove symbols or add them.  It can increase density
>> on a line, or remove it.  It can be a policy of variable naming, or it
>> can specifically note that variable naming has no bearing on a new
>> feature.  This is not limited in application.  It's just scoring.
>> When anyone complains about readability, break out the scoring
>> criteria and assess how good the _comparative_ readability claim is:
>> 2 vs 10?  4 vs 5?  The arguments will no longer be singularly about
>> "readability," nor will the be about the question of single score for
>> a specific statement.  The comparative scores of applying the same
>> function over two inputs gives a relative difference.  This is what
>> measures do in the mathematical sense.
>
> Unfortunately, they kind of study they did here can't support this
> kind of argument at all; it's the wrong kind of design. (I'm totally
> in favor of being more evidence-based decisions about language design,
> but interpreting evidence is tricky!) Technically speaking, the issue
> is that this is an observational/correlational study, so you can't use
> it to infer causality. Or put another way: just because they found
> that unreadable code tended to have a high max variable length,
> doesn't mean that taking those variables and making them shorter would
> make the code more readable.
>
I think you are right about the study, but are tangential to what I am
trying to say.

I am not inferring causality when creating a measure.  In the most
tangible example, there is no inference that the euclidean measure
_creates_ a distance, or that _anything_ creates a distance at all, it
merely generates a number based on coordinates in space.  That
generation has specific properties which make it a measure, or a
metric, what have you.

The average/mean is another such object: a measure of central tendency
or location.  It does not infer causality, it is merely an algorithm
by which things can be compared.  Even misapplied, it provides a
consistent ranking of one mean higher than another in an objective
sense.

Even if not a single person agrees that line length is a correct
measure for an application, it is a measure.  I can feed two lines
into "len" and get consistent results out.   This result will be the
same value for all strings of length n, and for a string with length m
> n, the measure will always report a higher measured value for the
string of length m than the string of length n.   This is straight out
of measure theory, the results are a distance between the two objects,
not a reason why.

The same goes for unique symbols.  I can count the unique symbols in
two lines, and state which is higher.  This does not infer a
causality, nor do _which_ symbols matter in this example, only that I
can count them, and that if count_1 == count_2, the ranks are equal
aka no distance between them, and if count_1 > count_2, count 1 is
ranked higher.

The cause of complexity can be a number of things, but stating a bunch
of criteria to measure is not about inference.  Measuring the
temperature of a steak doesn't infer why people like it medium rare.
It just quantifies it.

> This sounds like a finicky technical complaint, but it's actually a
> *huge* issue in this kind of study. Maybe the reason long variable
> length was correlated with unreadability was that there was one
> project in their sample that had terrible style *and* super long
> variable names, so the two were correlated even though they might not
> otherwise be related. Maybe if you looked at Perl, then the worst
> coders would tend to be the ones who never ever used long variables
> names. Maybe long lines on their own are actually fine, but in this
> sample, the only people who used long lines were ones who didn't read
> the style guide, so their code is also less readable in other ways.
> (In fact they note that their features are highly correlated, so they
> can't tell which ones are driving the effect.) We just don't know.
>

Your points here are dead on.  It's not like a single metric will be
the deciding factor.  Nor will a single rank end all disagreements.
It's a tool.  Consider line length 79, that's an explicit statement
about readability, it's "hard coded" in the language.  Disagreement
with the value 79 or even the metric line-length doesn't mean it's not
a measure.  Length is the euclidean measure in one dimension.

The measure will be a set of filters and metrics that combine to a
value or set of values in a reliable way.  It's not about any sense of
correctness or even being 

Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Antoine Pitrou

Yes, it seems that this study has many limitations which don't make its
results very interesting for our community.  I think the original point
was that readability *can* be studied rationnally and scientifically,
though.

Regards

Antoine.


On Tue, 1 May 2018 09:00:44 +0200
Jacco van Dorp 
wrote:
> I must say my gut agrees that
> really_long_identifier_names_with_a_full_description don't look
> readable to me. Perhaps it's my exposure to (py)Qt, but I really like
> my classes like ThisName and my methods like thisOne. I also tend to
> keep them to three words max (real code from yesterday:
> getActiveOutputs(), or at most setAllDigitalOutputs()). I also really
> dislike more than 3 or 4 arguments.
> 
> A question for another type of science would be, do I agree with this
> study because it agrees with me ?
> 
> It should be noted that the snippets used were short and small. This
> might cause a bias towards short identifiers - after all, if you only
> got 3 to keep track of it, they're more likely to be distinct enough
> compared to when you have 20. I couldn't give a source, but IIRC
> people can hold up to around 5 to 7 concepts in their head at one time
> - which means that if you got less identifiers than that, you don't
> remember the names, but their concepts.(further reading shows this is
> supported with their strongest negative correlation - # of identifiers
> strongly decreases readability.). Compare it to RAM - it's only big
> enough for 5 to 7 identifiers, and after that you have to switch them
> out to the harddisk. *nobody* wants to code that does this switching,
> and our brains don't like running it either. I think this is one of
> the main reasons list/generator comprehensions increase readability so
> much. You can get rid of 1 or 2 variable names.
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
> 



___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Greg Ewing

Steven D'Aprano wrote:
So what was the closure? If the surrounding function was still running, 
there was no need to capture the running environment in a closure?


You seem to be interpreting the word "closure" a bit
differently from most people. It doesn't imply anything
about whether a surrounding function is still running or
not.

A closure is just a piece of code together with a runtime
environment. In typical Pascal implementations, a closure
is represented by a (code_address, frame_pointer) pair,
where the frame_pointer points to a chain of lexically
enclosing stack frames. The language rules make it possible
to manage the frames strictly stack-wise, which simplifies
the memory management, but that doesn't make the closure
any less of a closure.

Contrast this with Modula-2, where only top-level functions
can be passed as parameters. When you pass a function in
Modula-2, only the code address is passed, with no
environment pointer.

--
Greg
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Nathaniel Smith
On Mon, Apr 30, 2018 at 8:46 PM, Matt Arcidy  wrote:
> On Mon, Apr 30, 2018 at 5:42 PM, Steven D'Aprano  wrote:
>> (If we know that, let's say, really_long_descriptive_identifier_names
>> hurt readability, how does that help us judge whether adding a new kind
>> of expression will hurt or help readability?)
>
> A new feature can remove symbols or add them.  It can increase density
> on a line, or remove it.  It can be a policy of variable naming, or it
> can specifically note that variable naming has no bearing on a new
> feature.  This is not limited in application.  It's just scoring.
> When anyone complains about readability, break out the scoring
> criteria and assess how good the _comparative_ readability claim is:
> 2 vs 10?  4 vs 5?  The arguments will no longer be singularly about
> "readability," nor will the be about the question of single score for
> a specific statement.  The comparative scores of applying the same
> function over two inputs gives a relative difference.  This is what
> measures do in the mathematical sense.

Unfortunately, they kind of study they did here can't support this
kind of argument at all; it's the wrong kind of design. (I'm totally
in favor of being more evidence-based decisions about language design,
but interpreting evidence is tricky!) Technically speaking, the issue
is that this is an observational/correlational study, so you can't use
it to infer causality. Or put another way: just because they found
that unreadable code tended to have a high max variable length,
doesn't mean that taking those variables and making them shorter would
make the code more readable.

This sounds like a finicky technical complaint, but it's actually a
*huge* issue in this kind of study. Maybe the reason long variable
length was correlated with unreadability was that there was one
project in their sample that had terrible style *and* super long
variable names, so the two were correlated even though they might not
otherwise be related. Maybe if you looked at Perl, then the worst
coders would tend to be the ones who never ever used long variables
names. Maybe long lines on their own are actually fine, but in this
sample, the only people who used long lines were ones who didn't read
the style guide, so their code is also less readable in other ways.
(In fact they note that their features are highly correlated, so they
can't tell which ones are driving the effect.) We just don't know.

And yeah, it doesn't help that they're only looking at 3 line blocks
of code and asking random students to judge readability – hard to say
how that generalizes to real code being read by working developers.

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Steven D'Aprano
On Tue, May 01, 2018 at 06:06:06PM +1200, Greg Ewing wrote:
> Steven D'Aprano wrote:
> >Pascal, for example, had lexical scoping back in the 1970s, but 
> >no closures.
> 
> Well, it kind of had a limited form of closure. You could pass
> a procedure or function *in* to another procedure or function
> as a parameter, but there was no way to return one or pass it
> out in any way. This ensured that the passed-in procedure or
> function couldn't outlive its lexical environment.

So what was the closure? If the surrounding function was still running, 
there was no need to capture the running environment in a closure?

Not a rhetorical question, I'm genuinely unsure.


-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Objectively Quantifying Readability

2018-05-01 Thread Jacco van Dorp
I must say my gut agrees that
really_long_identifier_names_with_a_full_description don't look
readable to me. Perhaps it's my exposure to (py)Qt, but I really like
my classes like ThisName and my methods like thisOne. I also tend to
keep them to three words max (real code from yesterday:
getActiveOutputs(), or at most setAllDigitalOutputs()). I also really
dislike more than 3 or 4 arguments.

A question for another type of science would be, do I agree with this
study because it agrees with me ?

It should be noted that the snippets used were short and small. This
might cause a bias towards short identifiers - after all, if you only
got 3 to keep track of it, they're more likely to be distinct enough
compared to when you have 20. I couldn't give a source, but IIRC
people can hold up to around 5 to 7 concepts in their head at one time
- which means that if you got less identifiers than that, you don't
remember the names, but their concepts.(further reading shows this is
supported with their strongest negative correlation - # of identifiers
strongly decreases readability.). Compare it to RAM - it's only big
enough for 5 to 7 identifiers, and after that you have to switch them
out to the harddisk. *nobody* wants to code that does this switching,
and our brains don't like running it either. I think this is one of
the main reasons list/generator comprehensions increase readability so
much. You can get rid of 1 or 2 variable names.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] A "local" pseudo-function

2018-05-01 Thread Greg Ewing

Steven D'Aprano wrote:
Pascal, for example, had lexical scoping back in the 1970s, but 
no closures.


Well, it kind of had a limited form of closure. You could pass
a procedure or function *in* to another procedure or function
as a parameter, but there was no way to return one or pass it
out in any way. This ensured that the passed-in procedure or
function couldn't outlive its lexical environment.

--
Greg

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/