[Python-ideas] Re: Add __eq__ to colletions.abc.Sequence ?

2020-07-05 Thread Neil Girdhar
Are all objects in Python equality-comparable?  I know that you can delete 
__hash__ to make an object unhashable (e.g., dicts).  If so, this is a 
great addition.

On Saturday, July 4, 2020 at 5:26:45 PM UTC-4, Joao S. O. Bueno wrote:
>
>
>
> On Sat, 4 Jul 2020 at 16:51, Serhiy Storchaka  > wrote:
>
>> 30.06.20 18:58, Joao S. O. Bueno пише:
>> > I ended up writting an __eq__ - and in the process I found it is not 
>> > _that_ straightforward  due
>> > to  having to check subclasses types when comparing.
>> > (given Base sequence A, child class B(A), class C(A) and class B1(B) - 
>> > Instances of B and B1 can be
>> > equal, but instances of B and C should always be different) - or in 
>> > Python, inside __eq__ :
>> >  if not issubclass(type(other), type(self)) and not 
>> > issubclass(type(self), type(other)):
>> >  return False
>>
>> It would be more correct to return NotImplemented.
>>
>> Also, it is enough to test isinstance(other, type(self)) because 
>> other.__eq__(self) be called first if the type of other is a subclass of 
>> the type of self.
>>
>
> Ah - yes. Half the logic is already on the __eq__ semantics - thanks.
> Well, I am updating that on my code right now. 
>
> Anyway I am not seeing anyone opposing this going into col...abc.Sequence 
> - 
> Maybe it is ok for a BPO?  
>
> (yes, there is this consideration I had, and also Guido,
> that it would create new behavior in classes that already exist, but I saw
>  no way that could break code not specially crafted to  break with this 
> change.)
>
>
> ___
>> Python-ideas mailing list -- python...@python.org 
>> To unsubscribe send an email to python-id...@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/K2P4ZWF6FIRPCRKUH7IHZHMC7E3HVJER/
>> 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/FXJWTXQWTW7C32JBEBOIYLYOXVDLTQ2P/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread David Mertz
On Sun, Jul 5, 2020, 10:25 PM Steven D'Aprano  wrote:

> > The standard library *does* seem to have taken pains to avoid
> "finite nans."
>
> I don't know what you mean by "finite nans". By definition, any NAN is not
> considered finite.
>

The scare quotes because I know that's not a real thing. Maybe "genetically
finite" ... I.e. do some operations on regular finite values that wind up
with NaN. I know, I know... That's not really right either, since finite
values can overflow to infinities on their own.

Do you mean, the stdlib has taken pains to avoid returning NANs ex novo,
> i.e. from purely finite arguments? Then I agree.
>

Yes. That's it. :-)


> min() and max() are notable, and unfortunate, exceptions in that their
> treatment of NANs depends on the order of argument. I would call that a bug
> except that the statistics module (which I wrote) has the same flaw, and
> I've argued in the past that this is not a bug :-)
>

Personal growth is healthy!

That's not the trig functions' fault, it's the fact that we cannot
> exactly represent pi/2 exactly. I'm not sure what you mean by pruning
> them, it is pretty much standard that tan(pi/2) doesn't fail:
>

Of course. math.pi is a number that isn't really pi, as any finite
representation must be. tan() is doing the right thing. I just meant that
if math.cot() were added to the standard library, I could pass an exact
zero as argument. None of the trig or hyperbolic functions that are
undefined at ZERO are included.

But yes, math.log(0) is another one where a NaN is avoided in favor of an
exception. A few different log bases, but same story for all.
___
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/ZVBGV7UDCFC4OEFE5UFV7ZNUFK223ZIC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Chris Angelico
On Mon, Jul 6, 2020 at 12:36 PM Steven D'Aprano  wrote:
> Four years ago, there was strong opposition to giving the bounds default
> values. I think the consensus at the time was that it is okay to
> explicitly provide "unbounded" arguments (whether you spell them as
> infinities, NANs, or None) but you should have to explicitly do so:
>
> clamp(x)
>
> just reads poorly.

Yes, but it's also useless (clamping without ANY bounds?). In terms of
reading poorly, this is far worse:

clamp(x, 10)

Does that ensure that it's no *greater* than 10 or no *less* than 10?
Since the args would be min before max, I would expect that this has a
lower bound and no upper bound, but there'll be people equally
confident that it should behave like range() and have an upper bound
with no lower bound (which would probably be more useful in a lot of
situations anyway).

So I also agree that the bounds should be given explicitly.

ChrisA
___
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/J5ZPUKV7IMQDJVHF6HTNQNNA6AJZNDMF/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Mon, Jul 06, 2020 at 03:21:04AM +0100, Henk-Jaap Wagenaar wrote:
> I do not agree clamp should be restricted to numeric values. I would expect
> clamp to be agnostic to the specifics of floats/numbers and like sort
> expect it to work for any values as long as they compare (using a dunder).

It is possible to write clamp so that it relies only on two things:

- the bounds must support equality and less than;
- the value must support less than.

That is pretty much as general as it gets. I think that it is okay to 
document clamp as *intended* for numbers but allow it to be used for 
non-numbers, similar to the builtin sum().

(Although sum needs to be tricked into supporting strings.)

Four years ago, there was strong opposition to giving the bounds default 
values. I think the consensus at the time was that it is okay to 
explicitly provide "unbounded" arguments (whether you spell them as 
infinities, NANs, or None) but you should have to explicitly do so:

clamp(x)

just reads poorly. I concur with that argument -- or at least, I don't 
disagree strongly enough to argue against it. This is why the 
implementation I posted earlier accepts None as bounds, but doesn't give 
them defaults.


-- 
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/CKL734WLAZ26OWPJHCTCM2QIDCLFH622/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Sun, Jul 05, 2020 at 09:42:07PM -0400, David Mertz wrote:

> The standard library *does* seem to have taken pains to avoid "finite
> nans."

I don't know what you mean by "finite nans". By definition, any NAN is 
not considered finite.

py> math.isfinite(math.nan)
False

Do you mean, the stdlib has taken pains to avoid returning NANs ex 
novo, i.e. from purely finite arguments? Then I agree.


> It kinda weakens your case about worrying about doing clamp() right
> in the face of NaNs :-).

Are you suggesting that we should do clamp() wrong instead? *wink*

What I intended is that the stdlib tends to raise rather than 
return a NAN from some calculation not already including NANs or INFs.
But if you pass NANs into the calculation, then the stdlib honours them.

py> math.atan(math.nan)
nan

So if you pass a NAN to clamp(), it should do the right thing, which may 
be returning a NAN:

clamp(NAN, -1, 1)  # Should certainly return a NAN.

or may not:

clamp(NAN, 1, 1)  # Should certainly return 1.


Only the behaviour when one or the other of the bounds are NANs is 
controversial. I acknowledge that there are two good behaviours, and it 
is reasonable for people to want one or the other. I have argued why one 
is better and less inconvenient than the other, but I won't rehash that 
argument here.

min() and max() are notable, and unfortunate, exceptions in that their 
treatment of NANs depends on the order of argument. I would call that a 
bug except that the statistics module (which I wrote) has the same flaw, 
and I've argued in the past that this is not a bug :-)

But in both cases, statistics and min/max, it is clear that the 
order-dependent behaviour satisfies nobody and is undesirable.



> It also looks like the trig functions are pruned to those that don't have
> undefined values for numbers I can type in.  I can *type*
> `math.tan(math.pi/2)`, of course.  But math.pi is a little bit smaller than
> the actual pi, so I just get a big number for an answer.

That's not the trig functions' fault, it's the fact that we cannot 
exactly represent pi/2 exactly. I'm not sure what you mean by pruning 
them, it is pretty much standard that tan(pi/2) doesn't fail:

https://stackoverflow.com/questions/20287765/math-tan-near-pi-2-wrong-in-net-right-in-java

and that comes out of the floating point representation, not tan.


> But I cannot try the hypothetical:
> 
> >>> math.cot(0)
> nan

No, but you could try this instead:

py> math.log(0.0)
Traceback (most recent call last):
  File "", line 1, in 
ValueError: math domain error



-- 
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/N7OCELBGCNAO5LUKBBTRKR35MB4AGSOJ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Henk-Jaap Wagenaar
I do not agree clamp should be restricted to numeric values. I would expect
clamp to be agnostic to the specifics of floats/numbers and like sort
expect it to work for any values as long as they compare (using a dunder).
I think having something like min=-math.inf is hence right out in my mind.
If I got this right, the implementation could be as simple as:

