Re: [Python-ideas] Optional parameters without default value

2017-03-10 Thread Todd
On Mar 10, 2017 02:42, "Terry Reedy"  wrote:

On 3/2/2017 3:03 AM, Serhiy Storchaka wrote:

> Function implemented in Python can have optional parameters with default
> value. It also can accept arbitrary number of positional and keyword
> arguments if use var-positional or var-keyword parameters (*args and
> **kwargs).
>

In other words, Python signature possibilities are already unusually
complex.


But there is no way to declare an optional parameter that
> don't have default value.
>
... [moving the following up]

> I propose to add a new syntax for optional parameters. If the argument
> corresponding to the optional parameter without default value is not
> specified, the parameter takes no value.

-1

Being able to do this would violate what I believe is the fundamental
precondition for python-coded function bodies: all parameters are bound to
an object (so that using a parameter name is never a NameError); all
arguments are used exactly once in the binding process; the binding is done
without ambiguity (or resort to disambiguation rules).  Calls that prevent
establishment of this precondition result in an exception.

This precondition is normal in computing languages.  I believe that all of
the ~20 languages I have used over decades have had it.  In any case, I
believe it is important in understanding Python signatures and calls, and
that there would need to be a strong reason to alter this precondition.
(Stronger than I judge the one given here to be.)


-1 also

Having used a language extensively that does not enforce this precondition
(MATLAB), I agree that not being able count on arguments existing makes
handing function arguments much more difficult.
___
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] Optional parameters without default value

2017-03-03 Thread Sven R. Kunze

On 03.03.2017 16:24, Yury Selivanov wrote:

TBH I think that optional parameters isn't a problem requiring new
syntax. We probably do need syntax for positional-only arguments
(since we already have  them in a way), but optional parameters
can be solved easily without a new syntax.

Syntax like:

1. def a(?foo),
2. def a(foo=pass),
3. def a([foo]),

will complicate the language too much IMO.

Yury


I never really encountered a real-world use where I would have needed 
this kind of parameter declaration ability.


It's like the ++ operator of C which comes in pre- and postfix notation.
It's really cool to teach the nuances of it. And to create exam 
questions using it. And to confuse students. But completely unnecessary 
in real-life code.


Sven
___
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] Optional parameters without default value

2017-03-03 Thread Ethan Furman

On 03/03/2017 06:29 AM, Victor Stinner wrote:


An alternative for generated signature of multiple optional arguments
is "bytearray([source[, encoding[, errors]]])", but I'm not a big fan
of nested [...],


But that's not the same thing.

  bytearry([source,] [encoding,] [errors])

says that each argument can be passed without passing any others.

  bytearray([source [, encoding [,errors]]])

says that in order to pass encoding, source must also be specified.

At least, that's what it says to me.

--
~Ethan~
___
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] Optional parameters without default value

2017-03-03 Thread Yury Selivanov

TBH I think that optional parameters isn't a problem requiring new
syntax. We probably do need syntax for positional-only arguments
(since we already have  them in a way), but optional parameters
can be solved easily without a new syntax.

Syntax like:

1. def a(?foo),
2. def a(foo=pass),
3. def a([foo]),

will complicate the language too much IMO.

Yury

On 2017-03-03 9:29 AM, Victor Stinner wrote:

Since yet another sentinel singleton sounds like a dead end, I suggest
to use [arg=value] syntax and require a default value in the
prototype, as currently required for *optional keyword* arguments.

"[...]" syntax for optional parameter is commonly used in Python
documentation (but the exact syntax for multiple optional arguments is
different than what I propose, see below). I already saw this syntax
for optional parameters in C and PHP languages at least.

Python prototype of the standard library and their generated signature:

 def bool([x=False])
 => bool([x])

 def bytearray([source=None], [encoding=None], errors="strict")
 => bytearray([source], [encoding], [errors])

 # in practice, default value of 'default' parameter (and maybe also 'key'?)
 # will more likely be a custom sentinel
 def sum(iterable, *args, [key=None], [default=None])
 => sum(iterable, *args, [key], [default])

 # "/" is an hypothetical marker for positional-only arguments
 def str.replace(old, new, [count=-1], /)
 => str.replace(old, new, [count], /)

 def pickle.dump(obj, file, [protocol=3], *, fix_imports=True)
 => pickle.dump(obj, file, [protocol], *, fix_imports=True)

An alternative for generated signature of multiple optional arguments
is "bytearray([source[, encoding[, errors]]])", but I'm not a big fan
of nested [...], IMHO it's harder to read. And I like the idea of
having a signature closer to the actual Python code.


Invalid syntaxes raising SyntaxError:

* no default value: "def func([x]): ..."
* optional arguments before *args: "def func(arg, [opt=None], *args):"

In practice, calling a function without an optional argument or pass
the (private?) sentinel as the optional argument should have the same
behaviour. Each module is free to decide how the sentinel is exposed
or not. For example, the inspect module has 2 sentinels: _empty is
exposed as Signature.empty and Parameter.empty, whereas _void is
private.

If I understood correctly, Argument Clinic already supports optional
positional arguments, and so doesn't need to be changed.


I'm not sure that it's useful for optional keyword-only arguments:

def func(*, [arg=None])
=> func(*, [arg])

The only difference with optional keyword-only arguments with a
default value is the signature:

def func(*, arg=None)
=> func(*, arg=None)

See also the discussion on converting the bisect functions to Argument
Clinic and issues with the generated signature:
http://bugs.python.org/issue28754

Victor
___
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] Optional parameters without default value

2017-03-03 Thread Victor Stinner
Since yet another sentinel singleton sounds like a dead end, I suggest
to use [arg=value] syntax and require a default value in the
prototype, as currently required for *optional keyword* arguments.

"[...]" syntax for optional parameter is commonly used in Python
documentation (but the exact syntax for multiple optional arguments is
different than what I propose, see below). I already saw this syntax
for optional parameters in C and PHP languages at least.

Python prototype of the standard library and their generated signature:

def bool([x=False])
=> bool([x])

def bytearray([source=None], [encoding=None], errors="strict")
=> bytearray([source], [encoding], [errors])

# in practice, default value of 'default' parameter (and maybe also 'key'?)
# will more likely be a custom sentinel
def sum(iterable, *args, [key=None], [default=None])
=> sum(iterable, *args, [key], [default])

# "/" is an hypothetical marker for positional-only arguments
def str.replace(old, new, [count=-1], /)
=> str.replace(old, new, [count], /)

def pickle.dump(obj, file, [protocol=3], *, fix_imports=True)
=> pickle.dump(obj, file, [protocol], *, fix_imports=True)

An alternative for generated signature of multiple optional arguments
is "bytearray([source[, encoding[, errors]]])", but I'm not a big fan
of nested [...], IMHO it's harder to read. And I like the idea of
having a signature closer to the actual Python code.


Invalid syntaxes raising SyntaxError:

* no default value: "def func([x]): ..."
* optional arguments before *args: "def func(arg, [opt=None], *args):"

