How can find all functions and bounded symbols in an "environment" - scheme

I am using a softer who has a build-in scheme interpreter. I know the "environment" name is (the-environment). How can I find all the functions and symbols in the environment ?
(define p (open-output-file "d:/test.txt"))
(display (the-environment) p)
can this will display all the functions ?
Thanks in advance.
Joe

As Eli Barzilay pointed out, whether or not you can reflectively find all the names bound in an environment depends on which implementation of Scheme you are using.
I infer from your question that you are working within MIT Scheme, since you said the "name" of the environment is (the-environment)
From my own experimentation with MIT Scheme (release 9.1.1), you can indeed enumerate the names of the bindings bound in an environment:
1 ]=> (define (add1 n) (+ n 1))
;Value: add1
1 ]=> (add1 3)
;Value: 4
1 ]=> (environment-bound-names (the-environment))
;Value 13: (add1)
1 ]=>
I was a little surprised when I first encountered the above; I had expected to see many more bindings in the environment than just the single one I had defined myself.
Is it because you need to walk up to the parent environments, recursively? Well:
1 ]=> (environment-parent (the-environment))
;Value: #f
1 ]=>
It seems like in addition to the bindings you can access by inspecting (the-environment), one must also inspect the bindings accessible via system-global-environment:
1 ]=> (define global-names (environment-bound-names system-global-environment))
;Value: global-names
1 ]=> (length global-names)
;Value: 4050
1 ]=> (not (null? (memq '+ global-names)))
;Value: #t
1 ]=> (car global-names)
;Value: valid-hash-number?
From there, one can use functions like environment-lookup to extract the values bound within each environment:
1 ]=> (environment-lookup system-global-environment '+)
;Value 14: #[arity-dispatched-procedure 14]
1 ]=> ((environment-lookup system-global-environment '+) 2 3)
;Value: 5
(This could be useful, for example, if you wanted to filter the global-names list to just the names that are bound to procedures in the system global environment.)
FYI: I did not know the above off the top of my head; but luckily, MIT Scheme, like a number of other Lisp dialects, offers an apropos function that is very useful when you think you know part of the name of a function you are seeking. (apropos n) prints out all the bound symbols that have n in their name; so in my case, I made a guess and ran (apropos 'env) to see all of the symbols that are related to environments. That list is a little too long to transcribe here as an example, but here is something similar:
1 ]=> (apropos 'lookup)
#[package 14 (user)]
#[package 15 ()]
1d-table/lookup
dld-lookup-symbol
environment-lookup
environment-lookup-macro
environment-safe-lookup
hash-table/lookup
rb-tree/lookup
wt-tree/lookup
;Unspecified return value

Related

How can I use CONS in reverse way?

Normally, we pass two arguments to cons, in RACKET
eg:
(cons 23 '(1 2 3))
which outputs '(23 1 2 3)
Is there any procedure to do the following
(procedure '(1 2 3) 23) => '(1 2 3 23)
Try this:
(append '(1 2 3) '(23))
=> '(1 2 3 23)
That's fine for appending a single element. If you're planning to repeatedly add many elements at the end, it's better if you cons everything at the head and then reverse the list when you're done. Why? because using append for building an output list will quickly degenerate into an O(n^2) solution (see: Schlemiel the Painter's algorithm)
In Lisp/Scheme/Racket if you want a procedure, writing it makes it largely indistinguishable from built in procedures:
#lang racket
(define (procedure a-list an-atom)
(cond
[(not (list? a-list)) (error "procedure: first argument not a list")]
[(pair? an-atom) (error "procedure: second argument is a list")]
[else
(append a-list (list an-atom))]))
Then use it:
> (procedure '(1 2 3) 23)
'(1 2 3 23)

Using sort! function in DrRacket

I'm dealing with vectors and trying to use sort! function which is listed here. However I get unbound identifier error. At the top of editor, I specified the language as
#lang scheme
Should I load another module to use this function?
The referenced documentation is for MIT Scheme, you're using Racket with the #lang scheme language. Use the sort procedure instead, which returns a new sorted list:
(define lst1 '(3 2 1 0))
(define lst2 (sort lst1 <))
lst1
=> '(3 2 1 0)
lst2
=> '(0 1 2 3)
If you need to modify the input list after sorting it, use:
(define lst1 '(3 2 1 0))
(set! lst1 (sort lst1 <))
lst1
=> '(0 1 2 3)
The documentation you link to is for mit-scheme rather than to Racket.
The documentation for Racket is here: http://docs.racket-lang.org/search/index.html?q=sort
Note that the scheme in #lang scheme doesn't mean R5RS or R6RS, but rather
the "MzScheme language". Nowadays one most people use #lang racket.
#lang scheme
(require rnrs/sorting-6)
(define v (vector 5 3 2))
(vector-sort! < v)
v
If you want to use R6RS with Racket here is an example:
#!r6rs
(import (rnrs lists (6))
(rnrs base (6))
(rnrs io simple (6)))
(display (find even? '(3 1 4 1 5 9)))
Just define your own sort! using a syntactic extension:
(define-syntax-rule (sort! lst p ...)
(set! lst (sort lst p ...)))
then
> (define lst1 '(3 2 1 0))
> (sort! lst1 <)
> lst1
(0 1 2 3)
DrRacket (or just racket in the CLI) is a multiple language implementation. To strangest thing is that #lang scheme (or just #!scheme) isn't following a Scheme standard at all but is the legacy name of a language that was R5RS compatible once, but has changed it's name to #!racket and has immutable pairs as standard.
Other languages supported by the racket program that uses mutable pairs are #!r5rs and #!r6rs. These follow the Scheme standard and if you use these you can compile and run your programs with other implementations as well. By just changing the first line to that you are telling that the rest of this file will be programmed in that language. R6RS has vector-sort while R5RS needs support by SRFI-95 sort library's sort!
PS: If you are following SICP you might be interested in #lang planet neil/sicp. See here if you need help getting it to work.

Scheme call/cc issue - implementing exit.

I am writing a program that needs to recursively analyze a list of "commands" and "programs" (it is an interpreter of some "robotic language" invented by our professor for a robot living in a maze). Because my initial implementation was too slow, I decided to use call-with-current-continuation.
I know how call/cc works, I have read this and this as an explanation.
My call/cc is based on this part of tutorial:
Often we want to use call-with-current-continuation to call some
procedure that takes arguments other than an escape procedure. For
example, we might have a procedure that takes two arguments besides
the escape procedure, thus:
(define (foo x y escape) ... (if (= x 0)
(escape 'ERROR)) ...)) We can fix this by currying the procedure, making it a procedure of one argument.
[ An earlier chapter should have a discussion of currying! ]
Suppose we want to pass 0 and 1 as the values of x and y, as well as
handing foo the escape procedure. Rather than saying
(call-with-current-continuation foo) which doesn't pass enough
arguments to the call to foo, we say
(call-with-current-continuation (lambda (escape) (foo 0 1 escape)))
The lambda expression creates a closure that does exactly what we
want. It will call foo with arguments 0, 1, and the escape procedure
created by call-with-current-continuation.
However, for some reason it doesn't work and throws this exception:
call-with-current-continuation: contract violation
expected: (any/c . -> . any)
given: #<procedure:...mazesimulator.ss:301:34>
I would like you to help me find my mistake and explain why it occurs...
Here is the part of code relevant to this question:
; main program
(define (simulate state expression-list program limit)
; read the input and set global variables
(set! current-orientation (list-ref state 2))
(set! current-coordinates (list-ref state 1))
(set! current-maze (list-ref state 0))
; call the inner function
(call-with-current-continuation (lambda (exit)
(command state expression-list program limit exit)))
; this is the output
(list list-of-executed-commands (list current-maze current-coordinates current-orientation))
)
;; main recursive function
;; analyses expression-list parameter
;; evaluates its elements
;; and calls itself on the cdr of the espression-list
(define (command state expression-list program limit exit)
(if (and (not (null? expression-list))(equal? stop-command #f))
; recursion end condition, the whole procedure will be done only
; if the list is still not empty
(if (atom? expression-list) ;if the list consists of only one command
(if (equal? stop-command #f) ;positive branch - if there were no erros before
(atomic-command state expression-list program limit exit) ;call atomic-command on this element
;when flag is set to #t
(exit))
; here comes a problem with "inner ifs"
(if (atom? (car expression-list)) ;negative branch - if the first element is "if"
(if (equal? (car expression-list) 'if) ;if the list consisits only of if-clause, no other commands ((if ...))
(if ((name->function (list-ref expression-list 1))) ;evaluate the boolean - wall? north? and choose corresponding branch
(command state (list-ref expression-list 2) program limit exit)
(command state (list-ref expression-list 3) program limit exit))
(evaluate-first-and-call-command-on-rest expression-list program limit exit))
(if (equal? (car(car expression-list)) 'if) ;if the if-clause is not the only element in list - "inner if" ((if ...) turn-left put-mark)
(begin ;not only evaluate if-clause,
(if ((name->function (list-ref (car expression-list) 1)))
(command state (list-ref (car expression-list) 2) program limit exit)
(command state (list-ref (car expression-list) 3) program limit exit))
(command state (cdr expression-list) program limit exit)) ;but also call command on cdr!
(evaluate-first-and-call-command-on-rest expression-list program limit exit))))
;when limit is exceeded or when the flag is set to #t
(exit) ))
New follow-up: So at this point I am puzzled by the poster's question. GoZoner has pointed out that the continuation passed by call/cc may require an actual parameter when invoked, but this is not generally true in Racket (which, based on the poster's error message, is the language implementation that I assume is under discussion).
Furthermore, the code snippet that the original poster put in the question is incomplete, so one cannot directly execute the code in an attempt to replicate the problem. (My informal analysis hasn't revealed an obvious bug in the use of call-with-current-continuation that was presented by the original poster.) It would be useful if the original poster could derive a minimal (or at least smaller) test case that exposes the same issue.
It could be that one of the specific languages or language levels within Racket uses a more restrictive form of call/cc, but I have not found evidence of such a language level. I will pose the question to the original poster.
Edit: Chris-Jester Young has pointed out that my commentary may not apply properly here (see comments on this answer). I need to more carefully investigate the Racket's handling of continuations in imperative code; the notes below may be leading the asker down an incorrect path. (I plan to delete this answer if I can confirm that my notes below are bogus.)
Follow-up edit: It appears that Racket's handling of call/cc does indeed pass along a continuation that will accept zero values when it is invoked from a context that discards the value. For example:
(define global 7)
(define (goner exit)
(set! global 11)
(exit)
(set! global 13)
(* 2 3))
(define (hi)
(define x global)
(call-with-current-continuation goner)
(* 5 x global))
(* 5 7 11)
(hi)
The above prints 385 (twice); once for (* 5 7 11), and once for (hi).
(Original commentary follows)
The fact that you are invoking (exit) with zero arguments leads me to think that you do not completely understand how call/cc works (as in its observable behavior), despite your claim to the contrary.
I recommend you play with some small examples, completely independently of your professor's robot maze infrastructure, before you try to incorporate call/cc into your solution.
For example, I can readily reproduce your error message this way:
(define (goner)
(* 2 3))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
From the above, I get:
call-with-current-continuation: contract violation
expected: (any/c . -> . any)
given: #<procedure:goner>
which is quite similar to your error message, no? (Though to be honest, that might just be a coincidence).
Compare the output from the run above with the outputs from runs of:
(define (goner exit)
(* 2 3))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
and:
(define (goner exit)
(* 2 (exit)))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
and:
(define (goner exit)
(* 2 (exit 3)))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
and:
(define (goner exit)
(* (exit 2) 3))
(define (hi)
(let ((x (call-with-current-continuation goner)))
(* 5 x)))
(hi)
Give some careful thought to what each is illustrating, and think about how it might matter in the case of your program.
The call/cc 'escape procedure' expects a single argument. You are calling it as (exit) without the required argument. Different Scheme implementations will handle this differently. Here is one that complains:
1 ]=> (define (doit exit)
(display "DOIT2\n")
(exit)) ;; no argument, expect error
;Value: doit
1 ]=> (define (try)
(call-with-current-continuation
(lambda (exit) (display "TRY\n") (doit exit)))
'done)
;Value: try
1 ]=> (try)
TRY
DOIT2
;The procedure #[continuation 13] has been called with 0 arguments; it requires exactly 1 argument.
The reason that the 'escape procedure' expects a value is that call/cc, like all Scheme functions, needs to produce a value. The argument that is provided is the return value of call/cc when the escape procedure is invoked.

Environment not part of a continuation?

Is the environment not part of a continuation in scheme?
I have tested this with Chicken, Gauche, Racket and Gambit, and they all behave similarly:
(define kont #f)
(let ((a 1)
(b 2))
(call-with-current-continuation
(lambda (k)
(set! kont k)
(display 'mutating)
(newline)
(set! a -1)
(set! b -2)))
(display (+ a b))
(newline))
I would expect -3 when the LET is evaluated, but +3 in the calls to kont (since I thought the program would remember the bindings of a and b before mutation):
(let ... ) ; <-- evaluating the LET above
; prints "mutating"
=> -3
(kont 100)
=> -3
(kont 100)
=> -3
So the continuation only affects control, and not the environment? In this case, why is it said that one of the ways to implement continuations is to "copy the stack" (are bindings are not on the stack?)
The continuation captures the bindings. However, as you surmise, these bindings are mutable.
You've been somewhat misled, here, by the "copies the stack" slogan. While this is a reasonable way to think about call/cc, it's not the whole story. For one thing, you really really wouldn't want a language feature that exposed whether or not local bindings were stack-allocated or not.
Instead, call/cc is defined using the notion of "program contexts". For a nice treatment of this, you might want to take a look at Shriram Krishnamurthi's (free, online) textbook PLAI, or at the (not-free, much more in-depth) book "Semantics Engineering with PLT Redex".
As an aside; your program doesn't really check what you wanted it to check, because you never invoked the captured continuation. I think you wanted to write something like this:
#lang racket
(define kont #f)
(let ([a 3])
(let/cc k
(set! kont k)
(set! a 4))
(printf "~s\n" a))
(kont)
... which shows pretty much the same behavior that you mention above.
You change the values of a and b in the environment with set!. So a and b is -1 and -2 in the continuation environment. You can not unroll side effects. There are no differences between a, b and kont in your continuation.

Applying a symbol as a procedure

Suppose I have a simple symbol:
> '+
+
Is there any way I can apply that symbol as a procedure:
> ((do-something-with '+) 1 2)
3
So that '+ is evaluated to the procedure +?
I'm not 100% sure, but would:
((eval '+) 1 2)
work? I'm not sure if you need to specify the environment, or even if that works - I'm a Scheme noob. :)
Lucas's answer is great. For untrusted input you can make a white list of allowed symbols/operators.
(define do-something (lambda (op)
(cond
((equal? op `+) +)
((equal? op `-) -)
((equal? op `*) *)
((equal? op `/) /)
((equal? op `^) ^))))
((do-something `+) 1 2)
Newbie too so hope I've understood your question correctly...
Functions are first class objects in scheme so you don't need eval:
1 ]=> (define plus +)
;Value: plus
1 ]=> (plus 2 3)
;Value: 5
HTH
Update: Ignore this and see the comments!

Resources