def clamp(value, *, min=None, max=None):
  if min is not None and value < min:
return min
  if max is not None and max < value:
return max
  return value

I think the crucial question here is: does the order of the ifs matter and
is that an issue. The only time (barring side effects, values changing in
between calls et cetera) it would make a difference if max < value < min.
Assuming transitivity (can anybody come up with an example of a
non-transitive order where clamping makes sense?) this means max < min and
so you can work around this by disallowing it:

def clamp_safe(value, * min=None, max=None):
  if max < min:
raise SomeException("Something about min < max")
  return clamp(value, min=min, max=max)

What I like about both of these is that they only use "<", just like sort.

Going back to nans, I think that would mean:

clamp(nan, min, max) = nan
clamp(value, nan, max) = clamp(value, None, max) = max(value, max)
clamp(value, min, nan) = clamp(value, min, None) = min(value, min)

On Mon, 6 Jul 2020 at 02:55, Christopher Barker  wrote:

>
> and we can use +inf and -inf for unlimited bounds as well. Yes, they are a
> bit of a pain to write in Python, but we could do:
>
> def clamp(value, min=-math.inf, max=math.inf):
> ...
>
> yes, that would make them optional, rather than required, and therefore
> provide a slight asymmetry between specifying min only or max only, but
> still be handy. to make it more consistent, but maybe more annoying in the
> common case, we could make them keyword only.
>
___
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/3AXOG34FEMLAWIQQTBH3CZ5J4JL4GJE7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread David Mertz
On Sun, Jul 5, 2020 at 10:04 PM Christopher Barker 
wrote:

> Since you brought that up -- I recall a lot of debate about whether NaN's
> should be considered missing values or "poisoning" in the statistics module
> -- there are arguments for both, and neither was clear or obvious. So using
> NaN to mean "not specified" in this context would not be obvious to
> everyone, and when we have the perfectly good None instead, why do it?
>

Well, yes... I wrote a lot of that debate :-)

I even sort of re-discovered quick select on my own... then eventually
figured out that a bunch of people had benchmarked a better implementation
to potentially use in statistics.median() a year before I tried.  Python
sorted() is really fast!  But it's still the WRONG way to do this, or at
least there should be a switch to allow nan-poisoning  and/or nan-stripping.

Btw, definitely +1 on math.clamp(value, *, lower=None, upper=None) .
>>
>
> what about:
>
> math.clamp(value, *, lower=-math.inf, upper=math.inf) .
>

Oh sure.  That's fine.  But the implementation would still need to check
for None and convert it to the infinities.  Ordinary users just simply ARE
going to try:

math.clamp(x, lower=None, upper=99)

And expect that to mean "I don't care about lower bound."

-- 
The dead increasingly dominate and strangle both the living and the
not-yet born.  Vampiric capital and undead corporate persons abuse
the lives and control the thoughts of homo faber. Ideas, once born,
become abortifacients against new conceptions.
___
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/JMNU4L42AAGKFGF6CSUW3CWY574QUFIM/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Christopher Barker
On Sun, Jul 5, 2020 at 6:51 PM David Mertz  wrote:

>
> will always return x for every finite and infinite value, so it must
>> return x for NANs too.
>>
>
> I strongly agree with Steven here.  Also about order-dependence in results
> of min() and max() being disturbing and contrary to IEEE-754.
>
> ... so, umm... Steven... statistics.median()?!
>

Since you brought that up -- I recall a lot of debate about whether NaN's
should be considered missing values or "poisoning" in the statistics module
-- there are arguments for both, and neither was clear or obvious. So using
NaN to mean "not specified" in this context would not be obvious to
everyone, and when we have the perfectly good None instead, why do it?

Btw, definitely +1 on math.clamp(value, *, lower=None, upper=None) .
>

what about:

math.clamp(value, *, lower=-math.inf, upper=math.inf) .

Also it seems we can have "NaN poisoning" behaviour without explicitly
checking for it. The real key is not that it's a NaN, but that it doesn't
compare as True to anything. Someone smarter than me could probably make
this cleaner, but this works:

In [112]: def min(x, y):
 ...: if x < y:
 ...: return x
 ...: elif y <= x:
 ...: return y
 ...: else:
 ...: return x if not (x < math.inf) else y

Note that I did that ugly ternary expression at the end in hopes that it
would work with non-float NaN-like objects, but no luck there, at least not
with Decimal:

In [113]: min(1, Decimal('NaN'))

---
InvalidOperation  Traceback (most recent call last)
 in 
> 1 min(1, Decimal('NaN'))

 in min(x, y)
  1 def min(x, y):
> 2 if x < y:
  3 return x
  4 elif y <= x:
  5 return y