In practice, calling a function without an optional argument or pass
the (private?) sentinel as the optional argument should have the same
behaviour. Each module is free to decide how the sentinel is exposed
or not. For example, the inspect module has 2 sentinels: _empty is
exposed as Signature.empty and Parameter.empty, whereas _void is
private.

If I understood correctly, Argument Clinic already supports optional
positional arguments, and so doesn't need to be changed.


I'm not sure that it's useful for optional keyword-only arguments:

def func(*, [arg=None])
=> func(*, [arg])

The only difference with optional keyword-only arguments with a
default value is the signature:

def func(*, arg=None)
=> func(*, arg=None)

See also the discussion on converting the bisect functions to Argument
Clinic and issues with the generated signature:
http://bugs.python.org/issue28754

Victor
___
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] Optional parameters without default value

2017-03-03 Thread Sven R. Kunze

On 03.03.2017 14:06, Victor Stinner wrote:

2017-03-03 6:13 GMT+01:00 Mike Miller :

Agreed, I've rarely found a need for a "second None" or sentinel either, but
once every few years I do.  So, this use case doesn't seem to be common
enough to devote special syntax or a keyword to from my perspective.

The question here is how to have an official support of this feature
in inspect.signature().

If we go to the special value (singleton) way, Ellispis doesn't work
neither since a few modules use Ellipsis for legit use case. Recent
user: the typing module for "Callable[[arg, ...], result]".


Exactly.

So, it should be obvious to you, that introducing "official" support 
leads yet to an endless chain of "but I would need yet another None" 
because we already use [None, Undefined, NotUsed, Ellipsis, , 
pypi project] in our projects.


Having every project rolling their own "NotDefined" makes it completely 
incompatible to each other. So, it's not possible to plug in return 
values to other functions and gets bitten.



Not providing an "official" solution, solves the matter.


Best,
Sven
___
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] Optional parameters without default value

2017-03-03 Thread Victor Stinner
2017-03-03 6:13 GMT+01:00 Mike Miller :
> Agreed, I've rarely found a need for a "second None" or sentinel either, but
> once every few years I do.  So, this use case doesn't seem to be common
> enough to devote special syntax or a keyword to from my perspective.

The question here is how to have an official support of this feature
in inspect.signature().

If we go to the special value (singleton) way, Ellispis doesn't work
neither since a few modules use Ellipsis for legit use case. Recent
user: the typing module for "Callable[[arg, ...], result]".

Victor
___
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] Optional parameters without default value

2017-03-02 Thread Matthias Bussonnier
On Thu, Mar 2, 2017 at 9:13 PM, Mike Miller  wrote:

>
> It is a built-in singleton so rarely known that you will almost never
> encounter code with it, so you'll have it all to yourself.  Even on a python
> mailing list, in a thread about sentinels/singletons, it will not be
> mentioned.  Some may "consider it unnatural."  It is…
>
> …
>
> … (hint)
>
> … (wait for it)
>
> …
>

<3 the suspens ! I got it before the end though !

I'll  tell you my secret as well. I have my own
(https://pypi.python.org/pypi/undefined)
I've set it up to raise on __eq__ or __bool__ to enforce checking for identity.

-- 
M
___
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] Optional parameters without default value

2017-03-02 Thread Mike Miller
Agreed, I've rarely found a need for a "second None" or sentinel either, but 
once every few years I do.  So, this use case doesn't seem to be common enough 
to devote special syntax or a keyword to from my perspective.


But, I'll let you know my secret.  I don't make my own sentinel, but rather use 
another singleton that is built-in already.  And if you squint just right, it 
even makes sense.


It is a built-in singleton so rarely known that you will almost never encounter 
code with it, so you'll have it all to yourself.  Even on a python mailing list, 
in a thread about sentinels/singletons, it will not be mentioned.  Some may 
"consider it unnatural."  It is…


…

… (hint)

… (wait for it)

…

>>> Ellipsis
Ellipsis


Don't think I've ever needed a "third None" but if I did I'd probably try an 
enum instead.


-Mike



On 2017-03-02 15:02, Barry Warsaw wrote:

On Mar 02, 2017, at 06:37 PM, Brett Cannon wrote:


So to me, there's actually two things being discussed. Do we need another
sentinel to handle the "None is valid" case, and do we want syntax to more
clearly delineate optional arguments?


No, and no (IMHO).

-Barry


___
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] Optional parameters without default value

2017-03-02 Thread Victor Stinner
In my code, I commonly use a NOT_SET singleton used as default value. I
like this name for the test:

if arg is NOT_SET: ...

;-)

I use that when I want to behave differently when None is passed. And yes,
I have such code.

Victor

Le 2 mars 2017 9:36 AM, "M.-A. Lemburg"  a écrit :

On 02.03.2017 09:03, Serhiy Storchaka wrote:
> Function implemented in Python can have optional parameters with default
> value. It also can accept arbitrary number of positional and keyword
> arguments if use var-positional or var-keyword parameters (*args and
> **kwargs). But there is no way to declare an optional parameter that
> don't have default value. Currently you need to use the sentinel idiom
> for implementing this:
>
> _sentinel = object()
> def get(store, key, default=_sentinel):
> if store.exists(key):
> return store.retrieve(key)
> if default is _sentinel:
> raise LookupError
> else:
> return default
>
> There are drawback of this:
>
> * Module's namespace is polluted with sentinel's variables.
>
> * You need to check for the sentinel before passing it to other function
> by accident.
>
> * Possible name conflicts between sentinels for different functions of
> the same module.
>
> * Since the sentinel is accessible outside of the function, it possible
> to pass it to the function.
>
> * help() of the function shows reprs of default values. "foo(bar= object at 0xb713c698>)" looks ugly.
>
>
> I propose to add a new syntax for optional parameters. If the argument
> corresponding to the optional parameter without default value is not
> specified, the parameter takes no value. As well as the "*" prefix means
> "arbitrary number of positional parameters", the prefix "?" can mean
> "single optional parameter".
>
> Example:
>
> def get(store, key, ?default):
> if store.exists(key):
> return store.retrieve(key)
> try:
> return default
> except NameError:
> raise LookupError

Why a new syntax ? Can't we just have a pre-defined sentinel
singleton NoDefault and use that throughout the code (and also
special case it in argument parsing/handling)?

def get(store, key, default=NoDefault):
if store.exists(key):
return store.retrieve(key)
...

I added a special singleton NotGiven to our mxTools long ago for
this purpose.

--
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
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] Optional parameters without default value

2017-03-02 Thread Barry Warsaw
On Mar 02, 2017, at 06:37 PM, Brett Cannon wrote:

>So to me, there's actually two things being discussed. Do we need another
>sentinel to handle the "None is valid" case, and do we want syntax to more
>clearly delineate optional arguments?

No, and no (IMHO).

-Barry


pgpULmSfZJDcd.pgp
Description: OpenPGP digital signature
___
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] Optional parameters without default value

