3

How can I achieve below in Scheme REPL? Create a variable name from a string.

=>(define (string->variable-name "foo") 12)

=>foo

12

=>(+ foo 8)

20

In Common Lisp, this should be

=> (set (intern "ANY-TEXT") 5)

=> ANY-TEXT

5

How do I build a #procedure like "string->variable-name" (and "variable-name->string") ?

Thanks a lot.

3
  • 1
    This really isn't something that you should want to do as it contradicts major design elements of Scheme. (For example, while R6RS allowed one to introduce identifiers, R7RS retracted that capability). What are you actually trying to accomplish? Writing your own REPL is easy; but it all depends on what you are trying to do. Commented Jan 17, 2014 at 20:52
  • A program language (like scheme) should have the ability to "creat variables though other variables". I am not a programmer but only a fan on programming, so if I was wrong please tell me. Commented Jan 18, 2014 at 1:17
  • 1
    Not every programming language does everything. Scheme is a small language with a narrow focus; it is not designed to meet everybody's needs. Conjuring identifiers bound to values, in a running program, is not a part of Scheme. Commented Jan 18, 2014 at 5:22

2 Answers 2

6

If what you're passing to string->variable-name is always a string literal (i.e., not a variable that contains a string), you can do that using a syntax-case macro that transforms the string literal to an identifier:

(define-syntax string->variable-name
  (lambda (stx)
    (syntax-case stx ()
      ((_ str)
       (string? (syntax->datum #'str))
       (datum->syntax #'str (string->symbol (syntax->datum #'str)))))))

and conversely, a variable-name->string macro could look like this:

(define-syntax variable-name->string
  (lambda (stx)
    (syntax-case stx ()
      ((_ id)
       (identifier? #'id)
       (datum->syntax #'id (symbol->string (syntax->datum #'id)))))))

However, remember: this will only work if you are working with string (in case of string->variable-name) or identifier (in case of variable-name->string) literals.


If, on the other hand, you want the ability to reflect on names in your current Scheme environment, this is not supported by standard Scheme. Some implementations, like Guile or Racket, do have this capability.

Here's a Guile example:

> (module-define! (current-module) 'foo 12)
> foo
12
> (define varname 'bar)
> (module-define! (current-module) varname 42)
> bar
42

and a Racket example:

> (namespace-set-variable-value! 'foo 12)
> foo
12
> (define varname 'bar)
> (namespace-set-variable-value! varname 42)
> bar
42
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks Chris. Codes you mentioned don't work for me. Petite Chez Scheme complain "Exception: Exception: invalid syntax string->variable-name" I'll try Racket later, I am using Windows, so it's hard for me to install Guile.
@ryrd How were you trying to call string->syntax-name? As I mentioned in my answer, it only works when using string literals, e.g., (string->syntax-name "foo"). You cannot use (let ((foo "bar")) (string->syntax-name foo)); I have a syntax guard in place to block that, and the error message suggests to me that you were indeed attempting such a thing and my guard caught it.
Yeap, I do want call string->variable-name as a regular #procedure, which also (define foo "bar")(string->variable-name foo) should work, and bar will also be a variable now. I want to use it as a procedure, but thank you :-)
@ryrd What are you trying to do at a high level, anyway? Poor-man's eval? I keep getting the feeling that we're dealing with an XY problem here.
@ryrd Sorry, that's not "high level". High-level is basically explaining why you're trying to do what you're doing. Like, are you really trying to access top-level variables by name, or is it okay to use a hash table to hold a list of user-defined variables? If the latter is okay, there is a portable Scheme solution to your problem (and GoZoner's answer is a variant of that, except he/she is using alists instead of hash tables).
0

Forgetting the syntax for a moment:

(define string->variable-name string->symbol)

(define name->value-mapping '())

(define (name-set! name value)
  (set! name->value-mapping
        (cons (cons name value)
              name->value-mapping))
  value)

(define (name-get name)
  (cond ((assoc name name->value-mapping) => cdr)
        (else 'unbound)))

Sure you can't do (+ 5 <my-named-value>) without some other help...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.