unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Parameters
@ 2008-02-04 13:51 Sebastian Tennant
  2008-02-04 14:28 ` Parameters Ludovic Courtès
  0 siblings, 1 reply; 7+ messages in thread
From: Sebastian Tennant @ 2008-02-04 13:51 UTC (permalink / raw)
  To: guile-user

Hi list,

No doubt something of a newbie question this...

This simple procedure behaves as expected, i.e., it provides the sum of
a list of numbers:

 (define add
   (lambda (l)
     (if (null? l)
         0
       (+ (add (cdr l)) (car l)))))

whereas this procedure results in a stack overflow:

 (define add
   (lambda l
     (if (null? l)
         0
       (+ (add (cdr l)) (car l)))))

the only difference being the designation of the formal parameter of the
anonymous procedure; l or (l).

Why is this?

Regards,

Sebastian





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Parameters
  2008-02-04 13:51 Parameters Sebastian Tennant
@ 2008-02-04 14:28 ` Ludovic Courtès
  2008-02-04 15:05   ` Parameters Sebastian Tennant
  0 siblings, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2008-02-04 14:28 UTC (permalink / raw)
  To: guile-user

Hi,

Sebastian Tennant <sebyte@smolny.plus.com> writes:

> This simple procedure behaves as expected, i.e., it provides the sum of
> a list of numbers:
>
>  (define add
>    (lambda (l)
>      (if (null? l)
>          0
>        (+ (add (cdr l)) (car l)))))
>
> whereas this procedure results in a stack overflow:
>
>  (define add
>    (lambda l
>      (if (null? l)
>          0
>        (+ (add (cdr l)) (car l)))))
>
> the only difference being the designation of the formal parameter of the
> anonymous procedure; l or (l).

When creating a procedure with `(lambda args body...)', then, no matter
how it is invoked, ARGS will always be bound to the *list* of arguments
that were passed to the procedure.  Consequently, such procedures can be
passed any numbers of arguments.

Conversely, `(lambda (x) body...)' is a one-argument procedure.  When it
is invoked, X is bound to its argument.

Thus, in your case, the first `add' would be used with a single
argument, e.g., `(add '(1 2 3 4))', while the second would be used with
an indefinite number of arguments, e.g., `(add 1 2 3 4)'.

Note that none of your procedures is tail-recursive, so they consume
stack space proportional to the length of L, which can lead to a stack
overflow for large lists.  A tail-recursive definition would be:

  (define add
    (lambda (l)
      (let loop ((l l)
                 (result 0))
        (if (null? l)
            result
            (loop (cdr l) (+ result (car l)))))))

Or you can just use `+'.  :-)

Hope this helps,
Ludovic.





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Parameters
  2008-02-04 14:28 ` Parameters Ludovic Courtès
@ 2008-02-04 15:05   ` Sebastian Tennant
  2008-02-04 15:29     ` Parameters Chusslove Illich
  2008-02-04 15:47     ` Parameters Ludovic Courtès
  0 siblings, 2 replies; 7+ messages in thread
From: Sebastian Tennant @ 2008-02-04 15:05 UTC (permalink / raw)
  To: guile-user

Quoth ludo@gnu.org (Ludovic Courtès):
> Sebastian Tennant <sebyte@smolny.plus.com> writes:
>> This simple procedure behaves as expected, i.e., it provides the sum of
>> a list of numbers:
>>
>>  (define add
>>    (lambda (l)
>>      (if (null? l)
>>          0
>>        (+ (add (cdr l)) (car l)))))
>>
>> whereas this procedure results in a stack overflow:
>>
>>  (define add
>>    (lambda l
>>      (if (null? l)
>>          0
>>        (+ (add (cdr l)) (car l)))))
>>
>> the only difference being the designation of the formal parameter of the
>> anonymous procedure; l or (l).
>
> When creating a procedure with `(lambda args body...)', then, no matter
> how it is invoked, ARGS will always be bound to the *list* of arguments
> that were passed to the procedure.  Consequently, such procedures can be
> passed any numbers of arguments.
>
> Conversely, `(lambda (x) body...)' is a one-argument procedure.  When it
> is invoked, X is bound to its argument.
>
> Thus, in your case, the first `add' would be used with a single
> argument, e.g., `(add '(1 2 3 4))', while the second would be used with
> an indefinite number of arguments, e.g., `(add 1 2 3 4)'.

