
Clojure is Imperative - momo-reina
http://www.lispcast.com/clojure-is-imperative
======
lmm
"imperative" does not seem like a good/valuable characterization. Yes, the
"do" form is imperative. That's why you're not supposed to use it much,
perhaps only for the top-level structure of your program, the part that acts
as an interpreter to connect the pure program to the outside world. _When you
express business logic in a language like clojure_ , that expression of the
business logic is not usually "a sequence of commands executed in order". It
usually looks more like "an expression tree and rules for how nodes are
evaluated".

The downside of a simple, transparent language like lisp is that it exposes
you to the dangerous parts of the underlying. An opaque abstraction (e.g.
expressing database operations as a tree of operations some of which define
transaction boundaries, rather than as a series of SQL commands some of which
open or close transactions) is vital for transforming dangerous things into
safe things. Ultimately a program looks like an expression of business-level
logic and then an opaque layer that pretends the computer is actually a
machine that understands your business. Lisp forces you to provide more of
that opacity yourself, whereas a language that already has a vocabulary for
drawing distinctions between different kinds of thing provides you some of the
scaffolding you need (the tradeoff being of course that it will be less
specialized to your particular circumstances).

------
lmkg
Just because Clojure has the DO form (or that Common Lisp has the PROG form)
doesn't mean that the language _is_ imperative. It means that it _allows_
imperative programming.

This is like saying that a language with casts doesn't have a type system. No,
it has a type system, it just also has an escape hatch that lets you break out
from the type system when you need to. Lisps' functional-ness is generally the
same sort of thing: They are designed primarily around function-oriented
programming, but provide straightforward escape hatches into imperative
programming. Common Lisp tends more towards being multi-paradigm than Clojure
(i.e. provides more imperative accommodations), but both have strict
evaluation, which the author seems to equate with imperative-ness.

The author spends more time talking about a small core and non-leaky
abstractions than about imperative-ness. On these points, I totally agree and
think it's a well-written article. I don't exactly see the connection with
being imperative, and I think it's a shame that the title will draw attention
away from those points. The thing that I really like about working in Clojure
is how the abstractions are built with care: I feel like whenever I just use
the base building blocks, they fit together seamlessly and edge cases usually
don't come up.

~~~
current_call
Are you saying that languages aren't imperative or declarative but programs
are?

~~~
lmkg
Eh... somewhat.

I do think that it's meaningful to describe a _program_ as being imperative or
declarative or object-oriented or functional or strongly-typed or whatever,
and that determination can be separate from the language that the program was
written in (up to a point). See also, "writing COBOL in any language."

But just because those descriptions apply to programs, that doesn't mean that
they are inapplicable to languages. At the least, those languages can be
described in terms what types of programs they _allow_ and what types they
_encourage_ , and how strongly. What programs they allow is a question mostly
of features, but what they encourage is more complicated question that often
involves the culture and ecosystem as much as the syntax or standard library.

E.g., Haskell encourages functional, strongly-typed programs. It's possible to
write an imperative, weakly-typed program by using a lot of monads and passing
data between modules as serialized strings. But that program is massively
cutting against the grain, so to speak, so it's still meaningful to describe
Haskell as functional and strongly-typed. Common Lisp functions naturally fit
together into a functional program, but it's nowhere near as difficult or
counter-intuitive to write an imperative program, so Common Lisp can lay
better claim to being multi-paradigm.

I do think that programs are the primary things that are described as
imperative or whatever. Languages are better-described by the programs they
encourage rather than the features they have. For example, JavaScript and Ruby
have all the features common to (dynamically-typed) functional languages
(closures, lambdas, functions-as-values, etc), but that's not the type of
program that is easiest to write in either language. That's why most people
don't describe JavaScript as a functional language, even though there are
certainly functional programs written in it.

------
fnordsensei
From what I've read, the exact definitions of imperative and declarative vary
a lot. The most useful rule of thumb I've come across is to consider
imperative to be concerned with HOW something is to be done, while declarative
concerns primarily WHAT is supposed to be done.

SQL is usually classified as declarative in that you're not telling the
database how to retrieve the top ten entries from a table - you're merely
informing it that you are interested in those entries.

