3

On Wikipedia, the article Programming paradigms defines

  • declarative as a paradigm in which the programmer merely declares properties of the desired result, but not how to compute it;
  • imperative as a paradigm in which the programmer instructs the machine how to change its state.

Is assignment declarative or imperative?

For instance,

  • x = 3 in Python;
  • PUT / HTTP/1.1\r\nHost: domain.org\r\n\r\n{"x": 3} in HTTP;
  • UPDATE relation SET value = 3 WHERE key = 'x'; in SQL.
2
  • 1
    +1. Case in point: Would SSA be considered declarative or imperative?
    – rwong
    Commented Jul 22, 2021 at 2:31
  • 3
    Assignment is imperative because it is an act. "X = 3" is not necessarily an assignment though, it can also be a declaration, an informative statement. What it is depends on the context. Commented Jul 22, 2021 at 10:43

5 Answers 5

9

Declarative vs imperative programming cannot always be distinguished on a syntactical level. To a large part, this is more about different programming styles: a declarative program will mostly describe the structure of the problem, whereas an imperative program will describe the steps of an algorithm that solves the problem. There is an interesting aspect we must get out of the way first, though: mutability: imperative programming inherently implies that data is modified. In declarative programming, we more often have descriptions of data flows without actual mutability. But while imperative/mutable vs declarative/immutable are correlated, this is not a hard and fast rule to distinguish them.

In your x = 3 Python example, we can't tell what programming paradigm is being used, because that would depend on the wider context. Python as a whole is biased towards imperative programming. It is very statement-oriented. Every statement does something, usually by modifying some state. But an assignment x = 3 could be interpreted as a declarative statement of fact: “in this context, x = 3”, or as an imperative command: “modify the x variable to have the new value 3”.

HTTP is a protocol, and I don't think it makes sense to apply programming language categories to this protocol.

You SQL example is interesting: the UPDATE statement modifies the state of the database, but SQL is widely considered to be a declarative language. In that SQL statement, you don't describe how to update the database. You don't look up indices, you don't perform table scans, you don't acquire locks, you don't update indices. The SQL statement just expresses a problem in this notation for relational algebra. I think this illustrates nicely that you can't always clearly separate these two concepts. A sequence of SQL statements might be imperative (especially when part of a stored procedure), but individual statements are a declarative description of database operations.

10
  • By context, you mean the whole program? So if the whole program is x = 3; y = 2; z = 1 then it is imperative as the execution order (control) is specified, but if the whole program is just x = 3 then it is declarative as the execution order is not specified?
    – Géry Ogam
    Commented Jul 21, 2021 at 9:58
  • @Maggyero By context, I mean how the variable is used. There might be data dependencies or orderings even in purely declarative languages. But if a variable is reassigned, that would be an indication that the program follows a more imperative style.
    – amon
    Commented Jul 21, 2021 at 10:10
  • Interesting, so assignment is declarative but reassignment is imperative. So the Python program x = 1; y = 2; z = 3 is declarative but the Python program x = 1; x = 2 is imperative.
    – Géry Ogam
    Commented Jul 21, 2021 at 10:21
  • @Maggyero - think of it more as of a spectrum, rather than an either-or kind of thing. Also, you are looking too finely, x = 1; y = 2; z = 3 is too small and too contrived a program for the distinction to be meaningful. I don't think it makes sense to characterize the generalized concept of assignment itself. Rather, think of it like this: if you have a complex data structure, if client code initializes it though a constructor then that is more declarative then if there was no ctor, and the client itself had a number of lines that directly manipulate the data structure to a desired state. Commented Jul 21, 2021 at 11:49
  • @Maggyero - in other words, it's about how much the calling code has to (or even can) fiddle with the internals of the thing that it is calling. So x = 3 can really only be meaningfully called declarative in comparison to the internals of the python implementation (you don't manipulate the low-level internal data representations directly). The other two are declarative in the sense that they are high-level descriptions that encode what you want to happen, and then there's a whole bunch of code at the other end that manipulates all kinds of internal structures to fulfill your request. Commented Jul 21, 2021 at 11:49