Understood... up to a point.  However, I don't understand why calling
the first procedure like this:

 (add '(1 2 3 4))

and calling the second procedure like this:

 (add 1 2 3 4)

doesn't result in 'l' having the same value; '(1 2 3 4), in each case?

To put it another way, I would expect both procedures to work provided
they are called with (a) suitable argument(s).

Why does the second procedure fail regardless of how it is called?

> Note that none of your procedures is tail-recursive, so they consume
> stack space proportional to the length of L, which can lead to a stack
> overflow for large lists.  A tail-recursive definition would be:
>
>   (define add
>     (lambda (l)
>       (let loop ((l l)
>                  (result 0))
>         (if (null? l)
>             result
>             (loop (cdr l) (+ result (car l)))))))

Noted.

Sebastian





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Parameters
  2008-02-04 15:05   ` Parameters Sebastian Tennant
@ 2008-02-04 15:29     ` Chusslove Illich
  2008-02-04 15:45       ` Parameters Sebastian Tennant
  2008-02-04 15:47     ` Parameters Ludovic Courtès
  1 sibling, 1 reply; 7+ messages in thread
From: Chusslove Illich @ 2008-02-04 15:29 UTC (permalink / raw)
  To: guile-user

[-- Attachment #1: Type: text/plain, Size: 312 bytes --]

> [: Sebastian Tennant :]
> Why does the second procedure fail regardless of how it is called?

Because the recursive call in it is of the first type, not corresponding to
the base call. You would need to use apply, i.e.

  (+ (apply add (cdr l)) (car l))

-- 
Chusslove Illich (Часлав Илић)

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Parameters
  2008-02-04 15:29     ` Parameters Chusslove Illich
@ 2008-02-04 15:45       ` Sebastian Tennant
  0 siblings, 0 replies; 7+ messages in thread
From: Sebastian Tennant @ 2008-02-04 15:45 UTC (permalink / raw)
  To: guile-user

Quoth Chusslove Illich <caslav.ilic@gmx.net>:
>> [: Sebastian Tennant :]
>> Why does the second procedure fail regardless of how it is called?
>
> Because the recursive call in it is of the first type, not corresponding to
> the base call.

Ah, of course... 

> You would need to use apply, i.e.
>
>   (+ (apply add (cdr l)) (car l))

Indeed.

Many thanks to all.






^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Parameters
  2008-02-04 15:05   ` Parameters Sebastian Tennant
  2008-02-04 15:29     ` Parameters Chusslove Illich
@ 2008-02-04 15:47     ` Ludovic Courtès
  2008-02-04 17:22       ` Parameters Sebastian Tennant
  1 sibling, 1 reply; 7+ messages in thread
From: Ludovic Courtès @ 2008-02-04 15:47 UTC (permalink / raw)
  To: guile-user

Hi,

Sebastian Tennant <sebyte@smolny.plus.com> writes:

> Understood... up to a point.  However, I don't understand why calling
> the first procedure like this:
>
>  (add '(1 2 3 4))
>
> and calling the second procedure like this:
>
>  (add 1 2 3 4)
>
> doesn't result in 'l' having the same value; '(1 2 3 4), in each case?

L should have the same value in both cases, i.e.,

  ((lambda l l) 1 2 3 4)
  => (1 2 3 4)

  ((lambda (l) l) '(1 2 3 4))
  => (1 2 3 4)

> Why does the second procedure fail regardless of how it is called?

Ah, I hadn't noticed it: your second procedure should read
"(apply add (cdr l))" instead of "(add (cdr l))".

>>   (define add
>>     (lambda (l)
>>       (let loop ((l l)
>>                  (result 0))
>>         (if (null? l)
>>             result
>>             (loop (cdr l) (+ result (car l)))))))
>
> Noted.

Or, more elegantly:

  (use-modules (srfi srfi-1))

  (define add
    (lambda (l)
      (fold + 0 l)))

Cheers,
Ludovic.





^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Parameters
  2008-02-04 15:47     ` Parameters Ludovic Courtès
@ 2008-02-04 17:22       ` Sebastian Tennant
  0 siblings, 0 replies; 7+ messages in thread
From: Sebastian Tennant @ 2008-02-04 17:22 UTC (permalink / raw)
  To: guile-user

Quoth ludo@gnu.org (Ludovic Courtès):
>>>   (define add
>>>     (lambda (l)
>>>       (let loop ((l l)
>>>                  (result 0))
>>>         (if (null? l)
>>>             result
>>>             (loop (cdr l) (+ result (car l)))))))
>>
>> Noted.
>
> Or, more elegantly:
>
>   (use-modules (srfi srfi-1))
>
>   (define add
>     (lambda (l)
>       (fold + 0 l)))

Wow!  More elegantly indeed!

Many thanks Ludovic.






^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2008-02-04 17:22 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-02-04 13:51 Parameters Sebastian Tennant
2008-02-04 14:28 ` Parameters Ludovic Courtès
2008-02-04 15:05   ` Parameters Sebastian Tennant
2008-02-04 15:29     ` Parameters Chusslove Illich
2008-02-04 15:45       ` Parameters Sebastian Tennant
2008-02-04 15:47     ` Parameters Ludovic Courtès
2008-02-04 17:22       ` Parameters Sebastian Tennant

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).