1. Declarative languages or constructs are much harder to debug when things are not working as expected. There are no breakpoints to put or no debug statements to write or no watch to put. It was supposed to do that and you just can't tell why it's doing this.
2. Performance issues are much harder to resolve with declarative constructs. When you get in hotspot, there is no way to run. You would be fortunate if your language/platform allows you to fall back to imperative mode but there are platforms/languages out there which insist in 100% declarative styles.
3. There is lot of bad declarative syntax that is not designed to be composable. Lot of time, it's just is not extensible or allows to take advantage of modern programming language constructs such as inheritance, functional patterns, etc.
1. Declarative expressions are much easier to spot for defects (and much easier to not introduce defects). So do you want easier interaction w/ your debugger or do you want less bugs?
2. "There is no way to run" is an overstatement, I think. You have to run toward understanding the abstractions you're using. (E.g., if I have GC issues in the JVM, it's not that I have no where to run, it's just that now I have to go understand the GC abstraction.)
3. There is a lot of bad imperative code out there that is just as inflexible to work with.
This is the difference between closed form versus summation problems. Sure, short closed form problems are much easier to understand than infinite sums. However, sometimes the closed form is borderline alien compared to the sum.
1. I would not say that SQL is harder to debug than imperative code. I have also noticed that I get less bugs and they take less time to solve when I push as much as possible to SQL. Usually something either works properly or it doesn't. I personally find SQL is one of the few languages where reading the code is easier than writing it.
2: Database optimizations must be some of the most well known ways to improve performance in the tech field.
3: SQL syntax isn't great (I wouldn't say it is terrible either).
To someone not familiar with the practice, I'd say that imperative programming is like manufacturing a car step by step, attaching parts to the engine, building the frame and so on. There are a plethora of tasks involved but it's usually clear how to finish them if you know the principles.
Declarative programming is like finding a magic incantation that makes a car pop into existence. It feels great when the default incantation works and you deliver a finished car in five minutes, but things tend to get confusing quickly if you decide that the car needs a customized transmission, a new row of seats, or (heaven forbid) a different number of wheels. Soon you're poring over arcane texts on GearChangeCommands and CabinPresenters and WheelLocators and potentially spending longer than you would have by just building the car in the slow, predictable way.
That said, I can't help but like the declarative style too, and would still prefer it much of the time to build user interfaces.
We abstract the "how" into declarative statements of "what" and "how many".
Analogy #1: if I were going to write a game for PC, I would directly write a game for PC, not a GBA ROM + GBA emulator for PC and make-believe that it's a PC game.
Analogy #2: if I want to write a novel in Spanish, it will not be possible to achieve the quality of a text written in Spanish from the beginning, by say, writing it in Japanese and using a translator (no matter how much you may like Japanese). Some idioms and culture-dependent things will be lost in translation. (Italian or Portuguese might be better, however)
So, to your analogy #1. If such an emulator already existed and was in wide use, you would not be doing any harm to your system to target it.
To extend your analogy to the absurd, it doesn't make sense to write your program out symbolically in a programming language, because at the end of the day it is electrical values in a processor.
With true declarative forms, you can treat them as data and do something other than execute them. It's hard to do much with an imperative form other than execute it. A scene graph or a game level file is a declarative form; you can view it from different angles and positions. The programs that plan actions for NPCs look at a game level and decide what to do. CAD files are declarative. Spreadsheets are mostly declarative.
The usual problem with declarative forms is lack of expressive power. If you need to express something the declarative form can't handle, it's tempting to bolt on some kind of imperative gimmick. This is how we ended up with Javascript.
So maybe it's my age showing, but I was taught that imperative was using explicit variables to control the "looping" (e.g. for with an index a la C style programming) whereas using "higher order functions" was not imperative. And I tend to agree with that. So I disagree that map and reduce are imperative because they don't explicitly control how the looping is done.
Can anyone cite where map and reduce are imperative? Must be some new-fangled text book that I'm not aware of ;)
And I get that someone could impose on me to cite references that map and reduce are not imperative. Point taken and I'm thinking that I got this from SICP in the first place so I'm looking it up now. Will report back if I find anything.
EDIT: First quote from SICP:
"In contrast to functional programming, programming that makes extensive use of assignment is known as imperative programming. In addition to raising complications about computational models, programs written in imperative style are susceptible to bugs that cannot occur in functionalprograms."
That said, that's mostly a specificity of Javascript than a property of the map operation. There's no reason you can't have a map on an FRP that truly declares a relationship between entities.
But the difference between imperative programming and declarative programming is not drawn by "ordering something done" (even if the article didn't define things precisely enough to prevent confusion on this point). It's basically a level-of-abstraction/level-of-detail thing. Saying "double each number in this list" is significantly different than saying "follow this step-by-step algorithm to double each number in the list".
The boundaries can get fuzzy; arguments can be made about where to draw the lines. But your approach lumps everything on one side of the line, and therefore becomes incapable of saying anything very useful.
Well, in JS, sure, but what about if you could do:
a = 13
b = map(function(x){ return x; }, [1, 2, 8, a])
print b
> [1, 2, 8, 13]
a = 26
print b
> [1, 2, 8, 26]
(While I'm representing it as a sequential program, the idea would be to plug "a" and "b" to some IO channels.)What I'm trying to say is that the concept of map is not necessarily imperative, just JS's version.
Well how would you write these snippets the right way then?with the language of your choice, so it fits the declaritive way a 100% ?
If you wanted to do something like that in a declarative way, though, consider a spreadsheet with an intelligent evaluator. The spreadsheet is a declaration of a dependency relationship. When a number is changed, the numbers depending upon it change. It's not always just a recalculation, either. There are spreadsheets that let you work backwards (change a total, watch the inputs change), and cloud-based spreadsheets that sync (one of YCombinator's companies, Fivetran, has one).
Spreadsheets also suffer from imperative creep. People try to use Excel spreadsheets for iterative work, which gets away from the declarative design.
That is, the base generalization here is invalid.
Further, there are plenty of things where imperative just makes sense. It is why we have plenty of imperatives in every day usage. I mean, sure, you could tell your kids "I want a clean room." Likely, they will look at you and wonder, if that is what you want, why don't you clean it. :)
So, sure, if there is a nice clean concise declarative way to specify something, do so. However, I think it is a fool's errand to think that can be the universal case. Even in an ideal sense. It is why you don't hear people trying to drop imperatives from daily life. (Or... do you?)
func [1,2,3,4,5] => [2,4,6,8,10] //Calculation inferred by compiler.
console.log (func [6,7,8,9,10]) //=> [12,14,16,18,20]
double xs => [xs[0] * 2, ..., xs[xs.length - 1] * 2]
map f xs => [f(xs[0]), ..., f(xs[xs.length - 1])]
sum xs => xs[0] + ... + xs[xs.length - 1]
foldl f z xs => f(f(..., f(z, xs[0])), xs[xs.length - 1])
foldr f z xs => f(xs[0], f(..., f(xs[xs.length - 1], z)))I'm playing around with a tool for building touch gestures visually, and I have some problems that look a bit like that (want to infer a function from some examples) but I don't yet know how.
If you are talking paths generated from touch gestures there is some research on that topic.
here is such psuedo code foo(x) { if (x <= 5) { x * 2 } else { x } } foo1(x) { if (x <= 6) { x * 2 } else { x+1 } } foo1(x) { if (x <= 7) { x * 2 } else { x+2 } }