How to change a Hunchentoot session cookie name by specializing a function? - common-lisp

I'm using Hunchentoot and would like to change the name of the session cookie. This is implemented with a generic function and the docs say to change the name you can "specialize the function".
I'm not really sure what this means here. I was under the impression that specializing a function is to dispatch a method on certain argument types. In this particular case, the function takes the server acceptor and I don't want to change that. Can someone illuminate me on this?
The API: http://weitz.de/hunchentoot/#session-cookie-name
Here's the implementation in the source:
(defgeneric session-cookie-name (acceptor)
(:documentation "Returns the name \(a string) of the cookie \(or the
GET parameter) which is used to store a session on the client side.
The default is to use the string \"hunchentoot-session\", but you can
specialize this function if you want another name."))
(defmethod session-cookie-name ((acceptor t))
"hunchentoot-session")

Make a subclass and specialize that way:
(defclass my-acceptor (hunchentoot:acceptor) ())
(defmethod session-cookie-name ((acceptor my-acceptor))
"my-session")
The function still takes an acceptor, it's just your kind of acceptor, now.

Related

If generic functions work well alone, what is the value of defclass?

I read a lot about generic functions in CL. I get it. And I get why they are valuable.
Mainly, I use them for when I want to execute a similar action with different data types, like this:
(defgeneric build-url (account-key)
(:documentation "Create hunter api urls"))
(defmethod build-url ((key number))
"Build lead api url"
(do-something...))
(defmethod build-url ((key string))
"build campaign api url"
(do-somthing... ))
In this example, campaign-url and lead-url are structures (defstruct).
My question is, at a high level, how do classes add value to the way generic functions + structures work together?
Structures historically predate classes, are more restricted and more "static" than classes: once a structure is defined, the compiler can generate code that accesses its slots efficiently, can assume their layout is fixed, etc. There is a lot of inlining or macro-expansion done that makes it necessary to rebuild everything from scratch when the structure changes. Being able to redefine a struct at runtime is not something defined by the standard, it is merely implementations trying to be nice.
On the other hand, classes have more features and are easier to manipulate at runtime. Suppose you write this class:
(defclass person ()
((name :initarg :name :reader .name)))
And you instantiate it:
(defparameter *someone* (make-instance 'person :name "Julia O'Caml"))
It is possible now to update the class definition:
(defparameter *id-counter* 0)
(defun generate-id ()
(incf *id-counter*))
(defclass person ()
((name :initarg :name :reader .name)
(dob :initarg :date-of-birth :reader .date-of-birth)
(%id :reader .id :initform (generate-id))))
And now, *someone*, which existed already, has two additional fields, dob that is unbound, and %id that is automatically initialized to 1. There is a whole section about Object Creation and Initialization (7.1) that defines how objects can be redefined, change class, etc.
Moreover, this mechanism is not fixed, a lot of the steps described above rely on generic functions. It is possible to define how an object is allocated, initialized, etc. The concept was standardized as what is known as the Meta-Object Protocol, which also introduces the concept of metaobject, the object representing a class: usually a class has a name, parent classes, slots, etc. but you can add new members to a class, or change how instance slots are organized (maybe your just need a global handle and a connection, and the actual instance slots are stored in another process?).
Note also that once CLOS/MOP was defined, it was also eventually possible to define structures in this framework: in the standard , defstruct (without a :type option) defines classes with a structure-class metaclass. Still, they do not behave like standard-class because as said above they are more restricted, and as such are subject to more aggressive compilation optimizations (in general).
Structures are nice if you need to program like in C and you are ok with recompiling all your code when the structure changes. It is however premature optimization to use them in all cases. It is possible to use a lot of standard objects without noticing much slowness nowadays (a bit like Python).

Assigning Spotify window to a group in StumpWM

I am currently starting to set up stumpwm, and I would like to assign a specific window to a particular group.
So far I have this:
(define-frame-preference "Spotify"
(0 t t :class "Spotify")
)
So essentially, I would expect that that would set the windows with the class Spotify to the group Spotify, this however does not happen.
Can anybody help me on this?
Thank you!
The relationship between X11 windows and Linux processes is thin: things are asynchronous, you start a process and some time later zero, one or more windows are created.
You have to work with callbacks, there is no easy way to create a process and synchronously have all its windows in return.
Some processes are nice enough to set the _NET_WM_PID property on windows (it looks like the "Spotify" application does it). You can retrieve this property as follows:
(first (xlib:get-property (window-xwin w) :_net_wm_pid))
Placement rules cannot help here, given how Spotify fails to set the class property early enough (see comments and other answer). But you can use a custom hook:
STUMPWM-USER> (let ((out *standard-output*))
(push (lambda (&rest args) (print args out))
*new-window-hook*))
(#<CLOSURE (LAMBDA (&REST ARGS)) {101A92388B}>)
Notice how I first evaluate *standard-output* to bind it lexically to out, so that the function can use it as a stream when printing informations. This is because the hook might be run in another thread, where the dynamic binding of the standard output might not be the one I want here (this ensures debugging in done in the Slime REPL, in my case).
When I start for example xclock, the following is printed in the REPL:
(#S(TILE-WINDOW "xclock" #x380000A))
So I can change the hook so that instead if does other things. This is a bit experimental but for example, you can temporarily modify the *new-window-hook* to react on a particular window event:
(in-package :stumpwm-user)
(let ((process (sb-ext:run-program "xclock" () :search t :wait nil))
(hook))
(sb-ext:process-kill process sb-unix:sigstop)
(flet ((hook (w)
(when (find
(sb-ext:process-pid process)
(xlib:get-property (window-xwin w) :_net_wm_pid))
(move-window-to-group w (add-group (current-screen) "XCLOCK"))
(setf *new-window-hook* (remove hook *new-window-hook*)))))
(setf hook #'hook)
(push #'hook *new-window-hook*))
(sb-ext:process-kill process sb-unix:sigcont))
Basically: create a process, stop it to minimize race conditions, define a hook that checks if the PID associated in the client matches the one of the process, execute some rules, then remove the hook from the list of hooks. This is fragile, since if the hook is never run, it stays in the list, and in case of errors, it also stays in the list. At the end of the expression, the hook is added and the process resumes execution.
So it seems like, as pointed out by coredump, the are issues in the way the Spotify window is defined.
As an alternative, there are fortunately plenty of ways to control spotify via Third Party Clients (ArchWiki)
Personally, I found that you can control spotify via Ivy on Emacs thanks to this project
Ivy Spotify and this will probably be what I will use.

Creating a JavaFX proxy causes a UnsupportedOperationException

I'm trying to write a JavaFX app in Clojure. As a simple test, I wanted to try to just launch a Hello World. To extend Application, I decided to try using proxy instead of :gen-class. I wanted to be able to create a bare-bones function that creates an Application, instead of requiring me to write the boilerplate every time.
The simple example I came up with was:
(let [^Application app
(proxy [Application] []
(start [self stage] (println "Hello World")))]
(Application/launch ^Class (.getClass app)
(into-array String [])))
The problem is, this causes an UnsupportedOperationException:
UnsupportedOperationException start chat.graphics_tests.javafx_wrapper.proxy$javafx.application.Application$ff19274a.start (:-1)
It seems like it can't find the start method that I implemented. My first thought was that the arguments to start were wrong. They seem correct though. The first argument it receives is "this", then the primary stage. I tried different numbers of arguments though, and I still get the same error. According to the docs:
If a method fn is not provided for an interface method, an
UnsupportedOperationException will be thrown should it be
called.
Which further my this suspicion.
The errors quite vague. Does anyone see what the problem is?
When writing proxy class definitions in Clojure you do not need the explicit self parameter in the method signature. The current instance will be implicitly bound to this which you will be able to use inside the methods.
Therefore your proxy call should look like this:
(proxy [Application] []
(start [stage] (println "Hello World")))
This appears to be because Application/launch requires a named class, which proxy doesn't create. (see the comment at the bottom of the answer. I'm trusting #Sam here).
I ended up caving and using :gen-class, and got it working after some fiddling.

How to change class's metaclass

This happens to me time and again: I define the class and forget that I wanted it funcallable or it is, say, Gtk widget class, thus it's metaclass needs to be stated. Once it is defined, however, SBCL doesn't let me change me the metaclass (even if there is no instance of this class). For example, evaluating
(defclass foo ()
((slot-a)))
and then adding a metaclass and re-evaluating:
(defclass foo ()
((slot-a))
(:metaclass gobject:gobject-class))
results in error:
Cannot CHANGE-CLASS objects into CLASS metaobjects.
[Condition of type SB-PCL::METAOBJECT-INITIALIZATION-VIOLATION]
See also:
The Art of the Metaobject Protocol, CLASS [:initialization]
Unfortunately I don't have a copy of The Art of the Metaobject Protocol to check what it says. For now the only way I could figure out is to restart lisp, which can be quite disruptive.
Since I realise the error soon enough, I don't mind dodging the defined class completely by removing it. Questions:
If I have created instances of the class, is there a way to find them to nullify them and get them GCed?
How to remove the class? Something like fmakunbound for functions.
Unfortunately I don't have a copy of The Art of the Metaobject Protocol to check what it says.
Even though I recommend reading the book, you can find some information online. See for example ENSURE-CLASS-USING-CLASS.
How to remove the class?
You can use (SETF FIND-CLASS):
(setf (find-class 'foo) nil)
Or, you can use the fancy slime inspector. You call slime-inspect-defintion while pointing the name of the class. Then, you'll see the name. When you select it, you inspect the symbol naming your class. Then, you can see something like:
It names the class FOO [remove]
Provided FOO only names a class, you can use the bigger hammer:
(unintern 'foo)
If I have created instances of the class, is there a way to find them to nullify them and get them GCed?
No, only the GC has the global view, and for practical reasons, it doesn't generally keep backward references about who references a particular object (and how)1.
There is no global record of all instances of a class unless you introduce your own (weak) hash-table to store them. But if you have kept a record of all of your instances, you can CHANGE-CLASS them. For example, you define:
(defclass garbage () ())
... any previously held reference in your object will be released and the GC has an opportunity to dispose of objects your instances where referencing. And when another object reference an instance of 'garbage, you can update it. Instead of using 'garbage, you could probably change instances of old classes to your new class (the name is the same, but the class object is different).
Note also that CHANGE-CLASS is a generic function.
1. Implementations might offer heap walkers. See for example Heap walkers in Allegro CL.

Do monads have fluent interfaces?

Forgive me if this question seems stupid, but I'm quite new to the whole world of functional programming so I'll need some denizens on StackOverflow to set me straight.
From what I gather, an operation on a monad returns a monad. Does this mean that monads have a fluent interface, whereby each function that is applied on a monad returns that monad after it applies some operation to the variable it wraps?
Presumably you're referring to the bind operator associated with monads, wherein one can start with a monadic value, bind it to a monadic function, and wind up with another monadic value. That's a lot like a "fluent method" (or a set of such making up a "fluent interface") that returns a "this" pointer or reference, yes, but what you'd be missing out on there is that the monadic function need not return a monadic value that's the same type as the input value. The fluent method convention is to return the same type of value so as to continue chaining calls that are all valid on the instance (or instances) being prepared.
The monadic bind operator signature looks more like this:
M[a] -> (a -> M[b]) -> M[b]
That is, the "return value" is possibly of a type different from to the first input value's type. It's only the same when the provided function has the type
(a -> M[a])
It all depends on the type of the monadic function—and, more specifically, the return type of the monadic function.
If you were to constrain the domain of the monadic functions you'd accept to those that return the same type as the monadic value supplied to the bind operator, then yes, you'd have something that behaves like a fluent interface.
Based on what I know about fluent interfaces, they are mostly about making the code "read nicely" by using method chaining. So for example:
Date date = date()
.withYear(2008)
.withMonth(Calendar.JANUARY)
.withDayOfMonth(15)
.toDate();
A Haskell do-notation version of it (using an imaginary date api) could look like:
do date
withYear 2008
withMonth JANUARY
withDayOfMonth 15
toDate
Whether or not this or other do-notation based DSLs like it qualify as a "fluent interface" is probably up for discussion, since there is no formal definition of what a "fluent interface" is. I'd say if it reads like this then it's close enough.
Note that this isn't exactly specific to monads; monads CAN have a fluent interface if you don't require method calling, but that would depend on the function names and the way the API is used.

Resources