InvalidOperation: [

It seems that Decimal Nan does not behave like FP NaNs :-(

-1 on built-in.  -0 on any other function signature.  Actually, I'm fine
with math.clip() as well, but clamp seems more popular.

One thing about putting it in the math module is that we could then make
assumptions about the float type. And we'd have to write it in C, so it
would be fast, even if there is some ugly NaN-checking behavior and the
like.

-CHB

-- 
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/V3XVFUNWATUWEJUS64JNLEJBPJ6HWGJH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Christopher Barker
On Sun, Jul 5, 2020 at 6:01 PM Greg Ewing 
wrote:

> On 6/07/20 3:55 am, Steven D'Aprano wrote:
> > With that interpretation, a NAN passed as the lower or upper bounds can
> > be seen as another way of saying "no lower bounds" (i.e. negative
> > infinity) or "no upper bounds" (i.e. positive infinity), not "some
> > unknown bounds".
>
> Python already has a value for representing missing or unspecified
> data, i.e. None. So we don't need to use NaN for that, and can
> instead reserve it to mean "no correct answer".
>

+1

and we can use +inf and -inf for unlimited bounds as well. Yes, they are a
bit of a pain to write in Python, but we could do:

def clamp(value, min=-math.inf, max=math.inf):
...

yes, that would make them optional, rather than required, and therefore
provide a slight asymmetry between specifying min only or max only, but
still be handy. to make it more consistent, but maybe more annoying in the
common case, we could make them keyword only.

> I agree with you that `clamp(lower=x, value=NAN, upper= x)` should
> > return x.
>
> I don't think I agree with that, because it relies on assuming that
> the lower and upper bounds can meaningfully be compared for exact
> equality, which may not be true depending on the circumstances.
>

and then we'd need to check if they were equal as well.


> > Treat a NAN bounds as *missing data*, which effectively means "there is
> > no limit", i.e. as if you had passed the infinity of the appropriate
> > sign for the bounds.
>

and really how often would one end up with NaN as a bound anyway? Often
they will be hard-coded. I"m having a really hard time imagining when you'd
end up with NaN for a bound that was NOT an error!

It would be far more likely for the value you want clamped to be NaN -- and
then it sure as heck should return NaN.

As for the behavior of min() and max() when provided a NaN (and much of
Python's handling of FP special values) -- I think that's a
practicality-beats-purity issue. I have a really hard time thinking that
anyone thinks that:

In [81]: min(1, math.nan)

Out[81]: 1

In [82]: min(math.nan, 1)

Out[82]: nan

is ideal behavior!

while I was writing this:

On Sun, Jul 5, 2020 at 6:38 PM Steven D'Aprano  wrote:

> ...  on this point at least the IEEE-754 standard is firm: if a
> function will return the same result for every non-NAN argument, then it
> must return the same result for NAN arguments too.
>
> clamp(value, x, x)
>
> will always return x for every finite and infinite value, so it must
> return x for NANs too.


Except that Python (maybe except for the math module) does not conform to
IEEE-754 in many other places.

So we do have a practicality beats purity choice here.

-CHB


-- 
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/Z5FBFJKBOJNDWOCGD7INMKPRN3YAS36V/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread David Mertz
On Sun, Jul 5, 2020 at 9:38 PM Steven D'Aprano  wrote:

> > >I agree with you that `clamp(lower=x, value=NAN, upper= x)` should
> > >return x.
>
> Sorry Greg, on this point at least the IEEE-754 standard is firm: if a
> function will return the same result for every non-NAN argument, then it
> must return the same result for NAN arguments too.
>
> clamp(value, x, x)
>
> will always return x for every finite and infinite value, so it must
> return x for NANs too.
>

I strongly agree with Steven here.  Also about order-dependence in results
of min() and max() being disturbing and contrary to IEEE-754.

... so, umm... Steven... statistics.median()?!

Btw, definitely +1 on math.clamp(value, *, lower=None, upper=None) .

-1 on built-in.  -0 on any other function signature.  Actually, I'm fine
with math.clip() as well, but clamp seems more popular.
___
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/7X64MLI6G4Q5ZSIZNBRCU3HAYWWWYOI3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread David Mertz
On Sun, Jul 5, 2020 at 8:57 PM Steven D'Aprano  wrote:

> On Sun, Jul 05, 2020 at 12:15:27PM -0400, David Mertz wrote:
> > This is a digression, but does anyone have a nice example IN PYTHON of
> > arriving at a NaN without going through infinity. I think Julia is right
> > and Python is wrong about '0/0', but as things are, that's not an
> example.
>
> I wouldn't expect one in Python, I think there is an unofficial policy
> of ensuring that Python builtins and the math library will not return
> NANs unless passed a NAN, or at least an INF, rather they will raise.
>
> > > >>> 1e1000-1e1000
> > > nan
> is just a funny way of writing INF - INF :-)
>

The standard library *does* seem to have taken pains to avoid "finite
nans."  It kinda weakens your case about worrying about doing clamp() right
in the face of NaNs :-).

I recognize there are funny ways of writing infinity.  But since Python
really doesn't quite follow IEEE-754 on 0/0, or math.fmod(x, 0.), or a few
other places it might arise in "natural" operations (i.e. it's easy not to
notice that your 'y' has become zero.

It also looks like the trig functions are pruned to those that don't have
undefined values for numbers I can type in.  I can *type*
`math.tan(math.pi/2)`, of course.  But math.pi is a little bit smaller than
the actual pi, so I just get a big number for an answer.  But I cannot try
the hypothetical:

>>> math.cot(0)
nan

For what we actually have:

>>> math.tan(math.pi/2)

1.633123935319537e+16

One ULP more:

>> math.tan(np.nextafter(math.pi/2, np.inf))

-6218431163823738.0


-- 
The dead increasingly dominate and strangle both the living and the
not-yet born.  Vampiric capital and undead corporate persons abuse
the lives and control the thoughts of homo faber. Ideas, once born,
become abortifacients against new conceptions.
___
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/P742DYSQAMWKAAKNPASMDSEXH6AGEXKO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Mon, Jul 06, 2020 at 12:59:28PM +1200, Greg Ewing wrote:

> >I agree with you that `clamp(lower=x, value=NAN, upper= x)` should
> >return x.
> 
> I don't think I agree with that

Sorry Greg, on this point at least the IEEE-754 standard is firm: if a 
function will return the same result for every non-NAN argument, then it 
must return the same result for NAN arguments too.

clamp(value, x, x)

will always return x for every finite and infinite value, so it must 
return x for NANs too.

Quoting one of the standard committee members:

NaN must not be confused with “Undefined.” On the contrary,  
IEEE 754 defines NaN perfectly well even though most language
standards ignore and many compilers deviate from that definition.
The deviations usually afflict relational expressions, discussed
below. Arithmetic operations upon NaNs other than SNaNs (see 
below) never signal INVALID, and always produce NaN unless 
replacing every NaN operand by any finite or infinite real values
would produce the same finite or infinite floating-point result 
independent of the replacements.

https://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF

See page 7.

This is why 1.0**NAN returns 1.0, and why math.hypot(INF, NAN) returns 
INF.


> because it relies on assuming that
> the lower and upper bounds can meaningfully be compared for exact
> equality, which may not be true depending on the circumstances.

I don't understand that objection. Can you give a concrete example?


> >Treat a NAN bounds as *missing data*, which effectively means "there is
> >no limit", i.e. as if you had passed the infinity of the appropriate
> >sign for the bounds.
> 
> If one of the bounds is missing, you don't need clamp(), you
> can use min() or max().

Only if you know it is missing. If the bounds come from some other 
calculation or from the user, how do you know they are missing?

if lower is upper is None:
pass
elif lower is None:
value = min(value, upper)
elif upper is None:
value = max(value, lower)
else:
value = clamp(value, lower, upper)


We don't have three slice functions to cover the cases where one or the 
other bounds is missing:

slice(start, stop)
slice_end_at(stop)
slice_start_at(start)

we just have a single function that takes a missing value.


-- 
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/R3IBF2EBARO6BJ7KKIWRJ57VWKLC7DN7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: giving set.add a return value

2020-07-05 Thread Christopher Barker
Sorry, this got lost in the shuffle without being sent, and the
conversation seems to have died down. but since I wrote it ...

On Sat, Jul 4, 2020 at 8:25 AM Stephen J. Turnbull <
turnbull.stephen...@u.tsukuba.ac.jp> wrote:

> Christopher Barker writes:
>
>  > I am really confused here -- I'm suggesting that is should NOT be
> possible
>  > to tell the difference.
>
> But it is possible to tell the difference, so that suggestion is moot.


I meant in the context of putting things in, or testing whether they are
in, sets. Not in any other context.

There are languages where there is no numeric tower, just numbers, and
> [0][0], [0][0.0], and [0][0+0j] all just work.  Python isn't one of
> them.  Fewer places you can tell in Python 3 than in Python 2, I
> believe, but several remain.


Sure, but putting them in sets, or using them as a key in a dict is not one
of them.

set.intern does yield the same result regardless of what's passed in:
> whichever is in the set.  That's *why* I can call it "intern".[1]


Fair enough. You can of course propose any functionality you want. I’m
suggesting that my understanding of what you are proposing doesn’t match
well with the rest of how sets work.

But to see if I understand correctly, you couldn’t quite use a set to
intern objects: once 2.0 was in there you could not put 2 in as well. You
could know that 2.0 was already in there when you tried to add 2, but it
would still never be added.

It seems if you really want to intern objects, you’d need something kind of
like, but not quite, a set().

Note: this all is only an issue for object that are of a different type,
but can compare equal and have the same hash - maybe the numeric types are
the only ones in the stdlib for which this is the case. Nevertheless, they
are commonly used :-)

Nope: turns out NamedTuples and Tuple are the "same" as far as sets are
concerned as well.

In [66]: s = {p}


In [67]: s

Out[67]: {Point(x=2, y=3)}

In [68]: s.add((2,3))


In [69]: s

Out[69]: {Point(x=2, y=3)}

In [70]: s = {(2,3)}


In [71]: s.add(p)


In [72]: s

Out[72]: {(2, 3)}

So if you want something that treats different types with the same value as
different, you really will need a different storage mechanism than a set.

-CHB
___
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/JKK6J7CGWLLSOQATFD5JRL6VAS3YQGGI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Greg Ewing

On 6/07/20 3:55 am, Steven D'Aprano wrote:

With that interpretation, a NAN passed as the lower or upper bounds can
be seen as another way of saying "no lower bounds" (i.e. negative
infinity) or "no upper bounds" (i.e. positive infinity), not "some
unknown bounds".


Python already has a value for representing missing or unspecified
data, i.e. None. So we don't need to use NaN for that, and can
instead reserve it to mean "no correct answer".


I agree with you that `clamp(lower=x, value=NAN, upper= x)` should
return x.


I don't think I agree with that, because it relies on assuming that
the lower and upper bounds can meaningfully be compared for exact
equality, which may not be true depending on the circumstances.


Treat a NAN bounds as *missing data*, which effectively means "there is
no limit", i.e. as if you had passed the infinity of the appropriate
sign for the bounds.


If one of the bounds is missing, you don't need clamp(), you
can use min() or max().

--
Greg
___
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/WD4RO57XMIKUDYWAXCRPE3MSJ2RZEBRU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Sun, Jul 05, 2020 at 12:15:27PM -0400, David Mertz wrote:
> This is a digression, but does anyone have a nice example IN PYTHON of
> arriving at a NaN without going through infinity. I think Julia is right
> and Python is wrong about '0/0', but as things are, that's not an example.

I wouldn't expect one in Python, I think there is an unofficial policy 
of ensuring that Python builtins and the math library will not return 
NANs unless passed a NAN, or at least an INF, rather they will raise.

Chris' example:

> > >>> 1e1000-1e1000
> > nan

is just a funny way of writing INF - INF :-)



-- 
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/DT4GE4UAPSAPPV3DSFF7SHEP3QR6BZGD/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Sun, Jul 05, 2020 at 11:58:58AM -0700, Bruce Leban wrote:

