From: Zadirion on
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.

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
From: Pascal Costanza on
On 28/04/2010 13:19, Zadirion wrote:
> 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.
>
> 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.

(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/
From: Captain Obvious on
Z> I'm new to functional programming, just barely getting the hang of it,
Z> I hope.

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.

From: RG on
In article
<3a86d701-1dc2-4c48-a1a2-1f48a95db7e1(a)k33g2000yqc.googlegroups.com>,
Zadirion <zadirion(a)gmail.com> wrote:

> 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
From: His kennyness on
Captain Obvious wrote:
> Z> I'm new to functional programming, just barely getting the hang of it,
> Z> I hope.
>
> I'm sorry to disappoint you, but Lisp is not really a functional
> programming language.
> But it supports functional programming to some extent, ok...

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