2017-03-02 Thread Abe Dillon
I honestly don't understand the reasoning behind using anything more
complex than a built-in sentinel value. Just plop "NotGiven" or whatever in
the built-ins and say "it's like None, but for the specific case of
optional parameters with no default value". Why prohibit people from
passing it to functions? That would just be an explicit way of saying: "I'm
not giving you a value for this parameter". Anything more than that is just
paranoia that people won't know how to use it in an expected manner.

I'm -0.5 on this proposal. It seems like it would add more confusion for
dubious benefit.

On Thu, Mar 2, 2017 at 2:07 PM, MRAB  wrote:

> On 2017-03-02 08:03, Serhiy Storchaka wrote:
>
>> Function implemented in Python can have optional parameters with default
>> value. It also can accept arbitrary number of positional and keyword
>> arguments if use var-positional or var-keyword parameters (*args and
>> **kwargs). But there is no way to declare an optional parameter that
>> don't have default value. Currently you need to use the sentinel idiom
>> for implementing this:
>>
>> _sentinel = object()
>> def get(store, key, default=_sentinel):
>>  if store.exists(key):
>>  return store.retrieve(key)
>>  if default is _sentinel:
>>  raise LookupError
>>  else:
>>  return default
>>
>> There are drawback of this:
>>
>> * Module's namespace is polluted with sentinel's variables.
>>
>> * You need to check for the sentinel before passing it to other function
>> by accident.
>>
>> * Possible name conflicts between sentinels for different functions of
>> the same module.
>>
>> * Since the sentinel is accessible outside of the function, it possible
>> to pass it to the function.
>>
>> * help() of the function shows reprs of default values. "foo(bar=> object at 0xb713c698>)" looks ugly.
>>
>>
>> I propose to add a new syntax for optional parameters. If the argument
>> corresponding to the optional parameter without default value is not
>> specified, the parameter takes no value. As well as the "*" prefix means
>> "arbitrary number of positional parameters", the prefix "?" can mean
>> "single optional parameter".
>>
>> Example:
>>
>> def get(store, key, ?default):
>>  if store.exists(key):
>>  return store.retrieve(key)
>>  try:
>>  return default
>>  except NameError:
>>  raise LookupError
>>
>> Alternative syntaxes:
>>
>> * "=" not followed by an expression: "def get(store, key, default=)".
>>
>> * The "del" keyword: "def get(store, key, del default)".
>>
>> This feature is orthogonal to supporting positional-only parameters.
>> Optional parameters without default value can be positional-or-keyword,
>> keyword-only or positional-only (if the latter is implemented).
>>
>> Could you use 'pass' as the pseudo-sentinel?
>
> Maybe also allow " is pass"/" is not pass" as tests for
> absence/presence.
>
>
> ___
> 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] Optional parameters without default value

2017-03-02 Thread MRAB

On 2017-03-02 08:03, Serhiy Storchaka wrote:

Function implemented in Python can have optional parameters with default
value. It also can accept arbitrary number of positional and keyword
arguments if use var-positional or var-keyword parameters (*args and
**kwargs). But there is no way to declare an optional parameter that
don't have default value. Currently you need to use the sentinel idiom
for implementing this:

_sentinel = object()
def get(store, key, default=_sentinel):
 if store.exists(key):
 return store.retrieve(key)
 if default is _sentinel:
 raise LookupError
 else:
 return default

There are drawback of this:

* Module's namespace is polluted with sentinel's variables.

* You need to check for the sentinel before passing it to other function
by accident.

* Possible name conflicts between sentinels for different functions of
the same module.

* Since the sentinel is accessible outside of the function, it possible
to pass it to the function.

* help() of the function shows reprs of default values. "foo(bar=)" looks ugly.


I propose to add a new syntax for optional parameters. If the argument
corresponding to the optional parameter without default value is not
specified, the parameter takes no value. As well as the "*" prefix means
"arbitrary number of positional parameters", the prefix "?" can mean
"single optional parameter".

Example:

def get(store, key, ?default):
 if store.exists(key):
 return store.retrieve(key)
 try:
 return default
 except NameError:
 raise LookupError

Alternative syntaxes:

* "=" not followed by an expression: "def get(store, key, default=)".

* The "del" keyword: "def get(store, key, del default)".

This feature is orthogonal to supporting positional-only parameters.
Optional parameters without default value can be positional-or-keyword,
keyword-only or positional-only (if the latter is implemented).


Could you use 'pass' as the pseudo-sentinel?

Maybe also allow " is pass"/" is not pass" as tests for 
absence/presence.


___
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] Optional parameters without default value

2017-03-02 Thread Brett Cannon
On Thu, 2 Mar 2017 at 08:58 Ethan Furman  wrote:

> On 03/02/2017 08:13 AM, Joao S. O. Bueno wrote:
>
> > Is it just me that find that having the un-assigned parameter raise
> > NameError (or other exception) much more cumbersome than
> > havign a sentinel-value?
>
> No.  While clever, the hassle of figuring out if you have a parameter
> clearly outweighs the benefit of avoiding a
> sentinel value.
>
> It would be a different story if we had exception-catching expressions.  ;)
>

I don't like the NameError solution either.

What I would like to know is how common is this problem? That will help
frame whether this warrants syntax or just providing a sentinel in some
module in the stdlib that people can use (e.g. functools.NotGiven; I do
prefer MAL's naming of the sentinel). Sticking it into a module would help
minimize people from using it in places where None is entirely acceptable
and not confusing the whole community when people suddenly start peppering
their code with NotGiven instead of None for default values.

And if this is really common enough to warrant syntax, then I would want:

  def foo(a, b, opt?): ...

to represent that 'opt' is optional and if not provided by the user then it
is given the value of NotGiven (or None if we are just after a syntactic
shortcut to say "this argument is optional").

So to me, there's actually two things being discussed. Do we need another
sentinel to handle the "None is valid" case, and do we want syntax to more
clearly delineate optional arguments?
___
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] Optional parameters without default value

2017-03-02 Thread Joao S. O. Bueno
Is it just me that find that having the un-assigned parameter raise
NameError (or other exception) much more cumbersome than
havign a sentinel-value?

I definitely don't find it clever - for one, a common default parameter -
sentinel or not, can be replaced in  a single line of code by an
expression using "if" or "or", while the Exception raising variant
require a whole try-except block.

So, while I like the idea of simplifying the "sentinel idiom", I don't
find any suggestion here useful so far.

Maybe something to the stlib that would allow something along:

from paramlib import NoDefault, passed

def myfunc(a, b, count=NoDefault):
 if not passed(count):
  ...
 else:
  ...

That would simplify a bit the sentinel pattern, do not pollute the
namespace, and don't  need any new syntax, (and still allow "if"
expressions without a full try/except block)