> > People who want NAN poisoning can opt-in by doing a check for NANs
> > themselves, either in a wrapper function, or by testing the bounds
> > *once* ahead of time and then just calling the stdlib `clamp` once they
> > know they aren't NANs.
> 
> 
> Imagine making the same statement about exceptions:
> 
>  Exceptions being raised should be opt-in.
> 
> 
> That sounds crazy but it's not. Before exceptions were commonplace, there
> were three possibilities when unreasonable operations were performed:

But using a NAN is not an unreasonable operation. There is a perfectly 
sensible interpretaion available for using NANs as bounds, and it is 
one which is supported by the IEEE-754 recommended treatment 
of minimum and maximum: missing values.

That same behaviour falls out naturally from a very simple, non- 
contrived and efficient implementation of clamp that relies only on the 
value supporting less than. (The bounds also have to support equality.) 
It doesn't even have to be numeric! So long as the value supports less 
than, you can clamp it. Whether that is meaningful or not depends on the 
value, but the feature is there for those who can make use of it. 
Duck-typing for the win!


>- return some arbitrary or random value (not a NaN because they hadn't
>been invented);

IEEE-754 goes back to the 1980s, before exceptions were commonplace.

So returning a NAN was certainly an option. On the Apple Mac, converting 
a string to a float would return a NAN if it was a non-numeric value 
like "abc". So did operations like arcsin(2).


>- and also set an "error flag" that could be checked by the caller to
>determine if something had gone wrong (but frequently was not);
>- terminate the program.
> 
> Things are much better now. Few argue that it was better before.

There are many people who consider exceptions to be a terrible mistake, 
including the creators of Go. So your analogy is not as strong as you 
think.


> Think of
> NaN as the value equivalent of an exception. NaN poisoning is the
> equivalent of the fact that any function that doesn't catch an exception
> passes it through.

Right. That's an excellent analogy. If exceptions were uncatchable, they 
would always be fatal and they would be just like the bad old days where 
any error would always terminate the program.

But they aren't uncatchable, and there are situations where NANs don't 
represent a fatal error that can only propagate through your calculation 
poisoning the results.

Here are some examples:

py> 1 < NAN
False

py> min(max(1, NAN), NAN)
1

py> 1**NAN
1.0

The first two are especially relevant for clamp.


> I don't usually write code that *uses *NaNs directly. If
> I want a distinguished non-numeric value, I use None or some other
> sentinel. If a NaN is produced by my code it indicates a bug. NaN poisoning
> increases the chance that a NaN generated somewhere won't be hidden by
> later code that manipulates that value. Why would I want to suppress that?

Then don't. I'm happy for you to test for it. Write a wrapper function 
that checks the bounds, and you are no worse off than if it was builtin.

In many use-cases, you won't even need a wrapper function, because the 
bounds won't be changing, or will change only rarely. So you only need 
test them once, not on every call to clamp. Win!

I respect your right to check the bounds for NANs. How about you respect 
my right to not to, and don't force me to do it *twice* to get the 
behaviour I want?


> Just as an exception can be suppressed by explicit code, Nan poisoning can
> be suppressed by explicit checks. 

What you want is for people who want to test for NANs to have the clamp 
function do it for them, and people who don't want to check for NANs to 
have to do it twice, once in their wrapper function, and once in the 
clamp function.

Your attitude here is literally:

"Oh, you don't want to check for NANs? Then I'll make you do it twice as 
much as everyone else!"


> So let me rewrite your second and third
> paragraphs above (recall Option 1 which you favor is ignore NaNs, and
> Option 2 is NaN poisoning):
> 
> Let's say the stdlib uses Option 2. The function doesn't need to do any
> explicit checks for NANs,

But that's not true, it does need to check for NANs explicitly, because 
order comparisons `x < NAN` don't return NANs.

There may be some clever arrangement of arguments for min and max that 
will return a NAN, but that's depending on accidental behaviour. You 
can't rely on it.

(Having the result of min and max depend on the order of arguments is 
not a feature, and relying on that accidental behaviour is not safe.)



-- 
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 

[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Christopher Barker
Sorry, that got sent too soon.

On Sun, Jul 5, 2020 at 1:59 PM Christopher Barker 
wrote:

> On Sun, Jul 5, 2020 at 6:15 AM MRAB  wrote:
>
>> > clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum:
>> Union[Number, Iterable[Number]])
>> >
>
> What would that return? What if the iterables were two different
> lengths?
>
> If anything, I would accept an iterable for the value, and return an
> iterator.
>
> min() with an iterable is essentially  a reduce. clamp() with an iterable
> would be a map.
>

Though then there is the question of what to return for a scalar value: an
iterator with one value or a scalar?

So maybe these kinds of operations should be left to numpy.

-CHB
___
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/NC334DSLOP72P5EABIEVNPLXIBLZWU7A/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread MRAB

On 2020-07-05 14:06, MRAB wrote:

On 2020-07-05 10:09, Federico Salerno wrote:
[snip]
FInally, I'd like to lit another fire: given that `min()` and `max()` 
accept an arbitrary amount of arguments, and that the signature that 
seems to be preferred for the hypothetical clamp at the moment sees 
`value` as the first positional argument, should the function then 
accept iterables as values for `minimum` and `maximum`?

Something along the lines of:

clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: 
Union[Number, Iterable[Number]])


I think that's overcomplicating it. How often have you actually wanted
that feature?

If you want bounds that are iterables, just use min/max on them first.

Another point: min and max accept either a single iterable or multiple 
values, but not a mixture, so they set a precedent for 'clamp' not 
accepting a mixture too.

___
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/OEHVQXY2JT6ESPRJ2K7RX2RQ4RJCOHLH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Rob Cliffe via Python-ideas

On 05/07/2020 10:09, Federico Salerno wrote:


On the topic of NaNs: I think in the face of ambiguity, we should 
refuse the temptation to guess and raise ValueError when the values 
given are not comparable to the point of clearly determining whether 
`value` is or isn't within `minimum` and `maximum` or which of the two 
bounds it exceeds. It is the programmer's responsibility to ensure 
they supply arguments that make sense, and non-numbers should be 
considered exceptional behaviour: as such, the programmer that 
anticipates those kinds of values should handle them exceptionally.


About the name: clamp seems to be the most favoured name and the 
discussion convinced me it's the one that should make it to the 
eventual proposal.


About the stdlib/builtin status: `min(max(x, min_), max_)` is a common 
enough idiom for a simple enough function that I think it is 
definitely beneficial and in no way dangerous to have, and that any 
status other than builtin would incur too much overhead for something 
so small. I risk claiming that most calls to max() and min() occur in 
modules that do not `import math` (or at the very least, they occur 
often enough without `import math`), and I believe clamp(), being very 
similar in scope to those, should benefit from similar status.
I don't think clamp is a common enough identifier in non-specific 
fields to disqualify its implementation as a builtin by itself. By 
contrast, terms like `min` and `max` are extremely common in pretty 
much all contexts, and yet we've all survived just fine by typing 
`min_` and `max_` or even shadowing the names altogether (which I 
prefer not to do, but is definitely an option).


+1 to all of the above (I don't feel strongly about the name).  All 
seems very sensible.


FInally, I'd like to lit another fire: given that `min()` and `max()` 
accept an arbitrary amount of arguments, and that the signature that 
seems to be preferred for the hypothetical clamp at the moment sees 
`value` as the first positional argument, should the function then 
accept iterables as values for `minimum` and `maximum`?

Something along the lines of:

clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: 
Union[Number, Iterable[Number]])

-1.  As others have said, this is over-egging it.

I think None should be allowed as a missing bound.

I don't think the new function should be restricted to numbers. There 
may be uses for strings, or for user-built classes; why restrict it 
unnecessarily?

If it quacks like supporting __lt__ and __gt__, it's a duck.

Rob Cliffe


___
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/YUOCR36ZBUGUDTHJ3HDBIEYFSUVHCXX7/
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/2WWV33TF5C5H7HXU7ETMTIOIWM3NU75P/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread David Mertz
On Sun, Jul 5, 2020, 3:51 PM Chris Angelico  wrote:

> On Mon, Jul 6, 2020 at 2:15 AM David Mertz  wrote:
> >
> > This is a digression, but does anyone have a nice example IN PYTHON of
> arriving at a NaN without going through infinity. I think Julia is right
> and Python is wrong about '0/0', but as things are, that's not an example.
> >
>
> Not sure why "without going through infinity" is relevant, but you can
> always just use float("nan") to get one, and I'm sure there are other
> calculations that result in nan. It's just that 0/0 (like any other
> operation that involves division by zero, including 0**-1) immediately
> raises, rather than silently returning a nan.
>

