But suppose I have a list and I need its length not once, but twice or
more inside my function. If i'm not supposed to use a variable to
store the length of the list, how am I supposed to reuse the result of
that computation (the length determining)?
(setq len (length mylist))
(concatenate 'list (subseq 0 (/ len 2)) (subseq (+ (/ len 2) 1) len))
How am i supposed to achieve this without using the len variable? Or
am I incorrectly understanding what functional programming is all
about? (I come from a c++ background so imperative programming is all
I know for now) I could call length each time where needed, but that
is obviously very inefficient and unnecessary.
Many thanks,
Gabriel
(let* ((len (length mylist))
(half-len (/ len 2)))
(concatenate 'list (subseq 0 half-len) (subseq (+ half-len 1) len)))
...or something like that. Binding local variables is not considered as
using side effects.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
I'm sorry to disappoint you, but Lisp is not really a functional programming
language.
But it supports functional programming to some extent, ok...
Z> So from what I understand, side-effects are not desirable when writing
Z> functional code. This means setq and variables in general should be
Z> avoided.
Those are recommendations for programmers coming from C-like languages, as
they tend to over-use setq and variables.
Variables are actually not different from function parameters. You might
want to use them when you want name some value.
C programmers often want to name every temporary value, as in C they usually
operate with shorter expressions. (As C doesn't allow to embed control
structure into the expression.)
So there is this recommendation -- write longer expressions without naming
temporaries.
But variables are not related to side-effects, as long as you do not assign
them via SETQ.
Making local variables via LET or LET* is fine. You can even name temporary
variables this way for no real reason, just because variable name might help
reading. (It is up to a personal taste.)
SETQ, indeed, has side-effects. But if you SETQ to a local variable
(introduced via LET), those side-effects are well-localized and are not a
big problem.
Sometimes using SETQ or, maybe, macros like PUSH or INCF makes code shorter.
It makes code "less functional", but if it has no effect on program in
general (if it affects only local variables) and you understand semantics
very well -- then why not?
But C programmers tend to over-use SETQ to initialize temporary variables
with it, so it is plain ugly.
Z> But suppose I have a list and I need its length not once, but twice or
Z> more inside my function.
That's a legit reason to introduce a variable.
Z> (setq len (length mylist))
Z> (concatenate 'list (subseq 0 (/ len 2)) (subseq (+ (/ len 2) 1) len))
Use LET, not SETQ. As a general rule, LET is much, much better than SETQ.
SETQ is for a last resort.
Z> I could call length each time where needed, but that
Z> is obviously very inefficient and unnecessary.
In theory, good compiler could optimize that away, but I would not bet on
it.
> I'm new to functional programming, just barely getting the hang of it,
> I hope.
> So from what I understand, side-effects are not desirable when writing
> functional code. This means setq and variables in general should be
> avoided.
Not quite. It is the DEFINITION of functional programming that it is
done without side-effects. So it's not that SETQ "should" be avoided,
it's that by definition if you use SETQ you're not doing functional
programming. Also, using variables (created with LET or LAMBDA or other
binding forms) is perfectly fine. You just can't change the value of a
variable after it has been created.
> But suppose I have a list and I need its length not once, but twice or
> more inside my function. If i'm not supposed to use a variable to
> store the length of the list, how am I supposed to reuse the result of
> that computation (the length determining)?
>
> (setq len (length mylist))
> (concatenate 'list (subseq 0 (/ len 2)) (subseq (+ (/ len 2) 1) len))
>
> How am i supposed to achieve this without using the len variable? Or
> am I incorrectly understanding what functional programming is all
> about? (I come from a c++ background so imperative programming is all
> I know for now) I could call length each time where needed, but that
> is obviously very inefficient and unnecessary.
Exactly right. C++ has poisoned your mind to conflate binding and
assignment. (If you don't understand what that means, read
http://www.flownet.com/ron/specials.pdf) So it's perfectly fine to BIND
a variable to store an intermediate result, e.g.:
(let ((len (length mylist)))
...
)
You just can't reassign LEN with SETQ. You can do this though:
(let ((len ...))
...
(let ((len ...))
...
This may appear to be equivalent to:
(let ((len ...))
...
(setq len ...)
...
)
but it isn't. Figuring out why it isn't is left as an exercise. HINT:
consider what happens if you create closures as part of your
computations.
rg
God, you are worse than I thought. Could you just go away or shut up for
ten years and learn something before speaking here again?
In Lisp, every form returns a value. Case closed. Thank you for playing.
kt
No but it is considered evil and taxed heavily by Mr. Graham.
But to the OP: Lisp is a multi-paradigm language designed for real work,
damn the religious wars. Functional is a great productivity thing so use
it where you can, bind variables where that is faster.
If you are in fact curious about pure functional programming go check
out one of those, and their proponents will help you with needing the
length twice. i honestly do not know what they do about that.
kt
CL-USER> (defun foo ()
(values))
FOO
CL-USER> (foo)
; No value
CL-USER>
In functional programming, for example in Haskell, if you bind l to be
a list then l can't change, also the functions are pure, that is
to the same input correspond the same output, so when you compute the
length of l the compiler can memorize the result and optimize the
code.
So functional programming take advantage of first you can't modify the
binding of a variable and only use pure functions (non pure require
a monad, a difficul concept to grasp for a C programmer.
I can always count on some newsgroup genius to point out the one
non-exception exception. It is a non-exception because there /is/ a
value if you are looking for one, namely nil. "; No value" is just a
choice of the author of your repl. My repl's author simply shows a new
prompt, which gets the edge for elegance in my book.
kt
(multiple-value-call (lambda (x) x) (values))
Is definitely an error.
Helmut
> * His kennyness [2010-04-28 21:12+0200] writes:
>
> > Mariano Montone wrote:
> >> His kennyness escribió:
Sigh. I hate it when smug lisp weenies get things wrong. Makes it hard
to clean up the mess.
Lisp is not considered functional because every form returns a value.
First, it is clearly not true that every form returns a value. You
don't even need to introduce the ambiguous case of (values). There are
many forms in CL that don't return anything, notably GO, THROW, and
ERROR.
The reason Lisp is considered a functional language is that it has
lexical closures as first-class data structures. That's really all you
need to do functional programming. It also has two additional features
that are generally considered part and parcel of functional programming:
linked lists and conditional expressions. But these don'y actually add
and real functionality since they can be built out of closures.
Everything else is a red herring.
rg
That's strictly true, but a functional data structures library can
sure be handy!
http://common-lisp.net/project/fset/
-- Scott
What does GO return? And, importantly, WHERE does it return?
Hk> God, you are worse than I thought. Could you just go away or shut up
Hk> for ten years and learn something before speaking here again?
Aha, come back when you learn about non-local control transfers.
A bit of problem here is that most modern programming languages have them.
Python and JavaScript always had them.
They were added relatively recently into C#, PHP, Delphi.
There are proposals to add them into Java and C++.
Should we consider all these languages functional? I don't think so. That
would be totally meaningless.
R> That's really all you need to do functional programming.
Well, ok, you can do functional programming in all those languages I've
listed above.
But another question is -- do you want to? Is that a preferred style?
using local variable is fine. In lisp, it's like this:
(let (var1 var2 ...)
(setq var1 val1)
(setq var2 val2)
...
body
)
the key to remember about functional programing, is that the behavior
of your function should only depends on input, and that usually means
just the argument it receives. Using local variable is still
functional programing, as long as those variables don't leak, such as
global variables, and they shouldn't keep a state (such as in OOP).
However, the quest to avoid using variables is of theoretical interest
as well as a interesting programing program of a given language.
there are, academic language that does not have variables at all.
(though, off hand i don't know any. Web search for the word
“cominator” and you'll find examples.)
without a pure functional lang such as Haskell, avoiding variable is
difficult or impossible.
Even Haskell, for practical reasons, have local variables, just that
you can't change a variable's value. (effectively, they are local
“constants”)
In a less strict functional lang OCaml/F#, you can have variables that
changes value.
Lisp, as a functional lang, is even less strict than the above ones.
Also, it is IMPOSSIBLE to write any non-trivial function without using
variables, mutable or not.
In Mathematica, which i've coded for over 10 years, am among the
world's say top 100 expert, i often avoid using ANY variables at all.
It is not difficult to do. Basically, any function is all just a
sequence of application of functions. Though, the code get complicated
for average programers to understand, but simple if you understand the
function application paradigm.
Mathematica can be considered as a lisp variant. However, lisps
(Common Lisp, Scheme Lisp, Emacs Lisp, Arc lisp, NewLisp, all can not
avoid variables. I'm pretty sure this includes Clojure lisp, Qi lisp,
or, that these two still would cost far more effort or un-natural code
to avoid vars than Mathematica)
Part of the reason why it is impossible to avoid using variables in
lisp,
i'v detailed in the past, in these essays:
• The Concepts and Confusions of Prefix, Infix, Postfix and Fully
Nested Notations
http://xahlee.org/UnixResource_dir/writ/notations.html
• Fundamental Problems of Lisp
http://xahlee.org/UnixResource_dir/writ/lisp_problems.html
In fact, trying code code in no-variable functional style is part of
the reason i discovered these lisp problems.
Look for the sections that discuss the nesting problem. The nesting
syntax is part of the problem, but there are other reasons that i
haven't discussed in the above essays. Maybe i'll write a detailed
essay about this topic in the future, but now just from the top of my
head ... (was going to write perhaps a one sentence description of
what i thought are the other reasons other than the nesting syntax,
because the problem cannot theoretically be just syntax... but am
tired, and i think the issue is more complex then i can think now...
will need to think about this another time)
Xah
∑ http://xahlee.org/
☄
> Lisp is not considered functional because every form returns a value.
> First, it is clearly not true that every form returns a value. You
> don't even need to introduce the ambiguous case of (values). There are
> many forms in CL that don't return anything, notably GO, THROW, and
> ERROR.
Even this is a red herring. The important thing (not about
being-a-functional-language but about being-a-Lisp) is that it's an
*expression language*: There are no statements in Lisp. What that
means is that if you can say x, you can say, for instance, (let ((y x)
...) freely (and this is true even for things like GO: Y will never
actually be bound to anything because control will have been
transferred, but it is syntactically a valid expression. What people
actually mean when they say "everything returns a value" (which is
false) is "everything is an expression".
This is quite distinct from C, say: I can say "if (x) then; else;", but
that's a *statement* not an expression, so I can't say "int foo = (if
(x) then; else;);" for instnace: indeed there is a whole construct in C
just for this: I have to say "int foo = (x? then : else);".
What this buys you is syntactic composabilty: you can freely compose
expressions with the result being another expression. In the above
case, I can take x and make (let ((y x)) ...), and I can quite happily
then have (let ((z (let ((y x)) ...))) ...), and so on.
And what *that* gets you turns out to be macros. People often wonder
if you could have a language "like C but with macros" and assume that
the thing that makes this difficult is syntax: it's not, it's the lack
of syntactic composability. It's not very difficult to write a front
end which has an s-expression syntax but the semantics of C:
(define-function (foo int) ((a int))
(if (bar a)
(return (+ a 1))
(return (- 1 a))))
and now you can use macros easily. Or you think you can until you find
that things like this are not valid:
(define-function (foo int) ((a int))
(return (+ a
(if (bar a) 1 -1))))
So you now need a whole bunch of idiosyncratic
this-is-a-statement/this-is-an-expression rules which are just endless
pain and make writing robust macros very hard.
Note in the above that I grounded everything on some undefined "x"
which was an expression. Expressions can have parts which are not
expressions: for instance in (let ((x 1)) ...) ((x 1)) is not an
expression, and neither is "FOR" in (loop for x from 1 below n ...).
> R> The reason Lisp is considered a functional language is that it has
> R> lexical closures as first-class data structures.
>
> A bit of problem here is that most modern programming languages have them.
> Python and JavaScript always had them.
Actually, Python didn't get them until version 2.2:
http://www.python.org/dev/peps/pep-0227/
> They were added relatively recently into C#, PHP, Delphi.
> There are proposals to add them into Java and C++.
>
> Should we consider all these languages functional? I don't think so. That
> would be totally meaningless.
I disagree. It depends on how you define functional language. There
are two reasonable definitions:
1. A functional language is one that supports programming in a
functional style. On this definition, being a functional language is
not a dichotomy, it's a continuum, and all of these languages are to
some extent functional.
2. A functional language is one that forces you to program in a
functional style. On this definition, none of these languages are
functional, including Lisp.
I personally prefer definition 1, though I don't really care to quibble
over terminology. But there is no reasonable way that you can say that
Lisp is definitively a functional language while Python and Javascript
are definitively not. The best you can do is argue that Lisp's support
for functional programming is better than the others.
> R> That's really all you need to do functional programming.
>
> Well, ok, you can do functional programming in all those languages I've
> listed above.
> But another question is -- do you want to? Is that a preferred style?
Sure. Why not? I write functional code in Python all the time. It's
annoying, but no more so than any of the zillion other annoyances that
coders have to face on a daily basis. And Python has some built-in
features (notably iterators and list comprehensions) that make
functional programming easier than in Lisp.
rg
> I disagree. It depends on how you define functional language. There
> are two reasonable definitions:
>
> 1. A functional language is one that supports programming in a
> functional style. On this definition, being a functional language is
> not a dichotomy, it's a continuum, and all of these languages are to
> some extent functional.
>
> I personally prefer definition 1
Yup. The only definition that /should/ stand is: functional = supports
functions as first class citizens, as per Christopher Strachey's
definition. And support for any paradigm is indeed a continuum.
I also find particularly annoying when people assume that functional =
purely functional. That's the kind of vocabulary fuzziness that leads to
comments I've heard too often like:
<C guy>:
Lisp? Ah yeah, that's this weird functional language with lots of parens...
<Haskell guy>:
Lisp? Ah yeah, that's this weird imperative language with lots of parens...
--
Resistance is futile. You will be jazzimilated.
Scientific site: http://www.lrde.epita.fr/~didier
Music (Jazz) site: http://www.didierverna.com
> coders have to face on a daily basis. And Python has some built-in
> features (notably iterators and list comprehensions) that make
> functional programming easier than in Lisp.
I don't know Python that well. Could you please give an example? I
am curious whether those constructs give something extra, and if so,
whether one could implement them in CL.
Thanks,
Tamas
Even if they're implementable, there's a lot of value in providing
things by default. For example, you can implement the condition system
with simpler features, but having a single, specified condition system
available with no extra effort is nicer.
Zach
> On Thu, 29 Apr 2010 06:55:24 -0700, RG wrote:
>
> > coders have to face on a daily basis. And Python has some built-in
> > features (notably iterators and list comprehensions) that make
> > functional programming easier than in Lisp.
>
> I don't know Python that well. Could you please give an example?
STFW.
> I am curious whether those constructs give something extra, and if so,
> whether one could implement them in CL.
Of course you can. And people have. STFW. Or you can start here:
http://rondam.blogspot.com/2008/02/joy-of-iterators.html
rg
I don't disagree with you, but my question was not about establishing
which language is nicer. I just want to see if I can learn something
useful from another language, and possibly adapt it to CL and play around
with it.
Cheers,
Tamas
Cool, nice exception to the exception to the exclusion. But it is a
compiler-macro that complains, so it is not that (values) does not
return nil if asked (it better, it's in the spec) it's that
multiple-value-call knows how to count.
kt
> Helmut Eller wrote:
> > * His kennyness [2010-04-28 21:12+0200] writes:
> >
> >> Mariano Montone wrote:
> >>> His kennyness escribió:
You know, Kenny, the arrogant Lisp weenie act would go over a lot better
if you actually knew what you're talking about.
? (defun foo () (values))
FOO
? (defun baz () (multiple-value-call (lambda (x) x) (foo)))
BAZ
? (baz)
> Error: Too few arguments in call to #<Compiled-function (:INTERNAL BAZ) (Non-Global) #x302000D4D68F>:
rg
>>>>> "Xah" == Xah Lee <xah...@gmail.com> writes:
Xah> using local variable is fine. In lisp, it's like this:
Xah> (let (var1 var2 ...)
Xah> (setq var1 val1)
Xah> (setq var2 val2)
Xah> ...
Xah> body
Xah> )
You can do this easier and more succintly in the following way:
(let ((var1 val1) (var2 val2) ...)
...
body)
'Andreas
--
ceterum censeo redmondinem esse delendam.
R> 1. A functional language is one that supports programming in a
R> functional style. On this definition, being a functional language is
R> not a dichotomy, it's a continuum, and all of these languages are to
R> some extent functional.
R> 2. A functional language is one that forces you to program in a
R> functional style. On this definition, none of these languages are
R> functional, including Lisp.
3. A functional language is one where functional style is preferred and
natural.
R> I personally prefer definition 1,
I strongly disagree with such definition, it doesn't make sense from
linguistical point of view.
"xxx-al language" should mean what language is about, not what it supports.
E.g. "logical language" is _mostly about_ logics, "imperative language" is
about imperative stuff etc.
If you want to say "language supports functional style/paradigm" -- say so.
And then you can talk about scale of that support.
But when you say "xxx is functional programming language", then it is
supposed to characterize primary programming style, otherwise it is totally
meaningless.
R> But there is
R> no reasonable way that you can say that Lisp is definitively a
R> functional language while Python and Javascript are definitively not.
Well, my point is that CL, Python and JavaScript support FP approximately to
same extent, and none of them is functional, as functional programming is
not a preferred programming style.
R> Sure. Why not? I write functional code in Python all the time. It's
R> annoying, but no more so than any of the zillion other annoyances that
R> coders have to face on a daily basis. And Python has some built-in
R> features (notably iterators and list comprehensions) that make
R> functional programming easier than in Lisp.
Aren't iterators inherently non-functional?
Usually people who mention functional programming want to juxtapose it to
imperative programming.
If your definition of functional programming language includes CL and JS,
that's not juxtaposition at all.
So your definition destroys meaning. Term "functional language" becomes
unusable, but maybe if it pleases lispers so they know that they still use
functional programming language it's ok?
It doesn't need to be 100% pure functional, but I think it should have at
least some support for immutable data structures to qualify as functional.
DV> <Haskell guy>:
DV> Lisp? Ah yeah, that's this weird imperative language with lots of
DV> parens...
Well, I guess I'm more like a Haskell guy on this, except that I'm
programming mostly in CL. But I know a bit of Haskell, and I see that there
is an abyss between them.
There is no primary programming style in Lisp. So we can only talk about
the programming styles it supports, not the ones it is "about".
And Lisp does support functional programming.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
> If you want to say "language supports functional style/paradigm" --
> say so. And then you can talk about scale of that support.
>
> But when you say "xxx is functional programming language", then it is
> supposed to characterize primary programming style, otherwise it is
> totally meaningless.
Where exactly can I find a legislation on what being functional is
"supposed to" mean ? In fact, this is exactly the idea I'm fighting
against. There is a silent and widespread assumption here, that a
language needs to have a /primary/ programming style, which is probably
to main source of misunderstanding and trolls about paradigms. Under
that assumption, you may be right, but then Lisp is nothing. It's not an
imperative language, not an OO one, it's not a meta-one, it's not a
functional one^C^C^C
Language[1] and thought go hand in hand. Your language reflects your
thoughts and vice-versa. When I claim that Lisp is a functional
language, I'm also advocating, from language to thought, the idea that
being multi-paradigm is important and shouldn't be regarded as a weird
corner-case. I'm trying to bend the language in order to make people
realize that there are silent assumptions that should be reconsidered.
> Well, my point is that CL, Python and JavaScript support FP
> approximately to same extent, and none of them is functional, as
> functional programming is not a preferred programming style.
That's because there is no preferred programming style, and my point is
that there shouldn't be any. Never.
> R> And Python has some built-in features (notably iterators and list
> R> comprehensions) that make functional programming easier than in
> R> Lisp.
> Aren't iterators inherently non-functional?
Mathematics are purely functional right? That's what everybody says.
Well, I find $\sum_{i=1}^{n} i$ pretty imperative and full of side
effects... unless iterators are in fact pretty functional :-)
The interesting question is: does an algorithm embed its own preferred
way of being expressed (i.e. its own paradigm). I believe so, and that's
why I use the "no primary paradigm" as my primary paradigm ;-). It seems
to me that even a mathematician would understand
(loop for i from 1 to 10 sum i)
better than
(labels ((sigma (a i) (if (> i 10) a (sigma (+ a i) (1+ i)))))
(sigma 0 1))
let alone abstracting true sigma, term and step functions.
Footnotes:
[1] not in the programming sense here, in the "natural language" one
> You know, Kenny, the arrogant Lisp weenie act would go over a lot better
> if you actually knew what you're talking about.
>
> ? (defun foo () (values))
> FOO
> ? (defun baz () (multiple-value-call (lambda (x) x) (foo)))
> BAZ
> ? (baz)
>> Error:
THis is not really any different to
(defun foo (x y)
(cons x y))
(foo 1)