Hacker News new | past | comments | ask | show | jobs | submit login
‘~’ is being removed from Rust (github.com/rust-lang)
126 points by steveklabnik on May 2, 2014 | hide | past | favorite | 115 comments



For those reading, you need to read comments by "thestinger" very carefully.

A lot of people respond as if he made the following two claims:

1) Recursive data structures are rare

2) Singly linked lists are useless

When in fact he made these two claims:

1) definitions of recursive data structures are not prevalent in code

2) unshared singly-linked lists are not useful

#1 is true since you define a recursive data structure only once, no matter how often you use it.

#2 is slightly less obvious. One of the big advantages of a singly linked-list over other structures is that you can share tails with multiple lists. With unique ownership that advantage goes away. (There is still the use-case of loaning out tails, but that is a fairly weak argument).

Another advantage of a singly-linked list is ease of implementation; that is negated when your standard library provides dynamic arrays and stacks already baked in.


Here's a quick summary: Rust is adding a new capability, `box`, which is a superset of the existing pointer functionality.[1] Therefore, this special case is being removed, and, if it turns out that `~` is missed, sugar can be re-introduced to bring it back.

That said, I don't think it will be. It's only really useful in function signatures, since types are inferred everywhere else, and `~` is harder to search for, as well as not on all keyboards. Plus, in Rust, you should always use stack allocation unless you absolutely have to, and so making heap allocation a little more weighty syntax-wise fits with the goals of the language. `~` -> `box` isn't that much heavier, either.

1: One way it's a superset: previously, only `~` supported 'placement new', and now, all pointers can with `box`. `box` also allows you to specify which allocator you'd like to use.


> `~` is harder to search for, as well as not on all keyboards.

Which keyboards do not have a '~' key? How do those people type a path relative to their home directory? Use $HOME/foo/bar all the time?


> Which keyboards do not have a '~' key?

Most euro keyboards need at least AltGr + key, possibly 2 keys (because ~ is a dead key, so a space is needed to insert the character itself)

> How do those people type a path relative to their home directory? Use $HOME/foo/bar all the time?

It's common to `cd; cd foo/bar`


These keyboards usually don't have a convenient way to type {}[] either, these are AltGr + number keys in the German and French layouts for example.

The keyboard situation doesn't seem to be as bad as for the degree sign °, which doesn't seem to be typeable on an English keyboard at all.


Not being able to type those symbols causes problems with almost all programming languages (i.e. programmers are likely to have customised their keyboards for those symbols), but ~ is really only a major problem for Rust (and maybe bit-fiddling in C).


French layout keyboards do have a convenient way to type {}[], for me with Canadian French it is under 7890 using alt.


French Canadian keyboards are fairly different from European French keyboards:

French Canadian: http://www3.uakron.edu/modlang/french/images/kbd4.gif

European French: http://www.fentek-ind.com/images/frenchkeytop.gif


At least on a German keyboard, the <> required for Box<T> is a more painful combination to type, as < is the key next to the left shift key and > is the shifted version of the same. At the same time, ~ is right alt and +, where + is roughly where ] is on a US English keyboard.

With my typing style, the former is a complex press-release sequence with the left pinky and ring finger, whereas the latter is a single chord executable with the right thumb and ring finger.


It is not 1974, and people are not limited to typing the characters molded into the type wheel and keytops at the factory. At the moment, it's as easy for me to type × or † as it is to type + or _, and I would happily make it as easy to type λ or ← to get the benefit of reading code as such.

The situation with ~ is simpler; it's used by plenty of programming systems today, and any programmer who uses it and can't type it as easily as on a default US keyboard (i.e. with one modifier+key press) is not using their tools effectively.


Sadly, most people don't use a sane layout. Instead, they use the default layout. It's just the status quo bias at work, which explains why the qwerty layout and staggered key still exist, despite overwhelming evidence in favour of alternatives.

(To anyone who feels the urge to educate me on the Fable of the Keys, remember that typing speed is not the only worthy criterion. Comfort, RSI, and ease of learning, matter much more.)


Many international keyboards don't have a tilde key. For example it's not shown on the Finnish/Swedish MacBook Pro keyboard at all.

It's not difficult to type (Alt+¨ followed by a space), but you can't find it by looking at the keyboard.


That's a specious argument IMO. The same case can be made for the pipe/vertical bar character. So I guess they have to remove that from the language too so Mac users won't be mildly inconvenienced.


You do not have to type a space though to get a pipe character. Tilde and backtick are the two characters which are hardest to write on a Swedish keyboard.


I actually use a Swedish keyboard and I've never found these dead keys to be a problem myself.

Vertical bar/pipe isn't shown on most European Macbook keyboards, nor is backslash in fact, so I guess backslash has to be removed too.

I'm just saying it's not a great argument.



My swedish mac keyboard layout forces me to use Alt ¨ + space to type ~. It's certainly annoying and I usually just type "cd" first.


I rarely use ~ for my home directory, and I type on a US keyboard. ~/ is three inconvenient keystrokes; cd<Enter> is three convenient keystrokes.


Does this change affects managed box? Or it only affect owned box?


You'll allocate a managed box with

  let x = box (GC) 5;
if my memory serves. The argument to `box` defaults to HEAP, so these are the same:

  let x = box (HEAP) 5;
  let x = box 5;
And of course, boxing an integer is silly. This is just for illustration.

The @ for managed boxes has been removed from the language for a while now. It's not technically gone because there's one or two instances in the compiler, IIRC, but it should be gone Real Soon Now.


> You'll allocate a managed box with let x: box (Gc) 5;

It's GC in full uppercase FWIW, it's a static marker[0] not the type name. And the syntax already works in 0.10 (although funnily enough only HEAP and GC exist, no e.g. RC)

> The argument to `box` defaults to HEAP, so these are the same:

Yep[1].

[0] http://static.rust-lang.org/doc/0.10/std/gc/index.html

[1] http://static.rust-lang.org/doc/0.10/std/owned/index.html


Thanks, I've uppercased it.


Thanks for the explanation! This change makes the code more clear to me. When I first read some rust code, those ~ and @ are annoying because I don't know their meaning and hard to search them for a explanation. The box keyword is a much better way for developers.


Thank you. That's exactly our thought process too, though there is some reasonable disagreement about it.


I've been reading a bunch of tutorials and such, including the official one, about Rust recently and you'd get the impression that using unique pointers were the norm. This discussion seems to suggest they should be generally avoided. Now I'm not sure if I've just been massively misreading everything (I come from a background in GC languages) or whether the messaging about usage is way off.


Well, the official pointer tutorial, which I wrote, says right up front that you should prefer stack allocation: http://static.rust-lang.org/doc/master/guide-pointers.html

Unique pointers are one of Rust's newest, shiniest features, so they do get talked about a lot. Probably disproportionally so.

Honestly, it's probably that the docs are still coming together. The tutorial is notoriously poor, Mozilla has hired someone to work on it, but the fixes haven't surfaced yet.


Re-read the pointer tutorial and yes I've clearly mis-remembered that so apologies! You're probably right that there's just a lot of discussion about them at the moment.

Anyway I'm very excited about Rust, really looking forward to 1.0.


As an early learner of Rust, but with strong experience in C++, I also agree with this choice. It seems much clearer to me than ~ and @.

And thanks for the explanations and the tutorial !


Any time. Glad you like them.


I'll be honest: Rust is kind of losing me with these changes. I started following/tracking the language about a year ago, and I thought the syntax looked really succinct and easily readable back then, but with changes like this, [T] => Vec<T>, the region/lifetime syntax, together with the propensity to abbreviate almost everything, code is quickly starting to look kind of soupy to me.

I get the arguments, and they're logically sound, but in the end it's beginnning to read like C++03.

On the one hand, the Rust community's generalising a lot of stuff, which sounds great, but then adding a bunch of macros (I know, this ain't yo daddy's C macros) to replace first-class citizens ([1, 2, 3] => vec!(1, 2, 3) for example), and I worry how IDEs will be able to handle macros from an autocomplete/intellisense standpoint, not just checking/displaying type information when using them, but also writing new ones.

I guess it's a language primarily by and for text editor users, and I'm beyond that point these days.

As I said, I started following the language daily a year ago, and a couple of months ago I was thinking of jumping in around this point in time, but right now I feel like I want to wait another year to see if the syntax has become more readily intelligible.

I still think it's a fantastic effort, and kudos for all the hard work.