On 2 March 2017 at 12:04, M.-A. Lemburg  wrote:
> On 02.03.2017 14:08, Serhiy Storchaka wrote:
>> On 02.03.17 12:04, M.-A. Lemburg wrote:
>>> This is not new syntax, nor is it a keyword. It's only a
>>> new singleton and it is well usable outside of function
>>> declarations as well, e.g. for class attributes which are
>>> not yet initialized (and which can accept None as value).
>>
>> If it is not a keyword, it could be used in expressions, e.g. assigned
>> to a variable or passed to a function. It could be monkey-patched or
>> hidden by accident (as True and False in Python 2).
>
> Yes, sure.
>
> My proposal was just to address the problems of
> changing Python syntax and making it possible to define
> positional only arguments in Python functions/methods in
> a backwards compatible way.
>
> The same could be had by adding a C function proxy to Python
> which then takes care of the error handling, since we already
> have the logic for C functions via PyArg_ParseTuple*().
> A decorator could then apply the proxy as needed or ignore this
> for older Python versions without breaking compatibility
> (or a PyPI extension could provide the same proxy logic for
> older versions).
>
> FWIW: I don't think the use case for positional only arguments
> to Python functions is strong enough to warrant breaking
> backwards compatibility by introducing new syntax.
>
> --
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Experts (#1, Mar 02 2017)
 Python Projects, Coaching and Consulting ...  http://www.egenix.com/
 Python Database Interfaces ...   http://products.egenix.com/
 Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> 
>
> ::: We implement business ideas - efficiently in both time and costs :::
>
>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>Registered at Amtsgericht Duesseldorf: HRB 46611
>http://www.egenix.com/company/contact/
>   http://www.malemburg.com/
>
> ___
> 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] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 14:08, Serhiy Storchaka wrote:
> On 02.03.17 12:04, M.-A. Lemburg wrote:
>> This is not new syntax, nor is it a keyword. It's only a
>> new singleton and it is well usable outside of function
>> declarations as well, e.g. for class attributes which are
>> not yet initialized (and which can accept None as value).
> 
> If it is not a keyword, it could be used in expressions, e.g. assigned
> to a variable or passed to a function. It could be monkey-patched or
> hidden by accident (as True and False in Python 2).

Yes, sure.

My proposal was just to address the problems of
changing Python syntax and making it possible to define
positional only arguments in Python functions/methods in
a backwards compatible way.

The same could be had by adding a C function proxy to Python
which then takes care of the error handling, since we already
have the logic for C functions via PyArg_ParseTuple*().
A decorator could then apply the proxy as needed or ignore this
for older Python versions without breaking compatibility
(or a PyPI extension could provide the same proxy logic for
older versions).

FWIW: I don't think the use case for positional only arguments
to Python functions is strong enough to warrant breaking
backwards compatibility by introducing new syntax.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
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] Optional parameters without default value

2017-03-02 Thread Paul Moore
On 2 March 2017 at 14:24, Steven D'Aprano  wrote:
> I like this! If the caller doesn't provide a value, the parameter
> remains unbound and any attempt to look it up will give a NameError or
> UnboundLocalError.

Hmm. But those exceptions currently indicate with almost 100%
certainty, a programming error (usually a mis-spelled name or a
control flow error). The proposal makes them a normal runtime
behaviour, in certain circumstances. What would happen if you
mis-spelled the name of the optional parameter? You'd get a NameError
from using the wrong name, rather than from the user not supplying a
value.

I don't think re-using NameError is a good idea here.
Paul
___
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] Optional parameters without default value

2017-03-02 Thread Stephan Houben
So let's turn the question around:
Since Coverity is user-extensible (and supports Python),
can you write a Coverity rule which detects wrong use of some given
NoDefault sentinel
with a useful level of reliability?

Actually I feel this should be feasible.

(And if so, mission accomplished?)

Stephan

2017-03-02 15:18 GMT+01:00 Chris Angelico :
> On Fri, Mar 3, 2017 at 1:15 AM, Stephan Houben  wrote:
>> I do not think such a magic linter can be written.
>> It seems an obvious instance of the Halting Problem to me.
>
> Yeah it can :) Static analysis is pretty impressive these days. Check
> out tools like Coverity, which can analyse your source code and tell
> you that, at this point in the code, it's possible for x to be >100
> and y to have only 100 bytes of buffer, and then you index past a
> buffer. You could do the same to track down the origin of an object in
> Python.
>
> However, I think this is far from an ideal solution to the problem.
>
> ChrisA
> ___
> 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] Optional parameters without default value

2017-03-02 Thread Steven D'Aprano
On Thu, Mar 02, 2017 at 10:03:29AM +0200, Serhiy Storchaka wrote:

> I propose to add a new syntax for optional parameters. If the argument 
> corresponding to the optional parameter without default value is not 
> specified, the parameter takes no value. As well as the "*" prefix means 
> "arbitrary number of positional parameters", the prefix "?" can mean 
> "single optional parameter".

I like this! If the caller doesn't provide a value, the parameter 
remains unbound and any attempt to look it up will give a NameError or 
UnboundLocalError.

The only question is, how often do we need a function with optional 
parameter that don't have a default? I've done it a few times, and used 
the sentinel trick, but I'm not sure this is common enough to need 
support from the compiler.

It is a really clever solution though.


 
> Alternative syntaxes:
> 
> * "=" not followed by an expression: "def get(store, key, default=)".

Too easy to happen by accident if you accidently forget to add the 
default, or delete it.


> * The "del" keyword: "def get(store, key, del default)".

This feature has nothing to do with del.


-- 
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] Optional parameters without default value

2017-03-02 Thread Chris Angelico
On Fri, Mar 3, 2017 at 1:15 AM, Stephan Houben  wrote:
> I do not think such a magic linter can be written.
> It seems an obvious instance of the Halting Problem to me.

Yeah it can :) Static analysis is pretty impressive these days. Check
out tools like Coverity, which can analyse your source code and tell
you that, at this point in the code, it's possible for x to be >100
and y to have only 100 bytes of buffer, and then you index past a
buffer. You could do the same to track down the origin of an object in
Python.

However, I think this is far from an ideal solution to the problem.

ChrisA
___
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] Optional parameters without default value

2017-03-02 Thread Steven D'Aprano
On Thu, Mar 02, 2017 at 01:08:42PM +0100, M.-A. Lemburg wrote:

> Sorry for the confusion. NoDefault would be usable just like
> any other singleton.

But that is exactly the trouble! We already have a singleton to indicate 
"no default" -- that is spelled None.

Occasionally, we need to allow None as a legitimate value, not just as a 
sentinel indicating a missing value. So the current practice is to 
create your own sentinel. That just pushes the problem back one more 
level: what happens when you have a function where the new NoDefault 
singleton is a legitimate value? You need a *third* sentinel value. And 
a fourth, and so on...


> There would only be one case where it would cause an exception,
> namely when you declare a parameter as having NoDefault as value.
> This would trigger special logic in the argument parsing code to
> disallow using that parameter as keyword parameter.

Did you miss Serhiy's comment?

Optional parameters without default value can be 
positional-or-keyword, keyword-only or positional-only (if 
the latter is implemented).