It struck me at some point that this definition must be relative to the level
of abstraction you're operating at. For example, when using (go …) blocks, I'm
declaring that I want the code contained within the block to be processed
asynchronously, but I'm not describing how that is to be done. Perhaps a
callback might be described as being "more imperative" since it contains more
implementation details?

So, am I correct in thinking that this discussion would hinge on what you
consider to be "concrete" and not? That something executes in sequence is
hardly enough to decide whether it is to be considered declarative or
imperative in nature.

~~~
Igglyboo
Declarative is what we'd like programming to be in the future. At the highest
level we could say "Computer, make me a first person shooter set in WW2" and
receive a ready to play game from that.

~~~
dragonwriter
"Make me a..." is clearly imperative.

------
kyllo
_You would only want to execute an expression and throw away its value for its
side effects._

Useful for IO as there's normally nothing I want to pass the value of a
println expression to, evaluating already prints it to stdout. Also useful for
mutation, but doing this in Clojure feels wrong since the immutable data
structures are among the language's greatest strengths.

~~~
SixSigma
Do you not care if your output succeeded ?

~~~
kyllo
It honestly hadn't occurred to me that printing to stdout could fail, or that
I'd need to check its return value to ensure it was successful. Can you think
of an situation where that might happen? And if so, why doesn't println throw
an exception?

On the other hand, a side effect like writing to a file or inserting to a
database can easily fail, but those of course throw exceptions.

