2

Is it possible to write the scheme function symtab below?

(define x 1)
(define y 2)
(symtab x) ; => (x . 1)
(symtab y) ; => (y . 2)

If it isn't possible, can a similar function be defined which has quoted arguments?

(symtab 'x) ; => (x . 1)
(symtab 'y) ; => (y . 2)
cfgauss
  • 69
  • 5

2 Answers2

1

Yes, with macros.

> (define-syntax symtab
  (syntax-rules ()
    ((_ x)
     (cons 'x x))))

> (define x 1)
> (define y 2)
> (symtab x) 
'(x . 1)
> (symtab y)
'(y . 2)
> 

A macro is not actually a function (so technically the essential answer to your question is no). With mere functions your task might even be impossible in most languages. But Scheme provides us with macros that allow us to manipulate a program from within itself. For more on macros and how they are different from functions I recommend taking a look at the following tutorial: http://www.greghendershott.com/fear-of-macros/all.html#%28part..Transform%29

It is based on Racket, but it is substantially applicable across various Scheme dialects. Enjoy!

Alex V
  • 3,416
  • 2
  • 33
  • 52
  • To clarify, it's not possible to create a Scheme function which works with unquoted arguments but it is possible to create a Scheme macro (your example). And it's also possible to create a Scheme function which works with quoted arguments (rsm's example). Is that correct? – cfgauss Nov 20 '18 at 03:29
  • yes, that's correct. it can't be done using functions, because arguments get evaluated (so you can't get argument original name, value only). it can be done with macro, but it's not very reliable in either case - please read closely related [Why isn't there an `unquote` Lisp primitive?](https://stackoverflow.com/questions/18515295/why-isnt-there-an-unquote-lisp-primitive) – rsm Nov 20 '18 at 11:16
  • @rsm Could you give examples of the unreliability of each of the two solutions? – cfgauss Nov 21 '18 at 00:39
  • @cfgauss Hi, please check my updated answer. Hope it's clear now. – rsm Nov 21 '18 at 10:03
1

It's possible with quoted arguments:

(define (symtab s)
  (cons s (eval s (interaction-environment))))

Now lets test it:

(define xy 12)

(symtab 'xy)
=> (xy . 12)

EDIT: However it's not very reliable (using macro too) - please read closely related Why isn't there an unquote Lisp primitive?

It's because Scheme like most languages is lexically scoped. It means that variable names are resolved when function is defined, as opposed to dynamic scope when variable names are resolved at run-time. So

(define xy 12)

(define (getXY) xy)

(getXY)
=> 12

This code works, because when we define getXY, name xy is known and can be resolved to top-level xy. However

(define (getXY) xy)

(let ((xy 21))
  (getXY))
=> Unbound variable: xy

This doesn't work, because when getXY was defined, xy was not known (and my Guile Scheme also gave me warning when defining getXY "warning: possibly unbound variable `xy'").

It will work in Emacs Lisp - dynamically scoped.

rsm
  • 2,530
  • 4
  • 26
  • 33