Yep - happy to help. May be tomorrow now though. Bed beckons.
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
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
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.
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 , 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 ). 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 ).
I can try to remember posting here when there’s something to see.
Thanks for the input on the description, I’ll think about it!
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.
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.
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.
Thanks again David, I’ve more to do on error handling but this one is now handled properly.
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.
Are you asking about the async/await Syntax sugar vs
futures::Future adapters, like
Thats right, you need 3 things:
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)
the executor runs “tasks”. A task is a boxed Future. It does that by calling the
Future::pollmethod for all registered tasks. An executor can also run multi-threaded on a threadpool.
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.
Originally this was the part I was missing, but my question to David was also about what Maidsafe were doing because I wasn’t sure how to reconcile the various explanations, but I’ve a decent picture now.
Your explanation is helpful too, thanks as I’m picking up more of the terminology as I go. ‘Boxed’ is a new one. I’m guessing it relates to
Box which I’ve not read up about yet. I think one of the two Rust async books I looked at could do with covering the things you have explained in your post above, because it it an important part of the picture - along with the implications of choosing between the different executors.
This is so atypical (in decades I can’t recall an example like this) that I think it would help if it was covered in the Rust book too.
PS I caused my first panic in libcore yesterday, and how did I manage this - by handling an error in some copied code that originally discarded it with unwrap()!
@JPL, John, sorry for the delay, I had to do a major refactor so
logtail can now be built with two different backends, one of which (crossterm) is a step towards Windows support.
So if you are still up for trying this out, please follow the instructions to get the code in the README (here) and then try building for Windows (as shown in a section below that). EDIT: don’t try it yet, as I’ve found something I need to fix first. See below.
I’ve opened github issue #3 where we can track any changes. I’ve no idea if I’ve done everything necessary for this to run on Windows, so let’s see what happens!
EDIT: I’m trying to cross compile and getting the same errors you were John, so I need to do a bit more before you can have another go.
Not vital, but you could try this and verify you can run the tui-rs crossterm example - see this comment. Thanks.
Yaaaaaaaaay, my PR got merged!
The Rust contributors have been super helpful and I’ve felt very welcome + they’ve responded instantly to my comments (it was almost scary ).
So…if I can get a PR merged into Rust you all can do it too! Just look for something that you think can be improved and open an issue (or directly a PR, if it is a small enough change).
They have a very thorough documentation on how to contribute - I will link it in the wiki.
Supplementary documentation for members and contributors of the Rust programming language:
Documentation on how to contribute to the Rust compiler:
The only thing that didn’t work was
RUSTFLAGS="-A unused" I note it’s commented out in
logtail-crossterm.rs so I’m guessing this is the problem
Running the command without that and everything was hunky dory
Ah yes, thanks for catching that. It’s because of the different command line in Windows.
Blimey, it all worked! Marvelous, thanks very much John. I’ve been making some more changes to the architecture and will start on support for SAFE Vaults soon.
I wonder if it works in MacOS too. Anyone fancy testing it on Mac? If so follow the instructions at https://github.com/theWebalyst/logtail-dash/