5

In a declarative approach, you declare facts, for example that gravity g is 9.80665 m/s2 or the number or wheels x is 3.

Many programming languages express this with some kind of declaration or assignment statement:

let g = 9.80665   // swift
double x = 3;       // c++, java
spaceship(red).  % prolog

In the declarative paradigm you tell the rules and let the system apply these rules to find the result. The rules and facts can be declared in any sequence.

In the imperative paradigm, you have to tell how to use these facts to come to the result; the sequence of operations matters. You may use assignment for other purpose than defining facts: every time you use an assignment that depends on the sequence of statements, and every time you use an assignment to change the previous value of a variable, it is no longer declarative.

Conclusion: assignment can be declarative or imperative, depending on how it is used.

33
  • Can you be clearer what it means to "declare facts" rather than state "how facts are used"? What even is a "fact" in this context? Even when "declaring", the order of operations must matter when outputs of any stage form the input to another.
    – Steve
    Commented Jul 22, 2021 at 12:08
  • @Steve I used “facts” as here i.e. a basic statement that we assume true, without need for any operation/inference/deduction. I avoided a too theoretical debate about whether freefall_speed is g*t*t/2. %prolog is a fact or is already a rule ;-)
    – Christophe
    Commented Jul 22, 2021 at 13:00
  • I'm confused because "facts" are not assumed to be true, rather they are articles of knowledge that at some point have been proven true. The word for things that are assumed without need for proof (even in principle) is an axiom or a tenet, not a "fact". I dare say there is a style of language often used in explaining "declarative programming" that doesn't correspond to English as we know it - your own link offers no definition, and uses the word "fact" in ways it immediately condemns as hand-wavy and vague! (1/2)
    – Steve
    Commented Jul 22, 2021 at 13:26
  • The real point anyway is how do "facts", "rules", "axioms" or whatever, differ from what exists in "imperative" languages (which are the supposed opposite of declarative languages)? As I explain in my own answer, no modern compiler of an imperative language translates the source code slavishly - all of them treat the source code as an exemplary implementation of the desired output or operation, rather than as something that must be followed to the letter. (2/2)
    – Steve
    Commented Jul 22, 2021 at 13:32
  • 1
    @Maggyero I’m not a master of functional programming, but some experimentations with Ocaml suggest that yes. As stated in an exchange with steve above, many functional programming language, which should work according to declarative paradigm, are nowadays multiparadigm.
    – Christophe
    Commented Jul 24, 2021 at 11:35
2

Imperative vs Declarative Programming

Many of the answers here (and the question itself for that matter) fall into the old trap of the "what vs how" metaphor. I think it's the wrong way to look at the question. It doesn't tell us if x = 3 is declarative or imperative. It doesn't tell us about a = b + c...

So let’s take this simple code a = b + c as a basis and view the statement in a few different languages to get the idea:

When we write a = b + c in an imperative language, like C, we are assigning the current value of b + c to the variable a and nothing more. We aren’t making any fundamental statement about what a is. Rather, we are simply executing a step in a process.

When we write a = b + c in a declarative language we are asserting a relationship between a, b and c such that it is always the case that a is the sum of the other two. It’s not a step in a process, it’s an invariant, a guarantee, a declaration of truth.

In essence, declarative code doesn't "do anything," it merely states facts. Imperative code is required otherwise nothing would ever get done. Any language allows you to write in either style.

So when examining code to determine its style don't think "what vs how." Instead ask yourself, "does this code express a fact that is always true regardless of the state of the system, or does it update the state of the system?

11
  • Thanks Daniel. It is funny that you answer here because I read your blog article yesterday. So you define the declarative/imperative distinction in terms of permanent relation/transient relation. But cannot facts be changed during computation in a declarative language? Competing definitions are JacquesB’s immutable state/mutable state, Steve’s higher-level language/machine language, and Christophe’s separated logic and control/intertwined logic and control.
    – Géry Ogam
    Commented Jul 24, 2021 at 12:56
  • 1
    @Maggyero Christophe's definition and mine are the same. Logic, by its nature, states facts that are true regardless of state. IE, logic describes invariants. And JacquesB's notion is a sub-type of mine and Christophe's. As I mentioned in my article, stateless execution is necessarily declarative as well. Only Steve's definition is at odds with the rest and it's because IMO, he's looking at the historical definition of the word, not its current usage.
    – Daniel T.
    Commented Jul 24, 2021 at 13:08
  • @DanielT. I also think that we have the same definition, and you have a nice way to express it. Indeed, in my examples, I have carefully avoided a=b+c, since this would be an assignment in an imperative language (deriving in a controlled manner new facts from existing facts) , and would be a rule in purely declarative languages (i.e. making a general statement regardless of b and c if those are not yet known, or regardless any 2 of the 3 variables with a decent inference engine). And the general rule has in many languages a very different syntax, not using assignment, which was the topic.
    – Christophe
    Commented Jul 24, 2021 at 14:15
  • 1
    "It’s not a step in a process, it’s an invariant, a guarantee, a declaration of truth." - but what is the difference between the two conceptions? I can take any plainly imperative code, and insist that it isn't actually a computational step, but a declaration of truth and a relationship that must hold. Yet the whole point of expressing the "relationship" is to define a necessary step of computation. Is there an example of relations that don't involved steps? Why would a programmer even specify a relationship, if it didn't imply a step in the computation?
    – Steve
    Commented Jul 24, 2021 at 18:52
  • 1
    The first paragraph of section 1.1 ‘Declarative vs. Imperative Languages’ of Frank Silbermann’s doctoral thesis A Denotational Semantics Approach to Functional and Logic Programming gives the following definitions based on Kowalski’s famous analysis ‘algorithm = logic + control’: a declarative language has explicit logic and implicit control; an imperative language has implicit logic and explicit control.
    – Géry Ogam
    Commented Jul 25, 2021 at 19:24
2

First we need to clarify the distinction between "declarative" and "imperative".

Be aware that there is no single canonical definition of "declarative" in computer science, so there is a certain level of subjective opinion and a lot of grey area. But a reasonable definition is:

In a declarative language the code is a specification of the desired end result. In an imperative language the code specifies a sequence of operations executed over time (hopefully resulting in the desired end result).

It follows from this that imperative languages have a notion of mutable state. Each operation change mutable state or have some other side effect (like generating output).

Declarative languages describes a single state and does not have any explicit notion of sequential execution or mutable state.

This brings us to assignment. Assignment can really have two meanings. In an imperative language like Python, assignment sets a mutable variable to a particular state. A variable can have multiple states over time (hence the name).

Declarative and functional languages can also have assignment, but these are more like aliasing. It binds a name to a particular value or expression in a given context. But the binding does not change over time. Assignment in declarative or functional languages are therefore more often called declarations or bindings rather then assignments.

This distinction may be subtle, but consider that in an imperative language like Python, a name like 'foo' might refer to different variables in different scopes and each variable may change value over time. In a declarative language, the same name may refer to different binding in different scopes, but a binding never change over time.

For example CSS is a declarative language and CSS variables are assigned a value, but they cannot change at runtime (which means the name "variable" is really a misnomer - it is a constant declaration rather than a variable).

Update in SQL is imperative since they change state. Base tables are sometimes called "relation variables" (or "relvars") to indicate they are mutable over time. In contrast, the query syntax in SQL is declarative.

The imperative/declarative distinction does not apply to protocols like HTTP. Here we would instead talk about side effects or not. PUT has a side effect.

29
  • Thanks! In other words, as amon said, reassignment is imperative. So in SQL UPDATE is imperative, while INSERT is declarative, right?
    – Géry Ogam
    Commented Jul 21, 2021 at 10:44
  • INSERT is also imperative since it changes state. SELECT is declarative.
    – JacquesB
    Commented Jul 21, 2021 at 10:47
  • Well contrary to UPDATE, INSERT does not really change state, it creates state.
    – Géry Ogam
    Commented Jul 21, 2021 at 11:19
  • 1
    I agree for INSERT. ‘CSS variables are assigned a value, but they cannot change value over time’ Yes and I think that the fundamental reason is that a CSS style sheet represents a single final state, not multiple intermediary states.
    – Géry Ogam
    Commented Jul 21, 2021 at 18:00
  • 1
    Isn’t declarative vs. imperative more about intent? If you insert a new key/value pair, you change a table, but you could nevertheless just declare in that table some new knowledge. You could even update a table with a value for key that had none (null in SQL semantic) and still be in a declarative paradigm. In a purely declarative language you could also declare new facts that change the internal state of the execution, without being accused of imperatism ;-) (1/2)
    – Christophe
    Commented Jul 22, 2021 at 14:19
0

In my view, the imperative/declarative distinction does not exist in the way most people seem to describe it.

What does exist is what nowadays would be recognised as the absence or presence of an "optimising compiler".

SQL is usually considered the canonical example of a "declarative" language. It was conceived during an era when assembly languages still reigned - where every CPU instruction was painstakingly specified.

By contrast to assembly, SQL bears no relation to specifying CPU instructions, and instead the basic work is done by employing a small set of array-oriented operators, and the database engine can fulfil an SQL query using a choice of multiple algorithms and strategies that bear no obvious relation to what the programmer wrote (and yet are provably equivalent).

In this context decades ago, practitioners knew what they meant by the imperative/declarative distinction, even if they don't seem to have bequeathed us with a sound explanation of it.

They meant the fundamental difference between assembly language where you specify every single CPU instruction, and something as comparatively wild as SQL where you write a few lines manipulating an abstract representation of data, and the compiler sort of works out the CPU instructions for itself.

Today however, assembly has long fallen by the wayside, and compilers for all mainstream languages can produce CPU instructions that don't relate in any simple way to the source code. Many languages run in their own VMs. Effectively all mainstream languages are now "declarative" to some significant degree.

SQL remains unique in the mainstream for the sheer breadth of optimisations available to the "compiler" (the database engine), since the entire technology was designed precisely for this purpose from the outset, and has had decades to mature. But it is only a question of degree in this respect, not of fundamental difference.

That said, the question of whether "assignment is declarative or imperative" simply falls away as meaningless, since all languages have some concept of assignment.

12
  • This is an interesting answer. But isn’t the presence of an optimizing compiler an obsolete criteria since the emergence of just in time compiling and bytecode, that would allow to compile anything when sufficient information is known, not to speak about transpilers? Haven’t many functional languages that use declarative paradigm (e.g Ocaml, f#) also their optimizing compiler? Even Prolog a declarative logic programming language has an optimizing compiler.
    – Christophe
    Commented Jul 22, 2021 at 14:07
  • I just see that JacquesB has solid arguments about SQL being an imperative language
    – Christophe
    Commented Jul 22, 2021 at 14:09
  • @Christophe, my point is precisely that the "optimising compiler" is what people a generation ago meant by "declarative". Effectively everything is now declarative, because declarative (in accordance with my argument) means that source code statements don't translate directly into a fixed set of machine instructions, but instead are manipulated by an optimising compiler. The usefulness of this distinction thus no longer exists, because the ideas and features which were specific to declarative languages decades ago, are actually now characteristic of every mainstream language.
    – Steve
    Commented Jul 22, 2021 at 15:07
  • Also, I wouldn't say @JaquesB has "solid arguments" about SQL being imperative. He more or less just baldly asserts that it is the case, and appears not to realise that the "query syntax" (which I gather means a select statement) is also capable of reassigning values to names - otherwise every time you created a calculated column, you'd have to give the output column a different name than the input column, which often isn't desired at all.
    – Steve
    Commented Jul 22, 2021 at 15:15
  • I think this is a good answer regarding the history of the word "declarative" in the software engineering context. However, the meaning of words can change over time. I think this particular word's definition has changed quite a bit over the last 47 years.
    – Daniel T.
    Commented Jul 24, 2021 at 12:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.