How to give a frame as argument to DrRacket when I paint a image by using a painter? (SICP 2nd Edition) - racket

I am reading SICP 2nd Edition.
A painter is represented as a procedure that, given a frame as argument, draws a particular image shifted and scaled to fit the frame.
I am using DrRacket (SICP Picture Language).
How to give a frame as argument to DrRacket when I paint a image by using a painter?

Here is an example
#lang racket
(require sicp-pict)
(paint einstein)
(paint
(λ (f)
(einstein (frame (vect 0. 0.) (vect 1. 0.) (vect 0. 1.)))))
(paint
(λ (f)
(einstein (frame (vect 0.5 0.5) (vect 0.5 0.) (vect 0. 0.25)))))
If you want all the gory details of the actual representation used:
https://github.com/sicp-lang/sicp/blob/master/sicp-pict/main.rkt

Related

Why is racket passing #<void> to my function instead of the state?

I'm learning Racket, and using the book Realm Of Racket. I reached the point where they show you how to animate an image moving down the window, and then suggest you try modifying it to react to a left or right-arrow key press to move the image sideways.
Seemed simple enough...
#lang racket
(require 2htdp/universe 2htdp/image)
(define WIDTH 500)
(define DX 0)
(define HEIGHT 500)
(define IMAGE .) ; The image doesn't show up here
(define (add3-to-state current-state)
(+ current-state 3))
(define (draw-image current-state)
(place-image IMAGE (+ DX (/ WIDTH 2)) current-state (empty-scene WIDTH HEIGHT)))
(define (state-is-500 current-state)
(>= current-state 459))
(define (set-delta current-state key)
(set! DX (+ DX 10)))
(big-bang 0
(on-tick add3-to-state)
(on-key set-delta)
(to-draw draw-image)
(stop-when state-is-500)
)
When I run this, the image moves downwards as before, but as soon as I hit a key, I get an error...
>=: contract violation
expected: real?
given: #<void>
...in the state-is-500 function.
Anyone able to explain why this is happening? As far as I can see, my function for on-key has the same form as the ones they show in the book.
I tried modifying the state-is-500 function to look like this...
(define (state-is-500 current-state)
(printf "~a\n" current-state)
(>= current-state 459))
...and the output I got was...
102
105
#<void>
...before the error happened.
So it looks like #<void> is being passed to the function, but why?
Thanks
The issue is that big-bang expects the function call on-key to return the new state of the game. You are not retuning anything thus the frameworks reports <void>
Thus if the state does not change the you should just return the input state e.g.
(define (set-delta current-state key)
current-state)
Also this framework and Racket itself makes you want to not mutate variables, that is you don't assign to them, or at least you assign to them only once. Thus set! is not something you should use often.
In this case the state of the app that the book provides is just the vertical distance so is just a single number as shown in add3-to-state. The original state is passed in as the first parameter to big-bang.
The change you have to make is that the current state is not just the up-down movement but also the side to side. This movement shows up as the second parameter to place-image. So you have to have a state that can provide the second and third parameters to that.

Setting Both `fullheight` and `width` in Emacs on OS X

I find the default size of the Emacs frame a little too small. From reading around I know that I can set the height and width quite easily with something like the following:
;;; 140 x 60 window size
(setq default-frame-alist '((width . 140) (height . 60)))
Which works great on my external monitor, however it is a litte too big for the laptop display. I can solve the height problem by changing to the follwing:
;;; automatically set the height
(setq default-frame-alist '((fullscreen . fullheight)))
Which sets the frame to be as tall as possible for the current screen. I can't however set the width of the frame if I use this method. Adding (width . 140) to the above alist sets the width to the right value but also sets the height to the default height again.
When I see the frame appear it sets itself to the full height, and then sets the width to the value I requested, and shrinks in height.
I can overcome this problem with the following code:
;;; Full height for the default window
(setq default-frame-alist
'((fullscreen . fullheight)))
;; Set the width in a hook and have all windows inherit
(setq frame-inherited-parameters
'(width height))
(add-hook 'after-init-hook
(lambda ()
(set-frame-parameter nil 'width 140)))
Which uses a hook to set the width of the first frame to the value I want, and then sets all other windows to inherit this value.
This isn't very elegant however, so the question is "how can I accomplish this in a simpler (or less hackish) way?".
If you want to see my exact init.el script, take a look at this gist
TL;DR
How can I set both the width of a frame, and set the frame to be as tall as possible on the current monitor, on OS X? It seems you can't specify (width . 140) and (fullscreen . fullheight) in the default-frame-alist.
I have come up with a solution to this. I explicitly calculate the height of the window rather than relying on (fullscreen . fullheight) to do it for me.
The updated code to set the values for the height and width is quite simple:
;;; Nice size for the default window
(defun get-default-height ()
(/ (- (display-pixel-height) 120)
(frame-char-height)))
(add-to-list 'default-frame-alist '(width . 140))
(add-to-list 'default-frame-alist (cons 'height (get-default-height)))
In this code the subtraction of 120 from the height of the screen makes sure that the height of the window takes into account the height of the dock and the menubar. For correct results you will have to make sure that this code is executed after you have chosen the font face to use, otherwise the computed height value will not be valid.
Placing the height calculation in its own function should allow special casing certain operating systems and versions. This method also has the added advantage that is faster to open the window as it doesn't "animate" the height to the full height value.
The last paragraph of the help text for display-pixel-height is:
For graphical terminals, note that on "multi-monitor" setups this
refers to the pixel height for all physical monitors associated
with DISPLAY. To get information for each physical monitor, use
‘display-monitor-attributes-list’.
What got me to this page is what looks like a bug in the X11 implementation but I'm not sure yet. In any case, display-pixel-height works only often but not always.
Sample output from display-monitor-attributes-list is:
(
(
(geometry 0 0 1920 1080)
(workarea 0 25 1920 1055)
(mm-size 478 268)
(frames #<frame *scratch* 0x14489a030>)
(source . "NS")
)
(
(geometry 192 1080 1512 982)
(workarea 192 1080 1512 950)
(mm-size 301 195)
(frames)
(source . "NS")
)
)
In my case, I have a laptop (bottom entry) and a monitor connected to it (the top entry).
One possible solution would be to go through the list, find the monitor with the largest height and do the computations based upon that height and then at the end also do something like (set-frame-position nil 192 1080) where the two coordinates come from the top and left coordinates (the first two values of geometry and work area of the monitor that has the greatest height.
It appears that the workarea is the more prudent set of values to use.
And to further make a robust solution, a hook should be added to window-configuration-change-hook so that when a monitor is added or removed, things will get updated.
I am currently asking some questions on the Emacs developers mailing list and working on a solution for myself. I plan to return and update this entry when I have a solution that I'm happy with but thought this information may be of use to others as is.
Update:
There is no bug. x-display-pixel-height has various X11 rude facts of life. For more details, see this reply.
The "Frame Layout" node in the info documentation for ELisp as a description of the Inner and Outer Frame along with many other concepts that are pertinent to this question.
Here is my current solution. I have not done the hook yet. I don't claim to know how to program in lisp but this code is working for me.
(defun workarea-height ( monitor )
"MONITOR is an entry from `display-monitor-attributes-list' The
height entry (4th value) of the 'workarea' is returned"
(nth 4 (assoc 'workarea monitor)))
(defun monitor-with-largest-height-helper ( a b )
"Compares the height of the workarea of two monitor entries such as
those contained in the output of `display-monitor-attributes-list'"
(let* ((a-height (workarea-height a))
(b-height (workarea-height b)))
(if (> a-height b-height)
a
b)))
(defun monitor-with-largest-height ()
"Returns the monitor entry from `display-monitor-attributes-list'
with the largest 'workarea' height"
(cl-reduce #'monitor-with-largest-height-helper
(display-monitor-attributes-list)))
(defun largest-monitor-height ()
"Returns the usable height in lines of the largest monitor currently
attached"
(let* ((largest-monitor (monitor-with-largest-height)))
(/ (- (workarea-height largest-monitor)
(- (frame-outer-height)
(frame-inner-height)))
(frame-char-height))))
(defun my-resize-frame-height ()
"Resizes the current frame to the full height of the largest monitor
currently attached."
(interactive)
(set-frame-height nil (largest-monitor-height)))
The other work left to do is to make sure the left and top of the frame are within the area of the largest monitor to the frame will be displayed on that monitor.

Dr Racket get pixmap width/height

I'm working on a project for university and was wondering if it is possible to get the height and width of a pixmap in some way. I know it is possible for rectangles and circles and stuff...
I'm using this to draw the pixmap, file is a jpg:
(define (draw-image! x y file)
(let ((posn (my-make-posn x y)))
((draw-pixmap MainWindow) file posn)))
Perhaps you already know this, but the library you're using is deprecated: in the manual, you'll see that it's part of the "Legacy Library."
Here's a simple program that loads a picture from a jpg, displays it, and prints its dimensions, using the 2htdp/image library:
#lang racket
(require 2htdp/image)
(define pic
(bitmap "/Users/clements/Pictures/Photo Booth Library/Pictures/Photo on 2012-02-12 at 10.53.jpg"))
pic
(image-height pic)
(image-width pic)
You'll probably have to update the path....

How to interactively read in two inputs and use them in a function call

I am currently taking a class to learn elisp so I have no experience with this language. I am trying to interactively read in two inputs (the width and length of a rectangle) and then use them to call a function to compute the area of the rectangle. The code I have is as follows:
(defun rectangle_Area(w l)
"Compute the area of a rectangle, given its width and length interactively."
(interactive "nWidth: ")
(interactive "nLength: ")
(setq area (rectangleArea w l))
(message "The rectangle's area is %f." area))
Currently I get a wrong number of arguments error.
Like I said, I have no previous experience... all I really need to know is how to store/read in two separate values using interactive.
Thank you for any help
C-hf interactive RET:
To get several arguments, concatenate the individual strings,
separating them by newline characters.
So we have:
(defun rectangle_Area(w l)
"Compute the area of a rectangle, given its width and length interactively."
(interactive "nWidth: \nnLength: ")
(setq area (rectangleArea w l))
(message "The rectangle's area is %f." area))

How to resize a buffer so it only takes a small part of the screen?

In Emacs how can I resize a buffer so it only takes a small part of the screen ?
Is there any way ?
I would like to have the src taking 70% of the screen and a file manager in the other 30%
Set width of current window on current frame to ~ 70%:
(window-resize nil (- (truncate (* 0.7 (frame-width))) (window-width)) t)
The other windows are shrunk automatically. If you want to adjust more than one it gets more difficult.
As command:
(defun window-resize-to-70-percent ()
(interactive)
(window-resize nil (- (truncate (* 0.7 (frame-width))) (window-width)) t))
Use separate window-manager frames for individual buffers (by default). Automatically shrink-fit the frames to fit the buffer content.
See One-On-One Emacs, in particular, libraries fit-frame.el and autofit-frame.el.