I like how Primeagen goes through the last ten years of random dev blog history.
@sumanth3036 Жыл бұрын
Content
@gcxs Жыл бұрын
I like that this blog post defined a new concept
@tcc1234 Жыл бұрын
It's not your average random dev...
@Don_XII11 ай бұрын
It is not a random dev at all.
@dnsfail Жыл бұрын
In case you're wondering why isn't every programming language using green threads instead of async/await: 1) every program has a runtime to schedule green threads which is suboptimal for native langs like rust or C++. 2) async/await is how things work under the hood at hardware level e.g. you open a file for async read, request some data using async kernel APIs, kernel requests data from disk controller to a certain memory address and sets an async flag if supported by the hardware, your async function is suspended and other functions on the same thread continue, the kernel keeps doing other stuff, disk controller finishes and send an IRQ, kernel responds and returns the data to you, your function resumes with the data. 3) if a green thread opens a file for reading, and doesn't specify async mode, ALL fellow green threads mapped to the same OS thread will be BLOCKED. (assuming the scheduler maps multiple green threads to multiple OS threads if not, the entire program blocks) This is a footgun which is solved by... using async APIs all the way! Java/Loom "fixes" this by having the JVM manually map all your blocking calls into non-blocking calls. Does it work? will it always work? how does it work with JNI? who knows! What is known is that this is a fragile and big undertaking by rewiring all the "normally" blocking methods to use non-blocking alternatives. 4) green threads may behave differently if your thread is only CPU bound. By abstracting over OS threads, you may not have the luxury of expecting threads running time-consuming CPU work to run parallel on a multi-core system, instead you may be executing expensive CPU tasks on the same OS thread! another point is that if you have green threads hogging CPU and others hogging IO, the IO hogs will naturally be suspended but how do you handle the cpu hogs? the solution is to cross your fingers that the scheduler is smart enough to preempt at a safe point.. and cry when it unfairly schedules time for it or introduces bugs so difficult and beyond control it makes a gopher cry (earlier versions of go) 5) due to how green threads work (program-level thread creation and scheduling) expect a drop in FFI perf and by drop I mean a HUGE drop which would kill slow managed langs that rely on FFI to faster native langs to speed things up.
@bestergester4100 Жыл бұрын
Thanks for your info
@Supakills101 Жыл бұрын
Amazing comment
@RobbenBanks15311 ай бұрын
Way too much reading
@SLAMarshall Жыл бұрын
A Blub language is a concept from Paul Graham from his essay Beating the Averages. It’s a hypothetical language, someone who programs in Blub doesn’t see the need for features beyond what Blub offers.
@thewhitefalcon8539 Жыл бұрын
Blub is whichever language you use every day. Some people's Blub is Visual Basic. Other's is Haskell.
@duncanw9901 Жыл бұрын
I like Haskell's solution, tbh. Make 95% of the code you write completely state-free, and your parallelization effort entails nothing more than swapping to a different state monad type.
@parnmatt Жыл бұрын
From Wikipedia: In mathematics and computer science, a higher-order function (HOF) is a function that does at least one of the following: • takes one or more functions as arguments (i.e. a procedural parameter, which is a parameter of a procedure that is itself a procedure), • returns a function as its result.
@Ryan-xq3kl Жыл бұрын
can we throw the guy who invented them in prison?
@liorean Жыл бұрын
@@Ryan-xq3kl Alonzo Church wouldn't deserve it, if he still lived.
@raffimolero64 Жыл бұрын
@Ryan-xq3kl Alonzo Church? Not sure if he was the first guy to come up with "functions take functions" in math but he sure did popularize it. Worked with Alan Turing himself, too.
@adriankal Жыл бұрын
@@Ryan-xq3klhow would you handle action on button click?
@NuncNuncNuncNunc Жыл бұрын
@@Ryan-xq3kl f(t(w(x)))
@comradestinger Жыл бұрын
Coming form gamedev I find all this talk about concurrency, async, etc wildly fascinating. Since most games solve concurrency via polling (Each object has a Tick/Update function that gets called every frame.) No need for callbacks or awaiting when you know your Update function will be called again in ~16 milliseconds anyways! And no, callbacks/async/etc is not faster. If your object doesn't need to do anything, it can just return from the update function immediately, or deactivate itself.
@ciberman Жыл бұрын
Update/Tick functions is most engines execute concurrently. The real pain in gamedev is writting a multithreaded renderer, because you have race conditions and syncronization issues.
@comradestinger Жыл бұрын
@@ciberman haha yeah, or networking ;-;
@themisir Жыл бұрын
Just something that caught my attention when playing with game engines. How does (or does it even) optimize the object polling when there's a bunch of deactivated objects, since it has to loop through them one by one and see if they're active or not. Would having 2 sets of objects solve the issue: one for active and another one for inactive objects. Or it's not a big deal for games to handle. Obviously there's not a simple answer I know. I am just wondering what's the general convention in that regard.
@ciberman Жыл бұрын
@@themisir normally it doesn't matter. The performance bottleneck in engines is not wether or not to call the update function but rather the update code itself. As all the update code normally blocks rendering so you should wait until all the update is executed before dispatching the rendering for that frame.
@comradestinger Жыл бұрын
@@themisir I don't know if there is a general convention or common strategy. Generally you don't have *that* many objects in a scene that needs to be updated every frame. Maybe a couple hundred to a couple thousand? so.. easiest is probably just have an "IsActive" bool on each object that is checked before calling Update. Checking a thousand bools every frame is not very much work.
@Bolpat Жыл бұрын
3:40 A higher-order function is a function that takes another function as a parameter and/or returns a function. However, in functional languages, functions returning functions just for the mere purpose of taking more than 1 parameter usually don't count as higer-order.
@RagTagPwner Жыл бұрын
It's hilarious to me how many times I've read this article, but each time I understand something new about it.
@sanderbos4243 Жыл бұрын
Amen
@istasi5201 Жыл бұрын
My man going through all them really good old articles
@on-hv9co Жыл бұрын
Hey Prime, if you wanna see some seriously func'd up design: i wrote a databsae-esque RCU for STM in a game engine. The Read/Write interface had to ensure synchronization so the calls are a R/W sync with user defined functions that perform the task. Works great for performance but a royal pain in the ass to debug when a function call like: TerrainUpdate(extractFunc,configFunc, database, args...)=>configFunc(Extractfunc,database,args...)=>database.table->push(extractFunc,args...)=>extractionFunc... is one "atomic" function.
@ThePrimeTimeagen Жыл бұрын
looks ass pain-ee
@confusedbystander2898 Жыл бұрын
This is syntactic salt not sugar.
@DaviAreias Жыл бұрын
Syntatic uranium
@claudiusraphael9423 Жыл бұрын
@@DaviAreias Urinium. Very Rare.Yellow channel.
@jaysistar2711 Жыл бұрын
At 12:00 that's the point! The reason Rust handle errors that way is to force errors to be handled. Maybe until you've spent a whole night debugging C that didn't report an error, you don't get it, but it's needed. Also, the whole function color things don't pose an issue in Rust, since futures must be passed to an executor, which means that you can just call `exe.block_on(...any future...)` to call and wait on an async function. Go routines are not as efficient as async/await, and it doesn't compose with other languages, but Rust async/await does.
@xXYourShadowDaniXx5 ай бұрын
This is just referencing the native Rust async/await and not Tokio right? I haven't dabbled with any async in Rust yet as I'm trying to make sure I understand the language more before I dive in.
@sk-sm9sh Жыл бұрын
I don't really hate colored functions even though I can see where it can annoying in case when you wrote an algorithm in non-async way and suddenly you decide that you need async version of it. Yet in my experience this happens rarely enough that I don't think it's big problem. On other hand I find it useful to divide code into pure-functions and non-pure functions. And async is basically telling you that this function is not a just a plain simple function but is doing some IO stuff and thus you know it can be less predictable, for instance it may take unpredictable amount of time to complete.
@keldwikchaldain9545 Жыл бұрын
Java is also keeping itself from falling down this hole because they're adding project loom and structured concurrency, which means that they never have to get stuck in this problem. As it stands they may not have *this* problem but they have a similar one with executors because of ultra high concurrency requirements, but once project loom lands all of that can transparently be ported and new code can ignore it.
@diadetediotedio6918 Жыл бұрын
23:00 And if freezing your current thread to obtain the value makes your language not colored, then C# is also not, you have the .Result that will block until it gets the value
@asdfasdf9477 Жыл бұрын
Erlang, Go and Haskell have "native" light threads, many other languages support some form of cooperative multitasking. But if somewhere deep in your callstack you filter a collection with a predicate that does IO, your problems won't be solved by any of those things.
@f1r3w4rr10r Жыл бұрын
2:54 I've seen this before. It seems like in some fonts "f" and "i" together are treated as a ligature for some reason and screw up the kerning. Of course you will only see this in font displays using ligatures.
@liorean Жыл бұрын
There is the green functions vs purple functions colouring too. Is it a pure function or any level of impure? And there's the cyan vs orange colouring. Is it always returning or does it sometimes throw? And there's the fuchsia vs yellow colouring. Does it return the modified value or does it just modify the argument? And there's the ever present black and white - is it a method on an object or is it s function taking an object as argument? All control flow is one of two things - a goto internally, or a ceeding processor time to the kernel awaiting some external signal. In really old computer literature, the second would be considered one program before the syscall and another program after the syscall...
@KManAbout Жыл бұрын
Ooo this is a good point. I guess this is what haskell purists are trying to say
@perigord6281 Жыл бұрын
@@KManAboutYeah, IG you can call each monad their own color of functions. `a -> IO b` for impure functions `a -> State s b` for stateful functions `a -> Async b` for async functions Etc.
@kyay10 Жыл бұрын
Kotlin's solution to this is that, if you know that your HOF will run the lambda locally, then you mark it with `inline`, which inlines it at the call site, and thus preserves the execution context. HOF are usually encouraged in Kotlin to be inline, unless you're storing the function somewhere for lazy eval or something Edit: Kotlin does use coroutines though, similar ish to Go, and so that might be part of why it's a lot easier to do it there. Still, it's a solvable problem. Coroutines in Kotlin also have the same exact syntax, and work by rewriting the code into an efficient state machine by using Continuation-passing style
@BosonCollider Жыл бұрын
The thing you really want to fix this is effect polymorphism, like Koka. I.e. where you can write higher order functions that are polymorphic over which effect the input function has. This puts a constraint on the internal implementation of some functions. Like if you write a foreach function, then if it is restricted to only take in pure functions it can execute all the calls sequentially or in parallel. While if it takes in functions with arbitrary effects it has to call them one after the other. Alternatively, koka lets you can handle functions with a finite range of different effects by using function overloading with one implementation per case.
@thewhitefalcon8539 Жыл бұрын
Or you have threads
@yarrichar Жыл бұрын
If we put everything in the one function with a goto here or there then we don't need to worry about calling other functions at all.
@emjizone Жыл бұрын
2:15 Whenever exposed to such a delicately formulated sentence, my brain urges itself to replace @ThePrimeTimeagen's cartoonish voice with the more aristocratic one of the game's _Dungeon Keeper_ narrator.
@elmersbalm5219 Жыл бұрын
Vitreous humour is a liquid inside the eye. Hence the sucking. Hairshirts are used by monks and such as a form of punishment as it's very uncomfortable.
@vukkulvar9769 Жыл бұрын
Eyeball soup Indiana Jones style
@callysibben416 Жыл бұрын
I never actually understood what async was, or why people often said that goroutines were a killer feature. I know understand both and it's radically changed how I think about impure functions. Thank you Bob and ThePrimeTime for explaining it so thoroughly
@mcspud Жыл бұрын
I remember reading this article back when it first came out. Wow.
@draakisback Жыл бұрын
It's interesting to me that the rust keyword generics proposal actually references this document. I've been aware of this issue for a while, I write my own compilers on occasion and in the instances where I've had to write a JS backend, I've had to worry about this issue and it ends up proliferating into the language that I'm trying to build. There are ways to mask it, you can make abstractions for threads and then just have them turn into futures/closures when you call them in the JS backend but it does become very complicated. By far my favorite concurrency model is probably elixir/erlangs otp. OTP makes it so that your program is processes all the way down, and since each process has its own isolated stack frame and heap, you don't have to worry about unwinding the stack frame when you run into an async call because you can just create a new isolated stack frame on another process. Elixir does have the concept of tasks in it, and they are essentially just small processes that you would spawn to do one thing. To be honest I've rarely found myself using tasks when writing large elixir apps. It's usually much more efficient to just use a pool of processes or create a thread pool; something of that nature. That way you don't have to worry about building a process for one call and can instead just have a pool of processes that you can invoke ah hoc. Also, technically all elixir code is synchronous and the concurrency comes from having multiple processes passing messages back and forth. When you build a process in elixir you usually use an abstraction called genserver. Genserver is just an idiomatic way of building a process with a bunch of callbacks which will get invoked in response to received messages. The genserver itself has three types of call backs, one of which is synchronous and two which are considered asynchronous. The call backs are called call, cast, and info. Call is synchronous in that it will always return a message to the calling process after it's finished it's computation while cast and info do not. Now because of the way that message passing works, your call can time out if the computation takes too long or if the server process has too many messages that it needs to handle before it gets to the call message. This is one of the main downsides of using processes as your main abstraction for parallel and concurrent execution but when you write an elixir application, you generally try to keep the computation costs pretty small in cases where you need to make synchronous calls to other processes. It's also why it's useful to have multiple processes that are clones of the same thing so that you can have each of them handling different atomic operations at the same time. I won't go further, since a lot of this goes into the challenges and designs of distributed computing but elixir does not have the colored function problem. Go routines are also extremely useful, though I will say that probably the biggest thing that I don't like about them is that you don't really have an ability to start and stop them at will when the program is executing. Obviously you can create as many go routines as you want throughout the execution of your program but if one of them fails it will crash your entire program. Conversely with elixir, if one of your processes fails you can just recover and pass the state to a new process to pick up where it left off. One of the mantras of writing Erlang or elixir is to let it die/crash; that's how you're able to achieve such high fault tolerance in your system. It also makes the error handling story so much easier since you can make it so that all of your processes are disposable. One of the larger apps I worked on with elixir was this full featured matching engine and order book. We used rust nifs (native interface functions) in this system; it made it so that we could offload any heavy computation to rust. Those two languages pair up very nicely because if you use results/options in your rust code, instead of crashing the nif and subsequently crashing your entire program when you hit a panic, you can return an error atom back to the elixir code to indicate that something went wrong. Then you can just use an elixir supervisor to restart the rust invocation. Each of the order books in the system was 20 or 30 elixir processes that wrapped small rust runtimes. When one of the runtimes errored out, the elixir supervisor would kick in and just restart it without losing the state (everything was backed up in ETS which is basically redis inside of the Erlang virtual machine). We also didn't really have to worry about rust futures and instead of using futures we mostly would pipe everything back to the elixir runtime using channels. This is intuitive because the channels act like message passing which is native in elixir. We did have one NIF that had to use Tokio but it was just a listener that lived in its own process. The elixir system never sent any information to this nif and instead just used it like an event queue. Just thinking about this makes me want to build more rust/elixir hybrid apps... They're also some really cool projects on the horizon that use rust which pertain to elixir. Lumen for example, though I think they changed the name of it was effectively a version of the BEAM (Erlang virtual machine) written in rust. There was also another project which again I forget the name of which used elixir as a wrapper around rust microservices. So you could write a bunch of small rust programs and have them all interact with one another seamlessly and they did so via the elixir VM.
@hidekxyz Жыл бұрын
Such an underrated comment and language, there's so many applications for elixir that I feel bad for not being a more know language around the community, I consider one of the most powerful languages in terms of features. Although elixir consumes more memory per task than other languages, for me it's a great trade-off since you have the isolation and thus the guarantee that your program will not halt due to an exception in a task. Also, because of it's concurrency, it makes more scallable than other interpreted languages on the market. I would like to know the name of the elixir wrapper for rust microservices, my friend was trying to solve the same problem too.
@Bukosaure Жыл бұрын
I watched this video by furiously and rigourously asking ChatGPT about every concept I wasn't familiar with. My tiny brain just grew into a small one. Such a magnificent feeling! Back to React, now.
@PS-dp8yg Жыл бұрын
Yes, a HOF is a function that either takes a function as an argument, return another function, or do both. I.E., Array.filter, Array.map, and Array.reduce are all HOFs because they are functions that accepts a function as an argument. None of those 3 Array functions return another function.
@CorrinWyndryder Жыл бұрын
Vitreous Humor: The transparent gelatinous tissues filling the eyeball behind the lens. Probably dates back to Ancient Greek medicininal understandings; humors being the word for bodily fluids.
@fistoflegend7846 Жыл бұрын
Bro. Wheel of Time. I hear the Based Department calling all the way from where I'm sitting.
@ThePrimeTimeagen Жыл бұрын
big fan, almost done with book 3
@fistoflegend7846 Жыл бұрын
@@ThePrimeTimeagen Ohhh boy. You're in for a hell of a good read for Shadow Rising.
@cparks1000000 Жыл бұрын
3:45 A higher-order function is a function that takes or emits a function; however, everything is a function. A list of type A of length N is simply a function f:[0,...,N-1] -> A (or f: [1,..., N] -> A for 1-based heathens). Even a constant c can be represented as a function f: [] -> c. In this sense, a higher-order function really has no meaning (unless we get into set-theory or complexity theory). There's legitimate uses of "safe" and "unsafe" functions. It's clearly unsafe to call an unsafe function inside a safe one.
@Tazato Жыл бұрын
It's totally bonkers to me how much of the pain that people who write JS has already been solved by Scala.
@Cammymoop Жыл бұрын
Promises are pretty nice actually
@emjizone Жыл бұрын
4:29 This is the birth of _React_, isn't it? Taking a simple hypertext document to a *higher level* of undebuggability.
@unowenwasholo Жыл бұрын
The Green Threadagen is the hero that we deserve, but not the one we need right now.
@samantony4423 Жыл бұрын
"Lesser of two evils" < "Getting punched in the gut vs. getting punched in the privates"
@Imaltont Жыл бұрын
Without having tried goroutines, but from this article it seems like it might have taken some pointers from dataflow variables coming from Oz (which again was inspired by erlang iirc). Oz lets you just spawn threads everywhere that relies on variables from elsewhere. If a thread encounters a variable that is not yet initialized, just declared, the thread will just stop until it has been initialized.
@Yupppi Жыл бұрын
Wheel of time was fucking poggers. It was split into like 26 books or something here in translation and at like 23 I learned the author had died and the publishing company translating them decided not to do the rest because it was not purely his writing.
@mattymerr701 Жыл бұрын
"You can avoid this in C# by using threads" Little did the author know, that async in C# is threads, and the easier way to do them now
@kamilkardel2792 Жыл бұрын
If you haven't looked that up already or been told, hairshirt is a rough shirt that ascetics (e.g. monks) would wear for mortification.
@madlep Жыл бұрын
Blog: “Wanna know one that doesn’t? Java” Me, flashing back to shared mutable state concurrency in Java: “Johnny?...Johnny!...JOHNNY!”
@edz8659 Жыл бұрын
Color me surprised
@SianaGearz Жыл бұрын
Wow you can learn a whole new flavour of English with just this blog post.
@yellingintothewind11 ай бұрын
Out of order execution and orthogonal register use means even restricted to a single (modern) core you still get thread concurrency, at least some of the time.
@flamewave000 Жыл бұрын
I remember when C# first got Async-Await (before JS), my boss at the time would call it the Async Zombie Infection. Anything calling an async function had to be itself async, until you could "cure" the callstack with an Async-Void.
@griffitaj7 ай бұрын
I love chat straight up lying about terms to prime.
@myusernameislongerth Жыл бұрын
4:14 higher order function takes a function as input and/or creates new function.
@ciberman Жыл бұрын
At first I REALLY thought the article was about pure and impure functions
@m00ni Жыл бұрын
Yeah, it really applies to any sort of effect: sync versus async, pure versus impure, throwing versus non-throwing, etc.
@sealsharp Жыл бұрын
I love the word "Goroutine". Glad they did that.
@absolutejam Жыл бұрын
It's simple, a red function just returns a value that is a monoid in the category of endofunctors
@ThePrimeTimeagen Жыл бұрын
ligma monads
@SeanJMay Жыл бұрын
A hairshirt was a Catholic shirt, worn for punishing one's self (penance). It was literally a hairy shirt, meant to make you hot and itchy and miserable, so that you suffer. It's often used as a metaphor for doing things which end up making you miserable. "Having a cross to bear"; "Martyring yourself"; "this is my hairshirt"; fits right in with the rest of the Christian "I'm making my life miserable" or "you're making your life miserable" or "you're making yourself miserable, so that people will pity/respect you".
@Vivraan Жыл бұрын
Thanks for taking up a suggestion I had also made!
@jswlprtk Жыл бұрын
Well that depends on what color is the constructor inheriting from the parent class which itself is inheriting srgb objects from classes s r g and b stored in seperate files so that sussan cannot pick her favourite colour when the web3 CTO clocks out but is still connected to the blockchain agen
@Omnifarious0 Жыл бұрын
Vitreous humour is the fluid in your eyes. A hairshirt is a self-torture device that people wore as penance for a sin or a constant reminder not to sin. It's very itchy and /or painful to wear on purpose. It's amusing that this author uses such wide-ranging vocabulary. I liked this article when it came out.
@DexieTheSheep Жыл бұрын
thinking of designing a programming language, and async/await vs threads is something I'm starting to be more and more indecisive about...
@Asto508 Жыл бұрын
Multithreading and asynchronous are not at odds with each other. You can combine those two just wonderfully.
@kittenhero568 Жыл бұрын
This async problem are homeomorphic to monadic structures in category theory, so we should be able to borrow the same solution for composing monadic functions
@sub-harmonik Жыл бұрын
stackful coroutines are amazing
@Combatwhombat Жыл бұрын
"The vitreous humor, also called vitreous fluid, is a clear gel-like substance that's located in your eye. It takes up the space between your eye's lens and retina. The vitreous cavity is the name of this space. The vitreous humor helps your eye keep its shape."
@edinalewis4704 Жыл бұрын
“You can avoid the pain of async by using threads”. As a Software Engineer in my 40’s this is the most backwards statement I’ve ever heard. Async/Await was developed specifically to avoid the pain of using threads!!!
@ThePrimeTimeagen Жыл бұрын
have you not used rust? fearless concurrency
@gubfhidnom4714 Жыл бұрын
Async and await and threading solve slightly different problems though. If you block on IO and spawn a new thread to do it, your main thread is no longer blocked but your thread is still being scheduled while waiting for the operation to complete so you're still wasting resources. With async IO, there's no thread until the continuation needs to run. Asynchrony and threads are very often confused and conflated.
@edinalewis4704 Жыл бұрын
@@gubfhidnom4714it was created to solve problems that were previously solved using threads (outside of the kernel that is). So it’s not that they solve different problems, they are different solutions to the same problem. Yes, you can benefit from the concurrency provided by async/await without using the parallelisation provided by threads on multicore CPUs, but thread aren’t guaranteed to be parallel. When threads were first invented, CPU’s only had one core, there was no parallel execution. Threads only gave you concurrency.
@edinalewis4704 Жыл бұрын
@@ThePrimeTimeagen I do love me some rust! But no async methods on traits is huge blocker for me. Looking forward to 1.74!! I know there is crate that offers a workaround, but it requires a heap allocation, we’re running on embedded systems so no_std!
@gubfhidnom4714 Жыл бұрын
@@edinalewis4704 Thanks for the clarification. I do understand what you're saying and I didn't mean to sound like I was disagreeing with you. What I meant by the "slightly different problems" is that threads are a general purpose solution to concurrency whereas asynchrony is a solution specific to IO that requires support from the underlying OS. I mentor a lot of junior/mid-level developers and the overwhelming majority think that async requires a thread while "waiting".
@zeocamo Жыл бұрын
Prime the GoLang err != nil problem is fix with a packages call Matchable, it add Rust match, option and result to Go, and it just works
@batatanna Жыл бұрын
My first experience with Async was when making an app using Java, and oh boy, just because firebase works assync I had to make literally everything async, I wasn't so used to error handle back then so when it came time to debug it I had no clue what to do. I spent two days inserting new try/catch's that normally I wouldn't have used have that been sync and an enormous ammount of Log.d()s everywhere for every single thing just so I could maneuver myself around the code
@Asto508 Жыл бұрын
Just because some parts of are async, doesn't mean that all of your code has to be async. That's probably the main mistake here. It's better to think about how to design the glue between your sync and async code by utilizing queues, event handling, etc. rather than transforming all of your code into one big async disaster. :)
@batatanna Жыл бұрын
@@Asto508 perhaps, but it was due a week and I didn't have time to optimize so I just accepted the ugly 💀
@michaelhart8928 Жыл бұрын
One thing about the Go channel thing, is it's not exactly a coloring as much as its forcing you to design your application concurrently around whatever is using the channel. You effectively are making the function observable. The thing that is nice though, is that you can solve this pretty easily by passing in a function or using an interface. One interface can simply just dispatch to the channel while the other continues processing the data within the same goroutine. Not to mention returning a channel I don't think is good design. Would rather require the caller to pass in the channel so you can reduce the number of channels within the application.
@georgehelyar Жыл бұрын
You can transform both ways between observables and async. The Rx books generally explain it pretty well. Personally i like the idea of observables but usually can't use them because of a lack of backpressure - if the producer produces faster than the consumer consumes and you can't drop things then you need to be able to tell the producer to slow down. Channels and iterators are useful here.
@anlumo1 Жыл бұрын
In Rust, you have to tell the runtime to run an async function (usually that function is called 'spawn' or a variation on that), otherwise the compiler doesn't know what to do with it. You can even have multiple runtimes in the same program executing async functions at the same time. So, that you have to await or spawn an async function is the direct result of the design decision to not bundle the language with an async runtime.
@ThePrimeTimeagen Жыл бұрын
but this also makes it a huge pain in the ass this is most certainly a two edged sword
@anlumo1 Жыл бұрын
@@ThePrimeTimeagen Yes, but I can see why they did it that way. It allows Rust to run on wasm with the browser's runtime and on embedded with a runtime specifically geared towards embedded. It also allows Futures to not be Send, so they are only scheduled on the thread they were created on (usually scheduled via 'spawn_local'). When there's a choice between ease of use and flexibility, Rust always tends towards the latter.
@cerulity32k Жыл бұрын
I use pollster, which just allows you to .block_on() a Future in sync code. No big runtime.
@sacredgeometry Жыл бұрын
Async/await, observables, dynamic it's all the same. That said function composition is a worse pattern when extrapolated to the same extent so it protecting against that bullshit is probably a feature not a bug.
@Nerdimo10 ай бұрын
You can still get race conditions without parallelism. Python natively doesn’t have true parallelism, yet you can have two threads running concurrently write to the same mutable object causing race conditions. It’s why locks exist in the first place.
@thux2828 Жыл бұрын
Thank you Primeagen and Bob. You're doing the Lord's work, keeping me from the sin of pride. Turns out I know nothing about anything.
@streetwear37 Жыл бұрын
Higher-order functions are functions which take functions as arguments. Functions which return a function are partial functions. by partial we mean partial applied function.
@SeanJMay Жыл бұрын
The huge problem with the article, where it talks about the love of Java (or C, or whatever), is that they are either assuming that you have 1 thread in Java, or that somehow thread-pool management, and bringing threaded results back together is somehow *not* concurrency that has bled into your code... it's just even worse when it comes to preventing data-races and stability ... without bleeding mutexes / semaphore checking everywhere ... Don't really have qualms with the Go statements. The compiler essentially handles all concurrency for you, at runtime, period, by determining which concurrency model to use, without ever giving you the choice.
@haydenmitchell9260 Жыл бұрын
the alerts bit is the most relatable adhd thing ever
@NuncNuncNuncNunc Жыл бұрын
Red/blue analogy is more general than async - think the M-word.
@stevenhe3462 Жыл бұрын
From what I've see, eliminating the red-blue problem always involve having a runtime for that. Thinking about Go and Erlang.
@cthutu Жыл бұрын
A higher-order function is a function that takes a function. For example, map, filter etc.
@michawhite7613 Жыл бұрын
22:40 Isn't that literally what await does?
@DryBones111 Жыл бұрын
This whole problem can be tackled by writing better code. The colour bleed isn't an issue of async, the problem is when devs put async calls in their logic. Anything async is an external dependency which belongs at the top level of your code, this way there is nowhere for it to bleed to. Coupling these calls to logic is the idiotic thing to do. Async functions as parameters should be grounds for instant dismissal, it is codebase poisoning. When the author explained the function colours, my first thought was pure/impure which I think categorises the problem more wholistically. Async is just another impure construct. At risk of sounding like functional programming bro, you're better off lifting functions to operate on async values than directly changing the functions to work on async inputs.
@emjizone Жыл бұрын
8:02 @ThePrimeTimeagen Wear a raw, untreated wool sweater directly on your skin until you understand what it is.
@nomoredarts8918 Жыл бұрын
About a year ago I came up with an idea for syntax highlighting that will colour functions according to return type. I think this will stand out especially with fp languages like Elm
@ericng8807 Жыл бұрын
as long as my strings are green
@Vixikats Жыл бұрын
This blog is great because it speaks the fundamental language of shitpost that all terminally online programmers need in order to function properly.
@keychera Жыл бұрын
Interesting that clojurescript core.async is mentioned. From what I gather, it is similar to goroutine (with a similar name: go blocks) So would that mean clojurescript could be colorless as well?
@almicc7 ай бұрын
Old-ish video, but at this point all the code I look at is async and it just turns into synchronous code with extra keywords every few lines. It's nice to be able to call run multiple functions at once, like say I need 3 reads from the database that don't depend on each other, but code gets harder to follow, and I find it's way more common that those 3 reads all require the previous one to pass. When writing to a database, I never want anything to fail, so if something does fail, I stop right there and error out. It's all async code that's never running in parallel, so why must it have to be async in the first place?
@adambickford8720 Жыл бұрын
Java is attempting to keep everything "blue" via `VirtualThread`s, essentially multiplexing 1:N to real threads. It allows you to "block" on a value per normal function call semantics, but in practice the VirtualThread gets taken off the current 'carrier thread' by the jvm and placed back once it is unblocked. Scaling millions of virtual threads is fine.
@y9san9 Жыл бұрын
In Kotlin you actually call async functions as all other functions without any special syntax. And there is also "inline" functions which are being inlined in the process of compilation therefore if you call that function from async stuff you can invoke async stuff as well inside lambdas that are passed to the function.
@ignorantslave663 Жыл бұрын
Kotlin is joyful language, love it
@randomseed Жыл бұрын
Check out Clojure's core.async and its `go` form. Note that this is a macro. So you are able, as a programmer, to add such feature to the Clojure language, by yourself. IMHO that's one of the meanings of "beating the averages" you've shown. Symbolic programming (where a language is its own meta-language) allows you to be free from colors or to make your own colors. :)
@LambdaJack Жыл бұрын
Ignorance is bliss, isn't it?
@Kotfluegel Жыл бұрын
So I guess in Go, you could technically pass a predicate to List::filter which makes a remote API call to determine the result. How do you then implement it so the remote API gets called concurrently for each list element instead of waiting for each predicate invocation one after another? I guess you'd have to write a specialized filter function, that does it for you which sounds an awful lot like a red function again. Except that it can be called from a blue function, but the point remains, that we still have two different implementations for the filter function around.
@Tomyb15 Жыл бұрын
The answer is always Haskell
@tokiomutex4148 Жыл бұрын
My function is locked, being higher order doesn't grant it any special privileges.
@pedrokalil4410 Жыл бұрын
I really love dart handling of this. Need to use an collection? Iterable. Need to use async with filter, expand, map, use an stream. Needs it back as an sync collection? await toList
@igorswies5913 Жыл бұрын
There is also a reverse kind of coloring with C++ with constexpr
@zyxyuv1650 Жыл бұрын
constexpr is a joke, it doesn't even make the function immutable, a constexpr function can still klobber any random global stuff it wants. Try it yourself and find out. Finding out how sad constexpr truly is was the last straw for me with C++. After coding C++ since my teenage years, constexpr was the end of C++. I switched to Rust.
@PS-dp8yg Жыл бұрын
The purpose of curry functions is the ability to compose functions (function composition). You cannot compose functions unless they are curried. A function that takes an input and returns an output becomes the input to another function. This only works with functions that takes in one input at a time. If the output of one function becomes the input of a function that takes in two arguments, it will not work. How do you get the value of the second argument? Functional programming languages such as Haskell, Elm, etc. are all curried by default. There is no such thing as functions with two or more parameters. Even though you think you are writing a function with two or more parameters, under the hood, they are all curried. This means that the function takes in one argument at a time and return another function with the remaining next argument, and etc.
@dasdeck Жыл бұрын
skill/mental model issue. async/await is just syntax sugar. The root cause of this "convolution" is single thread "parallelism". Also, you can break the chain of async declaration at any time by simple using the resulting promise then() callback instead of "await"ing the promise, but are you better off that way?
@confusedbystander2898 Жыл бұрын
No Tomment this time. Just a genuine thank you and welcome to Costco!
@karaloop9544 Жыл бұрын
3:04 That's ligatures, not kerning... right?
@mikethemonsta15 Жыл бұрын
A hairshirt is a shirt made of rough feeling hair. It is worn by religious people as a painful undershirt. Hair shirts are incredibly uncomfortable and they are worn for several reasons: 1) Penance for sins. Sin has a two fold affect. It damages our relationship with God and damages our character. We do penance to repair the damage to our character. 2) Mortification. There are a lot of sins we feel strong physical sensations to do. Lust, gluttony, even wrath as adrenaline is pumping through your body. People mortify themselves (voluntarily taking on pain) to train themselves when they feel pain to trust in God and avoid committing sin. If you are comfortable all the time, then you will have a more difficult time resisting these types of sins when they come around as you'll just want to make the uncomfortable feeling you are experiencing go away. Hair shirts were pretty common back in the day. Now, they are mostly just used by monks and clergy. There's lots of ways to do penance, including prayer, abstaining from things you like, works of mercy, etc. that don't involve mortification. And there are mortifications that actually are also healthy for you to do like cold showers. But the hair shirt remains a holy symbol, an offering of your body to God, and a way to mortify the senses so as to bring them in alignment with your higher reasoning capabilities. St. Pope John Paul II himself wore one and he was pope up until the early 2000's.
@ThePrimeTimeagen Жыл бұрын
is this similar to sackcloth and ashes during mourning times?
@mikethemonsta15 Жыл бұрын
@@ThePrimeTimeagenYeah they are similar! Sack cloth and ashes are usually public penances more to mortify your ego and vanity. To put into perspective your appearance is really but dust and ashes and remind others of this fact through your appearance. Hair shirts are usually worn as an under shirt. So you aren't displaying to others you are doing this penance. It's just between you and God. One of the risks of public penances are that others will try to praise you for doing penance which can be an occasion for vanity and pride. But private penances like hair shirts, a pebble in your shoe, etc. are just between you and God.
@robertj1679 Жыл бұрын
gimme async/await over callbacks any day, love me some syntactic sugar
@ShadoFXPerino Жыл бұрын
The solution is simple: write a linter which bans the use of either red or blue functions.
@soniablanche5672 Жыл бұрын
javascript has 4 colors: normal functions, async functions, generator functions and async generator functions
@Vivraan Жыл бұрын
Also C++ is trying to do coroutines as well now, not sure it will catch on.
@Veretax Жыл бұрын
I can't imagine why this happened but when you said the phrase hey man what's this kerning the OK Google Assistant activated Google is listening into your rants
@ThePrimeTimeagen Жыл бұрын
weird....
@mgsv_morbidslinky10 ай бұрын
4:29 Baader-Meinhof phenomenon
@renatocustodio1000 Жыл бұрын
Funny thing is that now java do async the best among literally all other environments with the new virtual threads. Problem is, you do need to use the latest jdk and many companies are stuck in java 8 or java 11.