LTK Scrolled Frame Scrollbars Not Resizing - common-lisp

Ltk is proving very frustrating due to missing and sometimes incorrect documentation.
(You'll find that the button styling options don't work)
I'm trying to make a simple scrolled frame that contains NxN many buttons.
Unfortunately, the scroll bars never seem to "get it".
It would seem like a no brainer that when you shove too many things inside a container it provides a scrolling mechanism automatically. We've been doing this in TUIs and GUIs for a LONG time.
Can anyone fix the code given below? Bonus points if you can figure out how to colorize the buttons a mixture of colors.
<code>
(defun run-demo ()
(with-ltk ()
(wm-title *tk* "NxN Button Tray")
(set-geometry *tk* 480 320 0 0)
(let* ((sw (make-instance 'scrolled-frame :master *tk*)))
(dotimes (y 20)
(dotimes (x 20)
(let* ((b (make-instance 'button
:master (canvas sw)
:text (format nil "(~a,~a)" x y))))
(grid b x y))))
(pack sw))))
</code>
Here is a screenshot of the problem. The scrollbars refuse to see their internal widget needs scrolling.
Thank you greatly for taking a whack at it...
Sincerely,
Pixel_Outlaw

I'm sure others will come across the same problem.
The answer was to use the following (interior w) accessor.
I only found this by browsing archives of the mailing list.
Jury is still out on the color scheme though.
(defun run-demo ()
(with-ltk ()
(wm-title *tk* "NxN Button Tray")
(set-geometry *tk* 480 320 0 0)
(let* ((sw (make-instance 'scrolled-frame :master *tk*)))
(dotimes (y 20)
(dotimes (x 20)
(let* ((b (make-instance 'button
:master (interior sw) ;push inside here!
:text (format nil "(~a,~a)" x y))))
(grid b x y))))
(pack sw))))

Related

using a struct as property list to macro

I have a struct with :name and :value that I'd like to use as arguments to a macro. But I'm not sure how to tell lisp that.
I can write out the call like
(sxql:yield (sxql:set= :name "a" :value 1))
"SET name = ?, value = ?"
("a" 1)
But I'd like to use an already existing structure
(defstruct my-struct name value)
(setq x (make-my-struct :name "a" :value 1))
; #S(MY-STRUCT :NAME "a" :VALUE 1)
using answers from Common LISP: convert (unknown) struct object to plist?
I've made
(defun struct-plist (x)
"make struct X into a property list. ugly kludge"
(let* ((slots (sb-mop:class-slots (class-of x)))
(names (mapcar 'sb-mop:slot-definition-name slots)))
(alexandria:flatten
(mapcar (lambda (n) (list (intern (string n) "KEYWORD")
(slot-value x n)))
names))))
(setq p (struct-plist x)) ; (:NAME "a" :VALUE 1)
My naive attempts are
(sxql:set= p) ; error in FORMAT: No more argument SET ~{~A = ~A~^, ~}
(funcall 'sxql:set= p) ; SXQL:SET= is a macro, not a function.
(macroexpand (sxql:set= p)) ; error in FORMAT ...
I imagine this is an easy/fundamental lisp programming question. But I'm not sure how to ask it (or search for answers). I'm also hoping there is an better struct<->plist story than what I've stumbled across so far.
EDIT: In case this is really an xy-problem. I've used flydata:defmodel to create the struct and I want to insert to a database using the same model.
This is definitely an xy problem: unfortunately I don't understand y (flydata?) well enough to answer the y part.
Here's why what you are trying to do can't work however. Consider this code in a file being compiled:
(defstruct mine name value)
...
(sxql:set= <anything derived from mine>)
Compiling this file must satisfy two constraints:
It does not fully create the structure type mine (see defstruct);
It must macroexpand sxql:set=.
What these constraints mean is that sxql:set= can't know about the structure at the time it is expanded. So any trick which relies on information about the structure must make that information available at compile time.
As I said, I don't understand the y part well enough to understand what you are trying to do, but a hacky approach to this is:
write a wrapper for defstruct which stashes information at compile time (strictly: at macro-expansion time);
write a wrapper for sxql:set= which uses that information to expand into something which makes sense.
Here is a mindless wrapper for defstruct. Note that this is mindless: it can only understand the most simple defstruct forms, and even then it may be wrong. It exists only as an example.
(eval-when (:compile-toplevel :load-toplevel :execute)
(defvar *structure-information* '()))
(defmacro define-mindless-structure (name &body slots)
(assert (and (symbolp name)
(every #'symbolp slots))
(name slots)
"I am too mindless")
(let ((found (or (assoc name *structure-information*)
(car (push (list name) *structure-information*)))))
(setf (cdr found) (mapcar (lambda (slot)
(list slot (intern (symbol-name slot)
(find-package "KEYWORD"))
(intern (concatenate 'string
(symbol-name name)
"-"
(symbol-name slot)))))
slots)))
`(defstruct ,name ,#slots))
So now
(define-mindless-structure mine
name value)
Will expand into (defstruct mine name value) and, at macroexpansion time will stash some information about this structure in *structure-information*.
Now I stop really understanding what you need to do because I don't know what sxql:set= is meant to do, but it might be something like this:
(defmacro mindless-set= ((s o))
(let ((info (assoc s *structure-information*))
(ov (make-symbol "O")))
(unless info
(error "no information for ~A" s))
`(let ((,ov ,o))
(sxql:set= ,#(loop for (slot initarg accessor) in (cdr info)
;; the compiler will whine about slot annoyingly
collect initarg
collect `(,accessor ,ov))))))
So with this macro, assuming a suitable define-mindless-structure for mine form has been seen by the time the macro is expanded, then
(mindless-set= (mine it))
Will expand into
(let ((#:o it))
(set= :name (mine-name #:o) :value (mine-value #:o)))
But, as I said, I am not sure what the expansion you actually want is.
Finally, before even thinking about using anything like the above, it would be worth looking around to see if there are portability libraries which provide compile/macroexpansion-time functionality like this: there very well may be such, as I don't keep up with things.

Dynamically bound variable : revert to previous state

I'm trying to understand dynamical and lexical bindings of a variable.
I was browsing SO and some links, when I encountered a problem on this one :
https://www.emacswiki.org/emacs/DynamicBindingVsLexicalBinding#toc2
I ran this code :
(let ((a 1))
(let ((f (lambda () (print a))))
(let ((a 2))
(funcall f))))
With expected result : 1 (and a warning which says that the second a variable is unused, which is normal).
Next, I tried :
(defvar a 99)
And reran the first code. Result is 2, like the tutorial says. Then, to experiment further, I tried to remove the dynamically binding variable a, to get again 1.
I tried to (makunbound 'a) or even (setq a 55) (I tried this by default, I think global lexical binding depends on implementation if I understand correctly...). makunbound seems to remove the symbol, but the "dynamically binding state" seems to be saved anyway. The result is still 2.
How can I reset Common Lisp to the previous state (before I dynamically bind the a variable) ? Restart SLIME do the trick, but I would rather have a way to do it programatically...
Thank you for your answer.
There is no portable way to revert the
special
proclaimation.
(CLISP offers
notspecial).
However, you can use unintern
to some extent: it will make new code treat your symbol as not
special because it is now a different symbol:
(defun test-a ()
(let ((a 1))
(let ((f (lambda () (print a))))
(let ((a 2))
(funcall f)))))
(test-a)
==> 1
(defvar a)
(test-a)
==> 2
now, let us try to "revert" defvar:
(unintern 'a)
(test-a)
==> 2
oops! Let us see:
(fdefinition 'test-a)
#<FUNCTION TEST-A NIL (DECLARE (SYSTEM::IN-DEFUN TEST-A))
(BLOCK TEST-A
(LET ((#:A 1)) (LET ((F (LAMBDA NIL (PRINT #:A)))) (LET ((#:A 2)) (FUNCALL F)))))>
you see, test-a is still using the old symbol a which is now uninterned (so printed as #:A). To get back, you need to re-eval the defun above and then you get
(test-a)
==> 1
again!

Is it foolish to make alexandria:curry not necessarily use funcall?

Currently a function curried with Alexandria's curry must be called with funcall. However it is possible to set the new function's symbol-function so that we can do without it and treat it like a real function. Illustrated on https://lispcookbook.github.io/cl-cookbook/functions.html#with-the-alexandria-library:
(defun adder (foo bar)
"Add the two arguments."
(+ foo bar))
(defvar add-one (alexandria:curry #'adder 1) "Add 1 to the argument.")
(funcall add-one 10) ;; => 11
(setf (symbol-function 'add-one) add-one)
(add-one 10) ;; => 11
;; and still ok with (funcall add-one 10)
Is there a good reason not to allow both styles ? This looks quite interesting to me in this context of currying.
ps: I did ask on Alexandria's issue tracker some 3 weeks ago
pps: https://gitlab.common-lisp.net/alexandria/alexandria/blob/master/functions.lisp#L116
Based on your comment, and looking at the issue, yes it would be "foolish" to change curry so that it binds functions in the global namespace:
This would be a major change for curry, which would break existing code
A macro with this functionality would not mesh well with the spirit of Alexandria, as far as I know. This would be better suited for Serapeum, which happens to already define such a function, namely defalias. As you can see, the definition is a little more involved than using symbol-value. See also the documentation.
For reference, this simple macro does the job:
(defmacro defcurry (name function &rest arguments)
"Returns a regular function, created by currying FUNCTION with ARGUMENTS."
`(let ((closure (alexandria:curry ,function ,#arguments)))
(setf (symbol-function ,name) closure)))
Example:
(defun adder (x y) (+ x y))
(defcurry 'add2 #'adder 2)
(add2 3) ;; no "funcall" here
;; => 5"
edit: but… this is much simpler:
(defun add2 (a)
(adder 2 a))

What does this self referencing code do?

What is this self reference for?
Could it be written in any other way?
Is there any advantage?
(defmacro sublet (bindings% &rest body)
(let ((bindings (let-binding-transform
bindings%)))
(setq bindings
(mapcar
(lambda (x)
(cons (gensym (symbol-name (car x))) x))
bindings))
`(let (,#(mapcar #'list
(mapcar #'car bindings)
(mapcar #'caddr bindings)))
,#(tree-leaves
body
#1=(member x bindings :key #'cadr)
(caar #1#)))))
It's just a way of reusing structure somewhere else. In the macro you have:
(tree-leaves body
#1=(member x bindings :key #'cadr)
(caar #1#))
Which is just a fancy way of writing:
(tree-leaves body
(member x bindings :key #'cadr)
(caar (member x bindings :key #'cadr)))
On the positive side if you correct a bug in the member form you'll fix it both places, but it's runs the same code twice so if member was expensive this wouldn't be the wise way to do it. However it is a macro, thus run at compile time, and member is fairly fast on mall lists (small == millions of elements or below) so I guess it won't matter if you read the references just as good as any other CL code. An alternative and perhaps more readable for other kind of lispers would be:
(let ((found (member x bindings :key #'cadr)))
(tree-leaves body found (caar found)))

Avoiding mutable state when I need to store (current-seconds) multiple times

I've put together the following rudimentary stopwatch in Racket (just learning now, the final aim is a pomodoro-timer).
#lang racket
(define start-time 0)
(define end-times '())
(define (start);; stores start-time
(set! start-time (current-seconds)))
(define (lap);; stores "laps" in list
(set! end-times (cons (current-seconds) end-times)))
(define (stop);; stores final time, displays lap-times in h, m, s and resets end-times
(begin
(set! end-times (cons (current-seconds) end-times))
(display
(reverse
(map (lambda (an-end)
(let ((the-date (seconds->date(- an-end start-time))))
(list
(sub1(date-hour the-date))
;; sub1 is needed because (date-hour(seconds->date 0) = 1
(date-minute the-date)
(date-second the-date)))) end-times)))
(set! end-times '())
))
While this does exactly what it should, I was wondering how I could avoid mutable state. If I follow HTDP, this is the kind of situation where mutable state is warranted, but after browsing Wadler's "Monads for Functional Programming", I'm still curious about how I could do without set!.
I know that to make it functional, I should add arguments to my functions. For instance, start would become
(define (start [now (current-seconds)])
now)
and a similar approach could work with lap and stop.
Still, while I know that after adding additional arguments to restore functionality, I should also pass arguments rather than storing values in variables, I don't see how in this case I can leverage this to avoid set! as well.
Update: Since all three answers below are highly valuable (thanks!), I didn't mark any of them as the unique correct one. Below is the minimal solution to my initial question. It is a combination of the loop-proposal of #Metaxal, with the example-usage of #Greg Hendershott.
#lang racket
(define (run)
(displayln "Enter 'lap' or 'quit':")
(let loop ([t0 (current-seconds)] [times '()])
(match (read-line)
["quit" (reverse
(map (lambda (x)
(let ((the-date (seconds->date x)))
(list
(sub1(date-hour the-date))
(date-minute the-date)
(date-second the-date)))) times))]
["lap" (loop t0 (cons (- (current-seconds) t0) times))]
[_ (loop t0 times)])))
What will likely happen in the following of your program is that you will have a loop.
Then this loop can be a function that takes as input the whole current state, and when you want to update its state, just call the loop again with the new state (you may also call the loop again with the same exact state of course).
Simplified example:
(define (loop [t0 (current-seconds)] [times '()])
;; ... do things here, possibly depending on user input ...
;; then loop with a new state:
(cond [<some-start-condition> (loop (current-seconds) '())]
[<some-lap-condition> (loop t0 (cons (- (current-seconds) t0) times))]
[<some-stop-condition> times])) ; stop, no loop, return value
This certainly changes the approach to your design though.
It's harder to use this approach when designing GUI programs, because the event loop often prevents you from (or makes it difficult) passing values from one event to the next.
However, in Racket, there is (the pedagogical, but still very good) big-bang that is made just for that.
In this case using set! is justified and hard to avoid, because we must "remember" state between invocations of the procedures. What we can do is improving the encapsulation of state, by hiding the variables that change inside a procedure and using a message dispatcher for accessing the procedures that refer to the mutable state. This is very similar to what we do with object-oriented programming, but only lambdas are required to implement it!
(define (make-timer)
; the "attributes" of the object
(let ([start-time 0]
[end-times '()])
; the "methods" of the object
(define (start)
(set! start-time (current-seconds)))
(define (lap)
(set! end-times (append end-times (list (current-seconds)))))
(define (stop)
(lap)
(display
(map (lambda (an-end)
(let ((the-date (seconds->date (- an-end start-time))))
(list
(sub1 (date-hour the-date))
(date-minute the-date)
(date-second the-date))))
end-times))
(set! end-times '()))
; return a dispatch procedure
(lambda (msg)
(case msg
((start) (start)) ; call the start procedure defined above
((lap) (lap)) ; call the lap procedure defined above
((stop) (stop)) ; call the stop procedure defined above
(else (error "unknown message:" msg))))))
I took the liberty of modifying some of your procedures to make them a bit simpler. Here's how we would use the timer object we just created:
(define timer (make-timer))
(timer 'start)
(sleep 1)
(timer 'lap)
(sleep 1)
(timer 'lap)
(sleep 1)
(timer 'lap)
(sleep 1)
(timer 'stop)
=> ((18 0 1) (18 0 2) (18 0 3) (18 0 4))
This technique is called "message passing", learn more about it in the wonderful SICP book.
For a simple example like this, I would probably do what #Metaxal
suggested.
However another approach is that you could explicitly define the state
as a struct:
(struct state (start-time end-times))
Then change the start, lap, and stop to be functions on state:
;; start : -> state
;; stores start-time
(define (start)
(state (current-seconds) '()))
;; lap : state -> state
;; stores "laps" in list
(define (lap st)
(match-define (state start-time end-times) st)
(state start-time
(cons (current-seconds) end-times)))
;; stop : state -> list
;; stores final time, displays lap-times in h, m, s
(define (stop st)
(match-define (state start-time end-times*) st)
(define end-times (cons (current-seconds) end-times*))
(reverse
(map (lambda (an-end)
(let ((the-date (seconds->date(- an-end start-time))))
(list
(sub1(date-hour the-date))
;; sub1 is needed because (date-hour(seconds->date 0) = 1
(date-minute the-date)
(date-second the-date)))) end-times)))
As in #Metaxal's answer, your "main loop" needs to handle the state and "thread" it through the functions as appropriate:
Example usage:
(define (run)
(displayln "Enter 'lap' or 'quit':")
(let loop ([st (start)])
(match (read-line)
["quit" (stop st)]
["lap" (loop (lap st))]
[_ (loop st)])))
Whereas #Óscar López's answer shows a style of OOP as explained in SICP.
A nice thing about Racket (and Scheme) is that you can choose whatever approach on the spectrum you think best fits the problem at hand, and your taste -- simple imperative, OOP imperative, pure functional.

Resources