Odd, I've just been getting the impression that the language is become much, much readable. I agree with thestinger, here:

> uses and instead of &&, or instead of ||, list instead of [] and so on. Most people find it far easier to read and search for these than the sigil alternatives. The avoidance of more than one way to do the same thing (like including both ~T and Box<T>) is another reason why people find Python easy to read.


What is the source of that statement? Because honestly, if the future of Rust is to look like this, that would be somewhat horrifying.

Python is a great language for beginners and people who get into programming through nontraditional channels without having much of a symbol-pushing background; presumably, being able to parse symbolic expressions naturally is a skill that needs to be learned, and perhaps even needs to be learned early in life to wield effectively. If you don't have the ability, classical systems languages will look like malicious ASCII soup and a language whose code you can actually read like a paragraph of text will be long-overdue respite from this misery; the same perhaps even applies to other non-verbose shorthand (as an anecdote, one of my graduate program's logic-heavy classes is currently suffering from a student who more or less constantly interrupts the lecture to get all the mathematical notation on the board read out to him in natural language). The latest startup/trendy tech boom has made a disproportionate number of people of this type gravitate towards programming, many of them coming from the wider blogosphere/"social internet"; as a result, their opinions regarding what is good or bad and legible or illegible have come to entirely dominate the airwaves. It is all to easy to forget that there is a barely visible core of often significantly more prolific "native" programmers hiding in newsgroups/IRC channels/mailing lists and more often than not having very different measures regarding what constitutes good language design. When Rust came about, its design held the promise to finally deliver something to this group that might offer a way out of the C monastery; having it reorient itself to appeal to more popular sensibilities at this point is bound to cause a lot of hard feelings.

Personally, I always found the flat monotonicity of Python code to be rather unpleasant to read and write. Having what some people like to denounce as "line noise" actually enables a very useful visual contrast between "structural" (parentheses, scope boundaries, operators) components of the code and largely user-defined "names". Looking at a piece of code like "if(vals[1]==1 && vals==[1,2,3]) { ... }" allows you to break up the code visually before having read and echoed to yourself even a single word of natural language; this can't be said of a (hypothetical) example like "if vals.at(1) equals 1 and vals equals list(1,2,3):". Adding to that the general lack of code layout flexibility and the deliberate lack of alternatives to express a given pattern, the resulting picture is that the way an experienced programmer would usually gather a slew of information from diagonally skimming over a piece of code (segmenting all of it using the visually distinct "line noise", gathering when and how data is accessed, inferring the original writer's priorities from how the code was spaced out and what constructs were chosen, spotting the names of external dependencies...) is severely crippled.


> When Rust came about, its design held the promise to finally deliver something to this group that might offer a way out of the C monastery; having it reorient itself to appeal to more popular sensibilities at this point is bound to cause a lot of hard feelings.

Syntax is a very small part of the overall design. Rust won't stop being Rust just by removing a few confusing sigils.


The key to this comment is "[t]he latest startup/trendy tech boom has made a disproportionate number of people of this type gravitate towards programming". The rest can be extrapolated from that sentiment.


I understand that the sentence you quoted is easily construed as a cheap potshot at startups, but all I meant to say is that suddenly, there is a large number of people coding - and, more importantly, writing about coding - who did not grow up staring at mangled C++ debug symbols and hex dumps. I don't mean to say not doing that makes you a worse programmer - the difference does, however, seem to explain the composition of two groups who like shouting things to the effect of "I don't understand how you can find that easier to read than this" at each other.


[T] => Vec<T>

It's ~[T] that is now Vec<T>, which was a good change in emphasis (the former is still valid, though it will become Box<[T]> with this RFC).

Besides the implementation differences, I think readability is improved when `Vec<T>` is written.


Ah yes, sorry.


I guess it's a language primarily by and for text editor users, and I'm beyond that point these days.

What do you mean?

EDIT: Imagine a programming language designed around an IDE. Fun thought. Not sure whether it's a useful thought, but it's fun to think about.


I actually regret that comment. I feel I was being a bit too negative in my original post, and I don't want to add fuel to the fire by continuing the argument here.


No, no... I'm sorry if my comment sounded strange. I wasn't being ironic or snarky, I was being genuine.

What are your thoughts regarding IDEs vs editors? It's an important topic.


Honestly, as a guy who works on a lot of old code that I didn't write, IDEs are a complete godsend. Features like 'find me everywhere this method gets called', or 'find everywhere this value gets written to', and just simple navigation between functions/files. They're a backbone of my maintenance programming strategies, and I don't know what I'd do without them.

I do all of my javascript coding in vim and don't miss IDEs so much, but that's because I mostly only work on my own javascript code. For large, multi-person projects I massively prefer working inside an IDE.


I think the real key here is not ide friendliness, but "compiler as a service." The compiler, by definition, is already capable of understanding our code. If that understanding can be exposed as a standard api, we can build up a set of powerful capabilities for refactoring and much deeper programmatic transformations. With very large code bases, this is no longer just nice-to-have ... it is the next tool we should rationally insist on.


And we shall call it Java.


That isn't really the case at all. Java (the language) is relatively small and simple. Java code can be written quite easily without an IDE. In fact, that's how it was done for many years by most Java developers, before Eclipse, NetBeans and other IDEs became more commonly used.

The unnecessarily complex design of many Java libraries and frameworks is generally what pushed developers toward using an IDE, not the language itself.


Actually we call them Smalltalk, Interlisp, Delphi, Visual Basic and Eiffel.


Text Editor vs IDE.


Hmm... I don't understand why it has to be Text Editor vs IDE. The two concepts are orthogonal. One is for editing text; the other is for understanding and autocompleting text. If their concern is that there aren't any good tools for Rust yet, that'll be solved with time.


I think you are missing the point of the statement. If one was designing a language meant to be developed in an IDE, you can hold various assumptions which would influence how syntax shapes up.

A trivial example which is not related to rust but I think serves as a decent example, you can assume the IDE will color/italicize/etc member variables to get rid of _var __var var__ nonsense. You can also use slightly less verbose terms even if they are less informative if you assume a tooltip with a concise and complete explanation pops up.


I'm a little terrified by the prospect of a language designed to be incomprehensible without a stack of tools that will explain it to you.


I'm not sure how interesting this topic really is. As an example, look at Smalltalk. Crazy easy syntax, and made to be used in an IDE that dwarf what most of us consider an IDE.


Feh. It's an interesting split between what I'll call the concisionists and the explicitists.

As a concisionist, this change stinks. I appreciate that the "not on my keyboard" argument is a big deal, but I'd argue that just merits a change of sigil, not adding verbosity.

Designing a language to be prolix just makes code more laborious to understand.


> As a concisionist, this change stinks.

Hardly. As thestinger argued so eloquently, legitimate use of the ~ are few and far between: typically, recursive data structure definitions, which are rare even when you go Recursive Crazy. (Functional programming would even avoid unique pointers, since they prevent sharing.)

From an information theoretic perspective, giving a special syntax for such an uncommon use doesn't make sense. If you want your language to be concise, you want the short-cuts to be used for frequent cases. Before we give a special syntax to unique pointers, we should address everything that's more often used. That would turn Rust into APL.

Since we don't want such a combinatorial explosion of special symbols, we're back to the good old Huffman encoding: short cuts for the frequent use cases, more verbosity for the rare ones.


> legitimate use of the ~ are few and far between: typically, recursive data structure definitions

Wait, don't you need it to instantiate the corresponding recursive data structures? As in, a typical cons-cell list would be created in a fashion like Cons(1, ~Cons(2, ~Cons(3, ~Nil))).


That's an illegitimate example.

Exposing unshared nodes like that does no good. Just write a cons function that embed the unique pointer, that will get rid of the tilde, and make for an even better syntax than what you just showed.


Sorry, I don't think I understand; could you explain what you mean by "exposing unshared nodes"? Also, are you saying that for every self-referential constructor of an algebraic datatype, the correct thing to do is to write a boilerplate function that simply wraps the constructor and a call to whatever the boxing operation winds up being...? That seems somewhat odd.


"Node" is the name I used to talk about the cons cells your singly linked list is made up of.

Now 2 things.

First, the tiled denotes unique pointers. Your example was a singly linked list. Singly linked lists have 2 important characteristics: adding or removing the first element is O(1), and the tails of those lists can be shared. With unique pointers, you can't share. By design. If you want several references to a "node", you need to use shared pointers, whose allocation is manage by reference counting or garbage collection. So you have a data structure whose only advantage is O(1) insertion and removal… of the head. That's not very useful to begin with, considering the absurd amount of heap allocation you need to do. Other data structures fare better (vectors, ring buffers…).

