Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default values in enum struct-variants #4109

Closed
EricLBuehler opened this issue Apr 23, 2024 · 4 comments · Fixed by #4158
Closed

Default values in enum struct-variants #4109

EricLBuehler opened this issue Apr 23, 2024 · 4 comments · Fixed by #4158

Comments

@EricLBuehler
Copy link

Hello everyone,

Thank you for your great work here. Our project makes extensive use of struct enum variants. However, we have many variants which should have default values: some of those variants are Option<...> and should default to None if they are not specified. This behavior would be similar to the kwargs in functions, where a default is used if the value is not specified.

Currently, for this enum:

#[pyclass]
enum Thing
  A {
    x: Option<i32>,
    y: i32,
    z: i32,
  }
}

I would use it like this: Thing.A(x=None, y=5, z=1).

However, setting x to None manually makes the code more verbose. It would be easier for the user to do the following:

#[pyclass]
enum Thing
  A {
    #[pyo3(default = None)] # <----- Add something like this?
    x: Option<i32>,
    y: i32,
    #[pyo3(default = 1)]
    z: i32
  }
}

Which would be used like this: Thing.A(y=5) where x=None and z=1.

I am not sure how difficult this is to implement, but it would be much appreciated to have this feature!

@Icxolu
Copy link
Contributor

Icxolu commented Apr 27, 2024

How about allowing #[pyo3(signature = ...)] on complex enum variants to specify the constructor signature? Like so:

#[pyclass]
enum Thing
  #[pyo3(signature = (x = None, y = 0, z = 1)]
  A {
    x: Option<i32>,
    y: i32,
    z: i32,
  }
}

This would be comparable to building the class hierarchi manuelly and gives the same control (default, pos/kw only args, ...) as a the constructor for a #[pyclass] struct would. We would also be able to reuse the existing attribute implementation from #[pyfunction]/#[pymethods]. I've experimented with that idea over here Icxolu@3e2c41b

@EricLBuehler
Copy link
Author

@Icxolu, I think that looks great! Do you plan to open a PR?

@Icxolu
Copy link
Contributor

Icxolu commented Apr 28, 2024

Thanks! Glad you like it. Yes, if people think the syntax and functionality proposed above is workable I'll open a PR from that. Given that #[pyo3(signature = ...] is currently only supported on functions (and is most intuitively understand there), I think I'll wait for a few more opinions whether we should reuse it here, or if we perhaps should rename it in this position
(#[pyo3(constructor = ...)], or something like that could also be an option) to make clear what the signature refers to.

@wyfo
Copy link
Contributor

wyfo commented Apr 29, 2024

I really like it too. And actually, I think it could also make sense to extend this feature to regular struct, to auto-generate constructors in a kind of dataclass-like fashion (but not necessarily in the same PR).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants