Title: Add a `match_class!` macro · Issue #771 · RustPython/RustPython · GitHub
Open Graph Title: Add a `match_class!` macro · Issue #771 · RustPython/RustPython
X Title: Add a `match_class!` macro · Issue #771 · RustPython/RustPython
Description: Summary Add a match_class! macro for implementing behavior that varies based on the built-in type of an object. Detailed Explanation Doing this currently with downcast is a bit awkward. Because it consumes the Rc, you have two options: C...
Open Graph Description: Summary Add a match_class! macro for implementing behavior that varies based on the built-in type of an object. Detailed Explanation Doing this currently with downcast is a bit awkward. Because it ...
X Description: Summary Add a match_class! macro for implementing behavior that varies based on the built-in type of an object. Detailed Explanation Doing this currently with downcast is a bit awkward. Because it ...
Opengraph URL: https://github.com/RustPython/RustPython/issues/771
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Add a `match_class!` macro","articleBody":"## Summary\r\n\r\nAdd a `match_class!` macro for implementing behavior that varies based on the built-in type of an object.\r\n\r\n## Detailed Explanation\r\n\r\nDoing this currently with `downcast` is a bit awkward. Because it consumes the `Rc`,\r\nyou have two options:\r\n\r\n1. Clone the object and then do a series of `if`s.\r\n\r\n```rust\r\nimpl PyFloat {\r\n fn eq(self: PyRef\u003cSelf\u003e, other: PyObjectRef, vm: \u0026VirtualMachine) -\u003e PyResult {\r\n if let Some(i @ PyInt { .. }) = other.clone().downcast() {\r\n Ok(PyInt::new(\u0026self.value + i.as_bigint()).into_ref(vm))\r\n } else if let Some(f @ PyFloat { .. }) = other.downcast() {{\r\n let output = self.value + f.value.to_bigint().unwrap();\r\n Ok(PyFloat::new(output))\r\n } else {\r\n Ok(vm.ctx.not_implemented())\r\n }\r\n }\r\n}\r\n```\r\n\r\n2. Use the returned `Err(obj)` of `downcast` to avoid the clone.\r\n\r\n```rust\r\nmatch other.downcast() {\r\n Ok(i @ PyInt { ..}) =\u003e {\r\n Ok(PyInt::new(\u0026self.value + ).into_ref(vm))\r\n },\r\n Err(obj) =\u003e match obj.downcast() {\r\n Ok(f @ PyFloat { .. }) =\u003e {\r\n let output = self.value + f.value.to_bigint().unwrap();\r\n Ok(PyFloat::new(output))\r\n },\r\n _ =\u003e Ok(vm.ctx.not_implemented()),\r\n }\r\n}\r\n```\r\n\r\nThis avoids a pointless clone at the cost of adding undesirable rightward drift. What we really want is to be able to use a `match`-like syntax that expands to the efficient version above:\r\n\r\n```rust\r\nimpl PyFloat {\r\n fn eq(self: PyRef\u003cSelf\u003e, other: PyObjectRef, vm: \u0026VirtualMachine) -\u003e PyResult {\r\n match_object!(other,\r\n i @ PyInt { .. } =\u003e {\r\n Ok(PyInt::new(\u0026self.value + i.as_bigint()).into_ref(vm))\r\n },\r\n f @ PyFloat { .. } =\u003e {\r\n let output = self.value + f.value.to_bigint().unwrap();\r\n Ok(PyFloat::new(output))\r\n },\r\n _ =\u003e Ok(vm.ctx.not_implemented()),\r\n )\r\n }\r\n}\r\n``` \r\n\r\n## Drawbacks, Rationale, and Alternatives\r\n\r\nThe main drawback is that it is another macro. It should be very straightforward to implement and to understand though.\r\n\r\n## Unresolved Questions\r\n\r\nWill allowing a full pattern in each match clause encourage making struct fields public, when they really should not be? An alternative would be to just allow the type name in each match arm.\r\n","author":{"url":"https://github.com/OddCoincidence","@type":"Person","name":"OddCoincidence"},"datePublished":"2019-03-31T22:32:58.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":6},"url":"https://github.com/771/RustPython/issues/771"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:29854429-534a-def5-4f21-2d7167282d2d |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 87AA:102E1B:43FB23:61F5F2:6A58B32F |
| html-safe-nonce | a75350e665cb74beaf103c23c155d7d22d6d4cab1c443c8e1b5df7114f4ce330 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4N0FBOjEwMkUxQjo0M0ZCMjM6NjFGNUYyOjZBNThCMzJGIiwidmlzaXRvcl9pZCI6IjcyOTk1MDIzNzk2ODY3MzY2ODciLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | 4ebcb0ad1d47dfe69d3309378d639106dd62e639c6950e3cf0444327348e45b0 |
| hovercard-subject-tag | issue:427455556 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/RustPython/RustPython/771/issue_layout |
| twitter:image | https://opengraph.githubassets.com/15c86602d4190c2fe7fde38d09ab996a5dd0575bc51737f29c0d2b2238f08593/RustPython/RustPython/issues/771 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/15c86602d4190c2fe7fde38d09ab996a5dd0575bc51737f29c0d2b2238f08593/RustPython/RustPython/issues/771 |
| og:image:alt | Summary Add a match_class! macro for implementing behavior that varies based on the built-in type of an object. Detailed Explanation Doing this currently with downcast is a bit awkward. Because it ... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | OddCoincidence |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5f2a0c7865178af3d91dd9f13b0cdfc3c73a2529c873d2780bb4c01271a57ec6 |
| turbo-cache-control | no-preview |
| go-import | github.com/RustPython/RustPython git https://github.com/RustPython/RustPython.git |
| octolytics-dimension-user_id | 39710557 |
| octolytics-dimension-user_login | RustPython |
| octolytics-dimension-repository_id | 135201145 |
| octolytics-dimension-repository_nwo | RustPython/RustPython |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 135201145 |
| octolytics-dimension-repository_network_root_nwo | RustPython/RustPython |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 8aae7b8d6caacacf5c66eaeb2702d8dc88d85b4a |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width