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.
' 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
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_ty...
Using ' for Rust lifetimes or Ada attributes is just a sigil 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 LispsIn 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.
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.
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.
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.
let f = ... and
let f' = ...It's a little less bad, because you can just have your own style guide that says "Don't do that".
Can you clarify why you have that opinion? What would your syntax suggestion have been?
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 €.
I think you didn't use that many languages to see other forms [1]. LISP and Scheme don't have single-quoted string literals for example. Double-quoted strings are not really universal either, for example SQL uses single-quoted strings and double-quoted names.
[1] https://rigaux.org/language-study/syntax-across-languages.ht...
The ' aren't used in places where strings occur (strings just don't make sense there anyways), don't take up to much space (i.e. give more space to the name).
I am not a Rust pro, but this has never been an issue for me, same for ! for macro expansions.
Not once has this come up for me. They are in completely different places syntactically and can never overlap.
Sure, `'` might be text related in a lot of languages but definitely not universally. In LISP 'foo is shorthand for (quote foo) and also does not have a second character. Ocaml uses 'foo for types and foo' is just a valid identifier. Standard ML also has 'foo for type variables and I believe also allows identifiers named foo'. Haskell allows identifiers named foo' as well.
Maybe it's odd coming from languages you are familiar with, but it's not at all something that is unique to Rust.
> Rust does this with ! as well if I understand correctly
I am not sure how the case with ! is similar. Macros just end with ! to make them clearer visually, it's not part of an operator. There can never be any syntax ambiguity with them, neither visually or lexically. Also what would be the point. Take this example:
try!(do_something(...)).further();
Do you really think this would be more readable? (macro try(do_something(...))).further();...
>> 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?
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).
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.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.
edit: -4 points on my parent comment for a totally valid opinion, not violating any commenting guide line (please enlighten me). However, for the down voters: "Please don't use Hacker News for political or ideological battle. That tramples curiosity."
It makes type information unnecessarily longer without adding information, and feels like writing "end_stm" instead of ";" after every line
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.
enum foo; blah ...;