It doesn't matter whether the parameter is positional or keyword, or how 
you call the function:

f(NoDefault)
f(x=NoDefault)

the effect should be the same.

But I think that's the wrong solution. If it were a good solution, we 
should just say that None is the "No Default" value and prohibit passing 
None as an argument. But of course we can't do that, even if we were 
willing to break backwards compatibility. There are good reasons for 
passing None as a legitimate value, and there will be good reasons for 
passing NoDefault as a legitimate value too.

The problem with having a special value that means "no value" is that it 
actually is a value. Serhiy has a good idea here: cut the gordian knot 
by *avoiding having a value at all*. The parameter name remains unbound. 
If you don't pass a value for the optional parameter, and then try to 
access the parameter, you get a NameError exception! That's really 
clever and I like it a lot.



-- 
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] Optional parameters without default value

2017-03-02 Thread Paul Moore
On 2 March 2017 at 13:11, Serhiy Storchaka  wrote:
> On 02.03.17 14:20, Paul Moore wrote:
>>
>> So I guess I'm +0.5 on the proposed "positional only parameters"
>> syntax, and -1 on any form of new language-defined sentinel value.
>
>
> My proposition is not about "positional-only parameters".

Bah, sorry. I'm getting muddled between two different threads. I'm not
having a good day, it seems :-(

On the proposed feature, I don't like any of the proposed syntaxes
(I'd rate "default=" with no value as the least bad, but I don't like
it much; "default?" as opposed to "?default" is a possible option).
I'm not convinced that the version using the new syntax is any easier
to read or understand - the sentinel pattern is pretty well-understood
by now, and a built-in replacement would need to result in noticeably
simpler code (which this proposal doesn't seem to).

Agreed that the help() output is ugly. It would of course be possible
to give the sentinel a nicer repr, if you wanted:

>>> class Sentinel(object):
... def __repr__(self): return ""
...
>>> _sentinel = Sentinel()
>>> def get(store, key, default=_sentinel):
...   pass
...
>>> help(get)
Help on function get in module __main__:

get(store, key, default=)

Whether it's worth doing this depends on the application, of course
(just like it's possible to hide the name of the sentinel if it
matters sufficiently).

Paul
___
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] Optional parameters without default value

2017-03-02 Thread Serhiy Storchaka

On 02.03.17 14:20, Paul Moore wrote:

So I guess I'm +0.5 on the proposed "positional only parameters"
syntax, and -1 on any form of new language-defined sentinel value.


My proposition is not about "positional-only parameters".


___
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] Optional parameters without default value

2017-03-02 Thread Chris Angelico
On Thu, Mar 2, 2017 at 11:22 PM, Stephan Houben  wrote:
> Would this also apply if we provide or capture the keyword arguments using
> ** ?
>
> I.e.
> f(**{"x": NoDict})
>
> (lambda **kw: kw)(x=NoDict)
>
> In that case I see a problem with this idiom:
>
> newdict = dict(**olddict)
>
> This would now start throwing errors in case any of the values of olddict
> was NoDefault.
>

You shouldn't be returning NoDefault anywhere, though, so the only
problem is that the error is being reported in the wrong place. If
this were to become syntax, enhanced linters could track down exactly
where NoDefault came from, and report the error, because that's really
where the bug is.

ChrisA
___
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] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 13:22, Stephan Houben wrote:
> OK, I get it, I think.
> 
> I presume it is really the object identity which matters, not the syntax,
> so:
> 
> y = NoDefault
> f(x=y)
> 
> would be equally an error.

Yes.

> Would this also apply if we provide or capture the keyword arguments using
> ** ?
> 
> I.e.
> f(**{"x": NoDict})

I think you meant NoDefault here.

> (lambda **kw: kw)(x=NoDict)
> 
> In that case I see a problem with this idiom:
> 
> newdict = dict(**olddict)
> 
> This would now start throwing errors in case any of the values of olddict
> was NoDefault.

Continuing the example, this case would throw an error as well:

kwargs = {'x': NoDefault)

f(**kwargs)
e.g. TypeError('x is a positional only parameter')

However, only because f "declared" x as optional positional
parameter.

If you'd pass the same dict to a function g as in:

def g(x):
pass

g(**kwargs)

it would not raise an exception, since Python functions always
allow passing in keyword parameters for positional parameters
(unlike C functions, which only allow this if configured that way).

> Stephan
> 
> 
> 
> 2017-03-02 13:08 GMT+01:00 M.-A. Lemburg :
> 
>> On 02.03.2017 12:31, Stephan Houben wrote:
>>> I am not sure if I fully understand the proposal then.
>>>
>>> NoDefault would be special syntax so that this would be disallowed:
>>>
>>> f(NoDefault)
>>>
>>> but this would be allowed:
>>> def f(x=NoDefault):
>>>...
>>>
>>> and also this:
>>>
>>> x is NoDefault
>>>
>>> So this would seem to require an exhaustive list of syntactic contexts
>>> in which NoDefault is allowed. I mean, can I do:
>>>
>>> x = NoDefault
>>>
>>> ?
>>>
>>> I observe that I can always get to the underlying NoDefault object in
>> this
>>> way:
>>>
>>> (lambda x=NoDefault:x)()
>>>
>>> So what happens if I do:
>>>
>>> f((lambda x=NoDefault:x)())
>>>
>>> ?
>>
>> Sorry for the confusion. NoDefault would be usable just like
>> any other singleton.
>>
>> There would only be one case where it would cause an exception,
>> namely when you declare a parameter as having NoDefault as value.
>> This would trigger special logic in the argument parsing code to
>> disallow using that parameter as keyword parameter.
>>
>> Example:
>>
>> def f(x=NoDefault):
>> # x is an optional positional parameter
>> if x is NoDefault:
>> # x was not passed in as parameter
>> ...
>> else:
>> # x was provided as parameter
>> ...
>>
>> These would all work fine:
>>
>> f()
>> f(1)
>> f(None)
>>
>> This would trigger an exception in the argument parsing code:
>>
>> f(x=NoDefault)
>>
>> e.g. TypeError('x is a positional only parameter')
>>
>> This would not trigger an exception:
>>
>> f(NoDefault)
>>
>> since x is not being used as keyword parameter and the
>> function f may want to pass the optional positional parameter
>> down to other functions with optional positional paramters
>> as well.
>>
>> Is this clearer now ?
>>
>> Note: The name of the singleton could be something else
>> as well, e.g. NoKeywordParameter :-)
>>
>>> Stephan
>>>
>>>
>>> 2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :
>>>
 On 02.03.2017 11:22, Stephan Houben wrote:
> In cases like this I would recommend creating the sentinel yourself:
>
> NoDefault = object()
>
> def get(store, key, default=NoDefault):
>if default is NoDefault:
> # do something
>
> You can arrange to not export NoDefault so that the client code cannot
 even
> access
> the sentinel value.

 Yes, I know... I've been using the mxTools NotGiven since 1998.

> This is strictly preferable over having yet another global
> value meaning "no value", since that just moves the goal posts:
> clients will complain they cannot pass in a default=NoDefault and get
 back
> NoDefault.

 Not really. NoDefault would mean: no value provided, not that
 you don't want a value. As a result, passing NoDefault would
 not be allowed, since then you'd be providing a value :-)

> Stephan
>
>
> 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
>
>> On 02.03.2017 10:06, Serhiy Storchaka wrote:
>>> On 02.03.17 10:36, M.-A. Lemburg wrote:
 Why a new syntax ? Can't we just have a pre-defined sentinel
 singleton NoDefault and use that throughout the code (and also
 special case it in argument parsing/handling)?

 def get(store, key, default=NoDefault):
 if store.exists(key):
 return store.retrieve(key)
 ...
>>>
>>> This means adding a new syntax. NoDefault should be a keyword (we can
>>> reuse existing keyword couldn't be used in expression), and it should
 be
>>> accepted only in the specific context of declaring function
>> parameter.
>>
>> This is not new syntax, nor is it a keyword. It's only a
>> new singleton and it is well usable 

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread Ivan Levkivskyi
On 2 March 2017 at 13:20, Paul Moore  wrote:

> On 2 March 2017 at 11:31, Stephan Houben  wrote:
> > NoDefault would be special syntax so that this would be disallowed:
> >
> > f(NoDefault)
>
> [...]
>
> So I guess I'm +0.5 on the proposed "positional only parameters"
> syntax, and -1 on any form of new language-defined sentinel value.
>
>
This is also my opinion.

--
Ivan
___
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] Optional parameters without default value

2017-03-02 Thread Stephan Houben
OK, I get it, I think.

I presume it is really the object identity which matters, not the syntax,
so:

y = NoDefault
f(x=y)

would be equally an error.

Would this also apply if we provide or capture the keyword arguments using
** ?

I.e.
f(**{"x": NoDict})

(lambda **kw: kw)(x=NoDict)

In that case I see a problem with this idiom:

newdict = dict(**olddict)

This would now start throwing errors in case any of the values of olddict
was NoDefault.

Stephan



2017-03-02 13:08 GMT+01:00 M.-A. Lemburg :

> On 02.03.2017 12:31, Stephan Houben wrote:
> > I am not sure if I fully understand the proposal then.
> >
> > NoDefault would be special syntax so that this would be disallowed:
> >
> > f(NoDefault)
> >
> > but this would be allowed:
> > def f(x=NoDefault):
> >...
> >
> > and also this:
> >
> > x is NoDefault
> >
> > So this would seem to require an exhaustive list of syntactic contexts
> > in which NoDefault is allowed. I mean, can I do:
> >
> > x = NoDefault
> >
> > ?
> >
> > I observe that I can always get to the underlying NoDefault object in
> this
> > way:
> >
> > (lambda x=NoDefault:x)()
> >
> > So what happens if I do:
> >
> > f((lambda x=NoDefault:x)())
> >
> > ?
>
> Sorry for the confusion. NoDefault would be usable just like
> any other singleton.
>
> There would only be one case where it would cause an exception,
> namely when you declare a parameter as having NoDefault as value.
> This would trigger special logic in the argument parsing code to
> disallow using that parameter as keyword parameter.
>
> Example:
>
> def f(x=NoDefault):
> # x is an optional positional parameter
> if x is NoDefault:
> # x was not passed in as parameter
> ...
> else:
> # x was provided as parameter
> ...
>
> These would all work fine:
>
> f()
> f(1)
> f(None)
>
> This would trigger an exception in the argument parsing code:
>
> f(x=NoDefault)
>
> e.g. TypeError('x is a positional only parameter')
>
> This would not trigger an exception:
>
> f(NoDefault)
>
> since x is not being used as keyword parameter and the
> function f may want to pass the optional positional parameter
> down to other functions with optional positional paramters
> as well.
>
> Is this clearer now ?
>
> Note: The name of the singleton could be something else
> as well, e.g. NoKeywordParameter :-)
>
> > Stephan
> >
> >
> > 2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :
> >
> >> On 02.03.2017 11:22, Stephan Houben wrote:
> >>> In cases like this I would recommend creating the sentinel yourself:
> >>>
> >>> NoDefault = object()
> >>>
> >>> def get(store, key, default=NoDefault):
> >>>if default is NoDefault:
> >>> # do something
> >>>
> >>> You can arrange to not export NoDefault so that the client code cannot
> >> even
> >>> access
> >>> the sentinel value.
> >>
> >> Yes, I know... I've been using the mxTools NotGiven since 1998.
> >>
> >>> This is strictly preferable over having yet another global
> >>> value meaning "no value", since that just moves the goal posts:
> >>> clients will complain they cannot pass in a default=NoDefault and get
> >> back
> >>> NoDefault.
> >>
> >> Not really. NoDefault would mean: no value provided, not that
> >> you don't want a value. As a result, passing NoDefault would
> >> not be allowed, since then you'd be providing a value :-)
> >>
> >>> Stephan
> >>>
> >>>
> >>> 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
> >>>
>  On 02.03.2017 10:06, Serhiy Storchaka wrote:
> > On 02.03.17 10:36, M.-A. Lemburg wrote:
> >> Why a new syntax ? Can't we just have a pre-defined sentinel
> >> singleton NoDefault and use that throughout the code (and also
> >> special case it in argument parsing/handling)?
> >>
> >> def get(store, key, default=NoDefault):
> >> if store.exists(key):
> >> return store.retrieve(key)
> >> ...
> >
> > This means adding a new syntax. NoDefault should be a keyword (we can
> > reuse existing keyword couldn't be used in expression), and it should
> >> be
> > accepted only in the specific context of declaring function
> parameter.
> 
>  This is not new syntax, nor is it a keyword. It's only a
>  new singleton and it is well usable outside of function
>  declarations as well, e.g. for class attributes which are
>  not yet initialized (and which can accept None as value).
> 
>  The only special casing would be in function call
>  parameter parsing to signal errors when the parameter
>  is used as keyword parameter.
> 
>  --
>  Marc-Andre Lemburg
>  eGenix.com
> 
>  Professional Python Services directly from the Experts (#1, Mar 02
> 2017)
> >>> Python Projects, Coaching and Consulting ...
> http://www.egenix.com/
> >>> Python Database Interfaces ...
> http://products.egenix.com/
> >>> Plone/Zope Database Interfaces ...
> http://zope.egenix.com/
>  

Re: [Python-ideas] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 12:31, Stephan Houben wrote:
> I am not sure if I fully understand the proposal then.
> 
> NoDefault would be special syntax so that this would be disallowed:
> 
> f(NoDefault)
> 
> but this would be allowed:
> def f(x=NoDefault):
>...
> 
> and also this:
> 
> x is NoDefault
> 
> So this would seem to require an exhaustive list of syntactic contexts
> in which NoDefault is allowed. I mean, can I do:
> 
> x = NoDefault
> 
> ?
> 
> I observe that I can always get to the underlying NoDefault object in this
> way:
> 
> (lambda x=NoDefault:x)()
> 
> So what happens if I do:
> 
> f((lambda x=NoDefault:x)())
> 
> ?

Sorry for the confusion. NoDefault would be usable just like
any other singleton.

There would only be one case where it would cause an exception,
namely when you declare a parameter as having NoDefault as value.
This would trigger special logic in the argument parsing code to
disallow using that parameter as keyword parameter.

Example:

def f(x=NoDefault):
# x is an optional positional parameter
if x is NoDefault:
# x was not passed in as parameter
...
else:
# x was provided as parameter
...

These would all work fine:

f()
f(1)
f(None)

This would trigger an exception in the argument parsing code:

f(x=NoDefault)

e.g. TypeError('x is a positional only parameter')

This would not trigger an exception:

f(NoDefault)

since x is not being used as keyword parameter and the
function f may want to pass the optional positional parameter
down to other functions with optional positional paramters
as well.

Is this clearer now ?

Note: The name of the singleton could be something else
as well, e.g. NoKeywordParameter :-)