Second, your example supposes the existence of a `cons()` function to begin with. If you really want to use unique pointers, you should write a function that accepts values, and wraps them in a pointer instead. That way, you can write `cons('A', cons('B', cons('C', empty)))`. There, no more pesky tiled: they have been factored in the definition of `cons()`. Less repeating yourself for the win.

> are you saying that for every self-referential constructor of an algebraic datatype, the correct thing to do is to write a boilerplate function that simply wraps the constructor and a call to whatever the boxing operation winds up being...?

Not quite. I'm saying the constructor itself should take care of the boxing operation. When devising a data structure, you generally know what it will be used for. It's memory allocation scheme should be a part of it. Hidden, if possible. For instance, unique pointers have value semantics. As such, they're an implementation detail. Leave them out of the interface. If it turns out you didn't need them after all, you can scrap them without breaking outside code.

Hmm, I guess that makes three…


Does this change pattern matching syntax of recursive data structures, if every node is an explicit box type? Could be cumbersome for matching parse-trees?


I have read that is doesn't change a thing. Maybe it's even more concise.

From what I have read, there is a general mechanism for pattern matching: let the custom data structure implement a "pattern match" method or something, which is then implicitly called with the pattern matching syntax. The explicit box type would be no different.

My guess is, parse-trees would be just as easy to match.


> As a concisionist, this change stinks.

There's two side to it: it makes creating unique pointers slightly harder, but at the same time it makes (unnecessary) overuse of unique pointers slightly harder/less likely, and that looks to be a concern of the core team.

> Designing a language to be prolix just makes code more laborious to understand.

Does it make the code more laborious to understand though? The concept becomes easier to search for and it's easier to talk about it (both because box/boxing is a term of art, and because "box" is a single syllable).


There's a nuance to point #2. The right amount of concision expresses the situation perfectly to someone skilled in the art, without requiring further reading to grasp or without requiring unneeded information to be waded through.

(philosophy) A language should support concision to allow those skilled in the art to use their time effectively.


I would argue that yes, it does. The examples I've seen of the change have become a mess of letters and i'm not too fond of it.


Could you cite some specific examples? I think that'd really help here.


Well if you had something like

     ~Vec<~Vec<~Vec[~T]>> (not 100% realistic example)
becomes

     Box< Vec< Box< Vec< Box< Vec[Box<T>]>>>>>
which really looks weird. It's like you have tire marks over your code.


Sorry, but I think that example is so unrealistic as to not really be worth discussing.


I wouldn't be so quick to dismiss it. Maybe that exact situation won't often arise, but in other languages like C++, Java and C# it's not at all uncommon to have nested collections.


Yes sure; but it is rare to have indirection for every layer of a nested collection (i.e. each collection will essentially be a pointer to some data, with a little bit of metadata (like length & capacity for a Vec), so having Box<Vec<T>> is a pointer to a pointer to the data: essentially pointless!).

In other words, one would write

   Vec<Vec<Vec<T>>>
That might be considered ugly, but it's not ugliness caused by the `~` change.


Could the opposite happen? What if you have `~~` pointer or `~&~` pointer?


I've never seen `~~` except for workarounds caused by the current lack of dynamically sized types (which is being fixed). `~&` is not very useful, as you'd be placing a stack-bounded lifetime on the heap (except for 'static, I suppose, but I've never seen that).


words are easier grep for, but I'd rather read x = (2 * 2)/y instead of "x assign 2 plus 2 divide y"


Mathematical operators are well established with well known meanings, but the Rust-specific ~ is not.


It would be after a little while of using the language, I just don't think it should optimize for new users.


What bugs me isn't the loss of this shorthand, but the decrease in shorthand overall.

Punctuation and other built-in language features give me a baseline for what I can understand and what I can always rely on. If I see ~T, even if I don't know what it means immediately, I still know that it's part of the core language and will get me a step closer to useful understanding; here is a thing I can probably use to solve some problems. Moving as much of the language into a stdlib as possible is a worthy goal that makes for a "cleaner" and more "elegant" language (whatever those mean), but it vastly reduces this effect.

The problem is that all of the core syntax and builtins are probably good to know, but not everything in the stdlib is useful. At least half of the stdlib for any given language tends to be worthless junk. Do you do Python? Did you know about the formatter module? popen2? asynchat? sunau? Probably not. But you almost certainly recognize 100% of Python's syntax and at least 90% of its builtins.

Contrast with Perl, which (besides having a ridiculous amount of built-in syntax) relegates such basics as OO support into the standard library. Subclassing is done by using a library, and there are even two distinct libraries for doing it in the stdlib! So to understand Perl code, you have to understand a good chunk of its stdlib as well, but not all of it because a lot of it is weird obscure junk, but there's nothing telling you which bit is important because it's just a thing everyone knows. (And the reliance on third-party libraries to fill in gaps in the language makes this far worse.)

One of C++'s major offputting properties is that everything is in a bloody library. (The other is that the features it does have all interact in obtuse ways.) You can learn what all of C++'s syntax does, and still be unable to make sense of real-world C++ code. I'd be pretty sad to see that happen to Rust.


From thestinger:

> Rust has strived to remove non-orthogonal features for a long time, and the language has been getting steadily smaller and simpler.

Hereby avoiding the one mistake that made C++ so horrible: lots and lots of non-orthogonal features. It's not just a matter of being cleaner or more elegant. It's a matter of having less to learn.

As for half the standard library being worthless junk… Rust probably won't be doing that mistake. If they simplify the language, they are likely to simplify the standard library as well, which means cutting the worthless junk out. Plus, it will likely be easy to use whatever is most useful: it will be all over the place in tutorials, manuals, examples, and of course actual code.

> One of C++'s major offputting properties is that everything is in a bloody library.

On the contrary, it's an assurance that you can implement bloody efficient data structures yourself, if the STL doesn't do what you want. This is what makes C++ a generally fast language: it's not optimized for special cases.

> You can learn what all of C++'s syntax does,

Most programmers can't. Experts do, but for the rest of us… C++ is impossible to parse, and has many, many, MANY pitfalls: http://www.yosefk.com/c++fqa/

Which is precisely what Rust is trying to avoid.


Perl's OO support as bad as you make it sound. You don't have to use the base or parent pragmas to subclass; it's just a lot less tedious if you do, because there's no special syntax for it. (It's kind of amusing to hear "Perl has too much syntax" in this context.)


~ for allocation was weird, but I will miss lack of ~ as analogy to * .

Will they change * to `RawPointer<T>` too? ;)

I'm not happy about change of [T] to Vec<T> either.

I hope all these changes will make a full circle and get a first-class syntax back.


> I'm not happy about change of [T] to Vec<T> either.

[T] wasn't a thing in Rust. ~[T] hasn't gone and won't go away either. See this email from acrichton: https://mail.mozilla.org/pipermail/rust-dev/2014-April/00935...


That email is somewhat outdated. ~[T] is certainly disappearing with that syntax, becoming Box<[T]>, andthere has been much back and forth about whether this Box<[T]> type actually offers anything over Vec<T>, or if it's just a "cute" consequence of the type system.

(The borrowed slices &[T] and &mut [T] are certainly here to stay.)


>first-class syntax

Perl-y symbol nonsense is not a first-class syntax


I agree. Syntax should be descriptive first and concise second.


> a first-class syntax back.

I would argue that this change elevates the clarity and quality of Rust syntax.


