简体   繁体   中英

what does Scheme `define` expression return?

I'm super new to this language and I came across a problem. Hope someone can help me out. Thanks.

Basically, I want to define a higher-order function make-adder . Here is my code.

(define (make-adder num)
  (define (foo x)
    (+ x num)))

(define adder (make-adder 5))

(adder 8) ;error points to here

But, I wonder why I got this error message.

# Error: expected
#     4
# but got
#     Traceback (most recent call last):
#       ...
#     SchemeError: str is not callable: foo

another interpreter I use also gave me an error but in a different way

Traceback (most recent call last)
0   (adder 8) [frame = Global]
Unable to pass parameters into the Symbol 'foo'

First, I wanted to know why I cannot use this code to define the make-adder higher order function like I always did in Python.

Second, I suppose that what a define procedure expression returns is a string? (because it said str foo is not callable ) But when I tried to test it out

scm> (define (foo x) (+ 1 x))
foo
scm> (string? (define (foo x) (+ 1 x)))
#f

So it turns out that it's not a string. I am so confused. What does foo stand for here? Is it a string or something else? Why I cannot call from it?

Hope anyone can help me out. Thank you.

Something that's not clear from the other answers is that (define...) is not an expression : it's a definition : a special bit of syntax which can occur in only certain special places allowed by the language. As such it simply doesn't have a value, because it can't occur anywhere where an expression is allowed.

From R6RS :

Definitions are not expressions, and cannot appear in all places where an expression can occur. Moreover, a definition has no value.

R5RS is not quite so clear on this, but says (this is chapter 5):

A Scheme program consists of a sequence of expressions, definitions, and syntax definitions. [...]

[...] Definitions are valid in some, but not all, contexts where expressions are allowed. They are valid only at the top level of a <program> and at the beginning of a <body>.

R7Rs says something similar.

What this means in particular is that definitions can't freely be used where expressions are expected: You can't say

(let ((x (define y 2)))
  ...)

for instance: that's simply not legal Scheme.

In particular you can't ever have a definition where its value (or lack of one) can mean anything. And one consequence of this is that I think your program is probably not legal Scheme.

It's not legal because the syntax for lambda is something like:

(lambda <formals> <body>)

Where <body> is

'a sequence of zero or more definitions followed by one or more expressions.'

(Text from R7RS , my emphasis.)

What this means is that the body of a lambda expression should have at least one expression:

  • (lambda ()) is not legal as it has no expressions;
  • (lambda () (define x 1)) is also illegal as it has one definition but still no expressions;
  • (lambda () (define x 1) x) is legal as it has one definition and one expression;
  • (lambda () 1) is also legal (no definitions, one expression).

Of course implementations may allow (and clearly sometimes do allow) expressions equivalent to (lambda ()) , but those expressions are not conforming Scheme.

This property of define in Scheme is very confusing to people who come from a traditional Lisp background (like me), where the nearest equivalent forms are expressions (there are still weird-non-expression things which can only go in some places, such as declarations, but function and variable definitions are not one of them).

It's a symbol.

#;1> (symbol? 'foo)
#t

How about:

(define (make-adder num)
  (define (foo x)
    (+ x num))
  foo)

You should return anonymous function ( lambda ):

(define (make-adder num)
  (lambda (x) (+ num x)))

(define adder (make-adder 5))
(adder 8)

Value returned by (define (foo x) (+ 1 x)) depends on development environment (for example, DrRacket returns nothing), because define has no return value. Your IDE probably returns symbol (try predicate symbol? ) or just function name.

It defines the foo , but doesn't return the foo . It looks like it returns its name , either as a string in one implementation, or a symbol , in another. This is probably implementation-dependent, or "undefined", in the language definition, the Report.

Scheme prides itself on being an expression-oriented language , meaning, every expression returns its value. It so happens that the value of the define expression is not the value of the entity (here, function foo ) it is defining, which might be a bit counter-intuitive.

So either return foo after defining it, as shown in the first answer, or just use the anonymous function ( lambda ) as the last expression as shown in the second answer, since the lambda form's value is the function itself (as opposed to its name, or being undefined at all).

In Scheme, functions are callable, but symbols or strings are, of course, not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM