Ok, I was skeptical at first, but this is pretty nice.
Thalidomide Vintage Ad Shirt $22.14 |
UFOs Are A Psyop Shirt $21.68 |
Thalidomide Vintage Ad Shirt $22.14 |
Ok, I was skeptical at first, but this is pretty nice.
Thalidomide Vintage Ad Shirt $22.14 |
UFOs Are A Psyop Shirt $21.68 |
Thalidomide Vintage Ad Shirt $22.14 |
>unwrap
>unwrap
>unwrap
now show the code without making it crash on error. Even c looks clean if you don't have error handling
>unwrap()
>unwrap()
>unwrap()
>unwrap()
>unwrap()
i know the language syntactically forcing you to handle all errors is a good idea but damn
C doesn't do error handling at all. In my case if something fails I know exactly where it failed and why. These aren't remotely the same things.
I also didn't mention C at all, and you couldn't do this kind of functional style with C, which is what I'm trying to focus on, but I'm looking forward to you sharing your convoluted macro stack that "kinda" allows you to do the "same thing," inadvertently proving my point without realizing it.
In other words, frick off from my thread, cnile baby duck.
I dont use c, I use zig which handles errors much cleaner than rust codebases. All error types are automatically joined when you propagate it up. Zig doesn't abort on memory allocation failure either unlike rust. Rust is a meme, they can't use the standard library in the linux kernel since it's unsafe (abort on failure), and that also includes all third party libraries. Linus complained about this. Zig doesn't have this problem. Nobody does a "unwrap" for errors that can happen in zig because the language makes it very clean to handle properly.
I have used zig before I used rust. Zig's errors are essentially global error codes, which is fine, but you absolutely have to check for errors if you want to catch them, and worst, it won't give you a neat stack trace with the exact error info for absolutely no work at all.
Like I said, those unwraps are essentially assert macros I use to check the correctness of the code, they aren't serious attempts at error handling. To do the same in zig you would still have these asserts. Exact same with C. The difference is that Rust
1. doesn't let me forget the asserts,
2. gives me automatic error information when these asserts fail that go beyond "this assert failed."
Zig has had this really annoying issue for a while where its absolute cancer to tie any sort of error info to errors sent by Zig without returning actual structs. Rust simply doesn't have this problem, and propagated errors can be converted through traits without any extra syntax.
>they can't use the standard library
Have they fixed Zig's vector implementation yet?
>Have they fixed Zig's vector implementation yet?
What is (was?) wrong with Zig's vectors?
I do not remember the timestamp, but it's a nice talk anyway.
they dont conform to rust ideology
8:30, thereabouts. Not sure if they changed anything with aliasing since then, since I stopped using zig in 0.11. I used to be super hyped for zig and used to think rust was the shittiest thing. But then I learned rust and I don't much care for zig anymore.
he's a c++nile who still thinks "vector" is a synonym for "array list"
Zig's actual vector types are fine
Zig's array lists are also fine but affected by the parameter optimization footgun
They use the standard library in a configuration with fallible allocation. This doesn't neatly apply to all APIs but it's available and it's enough to get them going.
Couldn't you just use the parts of the std which do not allocate memory along with implementing standard traits for custom heap management structures? I imagine you can still get a lot of good stuff from the std.
>pretty nice
>let t_db = Arc::clone(&self.0);
>.unwrap() x100
>multiple ways to pass parameters to prepared queries, using completely different methods
Is this bait?
>zig
>the language that accidentally compiles your valid and standard-compliant code into UB
This is 100% bait.
>let t_db = Arc::clone(&self.0);
What's the problem with this, other than you not understanding it?
>multiple ways to pass parameters to prepared queries, using completely different methods
It's all done through a single trait. You can use tuples if you need differently typed arguments and arrays otherwise. What exactly is the problem, other than you not understanding it?
>.unwrap() x100
Post your alternative.
>y-y-you don't understand it!!!
It's code golf homosexualry, same as Vector being shortened to Vec.
If I was into the "cryptic single character variable names" niche then C does it already.
>It's code golf homosexualry
Thank you for confirming that you indeed do not understand it. I like you didn't change your shit opinion at all even after I explained it to you.
>I am before I think
Yup, you sure are. A homosexual, that is.
wtf are you talking about? Nothing about this is code golfed. It's almost like (You) don't even know the sqlite c API or why the code has so many potential failure conditions.
>C doesn't do error handling at all. In my case if something fails I know exactly where it failed and why.
holy shit, this is the most enlightened post i've ever seen on this website
You're just moronic. Get back to me when you finally finish a rust project
>C doesn't do error handling at all
Yes it does it just handles it with error values that you have to operate on. This is pretty similar to what go does except there isn't explicit error types.
>C can't do functional style programming
If you mean chaining functions using the dot operator, sure, but you could pretty much do the same thing if you just moved the arguments into the parenthesis.
>Yes it does it just handles it with error values that you have to operate on.
Yes, which would make it about 3 times as verbose as just calling
>.unwrap()
and getting a proper error report if things go wrong. This is NOT a simple
>assert(a, b)
which is what you would otherwise do (in C for instance.)
Not only that, but if you want to add defaults in C then congratulations, you've just added about 200% more code, while in rust this is just
>unwrap_or(...)
But you will never actually see cnile baby ducks posting any alternatives to what they're complaining about because they know it would look like absolute dogshit, would be about 10 times as annoying to actually write, and 3 times as verbose. Not even gotos can save you in some cases.
Lmao.
>random code it doesn't understand
I wrote that code motherfricker
>C doesn't do error handling at all.
No, there is no equivalent to that type of error handling in C, you have to manually check thread global error codes and write out error messages manually as well. I look forward to reading your mental gymnastics on how
if (errno == ...) {
printf("...", ...)
exit(1);
}
is actually totally better than .unwrap()
> rust troony screencaps random code it doesn't understand
have a nice day, troony.
>C doesn't do error handling at all.
stick to what you're good at, rust troony: child rape. computers are just not your thing.
You drive to school in a special van, don't you?
>and you couldn't do this kind of functional style with C, which is what I'm trying to focus on, but I'm looking forward to you sharing your convoluted macro stack that "kinda" allows you to do the "same thing,"
I do enjoy the implementation in the STC. Best thing is it actually works better out of the box in terms of optimization than sophisticated implementations in C++.
#include <stdio.h>
#define i_TYPE Vec, int
#include "stc/stack.h"
#include "stc/algorithm.h"
int main(void)
{
Vec vec = c_init(Vec, {1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 9, 10, 11, 12, 5});
c_filter(Vec, vec
, c_flt_skipwhile(*value < 3) // skip leading values < 3
&& (*value & 1) == 1 // then use odd values only
&& c_flt_map(*value * 2) // multiply by 2
&& c_flt_takewhile(*value < 20) // stop if mapped *value >= 20
&& printf(" %d", *value) // print value
);
// 6 10 14 2 6 18
puts("");
Vec_drop(&vec);
}
Unwrapping a mutex lock is idiomatic, that propagates any panic that happened while the lock was held by another thread.
Unwrapping on db.prepare is probably idiomatic because it's a string literal, it can be statically guaranteed to be correct and if it's not then you want a loud crash. (I don't know the library though.)
Unwrapping spawn_blocking probably propagates any panic that happened in the closure?
Probably some of the other unwraps are not justified and are better bubbled upwards as Results.
>Probably some of the other unwraps are not justified and are better bubbled upwards as Results.
Depends. In my case I have no reason to handle these kinds of errors in my personal program nobody is going to use besides me. I am treating these unwraps as asserts, if something fails here I have 98% certainty I fricked up something in the code, and that's all I want.
In other words I get nothing from handling or propagating the rusqlite Result type. Even interning it into my custom Result would be a waste of time because I'm never going to handle it.
Also just to be clear, the thread was about functional style shit like map, filter, etc. not error handling.
>unwrap derangement syndrome
let me guess you think all day about unwrapping "things" huh
.unwrap_or(null)
>Explicitly panic instead of exceptions as shitty flow control
>Explicitly panic instead of completely ignoring errno or error returns
What's the problem again? Anytime you see unwrap, you know you can always expand it and if the condition is basically an impossibility unless your shit is broke, unwrap is fine.
How do you do error handling for a database failure anyway? Either it works or it doesn't and if it doesn't then who gives a frick if it crashes?
Honestly after years of experience, I really believe you don't want to handle errors other than maybe printing or signalling something to someone else.
Every shit code I've had problems with tries powering through a broken situation and will just uselessly stay broken until someone notices it.
Just have your code log some event and then immediately _exit() with some bad status code.
You have a service manager anyway and the service manager can execute extra code when your shit fails and restart your app in a good state.
Right now this morning I had to login, go check on an app in a k8s cluster that claims to be "healthy" only to find it is in a fail loop trying to connect to some service it can't reach. I kill the pod and it magically starts working. Made me more convinced that sometimes failing hard and fast is better than trying to be smart
pure cancer
>manually binding values and fetching results by position
ngmi
Dont see a problem.
>using | | for lambdas
stopped reading right there
>unwrap();
>unwrap();
>unwrap();
>unwrap();
>unwrap();
unlive() yourself
technology is fricking degrading
>assert(...);
>assert(...);
>assert(...);
>assert(...);
>would somehow be better
Sorta.
I'm using rocket, it has to be async and spawn_blocking works for my particular use case. If you know of any async sqlite libraries I'm all ears though.
>And stop using unwrap
Why, lol
is this for a booru?
Either use an async database driver or don't offer an async api. It's just making everything slower and dirtier. Cloning tag_ids just to use it in spawn_blocking is particularly egregious.
And stop using unwrap
Do not use {} when it's not needed. That let db is also pointless. Handle errors properly instead of unwrapping everything.
what in christ's forsaken name is this syntax?
All line noise
>everyone has the same reaction to rust syntax that I do
Glad it's not just me.
Tbh I think the worst offense is the brackets for arrays.
what......................
You're obviously supposed to use parentheses
ew
This is why CS is dead
why
>the hecking rust trannerinos decided to use || for lambdas, it's over, CS is dead
Actually it's because of the let keyword
man low level languages look like shit
ugly syntax 🙂
synchronous async is the best kind there is
can you do something like create an array of lambdas and run them in sequence, unwrapping each step? if you do this please make a generic version and release a crate
zig is nicer
Show us analogous zig code.
Or you could actually spend a bit of time making projects in both languages and decide for yourself.
Do what he asked. You won't because you know you're full of shit. Pic rel is the output I get from a single unwrap in rust. Shit like this is notoriously difficult to do cleanly in zig like I mentioned here
because of the way error handling works. You pretty much have to always retrieve data external to the error from somewhere else, which translates to extra code.
Lazy Black folk can't into error handling. Here's an error message your fricking user. Suck on this. Want more? Set a fricking environment variable if you know what that is. Ha, ha go frick yourself. ABEND. Core Dumped. Frick off.
>Incoherent melty when asked for code
Classic rust derangement syndrome.
Lazily written Rust code gives an ugly panic with plenty of error messages. Lazy C code tends to segfault. I know which I prefer
Good effortful code in either language doesn't do either of those of course
Good effortful code in C is also about 5 times as verbose, but lets just ignore that.
That's less relevant to that particular post. If you call people "lazy Black folk" then you probably think boilerplate builds character or something
I meant to say that was a bad thing. Verbose is probably not the correct word, noisy would be more apt, if we're comparing to something like Rust.
The unwrap Language
OP, instead of single db connection when sqlite already implements its own multiple reader / single writer concurrency and since you're using async based on the spawn_blocking and await:
https://lib.rs/crates/deadpool
How about creating an "unwrap block" macro?
Why? Just use ? and handle errors properly. There are even try blocks you can use for that.
Exception might not be a bad idea after all.
How?
instead of spamming .unwrap i prefer to spam the ? operator
and then the function returns the Result
kinda ziggish
Why pollute the return type when I'm not going to do anything with the error anyway? I get no benefit from propagating rusqlite results. Doing an unwrap directly after these calls gives me a message that exactly pinpoints where the error came from.
Even in dirty personal projects I find it can be helpful to distinguish between "this can happen" and "this shouldn't happen". anyhow makes it easy peasy and can even generate backtraces nowadays
Well yeah, none of my unwraps should happen.
There are plenty of errors I don't check for:
Syntax errors I don't check for because if my syntax is wrong then it will always fail. I fix the code and move on.
Same with invalid field accesses,
Same with invalid inputs, since rust is statically typed.
Poisoning happens sometimes since I'm fricking around with the database manually, but it's for testing purposes and I have no interest in handling them.
Constraint violation should never happen as per the invariants of the underlying system. If you were writing something to be used by a lot of users you should definitely check for this! In my case, this is a dashboard for a daemon that I'm never going to share with anybody, so it doesn't really matter at the moment. I still use PRAGMA foreign_keys = ON; for extra insurance on the database side. SQLITE constraint check violation messages are also terribly unhelpful in my experience.
I don't particularly care about any other kind of error at the moment.
I'm sure someone who knows a lot more about SQLITE than I do would have other important fail point checks, but for me it quite simply just works.
I know all of that but how do you actually handle the error other than dumping a message to the console and exiting anyway?
If it can't open the database or can't write to the database, etc, then you're fricked. Crashing versus printing a message nicely and exiting anyway isn't going to make much of a difference.
Well for syntax failures it's hard, unless you're talking about taking in external inputs, of course.
For poisoning you could reset the database connection, for instance.
For constraint violation you could have a message, no need to even break flow at all in this case, let alone exiting the program.
For everything else I have no clue, that's the only SQLite errors I know, lmao.
>If you can't open the database or can't write to the database, etc, then you're fricked
Depends on the DB, you can have failures for plenty of reasons. There's plenty you can do, f.e.
>log the error
>stash the transaction somewhere to be rerun later
>call some centralized error handling stuff
if what you're writing is not an application but a library, for the love of god don't crash because a DB request went wrong.
Either propagate an error code back to your caller, or ask the caller to give you a callback to handle errors however he wants.
>this is what FPgays consider to be "good" code
Every day it becomes clearer that OOP is the least horrendous programming paradigm.
Show an analogous OOP implementation.
The equivalent oojeet code wouldn't run on EL7 anyhow since the only used sqlite3 jdbc driver writes the sqlite executable code to /tmp.
Java jeet shit is a mess.
None of you will ever be a real woman
and you'll never be a man.
>pub async fn
why do I have to tag a function as "async"? why can't i just pass an arbitrary function into a threading api?
>why can't i just pass an arbitrary function into a threading api?
You can do this with e.g. std::thread::scope but that's not what async is. Async functions can halt midway through (when you await) to make room for another task on the same thread, there's some special stuff going on under the hood
>Async functions can halt midway through (when you await) to make room for another task on the same thread
Time slicing is a basic function of threads though, and external management exists in all threading APIs (though I don't know of any pthreads implementation that implements pthread_suspend, but there are alternatives that use signals, and Windows has SuspendThread)
It seems like async is a really fuzzy abstraction over the already super fuzzy abstraction of threads? At least on most platforms. Really strange language tbh.
You are on top of mount stupid right now my man. Async is not threads.
async tbhgars the function to a state machine that's polled until it's completed
That sounds insanely inefficient, like just gonna frick over the branch predictor? How does the function detach from the execution context? Any good reading on this?
https://rust-lang.github.io/async-book/01_getting_started/02_why_async.html
This has been the standard for high volume servers for decades. Do you think threading is fast?
Polling based, composing async model is generally zero cost or even faster than hand written solutions. It's definitely much faster than callback based async model.
Proofs? Moving some data and two hardware interrupts costs about the same as a single conditional.
Literally anything that doesn't loop over a branching instruction.
>That sounds insanely inefficient
absolute moron, why do you bother opening your mouth
>That sounds insanely inefficient
as opposed to what?
OP, for the love of god. Use deadpool-sqlite you frick.
why the frick are you gating a single connection to a sqlite db behind a mutex? did you build sqlite to be single threaded only or something?
I'm not going to even bother arguing constructively anymore.
t. C-nile
>I'm not going to even bother arguing constructively anymore.
You never did in the first place.
>Rust derangement syndrome
Now post the alternative code in C.
none of these morons ever used sqlite in c because they're pyBlack person toddlers.
why does rust not have pipes?
It's already got the functional influence, and pipes are just a superior, more flexible way to handle method-chains/ function-pipelines.
It also seem like a comparatively simple thing to implement, since any code that uses pipes could be trivially rewritten to not use pipes.
if you remove all the unnecessary syntactic vomit, rust actually looks like a decent and readable language lol
>if you remove all the unnecessary syntactic vomit
Post the alternative in your language.
i don't have a "my" language, i'm critiquing rust
if you need to spam it every 2nd line, it sounds like it should not exist, it's just bloat that hides what's actually going on
unwrap() is a method, not syntax
>unwrap()
>syntax
What
>added extra =>
>confuses values for references
>confuses namespaces for methods
What
i don't claim to understand rust and i spent like 1 minute doing that shitpost in ms paint, i just wanted to illustrate how unapproachable rust looks at the first glance to someone like me who doesn't know shit about it
You don't need to understand rust to know what is a syntax.
there is zero reason the accessor for a data structure's members and a namespace's members should be different. It's one of the many moronic design traits of C++ that Rust adopted for literally no reason except to make the language uglier.
foo::method(...) is something different than foo.method(...). foo.method(arg) is just a syntactic sugar for foo::method(foo, arg).
https://matklad.github.io/2023/01/26/rusts-ugly-syntax.html
turns an Option/Result into a T and panics if it's None/Error, like Maybe/Either type in Haskell
>https://matklad.github.io/2023/01/26/rusts-ugly-syntax.html
great article, i really like what the final result looks like, you get a clear picture of what's going on immediately upon glancing at the code, without having to focus on ignoring all the visual noise around it.
that is the style of code i like to read
that's what rust looks like when you've used the language and learned it after a few weeks. it's not noise, it all conveys information
Maybe doesn't panic. Except if you are using patternmatching. If you use the monad then
Nothing >>= f = Nothing
This means that in Haskell you don't have to explicitly error handle unless you want to:
main = do
x <- thing1
y <- thing2 x
z <- thing3 y
return z
Will return Nothing if any of things evaluates to nothing. Furthermore you can do case on any one of them for explicit error handling. Unfortunately in Rust something like that would require either the libraries be reimplemented accepting option types as input or perhabs a better idea would be some special function trait like async (if it's called a trait) that when used all option<T> types within the function are automatically unwraped when used somewhere where a T is expected and if the result is None then returning None. Basically making it so that
returns_option_T().expects_T()
is sugar for
match returns_option_T() {
None => return None
Some(t) => expects_T(t)
}
I think this would be good
Wait that's literally ? lol. I was thinking too much about emulating Haskell
literally javascript at that point
what is .unwrap and why do you call it so many times? Is it a function, if so then why do you start it with dot? Is it kinda like pythons self.something?
.unwrap() is an assert which tells me when something goes wrong with the call.
Instead of functions raising exceptions they typically return a Result that might be either an error or the return value. To get the return value out you have to decide what happens if there's an error inside. With unwrap() you tell it to just crash if there's an error. (You can also write ? to return the error from the current function, and there are a few other ways to do more sophisticated handling.)
unwrap is a method on Result.
>if you need to spam it every 2nd line, it sounds like it should not exist, it's just bloat that hides what's actually going on
A lot of these should be replaced by "?" in non-toy code.
If you got rid of it altogether then you wouldn't be able to see which operations could fail, you'd have much less of an idea what was going on.
i just don't get the usecase of async
calling out to a peripheral with high latency, but you can do some stuff while you wait.
>but you can do some stuff while you wait.
can you though? doesn't awaiting the function hog the thread?
Let's say you want to perform some kind of transformation on the GPS coordinates of the computer. You query out to the GPS peripheral, which takes a while, and in the meantime you can actually calculate out most of the transform information regardless of having the coordinates or not. So while you're waiting, you spend processor time doing that. When you run out of stuff to do, you finally wait for the coordinates to come back to you, and then just add the two vectors together. You've now ultimately saved yourself a little bit of time.
When asynchronous tasks don't run parallel, it starts to be a bit of a meme.
Awaiting a future pauses the task so the thread can pick a different task to work on. It's basically for IO bound programs.
is this actually fun to code in?
t. only know JS and Python
yeah and it's really fast. you don't really use types so it could be easy and what you've been missing your whole life or it could be hard
It's tedious if you aren't accustomed to type tetris. But it's a massive improvement over C++, and IIRC you can write Python modules in it.
No, it's absolutely abortive. Learn Haskell instead.
Very fun in ways that you won't find in JS and Python. Depends on taste of course but it taught me a lot about how things work under the hood and about what a type system can do for you
.await is syntax that looks like a property, not entirely unreasonable