What Color Is Your Function | Prime Reacts

  Рет қаралды 102,267

ThePrimeTime

ThePrimeTime

10 ай бұрын

Recorded live on twitch, GET IN
/ theprimeagen
Article: journal.stuffwithstuff.com/20...
Author: / munificentbob
MY MAIN YT CHANNEL: Has well edited engineering videos
/ theprimeagen
Discord
/ discord
Have something for me to read or react to?: / theprimeagenreact

Пікірлер: 305
@samuelschwager
@samuelschwager 10 ай бұрын
I like how Primeagen goes through the last ten years of random dev blog history.
@sumanth3036
@sumanth3036 10 ай бұрын
Content
@gcxs
@gcxs 8 ай бұрын
I like that this blog post defined a new concept
@tcc1234
@tcc1234 8 ай бұрын
It's not your average random dev...
@Don_XII
@Don_XII 4 ай бұрын
It is not a random dev at all.
@dnsfail
@dnsfail 10 ай бұрын
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
@bestergester4100 10 ай бұрын
Thanks for your info
@Supakills101
@Supakills101 10 ай бұрын
Amazing comment
@RobbenBanks153
@RobbenBanks153 4 ай бұрын
Way too much reading
@SLAMarshall
@SLAMarshall 10 ай бұрын
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
@thewhitefalcon8539 10 ай бұрын
Blub is whichever language you use every day. Some people's Blub is Visual Basic. Other's is Haskell.
@istasi5201
@istasi5201 10 ай бұрын
My man going through all them really good old articles
@parnmatt
@parnmatt 10 ай бұрын
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
@Ryan-xq3kl 10 ай бұрын
can we throw the guy who invented them in prison?
@liorean
@liorean 10 ай бұрын
@@Ryan-xq3kl Alonzo Church wouldn't deserve it, if he still lived.
@raffimolero64
@raffimolero64 10 ай бұрын
​@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
@adriankal 10 ай бұрын
@@Ryan-xq3klhow would you handle action on button click?
@NuncNuncNuncNunc
@NuncNuncNuncNunc 10 ай бұрын
@@Ryan-xq3kl f(t(w(x)))
@on-hv9co
@on-hv9co 10 ай бұрын
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
@ThePrimeTimeagen 10 ай бұрын
looks ass pain-ee
@confusedbystander2898
@confusedbystander2898 10 ай бұрын
This is syntactic salt not sugar.
@DaviAreias
@DaviAreias 10 ай бұрын
Syntatic uranium
@claudiusraphael9423
@claudiusraphael9423 8 ай бұрын
@@DaviAreias Urinium. Very Rare.Yellow channel.
@duncanw9901
@duncanw9901 10 ай бұрын
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.
@RagTagPwner
@RagTagPwner 10 ай бұрын
It's hilarious to me how many times I've read this article, but each time I understand something new about it.
@sanderbos4243
@sanderbos4243 10 ай бұрын
Amen
@comradestinger
@comradestinger 10 ай бұрын
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
@ciberman 10 ай бұрын
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
@comradestinger 10 ай бұрын
@@ciberman haha yeah, or networking ;-;
@themisir
@themisir 10 ай бұрын
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
@ciberman 10 ай бұрын
@@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
@comradestinger 10 ай бұрын
​@@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.
@sk-sm9sh
@sk-sm9sh 10 ай бұрын
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.
@Bolpat
@Bolpat 9 ай бұрын
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.
@asdfasdf9477
@asdfasdf9477 10 ай бұрын
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.
@BosonCollider
@BosonCollider 10 ай бұрын
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
@thewhitefalcon8539 10 ай бұрын
Or you have threads
@liorean
@liorean 10 ай бұрын
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
@KManAbout 10 ай бұрын
Ooo this is a good point. I guess this is what haskell purists are trying to say
@perigord6281
@perigord6281 10 ай бұрын
​@@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
@kyay10 10 ай бұрын
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
@diadetediotedio6918
@diadetediotedio6918 10 ай бұрын
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
@jaysistar2711
@jaysistar2711 10 ай бұрын
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.
@mcspud
@mcspud 10 ай бұрын
I remember reading this article back when it first came out. Wow.
@callysibben416
@callysibben416 10 ай бұрын
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
@yarrichar
@yarrichar 9 ай бұрын
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.
@draakisback
@draakisback 10 ай бұрын
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
@hidekxyz 10 ай бұрын
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.
@f1r3w4rr10r
@f1r3w4rr10r 10 ай бұрын
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.
@elmersbalm5219
@elmersbalm5219 10 ай бұрын
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
@vukkulvar9769 10 ай бұрын
Eyeball soup Indiana Jones style
@PS-dp8yg
@PS-dp8yg 10 ай бұрын
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.
@Bukosaure
@Bukosaure 8 ай бұрын
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.
@kamilkardel2792
@kamilkardel2792 10 ай бұрын
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.
@edz8659
@edz8659 10 ай бұрын
Color me surprised
@CorrinWyndryder
@CorrinWyndryder 10 ай бұрын
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.
@yellingintothewind
@yellingintothewind 3 ай бұрын
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.
@georgehelyar
@georgehelyar 10 ай бұрын
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.
@Imaltont
@Imaltont 9 ай бұрын
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.
@mattymerr701
@mattymerr701 9 ай бұрын
"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
@ciberman
@ciberman 10 ай бұрын
At first I REALLY thought the article was about pure and impure functions
@m00ni
@m00ni 10 ай бұрын
Yeah, it really applies to any sort of effect: sync versus async, pure versus impure, throwing versus non-throwing, etc.
@keychera
@keychera 10 ай бұрын
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?
@kittenhero568
@kittenhero568 10 ай бұрын
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
@absolutejam
@absolutejam 10 ай бұрын
It's simple, a red function just returns a value that is a monoid in the category of endofunctors
@ThePrimeTimeagen
@ThePrimeTimeagen 10 ай бұрын
ligma monads
@vivraan
@vivraan 10 ай бұрын
Thanks for taking up a suggestion I had also made!
@michaelhart8928
@michaelhart8928 10 ай бұрын
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.
@anlumo1
@anlumo1 10 ай бұрын
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
@ThePrimeTimeagen 10 ай бұрын
but this also makes it a huge pain in the ass this is most certainly a two edged sword
@anlumo1
@anlumo1 10 ай бұрын
@@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
@cerulity32k 10 ай бұрын
I use pollster, which just allows you to .block_on() a Future in sync code. No big runtime.
@nomoredarts8918
@nomoredarts8918 10 ай бұрын
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
@jswlprtk
@jswlprtk 10 ай бұрын
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
@batatanna
@batatanna 10 ай бұрын
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
@Asto508 10 ай бұрын
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
@batatanna 10 ай бұрын
@@Asto508 perhaps, but it was due a week and I didn't have time to optimize so I just accepted the ugly 💀
@sub-harmonik
@sub-harmonik 10 ай бұрын
stackful coroutines are amazing
@Yupppi
@Yupppi 5 ай бұрын
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.
@samantony4423
@samantony4423 10 ай бұрын
"Lesser of two evils" < "Getting punched in the gut vs. getting punched in the privates"
@stevenhe3462
@stevenhe3462 10 ай бұрын
From what I've see, eliminating the red-blue problem always involve having a runtime for that. Thinking about Go and Erlang.
@unowenwasholo
@unowenwasholo 10 ай бұрын
The Green Threadagen is the hero that we deserve, but not the one we need right now.
@confusedbystander2898
@confusedbystander2898 10 ай бұрын
No Tomment this time. Just a genuine thank you and welcome to Costco!
@flamewave000
@flamewave000 9 ай бұрын
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.
@DexieTheSheep
@DexieTheSheep 10 ай бұрын
thinking of designing a programming language, and async/await vs threads is something I'm starting to be more and more indecisive about...
@Asto508
@Asto508 10 ай бұрын
Multithreading and asynchronous are not at odds with each other. You can combine those two just wonderfully.
@SianaGearz
@SianaGearz 10 ай бұрын
Wow you can learn a whole new flavour of English with just this blog post.
@streetwear37
@streetwear37 9 ай бұрын
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.
@Tomyb15
@Tomyb15 10 ай бұрын
The answer is always Haskell
@keldwikchaldain9545
@keldwikchaldain9545 8 ай бұрын
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.
@Kotfluegel
@Kotfluegel 10 ай бұрын
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.
@quintencabo
@quintencabo 10 ай бұрын
This is a really great article
@NuncNuncNuncNunc
@NuncNuncNuncNunc 10 ай бұрын
Red/blue analogy is more general than async - think the M-word.
@sealsharp
@sealsharp 10 ай бұрын
I love the word "Goroutine". Glad they did that.
@Tazato
@Tazato 9 ай бұрын
It's totally bonkers to me how much of the pain that people who write JS has already been solved by Scala.
@fistoflegend7846
@fistoflegend7846 10 ай бұрын
Bro. Wheel of Time. I hear the Based Department calling all the way from where I'm sitting.
@ThePrimeTimeagen
@ThePrimeTimeagen 10 ай бұрын
big fan, almost done with book 3
@fistoflegend7846
@fistoflegend7846 10 ай бұрын
@@ThePrimeTimeagen Ohhh boy. You're in for a hell of a good read for Shadow Rising.
@sacredgeometry
@sacredgeometry 10 ай бұрын
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.
@thux2828
@thux2828 10 ай бұрын
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.
@Nerdimo
@Nerdimo 2 ай бұрын
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.
@y9san9
@y9san9 10 ай бұрын
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
@ignorantslave663 9 ай бұрын
Kotlin is joyful language, love it
@SeanJMay
@SeanJMay 10 ай бұрын
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.
@samcolserra2425
@samcolserra2425 10 ай бұрын
C# once again looking at the rest with a signature look of superiority 🔥🔥🔥
@cthutu
@cthutu 10 ай бұрын
A higher-order function is a function that takes a function. For example, map, filter etc.
@myusernameislongerth
@myusernameislongerth 10 ай бұрын
4:14 higher order function takes a function as input and/or creates new function.
@Cammymoop
@Cammymoop 9 ай бұрын
Promises are pretty nice actually
@cparks1000000
@cparks1000000 9 ай бұрын
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.
@manningfamilychronicles1601
@manningfamilychronicles1601 10 ай бұрын
You are doing so good with alerts...
@pedrokalil4410
@pedrokalil4410 10 ай бұрын
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
@hypergraphic
@hypergraphic 10 ай бұрын
Nice video. I had read about this in the past, but it's a good refresher. I've been wondering if one way to get away from async complexity in Rust would be to write single threaded rust and run multiple instances just like Python does with uvicorn. Sure, that might mean might use more resources than the async version, but it's already pretty fast single threaded.
@randomseed
@randomseed 10 ай бұрын
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
@LambdaJack 10 ай бұрын
Ignorance is bliss, isn't it?
@SeanJMay
@SeanJMay 10 ай бұрын
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".
@almicc
@almicc 12 күн бұрын
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?
@igorswies5913
@igorswies5913 10 ай бұрын
There is also a reverse kind of coloring with C++ with constexpr
@zyxyuv1650
@zyxyuv1650 9 ай бұрын
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.
@Sw3d15h_F1s4
@Sw3d15h_F1s4 10 ай бұрын
Felt this. I wanted to create a little game for my friends and I, and decided on C# for relatively stress free operation/gui on Windows (my friends are not techies). First thing i worked on was netcode, since this was also an exercise to get myself more familiar with sockets, etc. MS documentation says "use async/await! its great!" Sure, yeah, if you have things that eventually do return. Unfortunately I need a "game server," which means new clients should be able to connect at any time, messages should be received at any time, sent at any time to any number of clients, and do all this while not blocking the UI thread. My "solution" (which im not proud of) was to essentially call an async void function and discard the result, where the async function would await a new socket connection, then call/discard another async function to handle any input for that specific client. The input handler would last the duration of the clients connection and the code handling new connections was a while true loop on async. Horrible, I know. But it does work. Of course i realize now that the real solution is to actually use threads, and to have a background thread handling new connections and directing where input is handled. From a post-mortem of the original code i think this is what i tried to do anyway with async/awiat, but clearly this style of programming was not meant to be used where long-lived background tasks are required.
@Sw3d15h_F1s4
@Sw3d15h_F1s4 10 ай бұрын
the game essentially just needs to be a glorified chatroom, and I planned to control peices on the board through text commands broadcasted to all clients, and when a client gets a "move this to there" command it just works. it's a board game how hard can it be thought.
@emjizone
@emjizone 9 ай бұрын
4:29 This is the birth of _React_, isn't it? Taking a simple hypertext document to a *higher level* of undebuggability.
@AaronNies
@AaronNies 10 ай бұрын
Instead of adding `async/await` as language keywords they could've been user writable functions like what Kotlin did. Structured concurrency is so essential now with everyone adding it. See "Go statement considered harmful". Also, Code Coloring discussion is bigger than just concurrency. Different code worlds (contexts) could be GPU code, a cloud native context, etc. Think WebAssembly component worlds where we don't assume every part of code runs on a POSIX box--code coloring could be done within the same module or like WA be for a whole module.
@HappyCheeryChap
@HappyCheeryChap 10 ай бұрын
Is Haskell more like JS (blue and red) or Go (colorless) on this?
@robertlenders8755
@robertlenders8755 10 ай бұрын
Haskell is more like rainbow. Colours are actually monads and there are lots of different monads in Haskell. It also has ways to make functions be generic to colour and mix multiple colours
@rogergalindo7318
@rogergalindo7318 10 ай бұрын
if you want to do parallelism with pure functions, it’s essentially colorless, you just add a function around what you need to parallelize, and you call it a day, with threads, it gets a little more complicated because it gets restricted by IO, but functionally it’s a game of composing your monads so that it integrates with the rest of your program (with the effect system)
@vivraan
@vivraan 10 ай бұрын
Also C++ is trying to do coroutines as well now, not sure it will catch on.
@Omnifarious0
@Omnifarious0 10 ай бұрын
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.
@madlep
@madlep 10 ай бұрын
Blog: “Wanna know one that doesn’t? Java” Me, flashing back to shared mutable state concurrency in Java: “Johnny?...Johnny!...JOHNNY!”
@emjizone
@emjizone 9 ай бұрын
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.
@soniablanche5672
@soniablanche5672 10 ай бұрын
javascript has 4 colors: normal functions, async functions, generator functions and async generator functions
@guseynismayylov1945
@guseynismayylov1945 10 ай бұрын
I solved this problem by using Async Tree Pattern long time ago, which allows me to avoid using callbacks, Promises and async/await key words. But I doubt that people are open minded enough for this 😅
@Jabberwockybird
@Jabberwockybird 8 ай бұрын
Yellow and with Purple squirrely braces. It's the vscode default for javascript/typescript. Also, Primeagen, when you said blub language, I thought you said love language. what's your love language?
@KeinNiemand
@KeinNiemand 9 ай бұрын
But in C# you can call (red) async function from blue ones, you just have to use .Wait() on the task.
@PS-dp8yg
@PS-dp8yg 10 ай бұрын
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.
@ericng8807
@ericng8807 10 ай бұрын
as long as my strings are green
@haydenmitchell9260
@haydenmitchell9260 10 ай бұрын
the alerts bit is the most relatable adhd thing ever
@MrKyuubiJesus
@MrKyuubiJesus 10 ай бұрын
Call me crazy but I love C# feature of being able to make "await" synchronously
@georgerogers1166
@georgerogers1166 10 ай бұрын
A great use for call/cc
@Veretax
@Veretax 10 ай бұрын
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
@ThePrimeTimeagen 10 ай бұрын
weird....
@avi7278
@avi7278 10 ай бұрын
Easy solution, everything async! 😂
@wetfloo
@wetfloo 10 ай бұрын
#[tokio::main]
@avi7278
@avi7278 10 ай бұрын
@@wetfloo qué????
@renatocustodio1000
@renatocustodio1000 10 ай бұрын
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.
@symbioid
@symbioid 10 ай бұрын
isn't that fi something that happens with some code in pdf when converting to text? like a special character?
@pedrokalil4410
@pedrokalil4410 10 ай бұрын
I like go making errors explicity, just like rust. I think code should go in the direction of streams/observables of result objects with errors or successes for reactive values or futures of result objects for async values or functions that return results for functions that return errors and plain old pure functions for functions that dont return errors or invoke io
@diadetediotedio6918
@diadetediotedio6918 10 ай бұрын
In my humble opinion, there is a very objective and clear reason for the function colors problem to exist, what are we losing when we move from that reason to an environment that doesn't "color its functions"? When we're in C# for example, you know when you need an async/await, and yes that spreads throughout your program, but you also when you don't need an async/await, and we know that there are restrictions on what it can be done in functions of this type, we know the potential problems they leverage, at the end of the line all functions in all languages will have a color, what cost are we paying for languages that hide colors from us?
@SVVV97
@SVVV97 10 ай бұрын
Coloring (without multichromatic functions) adds a bunch of complexity and duplicated logic. Whole libraries currently get duplicated just to provide sync and async APIs.
@ThePrimeTimeagen
@ThePrimeTimeagen 10 ай бұрын
the problem comes to the spreading and the amount of thought you have to put into it. in every language you know (that i am aware of) that a function is red/blue. rust, javascript, c#, all of them come with enough information to know. personally i see why it sucks, i see leaky interface and i get angry. personally i like the async await paradigm though.
@diadetediotedio6918
@diadetediotedio6918 10 ай бұрын
@@ThePrimeTimeagen I can also see why it sucks, but at the same time a part of me understands why they exist. It is that, fundamentally, asynchronous functions are different from synchronous functions, when you write synchronous code you are writing something that will be processed linearly and directly by the processor, you can trust the memory that is on the stack, you can trust that nothing in the program will happen out of your control for that specific context (assuming we're not using threads of course), there may be a number of specific considerations. When a function is async, however, we're dealing with something that is essentially constantly moving around, which will need to be paused and resumed, you can't rely on your stack memory (unless it's copied entirely, which incurs other costs, and the different solutions lead to Pin on Rust), you can't count on the consistency of direct execution, you won't be absolutely sure which thread will execute your code (if we're dealing with async in a multithreaded environment like C# ) and you won't even know when (since that's the purpose of async in the first place), there are a lot of considerations that need to be made when using it (and I also understand that this is part of the tediousness of writing asynchronous code). Of course, that said, I've suffered a lot with function colors, nothing more annoying than realizing that you want to have a "lazy" code in a corner and that to do that you need to mark 300 functions above (hyperbole), I think that in that sense, C# at least manages to partially solve this with the possibility of blocking until you get a result, it wouldn't make a difference in terms of usability if, for example, the entire C# core library was asynchronous, because you can always use a .Result and block until having the result (not that it is the most performative or safest approach, of course, but sometimes it has its purpose to unify the worlds).
@br3nto
@br3nto 10 ай бұрын
Async await still sucks because it spreads like a disease. And you end up awaiting everything. So everything may as well have been synchronous. The code to kick off multiple async functions and await the completion of both also isn’t that nice to write or read. Especially if you have to await the return of one or more before kicking off addition async functions. I like the go syntax for this: a, b =:
Prime React: Fast Inverse Square Root - A Quake III Algorithm
30:19
ThePrimeTime
Рет қаралды 140 М.
Golang Building SSH and Bubble Tea App
57:08
TheVimeagen
Рет қаралды 59 М.
Pray For Palestine 😢🇵🇸|
00:23
Ak Ultra
Рет қаралды 33 МЛН
Dynamic #gadgets for math genius! #maths
00:29
FLIP FLOP Hacks
Рет қаралды 18 МЛН
КАРМАНЧИК 2 СЕЗОН 6 СЕРИЯ
21:57
Inter Production
Рет қаралды 437 М.
HTMX, the anti JS framework (vs React)
7:17
Kodaps Academy
Рет қаралды 63 М.
The State of Develper EcoSystems 2023
32:53
ThePrimeTime
Рет қаралды 109 М.
Software Engineers Hate Code | Prime Reacts
14:47
ThePrimeTime
Рет қаралды 51 М.
How GO Was Created - Less Is More | Prime Reacts
28:15
ThePrimeTime
Рет қаралды 127 М.
What Makes A Great Software Engineer?  -  Alexis Agahi
20:15
ConFoo Developer Conference
Рет қаралды 3,7 М.
The Stockholm Syndrome of SQL | Prime Reacts
31:21
ThePrimeTime
Рет қаралды 120 М.
Rust Functions Are Weird (But Be Glad)
19:52
Logan Smith
Рет қаралды 124 М.
Prime Reacts: I like this Backend
34:07
ThePrimeTime
Рет қаралды 223 М.
XML Is The Future
18:39
ThePrimeTime
Рет қаралды 176 М.
как спасти усилитель?
0:35
KS Customs
Рет қаралды 514 М.
How To Unlock Your iphone With Your Voice
0:34
요루퐁 yorupong
Рет қаралды 16 МЛН
3D printed Nintendo Switch Game Carousel
0:14
Bambu Lab
Рет қаралды 4,7 МЛН
Топ-3 суперкрутых ПК из CompShop
1:00
CompShop Shorts
Рет қаралды 321 М.