SCHEME - printf as a debug technique? - debugging

Is the printf command a sensible way to attempt a debug or other techinuqes would be faster and/or more precise?
(Assume that I'm using Racket or other dialects that allow printf).

First off. Scheme (R7RS, R6RS, R5RS) doesn't have printf. There is display and SRFI-28 format. Because of this I'll just read printf as print statement which again could mean you're just using display.
The correct answer is that your code should be made into small procedures that can be unit tested easily. If you do that you'll never need either a debugger or printing out debug info ever again.
Usually Scheme uses expressions and it's not always easy to just add a print statement without having to wrap it and the following statement in a begin. Because of that you may introduce bugs when you add and, even worse, remove debug information from your code. eg.
(if (test arg)
(call-something (car arg))
(call-something-else (cdr arg))
So how much would you have to change in order to print the result of (test arg) without altering the course of the code and how easy would it be to remove that without introducing a new bug? If I really wanted to print out debug info I would have made a macro:
(define-syntax dbg
(syntax-rules ()
((_ . rest)
(let ((expr 'rest)
(res rest))
(display (list expr '=> res))
res))))
Now you could just prefix dbg where you want to inspect:
(if (dbg test arg)
(call-something (car arg))
(call-something-else (cdr arg))
Imagine that the result og (test arg) is 5, then you'll get ((test arg) => 5) out without altering the result to if.
If you happen to use DrRacket it's very simple to use the very good debugger and macro stepper which they have. With it you'll just set a break point and run towards the interesting parts and step through as you see the values every step calculates. There are probably some other IDEs as well but I stopped looking after I found racket. Even when using DrRacket nothing is keeping you from using a different implementation in production, like Ikarus, provided that you write in one of the Scheme reports and not something implementation specific.
Be careful! People who are too comfortable with debuggers tend to make long procedures that look more like FORTRAN than Scheme. The best is to write programs as if you didn't have any means of debugging, use the debugger when you feel the need and refactor your code if you find yourself in the debugger all the time.

Related

How to `apply` a macro/syntax in Racket?

Suppose I have a list of arguments args and a macro/syntax f that takes a variable number of arguments. How do I apply f to args? Apparently apply doesn't work here.
For example, suppose I have a list of values bs and I want to know if they're all true, so I try (apply and bs) but I get the error "and: bad syntax". The workaround I came up with is (eval `(and . ,bs)) but I'm wondering if there is some standard way to achieve this sort of thing.
Update
A bunch of possible duplicates have been suggested, but most of them are just about the and example. This suggested question seems to be the same as mine, but the answer there is not very helpful: it basically says "don't do this!".
So maybe the point is that in practice this "apply + macro" question only comes up for macros like and and or, and there is no useful general question? I certainly ran into this issue with and, and don't have much Scheme experience, certainly no other examples of this phenomenon.
This is an XY problem. Macros are part of the syntax of the language: they're not functions and you can't apply them to arguments. Conceptually, macros are like functions which map source code to other source code, and which are called at compile time, not run time: trying to use them at run time is a category error. (In Common Lisp macros are, quite literally, functions which map source code to other source code: in Scheme I'm not quite so clear about that).
So if you have a list and you want to know if all its elements are true, you call a function on the list to do that.
It's easy to write such a function:
(define (all-true? things)
(cond [(null? things)
#t]
[(first things)
(all-true? (rest things))]
[else #f]))
However Racket provides a more general function: andmap: (andmap identity things) will either return false if one of things is not true, or it will return the value of the last thing in the list (or #t if the list is empty). (andmap (lambda (x) (and (integer? x) (even? x))) ...) will tell you if all the elements in a list are even integers, for instance.
There is also every which comes from SRFI 1 and which you can use in Racket after (require srfi/1). It is mostly (exactly?) the same as andmap.
One thing people sometimes try to do (and which you seem to be tempted to do) is to use eval. It may not be immediately clear how awful the eval 'solution; is. It is awful because
it doesn't, in fact, work at all;
insofar as it does work it prevents any kind of compilation and optimisation;
last but not least, it's a pathway to code injection attacks.
Let's see how bad it is. Start with this:
> (let ([args '(#t #t #f)])
(eval `(and ,#args)))
#f
OK, that looks good, right? Well, what if I have a list which is (a a a b): none of the elements in that are false, so, let's try that:
> (let ([args '(a a b)])
(eval `(and ,#args)))
; a: undefined;
; cannot reference an identifier before its definition
Oh, well, can I fix that?
> (let ([args '(a a b)]
[a 1] [b 2])
(eval `(and ,#args)))
; a: undefined;
; cannot reference an identifier before its definition
No, I can't. To make that work, I'd need this:
> (define a 1)
> (define b 2)
> (let ([args '(a a b)])
(eval `(and ,#args)))
2
or this
> (let ([args '('a 'a 'b)])
(eval `(and ,#args)))
'b
Yes, those are quotes inside the quoted list.
So that's horrible: the only two cases it's going to work for is where everything is either defined at the top level as eval has no access to the lexical scope where it is called, or a literal within the object which may already be a literal as it is here, because everything is now getting evaluated twice.
So that's just horrible. To make things worse, eval evaluates Scheme source code. So forget about compiling, performance, or any of that good stuff: it's all gone (maybe if you have a JIT compiler, maybe it might not be so awful).
Oh, yes, and eval evaluates Scheme source code, and it evaluates all of it.
So I have this convenient list:
(define args
'((begin (delete-all-my-files)
(publish-all-my-passwords-on-the-internet)
(give-all-my-money-to-tfb)
#t)
(launch-all-the-nuclear-missiles)))
It's just a list of lists of symbols and #t, right? So
> (eval `(and #,args)
; Error: you are not authorized to launch all the missiles
; (but all your files are gone, your passwords are now public,
; and tfb thanks you for your kind donation of all your money)
Oops.
It would be nice to be able to say, if I have a list that I want to check some property of that doing so would not send all my money to some person on the internet. Indeed, it would be nice to know that checking the property of the list would simply halt, at all. But if I use eval I can't know that: checking that every element of the list is (evaluates to) true may simply never terminate, or may launch nuclear weapons, and I can generally never know in advance whether it will terminate, or whether it will launch nuclear weapons. That's an ... undesirable property.
At the very least I would need to do something like this to heavily restrict what can appear in the list:
(define (safely-and-list l)
(for ([e (in-list l)])
(unless
(or (number? e)
(boolean? e))
(error 'safely-and-list "bad list")))
(eval `(and ,#l)))
But ... wait: I've just checked every element of the list: why didn't I just, you know, check they were all true then?
This is why eval is never the right solution for this problem. The thing eval is the right solution for is, well, evaluating Scheme. If you want to write some program that reads user input and evaluates, it, well, eval is good for that:
(define (repl (exit 'exit))
(display "feed me> ")
(flush-output)
(let ([r (read)])
(unless (eqv? r exit)
(writeln (eval r))
(repl exit))))
But if you think you want to apply a macro to some arguments then you almost certainly have an XY problem: you want to do something else, and you likely don't understand macros.

Change program code while running in Chicken Scheme

Is it possible to update the program code while it is being interpreted by csi, the Chicken Scheme Interpreter? If so, how?
So that I can interactively change part of the code and immediately see the effects of that changes.
For example, suppose I have written the following program:
(define (loop)
(print "Ciao")
(rest 1)
(loop))
(loop)
(assume (rest 1) has the effect of pausing the program for a second).
If I run this program, trough csi, it prints the string "Ciao" every second. If I change the string "Ciao" into something else, for example into "else", and I save the program code file, then csi continue interpreting the old program code, so I continuously see the string "Ciao". I'd like, in this case, that when I save the modified code with the string "Ciao" replaced by "else", csi continue its interpretation job by looking into the modified file, instead of the old file.
So that I obtain as output some "Ciao" followed by some "else": the "else" start to appear when I replace "Ciao" by "else" in the source code.
In general, the answer is "don't". The way you're supposed to use the REPL is by evaluating piecemeal changes against it, then evaluating a function or two to make sure everything went as expected. Part of this approach is structuring your program so that it can be easily tested in pieces, which implies not automatically starting any infinite loops. In the specific case you're asking about, you could instead write
(define (do-stuff)
(print "Ciao"))
(define (main-loop)
(do-stuff)
(rest 1)
(main-loop))
(define (start) (main-loop))
You can now incrementally develop do-stuff, periodically evaluating new versions to your interpreter and calling them to make sure they work, then eventually calling start once you're confident that it's doing the right thing.
You may get mileage out of this similar question asked about Common Lisp.
As an aside, if you were using Common Lisp and SLIME, you could now do more or less what you proposed:
(defun do-stuff ()
(format t "Ciao~%"))
(defun main-loop ()
(loop (progn (do-stuff)
(sleep 1))))
(main-loop)
Starting that up would start printing Ciao on separate lines in your SLIME REPL. If you changed do-stuff to
(defun do-stuff ()
(format t "else~%"))
then hit it with C-c C-c (the default binding for slime-compile-defun), you'd see your SLIME REPL start printing else lines in-flight.
CL-USER> (main-loop)
Ciao
Ciao
Ciao
; compiling (DEFUN DO-STUFF ...)else
else
else
else
else
else
; Evaluation aborted on NIL. User break.
CL-USER>
I'm not sure how to accomplish the same thing in Scheme, but I'm reasonably sure it's possible.
All that being said, you sometimes want to run a program part of which is an infinite loop. A real world example would be while testing a TCP server of some sort. If you're in such a situation, and your desired workflow is
Write file
Run csi my-file.scm
Edit file
Kill csi
Run csi my-file.scm
goto 3
and you basically just want to automate steps 4 through 6, you'll need an external tool to do it for you. Take a look at entr or hsandbox (the latter doesn't have Scheme support out of the box, but it doesn't look like it would be too hard to add).
There is no common way to make a running program check its source for changes but you there seems to be enough feratures available in Chicken to roll your own:
(use posix)
(use srfi-18)
(define (watch-reload! file)
(define (tsleep n)
(thread-sleep! (seconds->time (+ n (time->seconds (current-time))))))
(define (get-time)
(file-modification-time file))
(thread-start!
(lambda ()
(let loop ((filetime '()))
(let ((newtime (get-time)))
(when (not (equal? filetime newtime))
(load file))
(tsleep 10)
(loop newtime))))))
Now all you have to do is to use watch-reload! instead of load and it will check and reload every 10 seconds if the file has been modified.
If you save when the file is not valid scheme it stops working until you call watch-reload! on it again.
It may be that chicken programmers might have a better solution.

scheme call/cc for handling errors

I have a Scheme application that accepts some user input, computes, and gives some output. I would like to make it more robust by enabling some kind of error handling and a way to exit smoothly. Call with current continuation seems to be the thing to fill this gap here, but I'm not quite sure how to go about implementing it.
As of now, if the user enters some non-valid input, the program will crash and exit. I would simply like to keep the user in the application and give an error message instead. Here is an outline of my method, but I'm not sure where to implement it so that if an error occurs that would normally crash the system, just gives an error and keeps them in the program.
(define (handle_err)
(call/cc
(lambda (a)
(display "exception handled: a"))))
I would also like a clean exit from the program. That is, not a crash exit, nor a break. I would like the user to type "leave", have the program close and return to the interpreter. My outline looks much like the above, but it doesn't have the user leave the program, it just takes him back to the input prompt.
Any ideas are appreciated.
Yes, call/cc can handle this kind of transfer of control. One problem here is that the call/cc corresponds to the "try/catch" in this example, not to the "throw".
A bigger problem, though, is that you don't have any nice way in r5rs to get control when an error occurs.
This is really just a symptom of an even bigger problem, which is that various different Scheme implementations have solved this problem in different ways.
Personally, I would strongly urge you to take a look at Racket; it's supported on many versions of Linux, lives in many standard distros, and handles this really nicely:
#lang racket
(with-handlers ([exn:fail?
(lambda (exn)
(display "oh noes! An exception occurred!"))])
(try-something-dangerous))
(define (try-something-dangerous)
(/ 1 0))
Actually, I would recommend Racket even if you want to write r5rs programs; you can just begin your programs with
#lang r5rs
... to get full r5rs compliance.
Well, you make look at this approach
(define-syntax try
(syntax-rules ()
((_ handler throw chunk)
(call/cc (lambda (catch)
(let ((throw (lambda (exc) (catch (handler exc)))))
chunk))))))
(define (div p q)
(try
;; Error processing
(lambda (error) (printf "Error: ~s~n" error) error)
;; Error my be thrown with keyword "throw"
throw
;;Actual code to run
(if (= q 0)
;; Oh noes, error!
(throw "Division by zero")
;; All ok, do the work
(/ p q))))
(printf "1/0: ~s~n" (div 1 0))
(printf "1/2: ~s~n" (div 1 2))
The "throw" is used to capture name for throw function (this is need because of hygiene).

Racket REPL over TCP

I've built a rather complex application with Racket (formerly PLT Scheme) and would like to add a REPL for debugging purposes. I've tried to make it accessible over a TCP stream:
(define repl-server
(thread (lambda ()
(let ((listener (tcp-listen 8082 5 #t)))
(do () (#f)
(let-values (((in out) (tcp-accept listener)))
(thread (lambda ()
(let ((port-string (get-port-string in)))
(Try "debug-repl" #f
(begin
(file-stream-buffer-mode out 'line)
(display-and-log "Password: " out)
(flush-output out)
(when (string=? (read-line in) "whatever")
(log "Connect to REPL: " port-string))
(current-input-port in)
(current-output-port out)
(current-error-port out)
(read-eval-print-loop))
(close-input-port in)
(close-output-port out))))))))))))
(Try name result-if-exception form) is a macro providing basic exception handling, (log ...) and (display-and-log ...) do what they sound like.
Now if I access the REPL, I can't even evaluate constants, as I keep getting the error compile: unbound identifier (and no #%app syntax transformer is bound) at: #%top-interaction. How can I make this REPL work? And how can I access values defined before starting the REPL server?
You're using read-eval-print-loop, which is essentially the same as using eval, and therefore suffers from the same kind of problems. See the relevant Guide section for a detailed explanation. It's best to read that completely, but the answers that you're looking for are either what the "Namespaces" section describes, or the "Namespaces and Modules" section -- the first is if you want a toplevel kind of a namespace, and the second is if you want a namespace that corresponds to the actual file that the code appears in. (The first is usually better -- for example, if you use the second then repl-server is itself available for the REPL user, making it a questionable feature...)
Here's how it would look like:
...
(thread (lambda ()
(parameterize ([current-namespace (make-base-namespace)])
...same code...)))
...
and for the second one, define an anchor and use namespace-anchor->namespace as the last example on that page shows.
[BTW, see also the run-server thing, it's a little old, but can still be useful.]

In Scheme the purpose of (let ((cdr cdr))

I've been studying Scheme recently and come across a function that is defined in the following way:
(define remove!
(let ((null? null?)
(cdr cdr)
(eq? eq?))
(lambda ... function that uses null?, cdr, eq? ...)
What is the purpose of binding null? to null? or cdr to cdr, when these are built in functions that are available in a function definition without a let block?
In plain R5RS Scheme, there is no module system -- only the toplevel. Furthermore, the mentality is that everything can be modified, so you can "customize" the language any way you want. But without a module system this does not work well. For example, I write
(define (sub1 x) (- x 1))
in a library which you load -- and now you can redefine -:
(define - +) ; either this
(set! - +) ; or this
and now you unintentionally broke my library which relied on sub1 decrementing its input by one, and as a result your windows go up when you drag them down, or whatever.
The only way around this, which is used by several libraries, is to "grab" the relevant definition of the subtraction function, before someone can modify it:
(define sub1 (let ((- -)) (lambda (x) (- x 1))))
Now things will work "more fine", since you cannot modify the meaning of my sub1 function by changing -. (Except... if you modify it before you load my library...)
Anyway, as a result of this (and if you know that the - is the original one when the library is loaded), some compilers will detect this and see that the - call is always going to be the actual subtraction function, and therefore they will inline calls to it (and inlining a call to - can eventually result in assembly code for subtracting two numbers, so this is a big speed boost). But like I said in the above comment, this is more coincidental to the actual reason above.
Finally, R6RS (and several scheme implementations before that) has fixed this and added a library system, so there's no use for this trick: the sub1 code is safe as long as other code in its library is not redefining - in some way, and the compiler can safely optimize code based on this. No need for clever tricks.
That's a speed optimization. Local variable access is usually faster than global variables.

Resources