> Stephan
> 
> 
> 2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :
> 
>> On 02.03.2017 11:22, Stephan Houben wrote:
>>> In cases like this I would recommend creating the sentinel yourself:
>>>
>>> NoDefault = object()
>>>
>>> def get(store, key, default=NoDefault):
>>>if default is NoDefault:
>>> # do something
>>>
>>> You can arrange to not export NoDefault so that the client code cannot
>> even
>>> access
>>> the sentinel value.
>>
>> Yes, I know... I've been using the mxTools NotGiven since 1998.
>>
>>> This is strictly preferable over having yet another global
>>> value meaning "no value", since that just moves the goal posts:
>>> clients will complain they cannot pass in a default=NoDefault and get
>> back
>>> NoDefault.
>>
>> Not really. NoDefault would mean: no value provided, not that
>> you don't want a value. As a result, passing NoDefault would
>> not be allowed, since then you'd be providing a value :-)
>>
>>> Stephan
>>>
>>>
>>> 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
>>>
 On 02.03.2017 10:06, Serhiy Storchaka wrote:
> On 02.03.17 10:36, M.-A. Lemburg wrote:
>> Why a new syntax ? Can't we just have a pre-defined sentinel
>> singleton NoDefault and use that throughout the code (and also
>> special case it in argument parsing/handling)?
>>
>> def get(store, key, default=NoDefault):
>> if store.exists(key):
>> return store.retrieve(key)
>> ...
>
> This means adding a new syntax. NoDefault should be a keyword (we can
> reuse existing keyword couldn't be used in expression), and it should
>> be
> accepted only in the specific context of declaring function parameter.

 This is not new syntax, nor is it a keyword. It's only a
 new singleton and it is well usable outside of function
 declarations as well, e.g. for class attributes which are
 not yet initialized (and which can accept None as value).

 The only special casing would be in function call
 parameter parsing to signal errors when the parameter
 is used as keyword parameter.

 --
 Marc-Andre Lemburg
 eGenix.com

 Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/
 
>> 

 ::: We implement business ideas - efficiently in both time and costs :::

eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
Registered at Amtsgericht Duesseldorf: HRB 46611
http://www.egenix.com/company/contact/
   http://www.malemburg.com/

 ___
 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] Optional parameters without default value

2017-03-02 Thread Stephan Houben
I am not sure if I fully understand the proposal then.

NoDefault would be special syntax so that this would be disallowed:

f(NoDefault)

but this would be allowed:
def f(x=NoDefault):
   ...

and also this:

x is NoDefault

So this would seem to require an exhaustive list of syntactic contexts
in which NoDefault is allowed. I mean, can I do:

x = NoDefault

?

I observe that I can always get to the underlying NoDefault object in this
way:

(lambda x=NoDefault:x)()

So what happens if I do:

f((lambda x=NoDefault:x)())

?

Stephan


2017-03-02 12:15 GMT+01:00 M.-A. Lemburg :

