Learning Rust :safe:

Thanks for that tip @dirvine

Now I get this nice output

Have to say the ‘h’ option is much more useable then than ‘v’ for vertical on any more than two logs being viewed simultaneously

4 Likes

@happybeing Wow, your cli tool is really cool! Pretty impressive! Thank you for sharing.

I’ve just finished my first PR to the Rust code base by improving documentation on the Copy trait:
https://github.com/rust-lang/rust/pull/75049

I am really looking forward for this getting merged! :smiling_face_with_three_hearts:

I hope this thread will motivate people to start learning Rust! :crab:
Rust has the most welcoming community! If you have any questions, you will get a dozen answers and you will be treated with respect and empathy. :hugs:

4 Likes

Thanks @janriemer, it’s mostly a copy paste and adapt job, and as David discovered I’m still learning the basics. I’ve learned a lot doing it, and am very pleased to have used async functions to handle two concurrent tasks so easily.

I’m very impressed to see what you’re up to, and contributing to such a great project is awesome. Well done!

Thanks for testing it out @dirvine, and for the bug report. I’m still figuring out error handling - most of my code tries to do this but quite a bit doesn’t. The bug you found was something I copied and pasted, so I’m still learning to recognise things like .expect() for what they are. You found an interesting edge case though, because it’s ok for the logfile not to exist yet, but the path must be valid so I need to catch that!

Thanks @southside for testing it out and for posting the picture.

Any Mac or Windows users able to give it a go? If be interested to see what happens.

3 Likes

I’m on Linux at the mo but I’ll give Windows a try later. On Mint I found I had to sudo apt install gcc-multilib to get it to build. Working now though.

3 Likes

As you suspected, it doesn’t build on Windows 10.

Compiling quote v1.0.7 error[E0433]: failed to resolve: maybe a missing cratesys? --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\lib.rs:24:9 | 24 | pub use sys::size::terminal_size; | ^^^ maybe a missing crate sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\lib.rs:27:9
   |
27 | pub use sys::tty::{is_tty, get_tty};
   |         ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
 --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\async.rs:5:5
  |
5 | use sys::tty::get_tty;
  |     ^^^ maybe a missing crate `sys`?

error[E0433]: failed to resolve: maybe a missing crate `sys`?
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:29:5
   |
29 | use sys::attr::{get_terminal_attr, raw_terminal_attr, set_terminal_attr};
   |     ^^^ maybe a missing crate `sys`?

error[E0432]: unresolved import `sys`
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:28:5
   |
28 | use sys::Termios;
   |     ^^^ maybe a missing crate `sys`?

error[E0425]: cannot find function `get_tty` in this scope
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\async.rs:14:36
   |
14 |     thread::spawn(move || for i in get_tty().unwrap().bytes() {
   |                                    ^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_tty` in this scope
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\async.rs:43:36
   |
43 |     thread::spawn(move || for i in get_tty().unwrap().bytes() {
   |                                    ^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:45:9
   |
45 |         set_terminal_attr(&self.prev_ios).unwrap();
   |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_terminal_attr` in this scope
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:90:23
   |
90 |         let mut ios = get_terminal_attr()?;
   |                       ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `raw_terminal_attr` in this scope
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:93:9
   |
93 |         raw_terminal_attr(&mut ios);
   |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
  --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:95:9
   |
95 |         set_terminal_attr(&ios)?;
   |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:107:9
    |
107 |         set_terminal_attr(&self.prev_ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `get_terminal_attr` in this scope
   --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:113:23
    |
113 |         let mut ios = get_terminal_attr()?;
    |                       ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `raw_terminal_attr` in this scope
   --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:114:9
    |
114 |         raw_terminal_attr(&mut ios);
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error[E0425]: cannot find function `set_terminal_attr` in this scope
   --> C:\Users\John\.cargo\registry\src\github.com-1ecc6299db9ec823\termion-1.5.5\src\raw.rs:115:9
    |
115 |         set_terminal_attr(&ios)?;
    |         ^^^^^^^^^^^^^^^^^ not found in this scope

error: aborting due to 15 previous errors

Some errors have detailed explanations: E0425, E0432, E0433.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `termion`.

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: failed to compile `logtail v0.1.2`, intermediate artifacts can be found at `C:\Users\John\AppData\Local\Temp\cargo-install2u6Wab`

Caused by:
  build failed`
2 Likes

Thanks John, if you’re willing to try again in a bit I’ll look into what I think is needed for Windows and create something for you to try. Is that ok? You’ll need to clone the repo and build that rather than just cargo install, but first I will need to make some changes to the code.

1 Like

Yep - happy to help. May be tomorrow now though. Bed beckons.

2 Likes

Yes, here are my enemies
Panic (aborts program)
expect (aborts with message)
unwrap (will abort if error exists)
let _ = This generally is a wee bugger and exists in our code. The dev has said, this is a Result and I am gonna ignore the return type and keep going as I know better than the compiler, or at least I think I do.

As ever these things exist so folk will argue they are valid and can be correct, but IMO they are land mines. Either the underlying lib is bust or we are fooling ourselves. I have had debates with incredibly smart folk that these things are Ok, I say they are 100% not Ok. I often see devs from C / C++ being the worst culprits, super knowledgeable and talk about memory alignment calls and register storage and all the fancy pants stuff, however to me it’s no debate, dangerous is dangerous and we don’t know more than the compiler on almost 100% of these occasions.

Best to handle errors if possible, but never ignore them. If we cannot handle an error we should pass it up the stack, if no module can handle it then our program may be in undefined state, then we abort. This position forces error handling, then all we worry about is logic errors :wink:

9 Likes

IMO expect, unwrap and panic are fine in some cases.

For instance prototype code, so when you are just throwing something together to see if its what you want. No reason to spend any extra time handling errors when you are adding and removing code so frequently.

If a test should fail it’s pretty straight forward to just unwrap or expect things sometimes.

I also sometimes use these as insurance for me as a developer. For instance if I’m doing something where I know that “if this fails, I as a developer has done something wrong in the code, but it should never fail”. Then if I put an expect there I can force the program to crash instead with some useful message. In this case I’m using them for the same reasons asserts are used.

So I’m not of the opinion that they should be avoided at all costs in all cases, I think they have good use cases.


I’ve been learning Rust for a few years and I think it’s the best language.

I tried to get started building something for the SAFE network in Rust in 2018 and 2019, but I couldn’t figure out how to get a basic working application, and I couldn’t find any explanation of the API or examples that I could use as a starting point or anyone with time to help with those things. So instead I decided to commit more fully to a tool I’ve been experimenting with on and off for like 5 years at this point.

I’m working on a node based texture generation tool called Kanter. Have rewritten it at least 4 times trying to find a working architecture, but now the library is working and I’m creating a graphical user interface for it using OrbTk.

Since OrbTk is in development I’m running into bugs and gaps there, and it’s really fun to be able to help them out with reporting bugs, fixing issues I find, adding missing features etc. The maintainer is really welcoming and active, and he’s happy to help anyone who’s running into issues or wanting or trying to contribute, so it’s really fun. Feels like a proper collaboration!

It’s all really hard and really rewarding, and Rust is helping me all along the way.

In C or C++ I would not even dare to try building multi-threaded execution of a directed acyclic graph, which is the core of my application. But thanks to Rust being Rust I have actually done it, to my own astonishment. Rust is literally allowing me to do things that I wouldn’t be able to do otherwise, that’s amazing.

4 Likes

Thanks David, useful pointers - hadn’t seen let _ = yet so I’ll beware! My first job is to get used to writing bullet proof Rust so I appreciate your help there, (especially having written many times more C/C++ in my time than anything else :wink:, and much of that before we had decent support in the language such as try/catch). But this is slow as it’s hard to find good examples or a decent tutorial. The compiler is a great help, but I need to spend some time digging into the handling, or more propagation, of errors.

Great to hear what you are up to @lukas. Kanter sounds very interesting (I like graph network stuff :grimacing:). Be interested to see a demo at some point. BTW I was a bit confused by the description “node based” because it made me think it of Nodejs, so I’d consider clarifying that (maybe add “written in Rust” right up front :sunglasses:).

4 Likes

I can try to remember posting here when there’s something to see. :slight_smile:

Thanks for the input on the description, I’ll think about it!

2 Likes

A post was split to a new topic: Rust error handling for production and test

Thats awesome, I didn’t know about returning results from tests.

1 Like

Very useful read! I also didn’t know you could return results from tests.

I think the suggestion that tests should have same quality as production code sounds like a great rule of thumb. It also makes it more clear what is actually being tested. Having a single assert at the end of a test without any other potential failure points (unwraps etc) makes it very clear what’s being tested.

1 Like

@moderators, please split from David’s post above into a new topic: Rust error handling for production and test

I think this deserves its own topic so it doesn’t get lost! Thanks.

EDIT: Thanks @sascha, please can you move the responses to David’s post across too.

5 Likes

Thanks again David, I’ve more to do on error handling but this one is now handled properly.

2 Likes

well it doesnt crash :slight_smile:

2 Likes

It always worked with a logfile that doesn’t exist yet - the crash David found was if the parent directory doesn’t exist. It now exits and tells you why.

Currently working on a version for Windows.

3 Likes

Rustedbottom man speak with unforked tounge…

1 Like

Are you asking about the async/await Syntax sugar vs futures::Future adapters, like then etc?

Thats right, you need 3 things:

  1. the async/await syntax sugar (or the futures adaptors or a custom impl of the Future trait) to join different parts of your code, let them run after each another, etc… This is just using the API of the Future trait. The async/await syntax is now a native part of the Compiler (+ some basic things like a trimmed down variant of the Future trait and the waker API)

  2. the executor runs “tasks”. A task is a boxed Future. It does that by calling the Future::poll method for all registered tasks. An executor can also run multi-threaded on a threadpool.

  3. the reactor does the actual IO and calls into the waker to wake up a tasks (or rather the executor the task is running on) when an IO op has finished. You cant just mix multiple reactors, but it might work, it depends on the reactors you are running.

Rust has just the minimal required apis integrated to support the async/await syntax but nothing more. You need to installiert an external executor/reactor.

4 Likes