The differance is so blurred that we should really call it a spectrum of how human friendly a given code is, rather than recognise those as distinct ways of coding. Software engineers always work on some level of abstraction and even your declarative examples could be considered imperative in a larger context. Btw, looping through arrays and adding numbers could still be considered declarative as so much of what's really happening is hidden (saving variable states to registers etc.)
True, but in looping you are still giving instructions even if they are abstractions of what the machine is doing. I think a great way to learn the difference between the two is trying to learn Haskell. Haskell is a purely functional language, which functional programming is a subset of declarative programming. Because of that many programming concepts like loops, simply don’t exist in Haskell. But despite that it’s just as powerful, because instead it uses recursion.
Declarative code is supposed to be more human friendly but I often find it to be more confusing. I find it to be more difficult to remember all the diffrent syntaxes and how to use them than to just think of the underlying mechanism. I know its better to write as much declarative as possible because its supposed to be less mental work but I find it hard to wrap my head around declarative code for some reason. I like to write my own imperative declarative api because then I feel like I can understand and adapt what is happening in the background. The biggest thing I learned in this video is the fact that I now understand why I find a lot of code to become more and more frustrating to work with and understand. I am just not well versed in programming declaratively.
i don't really fault you for that -- frankly, the double/summation declarative examples are not even more human-readable than the imperative counterparts. if you know pretty basic syntax for *most* common programming languages, then the imperative one is significantly easier to read. the declarative ones require that you know what the map and reduce functions are, that you understand the => operator in js, and what the arguments to those functions even mean (what's the 0 in the reduce call? i have no idea, but i didn't have to ask that question for the imperative code) i left this video thinking "did he just describe a function call?" rather than being impressed by the "simplicity" of the declarative code -- for all intents and purposes, i don't see why a better declarative approach would've been to just call the double() function that was written out imperatively. that's a whole lot more human readable than calling map or reduce with ugly syntax
@@damirahman The 0 is the initial value. Reduce() has an absolutely awful syntax. It's quick and when I write js/ts I do use it for simple things like flattening trees or creating key-value maps from flat arrays, but nobody will ever convince me that it's "cleaner" than writing out the entire thing properly.
In fairness to declarative code, javascript is probably one of the worst languages that could have been used to demonstrate it cause javascript is just kinda awful to read in general. SQL is something you could think of as a "pure" declarative language, and I think it's much better designed to make this style of code readable. It uses verbs which are generally intuitive, and occasionally a bit redundant to make it read more easily at a glance. C# has a library called linq which is based on sql syntax, and it does similar things to the javascript functions but is much more readable, at least to me.
@@CaptainTechnicalityLP I think you get it. The language really defines if you want to program imperatively or declaratively. Javascript is not designed to be declarative in the first place. These features are added in later.
IMHO, any software should be much more explicitely be separated into a declarative and an imperative part. And the declarative part should NOT be written in a *programming* language at all. Failing to do so leads to confusing code in the way you described.
I code both ways depending on what makes the most sense, but I'd be hard pressed to explain the different styles. This video helped give me a vocabulary to help others distinguish imperative programming from declarative programming. Many thanks.
It's just different levels of abstraction. All imperative code is ripe to be labeled as declarative at some point. For example, "table for 2 please" is a small step in a large step of "eating dinner". (Get everyone ready, enter the car, get to a restaurant, get a table for two, order food, eat the food, head home)
keeping open mind, being pragmatic, flexible and believing everything has it's own place and purpose is a valuable mindset to have in programming. heck, in every possible thing you can do even.
But, ultimately, by the way you defined it, isn't "declarative" code simply modular/encapsulated code? You don't worry about the HOW when either A) you wrote a function that encompasses a humanly-readable method elsewhere and use it interchangeably within your different programs or B) someone else did it for you. Maybe you're using preexisting methods (such as Array.map), or write your code entirely in a very high-level language, some sort of visual script for example. People should code imperatively when there exist technical limitations. If you're making the engine for a videogame for example you need to squeeze the most power you can to get a maximum amount of fps. Maybe you're making a web page and you need it to load quickly on older devices, or perhaps it is a browser-based photoshopping app or any other heavy-weight application and you are trying to reduce lag. Maybe you are concerned with security issues and want to prevent hacking attempts that exploit the incorrect usage of preset functions. Declarative is more important when you don't have heavy efficiency requirements, since it speeds up development speed dramatically.
A balance of overhead- when creating an unwieldy beast that must be efficient, the developer must undertake significant MENTAL overhead, "thinking like a computer", to squeeze performance out of the machine. On the other hand, at higher levels, taking on that mental burden is not the best strategy, because you have only so much mental stamina, and the computer can handle doing some inefficient things in the name of the developer having an easier time with development. Gotta meet deadlines, or something.
@@heeyy3 ~~if you can't tell how it works based on declarative programming, it's probably not good declarative programming. You're supposed to be able to understand it because it's written in a human way...~~
Ideally, declarative programming are essentially a bunch of statements about the program, which can be used for running the program, but also to tell other things about the program, such as function invariants, value space constraints, etc. which not only allows to perform the program (which may not always be quite efficient, but always possible), but also analyze the program for various purposes, such as optimization, correctness, etc, which is something done much harder with imperative representations. Even in imperative languages such as java and c++ you almost always add some declarative information to your program, such as limiting visibility, instantiability, inheritance, input/output/value/error space, nullability, multiplicity and more. Declarative programming is basically defining the program purely in terms of its contract. In imperative programming, explicit static-time information is much more limited and deriving it from code is non-trivial. Therefore, a declarative program compiled with a good optimizer might actually be a much better thing than a poorly optimized imperative implementation.
@@heeyy3 It's probably because of vague/poor naming. For example, if I want a function to suck me off, then I may write def succ(). But succ what? More precisely I would have to name it to def succDicc().
I remember learning haskell and it blew my mind. Its a pure functional programming language and i always had a hard time explaining why its so weird to even other cs students. Its like a regular language except every line is a return statement and it takes 3 lines of code to write quicksort in haskell. Basically almost every line follows a: "FunctionName Parameters = ReturnValue"
Currently learning Haskell and I couldn't agree more. You basically say "Do this, combine it with this then do this after" and then it does it. I love it
ALL have imperative APIs underneith. Declarative Coding is marketing speak for adjusting the configuration of some prewritten software. The syntactic sugar and DX is the only thing that ever really evolves. It could be a domain specific language for a compiler like Svelte or a framework with classes like Rails or a bit of markup like React, it's all just filling out the options on some config that the imperative code in the library uses to do the real work. The error messages tend to get pretty bad when arbitrary options are misconfigured and Stack Overflow is born. Chasing other people's TPS reports is a terrible way to make a living. Declarative will always be a more frustrating way to code when things are erroring or poorly documented, but possibly faster when things are going well, like at the beginning of a project. (Progress) *Sigh*
"Declarative" programming is like my seven year old nephew learning to code. He wants to just make the game work by typing in whatever pops into his head, and then he gets frustrated and impatient when he realizes computers don't work that way.
I get really frustrated with these marketing buzzwords that might have some nuanced philosophical underpinnings but they are so overused by people who misunderstand them that they lose all real meaning. Here's my take on it: "declarative" = optimizing for human legibility, usually identified by having a clear story in the code and direct tie-in to the task at hand; "imperative" = optimizing for the machine (speed or other factors), usually identified by the code being tightly-coupled to its operating context (machine/environment/etc.). Also, positioning them as a dichotomy is what causes so much confusion on the topic. It is a spectrum. One commentator (or maybe the video) gives the example of a restaurant where declarative would be "I want a pizza" while imperative is "take 2 cups of flour, add salt... " however saying "I want pizza is context-constrained because what if the pizza there isn't any good? Even more declarative would be "make me happy" and the chef serves up whatever is the best for you and even more imperative would include "so find a field, put this wheat seed in the ground...." I wish we would throw out the "imperative vs. declarative" paradigm and more talk about human legibility vs context-coupled. All applications should be human-legibile on the higher levels, but as you drill down into these functions it should be a gradual transition towards context-coupling. This also leads into a discussion on lazy vs. eager execution which is a similar balance between human interpretability and machine optimization.
@@bobthemagicmoose I might add that in some cases we should also consider simply not making a developer api and opting for a graphical tool like a level editor or paint program. Not everyone needs to be a developer, and if they aren't operating at the lower levels (or lack an understanding of the lower levels), they probably *shouldn't* be a developer. It's totally fine to just give people a spreadsheet and have them enter some values without ever having them touch the code. It may be preferred.
@@bobthemagicmoose It does make me think. Are the level editors for the games I create "declarative"? Their user interface is largely concerned with "what" is in the levels, not how the levels are interpreted by the game in order to play properly. Am I doing "declarative programming" by making these levels, placing tiles and starting locations and other entities into my game world? By currently accepted definitions of the term, I'm not entirely convinced I'm not. And that's the problem. It's an ill-defined term which is used too broadly.
@@tedbendixson people argue about what "real" programming/developing is all the time... but I would say that "programming" is taking a task and deconstructing it into smaller tasks (aka instructions). If one of the tasks does not exist in the system, you break it down now until all tasks can be performed by the system you are using. The more complicated this process is (remember, the deconstruction needs to gradually get to tasks that map to instructions available to you!), the more it is considered programming. For most games, I think level editors require these skills because you have to deconstruct the experience you are going to create ("I want an easy puzzle that features x mechanic with a tutorial system to guide the player") into objects available in the level creator.
I have been prompting Chat GPT for half an hour to grasp the meaning of these terms but failed. This video beautifully explained it within 5 mins. Genius !!! Keep up the good work mate. Subscribed !!!
While I love the higher-order Array operations (map, filter, reduce, etc..), it's not always a good idea to use them for every situation. In some scenarios, where the input is large, callbacks can have a negative impact on the speed of the code execution during runtime due to context switching. Sometimes, a "for" loop, however verbose, is definitively faster.
It’s less about choosing between imperative and declarative programming styles, and more about keeping them separate. You want your declarative code to control what happens and when, and you want your imperative code to actually do the work.
I don't know what V8 does under the hood with iterators, but this tradeoff isn't inevitable in the general case. The Rust compiler, for example, can often translate maps/filters/etc. into IR that's at least as performant as a for loop with manual indexing, via inlining and other tricks. I say "at least" because the functional approach is often *faster*, since the compiler has all the information necessary to skip the bounds checks that it might otherwise insert in cases where there's no straightforward way to infer from context that the maximum size of the loop index is less than the size of the collection being accessed. Rust is very committed to zero-cost abstractions like that, but in this case I don't see anything about JavaScript that would prevent it from enjoying the same type of optimization, and that's kind of how I think about declarative approaches in general: they can be less performant, but they don't need to be, since they also give the compiler/runtime the benefit of an abstraction boundary behind which it can do optimizations with information that maybe isn't accessible or representable in the front-end environment.
@@AftercastGames "You want your declarative code to control what happens and when, and you want your imperative code to actually do the work." This is a really nice way to put it. I'll keep this in mind
What happens often in my project is that I start writing something imperative and as complexity increases I know which part I can extract to a method that provides the same mechanism in a declarative way, but reusable. It's actually been my most groundbreaking discovery with my gamedev projects that complexity only really goes up when I fail to do the above. When too much code is stuck inside an entity and should instead be extracted to a component that runs in the background. It actually does exactly the same thing but forces me to write better structured code so common data is in the entity, not the component. It took me almost 4 years of game prototyping to truly understand this and get a proper workflow in my engine.
Another way to look at declarative vs imperative is that the former rarely deals with time, whereas the latter is affected by time, i.e. you have to worry about the order. A more concrete example is, reading a file: imperative is a series of function calls such as fopen, fseek (possibly), fread and fclose. The declarative version would be read_data(file, offset, buffer, buffer_size).
I know this wasn't this video's intention, but I learned something about my own way of thinking. I'm autistic and I'm now realizing that the reasons why a) I'm having such a difficult time in this society and b) I'm a natural at programming is because I have a more imperative way of thinking whereas most people have a more declarative way of thinking. (Also, the latter is probably because programming was created primarily by autistic people to begin with.) No wonder people often compare us autistics to robots...
Wow, that's a really interesting observation. My Wife taught severe special ed and a common thing she'd do when helping kids with severe autism stay focused is elaborate the order of things ("First X, then Y") . That totally aligns with your theory.
@@uidotdev Thanks! Also, as someone who went to a special ed school, _"First_ work, _then_ snack." has been forever engrained into my head. Meanwhile, I was more concerned as to why you couldn't eat your snack _while_ doing your work. Also, I wanted to clarify that using functioning labels is looked down upon because it sort of puts kids in a box with no room to improve. A lot of us fluctuate over time. Like, I had "mild" autism for most of my life that became more "severe" in the past few months due to mental illness. I even lost the ability to talk for a few days despite having been fully-verbal since I took speech classes in kindergarten. Additionally, at my school, I had no problems forming friendships with the non-verbal kids. And, amongst each other, some of them even had crushes. (One of my non-verbal friends was infamous for partaking in PDA with his girlfriend, who was also non-verbal, during school events.) Most people don't seem to realize that there are ways to communicate that don't involve speaking.
@@uidotdev Wow. I was thinking that you are absolutely amazing at after effects. I think about opening a channel to teach some software engineering concepts but I am very concerned about edit as I have never really edited a video. I should start with whatever I know. Great video anyways. Thanks.
Dito last comment, even the meaning of imperative and declarative have now been rewired in my brain and now it feels like my head has been blown off, you have earned yourself a subscription, kudos to you sir...
Great video. If anybody is still asking 'why does this matter?' it may help to consider how much need there is for programming in the world. To keep the world running, we have to use declarative code or nothing would get done in time.
I call it the "uncertainty principle of programming" - the more domain, human level readability you have the less you know about what happens on the CPU. But that's rather hermetical 😁 Great video, will definitely send it around 👍
To play devil's advocate here, I have used both imperative and declarative languages, frameworks, and styles in the past. I believe that both have their benefits and drawbacks - however, in my opinion, the main drawback of the declarative side, which is INEXCUSABLE, is the inability to peek under the hood. By trying to exemplify the essence of programming, it has missed the trees for the forest. Imperative programming has its drawbacks, but these are mostly just annoyances, not anything as grave as this. Here's what I mean: Suppose you want to examine every element of a list and create a new list based on those elements. The map function works perfectly! The for loop is more ugly and takes longer to write. But, either one is just as intuitive and efficient as the other. Now, suppose you want to examine every second element of the list. Such a minor tweak requires a correspondingly minor tweak to the for loop, which retains its intuitiveness. Suddenly, the positions have been flipped - it's possible to express this in a declarative, functional way, but it takes much longer to write and to understand than the for loop. Another example. Suppose that you want to write a recursive algorithm that caches its results (aka dynamic programming). Such algorithms may be written either imperatively or declaratively (I know, I have tried to write these kinds of algorithms in functional languages). But here we encounter another problem. The very idea of declaratively writing an algorithm is absurd! When we write an algorithm, we very specifically want to instruct the computer how to accomplish an objective, not just tell it the objective that it should accomplish. Advocates of declarative and functional programming usually have pithy sayings, like "the essence of programming is composing functions and objects together" or "a program consists of interactions between interfaces", but such sayings miss the entire point of programming. The unique task of the programmer, compared to the mathematician or the physicist, is to create and codify efficient algorithms for highly specific systems. You don't need to be a programmer to write a data processing pipeline or a web UI that displays all rows of a table. Programming expertise comes into play when you're trying to fix edge cases, write fast algorithms, and fine-tune your algorithms to your specific client's needs. The important part of programming is actually the "ugly" part, and an imperative paradigm is needed to intuitively and efficiently codify the "ugly" parts. Sorry if that sounded like a rant. I enjoyed the video. I also believe in a *mostly* declarative / functional approach. However, I do not believe that any paradigm is superior to any other, and if anything, imperative / procedural must be the best due to its ability to easily handle ugly situations. Thank you for attending my TED talk.
Interesting thoughts. Sometimes you need to be able to look under the hood of course. But I don't think that the point is to never do imperative programming. That’s why he said that declarative APIs lay on top of imperative implementations. Code that is only imperative is super difficult to reason with. Code that is only declarative and hides its underlying mechanism is difficult to fully understand. A mix of both is needed.
@@ygeb93 good take, I agree. It's the same thing I feel about encapsulation. It's mostly useful but there are a few places where it limits your ability to get stuff done.
I'd disagree, Imperative is "better" under any meaningful usage of the word. At the end of the day, everything you ever write becomes assembly that tells the computer *_exactly_* what it ought to be doing. Unless we want to grant the credit of *_all_* abstraction to Declarative code, Imperative styles retain that direct behavioural model while still being simplifiable after the fact. When it comes to writing real programs, Imperative will *_always_* have the edge for that reason. Declarative's only real value is A : when you've decided to work with a language so absurdly far removed from the hardware writing the code yourself isn't even possible. (Python for instance NEEDS to offload heavy computational work onto other languages because its so insanely slow you couldn't write it even if you wanted to. In other words, Declarative abstraction is literally necessary because of the weakpoints in the language) Or B : when you are operating in a very codified problem space and working with pure concepts instead of gritty realities. In other words, you don't ask a haskell dev to write an embedded OS. Declarative & functional languages are excellent at working on very strict concepts but implementation absolutely kills them. For me a great example of the nuance here is Rust which, despite having many abstractions and incorporating functional concepts, is nonetheless very clearly imperative. Thats why I really don't think Declarative can be credited for abstraction, because even abstract languages clearly still behave Imperatively.
Isn't all programming declarative to some extent ? I mean when writing the function to double the elements of an array we ask the OS to give us an array . We do not know the exact memory addresses that will be occupied by this array or how the memory allocation (however it is )works ,etc .The programmer is shielded from knowing or dealing with all of that . So how do we decide which layer of abstraction is appropriate ? I guess it depends on the context and its not black & white . As things evolve and the we just keep putting another layer of abstraction over another , over another. Great video though! Totally loved how it flowed and how it got me thinking. Good job!
(as a programmer for thew last 20+ years) I also thought that when describing 'declarative' programming it had more to do with using a library where all the imperative programming was all done in the past and some new 'declarative' interface makes all that technology available in an easier-to-use declarative interface. So indeed you'Re right that there's declarative stuff in the imperative code too,. it's just so prevalent that most dont even see it: let myarray = [ ]; doesnt require you to code assembly to assign a space of ram and deal with it, its all declarative from that layer on, presented as a higher order programming language. html, css , angular, react or whatever declarative web stuff is just a higher order above the 'imperative' langugages below it, I wonder if this will repeat again in more technology stacks / language layers . etc... ?
@@felixgraphx Exactly my thoughts . Its definitely there in so many places although I feel that front end is the worst offender that I know and embedded space is least affected because you cannot stack when there is no space to put stuff , lol. All of this could be fine but what bothers me with these layers of abstraction is that they don't appear to be sturdy .Its like a tower of houses built on one another with no concern about sustainability just immediate gain and fewer people remember how the older houses even work . This is one of the reasons why software errors and malfunctions are so bloody common. If anyone likes this topic I will highly suggest the talk by jonathan blow. ua-cam.com/video/ZSRHeXYDLko/v-deo.html
While declarative code is itself an abstraction of imperative code, this doesn't mean that all imperative code is abstracted through declarative code. Imperative code also abstracts over other imperative code. You can think of this as "layers", and thereof we have layers of abstraction; from machine code to high level languages.
@@felixgraphx It was a reply to the original comment :-) The original comment questioned whether not all programming was "declarative". My comment explains why that is not always the case.
I was about to take my breakfast and I though: "This videos looks like a nice option" I wasn't wrong about it. Actually fantastic example approach. Keep the content my friend!
Good explanation. I alwasy thought about declarative was using the map or filter functions in js, but could never give a precise definition for it. And it's true: declarative is praised as being better but sometimes imperative is just better, and sometimes the only way. Just yesterday i was coding collision detection in js and the imperative way was just much better than the declarative
Interesting: When running the Imperative vs Declarative examples on a javascript benchmarking suite like jsbench, the Imperative examples run almost twice as fast
@@riddixdan5572 I'd say that argument is valid for source code, but not for production code if there is just a plain faster method available (at least for most cases). Of course this doesn't mean tho, that you have to give up one side's benefits for the other, as there are tools to optimize code for production environments too.
Depends how well the declarative libraries are written. If you're like me and can't optimize for shit then substituting a declarative can speed it up substantially.
@@JoelKesler Those methods run through conditionals that are unnecessary most of the time. That along with the callback stack frames is why they're alot slower than a basic for/while loop. A simple recursive function is faster too.
To me it feels like at the point you decided to create function "double", you're already being declarative. Actual implementation of that function seems almost irrelevant, and I certainly would prefer the first one to the "improved" one because by the point you wanted to look at how exactly is doubling an array elements thing happening, I'm thinking the first one is more self-explanatory. Which is fairly important, because being self-explanatory, easy to read and grasp is helpful for debugging, and the declarative step had happened already when you created and named a function to do this thing.
absolutely agree with this. and in production its just as important to be human readable to the other programmers so that if the bus situation occurs your not spending time and money trying to map everything out. Method names should be declarative and inside those methods can be either more declarative methods or the imperative. but no matter what logically it should be understood what the hell is going on by a peer in case of bus. funny enough i was actually hit by a bus on my way to work a while back but i was in a car.
I feel like this is very comparable to the tell dont ask principle. You tell other classes what to do instead of getting information from in order to do it yourself. Great video
This video help you clearly understand the difference between imperative(How) and declarative(What) programming with the analogy(restaurant), and an example of the code with a clear and simple explanation making even the non-tech person understand what is it all about. I do like the imperative approach just because it helps me understand exactly what is the code doing overall and may help with understanding time and space complexity line by line. However, I like declarative programming better because it helps with developing programs quickly, and easily pumping out your ideas into reality really quickly. And if you want really want to know behind the scene about a particular declarative approach you can always find some sort of documentation or community help that explains what it is doing under the hood. I also notice that there are lots of communities supporting declarative approaches to things and it seems like that might be the future. Edit: Some typos.
By the idea that imperative code is the "how" and declarative code is the "what", wouldn't it be reasonable to say that *all* code is declarative because in the end it all boils down to the computer executing the tasks, and we just tell it what task to execute? Of course using JS Map over a For loop is a good example of the difference in terms of actual application and usage. But from a more philosophical perspective, I really can't see any difference between "imperative" and "declarative" code except them being fancy words for comparing things like frameworks, libraries, or programming languages.
writing my own language has thought me a lot about imperative Vs declarative programming. So in std:liste I have method injections for the primitive list. these methods include simple for loops as well because, well my fault that I didn't implement for loops natively. So it's a method instead. And the implementation of for uses this weird syntax because of this. (lamb * 2 end)[Some list with elements]:for The method implemented being: metod for >> liste -> self -> func 0 -> i :. i < self:len iken # while i < self:len (self:[i])func son # end son # end But this is just the basics and the std will grow in the future to support more declarative code rather than the extremely imperative code it has right now
I like this comment a lot. It too feel like declarative statements are just abstractions. You can always take 10 "declarative" pieces of code, put them in a file and argue that it is imperative compared to a new abstraction that encapsulate all of them, no?
@@TheAwesomeDudeGuy You are right with the first one, the author also made clear that we should have an API around imperative code to make it declarative. But I don't think you got the point of what imperative and declarative is. The fact that you abstract already declarative code, doesn't mean the code you abstracted is not declarative. Why would wrapping multiple components inside another component make the code inside less descriptive of WHAT is happening? You can abstract declarative code without it stopping being declarative.
@@shuaima5989 lol I often default to more declarative stuff when I'm too lazy to go research yet again all of the nuances of those "easy" abstractions. Also, sometimes using all those abstractions leads down a dark spiral of twisted callbacks and return values. *Shudder*
It's for two reasons: 1. You might not be used to reading this type of code, so it's more of an issue of not understanding the declarations and their immediate implications. It's like the difference between your speed of travel when riding a bike for the very first time. It's going to be slow until you get used to it 2. This example is a proof of concept. Declarative code scales *a lot* better in production applications As a side note, here is an example that I think does a better job. Convert an array of objects into a string of comma-separated words. Which one would you prefer here? const toListText = (items) => { let text = '' items.forEach((item, idx) => { if (idx === item.word.length - 1) { text += item.word } else { text += item.word + ', ' } }) return text } const toListText = items=> { return items .map(({ word}) => word) .join(', ') }
Awesome! Made total sense. Only mod I would make to the video is longer pauses between sentences, it would allow me more time to ingest the concept of that makes sense
Declarative is just programming to an abstraction - there's stuff happening behind the scenes that you don't need to worry about. It's insane that people in the industry feel the need to over-complicate everything and attach them to some buzzword.
Good explanation, but I disagree that code needs to be more declarative. Adding a "human friendly" api doesn't make the underlying implementation any less complex. It just puts a smiley face on the complexity, and it can often mislead people into thinking there is less complexity than is actually present. It also leads to a programmer culture that's more about making code look "pretty" than being concerned about what problems the computer needs to solve to deliver value to the customer. Millions of programmers are basically doing the equivalent of secretarial work, shuffling code around to make it seem "clean" instead of being concerned with what their software is doing. At best, it's an innocent little waste of time. At worst, it becomes an obsession that leads to analysis paralysis and waste. Let computers be computers. Let programmers be programmers. The job of a programmer is to understand how to tell a computer what to do, not to spend all day shaping code so it fits your personal aesthetic preferences.
@@uidotdev I'm probably too harsh on code aesthetics. I do think some code aesthetics matter, but we as a culture definitely take it too far. There's a really good video by Brian Will criticizing OOP where he talks about what sort of code aesthetics we should be concerned about, and I largely agree with where he lands. Jonathan Blow makes some great points about when to factor code into functions, and it has helped me out greatly.
The world needs more programmers like you. Hiding the complexity of the problem behind an "all is well" smiley face is about the worst thing you can do. Jonathan Blow, as you also refer to, calls it "shuffling papers around on your desk". It does absolutely zero to help solve the problem and it only makes the resulting code *more* complex and slower to execute. Replacing for loops with slow random third party methods is such a bad practice that it's not even funny....and it will *not* make the code easier to read or understand. Any programmer knows what a for loop is. arr.reduce on the other hand? There are zero benefits to that. This is why modern software sucks. The best code is the honest code that reveals both intention and implementation at face value.
You have valid points, I think what you're missing here is the size of the development team. The larger the team, the more hands in the cookie jar, the more valuable human readable abstracted code becomes. If a developer has to read the code and think like a computer before the developer can implement changes, it ends up costing more time. That said, we shouldn't be optimizing and organizing code to be re-usable when it shouldn't exist in the first place. Knowing WHEN to take time to do this is often the different between an experienced developer, and an inexperienced developer. Ultimately, the problems with over-doing it don't often show their face until you're met with scale. And unfortunately, most developers don't get to experience large scale applications. This just leads to bad habits, even if the code is beautiful. It's interesting because modern programing is slowing turning novice developers into what I would actually consider a "user" rather than an actual developer. Consider someone just starting now, they might use 2, 3, or more frameworks that just install with a package manager. Might have no idea how css or native javascript even functions because they're "using" a bunch of pre-made classes and handy features from a framework. Or worse, a "website builder". Bottom line is, don't learn how to use a hammer and organize a 200 piece toolbox when all you really needed was a screwdriver.
@@XGhozt. I'm not yet convinced that this is better for large teams. I do work on a large team, and for the most part I notice that the extra work put into making the code more "human friendly" just increases the surface area of the code, creating more places where I find myself asking "What calls into this function / what uses this object?" There are many cases where nothing else calls into the function or the object is only ever used in one place. The abstraction is purely in the category of putting a smiley face on the complexity, and it makes me read and search through more code than I would have needed to otherwise. A major barrier and cost for large organizations is the time it takes to ramp up new developers. If you need to search through abstraction after abstraction just to find the meat, it's going to take much longer to get up to speed on how to work in that codebase. I would much prefer a minimally abstracted, concise, clear, and to the point codebase over one that creates extra abstractions to hide its inherent complexity. The former is at least being honest with me. On a more broad note, we as an industry just aren't measuring the effectiveness of many of these approaches. People say "such and such is better for large teams" but where are the studies demonstrating this to be the case? I would expect the major Universities to be conducting research on the effectiveness of certain programming practices within the context of different team sizes, but they just aren't. We're like the medical field before we had the FDA. Snake oil salesmen are everywhere. Many so-called best practices are just opinions, and preferring "declarative" over imperative is yet another programming fad that is not supported by a rigorous evidence-based approach.
This was a great video, but the bit that immediately made me subscribe was when you identified *why* the common explanations for declarative/imperative only make sense after you already understand them. Convinced me that you know that you're a talented educator.
The code examples you give are not great because it conflates the explicit-abstraction axis with the imperative-declarative one. For example, in C++ you can do std::ranges::transform(arr, arr.begin(), [](u64 item) -> u64 { return item * 2; }); and this is imperative, not declarative, because it denotes an action to take, rather than describing the output directly. In contrast, the (terrible) functional Javascript code function double(arr, i=0) { if (arr.length
Congrats, great explanation. Btw. Love your newsletter. And that must mean something. I'm using the internet for over 20 years, and I never liked newsletters at all (yuck spam). This is the first one I actually read regularly for a year now. Keep up the good job.
Great video! Very succinct! I liked the part about building declarative APIs out of imperative code. It would've been helpful to see some guidelines on how we can do this well. I also have the question about how to be productive in primarily declarative languages like Lisp or Haskell. Whenever I try to pick up those languages, I feel stuck. I guess I need to practice partial function application and composition more.
A really good overview! Declarative languages don't have to be domain-specific like SQL though There are general-purpose declarative languages that can express the 'what' without wrapping everything in subroutines and other imperative cruft. I don't know that much about logical languages, but at least in many functional ones it's the other way around - when you want to describe the low-level 'how' you build it out of functions and data structures while usually staying in the pure, declarative-thinking land
Did not expect this video to be this good lol
*declarative
True
rude
yooo the guy on the banner
@@RedStone576 o.O I didn't even see that ahahaha
The differance is so blurred that we should really call it a spectrum of how human friendly a given code is, rather than recognise those as distinct ways of coding. Software engineers always work on some level of abstraction and even your declarative examples could be considered imperative in a larger context. Btw, looping through arrays and adding numbers could still be considered declarative as so much of what's really happening is hidden (saving variable states to registers etc.)
That's a fair takeaway.
True, but in looping you are still giving instructions even if they are abstractions of what the machine is doing. I think a great way to learn the difference between the two is trying to learn Haskell. Haskell is a purely functional language, which functional programming is a subset of declarative programming. Because of that many programming concepts like loops, simply don’t exist in Haskell. But despite that it’s just as powerful, because instead it uses recursion.
@@timothymcguire5126 Smol brain here, how do you process an array like in the described double(arr) function without a loop?
@@SufferDYT for each member of array, do a thing; not neccesserally looping, could be in parallel, if no dependencies
@@overloader7900 Foreach sounds like a loop, but I see the distinction lol
Declarative code is supposed to be more human friendly but I often find it to be more confusing. I find it to be more difficult to remember all the diffrent syntaxes and how to use them than to just think of the underlying mechanism. I know its better to write as much declarative as possible because its supposed to be less mental work but I find it hard to wrap my head around declarative code for some reason. I like to write my own imperative declarative api because then I feel like I can understand and adapt what is happening in the background.
The biggest thing I learned in this video is the fact that I now understand why I find a lot of code to become more and more frustrating to work with and understand. I am just not well versed in programming declaratively.
i don't really fault you for that -- frankly, the double/summation declarative examples are not even more human-readable than the imperative counterparts. if you know pretty basic syntax for *most* common programming languages, then the imperative one is significantly easier to read.
the declarative ones require that you know what the map and reduce functions are, that you understand the => operator in js, and what the arguments to those functions even mean (what's the 0 in the reduce call? i have no idea, but i didn't have to ask that question for the imperative code)
i left this video thinking "did he just describe a function call?" rather than being impressed by the "simplicity" of the declarative code -- for all intents and purposes, i don't see why a better declarative approach would've been to just call the double() function that was written out imperatively. that's a whole lot more human readable than calling map or reduce with ugly syntax
@@damirahman The 0 is the initial value. Reduce() has an absolutely awful syntax. It's quick and when I write js/ts I do use it for simple things like flattening trees or creating key-value maps from flat arrays, but nobody will ever convince me that it's "cleaner" than writing out the entire thing properly.
In fairness to declarative code, javascript is probably one of the worst languages that could have been used to demonstrate it cause javascript is just kinda awful to read in general. SQL is something you could think of as a "pure" declarative language, and I think it's much better designed to make this style of code readable.
It uses verbs which are generally intuitive, and occasionally a bit redundant to make it read more easily at a glance. C# has a library called linq which is based on sql syntax, and it does similar things to the javascript functions but is much more readable, at least to me.
@@CaptainTechnicalityLP I think you get it.
The language really defines if you want to program imperatively or declaratively.
Javascript is not designed to be declarative in the first place. These features are added in later.
IMHO, any software should be much more explicitely be separated into a declarative and an imperative part. And the declarative part should NOT be written in a *programming* language at all. Failing to do so leads to confusing code in the way you described.
I code both ways depending on what makes the most sense, but I'd be hard pressed to explain the different styles. This video helped give me a vocabulary to help others distinguish imperative programming from declarative programming. Many thanks.
So glad you found it useful.
It's just different levels of abstraction. All imperative code is ripe to be labeled as declarative at some point.
For example, "table for 2 please" is a small step in a large step of "eating dinner". (Get everyone ready, enter the car, get to a restaurant, get a table for two, order food, eat the food, head home)
keeping open mind, being pragmatic, flexible and believing everything has it's own place and purpose is a valuable mindset to have in programming. heck, in every possible thing you can do even.
Been in the biz for over 6 years and now I also finally understand what the two means. Thanks!
Glad it helped!
I wanted to say that I forgot to subscribe and I legitimately remembered later in the day and went back to make sure I'd get more of your videos.
Means a lot. Thank you!
@@uidotdev Thank you for your reply! The pleasure is all mine really.
But, ultimately, by the way you defined it, isn't "declarative" code simply modular/encapsulated code? You don't worry about the HOW when either A) you wrote a function that encompasses a humanly-readable method elsewhere and use it interchangeably within your different programs or B) someone else did it for you. Maybe you're using preexisting methods (such as Array.map), or write your code entirely in a very high-level language, some sort of visual script for example.
People should code imperatively when there exist technical limitations. If you're making the engine for a videogame for example you need to squeeze the most power you can to get a maximum amount of fps. Maybe you're making a web page and you need it to load quickly on older devices, or perhaps it is a browser-based photoshopping app or any other heavy-weight application and you are trying to reduce lag. Maybe you are concerned with security issues and want to prevent hacking attempts that exploit the incorrect usage of preset functions.
Declarative is more important when you don't have heavy efficiency requirements, since it speeds up development speed dramatically.
A balance of overhead- when creating an unwieldy beast that must be efficient, the developer must undertake significant MENTAL overhead, "thinking like a computer", to squeeze performance out of the machine. On the other hand, at higher levels, taking on that mental burden is not the best strategy, because you have only so much mental stamina, and the computer can handle doing some inefficient things in the name of the developer having an easier time with development. Gotta meet deadlines, or something.
@@heeyy3 ~~if you can't tell how it works based on declarative programming, it's probably not good declarative programming. You're supposed to be able to understand it because it's written in a human way...~~
Ideally, declarative programming are essentially a bunch of statements about the program, which can be used for running the program, but also to tell other things about the program, such as function invariants, value space constraints, etc. which not only allows to perform the program (which may not always be quite efficient, but always possible), but also analyze the program for various purposes, such as optimization, correctness, etc, which is something done much harder with imperative representations. Even in imperative languages such as java and c++ you almost always add some declarative information to your program, such as limiting visibility, instantiability, inheritance, input/output/value/error space, nullability, multiplicity and more. Declarative programming is basically defining the program purely in terms of its contract. In imperative programming, explicit static-time information is much more limited and deriving it from code is non-trivial. Therefore, a declarative program compiled with a good optimizer might actually be a much better thing than a poorly optimized imperative implementation.
@@heeyy3 It's probably because of vague/poor naming. For example, if I want a function to suck me off, then I may write def succ(). But succ what? More precisely I would have to name it to def succDicc().
@@OmegaF77 *He is speaking the language of gods*
So basically, this boils down to what level of abstraction you are programming in?
I remember learning haskell and it blew my mind. Its a pure functional programming language and i always had a hard time explaining why its so weird to even other cs students. Its like a regular language except every line is a return statement and it takes 3 lines of code to write quicksort in haskell. Basically almost every line follows a:
"FunctionName Parameters = ReturnValue"
Currently learning Haskell and I couldn't agree more. You basically say "Do this, combine it with this then do this after" and then it does it. I love it
I am glad that UA-cam's algorithm recommended me this video.
Glad you enjoyed it!
Let's get UA-cam famous, Tyler!
New year, new me!
This has to be one of the best programming channels I've ever seen
Thanks for watching!
ALL have imperative APIs underneith. Declarative Coding is marketing speak for adjusting the configuration of some prewritten software. The syntactic sugar and DX is the only thing that ever really evolves. It could be a domain specific language for a compiler like Svelte or a framework with classes like Rails or a bit of markup like React, it's all just filling out the options on some config that the imperative code in the library uses to do the real work. The error messages tend to get pretty bad when arbitrary options are misconfigured and Stack Overflow is born. Chasing other people's TPS reports is a terrible way to make a living. Declarative will always be a more frustrating way to code when things are erroring or poorly documented, but possibly faster when things are going well, like at the beginning of a project. (Progress) *Sigh*
"Declarative" programming is like my seven year old nephew learning to code. He wants to just make the game work by typing in whatever pops into his head, and then he gets frustrated and impatient when he realizes computers don't work that way.
I get really frustrated with these marketing buzzwords that might have some nuanced philosophical underpinnings but they are so overused by people who misunderstand them that they lose all real meaning. Here's my take on it: "declarative" = optimizing for human legibility, usually identified by having a clear story in the code and direct tie-in to the task at hand; "imperative" = optimizing for the machine (speed or other factors), usually identified by the code being tightly-coupled to its operating context (machine/environment/etc.).
Also, positioning them as a dichotomy is what causes so much confusion on the topic. It is a spectrum. One commentator (or maybe the video) gives the example of a restaurant where declarative would be "I want a pizza" while imperative is "take 2 cups of flour, add salt... " however saying "I want pizza is context-constrained because what if the pizza there isn't any good? Even more declarative would be "make me happy" and the chef serves up whatever is the best for you and even more imperative would include "so find a field, put this wheat seed in the ground...."
I wish we would throw out the "imperative vs. declarative" paradigm and more talk about human legibility vs context-coupled. All applications should be human-legibile on the higher levels, but as you drill down into these functions it should be a gradual transition towards context-coupling. This also leads into a discussion on lazy vs. eager execution which is a similar balance between human interpretability and machine optimization.
@@bobthemagicmoose I might add that in some cases we should also consider simply not making a developer api and opting for a graphical tool like a level editor or paint program.
Not everyone needs to be a developer, and if they aren't operating at the lower levels (or lack an understanding of the lower levels), they probably *shouldn't* be a developer.
It's totally fine to just give people a spreadsheet and have them enter some values without ever having them touch the code. It may be preferred.
@@bobthemagicmoose It does make me think. Are the level editors for the games I create "declarative"? Their user interface is largely concerned with "what" is in the levels, not how the levels are interpreted by the game in order to play properly.
Am I doing "declarative programming" by making these levels, placing tiles and starting locations and other entities into my game world?
By currently accepted definitions of the term, I'm not entirely convinced I'm not. And that's the problem. It's an ill-defined term which is used too broadly.
@@tedbendixson people argue about what "real" programming/developing is all the time... but I would say that "programming" is taking a task and deconstructing it into smaller tasks (aka instructions). If one of the tasks does not exist in the system, you break it down now until all tasks can be performed by the system you are using. The more complicated this process is (remember, the deconstruction needs to gradually get to tasks that map to instructions available to you!), the more it is considered programming.
For most games, I think level editors require these skills because you have to deconstruct the experience you are going to create ("I want an easy puzzle that features x mechanic with a tutorial system to guide the player") into objects available in the level creator.
Finally, someone who knows what they are talking about. You are a gem dude.
so "declarative" means simply more abstract
It’s definitely a way to abstract code. Not the only one, that why we need the word.
Less than 5 minutes it took this guy to explain this properly
Rarely comment on youtube, but just wanted to say, this is an incredibly good explanation, thank you very much!
You're very welcome. Thanks for taking the time to let us know ❤️
I literally didn’t think I would’ve been able to understand that… The video is so quick yet so informative!
Glad it was helpful!
Welcome Back @Tyler McGinnis & Happy New Year 🖖
Good to be back!
I have been prompting Chat GPT for half an hour to grasp the meaning of these terms but failed. This video beautifully explained it within 5 mins. Genius !!!
Keep up the good work mate. Subscribed !!!
Thank you!
While I love the higher-order Array operations (map, filter, reduce, etc..), it's not always a good idea to use them for every situation. In some scenarios, where the input is large, callbacks can have a negative impact on the speed of the code execution during runtime due to context switching. Sometimes, a "for" loop, however verbose, is definitively faster.
Right. Whole goal was to portray declarative vs imperative as a scale with different tradeoffs along the way.
It’s less about choosing between imperative and declarative programming styles, and more about keeping them separate. You want your declarative code to control what happens and when, and you want your imperative code to actually do the work.
@@uidotdev but it didn't portray any tradeoffs ... i couldn't guess at least
I don't know what V8 does under the hood with iterators, but this tradeoff isn't inevitable in the general case. The Rust compiler, for example, can often translate maps/filters/etc. into IR that's at least as performant as a for loop with manual indexing, via inlining and other tricks. I say "at least" because the functional approach is often *faster*, since the compiler has all the information necessary to skip the bounds checks that it might otherwise insert in cases where there's no straightforward way to infer from context that the maximum size of the loop index is less than the size of the collection being accessed. Rust is very committed to zero-cost abstractions like that, but in this case I don't see anything about JavaScript that would prevent it from enjoying the same type of optimization, and that's kind of how I think about declarative approaches in general: they can be less performant, but they don't need to be, since they also give the compiler/runtime the benefit of an abstraction boundary behind which it can do optimizations with information that maybe isn't accessible or representable in the front-end environment.
@@AftercastGames "You want your declarative code to control what happens and when, and you want your imperative code to actually do the work."
This is a really nice way to put it. I'll keep this in mind
I want to declare something here.
I felt that was imperative to subscribe. That’s how you have got a new subscriber.
Welcome! ❤️
What happens often in my project is that I start writing something imperative and as complexity increases I know which part I can extract to a method that provides the same mechanism in a declarative way, but reusable. It's actually been my most groundbreaking discovery with my gamedev projects that complexity only really goes up when I fail to do the above. When too much code is stuck inside an entity and should instead be extracted to a component that runs in the background. It actually does exactly the same thing but forces me to write better structured code so common data is in the entity, not the component. It took me almost 4 years of game prototyping to truly understand this and get a proper workflow in my engine.
wow cool
More i browse through UA-cam more I love this world. No one could have done it better.
Thanks mate for such great analogy. Cheers !
So basically declarative programming is pushing the problem of implementing something on someone else... ?
exactly
I can honestly say that this single video changed the way I write code.
Another way to look at declarative vs imperative is that the former rarely deals with time, whereas the latter is affected by time, i.e. you have to worry about the order. A more concrete example is, reading a file: imperative is a series of function calls such as fopen, fseek (possibly), fread and fclose. The declarative version would be read_data(file, offset, buffer, buffer_size).
beat explanation ever. Watched the video cuz appeared in suggestion and stayed and subscribed due to quality opf explanation,.
Welcome!
Really looking forward to you becoming "UA-cam famous"!
Making my Mom proud. Finally.
This video clarified the hell out of those two terms in my programming vocabulary. Thank you very much, man.
Glad you enjoyed it
What a great start for you! You're going far.
Thank you Jarrett!
I know this wasn't this video's intention, but I learned something about my own way of thinking.
I'm autistic and I'm now realizing that the reasons why a) I'm having such a difficult time in this society and b) I'm a natural at programming is because I have a more imperative way of thinking whereas most people have a more declarative way of thinking. (Also, the latter is probably because programming was created primarily by autistic people to begin with.)
No wonder people often compare us autistics to robots...
Wow, that's a really interesting observation. My Wife taught severe special ed and a common thing she'd do when helping kids with severe autism stay focused is elaborate the order of things ("First X, then Y") . That totally aligns with your theory.
@@uidotdev Thanks! Also, as someone who went to a special ed school, _"First_ work, _then_ snack." has been forever engrained into my head. Meanwhile, I was more concerned as to why you couldn't eat your snack _while_ doing your work.
Also, I wanted to clarify that using functioning labels is looked down upon because it sort of puts kids in a box with no room to improve. A lot of us fluctuate over time. Like, I had "mild" autism for most of my life that became more "severe" in the past few months due to mental illness. I even lost the ability to talk for a few days despite having been fully-verbal since I took speech classes in kindergarten.
Additionally, at my school, I had no problems forming friendships with the non-verbal kids. And, amongst each other, some of them even had crushes. (One of my non-verbal friends was infamous for partaking in PDA with his girlfriend, who was also non-verbal, during school events.) Most people don't seem to realize that there are ways to communicate that don't involve speaking.
How are map and reduce declarative? I don't get it.
This seems more about abstraction.
It's a tricky one, just like how literally everything seems to be able to be called an api lol
Bro, you have no idea! This is exactly what I needed to understand these confusing concepts. Thanks Brother!
Top quality video and explanation, like in one with 5000 views
Thank you Vital!
Somehow i feel u r so underrated. The topics u choose are actually very helpful. Thanks again for the time man.
That means a lot. Thank you!
Came to SUBSCRIBE AND RING THE BELL, woah already done !
LFG!
this is becoming my favorite programming channel, period.
okay now the real question is how long did it really take to make this vid, and what software did you use ;)
4-5 days. I'm a noob so coded the animations with Framer Motion and did everything else in Screenflow.
@@uidotdev Wow. I was thinking that you are absolutely amazing at after effects. I think about opening a channel to teach some software engineering concepts but I am very concerned about edit as I have never really edited a video. I should start with whatever I know. Great video anyways. Thanks.
Dito last comment, even the meaning of imperative and declarative have now been rewired in my brain and now it feels like my head has been blown off, you have earned yourself a subscription, kudos to you sir...
keep making content like this and you'll blow up! this video is giving my fireship vibes but way more chill.
Amazing. Just the video I was looking for to show to one of my new juniors
Glad I could help!
Great video. If anybody is still asking 'why does this matter?' it may help to consider how much need there is for programming in the world. To keep the world running, we have to use declarative code or nothing would get done in time.
Glad you enjoyed it!
I call it the "uncertainty principle of programming" - the more domain, human level readability you have the less you know about what happens on the CPU. But that's rather hermetical 😁
Great video, will definitely send it around 👍
To play devil's advocate here, I have used both imperative and declarative languages, frameworks, and styles in the past. I believe that both have their benefits and drawbacks - however, in my opinion, the main drawback of the declarative side, which is INEXCUSABLE, is the inability to peek under the hood. By trying to exemplify the essence of programming, it has missed the trees for the forest. Imperative programming has its drawbacks, but these are mostly just annoyances, not anything as grave as this. Here's what I mean:
Suppose you want to examine every element of a list and create a new list based on those elements. The map function works perfectly! The for loop is more ugly and takes longer to write. But, either one is just as intuitive and efficient as the other. Now, suppose you want to examine every second element of the list. Such a minor tweak requires a correspondingly minor tweak to the for loop, which retains its intuitiveness. Suddenly, the positions have been flipped - it's possible to express this in a declarative, functional way, but it takes much longer to write and to understand than the for loop.
Another example. Suppose that you want to write a recursive algorithm that caches its results (aka dynamic programming). Such algorithms may be written either imperatively or declaratively (I know, I have tried to write these kinds of algorithms in functional languages). But here we encounter another problem. The very idea of declaratively writing an algorithm is absurd! When we write an algorithm, we very specifically want to instruct the computer how to accomplish an objective, not just tell it the objective that it should accomplish.
Advocates of declarative and functional programming usually have pithy sayings, like "the essence of programming is composing functions and objects together" or "a program consists of interactions between interfaces", but such sayings miss the entire point of programming. The unique task of the programmer, compared to the mathematician or the physicist, is to create and codify efficient algorithms for highly specific systems. You don't need to be a programmer to write a data processing pipeline or a web UI that displays all rows of a table. Programming expertise comes into play when you're trying to fix edge cases, write fast algorithms, and fine-tune your algorithms to your specific client's needs. The important part of programming is actually the "ugly" part, and an imperative paradigm is needed to intuitively and efficiently codify the "ugly" parts.
Sorry if that sounded like a rant. I enjoyed the video. I also believe in a *mostly* declarative / functional approach. However, I do not believe that any paradigm is superior to any other, and if anything, imperative / procedural must be the best due to its ability to easily handle ugly situations.
Thank you for attending my TED talk.
Interesting thoughts.
Sometimes you need to be able to look under the hood of course. But I don't think that the point is to never do imperative programming. That’s why he said that declarative APIs lay on top of imperative implementations. Code that is only imperative is super difficult to reason with. Code that is only declarative and hides its underlying mechanism is difficult to fully understand. A mix of both is needed.
@@ygeb93 good take, I agree. It's the same thing I feel about encapsulation. It's mostly useful but there are a few places where it limits your ability to get stuff done.
Well said!
I'd disagree, Imperative is "better" under any meaningful usage of the word. At the end of the day, everything you ever write becomes assembly that tells the computer *_exactly_* what it ought to be doing. Unless we want to grant the credit of *_all_* abstraction to Declarative code, Imperative styles retain that direct behavioural model while still being simplifiable after the fact.
When it comes to writing real programs, Imperative will *_always_* have the edge for that reason.
Declarative's only real value is
A : when you've decided to work with a language so absurdly far removed from the hardware writing the code yourself isn't even possible. (Python for instance NEEDS to offload heavy computational work onto other languages because its so insanely slow you couldn't write it even if you wanted to. In other words, Declarative abstraction is literally necessary because of the weakpoints in the language)
Or
B : when you are operating in a very codified problem space and working with pure concepts instead of gritty realities. In other words, you don't ask a haskell dev to write an embedded OS. Declarative & functional languages are excellent at working on very strict concepts but implementation absolutely kills them.
For me a great example of the nuance here is Rust which, despite having many abstractions and incorporating functional concepts, is nonetheless very clearly imperative. Thats why I really don't think Declarative can be credited for abstraction, because even abstract languages clearly still behave Imperatively.
To be honest, your comment is better than most TED talks I've heard.
Best explanation I’ve come across so far!
Thank you!
Isn't all programming declarative to some extent ?
I mean when writing the function to double the elements of an array we ask the OS to give us an array . We do not know the exact memory addresses that will be occupied by this array or how the memory allocation (however it is )works ,etc .The programmer is shielded from knowing or dealing with all of that .
So how do we decide which layer of abstraction is appropriate ? I guess it depends on the context and its not black & white .
As things evolve and the we just keep putting another layer of abstraction over another , over another.
Great video though! Totally loved how it flowed and how it got me thinking. Good job!
(as a programmer for thew last 20+ years) I also thought that when describing 'declarative' programming it had more to do with using a library where all the imperative programming was all done in the past and some new 'declarative' interface makes all that technology available in an easier-to-use declarative interface. So indeed you'Re right that there's declarative stuff in the imperative code too,. it's just so prevalent that most dont even see it: let myarray = [ ]; doesnt require you to code assembly to assign a space of ram and deal with it, its all declarative from that layer on, presented as a higher order programming language. html, css , angular, react or whatever declarative web stuff is just a higher order above the 'imperative' langugages below it, I wonder if this will repeat again in more technology stacks / language layers . etc... ?
@@felixgraphx Exactly my thoughts . Its definitely there in so many places although I feel that front end is the worst offender that I know and embedded space is least affected because you cannot stack when there is no space to put stuff , lol.
All of this could be fine but what bothers me with these layers of abstraction is that they don't appear to be sturdy .Its like a tower of houses built on one another with no concern about sustainability just immediate gain and fewer people remember how the older houses even work . This is one of the reasons why software errors and malfunctions are so bloody common.
If anyone likes this topic I will highly suggest the talk by jonathan blow.
ua-cam.com/video/ZSRHeXYDLko/v-deo.html
While declarative code is itself an abstraction of imperative code, this doesn't mean that all imperative code is abstracted through declarative code. Imperative code also abstracts over other imperative code. You can think of this as "layers", and thereof we have layers of abstraction; from machine code to high level languages.
@@dealloc yes, imperative code is from both declarative and other imperative. no one implied otherwise, (if i did i misspoke) :)
@@felixgraphx It was a reply to the original comment :-) The original comment questioned whether not all programming was "declarative". My comment explains why that is not always the case.
I was about to take my breakfast and I though: "This videos looks like a nice option"
I wasn't wrong about it. Actually fantastic example approach. Keep the content my friend!
So glad you enjoyed it!
Good explanation. I alwasy thought about declarative was using the map or filter functions in js, but could never give a precise definition for it. And it's true: declarative is praised as being better but sometimes imperative is just better, and sometimes the only way. Just yesterday i was coding collision detection in js and the imperative way was just much better than the declarative
Glad it was helpful!
One of the best and most succinct programming related videos that I have ever watched! Major props!
IN! I love your work
Thank you Mike!
Holly hell you explained this in a way that makes perfect sense thank you.
I didnt even know this concept existed but now I understand lol
Nicely done, interestingly enough I was trying to come up with a good explanation of these terms for my peers
Glad you found it useful!
amazing video! thank you! saying “what” vs “how” never really help me with any concrete understanding. Thank you for this down to earth explanation!
Glad you enjoyed it!
Interesting: When running the Imperative vs Declarative examples on a javascript benchmarking suite like jsbench, the Imperative examples run almost twice as fast
Imperative - Using for loop
9,361,471 ops/sec
Declarative - Using array map and array reduce
5,184,327 ops/sec
until you hit an actual bottleneck that is caused by using map instead of for-i, readability of the code takes priority over anything.
@@riddixdan5572 I'd say that argument is valid for source code, but not for production code if there is just a plain faster method available (at least for most cases).
Of course this doesn't mean tho, that you have to give up one side's benefits for the other, as there are tools to optimize code for production environments too.
Depends how well the declarative libraries are written. If you're like me and can't optimize for shit then substituting a declarative can speed it up substantially.
@@JoelKesler Those methods run through conditionals that are unnecessary most of the time. That along with the callback stack frames is why they're alot slower than a basic for/while loop. A simple recursive function is faster too.
You have a very soothing voice, and the animations are very enjoyable. Keep up the great work!
Thank you Arno!
To me it feels like at the point you decided to create function "double", you're already being declarative. Actual implementation of that function seems almost irrelevant, and I certainly would prefer the first one to the "improved" one because by the point you wanted to look at how exactly is doubling an array elements thing happening, I'm thinking the first one is more self-explanatory. Which is fairly important, because being self-explanatory, easy to read and grasp is helpful for debugging, and the declarative step had happened already when you created and named a function to do this thing.
absolutely agree with this. and in production its just as important to be human readable to the other programmers so that if the bus situation occurs your not spending time and money trying to map everything out. Method names should be declarative and inside those methods can be either more declarative methods or the imperative. but no matter what logically it should be understood what the hell is going on by a peer in case of bus. funny enough i was actually hit by a bus on my way to work a while back but i was in a car.
I feel like this is very comparable to the tell dont ask principle. You tell other classes what to do instead of getting information from in order to do it yourself. Great video
Oh man! I didn't even know I wanted this video. But it's amazing. Thank you for clearing that up for me. 😌
Thank you! Glad you enjoyed it.
This video help you clearly understand the difference between imperative(How) and declarative(What) programming with the analogy(restaurant), and an example of the code with a clear and simple explanation making even the non-tech person understand what is it all about.
I do like the imperative approach just because it helps me understand exactly what is the code doing overall and may help with understanding time and space complexity line by line. However, I like declarative programming better because it helps with developing programs quickly, and easily pumping out your ideas into reality really quickly. And if you want really want to know behind the scene about a particular declarative approach you can always find some sort of documentation or community help that explains what it is doing under the hood.
I also notice that there are lots of communities supporting declarative approaches to things and it seems like that might be the future.
Edit: Some typos.
Dude please make more videos!
It's my biggest focus this year ❤
@@uidotdev Woop woop! 👏
I know my comment comes way later, but this is a great explanation and helped me understand the difference. Thanks.
By the idea that imperative code is the "how" and declarative code is the "what", wouldn't it be reasonable to say that *all* code is declarative because in the end it all boils down to the computer executing the tasks, and we just tell it what task to execute? Of course using JS Map over a For loop is a good example of the difference in terms of actual application and usage. But from a more philosophical perspective, I really can't see any difference between "imperative" and "declarative" code except them being fancy words for comparing things like frameworks, libraries, or programming languages.
i've never heard of these concepts before, but i can certainly say that i understand them after this.
I imagine you'll start hearing them more now. Glad you enjoyed it!
Thanks from Ukraine!
❤
I think abstract concepts like these are best understood through video with animations / images. Thanks a lot!
Glad you enjoyed it!
writing my own language has thought me a lot about imperative Vs declarative programming. So in std:liste I have method injections for the primitive list. these methods include simple for loops as well because, well my fault that I didn't implement for loops natively. So it's a method instead.
And the implementation of for uses this weird syntax because of this.
(lamb * 2 end)[Some list with elements]:for
The method implemented being:
metod for >> liste -> self -> func
0 -> i
:. i < self:len iken # while i < self:len
(self:[i])func
son # end
son # end
But this is just the basics and the std will grow in the future to support more declarative code rather than the extremely imperative code it has right now
Shut up ! Omg this is the best and most concise explanation ever.
WoW!
I’m so shocked. I now understand stand the difference
❤
Liked and subscribed! Let's gooooo! 👊
❤
I really appreciate how short these are
Thanks for watching!
Imperative = How
Declarative = What
Makes sense now!!
Glad you found it useful!
Thanks for this video!
You're welcome!
Great explanation/introduction! Another concept that helps me code more thoughtfully.
Amazing explanation. Loved how the entire video "flowed" from start to end!
I wish all programming related videos were like this.
How is a "for" loop not declarative with relation to the interpretor's implementation of a "for" loop?
I like this comment a lot. It too feel like declarative statements are just abstractions.
You can always take 10 "declarative" pieces of code, put them in a file and argue that it is imperative compared to a new abstraction that encapsulate all of them, no?
Agreed, maybe the for loop vs js array method is not a very good example? Also as a bad js developer the reduce is harder to read than the for loop 😂
@@TheAwesomeDudeGuy You are right with the first one, the author also made clear that we should have an API around imperative code to make it declarative. But I don't think you got the point of what imperative and declarative is. The fact that you abstract already declarative code, doesn't mean the code you abstracted is not declarative. Why would wrapping multiple components inside another component make the code inside less descriptive of WHAT is happening? You can abstract declarative code without it stopping being declarative.
@@shuaima5989 this video by Fireship should help you with reduce
ua-cam.com/video/tVCYa_bnITg/v-deo.html
@@shuaima5989 lol I often default to more declarative stuff when I'm too lazy to go research yet again all of the nuances of those "easy" abstractions. Also, sometimes using all those abstractions leads down a dark spiral of twisted callbacks and return values. *Shudder*
I have been looking around for a nice explanation and I look no more. Thanks!
I actually think the first 3 examples are clearer. Idk if that’s weird
Actually not weird at all, was just hard to cover that in a video like this. Declarative doesn't always mean "better".
It's for two reasons:
1. You might not be used to reading this type of code, so it's more of an issue of not understanding the declarations and their immediate implications. It's like the difference between your speed of travel when riding a bike for the very first time. It's going to be slow until you get used to it
2. This example is a proof of concept. Declarative code scales *a lot* better in production applications
As a side note, here is an example that I think does a better job. Convert an array of objects into a string of comma-separated words. Which one would you prefer here?
const toListText = (items) => {
let text = ''
items.forEach((item, idx) => {
if (idx === item.word.length - 1) {
text += item.word
} else {
text += item.word + ', '
}
})
return text
}
const toListText = items=> {
return items
.map(({ word}) => word)
.join(', ')
}
Awesome! Made total sense. Only mod I would make to the video is longer pauses between sentences, it would allow me more time to ingest the concept of that makes sense
Awesome tutorial I'm taking the self taught approach to programming and I found this video extremely helpful
So glad to hear.
Thanks, I'm in the camp of hearing these terms repeatedly without understanding what they mean. I needed this video. Thanks
So glad you found it helpful. Thanks for taking the time to let us know.
Declarative is just programming to an abstraction - there's stuff happening behind the scenes that you don't need to worry about. It's insane that people in the industry feel the need to over-complicate everything and attach them to some buzzword.
If I create an imperative abstraction is it more declarative?
Great explanation. Declarative code is just an abstraction to allow users to ask what they want.
Good explanation, but I disagree that code needs to be more declarative. Adding a "human friendly" api doesn't make the underlying implementation any less complex. It just puts a smiley face on the complexity, and it can often mislead people into thinking there is less complexity than is actually present.
It also leads to a programmer culture that's more about making code look "pretty" than being concerned about what problems the computer needs to solve to deliver value to the customer. Millions of programmers are basically doing the equivalent of secretarial work, shuffling code around to make it seem "clean" instead of being concerned with what their software is doing.
At best, it's an innocent little waste of time. At worst, it becomes an obsession that leads to analysis paralysis and waste.
Let computers be computers. Let programmers be programmers. The job of a programmer is to understand how to tell a computer what to do, not to spend all day shaping code so it fits your personal aesthetic preferences.
Fair comment. Thanks for taking the time to write it up.
@@uidotdev I'm probably too harsh on code aesthetics. I do think some code aesthetics matter, but we as a culture definitely take it too far.
There's a really good video by Brian Will criticizing OOP where he talks about what sort of code aesthetics we should be concerned about, and I largely agree with where he lands.
Jonathan Blow makes some great points about when to factor code into functions, and it has helped me out greatly.
The world needs more programmers like you. Hiding the complexity of the problem behind an "all is well" smiley face is about the worst thing you can do. Jonathan Blow, as you also refer to, calls it "shuffling papers around on your desk". It does absolutely zero to help solve the problem and it only makes the resulting code *more* complex and slower to execute. Replacing for loops with slow random third party methods is such a bad practice that it's not even funny....and it will *not* make the code easier to read or understand. Any programmer knows what a for loop is. arr.reduce on the other hand? There are zero benefits to that.
This is why modern software sucks. The best code is the honest code that reveals both intention and implementation at face value.
You have valid points, I think what you're missing here is the size of the development team. The larger the team, the more hands in the cookie jar, the more valuable human readable abstracted code becomes. If a developer has to read the code and think like a computer before the developer can implement changes, it ends up costing more time.
That said, we shouldn't be optimizing and organizing code to be re-usable when it shouldn't exist in the first place. Knowing WHEN to take time to do this is often the different between an experienced developer, and an inexperienced developer.
Ultimately, the problems with over-doing it don't often show their face until you're met with scale. And unfortunately, most developers don't get to experience large scale applications. This just leads to bad habits, even if the code is beautiful.
It's interesting because modern programing is slowing turning novice developers into what I would actually consider a "user" rather than an actual developer. Consider someone just starting now, they might use 2, 3, or more frameworks that just install with a package manager. Might have no idea how css or native javascript even functions because they're "using" a bunch of pre-made classes and handy features from a framework. Or worse, a "website builder".
Bottom line is, don't learn how to use a hammer and organize a 200 piece toolbox when all you really needed was a screwdriver.
@@XGhozt. I'm not yet convinced that this is better for large teams.
I do work on a large team, and for the most part I notice that the extra work put into making the code more "human friendly" just increases the surface area of the code, creating more places where I find myself asking "What calls into this function / what uses this object?" There are many cases where nothing else calls into the function or the object is only ever used in one place. The abstraction is purely in the category of putting a smiley face on the complexity, and it makes me read and search through more code than I would have needed to otherwise.
A major barrier and cost for large organizations is the time it takes to ramp up new developers. If you need to search through abstraction after abstraction just to find the meat, it's going to take much longer to get up to speed on how to work in that codebase.
I would much prefer a minimally abstracted, concise, clear, and to the point codebase over one that creates extra abstractions to hide its inherent complexity. The former is at least being honest with me.
On a more broad note, we as an industry just aren't measuring the effectiveness of many of these approaches. People say "such and such is better for large teams" but where are the studies demonstrating this to be the case? I would expect the major Universities to be conducting research on the effectiveness of certain programming practices within the context of different team sizes, but they just aren't.
We're like the medical field before we had the FDA. Snake oil salesmen are everywhere. Many so-called best practices are just opinions, and preferring "declarative" over imperative is yet another programming fad that is not supported by a rigorous evidence-based approach.
This was a great video, but the bit that immediately made me subscribe was when you identified *why* the common explanations for declarative/imperative only make sense after you already understand them. Convinced me that you know that you're a talented educator.
The code examples you give are not great because it conflates the explicit-abstraction axis with the imperative-declarative one. For example, in C++ you can do
std::ranges::transform(arr, arr.begin(), [](u64 item) -> u64 { return item * 2; });
and this is imperative, not declarative, because it denotes an action to take, rather than describing the output directly. In contrast, the (terrible) functional Javascript code
function double(arr, i=0) {
if (arr.length
Appreciate the comment. Thanks for watching.
Well said. Expressiveness and levels of abstraction are key to managing complexity...map and reduce do that...they are not declarative.
@@uidotdev this comment by @uidotdev basically means "i dont give a fuck, fuck off"
@@bradmazurek Yeah I thought map and reduce were more of a functional programming thing rather than a declarative thing.
Thanks, I've watched this video twice and understood! 🙏🙏😆
Glad it was helpful!
Congrats, great explanation.
Btw. Love your newsletter. And that must mean something. I'm using the internet for over 20 years, and I never liked newsletters at all (yuck spam). This is the first one I actually read regularly for a year now. Keep up the good job.
That means a lot. Thank you Tony!
I didn't expect this video do the this good. The animations and the concise and clear explanation reminds me a lot of 3Blue1Brown's style
Glad you enjoyed it!
Awesome concept, never thought of this, keep it up 👍
Glad you enjoyed it!
Very good video explanation, thank you! The Wikipedia definitions for these concepts is rather weird and this video isn’t. 👍🏼👍🏼
Glad you liked it!
Great video! Very succinct! I liked the part about building declarative APIs out of imperative code. It would've been helpful to see some guidelines on how we can do this well. I also have the question about how to be productive in primarily declarative languages like Lisp or Haskell. Whenever I try to pick up those languages, I feel stuck. I guess I need to practice partial function application and composition more.
Solid suggestion. Thanks!
i didn't expect this. Such a good video.
Glad you enjoyed it!
A really good overview!
Declarative languages don't have to be domain-specific like SQL though
There are general-purpose declarative languages that can express the 'what' without wrapping everything in subroutines and other imperative cruft.
I don't know that much about logical languages, but at least in many functional ones it's the other way around - when you want to describe the low-level 'how' you build it out of functions and data structures while usually staying in the pure, declarative-thinking land
Great video - like this format with historical context.
Thank you!
Great video! Your explanation was extremely clear and concise. I immediately got what I came looking for. +1 sub from me :D
Glad you enjoyed it. Welcome!
very well done; i see the inspiration from JCS, yt needs more like this
Not sure who JCS is. Have a link?
That's explained well. Good job
Thank you!
Perfect explanation. Great stuff!
Glad you enjoyed it!