[taos-glug] Re: Can "first class" procedures have more than oneargument?

  • From: Jonathan Bartlett <johnnyb@xxxxxxxxxx>
  • To: taos-glug@xxxxxxxxxxxxx
  • Date: Sun, 10 Aug 2003 17:55:59 -0700 (PDT)

Short answer - you can have as many arguments as you want.  In fact,
(define (myfunction x y z)
        ;Your Function Here
)

is shorthand for

(define myfunction (lambda (x y z)
        ;Your Function Here
))

There is no difference between the two, except that the first is a little
shorter.  When teaching people scheme, I always use the second to
demonstrate that defining a function (lambda) is an entirely separate
operation from assigning a name to a value (define).

Long answer - haven't had time to look at it closely.

More In-Depth Mathematical Answer -
Most useful anonymous functions only have one argument.  I don't know why
this is, but usually, when developing a system where you have anonymous
functions, most of them have one or two arguments.  Interestingly,
with closures, everything can be decomposed into functions of one
argument.

Traditional programming languages (i.e. - those not Lisp-based)
are from a mathematical concept called Turing Machines, where you
essentially had the following operations: Load a value, decode it based on
your current state, then, based on a state lookup table, you can do any of
the following: change state tables, move forward on the tape, move
backward on the tape, store a new value at the current position.
Therefore, most current languages focus on storing/retrieving values and
state changes.  Interstingly, using only those operations, you can define
any automated computation.

Another mathematical concept invented at the same time was called Lambda
Calculus.  It had exactly TWO constructs - creation of functions of one
argument, and calling functions of one argument.  It didn't have the
concept of even integers - it was all based on function creation and
execution, and these being all functions of one argument.  Interestingly,
the Lambda Calculus and Turing Machines can both solve the same classes of
problems.  The difference is, Turing Machines are easier to implement in
hardware, while Lambda Calculus is easier to write and modify programs
for.

Anyway, my guess is that, although modern languages have expanded beyond
their theoretical bases, much of it remains.  So, creation of anonymous
functions with one argument is pretty common with Scheme/Lisp programmers,
especially since that was originally the ONLY operation available.

In fact, I think Standard ML still only has functions of one argument,
although they have syntactic sugar to make it "look" like you have
functions of more than one argument.

Anyway, that was a lot longer than I intended it.

Jon

On Sun, 10 Aug 2003, Philip Ansteth wrote:

>
> I haven't found it stated one way or the other in SICP.   In Section
> 1.3.4, all the examples have one argument, i.e., every instance of
> "(lambda (x) . . ." has
> (x) only, not (x y) nor (x y z).
>
> Is it necessary to have only one?
>
> Here's why I'm asking.
>
> When I got to Exercise 1.44, I thought the "small number", dx,
> should be changeable in order to control the smoothing process.
> (I guessed, smaller dx, smoother curve).   Also, I thought the
> idea of a global variable was not so great.
>
> So, I tried to
> write 'smooth' first as
>     (define (smooth f dx) (lambda (x) . . .
> and later as
>     (define (smooth f) (lambda (x dx) . . .
>
> They both yield the same result;
> guile> (define (smooth f dx)
>        (lambda (x)
>        (/ (+ (f (- x dx)) (f x) (f (+ x dx))) 3)))
> guile> ((smooth cos .01) 1.0)
> 0.540284295941361
> guile>  (define (smooth f)
>       (lambda (x dx)
>        (/ (+ (f (- x dx)) (f x) (f (+ x dx))) 3)))
> guile> ((smooth cos) 1.0 .01)
> 0.540284295941361
>
> But when I tried to combine this with the "repeated" procedure as suggested
> in the exercise, I couldn't ever make it work.   I thought that, instead of
>      (((repeated smooth 2) cos) 1.0)
> I should be able to write
>      (((repeated smooth 2) cos .001) 1.0)
> or
>      (((repeated smooth 2) cos) 1.0 .001)
>
> But these didn't seem to work.
>
> So, I looked into the way I wrote 'repeated', which invoked, 'compose'
> which I wrote as follows:
>
> (define (compose f g)
>   (lambda (arg)
>     (f (g arg))))
>
> I gave up at this point because it looked as if, even if it were
> possible to add more arguments to f and g, it would disturb several working
> procedures.
>
> My pragmatic tendencies overcame my curiosity.
>
> So I had to return to using (define dx .0001), and dx thus become a global
> value.   Globals are usually considered to be a BAD THING.
>
> I reviewed the book to see if the authors had made any comment.   I didn't
> see any in Section 1.3.4.   They just say, " . . . along with the
> definition '(define dx 0.00001)'.   (This is statement is after they
> define 'deriv'.)
>
> (I think that, in this case, the authors could be accused of trying
> to conceal a defect in their presentation by "hiding it in plain sight."
> I'm learning from these guys, but they sure don't make it easy.)
>
> Clearly one could address my complaints by putting smooth, repeated, compose
> and dx into a block, which
> would remove need for a global variable (although it would be global
> to that block).   Furthermore, doing so would also hide the potentionally
> reusable 'compose' and 'repeated' procedures.
>
> I guess it's also possible to pass a compound object as the sole argument,
> and then have the procedure dissect it.
>
> Any thoughts, anybody?
>
>


Other related posts:

  • » [taos-glug] Re: Can "first class" procedures have more than oneargument?