modeller
modeller

Reputation: 3850

What is the semantic difference between defining a name with and without parentheses?

(Though this is indeed simple question, I find sometimes it is common mistakes that I made when writing Scheme program as a beginner.)

I encountered some confusion about the define special form. A situation is like below:

(define num1
  2)

(define (num2)
  2)

I find it occurs quite often that I call num2 without the parentheses and program fails. I usually end up spending hours to find the cause.

By reading the r5rs, I realized that definition without parenthesis, e.g. num1, is a variable; while definition with parenthesis, e.g. num2, is a function without formal parameters.

However, I am still blurred about the difference between a "variable" and "function".

From a emacs lisp background, I can only relate above difference to similar idea as in emacs lisp:

In Emacs Lisp, a symbol can have a value attached to it just as it can have a function definition attached to it. [here]

Question: Is this a correct way of understanding the difference between enclosed and non-enclosed definitions in scheme?

Upvotes: 2

Views: 268

Answers (3)

Jatin
Jatin

Reputation: 31724

Even though @sepp2k has answered the question, I will make it more clearer with example:

1 ]=> (define foo1 (display 23))
23
;Value: foo1    

1 ]=> foo1

;Unspecified return value

Notice in the first one, foo1 is evaluated on the spot (hence it prints) and evaluated value is assigned to name foo1. It doesn't evaluate again and again

1 ]=> (define (foo2) (display 23))

;Value: foo2

1 ]=> foo2

;Value 11: #[compound-procedure 11 foo2]

1 ]=> (foo2)
23
;Unspecified return value

Just foo2 will return another procedure (which is (display 23)). Doing (foo2) actually evaluates it. And each time on being called, it re-evaluates again

1 ]=> (foo1)
;The object #!unspecific is not applicable.

foo1 is a name that refers a value. So Applying foo1 doesn't make sense as in this case that value is not a procedure.

So I hope things are clearer. In short, in your former case it is a name that refers to value returned by evaluating expression. In latter case, each time it is evaluated.

Upvotes: 1

sepp2k
sepp2k

Reputation: 370122

In Scheme, unlike Common Lisp and Emacs Lisp, there are no different namespaces for functions and other values. So the statement you quoted is not true for Scheme. In Scheme a symbol is associated with at most one value and that value may or may not be a function.

As to the difference between a non-function value and a nullary function returning that value: In your example the only difference is that, as you know, num2 must be applied to get the numeric value and num1 does not have to be and in fact can't be applied.

In general the difference between (define foo bar) and (define (foo) bar) is that the former evaluated bar right now and foo then refers to the value that bar has been evaluated to, whereas in the latter case bar is evaluated each time that (foo) is used. So if the expression foo is costly to calculate, that cost is paid when (and each time) you call the function, not at the definition. And, perhaps more importantly, if the expression has side effects (like, for example, printing something) those effects happen each time the function is called. Side effects are the primary reason you'd define a function without parameters.

Upvotes: 3

Alex Celeste
Alex Celeste

Reputation: 13370

There is no difference between a value and a function in Scheme. A function is just a value that can be used in a particular way - it can be called (as opposed to other kinds of value, such as numbers, which cannot be called, but can be e.g. added, which a function cannot).

The parentheses are just a syntactic shortcut - they're a faster, more readable (to experts) way of writing out the definition of the name as a variable containing a function:

(define (num)
  2)

;is exactly the same as

(define num
  (lambda () 2) )

The second of these should make it more visually obvious that the value being assigned to num is not a number.

If you wanted the function to take arguments, they would either go within the parentheses (after num, e.g. (num x y) in the first form, or within lambda's parentheses (e.g. (lambda (x y)... in the second.

Most tutorials for the total beginner actually don't introduce the first form for several exercises, in order to drive home the point that it isn't separate and doesn't really provide any true functionality on its own. It's just a shorthand to reduce the amount of repetition in your program's text.

In Scheme, all functions are values; variables hold any one value.

Upvotes: 4

Related Questions