racket/gui: sleep without freezing gui - user-interface

I'm writing a unit test and I want to:
open a frame
wait a few seconds
close the frame
Here's the code I tried:
#lang racket/base
(require plot racket/class)
(define f
(plot3d-frame (surface3d (λ (x y) (* (cos x) (sin y))) -3.0 3.0 -3.0 3.0)))
(send f show #true)
(sleep 10)
(send f show #false)
Running this opens a blank frame, waits 10 seconds, and closes the frame. The plot never appears. I guess this is because sleep puts the whole thread, including the eventspace, to sleep.
Is there a way to make my code sleep without making the GUI to sleep?

Yes, use sleep/yield
#lang racket/base
(require plot racket/class racket/gui/base)
(define f
(plot3d-frame (surface3d (λ (x y) (* (cos x) (sin y))) -3.0 3.0 -3.0 3.0)))
(send f show #true)
(sleep/yield 10)
(send f show #false)
;; "It works every time!"

Related

How to step through this evaluation?

I would like to see how the value of a square root is iteratively improved. For example on the following:
#lang sicp
(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(define (improve guess x) (average guess (/ x guess)))
(define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001 ))
(define (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x)))
(define (sqrt x) (sqrt-iter 1.0 x))
(sqrt 2)
It gets values such as the following:
1 1
2 1.5
3 1.4166666666666665
4 1.4142156862745097
As an example of what I want to show, in Javascript I would do something like:
const sqrt_iter = (guess, x) => {
console.log(count++, guess);
return good_enough(guess, x) ? guess : sqrt_iter(improve(guess, x), x);
}
const sqrt = x => sqrt_iter(1.0, x);
How could I print or trace these intermediate values in DrRacket/SICP? I tried doing (trace sqrt) but it said not found.
I am sure Racket has some fancy trace facility. But there's a famous quote (due I think to John Foderaro):
Lisp [for which read Racket] is the programmable programming language.
What this means is: if there's no tracing facility, or you are too lazy to make one, you can just write one.
Here is a rudimentary one I wrote in five minutes:
#lang racket
(provide define/traced)
(define trace-depths (make-parameter 0))
(define (spaces n)
(make-string n #\ ))
(define-syntax define/traced
(syntax-rules ()
[(_ (name arg ...) form ...)
(define/traced name (λ (arg ...) form ...))]
[(_ (name . args) form ...)
(define/traced name (λ args form ...))]
[(_ name function)
(define name
(λ args
(let* ([depth (trace-depths)]
[prefix (spaces depth)])
(parameterize ([trace-depths (+ depth 1)])
(printf "~A~S ...~%" prefix `(,'name ,#args))
(call-with-values
(thunk (apply function args))
(λ results
(printf "~A-> ~S~%" prefix results)
(apply values results)))))))]))
Stash this in a file called define-traced.rkt and then require it, and tell it to trace the procedures you care about:
#lang racket
(require "define-traced.rkt")
(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(define/traced (improve guess x) (average guess (/ x guess)))
(define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001 ))
(define/traced (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x)))
(define (sqrt x) (sqrt-iter 1.0 x))
(sqrt 2)
Which will duly print this:
(sqrt-iter 1.0 2) ...
(improve 1.0 2) ...
-> (1.5)
(sqrt-iter 1.5 2) ...
(improve 1.5 2) ...
-> (1.4166666666666665)
(sqrt-iter 1.4166666666666665 2) ...
(improve 1.4166666666666665 2) ...
-> (1.4142156862745097)
(sqrt-iter 1.4142156862745097 2) ...
-> (1.4142156862745097)
-> (1.4142156862745097)
-> (1.4142156862745097)
-> (1.4142156862745097)
1.4142156862745097
Note that when I said it was a rudimentary facility I meant it: in particular it will probably turn tail calls into non-tail calls, and there are many other things wrong with it. But it took less long to write than it would take to read the manual on some hairy facility. If I was going to use this thing just once (and this is probably the only time I will ever use it: it only made it into a file so I could require it in another file) it's worth it. This is one of the glories of Lisp-family languages.
Try begin with printf (and also add one variable as counter):
#lang racket
(define (square x)
(* x x))
(define (average x y)
(/ (+ x y) 2))
(define (improve guess x)
(average guess (/ x guess)))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001 ))
(define (sqrt-iter guess x count)
(begin
(printf "~a ~a \n" count guess)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x
(+ 1 count)))))
(define (sqrt x) (sqrt-iter 1.0 x 1))
(sqrt 2)
1 1.0
2 1.5
3 1.4166666666666665
4 1.4142156862745097
1.4142156862745097
Note that I used #lang racket- it seems that sicp don't have print or printf, but you can try write or display to achieve similar result.
#ignis provides the proper technique for this. However, before you dive into the deep ocean of define-syntax, maybe you want the quick-and-dirty approach -
#lang sicp
(define (sqrt-iter guess x)
(for-each display (list "sqrt-iter" " " guess " " x "\n"))
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(sqrt 2)
sqrt-iter 1.0 2
sqrt-iter 1.5 2
sqrt-iter 1.4166666666666665 2
sqrt-iter 1.4142156862745097 2
1.4142156862745097

Is there a way to get the mouse's X and Y coordinates in MIT Scheme?

I've been experimenting with X Graphics in MIT Scheme, and I was wondering whether there is a way to get the cursor position on the screen/in relation to the X window from within the language, to change the graphics based on the mouse location.
I figured out a way myself, but it's pretty nasty since I had to use additional packages:
(define (get-position)
(define a (open-output-string))
(run-shell-command "xdotool getmouselocation" 'output a)
(define output (get-output-string a))
(close-port a)
((lambda (x) (list (string->number (cadar x)) (string->number (cadadr x))))
(map (string-splitter 'delimiter #\:) ((string-splitter) ((string-trimmer) output)))))
(define resolution (let ((a (open-output-string)))
(run-shell-command "xdpyinfo | grep dimensions | awk '{print $2;}'" 'output a)
(define output (get-output-string a))
(close-port a)
(map string->number ((string-splitter 'delimiter #\x)
((string-trimmer) output)))))
Then, to get the relative position of the cursor on the screen, you just do
(map (lambda (x y) (inexact (/ x y))) (get-position) resolution)
(You do have install xdpyinfo and xdotool beforehand though, so keep that in mind)

How to stop this sleeping program in Racket

I have following code of a countdown timer. It starts all right but it does not stop on pressing the stop button.
#lang racket/gui
(define myframe (new frame% [label "Timer"] [x 500] [y 200] ) )
(define tfsecs (new text-field% [parent myframe] [label "Secs:"]))
(define msgbmi (new message%
[parent myframe] [auto-resize #t] [label ""] ))
(define stopflag #f)
(define (OnButtonPressFn n)
(sleep 1)
(set! n (sub1 n))
(define m 0)
(send msgbmi set-label "")
(for((i (in-naturals)) #:break stopflag)
(set! m (- n i))
; (printf "running; i= ~a~n" m)
(send msgbmi set-label (number->string m))
(sleep 1) ) )
(define startbutton
(new button% [parent myframe] [label "Start"]
(callback (lambda (b e)
(define secs (string->number (send tfsecs get-value)))
(when secs (OnButtonPressFn secs))))))
(define stopbutton
(new button% [parent myframe] [label "Stop"]
(callback (lambda (b e)
(set! stopflag #t)))))
(send myframe show #t)
It stops if I limit the for loop to end it at 0. But I want it to keep showing how much time is over till the stop button is pressed.
Apparently, the stopflag being set by stop button is not being read by running loop. How can this be corrected? How can I make the stop button work properly here?
Let's follow the intended control flow.
First we click the start button. The system generates an event. The event handler (the call back is called) and the click is handled. Then later on the stop button is clicked. The system generates a new event and the event handler for the stop button is called.
The problem in your program is that the event handler for the start button never returns. The system only handles one event at a time, so if you never return from an event handler, any following events will not be handled.
One way to fix the problem is to start a new thread to do the actual work:
(define (OnButtonPressFn n)
(thread (λ ()
(sleep 1)
(set! n (sub1 n))
(define m 0)
(send msgbmi set-label "")
(for((i (in-naturals)) #:break stopflag)
(set! m (- n i))
; (printf "running; i= ~a~n" m)
(send msgbmi set-label (number->string m))
(sleep 1) ) )))
This event handler creates a new thread (that runs concurrently with the event loop) and then returns immediately. The event loop is there able to handle new events. In the mean time the new thread does the work (here printing numbers).

alias a name for the clause of a macro

I would like to alias some racket 2htdp functions/macros, so that I can translate them in another language for my children.
Things which are functions I can simply alias with define. I'm having trouble with the big-bang structure; If I try to alias on-tick for instance, everytime I get big-bang: [new-name] clauses are not allowed within big-bang.
I tried various variants of define-syntax but I could not make it work so far (that said, I'm a complete racket newbie).
Something like this works (well, ladja is not defined):
#lang racket
(require 2htdp/universe 2htdp/image)
(big-bang 0
(on-tick (lambda (x) (+ x 1)))
(to-draw (lambda (x) (place-image ladja 150 x (prazni-prostor 300 300))))
(stop-when (lambda (x) (= x 300))))
But this doesn't (triggers the error):
#lang racket
(require 2htdp/universe 2htdp/image)
(define new-name on-tick)
(big-bang 0
(new-name (lambda (x) (+ x 1)))
(to-draw (lambda (x) (place-image ladja 150 x (prazni-prostor 300 300))))
(stop-when (lambda (x) (= x 300))))
I see that big-bang is a macro, so that explains the issue: I guess I would have to be able to force my macro to be evaluated first, somehow?
If you're writing a module that you would require into your program, then you can use provide with rename-out to provide an alias:
In big-bang-with-new-name.rkt:
#lang racket
(require 2htdp/universe 2htdp/image)
(provide big-bang
to-draw
stop-when
empty-scene
(rename-out [on-tick new-name]))
Using it in another file:
#lang racket
(require "big-bang-with-new-name.rkt")
(big-bang 0
[new-name (lambda (x) (+ x 1))]
[to-draw (lambda (x) (empty-scene 200 200))]
[stop-when (lambda (x) (= x 300))])
Many macros use free-identifier=? to recognize keywords like this. Rename transformers cooperate with free-identifier=? to create exact aliases. This means you can also define new-name as a rename transformer in the main file like this:
#lang racket
(require 2htdp/universe 2htdp/image)
(define-syntax new-name (make-rename-transformer #'on-tick))
(big-bang 0
[new-name (lambda (x) (+ x 1))]
[to-draw (lambda (x) (empty-scene 200 200))]
[stop-when (lambda (x) (= x 300))])

Squaring a Procedure in Scheme

I am an electrical engineer who is trying to learn scheme in internet.I want to take the square of sin x but i fail.I think I need a function which makes (Number,Number) - (Number,Number).So it should take lambda x and lambda f and calculate square (f x).But I am stuck and I cant write this code. Can anyone write this?
Just nest the function calls. An easy way would be:
(define (square x)
(* x x))
(square (sin x))
Or create a composed function:
(define square-sin (compose square sin))
(square-sin x)
Two ideas here:
(define (sqr-f f) (compose sqr f))
Usage:
((sqr-f sin) 1)
Or an uncurried version:
(define (sqr-f-u f . x) (sqr (apply f x)))
Usage:
(sqr-f-u + 1 2)

Resources