Testing for the definedness of a variable in Scheme - scheme

Besides regular definitions like (define variable value) Scheme also allows for uninitialized definitions like (define variable), when the variable is bound to some value later on with the aid of set!.
Are there procedures allowing to test whether a symbol is a defined (not necessarily initialized) variable? Something like (defined? 'variable) which should return #t if variable is defined and #f otherwise?

The form (define var) is a non-standard extension.
According to R5RS define has one of the following forms:
(define <variable> <expression>)
(define (<variable> <formals>) <body>)
(define (<variable> . <formal>) <body>)
As far as I can tell the same goes for R6RS and R7RS.
Most likely (define foo) expands to (define foo the-undefined-value) in your implementation. This means you can use (if (eq? foo the-undefined-value) ...) to test whetherfoo` is has been initialized or not.
http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-8.html#%_idx_190
Update:
I checked R6RS and it says:
(define <variable> <unspecified>)
where <unspecified> is a side-effect-free expression returning
an unspecified value.
Consider
(define foo)
(define bar)
It is up to the implementor whether the same unspecified value that is bound to both foo and bar.
Try this program:
(define unspecified)
(define unspecified1)
(eq? unspecified unspecified1)
If the program evaluates to #t then you can write an initialized? predicate like this:
(define unspecified)
(define (initialized? x) (not (eq? x unspecified)))
(define test)
(initialized? test)
(set! test 42)
(initialized? test)

There is simple universal solution based on try-catch. I've tested it on Gambit v4.9.3.
(define (defined? var-symbol)
(with-exception-handler
(lambda (e) void)
(lambda () (not (eq? void (eval var-symbol))))
)
)
And here are the test cases:
> (defined? 'a)
#f
> (define a 123)
> (defined? 'a)
#t
> (defined? 'x)
#f
> (define x)
> (defined? 'x)
#t
> (defined? 'f)
#f
> (define (f a b) (+ a b))
> (defined? 'f)
#t
With this you can make conditional definitions:
(define (define-if-not var-symbol init)
(if (defined? var-symbol) void
(let ((value (init)))
(eval (list 'define var-symbol value))
value
)
)
)
The tests:
> (define a 'abc)
> (define (make-123) 123)
> (define-if-not 'a make-123)
#<procedure #2 void>
> (define-if-not 'b make-123)
123
> a
abc
> b
123
This variant of define-if-not has a caveat: if the value is a symbol, eval treats it as a reference. This is the short demo:
> (define value 123)
> (eval (list 'define 'a value))
> (define value 'abc)
> (eval (list 'define 'a value))
*** ERROR -- Unbound variable: abc
The following [nasty] solution overcomes it for Gambit:
(define define-if-not-private)
(define (define-if-not var-symbol init)
(if (defined? var-symbol) void
(let ((value (init)))
(set! define-if-not-private (lambda () value))
(eval (list 'define var-symbol '(define-if-not-private)))
value
)
)
)

According to the scheme report (standard) define is used to define a variable. (put it into existence) Using define without an expression like (define test) defines the variable to some value chosen by the implementation.
It can only be used once in the same scope for the same variable, thus set! is to alter an existing variable to something else, but it cannot remove it's existence.
There is nothing in the report to remove a binding or to check if a binding exists. Using a variable without it being defined will have undefined consquences.
Implementations may have feature beyond the report. These things are typically stuff the guts of a scheme system should know about and they may expose it to the user, but it is implementation dependent and not standard.

Related

How do I get a function's name as a symbol?

I am trying to define a function func->symbol that takes a function and returns its name as a symbol. For example:
(define (pythagoras a b)
(sqrt (+ (* a a) (* b b))))
;; #1
(func->symbol pythagoras) ; Returns: 'pythagoras
;; #2
(func->symbol (if #t pythagoras sqrt)) ; Returns: 'pythagoras
;; #3
(let ((f (if #t pythagoras sqrt)))
(func->symbol f)) ; Returns: 'pythagoras
;; #4
(let ((f (if #t pythagoras sqrt)))
(let ((g f))
(func->symbol g))) ; Returns: 'pythagoras
This is a follow-up question on How do I get a definition's name as a symbol? which only deals with case #1. For case #1, a simple macro def->symbol is sufficient:
(define-syntax def->symbol
(syntax-rules ()
((_ def) 'def)))
However, this macro definition does not pass cases #2, #3, #4. Is it possible to define func->symbol, or is Scheme not expressive enough for this?
In Racket, in many cases, you can get a function's name using object-name. But it is probably a bad idea to rely on this result for anything other than debugging.
Perhaps it's worth an answer which shows why this is not possible in any language with first-class functions.
I'll define what I mean by a language having first-class functions (there are varying definitions).
Functions can be passed as arguments to other functions, and returned as values from them.
Functions can be stored in variables and other data structures.
There are anonymous functions, or function literals.
Scheme clearly has first-class functions in this sense. Now consider this code:
(define a #f)
(define b #f)
(let ((f (lambda (x)
(+ x 1))))
(set! a f)
(set! b f))
Let's imagine there is a function-name function, which, given a function, returns its name. What should (function-name a) return?
Well, the answer is that there's simply no useful value it can return (in Racket, (object-name a) returns f, but that's clearly exposing implementation details which might be useful for debugging but would be very misleading as a return value for a function-name procedure.
This is why such a procedure can't exist in general in a language with first-class functions: the function which maps from names to values is many-to-one and thus has no inverse.
Here is an example of the sort of disgusting hack you could do to make this 'work' and also why it's horrible. The following is Racket-specific code:
(define-syntax define/naming
;; Define something in such a way that, if it's a procedure,
;; it gets the right name. This is a horrid hack.
(syntax-rules ()
[(_ (p arg ...) form ...)
(define (p arg ...) form ...)]
[(_ name val)
(define name (let ([p val])
(if (procedure? p)
(procedure-rename p 'name)
p)))]))
And now, given
(define/naming a
(let ([c 0])
(thunk
(begin0
c
(set! c (+ c 1))))))
(define/naming b a)
Then:
> (object-name a)
'a
> (object-name b)
'b
> (eqv? a b)
#f
> (a)
0
> (b)
1
> (a)
2
So a and b have the 'right' names, but because of that they are necessarily not the same object, which I think is semantically wrong: if I see (define a b) then I want (eqv? a b) to be true, I think. But a and b do capture the same lexical state, so that works, at least.

How to define a function in scm scheme that tests if its parameter is a macro?

For example, assuming 'match is a macro and 'car isn't:
> (macro? 'match)
#t
> (macro? 'car)
#f
Most schemes have no such macro? function. To distinguish normal functions from macros you can use procedure? from RnRS:
> (procedure? car)
#t
The problem is that you cannot name the keyword using Scheme syntax:
> (procedure? let)
Exception: invalid syntax let
So you have to use a symbol, like 'let, to refer to it. Given that eval needs to be able to tell keywords apart from other identifiers, you can try something like this:
(define keyword?
(lambda (symbol)
(guard (x [else (syntax-violation? x)])
(eval symbol)
#f)))
(keyword? 'let) ⇒ #t
(keyword? 'car) ⇒ #f
(keyword? 'does-not-exist) ⇒ #f
But this is certainly a rather big hammer. And this single-argument form of eval is a Chez Scheme extension, supplying (interaction-environment) as the default environment. It is also not completely safe because this hangs:
(let-syntax ([foo (lambda (x) (raise "oops"))])
(keyword? 'foo))

Standard way to handle quoted symbol in lisp macros in Scheme

For some code I was working I've needed to handle 'x inside macro. What is standard way of handling those values?
I have code like this:
(define (quoted-symbol? x)
(and (pair? x) (eq? (car x) 'quote) (symbol? (cadr x)) (null? (cddr x))))
(define-macro (test x)
(if (quoted-symbol? x)
`(begin
(display ',(cadr x))
(newline))))
(test 'hello) ;; 'hello will be expanded into list (quote hello)
Is this how this should be handled, or is just in macro you don't use quoted symbols?
NOTE: I'm not asking about hygienic macros (I'm asking about real lisp macros), so please no answers with hygienic macros.
EDIT:
My macro works correctly in Guile and BiwaScheme and in my own scheme like lisp in JavaScript. Here is better example:
(define-macro (test x)
(if (quoted-symbol? x)
`',(cadr x)))
(define (example arg)
(list arg (test 'world)))
(example 'hello)
the question was not about display, but about (cadr x).
EDIT2: You've asked so here you go, my macro:
(define-macro (--> expr . code)
"Helper macro that simplify calling methods on objects. It work with chaining
usage: (--> ($ \"body\")
(css \"color\" \"red\")
(on \"click\" (lambda () (print \"click\"))))
(--> document (querySelectorAll \"div\"))
(--> (fetch \"https://jcubic.pl\") (text) (match /<title>([^<]+)<\/title>/) 1)
(--> document (querySelectorAll \".cmd-prompt\") 0 \"innerText\")"
(let ((obj (gensym)))
`(let* ((,obj ,(if (and (symbol? expr) (not (null? (match /\./ (symbol->string expr)))))
`(.. ,expr)
`,expr)))
,#(map (lambda (code)
(let ((name (gensym))
(value (gensym)))
`(let* ((,name ,(cond ((quoted-symbol? code) (symbol->string (cadr code)))
((pair? code) (symbol->string (car code)))
(true code)))
(,value (. ,obj ,name)))
,(if (and (pair? code) (not (quoted-symbol? code)))
`(set! ,obj (,value ,#(cdr code)))
`(set! ,obj ,value)))))
code)
,obj)))
;; ---------------------------------------------------------------------------------------
(define (quoted-symbol? x)
"(quoted-symbol? code)
Helper function that test if value is quoted symbol. To be used in macros
that pass literal code that is transformed by parser.
usage:
(define-macro (test x)
(if (quoted-symbol? x)
`',(cadr x)))
(list 'hello (test 'world))"
(and (pair? x) (eq? (car x) 'quote) (symbol? (cadr x)) (null? (cddr x))))
the macro is used in my scheme like lisp in JavaScript, like the doc string suggest:
(--> document (querySelectorAll ".class") 0 "innerText")
I want to support:
(--> document (querySelectorAll ".class") 0 'innerText)
The code can be tested online at: https://jcubic.github.io/lips/ (You need to copy/paste the code since current version allow only method calls).
To get expansion you can use
(pprint (macroexpand (--> document (querySelector "x"))))
if it don't work (don't expand) it mean that macro is broken somehow.
dot is build in function that get property of an object and .. macro:
(define-macro (.. expr)
"(.. foo.bar.baz)
Macro that gets value from nested object where argument is comma separated symbol"
(if (not (symbol? expr))
expr
(let ((parts (split "." (symbol->string expr))))
(if (single parts)
expr
`(. ,(string->symbol (car parts)) ,#(cdr parts))))))
that can be use to get nested property like (.. document.body.innerHTML)
Scheme doesn't have "real lisp macros". Some implementations has something similar, but the forms have different names and uses. They are not portable at all.
The standard way of handling 'x is to handle it like an expression that gets evaluated in the expansion. Eg.
(define var 'x)
(test 'x)
(test var)
The two test forms should amount to the same even though the macro test gets (quote x) in the first and the symbol var in the second. At the time of the expansion var does not exist since the implementation can expand all the macros before starting.
You implementation of test will not work. Eg. the display might be run one or twice and then each time you call a procedure that uses it it will gfail since the expansion is the undefined value and it might not be fit for evaluation. eg.
(define (example arg)
(list arg (test 'w)))
When this is defined you get 'w or (quote w) printed with a newline and then the procedure it tries to store is:
(define (example arg)
(list arg #<undefined>))
Note that what constitutes the undefined value is chosen by the implementaion, but I know for sure that in many implementaions you cannot evaluate #<undefined>.

Getting #<undef> back when calling a scheme function

I have the following code in Scheme:
(define (processExpression lst)
(define operand (car lst))
(define operator1 (cadr lst))
(define operator2 (caddr lst))
(if (list? operand)
(begin
(display "Invalid syntax! Erroring out!")
(quit)
)
)
(if (and (number? operator1) (number? operator2))
;The list was of the form (operand c1 c2)
(simplePrefix lst)
)
(if (and (list? operator1) (number? operator2))
(begin
(list operand operator2 (processExpression operator1))
)
)
)
(define (simplePrefix lst)
(let (
(operand (car lst))
(operator1 (cadr lst))
(operator2 (caddr lst)))
(list operator1 operand operator2)
)
)
(display "Please enter a valid s-expression")
(let ((input (read)))
(display (simplePrefix input))
)
This code takes and s-expression and converts it based on some rules. One rule should be that the expression (+ (+ 1 2) 2) should return (+ 2 (1 + 2)).
Currently when I call this code with that expression I get back the result "#undef>" but I have no idea why. The code should call the simplePrefix function on the (+ 1 2) part of the expression and return (1 + 2) but it does not. Does anyone understand why?
The value of
(if condition
something)
is undefined if condition is false, because there's no else part in the if form. In the R5RS version of Scheme, this is stated (emphasis added):
4.1.5 Conditionals
syntax: (if <test> <consequent> <alternate>)
syntax: (if <test> <consequent>)
Syntax: <Test>, <consequent>, and <alternate> may be arbitrary expressions.
Semantics: An if expression is evaluated as follows: first, <test> is evaluated. If it yields a true value (see section
6.3.1), then <consequent> is evaluated and its value(s) is(are) returned. Otherwise <alternate> is evaluated and its value(s)
is(are) returned. If <test> yields a false value and no
<alternate> is specified, then the result of the expression is
unspecified.
(if (> 3 2) 'yes 'no) ===> yes
(if (> 2 3) 'yes 'no) ===> no
(if (> 3 2)
(- 3 2)
(+ 3 2)) ===> 1
Some Scheme-like languages (e.g., Racket) will actually warn you if you try this:
Welcome to Racket v6.1.
> (if #t
(display "hello"))
stdin::1: if: missing an "else" expression
in: (if #t (display "hello"))
context...:
In Common Lisp, the else part is optional, and defined to be nil if not provided:
This is SBCL 1.2.4.58-96f645d, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
* (if t
(print 'hello))
HELLO
HELLO
* (if nil
(print 'hello))
NIL
The expression
(if condition result)
is not equivalent to
if condition
return result
in other languages.
It doesn't return a value, it has a value.
If the condition is false, that value is undefined.
If it is followed by other expressions in a sequence, the value is ignored and the following expressions are evaluated.
The result of evaluating a function application is the value of the last expression in the function's body
(define (foo)
(if (= 1 1)
"one is one")
"I am still here")
> (foo)
"I am still here"
These two added together lead to the error you're experiencing.

How do you return the description of a procedure in Scheme?

Suppose I have something like this:
(define pair (cons 1 (lambda (x) (* x x))
If I want to return the front object of the pair I do this:
(car pair)
And it returns 1. However when the object is a procedure I don't get the exact description of it.
In other words:
(cdr pair)
returns #<procedure> and not (lambda (x) (*x x)).
How do I fix this?
Although there's no way to do this generally, you can rig up something to do it for procedures that you define.
Racket structs can define a prop:procedure that allows the struct to be applied (called) as a procedure. The same struct can hold a copy of your original syntax for the function definition. That's what the sourced struct is doing, below.
The write-sourced stuff is simply to make the output cleaner (show only the original sexpr, not the other struct fields).
The define-proc macro makes it simpler to initialize the struct -- you don't need to type the code twice and hope it matches. It does this for you.
#lang racket
(require (for-syntax racket/syntax))
;; Optional: Just for nicer output
(define (write-sourced x port mode)
(define f (case mode
[(#t) write]
[(#f) display]
[else pretty-print])) ;nicer than `print` for big sexprs
(f (sourced-sexpr x) port))
(struct sourced (proc sexpr)
#:property prop:procedure (struct-field-index proc)
;; Optional: Just to make cleaner output
#:methods gen:custom-write
[(define write-proc write-sourced)])
;; A macro to make it easier to use the `sourced` struct
(define-syntax (define-proc stx)
(syntax-case stx ()
[(_ (id arg ...) expr ...)
#'(define id (sourced (lambda (arg ...) expr ...)
'(lambda (arg ...) expr ...)))]))
;; Example
(define-proc (foo x)
(add1 x))
(foo 1) ; => 2
foo ; => '(lambda (x) (add1 x))
The procedure cons evaluates its arguments: 1 is self-evaluating to 1; (lambda ...) evaluates to an anonymous procedure. If you want to 'prevent' evaluation, you need to quote the argument, as such:
> (define pair (cons 1 '(lambda (x) (* x x))
> (cdr pair)
(lambda (x) (* x x))

Resources