Are you professional programmer? Wanna ask about your learning methode

Hi, Rust is my first languange, just for fun only and i like this stuff. I wrote The book summary on personal blog every time i finish the chapter, so i can read it anytime to recall my memory.

So as a professional programmer in Rust, are you memorize syntax? just curious.

Thank you.

The thing I try to do is not to copy/paste things that are new to me. I type it out every time. If it's something I retype enough I will eventually learn it from memory.

And eventually I stick things in editor macros so I don't have to retype them, but as a general principle I only add things that I already know by heart.

I very rarely sit down and actually try to memorize syntax -- it happens implicitly while actually writing the same code over and over again.

9 Likes

Great, thank you. I'll do that.

I think focusing on memorization is the wrong way to go in programming. With very few exceptions what matters most is being able to find the information you need. Whether or not you know it off the top of your head affects how fast you can finish a given task, but speed in a "words per minute" sense basically never matters in professional programming.

As an oversimplified example: If you know Vec has a method to preallocate storage and you know where the docs for std are, not knowing the exact name Vec::with_capacity realistically isn't going to slow you down that much. But if you don't know it exists and just use Vec::new because that's what you remember, that can actually cause noticable performance problems even in relatively simple programs[1].

Knowing the basic concept of pre-allocation, some keywords, and where to find the docs get you most of the value. Remembering with_capacity specifically is nice, but not required.


  1. though it usually only matters when you're creating a lot of Vecs or copying very large data sets ↩ī¸Ž

16 Likes

For me, Rust is not my first language. I have about 20 years of C# experience. To learn Rust I proceed in such a way that I write myself short "recipes" how to transfer the patterns known from C# correctly into the Rust world. So, for example, how I translated the concept of try-catch I know into Rust using its Result<T, E> etc. However, it feels like many Rust concepts are close enough to C# concepts that the learning curve is minimal. Then after a few days or weeks of Rust development, concepts like Result<T, E> etc. were familiar.

Yes, I learn the syntax rather implicitly, though. I don't spend hours or days explicitly learning the Rust syntax, but start directly with a small project, a tool I could use or even a tool I have already written in another language. By rewriting this tool in Rust, I learn the language with its concepts and syntax.

Which actually helped me a lot: using ChatGPT Plus as a personal tutor. I can ask the AI as many Rust questions as I want. And most importantly, I can ask from a context I know. For example, I can explain to the AI how I would do something in C# and then ask for help on how to implement that concept in Rust.

This works surprisingly well. Then, when the AI does hallucinate and claim nonsense, the Rust compiler comes along and says directly what doesn't work and why. In combination with the Rust documentation and this forum, this is indeed very helpful.

So that's my learning method for Rust :grinning:.

1 Like

I think the best way to learn things is to use them. Memorisation is probably the worst way to learn something because, although it will let you recall a specific piece of information, it doesn't help you apply it or combine it with other ideas. Oh, and your "memorised" facts are constantly decaying, so you have to keep re-memorising them forever.

Actually applying information allows your brain to make stronger connections between ideas, which helps them stick in your memory, and makes them easier to use. When you write a sentence, you're not thinking about every single word in isolation, you're recalling patterns of words and common sentence structures and filling them in on the fly using those connections. In some ways, a programming language is not that different to a natural language.

Pick a project that's either something you're very familiar with, or don't know how to do but are interested in. Do it in Rust. Get stuck and completely fail? No you didn't, you learned more about what not to do. Scrap it, start again. Just keep writing and trying stuff. The world doesn't need yet another slow, crappy raytracer or another awful scripting language... but you're doing it to learn, so that's fine.

If you use something, you'll remember it. If you don't use it, why bother remembering it?

Speaking of which, I need to get around to finding an excuse to learn CUDA. And LLMs. I actually have a really, really terrible idea for that, but need to find time...

7 Likes

No, I never specifically set out and memorize syntax. That's one of the most useless things you can do with your time.