Like I said, digression. I teach ieee-754 pretty often, or at least touch
on it. I want to demonstrate to students that they might have NaN values to
consider.

Constructing one purely artificially with 'float("nan")' doesn't make the
point well. Some operation that ends up with overflow infinities that are
divided or subtracted is OK. But it would be nice to show a clean example
where NANs arise without infinities arising first.
___
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/EUL4LL2WYRAH2TMYEAGAJMT3WTODWIX6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Christopher Barker
On Sun, Jul 5, 2020 at 6:15 AM MRAB  wrote:

> > clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum:
> Union[Number, Iterable[Number]])
> >

 Ss (
 IsA
Zzz
What would that return? What if the iterable were two different
lengths?

If anything, I would accept an iterable for value, and return an iterator.

Min() with an iterable is essential a reduce. Clamp() with an iterable
would be



> I think that's overcomplicating it. How often have you actually wanted
> that feature?
>
> If you want bounds that are iterables, just use min/max on them first.
> ___
> 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/QCP347S4JF4COOCCVNALCH7XBNBINF5A/
> Code of Conduct: http://python.org/psf/codeofconduct/
>
-- 
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/I7MNWPD3BPXJOWCADD6QOJBK4UYUXFX7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Chris Angelico
On Mon, Jul 6, 2020 at 2:15 AM David Mertz  wrote:
>
> This is a digression, but does anyone have a nice example IN PYTHON of 
> arriving at a NaN without going through infinity. I think Julia is right and 
> Python is wrong about '0/0', but as things are, that's not an example.
>

Not sure why "without going through infinity" is relevant, but you can
always just use float("nan") to get one, and I'm sure there are other
calculations that result in nan. It's just that 0/0 (like any other
operation that involves division by zero, including 0**-1) immediately
raises, rather than silently returning a nan.

ChrisA
___
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/YZBMLNWSJLGG7ZNTRZ4YKOCALUTXDLNQ/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Bruce Leban
On Sun, Jul 5, 2020 at 8:57 AM Steven D'Aprano  wrote:

>
> In the absense of any clear winner, my position is that NAN poisoning
> should be opt-in. We should pick the option which inconveniences people
> who want the other the least .
>
> Let's say the stdlib uses Option 1. The function doesn't need to do any
> explicit checks for NANs, so there's no problem with large integers
> overflowing, or Decimals raising ValueError, or any need to do a
> conversion to float.
>
> People who want NAN poisoning can opt-in by doing a check for NANs
> themselves, either in a wrapper function, or by testing the bounds
> *once* ahead of time and then just calling the stdlib `clamp` once they
> know they aren't NANs.


Imagine making the same statement about exceptions:

 Exceptions being raised should be opt-in.


That sounds crazy but it's not. Before exceptions were commonplace, there
were three possibilities when unreasonable operations were performed:

   - return some arbitrary or random value (not a NaN because they hadn't
   been invented);
   - and also set an "error flag" that could be checked by the caller to
   determine if something had gone wrong (but frequently was not);
   - terminate the program.

Things are much better now. Few argue that it was better before. Think of
NaN as the value equivalent of an exception. NaN poisoning is the
equivalent of the fact that any function that doesn't catch an exception
passes it through. I don't usually write code that *uses *NaNs directly. If
I want a distinguished non-numeric value, I use None or some other
sentinel. If a NaN is produced by my code it indicates a bug. NaN poisoning
increases the chance that a NaN generated somewhere won't be hidden by
later code that manipulates that value. Why would I want to suppress that?

Just as an exception can be suppressed by explicit code, Nan poisoning can
be suppressed by explicit checks. So let me rewrite your second and third
paragraphs above (recall Option 1 which you favor is ignore NaNs, and
Option 2 is NaN poisoning):

Let's say the stdlib uses Option 2. The function doesn't need to do any
> explicit checks for NANs, so there's no problem with large integers
> overflowing, or Decimals raising ValueError, causing errors that don't
> get noticed,

or any need to do a conversion to float.
>
> People who don't want NAN poisoning can opt-out by doing a check for NANs
> themselves, either in a wrapper function, or by testing the bounds
> *once* ahead of time and then not calling the stdlib `clamp` once they
> know they are NANs.


This is a better argument. People that use NaNs and expect them write code
to handle it. The rest of us don't want to be surprised by suppressed
errors.

--- Bruce
___
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/X7RGOQWB5OOEXWKYL2VVPIBZ56YAYOAO/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Federico Salerno

On 05/07/2020 16:15, Steven D'Aprano wrote:

Perhaps you should reconsider your expectations there. They do different
things because they are different functions with different signatures
and different purposes. It isn't even necessary to use min and max in
the implementation of clamp, in fact it is better not to.

Any "consistency" arguments for clamp versus min/max are weak at best.


Point taken. I don't have a strong opinion on this but I'm curious if 
others would find it useful to have iterables as acceptable types for 
bounds. Or maybe even allowing a range instance to be supplied as bounds 
(I can't think of a use case where I couldn't just pass the bounds of 
the range instead, but maybe someone else can).

___
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/UVLZ2JWSH3OND6MJ3TPDFPQMLVSP4NO7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: exception instance call should raise exception

2020-07-05 Thread Tiago Illipronti Girardi
Your original proposal appears to want this behavior:

class BaseException:
def __call__(self):
raise self

That could be expanded to something like:

class BaseException:
def __call__(self, *args):
if not args:
raise self
if len(args) > 1:
TypeError(f"{self} expects at most one argument")()  # this adds 
yet another call level
raise self from args[0]

@staticmethod
def reraise():
raise


Why, though? One would usually want to raise the exception at the same call 
level of the invalid operation, not an extra one. Also, the raise statement 
makes it clear that something went wrong, and is easily recognized by static 
code analysers.
___
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/P3AHT7LKQ5QATZN5KUJVMPUEVSYWF4OH/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread David Mertz
This is a digression, but does anyone have a nice example IN PYTHON of
arriving at a NaN without going through infinity. I think Julia is right
and Python is wrong about '0/0', but as things are, that's not an example.

On Sun, Jul 5, 2020, 12:05 PM Chris Angelico  wrote:

> On Mon, Jul 6, 2020 at 1:58 AM Steven D'Aprano 
> wrote:
> > Python makes it quite hard to get a NAN from the builtins, but other
> > languuages do not. Here's Julia:
> >
> > julia> 0/0
> > NaN
> >
> > So there's at least one NAN which means *there is no correct answer*.
>
> >>> 1e1000-1e1000
> nan
>
> ChrisA
> ___
> 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/TDIWUV4DCURDEKFMFVY2YZZWQ6ODWOFP/
> 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/NZNMC3KSCKMBGIHXDJZPE5T4RI3TO3CE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: exception instance call should raise exception

2020-07-05 Thread Soni L.



On 2020-07-05 12:58 p.m., MRAB wrote:

On 2020-07-05 14:10, Soni L. wrote:



On 2020-07-05 10:03 a.m., MRAB wrote:

On 2020-07-05 13:39, Soni L. wrote:

1. saves keywords and 2. can be passed as callables.

since there's no lambda: raise, 2 is a new feature.


How would you re-raise an exception?


just call it.


Wouldn't that just conflate raise with re-raise?


raise x vs except: raise?

just except foo: foo()





What would be the replacement for:

    raise ex from None

and so forth?


no idea. just don't use that anymore?


[snip]

___
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/SKPHKNJKLYN6QQWBEY2XIVRYANPUUS33/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Chris Angelico
On Mon, Jul 6, 2020 at 1:58 AM Steven D'Aprano  wrote:
> Python makes it quite hard to get a NAN from the builtins, but other
> languuages do not. Here's Julia:
>
> julia> 0/0
> NaN
>
> So there's at least one NAN which means *there is no correct answer*.

>>> 1e1000-1e1000
nan

ChrisA
___
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/TDIWUV4DCURDEKFMFVY2YZZWQ6ODWOFP/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread MRAB

On 2020-07-05 15:15, Steven D'Aprano wrote:
[snip]

The only differences I can see are that my implementation of clamp()
supports None as a short-hand for infinity; and that it treats NANs
according to the standard, unlike the builtin min and max, which manage
to provide the worst of both possible words: they treat NANs according
to the order of the arguments, thus satisfying nobody and annoying
everybody.

