PyO3 / pyo3

Rust bindings for the Python interpreter
https://pyo3.rs
Apache License 2.0
12.06k stars 744 forks source link

Destructure arguments in function signatures #4231

Open nickdrozd opened 4 months ago

nickdrozd commented 4 months ago

I would like to destructure compound types in function signatures:

type CompoundType = (u64, u64);

#[pyfunction]
pub fn function((arg1, arg2): CompoundType) {}

But this is currently not supported:

error: destructuring in arguments is not supported
  --> src/lib.rs:39:17
   |
39 | pub fn function((arg1, arg2): CompoundType) {}
   |                 ^^^^^^^^^^^^
davidhewitt commented 4 months ago

While I'm open to this in principle, what would the argument be called on the Python side? At the moment we use the single identifier of the variable as the python argument name.

We could require something like a #[pyo3(name = "foo")] annotation on this pattern argument, I guess. I've wanted the ability to change the Python name of arguments in the past e.g. for unused arguments:

#[pyfunction]
fn bar(#[pyo3(name = "foo")] _foo: Foo) {
   // _foo is never used
}

So maybe with the requirement of needing a Python name annotation, this would be possible. Other opinions welcome!

alex commented 4 months ago

It's worth noting that Python used to support unpacking tuples in function signatures, and it was removed in Python 3. From that perspective I think it may add more confusion?

On Mon, Jun 3, 2024 at 1:40 PM David Hewitt @.***> wrote:

While I'm open to this in principle, what would the argument be called on the Python side? At the moment we use the single identifier of the variable as the python argument name.

We could require something like a #[pyo3(name = "foo")] annotation on this pattern argument, I guess. I've wanted the ability to change the Python name of arguments in the past e.g. for unused arguments:

[pyfunction]fn bar(#[pyo3(name = "foo")] _foo: Foo) {

// _foo is never used}

So maybe with the requirement of needing a Python name annotation, this would be possible. Other opinions welcome!

— Reply to this email directly, view it on GitHub https://github.com/PyO3/pyo3/issues/4231#issuecomment-2145776566, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAAGBDQ7V7LPF4CLJINX3DZFSTA7AVCNFSM6AAAAABIWSEI7SVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNBVG43TMNJWGY . You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- All that is necessary for evil to succeed is for good people to do nothing.

davidhewitt commented 4 months ago

That's a very good point. It's also quite easy to just move the destructuring into the first line of the function, so it's not like this requires a difficult workaround...

mejrs commented 3 months ago

I've wanted this to make it easier to work with newtypes but also ran into "then what do we get argument names from" problem. I would prefer an additional line inside the function over something like #[pyo3(name = "foo")]. I'm really not a fan of those.