5 ms·
Here's a nice example of a Trait that has async functions: fn list_items<'life0, 'life1, 'async_trait>( &'life0 self, collection_href: &'li
by WhyNotHugo 2y ago
Here's a nice example of a Trait that has async functions:
fn list_items<'life0, 'life1, 'async_trait>(
&'life0 self,
collection_href: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Vec<ItemRef>, Error>> + Send + 'async_trait>>
where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Rendered docs: https://mirror.whynothugo.nl/vdirsyncer/v2.0.0-beta0/vstorage/base/trait.Storage.html#tymethod.list_items https://mirror.whynothugo.nl/vdirsyncer/v2.0.0-beta0/vstorag...
Source: https://git.sr.ht/~whynothugo/vdirsyncer-rs/tree/v2.0.0-beta0/item/vstorage/src/base.rs#L79 https://git.sr.ht/~whynothugo/vdirsyncer-rs/tree/v2.0.0-beta...
- virtualritz 2y ago> https://mirror.whynothugo.nl/vdirsyncer/v2.0.0-beta0/vstorage/base/trait.Storage.html#tymethod.list_items https://mirror.whynothugo.nl/vdirsyncer/v2.0.0-beta0/vstorag... Unrelated to parent but maybe relevant to you: Rust API naming guidelines say no `get_` prefix on getters. https://rust-lang.github.io/api-guidelines/naming.html#getter-names-follow-rust-convention-c-getter https://rust-lang.github.io/api-guidelines/naming.html#gette...
- mrweasel 2y agoThe use of ' as a symbol that has any meaning on it's own has got to be one of the most stupid choices I've seen in a language. It's made worse by the fact that you can still use '...' as s character literal. Not only is is incredibly ugly it's also rather confusing, but it fits well into how I view Rust, complicated for the sake of making the developers look smart. It wouldn't fit the syntax of the language obviously, but why not simply have the developer prefix the variable with the keyword "lifetime", rather than assigning a symbol. It seems a little like starting functions in Go with a upper case letter to export them, dude just give us an export keyword, it's fine.
- the_mitsuhiko 2y ago> The use of ' as a symbol that has any meaning on it's own has got to be one of the most stupid choices I've seen in a language Can you clarify why you have that opinion? What would your syntax suggestion have been?
- lelanthran 2y ago>> It wouldn't fit the syntax of the language obviously, but why not simply have the developer prefix the variable with the keyword "lifetime", rather than assigning a symbol. ... >> The use of ' as a symbol that has any meaning on it's own has got to be one of the most stupid choices I've seen in a language > What would your syntax suggestion have been? Is the syntax suggestion he provided not applicable?
- Ygg2 2y ago> Is the syntax suggestion not applicable? Lets look at proposed syntax fn list_items<lifetime life0, lifetime life1, lifetime async_trait>( &lifetime life0 self, collection_href: &lifetime life1 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<ItemRef>, Error>> + Send + async_trait>> where Self: life0, life0: async_trait, life1: async_trait, I'm not going to pretend I understood what mrweasel meant fully, so I assume we can either omit generic or in parameter declaration (so I went with omitting lifetime keyword in parameters): fn list_items<lifetime life0, lifetime life1, lifetime async_trait>( &life0 self, collection_href: &life1 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<ItemRef>, Error>> + Send + async_trait>> where Self: life0, life0: async_trait, life1: async_trait, I guess you might be able to omit the "generic part" like so (it might be impossible, lifetime are just generics useful for lifetime tracking): fn list_items( &lifetime life0 self, collection_href: &lifetime life1 str, ) -> Pin<Box<dyn Future<Output = Result<Vec<ItemRef>, Error>> + Send + async_trait>> where Self: life0, life0: async_trait, life1: async_trait, In both cases, you get a huge verbosity increase, and mix between not knowing if a value like `Self: x` is a trait with lower case or a lifetime. So you trade verbosity for more ambiguity and programmer confusion, and possibly worse error reporting (is &a b a lifetime or a missing comma e.g. &a, b).
- mrweasel 2y agoBecause pretty much any other language has '...' for strings, or at least something to do with text. It's also a character that in all other languages (that I know of) must be closed with another '. Now you could say, we don't close it in contractions in English, so there's a case where one ' can just exist on it's own. That's sort of fine, a bit outside of the realm of programming, but fine, but then I think you should remove then '...' usage. It's really confusing that the same character has two different meanings depending on something that happens later. Rust does this with ! as well if I understand correctly, so it's NOT like everywhere else, but something!() is macro expansion... Why not just prefix with "macro" so macro something() So you have something that has a ' in front, is that a lifetime, or a missing ' later? The compiler will catch it, so it not a problem in that sense, it just makes it hard to read the code. Personally I would almost always prefer a keyword. For Rust I think my problem is that the language is a little to happy with symbols and operators being one character picked for the none numbers and letters and the choice of ' makes it seem like they are running out of characters to choose from. Like we just one or two features away from assigning meaning to § and €.
- toolslive 2y agoin OCaml, the single quote is a valid char for an identifier: let f = ... and let f' = ...
- mrweasel 2y agoI did not know that, and I question that choice as well. Why would you use that? It's a little less bad, because you can just have your own style guide that says "Don't do that".
- steezeburger 2y agoIt's common math notation to have f and f prime to represent something derived from f.
- Degorath 2y agoAs an OCaml beginner I've mostly seen it used for inner functions in lieu of calling the inner function `f_impl`.
- deleted 2y ago[deleted]
- lifthrasiir 2y agoMany languages (mostly functional) allow trailing apostrophes after alphanumeric identifiers, which mirror primes in mathematical and technical notations, so there are surely precedents. Rust doesn't allow multi-letter character literals for the usual reason, so there is no real ambiguity. Some old editors do only have a very-limited syntax highlighter with fixed rules (e.g. no regexp), so such editors will be indeed unable to handle this, but they won't be able to support many other languages if that's the case.
- atoav 2y agoI agree that this is a stupid choice. Yet I wrote many reliable and performant programs without using lifetime specifiers once. One of those programs was a text tokenizer that got second place on performance and was only beaten by a highly optimized piece of assembler. This is not nothing if you ask me. Rust is a language within which your shifty naive program will still outperform many other solutions, all while being reliable as heck if you wield the type system the right way. The only thing that I dislike about it is that certain code becomes unreadable. As this article says it often becomes unreadable for a reason — a reason which you would just not think about in other languages — but unreadable is still unreadable.
- swiftcoder 2y agoLisp variants have used the ' prefix as shorthand for the quote operator (interpret whatever comes next as a literal, instead of evaluating it) since about the time C became popular...
- kazinator 2y agoI don't know exactly when 'X denoting (QUOTE X) appeared, but I can see that it is described in a paper about the Lisp 2 system, from 1966. So it is at least 9 years before the B and NB languages evolved into C. The Lisp 1.5 Programmer's Manual from around 1962 doesn't mention it yet, using (QUOTE ...) for all occurrences of quote.
- jeroenvlek 2y agoA lifetime keyword would actually go a long way in improving ergonomics. You could even make it synonymous with '. Then people can choose. Maybe one will get much more traction and the other can be deprecated.
- kitkat_new 2y agowhy? It makes type information unnecessarily longer without adding information, and feels like writing "end_stm" instead of ";" after every line
- mrweasel 2y agoThat's the trade off isn't it. ' is unnecessarily short and doesn't convey any information at all, or worse, the wrong information. There are other comments that point out that ' is valid in identifier, or used to indicate that something is derived from something else. Some will prefer the short nature of just typing ', where people like me would prefer that you just add a few more characters so it reads more easily.
- kitkat_new 2y agoIt is, but not a trade off many would make. ' itself (!) may not convey information, but it's existence does convey information. While making it a keyword may help beginners to understand code and wish they could see the meaning directly, because they don't know the meaning of certain symbols yet, people who know the language and productively produce code are more concerned about content rather than syntax. Content meaning the name of the life time, the name of the types, the name parameters, the structure of the types, the constraints on the types, etc. Especially for Rust, there is a lot of the things mentioned above, and since the concepts in Rust aren't easy, it's important that these things get as much space as possible from the limited space on the screen, instead of wasting it by self explaining syntax elements, which are trivial to memorize. Thus { instead of begin_function_body, *; instead of statement_end, ? instead of 'if err != nil then return err' and ' instead of lifetime.
- Brian_K_White 2y ago
- thesuperbigfrog 2y ago>> The use of ' as a symbol that has any meaning on it's own has got to be one of the most stupid choices I've seen in a language. ' has a long history of use for various purposes in programming language syntax not derived from C. In Ada, attributes are a single quote followed by the attribute name. If I have an enum called Fruit then Fruit'First would give the first value in the Fruit enum definition. http://www.ada-auth.org/standards/22rm/html/RM-4-1-4.html http://www.ada-auth.org/standards/22rm/html/RM-4-1-4.html Attributes provide meta information about types and are very useful when working with custom integer types and ranges: https://learn.adacore.com/courses/advanced-ada/parts/data_types/types.html https://learn.adacore.com/courses/advanced-ada/parts/data_ty... Using ' for Rust lifetimes or Ada attributes is just a sigil https://en.m.wikipedia.org/wiki/Sigil_(computer_programming) https://en.m.wikipedia.org/wiki/Sigil_(computer_programming) It is not too different from: & for addresses / references in C, C++, and Rust, * for dereferencing in C, C++, and Rust $ for value substitution in shells and scripting languages : to mark keywords in Clojure and some Lisps
- kazinator 2y agoIt may not be too different from references, but Rust separately has those also, separately from lifetimes. In modern languages, we don't have to think about lifetimes most of the time, let alone notate them. Rust has too much stuff converging into the same context.
- xelxebar 2y agoWait. Are you a Cobol programamer? Your argument has nothing to do with ' per se; it's completely generic for every "symbol" in a language. https://www.mainframestechhelp.com/tutorials/cobol/arithmetic-statements.htm "Confusing" is mostly a question of familiarity; "ugly" one of taste. When you're designing a language's syntax, there is a tension between making the language feel recognizable to beginners/non-users and communicating important information saliently to experts. The former errs on the side of least-common-denominator symbols and explicit constructions, while the latter errs on the side of expression density and implicit understanding. Language features that appeal to beginners and outsiders naturally aid in language adoption, even if they actively work against expert practitioners. So, funnily enough, we should a priori expect the zeitgeist opinion to favor lowest-common-denominator languages features and shun high-utility but "complex" ones. That is a real shame, however. As a business or whatever, instead of maximizing for ease of onboarding, I want to maximize for facility in exploring the end-goal problem domain, i.e. expert work. Instead of picking a "readable" language, I want to pick one that increases our ability to find simple solutions to complex-seeming problems, conventionally readable or not. IMHO, baseline languages like Python are great for writing down what you already think but terrible for iterating on your understanding, and 95% of our work as engineers is (should be?) changing our understanding of the problem to fit reality as it bumps us in the face.
- prirun 2y ago> IMHO, baseline languages like Python are great for writing down what you already think but terrible for iterating on your understanding, and 95% of our work as engineers is (should be?) changing our understanding of the problem to fit reality as it bumps us in the face. I have to disagree. I've been working on HashBackup for 15 years now, and believe me, my understanding of backups has grown immensely over those years - with Python. Python may have some things I have to work around, as all computer languages do, but after all this time I still love working on and just reading through the code that has resulted from over 3200 commits. Python's simple, easy-to-read syntax, encourages me to change things, even in a complex section of code that I haven't looked at in years. For me, Rust's emphasis on multi-character syntax vs keywords makes it visually unappealing and ugly, and I don't think I'd enjoy working on ugly code for 15 years, even if it does run fast. Not intending to start a huge language discussion, but I do think the specific point of Python not being suitable for experts in a problem domain is not true, at least not for me.
- needlesslygrim 2y agoI assume it's derived from the OCaml generic type syntax (the first Rust compiler was written in OCaml after all), for example the definition of the type `Option.t` in OCaml: type 'a t = 'a option = | None | Some of 'a I think this is the case because IIRC this function: fn slice<'a>(s: &'a str) -> &'a str { &s[0..2] } Is generic over the lifetime of `s`, and it I assume it would have been difficult to distinguish generic types and lifetimes.
- steveklabnik 2y agoIt’s related yeah. In Ocaml it’s a generic, and in Rust, lifetimes are also a generic type.
- needlesslygrim 2y agoGood to know, also cool that you replied!
- the_mitsuhiko 2y agoIt's worth pointing out here for people not familiar with Rust, that this is the result of code generation by a third party crate to enable async methods on traits.
- Filligree 2y agoWhich isn't even needed anymore; now the compiler accepts it without any macros.
- WhyNotHugo 2y agoThe compiler only supports these for static dispatch, the above use case relies on dynamic dispatch.
- Dagonfly 2y agoWell, you can't use the `async` keyword version if you need the `Send` bound. Imo, Rust should introduce some syntax like `async(dyn+Send)` that desugars to `Box<dyn Future<Output = bla> + Send>`. This solves most of the async wards if you don't care about heap allocation and perfect performance.
- ahahahahah 2y agoThat's partially not true. You can use a non-async form in the trait definition to require the Send bound and then the trait impls can use the async form. See https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d55f089dc3de8df08cf0fe5b2c8d0e2f https://play.rust-lang.org/?version=nightly&mode=debug&editi...
- Dagonfly 2y agoFair point. Though, the code in question was a trait definition.
- iknowstuff 2y agoor just async fn list_items(&self, colletion_href: &str) -> Result<Vec<ItemRef>, Error>