The first part is, I think, important because with the min+max idiom, if
one side is unbounded, you can just leave it out:

 min(x, 1000)  # like clamp(x, -float('inf'), 1000)

but with clamp you have to supply *something* to mean "unbounded", and
using float("inf") is not very convenient. So it's just a tiny bit of
sugar to make the function more useful.


+1 to using None.

[snip]
___
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/3GVTX4TM2Z5VZXQLBMJTJQS6S6FK76J5/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: exception instance call should raise exception

2020-07-05 Thread MRAB

On 2020-07-05 14:10, Soni L. wrote:



On 2020-07-05 10:03 a.m., MRAB wrote:

On 2020-07-05 13:39, Soni L. wrote:

1. saves keywords and 2. can be passed as callables.

since there's no lambda: raise, 2 is a new feature.


How would you re-raise an exception?


just call it.


Wouldn't that just conflate raise with re-raise?



What would be the replacement for:

    raise ex from None

and so forth?


no idea. just don't use that anymore?


[snip]
___
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/XJNVGMBPF3W5HJN5A5TLQURYR4HPBWPE/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Sat, Jul 04, 2020 at 09:11:34AM -0700, Ben Rudiak-Gould wrote:

Quoting William Kahan, one of the people who designed IEEE-754 and NANs:

> What he says there (on page 9) is
> 
> >Some familiar functions have yet to be defined for NaN . For instance 
> >max{x, y} should deliver the same result as max{y, x} but almost no 
> >implementations do that when x is NaN . There are good reasons to 
> >define max{NaN, 5} := max{5, NaN} := 5 though many would disagree.
> 
> It's clear that he's not referring to standard behavior here and I'm
> not convinced that even he believes very strongly that min and max
> should behave that way.

Are you suggesting that Kahan *doesn't* believe that min() and max() 
should be symmetric?

This is what Python does now:

py> max(float('nan'), 1)
nan
py> max(1, float('nan'))
1

That's the sort of thing Kahan is describing, and it's clear to me that 
he thinks that's a bad thing.

I will accept that treating NANs as missing values (as opposed to 
NAN-poisoning behaviour that returns a NAN if one of the arguments is a 
NAN) is open to debate. Personally, I don't think that there aren't 
many, or any, good use-cases for NAN-poisoning in this function. When we 
had this debate four years ago, I recall there was one person who 
suggested a use for it, but without going into details that I can 
recall.


> NaN means "there may be a correct answer but I don't know what it is."

That's one interpretation, but not the only one.

Python makes it quite hard to get a NAN from the builtins, but other 
languuages do not. Here's Julia:

julia> 0/0
NaN

So there's at least one NAN which means *there is no correct answer*.

In my younger days I was a NAN bigot who instisted that there was only 
one possible interpretation for NANs, but as I've gotten older I've 
accepted that treating them as *missing values* is acceptable.