~~~
klibertp
Output redirected to a file and file being already closed, for one. Or anyway,
stdout being closed midway due to many other possible reasons: this is
(probably) why printf returns a number of bytes written or -1, for example:
[http://www.cplusplus.com/reference/cstdio/printf/](http://www.cplusplus.com/reference/cstdio/printf/)

------
dragonwriter
"Imperative" isn't really a binary feature of programming languages, the
imperative-declarative axes is more a continuous axes of variation describing
code (which can be applied to languages, as well, as a general
characterization of code written in the language.)

And, while its certainly possible to write very imperative code in clojure (or
even Haskell!), idiomatic clojure is more declarative and less imperative than
most popular languages, so, I think, on balance, "is imperative" is not a
useful description.

That being said, in most "declarative" languages, there still remains the risk
of being bitten by issues related to order of operations and structure of the
code that aren't apparent if you view the code as _purely_ declarative
statements of intent rather than as to some degree imperative instructions.
And if you call anything that presents that issue as "imperative", virtually
_all_ programming languages are "imperative".

~~~
dllthomas
_' That being said, in most "declarative" languages, there still remains the
risk of being bitten by issues related to order of operations and structure of
the code that aren't apparent if you view the code as purely declarative
statements of intent rather than as to some degree imperative instructions.
And if you call anything that presents that issue as "imperative", virtually
all programming languages are "imperative".'_

Yeah, particularly painful is massaging something purportedly "declarative" in
order to get particular operational semantics out of it.

I sometimes dream of a future language that will have a denotational layer
separated from an operational one, with each playing off the other. In the
limit, you can implement things entirely in the denotational and the compiler
will fill in the operational details - but when that breaks down you have the
option to specify _how_ it works in a way that's _built for_ specifying how it
works (and, ideally, then _checked against_ your declarative specification).
Ideally here, you can express arbitrarily strong or weak _constraints_ upon
both and the compiler will say "done", or "I don't see how", or "I can prove
that's impossible."

------
StavrosK
I just started learning Clojure, so I don't really understand this article
very well. Is Clojure significantly different from other LISPs (e.g. Racket)?

~~~
astine
The author of this article is straining logic to argue that Clojure is not a
functional language. It's true that Clojure is not a _purely_ functional
language, but most people should already know that. Unlike Haskell, Clojure
allows side affects in code. It exposes the underlying Java platform
'transparently' which is definitely imperative. In that respect it's not too
much different from other Lisps which allow side affects and generally have an
FFI of some sort for working with imperative code written in other languages.

Unlike other Lisps, though, Clojure's core semantics are very strongly
functional. All of Clojure's core data structures and types are immutable and
to have mutable state you need to resort to reference types with special
semantics to have mutable state. It would be uncomfortable to write Clojure
code in a primarily imperative fashion. Common Lisp by contrast has no problem
with imperative code or mutable state.

~~~
StavrosK
Ah, thanks. It does look pretty functional from my limited experience so far,
plus I think these debates are very academic. You can write purely functional
Python if you want, it's just going to be neither easy nor practical.

------
aminit
Which language is not imperative then? The only program writtten in non-
imperative language I can think of would return random values (of random type,
also not known to mankind, including total destruction and creation of life)
and crashed avery second function call.

~~~
debacle
prolog, for one.

~~~
aminit
Prolog functions are a little more advanced 'if' statements. Flow of the
execution is always the same. Data may be processed in a different order, but
the rest is purely imperative. Logic never changes.

~~~
kyllo
You're implying that the opposite of "imperative" is "nondeterministic."
That's incorrect.

Prolog is _declarative_ as opposed to imperative. User source code declares
rules/constraints, and the Prolog compiler performs a search algorithm to
arrive at a solution that satisfies the constraints.

~~~
aminit
I exaggerated a little with this randomness.

Let me explain:

Given the same input Prolog program and imperative (Pascal?) one will give the
same results. Because Prolog is imperative.

Non-imparative languages give estimated results (actually I don't know any of
these). Why? Because for example data is too large to do simple things like
counting all elements. Thats non-imperative. Result is no longer based on what
is in the data space, but based on its characteristics. For example, you may
calculate a number of helium atoms in a cubic inch, but you will never do such
thing like counting them one by one (imperative way).

~~~
debacle
aminit I am not sure if you know what imperative means.

Imperative programs have a state or virtual machine that is manipulated by the
program. All programs, at heart, are imperative, but higher level constructs
allow for procedural or declarative programming which abstracts away the
lower-level imperative bits.

    
    
        // Imperative 
        if(foo == 'Tuesday') {
            print 'Taco Tuesday';
        }
        
        // Procedural
        if(isTacoTuesday(foo)) {
            writeTacoTuesday();
        }
       
        // Functional (but not monadic)
        (if (eq foo 'Tuesday') (print 'Taco Tuesday'))
    
        // Declarative
        taco_tuesday : foo == 'Tuesday'
        run : ( taco_tuesday -> write('Taco Tuesday') ; true )
        run;
    

No I have not had lunch yet.

~~~
kyllo
Nice.

I like this more for a functional idiom:

    
    
        case foo of 
            TUESDAY => "Taco Tuesday"
            | _ => "Not Taco Tuesday"
    

Or this:

    
    
        (cond (= foo TUESDAY)
            ("Taco Tuesday")
            ("Not Taco Tuesday"))
    

_All programs, at heart, are imperative_

Yes, but only because the underlying machine architecture is imperative,
right? If you had a chip that could evaluate pure functions with no mutable
state (like a Lisp Machine that used a purely functional dialect of Lisp) then
you could have programs with no underlying imperativeness.

But in a perhaps more relevant sense, in languages like Haskell or Prolog it
is possible to write a program with no imperative state manipulation happening
at the programmer's working level of abstraction.

Still, this really has nothing to do with determinism.

Also, I like SQL as an example of declarative programming.

    
    
        SELECT * FROM USERS
        WHERE JOIN_DATE = "20150106"
    

That is a declarative program; the SQL engine it's run on decides the
underlying imperative implementation of the solution at runtime. It is also
deterministic in that when it's run on the same database containing the same
data multiple times it will return the same result.

From what I know about Prolog, I understand it's similar in this regard.

~~~
qbrass
Look at your case statement. In most languages, if you swapped the order of
TUESDAY and _, you'd get different results.

An actual declarative language would choose TUESDAY over _ because it's the
most specific match, and not because it matched it first.

~~~
kyllo
Yes, good point, but this was not meant to be an example of declarative
paradigm, just functional paradigm. It's SML, which is not a particularly
declarative language. Haskell is a little bit more declarative but AFAIK its
pattern matching works the same way as SML.

------
mamcx
He explain his intention was another thing, and this post make it more clear,
I think:

[http://www.lispcast.com/two-kinds-of-
bootstrapping](http://www.lispcast.com/two-kinds-of-bootstrapping)

------
pwr22
He talks about how lisps are bootstrapped on a small core, and that is nice.
Reminded me that this is the approach that Perl 6 is trying to take (NQP is
the core) although on a larger and more complicated language

