On Fri, Aug 6, 2021 at 9:59 PM Steven D'Aprano <st...@pearwood.info> wrote:
> > def fib(0):
> >     return 0
> >
> > def fib(1):
> >     return 1
> >
> > def fib(n):
> >     return fib(n-1) + fib(n-2)
>
> I think that there is something rather disturbing about writing a
> function definition with a constant literal as parameter. It looks wrong
> and I'm sure it's going to confuse beginners.

Agreed, but that's because Python behaves differently.

But we already have a way to have a function-ish thing that then
changes behaviour: a property's .setter/.deleter modifiers. Borrowing
an idea from that:

@multidispatch
def fib(n): return fib(n-1) + fib(n-2)
@fib.specialize(n=0)
def fib(n): return 0
@fib.specialize(n=1)
def fib(n): return 1

I'm not really a fan, but (a) it does avoid the "literal as parameter"
problem, and (b) it fits Python's syntax.

> If we did allow the use of literals as parameters, what would happen if
> we ran some other code in between the cases of the function?
>
>     def fib(0):
>         return 0
>
>     print("suprise!")
>
>     def fib(1):
>         return 1
>
>
> We would, apparently, have two distinct modes:
>
> - sometimes re-defining a function replaces the previous binding;
>
> - but other times, it extends the function with a new case.
>
> What are the rules for each?

Agreed. Use of a dedicated specialization operation would avoid this
problem. Obviously you wouldn't normally want to do it, but if you
did, the behaviour in between those steps would be well-defined:
specializations not yet applied would not be used, and the function
would execute using the generic form.

(Also, I don't think you'd ever want to do it, but you could have a
specialization in a different scope from the generic one. The
decorator would attach the specialization to the generic.)

> > def allow_entry({"name": "Bob"}):
> >     return "Bob is not allowed in ever!"
>
> I don't know how to interpret that syntax. Does that mean `allow_entry`
> takes a single argument, which much be a dictionary with a single key,
> 'name'?
>
>     result = allow_entry({'name': 'Bob'})
>     assert result = "Bob is not allowed in ever!"
>
> If that's not what you mean, then how would I write a function that
> *actually does* literally match the dict `{'name': 'Bob'}`?

Presumably the behaviour would be the same as the match statement.

https://www.python.org/dev/peps/pep-0622/#mapping-patterns

And that's where any proposal based on current syntax is going to fall
down. It's easy enough to build something like singledispatch, but
much much harder to make something that can handle the full
flexibility of match statements. So you're left with two options: a
simpler version that lets you build up the patterns from multiple
functions, or the full-power version that has a single master function
that can do the dispatching.

To be quite honest, I would usually just write it as a single function
with a match statement in it. But there are definitely times when I've
wanted to be able to build up pattern matching in a more declarative
way (think of what can be done with Flask's request routing, for
instance), and maybe there'd be enough to justify something like that.

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

Reply via email to