If it's your N-th language (I knew at least some of Basic, C, C++, Python, Objective-C, JavaScript, Swift, and Haskell before I learned Rust), learning new syntax will come naturally, and you'll be able to focus on the important things. Syntax is not one of them.

Well, it kind of is – nobody wants to learn crazy, very unfamiliar, inconsistent, highly context-dependent, or otherwise ugly syntax. But as syntax is somewhat arbitrary, it's the absolute easiest part to learn. The syntax is what it is because someone defined it like so. There's nothing interesting in syntax. Good syntax is boring and it gets out of the way.

What's interesting about a language is its semantics. That's where the "whys" come forth, and what people struggle with as well. Commonly, even when someone says or thinks s/he is confused "by the syntax", it's not actually the syntax. It's the meaning behind it.

Learning to program by memorizing is not a productive approach. You can't possibly memorize everything that's ever going to be needed or useful for you. My benchmark for knowing a technology is: I know it when I know my lexical stuff by heart not because I specifically set out to memorize it, but because I've used it enough to solve problems that I naturally remember it.

Try to solve problems and understand why the things are the way they are. Use the language and the libraries – knowing by heart what combinators Option has or which functions you can use for splitting a string is valuable and makes you productive – but only if you actually learned to use them. You can recite all the method names of u64 and still be completely clueless as to how to sort an array of integers.

7 Likes

When we are little children learning our native language for the first time do we memorise syntax? No. We don't even know what syntax is. We hear people speaking and make connections between their sounds and objects/actions in the world around. We start to speak, making whatever noises we can, slowly we find what works best and before long we are making words and sentences.

For me all that work on grammar and spelling etc in school was very tedious and to this day I can't tell you the grammatical rules of English and my spelling is terrible.

I believe it is the same with learning programming languages. Or even learning to program initially. We see code in books and tutorial, on forums on YouTube in programs that interest us, we start to imitate it, we write out what we find and tinker with it to do what we want. Learning by doing. All that syntax detail gets somehow magically absorbed into our minds.

Now here is the magic part: The Rust compiler puts out very nice error messages when we make mistakes, it shows exactly where we have gone wrong and very often suggests ways to fix it. It's kind of fun having a conversation with the compiler. And if we use rust-analyser in our editor mistakes are brought to our attention as we type. Highly recommended. So it does not matter if we forget syntax details most of the time.

Of course it helps to have a good memory, even if only temporarily, so that one does not constantly have to fix mistakes and look things up. But I don't thing there is much we can do to improve that and all that effort to memorise details is tedious.

Having said all that, I strongly suggest reading the Rust book, maybe more than once, so that one is aware of what can be done even if one immediately forgets the details of how to do it.

7 Likes

The best advice I can give is to take advantage of the tools.

The compiler is a huge help! I've been using Rust in some way for 6+ years, and there's still no way I could always get all the &s and borrowing perfect the first try. There's just no reason to bother -- get close, and let the compiler remind you of the little details.

Call a function without all the parameters and let the compiler tell you what you need to add. Write foo.bar and let it tell you if it was supposed to be foo.bar(). Leave the function -> _ and copy-paste the type from the suggestion. Etc.

9 Likes

I'm a Python veteran (since Python 1.6) but I've also just started learning Rust - went through the Rust Book, and am now studying some open source projects (Aho-Corasick, Regex, Daachorse) to see what idiomatic Rust code looks like. After reading the Rust Book I found the YouTube videos of Jon Gjengset tough but very helpful.
The Rust stdlib API docs are great - but sometimes a bit overwhelming. The Rust compiler is truly amazing in its error messages - but unfortunately I don't always know enough to understand those, so I think for a beginner in Rust it's only helpful for rather simple errors. I'd also say that asking ChatGPT for snippets of sample code can be very helpful - helped me a lot, though you have to be careful and critical - it does make pretty subtle mistakes sometimes.

3 Likes

One thing many people mentioned here that I don't really agree with is how helpful compiler error messages are for learning.

