[–]▶ No.838986>>839031 >>843301 [Watch Thread][Show All Posts]
Some people like throwing exceptions all over the place, putting try and catch blocks on anything they can (such as args parsing, etc), and generally making a mess of things. I find that introductory programming courses really encourage this kind of behavior because they are required to have a section that teaches about exceptions.
Some people say that you should almost never throw exceptions, unless the problem truly is exceptional. This makes a lot more sense to me.
However, recently I learned that people are putting exceptions into their constructors because we're all being forced to use shitty languages that have no other way to return a failure from a constructor or to check the constructor's inputs. Is this really the solution (for langs such as c++)?
What do you think?
▶ No.838988>>838991 >>839075 >>843184
I only use asserts, and have literally never used exceptions. I work on games, where exceptions are discouraged and pretty much never used at all.
▶ No.838991>>839000
C++ projects that avoid exceptions do empty constructors that require an initialize() call. I don't think it's worth avoiding them today as almost all platforms now produce mostly sane code for them, although there are still some horror shows. They should only be used to handle unexpected errors though, as they're still a complex, bloaty, and awkward form of feedback. E.g. if you're writing a network transport and your "buffer full" feedback is an exception then you've fucked up.
>>838988
>shitty gamedev error 'handling'
gamedevs really shouldn't be in these conversations.
▶ No.838993
error checking is for the weak
you either write bad ass code in one pass
or you go home
▶ No.838995>>839195
Also, I'd suggest networking as the trial by fire for error checking. Try writing some non-trivial low-level networking code in Linux to get a feel for how your method of error handling works. My C code is almost always more than 50% error handling. If you want to get that closer to 100%, try using anything where you need to work with CMSG headers.
▶ No.838998>>839075
If a function can fail, you just make it return something indicating it failed, such as -1, false, 0, None, Nothing, or even writing to an output variable if the language forces you to. Exceptions are some retarded shit for the same group who think the precanned HTTP methods and error codes have any point.
Fun fact: 50% of the code in existence which relies on exception handling will just fail and show the exception to the user, leaving the code still broken because the exception wasn't properly handled. The other 50% will just fail, be ignored by a top level handler, and not tell the user anything, _still_ leaving the program in a broken state.
While you _can_ use exceptions properly, it just ends up being a roundabout way of having "exceptional" return values.
▶ No.839000>>839002
>>838991
>They should only be used to handle unexpected errors though
If you write the code to handle it, doesn't that mean it's expected?
▶ No.839002>>839003
>>839000
Think of a web browser. Getting a 404 is an expected error, and handling it out of band would just complicate the code.
▶ No.839003
>>839002
He's just being a smartass I hope. If not then there are Amish people with more understanding of tech than him. Wouldn't surprise me given the scummy neo luddites that show up here sometimes.
▶ No.839005
I'm guessing exceptions are not the same as errors. However I can't really think of an example where an exception isn't an error.
▶ No.839006>>839010 >>839057 >>839223 >>840777 >>843302
exceptions aren't just for error handling
this is how you break loops in python
class LoopBreak(Exception):
pass
b=3
try:
while(1==1):
for i in range(0,10):
if i==b:
raise LoopBreak
except LoopBreak:
print("i=b")
▶ No.839008>>839064
Actually, exceptions are an elegant way of handling what can be incredibly obtuse chains of failures in real-world software. The only real argument for not using them is in the case of absolute time/space determinism needs (as in realtime application areas).
And as far as C++ is concerned, the language will let you write as much error code spaghetti return code as you'd care to though you'd be ignorant to say the least to use that approach when RAII is so beautiful mathematically.
▶ No.839010>>839124
>>839006
That's horrific and must be outrageously expensive. Just use a variable like someone who isn't deliberately trying to be the biggest faggot in the world.
▶ No.839031
>>838986 (OP)
I think the sole purpose of the post is provoking hostile reaction.
▶ No.839057>>839061 >>839064
>>839006
Anon, I'd like to introduce you to my friend; his name is break.
▶ No.839061>>839064 >>839066 >>839067
>>839057
He's trying to work around python not having a multi-level break, and instead of just adding a variable like anyone sane is using a massive amount of bloat and a custom class.
▶ No.839064>>839085
>>839057
>>839008
breaks don't break out of multiple layers of loop
>>839061
this
▶ No.839066>>839068 >>839071
>>839061
it's not just a workaround i'm pretty sure this is the suggested "pythonic" way to do multilevel break in python. i'm not suggesting it's good, but it's python.
▶ No.839067>>839069
>>839061
loop1:
#do some shit
loop2:
#do some more shit
break
break
#even more shit
▶ No.839068
>>839066
No well-run python project would allow someone to commit that.
▶ No.839069
>>839067
The inner loop needs to set a flag as the second break is conditional.
▶ No.839070
I like Erlang, "Let it crash", way of error handling. Basically processes are organized in the hierarchical order within process tree. If something unexpected happens you just restart sub-tree and start from clean state.
It is a lot easier than trying to enumerate all the errors. And it is a lot safer to start from clean state than trying to fix state when error is detected.
▶ No.839071
>>839066
The pythonic way is to do it with
def execute():
shellcode = bytearray("\x31\xC9\xB8\x02\x00\x00\x00\x31\xDB\x39\xD8\x7E\x03\x43\xEB\xF9\x01\xD8\x41\x83\xF9\x05\x75\xF1")
▶ No.839075>>839087
>>838988
>I work on games, where exceptions are discouraged and pretty much never used at all.
So (You) are the reason why when games crash, they crash with either Unhandled Exception or Segmentation Fault. Let me guess, you also use asserts to check if the pointers are not null?
>>838998
In my experience, albeit limited, there's very little that you can do after catching the exception, other than CLE: 1) clean up, 2) log and 3) exit.
To me an exception represents an unfixable error: data is corrupted, data can't be read, data can't be written, file can't be opened, memory can't be allocated, this sort of thing. The kind of thing which is a fatal error because it doesn't make sense to retry doing it once it failed. So basically, a user inputting the wrong password is not an exception, but not being able to open the password hash file is. If I'm wrong teach me.
▶ No.839085>>839086 >>839125
>>839064
The only use case for goto. This and meta generated automatons.
▶ No.839086>>839200
>>839085
goto is also very useful for error handling.
▶ No.839087>>839091
>>839075
lemme guess you'd like the game to crash with Handled Exception.
▶ No.839091>>839096 >>839111
>>839087
No, I'd like it to crash with a proper error message, you little faggoteer.
▶ No.839096
>>839091
>looks like this bear ass isn't collectible, better crash the player's game without saving rather than handle the error
▶ No.839111>>839131 >>840778
>>839091
In games it is unimportant, wow the game crashed after 16 hours of gameplay, too bad, just restart the game faggot, big deal.
If you have to constantly catch exceptions, your code is shit. Better discover your programming errors with asserts during development, and fix them immediately, than having to do run-time damage control with slow ass exception handling.
▶ No.839124>>839132 >>839133
>>839010
Python uses exceptions internally all over the place. They're relatively inexpensive, taking the efficiency of the rest of the language into account.
For example, StopIteration.
▶ No.839125>>840507
>>839085
If you didn't have while loops then implementing a while loop using goto would also be a use case. I can't help but feel that use of goto is a symptom of a missing feature.
▶ No.839131>>839138
>>839111
>just restart the game faggot, big deal
>If you have to constantly catch exceptions, your code is shit.
gamedevs, everyone.
▶ No.839132>>839136
>>839124
They're extremely expensive. Don't make me rub your nose in this.
▶ No.839133
>>839124
this tbh. the language is such shit that worrying about exception costs is like worrying that you tracked a little bit of dirt into the pigsty.
▶ No.839136>>839166
>>839132
I said "relatively". Python exceptions in particular are not that bad compared to all the other things in Python, which also tend to be slow.
▶ No.839137
Exceptions are fantastic. You don't have to think of every edge case when you can just handle a blanket exception and log something about it.
You can also avoid messy if/else if/ else blocks or switch statements if you replace it with the code that covers the intended case in a try block.
▶ No.839138>>839178
>>839131
Games run fast. Even terrible 30fps games are way way faster than pretty much everything else you use.
But hey at least all the other software never crashes due to all their error handling right.
▶ No.839166>>839249
>>839136
It's a big "relatively". They're super heavy. Even in that simple example earlier where most of the time is spent printing, they're still heavy enough to double the runtime.
#!/usr/bin/python
class LoopBreak(Exception):
pass
def foo1():
b=3
try:
while(1==1):
for i in range(0,10):
if i==b:
raise LoopBreak
except LoopBreak:
print("i=b")
def foo2():
b=3
done = False
while(1==1):
for i in range(0,10):
if i==b:
done = True
break
if done:
break
print("i=b")
for i in xrange(1000000):
#asdf
#foo1()
#foo2()
$ time ./foo.py > /dev/null
real 0m1.855s
user 0m1.843s
sys 0m0.015s
$ time ./foo.py > /dev/null
real 0m0.950s
user 0m0.937s
sys 0m0.015s
▶ No.839178>>839192 >>839215
>>839138
>Games run fast. Even terrible 30fps games are way way faster than pretty much everything else you use.
lol. I do low-level networking and I can guarantee you that 99% of gamedevs can't even figure out how to properly handle affinity let alone do anything that needs to be fast. It's funny to real programmers as gamedevs don't realize they're looked at like webdevs with egos.
▶ No.839192
>>839178
>real programmers
truly embarrassing
▶ No.839195>>839225 >>839394
>>838995
What's the best language for network shit?
>inb4 rust
▶ No.839200
▶ No.839215>>839216 >>839246
>>839178
>how to properly handle affinity
not him, but what is this?
▶ No.839216
>>839215
What anon really meant to say was, how to properly handle "furaffinity".
Do i need to say more?
▶ No.839223>>839249
▶ No.839225>>839231
▶ No.839231>>839289
>>839225
What is the best language that is actually being used?
FP is a meme anon
▶ No.839246
>>839215
You want to tell your operating system to schedule a program on the same core/s each time to reduce cache misses. Setting this is usually refered to as setting a programs "affinity".
Most people don't need to care since computing power is a dime a ghz. Sometimes if you're running on resource constrained systems you need to care.
▶ No.839249
>>839223
no shit, what a turd, so this actually is the correct way to do it in python.
https://www.python.org/dev/peps/pep-3136/
and they're never going to change it.
code that requires breaking out of more than 1 loop is "complex". and god forbid they add the functionality and programmers do shit with it they don't like and can't read.
that pep states all the alternatives that I can think of, all of them shitty.
1 - use a variable for each layer of loop and end up with a mess of variables and checking to break each loop
2 - Break exception
(1 and 2)
>>839166
3 - basically 1 but using more if statements at the end instead of checking a variable.
The loop break exception, 2, makes a lot more sense to me but fuck, that 100% performance hit. Option 3 has to perform worse by definition than 1 because it's just multiple if statements instead of the one if statement for the variable.
I'm glad I got used to straight C again.
▶ No.839289>>839313
>>839231
FP can be a meme, and it's certainly not something your average JS/Java dev is going to care about, but there are companies out there writing solutions in Erlang.
Racket is also quite nice to write servers in, but as you said actually used, I assume you mean popular. None of the popular languages really add much to sockets over what C is doing, although Go has features which remove the complexity of multithreading.
If I had to write a server right now, I'd choose in order of preference: Erlang, Ada, Racket and C. If I thought it might be maintained by others, then Go would be a good choice.
tl;dr Use Go.
▶ No.839313
>>839289
nice try google shill
▶ No.839394>>839448
>>839195
C and C++. I'd strongly recommend C-like C++ as exception handling drastically reduces the ridiculous amount of error handling.
▶ No.839448>>839557
>>839394
>exception handling drastically reduces the ridiculous amount of error handling.
explain further
▶ No.839557>>840487
>>839448
Use of RAII and exceptions means in most cases you can just skip adding any error handling. You also don't need to write error forwarding either (call function, returns -1, check if it returned -1, return -1, etc..).
▶ No.840487>>840515 >>840581 >>840637
>>839557
>use RAII + exceptions == no error handling code needed
pajeetgod tier error handling:
int main()
try
{
}
catch (...)
{
std::clog << "Sorry!\n";
}
let's hope the global object constructors don't throw, because I dunno how to catch those.
▶ No.840493>>840516
>have to work with java for CC uni
>as if the language wasn't shit by itself, every fucking library throws exceptions
I fucking hate this shit. I can't just validate input on a higher layer and send it down on the basis that it's going to work, the language assumes you're a retard and everything is going to break if they let you handle basic shit though I guess that's true, for most >java programmers, at least.
Why can't they just make functions that return null if shit fucks up instead of forcing you to use try catchs or throwing shit?
▶ No.840507
>>839125
Imagine break and continue statements taking a loop top-level argument (break(2) break out of two loops, for example). This would be pretty good.
▶ No.840515
>>840487
even better:
fn main() {
let arg = std::panic::catch_unwind(|| std::env::args().nth(1).unwrap().parse::<i32>().unwrap());
println!("{:?}", arg);
}
▶ No.840516>>840566
>>840493
How do exceptions give you less freedom to handle shit than null return values?
▶ No.840566
>>840516
With exceptions, you have to treat them, or else it might not even compile, whereas you can do whatever you want with nulls.
I can't think of anything right now, but let's say you have something in your program that may not run in some computers. It's just a fancy cool thing you want to run, but there's no detriment in not running it, the user doesn't even need to know that it didn't work. Maybe it's a bug regarding hardware or just some OS stuff.
Anyway, with null returns you can just call the function. Done. You don't need to know if it ran or not.
With exceptions, however, you need to treat it, no discussion. So you end up with an useless try catch in the middle of your code that serves no purpose.
Another case where null values are better is like the above, where you won't treat it, except in this case you already know it's not going to generate errors.
Your program does something like, for example, opening a file, except you have a front end for the user that makes sure the file exists.Maybe your program scan for files and only lets the user select from those, in any case, it won't try to open an invalid file.
With nulls, you just call the function and open the file. Done.
With exceptions, however, you, once again, need to either have an useless try catch, or just throw everything for as long as you can. It both clutters your code and it's simply unnecessary.
Plus, if you are doing many things at once, you might need to nest try and catches, which looks fucking disgusting.
▶ No.840581>>840688 >>840807 >>842459
>>840487
>let's hope the global object constructors don't throw, because I dunno how to catch those.
Like this:
struct muh_type
{
muh_type() { throw 0; }
};
muh_type muh_object = []{
try { return muh_type(); }
catch (...) { std::cerr << "muh exception handling"; /* ... */ }
}();
▶ No.840633>>840654
Funny how Rust solves all the constructor problems by going back to the old way.
In Rust, "constructors" are just a convention:
impl<T> Vec<T> {
pub fn new() -> Vec<T> { ... }
}
>Constructors are static (no self) inherent methods for the type that they construct. Combined with the practice of fully importing type names, this convention leads to informative but concise construction:
use vec::Vec;
// construct a new vector
let mut v = Vec::new();
>There is exactly one way to create an instance of a user-defined type: name it, and initialize all its fields at once:
struct Foo {
a: u8,
b: u32,
c: bool,
}
enum Bar {
X(u32),
Y(bool),
}
struct Unit;
let foo = Foo { a: 0, b: 1, c: false };
let bar = Bar::X(0);
let empty = Unit;
>That's it. Every other way you make an instance of a type is just calling a totally vanilla function that does some stuff and eventually bottoms out to The One True Constructor.
>Unlike C++, Rust does not come with a slew of built-in kinds of constructor. There are no Copy, Default, Assignment, Move, or whatever constructors. The reasons for this are varied, but it largely boils down to Rust's philosophy of being explicit.
Constructors were a mistake. Exceptions were a mistake. Rust uses the Option enum for returning errors.
https://doc.rust-lang.org/book/first-edition/error-handling.html#the-option-type
▶ No.840637
>>840487
You don't understand, but then that's expected. With RAII and exceptions, you don't need error handling and forwarding on calls where you weren't doing error recovery. The exact same error response as you might have written in C can thus be coded with a tiny fraction of the error handling code, which is good as error handling code tends to be extremely poorly tested and buggy.
▶ No.840654>>840771
>>840633
let mut v = Vec::new();
Somehow this is supposed to be better than
Vec v;
lol rust.
You can do the same static pseudo-constructor thing in C++ if you really want to, by the way.
>Rust's philosophy of being tedious and ugly
fixed
>Rust uses the Option enum for returning errors.
>le .unwrap() syntax noise face
▶ No.840688>>840807
>>840581
That's disgusting even for C++, congrats!
I have a question though, what if the move constructor throws? Or is it the copy constructor, I'm not 100% sure. Please don't tell me about noexcept because I'm not in the mood for std::terminate.
▶ No.840745
>That's disgusting even for C++, congrats!
Is straightforward simplicity and an absence of dumb syntax noise considered "disgusting" by the rust community? Is rust the cause of mental illness, or do you have to be mentally ill to like rust?
>if the move constructor throws
If you build your shit right, there's no reason it should be able to.
>Or is it the copy constructor
You catch the exception and deal with it. Or you don't, and let the program terminate. There is nothing special about the copy constructor in that regard.
▶ No.840771>>840801
>>840654
Constructors aren't mandatory in Rust, did you even fucking read the post?
▶ No.840777
>>839006
>goto-oriented programming is considered pythonic
No wonder the productive half of their ecosystem avoids the python 3 half like aids
▶ No.840778
>>839111
1337 skiddie tryhards like you are the reason metrosexuals like EA now own the game industry
▶ No.840801
>>840771
>Constructors aren't mandatory in Rust
Where did I imply that they are? Did you fucking read my post? I was comparing C++ constructors with whatever rust has that has the same capabilities and general semantics. Comparing constructors with plain named initialization (which C also has and C++20 will have) is like comparing apples to oranges.
▶ No.840807
>>840688
Just to mention, in >>840581 (when you remove the throw statement) neither the copy constructor nor the move constructor is ever called, thanks to guaranteed copy elision (since C++17). It's truly zero overhead. And if you want to limit the boilerplate, just declare all your global variables as fields of a struct with default values, then instantiate that struct and do the try-catch thing just once. Normally you shouldn't have that many global variables anyways.
▶ No.842459
>>840581
These names are hilarious.
▶ No.842886
EAFP is literal trash that leads to nothing but legitimate errors being silenced, I avoid it as much as possible (except for things like writing to files where I need to check the writes gone through etc).
▶ No.843184>>843299
>>838988
asserts are for when you get to an internal state in your own code that you didn't expect. An assert should never get triggered and if it does it implies you should fix something in your code.
Exceptions (or equivalent logic to propagate errors to the caller) are for a state caused by something external to your code, but that you cannot handle. An example is the environment, where if a file is missing we might be able to propagate that error up to a level where we could tell the user about it. Similarly if they are not connected to a network. Another example is bad input to a library. As the library author you can't guarantee that the user gives you valid input so you need exceptions to tell the user about this.
As a game dev, it makes sense that you don't use exceptions because you are writing a single monolithic product, not a library.
▶ No.843299
>>843184
*game server shits itself*
better not provide contingency plan for this on client
▶ No.843301
>>838986 (OP)
I only put try/catch statements to handle the programming language's own exception throws.
▶ No.843302
>>839006
You could make an anonymous function and use "return" to get out of all the loops.