> On 02.03.2017 11:22, Stephan Houben wrote:
> > In cases like this I would recommend creating the sentinel yourself:
> >
> > NoDefault = object()
> >
> > def get(store, key, default=NoDefault):
> >if default is NoDefault:
> > # do something
> >
> > You can arrange to not export NoDefault so that the client code cannot
> even
> > access
> > the sentinel value.
>
> Yes, I know... I've been using the mxTools NotGiven since 1998.
>
> > This is strictly preferable over having yet another global
> > value meaning "no value", since that just moves the goal posts:
> > clients will complain they cannot pass in a default=NoDefault and get
> back
> > NoDefault.
>
> Not really. NoDefault would mean: no value provided, not that
> you don't want a value. As a result, passing NoDefault would
> not be allowed, since then you'd be providing a value :-)
>
> > Stephan
> >
> >
> > 2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :
> >
> >> On 02.03.2017 10:06, Serhiy Storchaka wrote:
> >>> On 02.03.17 10:36, M.-A. Lemburg wrote:
>  Why a new syntax ? Can't we just have a pre-defined sentinel
>  singleton NoDefault and use that throughout the code (and also
>  special case it in argument parsing/handling)?
> 
>  def get(store, key, default=NoDefault):
>  if store.exists(key):
>  return store.retrieve(key)
>  ...
> >>>
> >>> This means adding a new syntax. NoDefault should be a keyword (we can
> >>> reuse existing keyword couldn't be used in expression), and it should
> be
> >>> accepted only in the specific context of declaring function parameter.
> >>
> >> This is not new syntax, nor is it a keyword. It's only a
> >> new singleton and it is well usable outside of function
> >> declarations as well, e.g. for class attributes which are
> >> not yet initialized (and which can accept None as value).
> >>
> >> The only special casing would be in function call
> >> parameter parsing to signal errors when the parameter
> >> is used as keyword parameter.
> >>
> >> --
> >> Marc-Andre Lemburg
> >> eGenix.com
> >>
> >> Professional Python Services directly from the Experts (#1, Mar 02 2017)
> > Python Projects, Coaching and Consulting ...  http://www.egenix.com/
> > Python Database Interfaces ...   http://products.egenix.com/
> > Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> >> 
> 
> >>
> >> ::: We implement business ideas - efficiently in both time and costs :::
> >>
> >>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> >> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
> >>Registered at Amtsgericht Duesseldorf: HRB 46611
> >>http://www.egenix.com/company/contact/
> >>   http://www.malemburg.com/
> >>
> >> ___
> >> 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/
> >
>
> --
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Experts (#1, Mar 02 2017)
> >>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
> >>> Python Database Interfaces ...   http://products.egenix.com/
> >>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> 
>
> ::: We implement business ideas - efficiently in both time and costs :::
>
>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>Registered at Amtsgericht Duesseldorf: HRB 46611
>http://www.egenix.com/company/contact/
>   http://www.malemburg.com/
>
>
___
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] Optional parameters without default value

2017-03-02 Thread Stephan Houben
In cases like this I would recommend creating the sentinel yourself:

NoDefault = object()

def get(store, key, default=NoDefault):
   if default is NoDefault:
# do something

You can arrange to not export NoDefault so that the client code cannot even
access
the sentinel value.

This is strictly preferable over having yet another global
value meaning "no value", since that just moves the goal posts:
clients will complain they cannot pass in a default=NoDefault and get back
NoDefault.

Stephan


2017-03-02 11:04 GMT+01:00 M.-A. Lemburg :

> On 02.03.2017 10:06, Serhiy Storchaka wrote:
> > On 02.03.17 10:36, M.-A. Lemburg wrote:
> >> Why a new syntax ? Can't we just have a pre-defined sentinel
> >> singleton NoDefault and use that throughout the code (and also
> >> special case it in argument parsing/handling)?
> >>
> >> def get(store, key, default=NoDefault):
> >> if store.exists(key):
> >> return store.retrieve(key)
> >> ...
> >
> > This means adding a new syntax. NoDefault should be a keyword (we can
> > reuse existing keyword couldn't be used in expression), and it should be
> > accepted only in the specific context of declaring function parameter.
>
> This is not new syntax, nor is it a keyword. It's only a
> new singleton and it is well usable outside of function
> declarations as well, e.g. for class attributes which are
> not yet initialized (and which can accept None as value).
>
> The only special casing would be in function call
> parameter parsing to signal errors when the parameter
> is used as keyword parameter.
>
> --
> Marc-Andre Lemburg
> eGenix.com
>
> Professional Python Services directly from the Experts (#1, Mar 02 2017)
> >>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
> >>> Python Database Interfaces ...   http://products.egenix.com/
> >>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/
> 
>
> ::: We implement business ideas - efficiently in both time and costs :::
>
>eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
> D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
>Registered at Amtsgericht Duesseldorf: HRB 46611
>http://www.egenix.com/company/contact/
>   http://www.malemburg.com/
>
> ___
> 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] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 10:06, Serhiy Storchaka wrote:
> On 02.03.17 10:36, M.-A. Lemburg wrote:
>> Why a new syntax ? Can't we just have a pre-defined sentinel
>> singleton NoDefault and use that throughout the code (and also
>> special case it in argument parsing/handling)?
>>
>> def get(store, key, default=NoDefault):
>> if store.exists(key):
>> return store.retrieve(key)
>> ...
> 
> This means adding a new syntax. NoDefault should be a keyword (we can
> reuse existing keyword couldn't be used in expression), and it should be
> accepted only in the specific context of declaring function parameter.

This is not new syntax, nor is it a keyword. It's only a
new singleton and it is well usable outside of function
declarations as well, e.g. for class attributes which are
not yet initialized (and which can accept None as value).

The only special casing would be in function call
parameter parsing to signal errors when the parameter
is used as keyword parameter.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
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] Optional parameters without default value

2017-03-02 Thread Ivan Levkivskyi
On 2 March 2017 at 09:36, M.-A. Lemburg  wrote:

> On 02.03.2017 09:03, Serhiy Storchaka wrote:
> > Function implemented in Python can have optional parameters with default
> [...]
>
Why a new syntax ? Can't we just have a pre-defined sentinel
> singleton NoDefault and use that throughout the code (and also
> special case it in argument parsing/handling)?
>

I think for the sane reason that we didn't add Undefined to PEP 484 and PEP
526:
Having "another kind of None" will cause code everywhere to expect it.
(Plus Guido didn't like it)

--
Ivan
___
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] Optional parameters without default value

2017-03-02 Thread M.-A. Lemburg
On 02.03.2017 09:03, Serhiy Storchaka wrote:
> Function implemented in Python can have optional parameters with default
> value. It also can accept arbitrary number of positional and keyword
> arguments if use var-positional or var-keyword parameters (*args and
> **kwargs). But there is no way to declare an optional parameter that
> don't have default value. Currently you need to use the sentinel idiom
> for implementing this:
> 
> _sentinel = object()
> def get(store, key, default=_sentinel):
> if store.exists(key):
> return store.retrieve(key)
> if default is _sentinel:
> raise LookupError
> else:
> return default
> 
> There are drawback of this:
> 
> * Module's namespace is polluted with sentinel's variables.
> 
> * You need to check for the sentinel before passing it to other function
> by accident.
> 
> * Possible name conflicts between sentinels for different functions of
> the same module.
> 
> * Since the sentinel is accessible outside of the function, it possible
> to pass it to the function.
> 
> * help() of the function shows reprs of default values. "foo(bar= object at 0xb713c698>)" looks ugly.
> 
> 
> I propose to add a new syntax for optional parameters. If the argument
> corresponding to the optional parameter without default value is not
> specified, the parameter takes no value. As well as the "*" prefix means
> "arbitrary number of positional parameters", the prefix "?" can mean
> "single optional parameter".
> 
> Example:
> 
> def get(store, key, ?default):
> if store.exists(key):
> return store.retrieve(key)
> try:
> return default
> except NameError:
> raise LookupError

Why a new syntax ? Can't we just have a pre-defined sentinel
singleton NoDefault and use that throughout the code (and also
special case it in argument parsing/handling)?

def get(store, key, default=NoDefault):
if store.exists(key):
return store.retrieve(key)
...

I added a special singleton NotGiven to our mxTools long ago for
this purpose.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Mar 02 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
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] Optional parameters without default value

2017-03-02 Thread Serhiy Storchaka
Function implemented in Python can have optional parameters with default 
value. It also can accept arbitrary number of positional and keyword 
arguments if use var-positional or var-keyword parameters (*args and 
**kwargs). But there is no way to declare an optional parameter that 
don't have default value. Currently you need to use the sentinel idiom 
for implementing this:


_sentinel = object()
def get(store, key, default=_sentinel):
if store.exists(key):
return store.retrieve(key)
if default is _sentinel:
raise LookupError
else:
return default

There are drawback of this:

* Module's namespace is polluted with sentinel's variables.

* You need to check for the sentinel before passing it to other function 
by accident.


* Possible name conflicts between sentinels for different functions of 
the same module.


* Since the sentinel is accessible outside of the function, it possible 
to pass it to the function.


* help() of the function shows reprs of default values. "foo(bar=object at 0xb713c698>)" looks ugly.



I propose to add a new syntax for optional parameters. If the argument 
corresponding to the optional parameter without default value is not 
specified, the parameter takes no value. As well as the "*" prefix means 
"arbitrary number of positional parameters", the prefix "?" can mean 
"single optional parameter".


Example:

def get(store, key, ?default):
if store.exists(key):
return store.retrieve(key)
try:
return default
except NameError:
raise LookupError

Alternative syntaxes:

* "=" not followed by an expression: "def get(store, key, default=)".

* The "del" keyword: "def get(store, key, del default)".

This feature is orthogonal to supporting positional-only parameters. 
Optional parameters without default value can be positional-or-keyword, 
keyword-only or positional-only (if the latter is implemented).


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