(Besides, like it or not, that's what a ton of software does.)

With that interpretation, a NAN passed as the lower or upper bounds can 
be seen as another way of saying "no lower bounds" (i.e. negative 
infinity) or "no upper bounds" (i.e. positive infinity), not "some 
unknown bounds".


> For example, evaluating (x**2+3*x+1)/(x+2) at x = -2 yields NaN.

*cough*

Did you try it?

In Python it raises an exception; in Julia it returns -Inf. Substituting 
-2 gives -1/0 which under the rules of IEEE-754 should give -Inf.


> The correct answer to the problem that yielded this formula is 
> probably -1,

How do you get that conclusion?

For (x**2+3*x+1)/(x+2) to equal -1, you would have to substitute either 
x=-3 or x=-1, not -2.


py> x = -1; (x**2+3*x+1)/(x+2)
-1.0
py> x = -3; (x**2+3*x+1)/(x+2)
-1.0



[...]
> It's definitely true that if plugging in any finite or infinite number
> whatsoever in place of a NaN will yield the same result, then that
> should be the result when you plug in a NaN. For example, clamp(x,
> NaN, x) should be x for every x (even NaN), and clamp(y, NaN, x) where
> y > x should be a ValueError (or however invalid bounds are treated).

I think you are using the signature clamp(lower, value, upper) here. Is 
that right? I dislike that signature but for the sake of the argument I 
will use it in the following examples.

I agree with you that `clamp(lower=x, value=NAN, upper= x)` should 
return x. I agree that we should raise if the bounds are in reverse 
order, e.g.

clamp(lower=2, value=x, upper=1)

I trust we agree that if the value is a NAN, and the bounds are not 
equal, we should return a NAN:

clamp(1, NAN, 2)  # return a NAN

So I think we agree on all these cases.

So I think there is only one point of contention: what to do if the 
bounds are NANs?

There are two obvious, simple and reasonable behaviours:

Option 1: 

Treat a NAN bounds as *missing data*, which effectively means "there is 
no limit", i.e. as if you had passed the infinity of the appropriate 
sign for the bounds.

Option 2:

Treat a NAN bounds as invalid, or unknown, in which case you want to 
return a NAN (or an exception). This is called "NAN poisoning".

I will happily accept that people might reasonably want either 
behaviour. But unless we provide two implementations, we have to pick 
one or the other. Which should we pick?

In the absense of any clear winner, my position is that NAN poisoning 
should be opt-in. We should pick the option which inconveniences people 
who want the other the least.

Let's say the stdlib uses Option 1. The function doesn't need to do any 
explicit checks for NANs, so there's no problem with large integers 
overflowing, or Decimals raising ValueError, or any need to do a 
conversion to float.

People who want NAN poisoning can opt-in by doing a check for NANs 
themselves, either in a wrapper function, or by testing the bounds 
*once* ahead of time and then just calling the stdlib `clamp` once they 
know they aren't NANs.

If they use a wrapper function, they end up testing the bounds for NANs 
on 

[Python-ideas] Re: Access (ordered) dict by index; insert slice

2020-07-05 Thread Stephen J. Turnbull
Steven D'Aprano writes:

 > Regarding your observation that dict views behave poorly if they
 > have unhashable values, I agree, it is both odd and makes them less
 > useful. Possibly at some point between the PEP and the release of
 > the feature something changed, or perhaps it's just an oversight.

I'm not sure what you expect from views, though:

Python 3.8.3 (default, May 15 2020, 14:39:37) 
>>> set([[1]])
Traceback (most recent call last):
  File "", line 1, in 
TypeError: unhashable type: 'list'
>>> {'a' : [1]}.keys() <= {'a' : [1], 'b' : 2}.keys()
True
>>> {'a' : [1]}.values() <= {'a' : [1], 'b' : 2}.values()
Traceback (most recent call last):
  File "", line 1, in 
TypeError: '<=' not supported between instances of 'dict_values' and 
'dict_values'
>>> {'a' : [1]}.items() <= {'a' : [1], 'b' : 2}.items()
True

So all of the above are consistent with the behavior of sets, except
that items views do some part of comparisons themselves to deal with
non-hashables which is an extension to set behavior. And values views
don't pretend to be sets.  The ValuesView ABC is not derived from Set,
presumably because dict.values returns something like a multiset.

Most set operations on key and item views seem to convert to set and
where appropriate return set (which makes sense, since returning a
view would require synthesizing a dict to be the view of!)  This means
you can't do set operations (except comparisons) on items views if any
values aren't hashable.

I'm not sure what I think about this:

>>> {'a' : 1, 'b' : 2}.values() == {'b' : 2, 'a' : 1}.values()
False

That does seem less than useful.  But I guess a multiset comparison
requires an auxiliary data structure that can be sorted or a
complicated, possibly O(n^2), comparison in place.
___
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/3UBEDD3HPQ56KUI2BJRH4VVZTRZCTUXB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Stephen J. Turnbull
2qdxy4rzwzuui...@potatochowder.com writes:
 > On 2020-07-05 at 12:18:54 +0900,
 > "Stephen J. Turnbull"  wrote:
 > 
 > > Which suggests the question: Is there a commonly used equivalent for
 > > complex numbers?
 > 
 > How would that work?  Complex numbers are unordered, but I suspect that
 > you know that.

Oh, that's not a problem.  Impose one, and done.  If you insist on two
complex-parameter bounds, there's at least one interesting way to
specify a total order with a connected "region" "between" any two
complex numbers: lexicographic in (magnitude, argument).

But my question was more "what's the use case?"  So I'm not persuaded
by thinking of confining the mouse pointer to a window whose points
are represented by complex numbers.  I was more wondering if, for
example, it would be useful in working with electromagnetic waveforms,
or such applications where for some reason the complex plane is more
useful than the real one.

But let's think bigger, much bigger.  Really, clamp is a topological
concept with a bounding *set*.

What's not to love about clamp(z, Mandelbrot)? :-)
___
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/OT26JNLZTR5QPUW2EGPSRDOI562ZJ73O/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Sat, Jul 04, 2020 at 01:01:15AM +0100, MRAB wrote:

> Should it raise an exception if minimum > maximum?

I think there are only two reasonable answers to this:

- raise an exception if the lower bounds is greater than the 
  upper bounds ("errors should never pass silently");

- or Do What I Mean by swapping them if they are in the wrong
  order:

if lower > upper:
lower, upper = upper, lower


I'm +1 on raising and about +0.1 on DWIM. People who have read my 
posts on this mailing list in the past may remember that I am usually 
very suspicious of, if not hostile to, DWIM functions, but in this case 
I think it's harmless.

This is what numpy does if you get the order wrong:

py> import numpy as np
py> np.clip(5, 1, 10)  # This is correct.
5
py> np.clip(5, 10, 1)  # WOT?
10

Silently returning garbage is not, in my opinion, acceptable here.



-- 
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/NJBJQSOCXBQ5PGXIP2Y5SFBQ25K46ZLC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Sat, Jul 04, 2020 at 10:16:45AM +0200, Federico Salerno wrote:

> Yes, I'd expect ValueError if min > max or max < min.

Is there a difference between those two conditions? *wink*


> On 04/07/2020 02:03, Steven D'Aprano wrote:
> >Bottom line is that passing a NAN as the lower or upper bound should 
> >treat it as equivalent to "unbounded", that is, equivalent to ±∞. The 
> >beauty of that is that it can be implemented without explicitly 
> >testing for NANs, which involves unnecessary conversions to float, and 
> >may even raise an exception. Here is the version I use: ... Features: 
> >* uses None as a convenient alias for unbounded; * treats NANs 
> >according to the standard; * requires no explicit conversion to float 
> >or testing for NANs; * so this will work with Fractions and Decimals.
> 
> I'm not opposed to this but wouldn't the programmer expect it to behave 
> much like a shorthand of the existing min() + max()?

For regular numeric numbers, it does.

The only differences I can see are that my implementation of clamp() 
supports None as a short-hand for infinity; and that it treats NANs 
according to the standard, unlike the builtin min and max, which manage 
to provide the worst of both possible words: they treat NANs according 
to the order of the arguments, thus satisfying nobody and annoying 
everybody.

The first part is, I think, important because with the min+max idiom, if 
one side is unbounded, you can just leave it out:

min(x, 1000)  # like clamp(x, -float('inf'), 1000)

but with clamp you have to supply *something* to mean "unbounded", and 
using float("inf") is not very convenient. So it's just a tiny bit of 
sugar to make the function more useful.

I've been using it for about four years, and it's nice to have. Having a 
short-cut for clamp is a good usability feature that costs very little 
(a couple of extra pointer comparisons to test for `is None`, which is 
cheap as it comes in Python).


> Should these two 
> then be modified to exhibit the same behaviour? I'd find it inconsistent 
> if clamp() did but min() and max() didn't.

Perhaps you should reconsider your expectations there. They do different 
things because they are different functions with different signatures 
and different purposes. It isn't even necessary to use min and max in 
the implementation of clamp, in fact it is better not to.

Any "consistency" arguments for clamp versus min/max are weak at best.



-- 
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/6SLKNXMFPIH2UMR3SBQP7H2B7QXCYMUN/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: exception instance call should raise exception

2020-07-05 Thread Steven D'Aprano
On Sun, Jul 05, 2020 at 10:10:01AM -0300, Soni L. wrote:

> >What would be the replacement for:
> >
> >    raise ex from None
> >
> >and so forth?
> 
> no idea. just don't use that anymore?

So your plan is to make Python less useful, less powerful, and be unable 
to do things that it can do now? Sounds great! Not.

If you want a callable that raises:

def throw(exception, *args):
raise exception(*args)

func = lambda x: throw(ValueError, 'bad value') if x < 0 else x+1


Problem solved. The best part of this is that this function is 100% 
backwards compatible all the way back to Python 1.0, and you don't have 
to wait until Python 3.10 or 3.11 to use it.


-- 
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/FLM64YJJ6X6NWCXO7HQW6FOSA776FUS2/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: exception instance call should raise exception

2020-07-05 Thread Soni L.



On 2020-07-05 10:03 a.m., MRAB wrote:

On 2020-07-05 13:39, Soni L. wrote:

1. saves keywords and 2. can be passed as callables.

since there's no lambda: raise, 2 is a new feature.


How would you re-raise an exception?


just call it.



What would be the replacement for:

    raise ex from None

and so forth?


no idea. just don't use that anymore?



I prefer the clarity of knowing that it's raising an exception and not 
just calling. Calls usually return.



On 2020-07-05 1:15 a.m., Steven D'Aprano wrote:

On Sun, Jul 05, 2020 at 12:48:08AM -0300, Soni L. wrote:
> ValueError()() should be the same as raise ValueError() but with 
an > extra call level.

> > and raise should be deprecated.

Proposals that are given without justification should be rejected
without justification:

"No they shouldn't."

If you feel like giving reasons for these changes other than 
"because I,

Soni, say so", then I will consider the merits of those reasons before
agreeing or disagreeing with the proposal.


___
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/MFNOEEOUMRGJXM433DQQVT57S5ERM7U3/

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/D4ECM6WBYNRY2MX2FSAXI6HNNCW6L47R/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread MRAB

On 2020-07-05 10:09, Federico Salerno wrote:
[snip]
FInally, I'd like to lit another fire: given that `min()` and `max()` 
accept an arbitrary amount of arguments, and that the signature that 
seems to be preferred for the hypothetical clamp at the moment sees 
`value` as the first positional argument, should the function then 
accept iterables as values for `minimum` and `maximum`?

Something along the lines of:

clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: 
Union[Number, Iterable[Number]])

I think that's overcomplicating it. How often have you actually wanted 
that feature?


If you want bounds that are iterables, just use min/max on them first.
___
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/QCP347S4JF4COOCCVNALCH7XBNBINF5A/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: exception instance call should raise exception

2020-07-05 Thread MRAB

On 2020-07-05 13:39, Soni L. wrote:

1. saves keywords and 2. can be passed as callables.

since there's no lambda: raise, 2 is a new feature.


How would you re-raise an exception?

What would be the replacement for:

raise ex from None

and so forth?

I prefer the clarity of knowing that it's raising an exception and not 
just calling. Calls usually return.



On 2020-07-05 1:15 a.m., Steven D'Aprano wrote:

On Sun, Jul 05, 2020 at 12:48:08AM -0300, Soni L. wrote:
> ValueError()() should be the same as raise ValueError() but with an 
> extra call level.
> 
> and raise should be deprecated.


Proposals that are given without justification should be rejected
without justification:

"No they shouldn't."

If you feel like giving reasons for these changes other than "because I,
Soni, say so", then I will consider the merits of those reasons before
agreeing or disagreeing with the proposal.


___
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/MFNOEEOUMRGJXM433DQQVT57S5ERM7U3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Alex Hall
On Sun, Jul 5, 2020 at 2:36 PM Federico Salerno 
wrote:

> On the topic of NaNs: I think in the face of ambiguity, we should refuse
> the temptation to guess and raise ValueError when the values given are not
> comparable to the point of clearly determining whether `value` is or isn't
> within `minimum` and `maximum` or which of the two bounds it exceeds. It is
> the programmer's responsibility to ensure they supply arguments that make
> sense, and non-numbers should be considered exceptional behaviour: as such,
> the programmer that anticipates those kinds of values should handle them
> exceptionally.
>
+1

> About the stdlib/builtin status: `min(max(x, min_), max_)` is a common
> enough idiom for a simple enough function that I think it is definitely
> beneficial and in no way dangerous to have, and that any status other than
> builtin would incur too much overhead for something so small. I risk
> claiming that most calls to max() and min() occur in modules that do not
> `import math` (or at the very least, they occur often enough without
> `import math`), and I believe clamp(), being very similar in scope to
> those, should benefit from similar status.
>
> I don't think clamp is a common enough identifier in non-specific fields
> to disqualify its implementation as a builtin by itself. By contrast, terms
> like `min` and `max` are extremely common in pretty much all contexts, and
> yet we've all survived just fine by typing `min_` and `max_` or even
> shadowing the names altogether (which I prefer not to do, but is definitely
> an option).
>
 Has anyone suggested a .clamp method on the various numerical classes?