Granted, Rust's compiler error messages are of significantly better quality than anything else I've seen so far among mainstream compiled languages. They are pretty, include suggestions, and are mostly accurate.

However, strangely the only benefit I really feel is the most shallow one, them being pretty. They are easy to read, and the span/source location information is basically 100% accurate (or at least I haven't written enough weird code to expose any span-related bug :grin:). However, while the errors are usually semantically right, they aren't exactly helpful most of the time:

  • If a suggestion is right, it's almost always in a simple enough case that I could have figured it out myself and it was likely just a trivial typo;
  • If the root cause of an error is more complicated, however, for example lifetime mismatches in HRTBs or a missing trait bound in a deeply-nested generic type, then whatever the compiler tells me to fix the code likely won't work at all, or at least it won't be the right solution even if technically correct. Perhaps the prime examples are:
    • "moved because type T doesn't implement the Copy trait" – when the solution is basically never to try and force-add Copy but to completely re-think ownership and borrowing structure, or use helpers such as Option or mem::take();
    • "XYZ requires that the type T lives for the 'static lifetime" – again, adding 'static annotations won't help; when I (and others) encounter such an error, the solution is usually switching from borrowed to owned data, adding Arc, etc.
  • If there is more than one error, usually only one of them actually relates to the root cause; the rest of the errors are often just artifacts resulting from the compiler trying to guess what you meant by your half-wrong code, and then confusing itself into oblivion by doing so.

As a result, I basically stopped looking at how the compiler suggests me to change my code, and I do the exact same thing that I did when working with C++: extract the span information, go to that part of my code in the editor, open the documentation of the relevant function/type, and figure out by myself what went wrong. Sometimes I use the let _: () = expr trick to get the exact type of an expression, but that's all.

So I wouldn't really recommend trying to learn Rust by paying particularly heavy attention to the error messages. They are nice, but you shouldn't be learning the language by hammering your code based on automatic suggestions until it somehow happens to compile.

4 Likes

Agree with you. Although unrelated to your point, I think adoption of a language is quite dependent on the syntax of the language. Like I find languages like Nimlang really unattractive to learn because of its syntax even though it has powerful capabilities, as advertised, such as metaprogramming (which is a capability that is rare among languages, Golang does not even have operator overloading lol). Would you mind sharing your expert opinion on my thoughts?

1 Like

The syntax is the UI for the language. That's what people first see, so I can imagine it is one big factor in adoption. But people are not rational; them being scared away (or attracted) by syntax doesn't mean that it's the most important part.

And then there are legitimate concerns about syntax. For example, the supposedly "readable" indentation-only syntax of Python is terribly brittle when it comes to editing or transferring code. (I wouldn't dare running Python code I got by email, because the indentation might have changed, completely changing what the code does compared to the original.) But forced indentation is good for preventing people from writing ugly code for the most part, so it does have its advantages as well.

As for operator overloading, I couldn't care less. The distinction between operators and functions is, I think, useless for the most part. I'd be happy to write array.at(index) instead of array[index]. I'm of course not talking about "operators" that legitimately have special semantics not expressible using functions alone (e.g., . for field access or & and * for pointer and place manipulation), but add(a, b) really doesn't have any less meaning than a + b. It's just a question of what we are used to based on hundreds of years of mathematical notation.

4 Likes

+1 on that. His videos are great when you try to deep dive into a subject but can't find enough information about it or you feel like you're not really getting it by just reading documentation.
What's very helpful about his videos is that they are mostly stream recordings, so you get to witness multiple Q&A sessions with the stream audience about the current subject throughout the video. So most questions that come to mind will be answered.

2 Likes

On a side note, I feel the problem of unreadable code due to weird/nonexistent indentation is today better solved by just having a standard formatter. Maybe pythons design was influenced by the countless formatting standards used in c/c++.

I think it's exactly the opposite. The compiler might seem unhelpul for you because of your experience, but considering that the vast majority of programmers come from dynamically-typed langauges, the compiler is extremely helpful, specially during the first "steps" into rust.

Consider the following case:

A user comes from any of the mainstream languages and decides to give Rust a try. One of the most trivial tasks is to operate on a homogeneous collection such as Vec, i.e. filtering on it. So the newcomer types something along the lines of this:

let my_vec = vec![1, 2, 3];
    
let filtered = my_vec.into_iter().filter(|num| num > 1).collect();

The compiler will complain first about the comparison, suggesting that we can't compare a reference with an integer:

  |
4 |     let filtered = my_vec.into_iter().filter(|num| num > 1).collect();
  |                                                          ^ expected `&_`, found integer
  |
  = note: expected reference `&_`
                  found type `{integer}`
help: consider borrowing here
  |
4 |     let filtered = my_vec.into_iter().filter(|num| num > &1).collect();

Once the newcomer applies the suggestion, then the compiler complains about a type annotation being needed due to the call to collect:

  |
4 |     let filtered = my_vec.into_iter().filter(|num| num > &1).collect();
  |         ^^^^^^^^
  |
help: consider giving `filtered` an explicit type
  |
4 |     let filtered: Vec<_> = my_vec.into_iter().filter(|num| num > &1).collect();
  |                 ++++++++

Yes, this is a trivial example, but one that I have observed over and over again here in the forums and in SO.

As soon as a user becomes more familiar with Rust, the compiler becomes less and less helpful... which by itself is not a bad thing. On the contrary, I think the compiler error has fulfilled its duty by teaching the new coders about how to write code in Rust. For everything else, there's masterc... this forum :smile:.

2 Likes

The problem with that is you can't force people to use a "standard formatter".

Those who know about, and are willing to use, a formatter are the people who already write nice code. Those writing unindented mess are usually beginners or non-professionals who don't care or genuinely don't know better. No amount of recommendations, good practices, and easy-to-use 3rd-party formatters can change this. If it's optional, not everyone will use or respect it.

The only way to make these people indent their code properly is if the core interpreter's/compiler's parser – that they have to use — unconditionally hard-rejects their code, from day 0.

(Now I'm not saying that languages therefore have to use significant whitespace. Quite the contrary – I'm team braces all the way. But 2 decades of experience proved to me that people only care about hard errors.)

Yes. If you read my post carefully, that's exactly what I wrote.

The compiler can guess what you meant in the most trivial cases. This won't get you very far, though. It may help you successfully write a hello world involving Vec, for sure. But that's like week #1. That's not the hard part of Rust.

No, but that wasn't my point. Most rust code I have read looks very similar. Talking about aspects a formatter would handle. With c++ that was not the case. And neither was python btw. Sometimes I want to rip my hair out when people just don't put any spaces around operators and equality signs.

My hypothesis is that rust code often looks similar because rust comes with cargo fmt included and has a great lsp that can format on save. I think it's less about forcing people and more about making it so convenient that there is no reason for them to not use it.

A lot of people use vscode. You ask on a forum what you need people tell you the rust analyzer plugin. Just a simple one click download and installation away.

Of course there are always people that won't do it, but if the percentege is low enough then it is not really a problem.

But who knows. It might also just be that the ratio of enthusiasts vs more careless people using rust is just very high.

1 Like

The thing for me is that I have worked in all kind of places with a variety of languages and all kind of "in house" formatting standards and coding standards.

It's a pain in the a** keeping in line with all that nonsense.

Then I find Rust. And and cargo fmt. And VS code with just fixes all formatting on ever save.

Brilliant! I don't have to thing about any of that any more.

Now, I don't always agree with what the formatter wants. Well, I don't care. I can live with it. I don't want to think about spaces and brace placement etc on some arbitrary aesthetic grounds. And most importantly I think if everyone did that we would have nice, reader friendly, consistency across the entire code base of thousands of projects that is available for us to peruse.

We should be prepared to sacrifice our personal preferences and whims for the greater good of all involved.

4 Likes