1. Functions are first-class values (including being able to
produce new functions dynamically).
2. The community that uses the language follows a style that
is predominantly functional.
Lisp certainly satisfies the former (although so do a lot of
modern languages to some degree). I guess I can't really speak with
authority about the latter.
The Lisp dialect with which I have most familiarity is Emacs Lisp. That
tends to be used in a rather non-functional way, but that's probably
inevitable given the context (i.e. the main purpose of Lisp code is to
modify the editing state in response to user commands).
From what I've seen of other Lisp usage, updating variables on each pass
through a loop seems more common than "reduce", but that isn't really a
statistically-sigificant sample.
Both Python and JavaScript started as primarily imperative languages.
Even if they both had function values from day one (which I
don't think they did, but I'm certainly not an expert on the
history of either language), I believe they were put in as minor
elements, not as essential elements.
I don't know about Python; JavaScript had functions as values from day
one. It's far more widely-used than "lambda" in Python, if only
to define prototype (class) members, i.e.:
MyClass.foo = function(arg) { ... }
or:
MyClass.prototype = {
foo : function(arg) { ... }
}
The more traditional syntax:
function foo(arg) {...}
only works for simple names.
But in spite of all that, I don't think that you can really call
JavaScript a functional language. It certainly doesn't satisfy your
second criterion above.
These kinds of QOI issues are a red herring, I think. For example,
I'm pretty sure early Lisp's didn't have tail call optimization, but
that doesn't change whether Lisp is a functional language. How can
the language be used, how is it expected to be used, how is it
actually used?
If you don't have tail-call optimisation, you don't really have much
choice but to use iteration instead of recursion. IOW, it can't be used,
isn't expected to be used, and won't be used in a functional style.
[I can agree with you about the "doesn't change whether Lisp is a
functional language", albeit from the opposite side.]
For me, "functional" means that "function" has the mathematical meaning,
rather than "procedure which returns a value". An "impure" functional
language is one with strict semantics (e.g. ML); anything more impure than
that is an imperative language, with or without functions-as-values.
gcc's __attribute__((pure)) indicates the mathematical notion of a
function: no side effects, result depends only on the arguments (albeit
with strict semantics, obviously). glibc uses this for e.g. strlen,
strcmp, etc, although not for the math functions as these are affected by
the fenv.h stuff and can set the exception flags. gcc will use this
attribute to eliminate unnecessary calls.