Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fundamental Difference Between Variable Definition and Function Definition

Tags:

racket

I am learning Racket via the book Realm of Racket. I noticed that defining a variable and defining a function is done via the same keyword - define. This got me thinking about what the fundamental difference is between a function that takes no arguments and simply returns the value 5, and a variable that returns the value 5. i.e.:

(define fiveVar 5)

(define (fiveFun)
  5)

(Apologies if camel-case is not the right naming convention - just picked up the book and don't know any Lisp).

At first glance, it seems to me that I am simply giving a name to the value 5 in both cases. In fact, I can even re-attach the name fiveFun: (set fiveFun 6), just as I can with a variable.

So again, it seems to me that there is no difference between defining a variable and defining a function. In both cases, I am giving a name to a data type. In the case of the function data type, it can be applied, whereas a number cannot.

like image 742
Steven L. Avatar asked Dec 18 '25 13:12

Steven L.


1 Answers

Pretty much, yeah. In fact, the (define (f x ...) ...) notation is just a convenient abbreviation in Scheme and other Lisp-1s, which is in contrast to Common Lisp and other Lisp-2s which separate functions and values into separate namespaces.

In Racket and Scheme, when you write this:

(define (f x) (+ x 1))

It’s actually just a shorthand notation for writing this:

(define f (lambda (x) (+ x 1)))

The lambda form is a special form that produces a procedure value, but the binding that is created, in this case f, is no different from the binding for an ordinary value. Since procedures are just values like any other, this makes using so-called “higher-order” functions—functions that accept functions as arguments—easy to write and use. For example, filter takes a function as its first argument:

> (filter even? '(1 2 3 4))
'(2 4)

Now, with that in mind, the function definition you wrote in your question is actually this, without the shorthand:

(define fiveFun (lambda () 5))

So then, consider the difference between these two things:

(define fiveVar 5)
(define fiveFun (lambda () 5))

Well, one of them is a number, 5, and the other is a function with no arguments which, when applied, produces 5. Some languages, mostly purely functional ones, do not even have a concept of a function that takes no arguments, so there is no meaningful way to express fiveFun in those languages. In Racket, however, there are a couple reasons you might want such a function:

  1. You can use a no-argument function to “delay” evaluation until another time, or even run it multiple times, which is useful if running the function has side effects. For example:

    > (define x (begin (displayln "Hello!") 5))
    Hello!
    > x
    5
    > x
    5
    
    > (define f (lambda () (displayln "Hello!") 5))
    > f
    #<procedure:f>
    > (f)
    Hello!
    5
    > (f)
    Hello!
    5
    
  2. Also, a value might take a long time to produce, and you might want to defer its evaluation until it’s actually needed. You could use a zero-argument function to run the computation “lazily”, when the function is actually used.

As a small piece of terminology, a zero-argument function is often called a “thunk”, which you might see in some places in the Racket documentation. There’s even a form called thunk from racket/function which is a small shorthand for a zero-argument lambda.

like image 115
Alexis King Avatar answered Dec 21 '25 04:12

Alexis King



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!