Since this is a convenience that's easy to do without or implement
yourself, I don't think it's important that it's super general and can
instantly be used with anything comparable.
___
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/GQGN3BYHJLCRDL4NZ2NSCI4F26TF5S4W/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: exception instance call should raise exception

2020-07-05 Thread Soni L.

1. saves keywords and 2. can be passed as callables.

since there's no lambda: raise, 2 is a new feature.

On 2020-07-05 1:15 a.m., Steven D'Aprano wrote:

On Sun, Jul 05, 2020 at 12:48:08AM -0300, Soni L. wrote:
> ValueError()() should be the same as raise ValueError() but with an 
> extra call level.
> 
> and raise should be deprecated.


Proposals that are given without justification should be rejected
without justification:

"No they shouldn't."

If you feel like giving reasons for these changes other than "because I,
Soni, say so", then I will consider the merits of those reasons before
agreeing or disagreeing with the proposal.



___
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/WZGPUJ3D6PCKMYXEXUA7W3KD4AFV5W65/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Federico Salerno
On the topic of NaNs: I think in the face of ambiguity, we should refuse 
the temptation to guess and raise ValueError when the values given are 
not comparable to the point of clearly determining whether `value` is or 
isn't within `minimum` and `maximum` or which of the two bounds it 
exceeds. It is the programmer's responsibility to ensure they supply 
arguments that make sense, and non-numbers should be considered 
exceptional behaviour: as such, the programmer that anticipates those 
kinds of values should handle them exceptionally.


About the name: clamp seems to be the most favoured name and the 
discussion convinced me it's the one that should make it to the eventual 
proposal.


About the stdlib/builtin status: `min(max(x, min_), max_)` is a common 
enough idiom for a simple enough function that I think it is definitely 
beneficial and in no way dangerous to have, and that any status other 
than builtin would incur too much overhead for something so small. I 
risk claiming that most calls to max() and min() occur in modules that 
do not `import math` (or at the very least, they occur often enough 
without `import math`), and I believe clamp(), being very similar in 
scope to those, should benefit from similar status.
I don't think clamp is a common enough identifier in non-specific fields 
to disqualify its implementation as a builtin by itself. By contrast, 
terms like `min` and `max` are extremely common in pretty much all 
contexts, and yet we've all survived just fine by typing `min_` and 
`max_` or even shadowing the names altogether (which I prefer not to do, 
but is definitely an option).


FInally, I'd like to lit another fire: given that `min()` and `max()` 
accept an arbitrary amount of arguments, and that the signature that 
seems to be preferred for the hypothetical clamp at the moment sees 
`value` as the first positional argument, should the function then 
accept iterables as values for `minimum` and `maximum`?

Something along the lines of:

clamp(value: Number, minimum: Union[Number, Iterable[Number]], maximum: 
Union[Number, Iterable[Number]])

___
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/YUOCR36ZBUGUDTHJ3HDBIEYFSUVHCXX7/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Jeff Allen


On 05/07/2020 05:39, Steven D'Aprano wrote:

On Sun, Jul 05, 2020 at 12:18:54PM +0900, Stephen J. Turnbull wrote:


  > and I'd like to toss a possible `coerce`

Here my issue is that for me the *target* of a coercion should be a
"single thing", which could be a type, but might also be a scalar. ...

No, I agree. In computing, coerce nearly always means to coerce to a
type, not to coerce to some range of values.


"bound", or probably "bounded" (for the same reason we have "sorted").

"clamp" and "clip" sound to me like things you do to a waveform (with 
Schottky diodes!), so it works for me but I'm not sure it travels well. 
Elsewhere in the thread (tree) we're already calling arg[1:2] "bounds", 
so reading this as "the value of x bound[ed] by the range -1 to +5" 
seems natural.


Or "limited" possibly?

I'm +0 on the idea FWIW. I also find it difficult to read, but I tend to 
in-line it as ifs, in part for clarity.


Jeff Allen

___
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/T7HC7CNOZAHZHLKB36OR3772MAICWIUG/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Access (ordered) dict by index; insert slice

2020-07-05 Thread Christopher Barker
On Wed, Jul 1, 2020 at 8:37 AM Stestagg  wrote:

>  1. ordered collections that have some set-like operators added for
> convenience, (conceptually, if not exactly, class ...(Set, Sequence):)  but
> are missing a single method full Sequence interface (__getitem__)
> or
>  2. Sets that happen to have a stable/deterministic element order
>
> My opinion is that, as of Python 3.7, they are effectively 1, even if the
> isinstance hooks haven't been updated.  I can see why people may think of
> them as 2. I don't have any desire to change minds on this :)
>
> Semantic quibbling aside, My opinions/reasoning on the different options
> are the following:
>

as long as we are semantic quibbling (1) is not quite right -- they don't
"have some set-like operators, they have the full set of them, and they
they ARE Sets:

In [44]: d = {"this": 4, "that": 23}


In [45]: isinstance(d.keys(), Set)

Out[45]: True

But see another recent thread on this list - they don't have all the same
methods as the builtin set() type. But the ABC doesn't specify those, so
they don't need to.

However, that doesn't mean that it's somehow critical for them not to grow
some extra functionality -- they would still be Sets.

* Add numeric `__getitem__` to `dict_*` view classes:

> +1  - This restores code that used to work in python 2, and makese some
> things a bit easier.  The O(n) behaviour is not ideal, but in my opinion is
> an acceptable compromise
>

well, not really -- it only lets some things work like they did in Py2:
most code I've ported from py2 to py3 that I needed to wrap list() around
the views needed more than indexing -- I usually needed the list itself to
be a persistent, mutable Sequence, not a view.

I'm +1 on on this, ;cause why not? but honestly , the only good use case
I've seen is random.choice() -- and while I've needed that, I can't say
I've needed it often.


> * Add new method to dict class:
> -1 This doesn't feel like a good solution to me.  Rather than continue to
> argue about the justification for why, let's just say its a personal
> judgement
>

wqe neither, gut it's not just a personal taste -- a getter wouldn't work
with random.choice, the only known use case :-)  -- unless the new method
returned a Sequence-like view that could be indexed.

Granted, it would allow an easier way to get a random item, but not as
slick as:

random.choice(a_dict.items())

I think it was Oscar that pointed out that repeated indexing of a view
would be worse performance wise than making a proper list -- so that
*might* be considered an attractive nuisance.

-CHB

-- 
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/RMFV2PJBFXI5QFT3L3K6G45VG4QGZVIY/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Steven D'Aprano
On Sun, Jul 05, 2020 at 06:35:38PM +1200, Greg Ewing wrote:

> All in all, I think "clamp" is the best term for this.

+1

-- 
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/6NNMNZSALHQKJVNMPZZWDGT63XDXCYLU/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Add builtin function for min(max())

2020-07-05 Thread Greg Ewing

On 5/07/20 4:39 pm, Steven D'Aprano wrote:

Complex numbers represent points on a plane; it is very common in
graphical toolkits to need to clamp an object to within some window or
other region of the plane,


But graphical toolkits don't treat points as complex numbers.
The question is whether there is a conventional generalisation
of clamp() used in complex analysis. There isn't one that I
know of.


so that you don't (e.g.) drag your object
outside of the document, or position it somewhere off screen where it is
impossible for the user to click on.


I wouldn't call this operation "clipping", though -- see below.


There are two standard terms for this function: clamp and clip,
depending on whether you view the operation as squashing the value into
a range or cutting off the bits that don't fit.


The notion of clipping in computer graphics is not really the same
thing. If you're drawing a point clipped to a window, and it's
outside the window, then you skip drawing it altogether, you don't
move it to the boundary of the window. And if you're drawing a line
that's partly inside and partly outside the window, you need to cut
off the part that's outside -- but you can't do that by clamping
the outside point to the window, you need to do something more
complicated.

Another data point: In OpenGL documentation, the operation of
limiting colour values or texture coordinates to be within a
certain range is called "clamping".

All in all, I think "clamp" is the best term for this.

--
Greg
___
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/VLSAYZ7GSIUNT7FGN5ZV4SDXX7RAFSQC/
Code of Conduct: http://python.org/psf/codeofconduct/