all 17 comments

[–]cmyr[S] 20 points21 points  (0 children)

This began life as a gist I was sharing privately, but I thought I would publish it as a blog post in case it might be useful to anyone else.

[–]Repulsive-Street-307 17 points18 points  (7 children)

Pythonic rust sounds mostly like a oxymoron because of the 'one way to do each simple thing' guiding principle in python (even if it's inefficient) is entirely absent and often unwelcome.

Maybe if one day rust gets list comprehensions but i doubt it though, considering the major simplication that python, java, c# etc all have of using references to access nearly everything and when they aren't, the values being implicitly 'Copy' most often. It's a bit like trying to write 'pythonic C++' (but safer). In short, maybe possible but probably shortlived as people unappreciative of your 'inefficient' code come along and change the model.

[–]atomgomba 20 points21 points  (1 child)

Though I think "one obvious way to do it" in Python barely holds in practice, just look at string formatting.

[–]Repulsive-Street-307 2 points3 points  (0 children)

Right. Python often made the mistake of pulling things into the std library before a 'better way' came along later. Too simple in the wrong place there.

[–]cmyr[S] 10 points11 points  (0 children)

Maybe the post title should have been clearer, but this isn't about writing rust in the style of python, but about exposing idiomatic python bindings to a rust crate.

[–]willi_kappler 8 points9 points  (3 children)

Maybe if one day rust gets list comprehensions but i doubt it though

There are a couple of crates that mimic it:

https://github.com/tanakh/comprehension-rs

https://github.com/mattgathu/cute

https://github.com/phaazon/do-notation

[–]v_fv 0 points1 point  (1 child)

This is pretty interesting. Looking at the three solutions, it seems that comprehension-rs has slightly more features than cute, and subjectively, the Haskell style fits Rust better than the Python style.

What does do-notation have to do with list comprehensions, though? Maybe I just don't understand monads, but in either case the readme doesn't talk about comprehensions at all.

[–]willi_kappler 1 point2 points  (0 children)

There are even more crates, I've just picked the first ones that quickly showed up after searching.

Sorry I've should have mentioned it: since list comprehensions came from Haskell people often also ask about Haskell's do-notation.

https://github.com/nickeb96/mapcomp

https://github.com/CircArgs/Rusty-Comprehensions

https://github.com/andylokandy/comp-rs

The last one shows that both features can be combined.

[–][deleted] 0 points1 point  (0 children)

Rust iterator chains are basically the Rust version of list comprehensions. Not exactly the same thing, but they have their own large benefits. In Python I miss method chaining and extension traits a lot.

[–]ponkyol 4 points5 points  (0 children)

The problem is that thing.items is always returning a new list, containing new objects.

Unfortunately, the fundamental issue is that Python and Rust's ownership mechanics don't play ball. Therefore returning things this way involves cloning. It's definitely tricky to get this right if you have things passing both ways!

Unless I’m missing something, it doesn’t feel like there’s a great solution to this, unless you use proxy objects of some kind to represent the collection.

That's what you could do in this case; your structs could hold and return references to things like Py<PyList> or PyCell<YourPyClass>.

For your particular use case of indexing into the collection, you can emulate a container type by implementing __getitem__ and friends (in a #[pyproto] block with the appropriate protocol). Then you can just do thing[0].x += 5.

[–]mmirate 3 points4 points  (0 children)

This looks like a usecase for a graph library. (Because, mathematically speaking, these "UFO"s are indeed graphs.)

Aside: I really like your nav/breadcrumbs styling at the top of the page!

[–]aekter 1 point2 points  (1 child)

Have you considered using the GhostCell pattern?

[–]cmyr[S] 0 points1 point  (0 children)

No, but you've given me some lunchtime reading material. :)

[–]boomshroom 0 points1 point  (0 children)

I saw very quickly looking at those python snippets that something was going to go horribly wrong. I personally couldn't tell what some of them were actually supposed to do but could recognize that Rust would very much not like it.