Orthogonally to whether this is a good or bad idea, I really wish the PR and subsequent community management had been handled more carefully for something that was pretty much bound to be a very controversial change (tellingly, /r/rust even had a preemptive thread about it before it materialised: http://www.reddit.com/r/rust/comments/236plz/thoughts_on_rem... ). Although I perhaps am in a bad position to complain after having been caught up in the less savoury parts of the exchange myself, I can't help it but believe that the often outright hostile tone and the swift wagon-circling by the proponents (in response to what they probably felt was an unreasonable onslaught of repetitive criticism) will have left a very bad aftertaste with a lot of readers. Much of this could have been prevented by preparing a clean document explaining the motivation and ramifications of the change to a general audience in advance, and perhaps by having the moderators apply some gentle pressure on the loose guns on either side to pipe it down.


The OP is, in fact, that document. You'll notice this in a pull request to Rust's RFC repo. This change has been prominently brewing in the Rust community for a long time. The fact is that people have strong opinions about Rust and this is a critical time in its development - people are going to complain.


I could have put some more thought into this response.

As Rust becomes more popular while we try to bring home the last few major changes, we've had this problem a few times, where the broader community is surprised and partially shocked and disappointed at a change that has been brewing for a while.

Certainly, more effort could be put into messaging and explaining how big changes are going to effect users. Figuring out how much, and what sort of, messaging is sufficient is not easy, and somebody is always going to find something objectionable about nearly everything. Additionally, Rust is still in an alpha state, in heavy development. The project is not in production mode yet.

We're always learning from mistakes and evolving the process.

Finally, Rust is in the home stretch. In some sense, we're at a stage where we need to hurry up and just get it done, at the expense of some community fallout along the way. If Rust is good, the ill will from the churn will be forgotten in time; if Rust is bad it will die. With the attention Rust is attracting, community momentum wants Rust to stop changing, but Rust must change a bit more. Rust needs to get to a point where the design can be justified and maintained for years to come, before its own popularity forces it to slow down.


Thanks for the detailed response. I understand that having to deal with this sort of situation instead of working on bringing the project closer to fruition must be very annoying from a core developer's perspective. Sorry for contributing my part to this being dragged out further.

To clarify, what has distraught me the most about this change is not even the change itself (although I do think that, however small or warranted on its own it may be, it may have long-term ramifications that need to be considered much more carefully), but the way the process seemed to diverge from the fairly open and inclusive discussion that seemed to regularly take place in the past. This change may well have been brewing somewhere for a while, but from the point of view of someone who is not in the "inner circle", what was perceivable of it essentially was the thread I linked above some 16 days ago (which was remarkably full of responses by apparent "insiders" that aimed to discourage people from discussing the topic at that point in time) and the thread announcing the RFC, in which even some of the most basic questions needed for a casual observer to understand the tradeoffs were unanswered when the proposal of the RFC was mainlined something like half a day later.

The end result is something that looks similar to what happened with GNOME 3 to someone who was in the opposing camp in both cases, where the "in-group" at some point decided that they had identified a development agenda of utmost importance to what has in fact been part of the central mission of the project all along, and increasingly came to send the message that they held disagreeing members of the "out-group" to be obsessive hecklers and people who should just get out already if they don't like it - although nothing says it has to end up like that, where this took the state of Linux desktop environments is easily observed nowadays.

When considering the overall lifecycle of a project, the number of remaining "difficult decisions" is a far more accurate metric of completion than code or concept. Frustratingly, it is pretty much bound to increase towards the full end of the scale of the latter when the development process is a highly public affair. People wouldn't argue this topic with such ferocity if it wasn't for their appreciation of your work so far and high expectations for this project; please don't let that go to waste by shortcutting the decision process when you have come this far.


Yeah, I've read the document, and I would hope that most other people who proceeded to debate the topic did as well. I honestly don't think that it does a commensurate job of presenting the case for it (and after reading many of the comments by proponents, I certainly am under the impression that there is a strong case for it; I just still think the case against it is stronger). A lot of the comments also show widespread uncertainty about the silent assumptions; I, for my part, am still at a loss as to why something like Cons(1, ~Cons(2, ~...)) is not an interesting or common use case according to some proponents (not necessarily restricting the question to cons-cell lists - the invoked universal utility of sharing tails, for instance, seems far less universal across the practical use cases of many other data structures).


I can't quite tell from your last sentence if you realise this, but ~ doesn't provide sharing at all: ~T/Box<T> acts like a T in almost all ways, except it is guaranteed to be pointer sized (hence its use in recursive data structures, to allow them to exist without being infinite large). A pointer like Rc is required for sharing.

Do note that the Cons cell construction becomes `Cons(1, box Cons(2, box ...))` which doesn't seem particularly bad.


Thanks for the clarification; I do realise this. The context in which the question arose was that several of the "for" arguments seem to state something to the effect of ~ being rare in code due to only occurring in type definitions.


I believe that was just addressing the fact that the type `Box<T>` is more annoying than the type `~T`, since the `box expr` replacement for the `~expr` expression is relatively nice (admittedly I wasn't following the discussion in great detail).


Now that '~' is being removed for pointers, can it be used instead for unary bitwise NOT instead of '!'?


Not specifically related to this exact rust topic, but the interest in rust made me add support to my compiler explorer so you can tap rust code and see how it compiles interactively at http://rust.godbolt.org


That's very cool; how do you get colourise to associate lines to the regions of assembly?


I parse the debug line directives in the assembler output. Something about the way rust/llvm outputs with -O makes this a little worse than the equivalent in C++/clang but it's 'good enough' to get the gist of what's happening I think.


Oh, nice. Rust's debuginfo does seem to have a few peculiarities where lines numbers don't quite work out (or something, I haven't really been able to "quantify" it); but there's currently someone working on debuginfo.


Gee, with this few sigils remaining, Rust is going to have a very hard time finding widespread adoption, since it won't stand out from competing languages!


We still have "fn". :)


..and since you're freeing up ~, you can now rename 'fn' to it. Rust criticism would drop to nearly zero, because everyone would focus in on your crazy function-defining-tilde and those people just don't get it.


fn is my favorite keyword for function definition. "function" is too long. "def" doesn't say anything about functions (unless you read it as DEfine Function). "func" sounds too funny. "defun" always reads "defunct" to me.

And just out of curiosity, where did the rust designers get the inspiration for "fn"? I know plan 9 rc and clojure have "fn". Or maybe it's independent invention?


Well, I slightly prefer "fun", but the Rust community pretty firmly favors "fn", and they're about the same anyway.

As far as I know it came from ML.


"fun" is even funnier than "func"!

ML etymology sounds pretty plausible (I didn't know ML uses fn) since I can see there is a strong influence of ML on Rust.


Anonymous functions in ML, possibly.


So that's what happened to Smalltalk and Lisp.


I like this change.. 'box' is obviously more letters, but cognitively (for some reason) seems to enforce the operation better.


Honestly. it feels like the language is losing something. I'm having a hard time identifying what that is, but I think it's something like the 'Rusty-ness' of the language, similar to how code can be more or less 'Pythonic'.

The language is still in flux and there is only one way to find out whether we will miss '~'. Let's do it.


Is this a good time to point out that the language is stabilizing?


It seems to me that the current focus on "do all the breaking changes we want to do so that we can get to 1.0" naturally leads to a prevalence of breaking changes. So in a strange way, yes, this sort of breaking change is evidence of the language stabilizing.


I don't think we can really consider it to be "stabilizing" when there are relatively significant and breaking changes like this still going on.

It may be headed in the direction of stability, but that's quite different from stabilizing.

We can consider it to be stabilizing once the language and standard libraries have been frozen, and the only changes happening are very minor ones that are fixing critical bugs.

Until then, it's still in the research and development stage, at best.


I think "heading in the direction of stability" and "stabilizing" are the same thing. But pedantry aside, it does really seem to me that the breaking changes going on now are fundamentally different in character than those that used to happen - they are much less about experimental functionality, and much more about "let's fix as many of our frustrations as possible before we're stuck with them". For instance, the specific change under discussion would (I think) be fairly easy to re-add backwards compatibly, but probably impossible to remove.

But meh, this maybe ours is a (boring) purely definitional disagreement - I think we can consider it stabilized once the language and standard libraries have been frozen and only bug fixes and minor changes are occurring.


It shouldn't be a huge change for users of Rust - `~` is used far less than most people think.


Indeed. Most of the usages I've written have been ~[...] or ~str. I think both have drop-in replacements. (And if I had some bloody time, I'd update my code and find out.) This kind of change doesn't affect how you write code the way that the 1:1 thread/M:N model thing does.

Note: I'm not laughing at you, I'm laughing with you.


When will people get over syntax? It's a bit ridiculous how much time we spend fussing over ASCII considerations instead of working on novel ways to present code (making the manner it was written irrelevant).


Is the comparison to Python that great? A language like Rust has more things that you have to keep track of yourself, as a programmer. Having English-like syntax might work great in a language with relatively simple semantics, but I don't think that it necessarily follows at all that that kind of design scales to languages where you have to be explicit on the level of pointer types and such.


That was one of my most used features. This stinks!


The feature isn't going away, just the syntax.


Oh thank Christ.


Read before you post!




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: