[HN Gopher] Rust 1.46 ___________________________________________________________________ Rust 1.46 Author : pietroalbini Score : 317 points Date : 2020-08-27 15:58 UTC (7 hours ago) (HTM) web link (blog.rust-lang.org) (TXT) w3m dump (blog.rust-lang.org) | est31 wrote: | The most exciting component of this release is the const fn | improvements. With loops and if available, you can now do non- | trivial computation in const fn for the first time. It reduces | the gap between Rust's const fn and C++'s constexpr to a large | degree. Ultimately, the miri execution engine that this feature | builds upon, supports a much larger set of features that even | constexpr supports. It's been a project spanning years to get it | merged into the compiler, used for const fn evaluation, and | stabilize it's features (this part is far from over). | | In addition to the linked examples, I have some code of my own | which is made simpler due to this feature: | https://github.com/RustAudio/ogg/commit/b79d65dced32342a5f93... | | Previously, the table was present as an array literal in C-style, | now I can remove it once I decide for the library to require the | 1.46 compiler or later versions. | | Link to the old/current generation code: | https://github.com/RustAudio/ogg/blob/master/examples/crc32-... | tines wrote: | > supports a much larger set of features that even constexpr | supports | | This sounds promising. Can you give examples? I don't know Rust | at all, and the reason I like C++ is its metaprogrammability. | tobz1000 wrote: | I believe in a talk[1] it was mentioned that Rust's const | eval will support heap-allocated values (accessed as | references). A quick search suggests that C++20 will also | support this, although it may be safer in Rust as it can give | a stronger guarantee that the static memory won't be written | to. | | [1]https://youtu.be/wkXNm_qo8aY?t=888 | steveklabnik wrote: | Basically, the interpreter interpret's rustc's internal IR, | so it can theoretically support the entire language. That's | not a good idea for various reasons, though, so its | capabilities are effectively on an allowlist, that we expand | over time as we're sure we want to enable a given feature. | tines wrote: | That seems like a really good design, as opposed to having | an AST interpreter like I might do otherwise. But would | this indeed support a "much larger set of features" than | constexpr as was claimed? | steveklabnik wrote: | I _think_ that the earlier const evaluator was an AST | interpreter? It 's been a long time and I don't work on | this code, so I'm not 100% sure. | | I don't know constexpr well enough to comment on that | claim. | kibwen wrote: | I think some clarification is warranted here, because Miri is | intended to be used for more than just constant evaluation. | In particular, Miri wants to be able to dynamically verify | `unsafe` code in order to detect undefined behavior, which | means that it will eventually want to support the entire Rust | language. However, just because Miri supports any given Rust | feature does not necessarily mean that that feature will be | made available for constant evaluation; consider features | that are non-deterministic (like RNG) or architecture- | dependent/nonportable (like floating-point operations), and | how const-evaluating such things could potentially cause | memory-unsafety to occur when runtime output and const output | differ. | marricks wrote: | I wonder why && and || are not allowed in const functions? | | > All boolean operators except for && and || which are banned | since they are short-circuiting. | | I guess I'm missing something obvious but why does the short | circuiting break const-ness? | Rusky wrote: | That was a restriction from before 1.46 stabilized control | flow in const functions. Now that we have worked out the | details around `if`, we can also stabilize `&&` and `||`. | | (I'm a little surprised they weren't stabilized at the same | time! Edit: they were! I just didn't look closely enough.) | est31 wrote: | > (I'm a little surprised they weren't stabilized at the | same time!) | | They were stabilized at the same time, see the release | announcement. | | https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html | phire wrote: | Short circuiting introduces conditional branching. If you | call a function on the right hand side of a || or && it might | or might not be executed depending on the value of the left | hand side. | | Until this version of rust, all conditional branches were | banned from const functions. | | I guess to keep things simple they just banned any feature | that might cause branching. | marton78 wrote: | Why is branching a problem? Since `if` is now enabled in a | const fn, it's trivial to rewrite && with & and if. | kibwen wrote: | `if` wasn't enabled before, so `&&` wasn't enabled. Now | that `if` is enabled, `&&` now works too. | marricks wrote: | Ahh that makes a lot of sense, if you're going to have a | compiler insert the result of a function having conditional | branching seems a bit gnarly I guess? | Filligree wrote: | It's conditional based on what's ultimately constant | data, so you end up with predictable output regardless. | kibwen wrote: | For the history of this feature request, see | https://github.com/rust-lang/rust/issues/29608 as a | starting point. | djhworld wrote: | Is there a resource that explains what const functions are and | why you would use them? | steveklabnik wrote: | https://doc.rust-lang.org/edition-guide/rust-next/const-fn.h... | kumarvvr wrote: | So, I want to learn Rust. I am a C# / Python programmer, | experienced. | | Are there any particular set of problems that I can solve | systematically, so that I can learn all the features of Rust? | smabie wrote: | Write a chip8 emulator in Rust. | BiosElement wrote: | You might check out https://exercism.io/tracks/rust . Some are | a little heavy in the math department but personally I've | always found test drive learning useful when learning a new | language thanks to instant feedback. | adamnemecek wrote: | Try to do some graphics programing with thr backend of your | choice. There is also this cool nanovg port | https://github.com/cytecbg/gpucanvas. Run the demo in examples | to see the nanovg demo. | datanecdote wrote: | I am in similar boat. Python centric data scientist. Very | tempted to try to learn Rust so I can accelerate certain ETL | tasks. | | Question for Rust experts: On what ETL tasks would you expect | Rust to outperform Numpy, Numba, and Cython? What are the | characteristics of a workload that sees order-of-magnitude | speed ups from switching to Rust? | brundolf wrote: | I'm far from an expert, but I would not expect hand-written | Rust code to outperform Numpy. Not because it's Rust and | Numpy is written in C, but because Numpy has been deeply | optimized over many years by many people and your custom code | would not have been. When it comes to performance Rust is | generally comparable to C++, as a baseline. It's not going to | give you some dramatic advantage that offsets the code- | maturity factor. | | Now, if you're doing lots of computation _in Python itself_ - | not within the confines of Numpy - that 's where you might | see a significant speed boost. Again, I don't know precisely | how Rust and Cython would compare, but I would very much | expect Rust to be significantly faster, just as I would very | much expect C++ to be significantly faster. | xvedejas wrote: | Trying to implement anything in Rust will set you up for a | crash-course. Even the simplest non-trivial programs will | introduce you to the Rust borrow checker, a major feature | absent in C# / Python. | steveklabnik wrote: | https://doc.rust-lang.org/stable/book/ is not purely problems, | but does have some problem chapters. (I am a co-author.) | | https://doc.rust-lang.org/stable/rust-by-example/ is the "by | example" introduction, which is all about sample programs, but | feels a bit dated, IMHO. Still not incorrect, but not up-to- | date. | | You may also like the O'Reilly book, or Rust In Action, which | use more fully-featured example programs more heavily than The | Book does. | apendleton wrote: | Meta-answer: my default when picking up a new language is | usually to learn just enough to be able to start writing code, | and then learn new things piecemeal as necessary to solve | whatever thing I'm working on, and it sounds like you're hoping | to do something like that here. | | I found that approach for Rust in particular to not work well | at all, and have colleagues who've reported the same. There are | some fairly complicated, fundamental concepts that are unique | to Rust that I think need to be tackled before you can really | do much of anything (mostly borrowing and lifetimes), and | that's not immediately obvious from starter programs -- because | of lifetime elision, some early programs can look deceptively | familiar, but there's a bunch of barely-hidden complexity | there, and as soon as you start to stray from the tutorial | path, you'll run headfirst into a wall of compiler errors that | you're not yet equipped to understand. For Rust I'd highly | recommend just reading a book cover to cover first (either TRPL | or the O'Reilly one), and _then_ starting to write code. | somurzakov wrote: | try to write ETL in rust | shawnz wrote: | You could try this: https://github.com/rust-lang/rustlings | brundolf wrote: | Once you've learned the basics (plenty of links in the | siblings, including the official Rust Book), this is a key (and | entertaining!) unofficial resource that really hammered home | for me the ways that Rust is different from the C family when | it comes to working with references: https://rust- | unofficial.github.io/too-many-lists/ | | It also taught me about Boxes and Rc's, which are essential for | certain kinds of things, and which I don't remember being | covered in the main Rust Book at all | steveklabnik wrote: | https://doc.rust-lang.org/stable/book/ch15-01-box.html | | https://doc.rust-lang.org/stable/book/ch15-04-rc.html | brundolf wrote: | Yeah, I figured they were probably in there somewhere. It's | possible I read the book before they were added, or that I | skipped them (I glossed over some of the final chapters), | or it's possible I just didn't fully grasp how important | they were until I followed the linked-list tutorial. | | What I like about the latter is how closely it steps | through the problem-solving process within the context of a | very familiar task, teaching you at each stage 1) why the | borrow-checker is upset and 2) what tool you need to apply | in order to satisfy it. If the Book taught me "what is Rust | and what are its features?", this taught me "how do I use | Rust in practice?". | steveklabnik wrote: | Oh yeah, don't get me wrong, the linked-list tutorial is | amazing. :) | jandrese wrote: | One thing I'd be wary of is Googling error messages and taking | answers from Stack Exchange. Rust has mutated (heh) a fair bit | over the years and many SE answers to noob problems are | obsolete and sometimes incorrect. At the very least check the | datestamp on any answer and be wary of anything more than a | year or two old. This goes double if the answer has some | extremely awkward looking syntax with lots of modifiers and | underscores sprinkled throughout. There's probably a better way | to do it now, or an alternative solution that works better. Or | maybe you're just trying to do something that Rust makes hard, | like concurrent processing on a shared data structure. | | The manual is safer even though it's harder to find your exact | problem and solution, especially when you're just starting out. | shepmaster wrote: | I literally spend tens of hours a week on Stack Overflow | ensuring this isn't the case, or if it is that it's clearly | notated. | | As always, feel free to drop into the Rust Stack Overflow | chat room[1], or any of the official Rust discussion | channels, and ping me or other Stack Overflow contributors to | review and update answers. | | 1: https://chat.stackoverflow.com/rooms/62927/rust | gchamonlive wrote: | I like to implement something I have already done before. In my | case, the ID3 algorithm has a nice balance of challenge, | experience and documentation available. You could try to write | it for a specific case, where you structure your data, and then | apply it to a generic case. | [deleted] | thomasahle wrote: | If anyone wants to know more about const fns, see | https://doc.rust-lang.org/reference/items/functions.html#con... | | It is the Rust way of specifying a function as being _pure_. In | other words the output is dependent only on the function | arguments, and not on any external state. | | This means they can be evaluated at compile time. I suppose in | the future, it could also allow better compiler optimizations. | ko27 wrote: | Never worked with Rust, but I am pretty sure that having a | function be pure is not enough to evaluate it at compile time. | mijamo wrote: | Why not? By definition the output does not depend on runtime | property so you should be able to compute it at compile time | right? | ko27 wrote: | Well, that is not the definition. Output of a pure | functions can depend on input arguments, and those | arguments can definitely depend on runtime properties. | | https://en.wikipedia.org/wiki/Pure_function | eloff wrote: | Pure functions are functions where the return value only | depends on the function arguments. If the function | arguments are not known at compile time, obviously you | can't evaluate it at compile time. It would only be | possible to do that when all the arguments are also known | at compile time (constants). | tgb wrote: | But a const fn can also do that: if given non-constant | parameters it will be evaluated at run-time. So I (having | never used Rust before) still haven't see the distinction | between pure and const. What's an example of a function | that is pure but cannot be evaluated at compile time with | constant parameters? | eloff wrote: | The parent didn't specify calling with constant | parameters, which makes a huge difference. To answer your | question, basically anything the compiler doesn't know | how to evaluate - which has been expanded in this | release, but does not include everything still. | tgb wrote: | Looks like we have some terminology confusion. I read | mijamo's question as being about the theoretical ability | to evaluate at compile time (the value is knowable) not | whether the compiler does do it, and that's what I meant | in my comment too. | | If you say that 'pure' functions are not compile-time- | evaluatable because they may be given parameters that are | not known at compile time, then you must also say that | const fns are not compile-time-evaluatable. I think it's | also clear that we mean for const fns to count, so the | assumption that the parameters are known at compile time | was implicit in the question. | | Under those two assumptions: are pure functions | evaluatable (in theory) at compile-time (on values known | at compile time)? As far as I can think, the answer is | yes? In which case, I'm not entirely sure what the | distinction between 'pure' and 'cosnt fn' is supposed to | be except to separate out the part of 'pure' functions | that can are evaluated _in practice_. Is there anything | more to it? | eloff wrote: | I think that's it in a nutshell. You can't evaluate | everything at compile time, even when you could | theoretically. So you need some way to mark the subset of | pure functions that can be evaluated at compile time, | which is what const fn does. That way if a const fn only | calls other const functions you know you can evaluate it. | It's a convenient way of tagging functions. | thomasahle wrote: | That's what I thought I said in the original comment. I | wonder what people disliked. | tgb wrote: | That makes sense, thanks. | [deleted] | steveklabnik wrote: | Yes, we don't actually use the "pure" terminology for this | reason. | the_duke wrote: | Rust has no notion of purity. This would require something like | an effect system. | | const functions can't directly do any IO or even allocation - | at the moment. | | But this can be easily circumvented, eg by using a proc macro | that does IO. | | Sidenote: even in Haskell the function signature doesn't | guarantee purity, due to unsafePerformIO. | pitterpatter wrote: | An interesting history note: Rust used to have an effects | system which included actually being able to annotate a | function as pure. | steveklabnik wrote: | From way back in 2013, a HN thread | https://news.ycombinator.com/item?id=6940624 | | Sadly it looks like the wayback machine does not have a copy | of the original. Does anyone know how to get one? | est31 wrote: | Alright this sent me down a rabbit hole. | | The URL is: http://thread.gmane.org/gmane.comp.lang.rust.de | vel/3674/focu... | | I've also seen it without the trailing /focus. | | The web interface of gmane.org is down, so the link is not | available. Turns out though that the rust-dev mailing list | archive is present on both mail.mozilla.org and mail- | archive.com, so one only has to find the mail corresponding | to the link. | | https://www.mail-archive.com/rust-dev@mozilla.org/ | | https://mail.mozilla.org/pipermail/rust-dev/ | | Using archive.org's "find all archived websites with this | prefix" feature one can obtain a total of three archived | e-mails. | | http://web.archive.org/web/*/http://article.gmane.org/gmane | .... | | http://web.archive.org/web/20140723013539/http://article.gm | a... | | http://web.archive.org/web/20140719142224/http://article.gm | a... | | http://web.archive.org/web/20141225073140/http://article.gm | a... | | Now, one searches for lines in those e-mails in on mail- | archive.com and finds these corresponding links: | | https://www.mail-archive.com/rust- | dev@mozilla.org/msg06831.h... | | https://www.mail-archive.com/rust- | dev@mozilla.org/msg09516.h... | | https://www.mail-archive.com/rust- | dev@mozilla.org/msg10494.h... | | Observe that the differences between the two IDs are | different each time, namely decreasing: 53, 50, 45 | | So it's not a constant difference. What to do now? | | Let's google the URL! It points towards this hn comment: | https://news.ycombinator.com/item?id=7554676 | | It gives one piece of information: the e-mail was written | by Graydon. Similarly, commenters in https://www.reddit.com | /r/programming/comments/1t8y6g/why_rus... mention his name, | making it very likely that the e-mail was written by him. | | Another hint comes from the reddit thread you linked above: | someone named maxcan stated they started the thread. | Looking up their name plus "pure" gives only e-mails from a | single thread, including an e-mail from Graydon: | https://www.mail-archive.com/search?l=rust- | dev%40mozilla.org... | | This is the E-Mail: | | https://www.mail-archive.com/rust- | dev@mozilla.org/msg03913.h... | | https://mail.mozilla.org/pipermail/rust- | dev/2013-April/00392... | | Also archived it, just to be sure: | | http://web.archive.org/web/20200827181214/https://www.mail- | a... | | It covers precisely the topic you mentioned and is in a | thread started by maxcan. I think it's the e-mail we are | looking for. | | To verify, the difference between the two IDs is either | 239, or 58, depending on which of the two numbers in the | URL point to the actual E-Mail, but 58 is more likely. The | 0.7 release announcement for example has a difference of 57 | and is quite close to both: | | https://www.mail-archive.com/rust- | dev@mozilla.org/msg04653.h... | | https://news.ycombinator.com/item?id=5986985 | steveklabnik wrote: | Argh! you are a better sleuth than me. I was looking at | that month's rust-dev archives and didn't realize the | subject did not have "pure" in it, so I looked right over | it. | | This is! Thank you so much! | kibwen wrote: | Gmane was just a nice interface for reading mailing lists, | in this case it was just referring to some thread on the | old rust-dev mailing list, which is archived at | https://mail.mozilla.org/pipermail/rust-dev/ . Sadly I | can't tell exactly which thread it was, but I'm guessing it | was https://mail.mozilla.org/pipermail/rust- | dev/2013-January/002... . | | (Niko also once wrote a blog post which gives an overview | of the old purity system: https://smallcultfollowing.com/ba | bysteps/blog/2012/10/12/ext... ) | steveklabnik wrote: | I knew it was, but couldn't find a rust-dev post with | "pure" in the same time-frame. Thank you! Yours may be | it, but I think est has a convincing case that it was the | thread this one spun out from... | | Thanks for that link to Niko's blog too! | cordite wrote: | These const fn's are cool, but won't this also lead to long | compile times down the road? | Verdex wrote: | Yeah, but only if you use them to compute significant items | during compilation. | | The upside of course is that any computation you compute at | compile time is a computation that you don't compute at | runtime. For some applications this trade off is definitely | worth the cost of admission. | | At the end of the day it's a trade off that will have to be | made in light of the scenario it's being used in. Being able to | make that decision is a good thing. | steveklabnik wrote: | Yes, any time you move computation to compile time, it makes | the compile time take longer. As always it is a tradeoff. | | One thing that people may not realize, especially now that we | have loop. You may expect this to hang the compiler: | const fn forever() -> ! { loop { | } } static FOO: u32 = forever(); | | But it won't: error[E0080]: could not | evaluate static initializer --> src/lib.rs:2:5 | | 2 | / loop { 3 | | 4 | | | } | | ^ | | | | | |_____exceeded interpreter step limit (see | `#[const_eval_limit]`) | inside `forever` at | src/lib.rs:2:5 | | This does place an upper limit on any given const fn. | cordite wrote: | That's fantastic! | | That could be a real hard-to-source build stall. | brundolf wrote: | Nifty! | LEARAX wrote: | The quality of life improvements to cargo look very nice, and I | feel that rust wouldn't be remotely as successful without such a | tool. I'm very glad I won't have to be manually picking target | directories out of my borg backups anymore when I'm running out | of disk space. | orthecreedence wrote: | Awesome! Any idea when relative links will be available in | rustdoc? Seems like it's just on the edge of stabilizing | (https://github.com/rust-lang/rust/pull/74430) but I'm curious | how long it takes to see in a release after this happens. | steveklabnik wrote: | There can be fuzziness here depending on exactly when it lands, | but generally, if something lands in nightly, it'll be in | stable two releases after the current stable. | kevinastone wrote: | Glad to see `Option::zip` stabilized. I tend to write such a | helper in many of my projects to collect optional variables | together when they're coupled. Really improves the ergonomics | doing more railroad-style programming. | sfvisser wrote: | I'm learning rust right now and there is a lot to like. Steady | updates like this are also very motivating. The ecosystem feels | very sane - especially compared to npm. Top notch Wasm support, | cross compiling is a breeze. | | That said, coming from a FP background (mostly Haskell/JS, now | TS) Rust is... hard. I do understand the basic rules of the | borrow checker, I do conceptually understand lifetimes, but | actually using them is tricky. | | Especially in a combinator world with lots of higher order | functions/closures it's often completely unclear who should own | what. It often feels my library/dsl code needs to make ownerships | decisions that actually depend on the usage. | | Anyways, I guess this gets easier over time, right? Should I | avoid using closures all over the place? Should my code look more | like C and less like Haskell? | | _[edit] great answers all, providing useful context, thanks_ | vmchale wrote: | > I do understand the basic rules of the borrow checker | | It ends up being doable. I dabbled in ATS, developed Stockholm | syndrome, and now Rust ain't too bad. | | Higher-order functions are difficult in Rust or with | linear/affine types in general. Haven't looked at what Rust | does recently. | | > Should I avoid using closures all over the place? Should my | code look more like C and less like Haskell? | | When in Rome do as the Romans :) | | Anyway, some fun imperative programming stuff you can do in | Rust that is fickle in Haskell (or OCaml/Standard ML). | thenewwazoo wrote: | I don't have time for an exhaustive answer, so I'll give you | some rules of thumb when using Functional-style combinators: | | * If you need to keep unchanged the input, you must either use | a reference-to (.iter()) or copy-of (.iter().cloned()) of each | item | | * If you don't need the input ever again, you should move the | items (.into_iter()) | | These rules follow for each step of the chain. | | I very very often write very Functional code in Rust and I find | it natural and easier to reason about than imperative-style | code. The example I could find the fastest: | https://github.com/thenewwazoo/aoc2019/blob/master/src/day10... | | Edit: another example (this one uses types that are Copy so the | copies are implicit) | https://github.com/thenewwazoo/cryptopals/blob/master/src/tr... | | Another edit: I am not a Functional programmer, and have never | known Haskell or any Lisp. Erlang is as close as I've ever | gotten. I've found Rust to be a fantastic language for writing | Functionally. | trumpeta wrote: | I've been using .to_owned() liberally, that often does the | trick in the first instance, albeit at the potential cost of | a copy. | estebank wrote: | This is a perfectly reasonable solution. You might be | leaving performance on the table but | | 1) if perfomance isn't a measurable problem for you, then | there's on point on eking the last bit of performance from | these allocations | | 2) it simplifies the code itself | | 3) sometimes clones are actually efficient, people forget | to make their small ADTs Copy | | 4) if you're learning the language this lets you delay the | moment when you have to fully understand the way lifetimes | actually behave in complex cases, which means that when you | _do_ do that you will have a better grasp of the rest of | the language and will be able to form a better mental model | of how it fits with other features | [deleted] | Shorel wrote: | Yep. I made my first Rust script last week and the amount of | care required is similar to C++. | | It is definitely not easier compared to C++, contrasting with | D, which is easier than C++. | | However, the program worked correctly at the first try, which I | guess it is also a consequence of the Rust model. | stevencorona wrote: | This echoes my experience with learning Rust over the past few | weeks (coming from Elixir). | | There is a lot to like, understand lifetimes conceptually, but | it's hard. | dnautics wrote: | If you're coming from elixir, and not doing this for work, I | highly suggest zig; zig feels like elixir since both have the | comptime concept. | nemothekid wrote: | > _the borrow checker, I do conceptually understand lifetimes, | but actually using them is tricky._ | | I've been using Rust for a little over year, almost daily at | work, and for several projects. I have a pretty good intuition | about how the borrow checker works and what needs to be done to | appease it. That said, I don't think I'm any closer to | understanding lifetimes. I know conceptually how they are | supposed to work (I need the reference to X to last as long as | Y), but anytime I think I have a situation that could be made | better with lifetimes, I can't seem to get the compiler to | understand what I'm trying to do. On top of that very little of | my code, and the code I read actually uses lifetimes. | jedisct1 wrote: | I've been writing Rust code since before the 1.0 days, and I | still can't understand lifetimes in practice. | | When the compiler starts complaining about lifetimes issues, | I tend to make everything clone()able (either using Rc, or | Arc, or Arc+Mutex, or full clones). | | Because if you start introducing explicit lifetimes | somewhere, these changes are going to cascade, and tons of | annotations will need to be added to everything using these | types, and their dependent types. | saagarjha wrote: | I think you're really intended to do the latter rather than | the former. I mean, Rust lets you do either-it gives you | the choice if performance isn't your concern-but usually | it's better to not clone everything. | steveklabnik wrote: | Nah, either is fine. Rust gives you the tools to do both | for good reason. Which is right for you completely | depends. | dahfizz wrote: | It's worth noting that every reference in Rust has a | lifetime, but the compiler is usually smart enough to infer | it. What you are talking about is explicit lifetimes. | adsjhdashkj wrote: | As someone in a similar description as you - i find my | lifetime understanding... moderate. Complex lifetime usage | still can tweak my brain - notably how i can design it. But | simple lifetime usage is intuitive. | | A simple example i often run into is wanting to do something | with a string, without taking owned parts of the string. Very | intuitive how the str matches the lifetime of the owned | value. | | On the otherhand, the other day i was trying to write a piece | of software where: | | 1. I wanted to deserialize a large tree of JSON nodes. I had | the potential to deserialize these nodes without owning the | data - since Serde supports lifetimes, i could deserialize | strings as strs and hypothetically not allocate a lot of | strings. | | 2. In doing that, because a tree could be infinitely large i | couldn't keep all of the nodes together. Nodes could be kept | as references, but eventually would need to be GC'd to | prevent infinite memory. | | 3. To do this, i _think_ lifetimes would have to be separate | between GC'd instances. Within a GC'd instance, you could | keep all the read bytes, and deserialize with refs to those | bytes. When a GC took place, you'd convert the remainder | partial nodes to owned values (some allocation) to consume | the lifetime and restart the process with the owned node as | the start of the next GC lifetime. ... or so my plan was. | | I have, i think, just enough understanding of lifetimes to | _almost_ make that work. I _think_ some allocations would be | required due to the GC behavior, but it would still reduce | ~90% of allocations in the algorithm. | | Unfortunately, i got tired of designing this complex API and | just wrote a simple allocation version. | | Conceptualizing allocations and the lifetimes to make it work | are.. interesting. Especially when there is some data within | the lifetime that you want to "break out of" the lifetime, as | in my example _(where i had a partial node, and i made it | owned)_. | | I still think i understand enough to do it - it'll just take | a fair bit of thinking and working through the problem. | tick_tock_tick wrote: | These kind of optimization are incredibly painful in Rust | one common suggestion is to sidestep the issue and store an | offset + length in the nodes and then you take that to look | up the value from the original string when you need the | value. | zozbot234 wrote: | _> The ecosystem feels very sane [] compared to npm_ | | Now that's damning with faint praise. | saagarjha wrote: | Parts of Rust's ecosystem are just npm but with saner people | using it at the moment. | ragnese wrote: | And it's probably going to be a pretty big issue in a few | years, IMO. | ragnese wrote: | > Anyways, I guess this gets easier over time, right? | | Yes. | | > Should I avoid using closures all over the place? | | Not necessarily. | | > Should my code look more like C and less like Haskell? | | Yes. Others sometimes don't like to hear this, but IMO, Rust is | not at all functional. Passing functions around is not | ergonomic (how many function types does Rust have again? | Three?). Even making heavy use of Traits, especially generic | ones, is difficult. | | Rust is very much procedural. Java-style OOP doesn't work | because of the borrowing/ownership. And FP style function | composition doesn't work without Boxing everything. But then | you'd need to be careful about reference cycles. | vmchale wrote: | > how many function types does Rust have again? Three? | | It has to, right? ATS has many function types as well, plus | stack-allocated closures (I think Rust has that too??) | steveklabnik wrote: | Rust's closures do not heap allocate unless you box them, | like any other struct, because closures are sugar for a | struct + a function, that's correct. | | (and yes, there are three types of closures, because they | need to know if they take said struct by reference, by | mutable reference, or by owner.) | ragnese wrote: | It does have to, because of the way mutation and ownership | work. Which is great! But it makes functional programming | awkward. The language does not "steward" you toward | function composition. | estebank wrote: | > how many function types does Rust have again? Three?). | | Depending on what you meant, there are _more_ than three: | * There are 3 traits, used by closures depending on their | needs: * Fn(Args) -> Output * FnMut(Args) -> | Output * FnOnce(Args) -> Output * *Every* `fn` | is its own type (`fn() {foo}`) * Function pointers | (`fn()`), which is how you pass the above around in practice | | > Rust is very much procedural. | | I think this is like saying Python is very much procedural: | true, but loses some nuance. Rust has _some_ attributes of | OOP, _some_ attributes of FP. Some constructs from OOP and FP | are made harder once you involve borrowing. Saying it is | procedural conjures images of Pascal and K &R C in people's | minds. To bolster your argument, though, I mostly use method | chaining for iterators but every now and then I need to turn | it into a `for` loop to keep the lifetimes understandable for | the compiler, myself and others. | ragnese wrote: | I realized after I wrote the comment that I was really | referring to the closure traits when I said that. And I | really should have said "kind" instead of "type" because, | like you said, every different function has its own _type_. | | But anyway, I don't _really_ disagree with your point about | categorizing languages as OOP, Procedural, or Functional. | | But honestly, in this case, I think it's pretty damn clear | than Rust is procedural WAY more than it's either OOP or | FP. (Note: By OOP, I mean Java-style with tall ownership | hierarchies and object-managed mutable state, not | necessarily caring about inheritance. And definitely not | referring to Alan-Kay-Style-OOP a la Lisp and Smalltalk). | | Scala can be looked at as FP and/or OOP. C++ can be looked | at as Proc and/or OOP. Python, IIRC, can kind of do all of | them, but I don't remember it being easy to make | copies/clones in Python, so FP is questionable. | | Have you ever tried to write two versions of a complex | async function in Rust? One with async and one with Futures | combinators? Due to ownership, the Futures combinators | approach very quickly devolves into a nightmare. The | language doesn't "want" you to do that. | | What about function composition? Very awkward to do with | matching up the different Fn traits. | | And deeply nested object hierarchies are a no-go, too, | because of the inability to do "partial borrows" of just a | single field of a struct. | | I mean, yes, it's not C because it has a real type system | and generics. But... it's pretty much C in that you just | write functions and procedures that operate on structs. | | EDIT: Perhaps my "hardline" approach on calling Rust | procedural is in response to people who have come to Rust | from non-FP languages, see `map`, `filter`, and `Option` | and start calling Rust functional. That's not functional | programming! Ask someone who does OCaml to try out Rust and | see if they call Rust functional afterwards. | noctune wrote: | >And deeply nested object hierarchies are a no-go, too, | because of the inability to do "partial borrows" of just | a single field of a struct. | | I'm not totally sure if this is what you mean, but FYI | you can borrow multiple fields mutably using | destructuring: struct Foo(u8, u8); | fn main() { let mut bar = Foo(1, 2); | let Foo(ref mut x, ref mut y) = &mut bar; *x | += 1; *y -= 1; println!("{} {}", | bar.x, bar.y); } | edflsafoiewq wrote: | Just let x = &mut bar.0 will work, but this | "intelligence" is confined to the body of a single | function. Rust possesses the somewhat curious property | that there are functions that are intended to always be | called like this foo(&bar.x, &bar.y, | &bar.z) | | which cannot be refactored to foo(&bar) | steveklabnik wrote: | This is a complex topic, but what it boils down to is | that the function signature is the API. If you borrow the | whole thing, you borrow the whole thing, not disjoint | parts of it. | | This is also why it's okay in the body of a single | function; that doesn't impact a boundary. | | We'll see what happens in the future. | ragnese wrote: | The problem comes when someone else needs to also borrow | the Foo, even immutably. In Java-style OOP, you typically | have "objects" that own other objects, all the way down. | And you manage state internally. | | So it often comes up that you might call several methods | in a given scope. If even one of those mutably borrows | one field of one sub-object, then you can't have any | other borrows of that object anywhere else in that scope. | | Newbies from other languages trip on that often enough | that I used to see questions about it in r/rust fairly | frequently. | int_19h wrote: | I think that Rust is often assumed to be functional because | it has ADTs and nice pattern matching, both of which have | historically been a feature specific to FP. Just goes to show | how fuzzy our definition of FP really is... | ragnese wrote: | Agreed. Same with "OOP". Who the hell knows what people | really mean when they say that. | | Those people who think that "FP" means "type system like | Haskell" are wrong, though, IMO. It precludes languages | that are much more function-based, such as Clojure, | Schemes, Elixir. | wtetzner wrote: | Functional in my mind more or less means means working | with immutable values. | scott31 wrote: | Note that entire rust team was recently fired from Mozilla, so it | is unclear how the future looks like for the language. Especially | since it does not have a spec and only have single reference | implementation | kibwen wrote: | _> entire rust team was recently fired from Mozilla_ | | This is completely incorrect, verging on FUD. Mozilla had very | few people working full-time on Rust; of the people who were | laid off in the recent wave, the ones working on projects | adjacent to Rust were working on Servo or WASM-related | codebases. In particular, the person at Mozilla who was most | central to Rust development, Niko Matsakis, is still employed | there and still working full-time on Rust. | adamch wrote: | The Rust teams discusses their post-Mozilla future here: | https://blog.rust-lang.org/2020/08/18/laying-the-foundation-... | TLDR: they're feeling pretty good. | AsyncAwait wrote: | They're moving to a Rust Foundation with corporate sponsorship | model. I think Rust will be fine, even Amazon expressed | interest in sponsoring development. | Verdex wrote: | Hear hear. | | System languages don't grow on trees. Rust has had a lot of | non-trivial effort put into it and is very usable _right | now_. Somebody is going to see the value just lying around | and is going to pick up the financial slack. | | I see it as vaguely analogous to the current movie theater | situation in the US. A lot of companies are seeing the end of | their business, but all of those buildings are still sitting | around waiting for someone to swoop in and buy them for fire | sale prices. | hu3 wrote: | What's baffling to me is how scott's comment is [flagged] | and [dead]. | | You trully can't have unconfortable opinions about Rust | here. That's blatant censorship. | | Replying to you since I don't see a reply button to his | comment. | steveklabnik wrote: | It's a factually incorrect comment: the entire Rust team | was not fired from Mozilla. | | Does that mean it deserves to be flagged? I didn't flag | it. But to be clear, while it does have some opinions, it | is also plain incorrect in the facts it asserts. | | You can also find, many, many, many comments critical of | Rust that are upvoted, let alone not flagged. I wouldn't | extrapolate from a single comment. | hu3 wrote: | This is a discussion forum. Users will exaggerate and get | facts wrong. Some ammount of lenience is expected before | completely silencing their voice. | | With that said, where can one read about who is in | Mozilla's Rust team? Is that information even public? | steveklabnik wrote: | Sure. As I said, I did not flag it. | | > Is that information even public? | | It is in a really weird space. However, a lot of the | folks involved have chosen to talk about where they're at | publicly, and Niko said he was not laid off. | | Also, for what it's worth: there's a charitable and | uncharitable reading of the comment. | | Charitable reading: everyone who was at Mozilla who was | paid to work on Rust was laid off. | | Non-charitable reading: everyone who was paid to work on | Rust was at Mozilla, and was laid off. | | HN readers are supposed to follow the principle of | charity, but it's quite possible that people either | ignored that, or mis-understood the parent as saying the | latter, in which case, it feels quite egregiously | incorrect, rather than maybe slightly wrong. | hu3 wrote: | Thanks for keeping our conversation civil despite my | tone. | echelon wrote: | `const fn` improvements are amazing! | | I can't wait for when we'll be able to `const fn` all the things. | Regex, expensive constants that feel as though they should be | literals, etc. ___________________________________________________________________ (page generated 2020-08-27 23:01 UTC)