currently, when I am experimenting the continuation in functional languages, my understanding is that a continuation records the current program counter and register files, and when a continuation is returned, then the PC and the registered files will be restored to the values it has recorded.
So in the following dumb example from Might's blog post,
; right-now : -> moment
(define (right-now)
(call-with-current-continuation
(lambda (cc)
(cc cc))))
; go-when : moment -> ...
(define (go-when then)
(then then))
; An infinite loop:
(let ((the-beginning (right-now)))
(display "Hello, world!")
(newline)
(go-when the-beginning)) ; here the-beginning continuation passed to go-when, which ultimately will have an continuation applied to an continuation, that returns a continuation, which will cause the the program point resumed to the PC and registers states recorded in it.
I am not sure my understanding right.. Please correct me if you think it is not.....
Program counter and register files are not what the continuation records.
The best way to describe the meaning of call-with-current-continuation is that it records the program context. For instance, suppose you're evaluating the program
(+ 3 (f (call-with-current-continuation g)))
In this case, the context of the call-with-current-continuation expression would be
(+ 3 (f [hole]))
That is, the stuff surrounding the current expression.
Call-with-current-continuation captures one of these contexts. Invoking a continuation causes the replacement of the current context with the one stored in the continuation.
The idea of a context is a lot like that of a stack, except that there's nothing special about function calls in contexts.
This is a very brief treatment. I strongly urge you to take a look at Shriram Krishnamurthi's (free, online) book PLAI, in particular Part VII, for a more detailed and careful look at this topic.
Related
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.
a go block returns a channel and not the return value, so how can one extract the return value in a go block, when cljs doesn't have <!!?
For example, given the following code:
(go (let [response (<! (http/get "https://api.github.com/users"
{:with-credentials? false
:query-params {"since" 135}}))]
(:status response)))
will return a channel but not (:status response). How to make this go block return a (:status response)?
<!! doesn't exist in javascript because the runtime does not support it. Javascript is single-threaded and <!! is a blocking operation. Blocking the main thread in a browser-based environment is a bad idea as it would simply freeze all javascript actions (and potentially freeze the whole page) until unblocked.
Instead, consider using clojure.core.async/take! like so:
(take! channel (fn [value] (do-something-with value)))
I am badly in a need to use mouse-events directly
Is it possible to get the mouse-event without using big bang ?
i.e I want to build a function like the following:
(define (check-if-button-down mev) (mouse=? mev "button-down"))
But for getting mev, the input is being fed from on-mouse of bigbang
About me :
I am new to racket programming
Short answer: not really.
However: the big bang model calls your mouse event handler when a mouse event occurs, so if you want to know whether the mouse button is pressed, your world state should include a boolean indicating whether the mouse button is pressed, and your mouse event handler should return a world state that updates this boolean correctly.
Is there some reason this architecture doesn't work for you?
If this is a student project, you may have to stick with what big-bang offers (see John Clements' answer).
But if you can use racket/gui (either as a language #lang racket/gui or as an additional (require racket/gui)), then you are looking for get-current-mouse-state.
For example
#lang racket
(require racket/gui)
(define (mouse-button-down?)
(define-values (pt state)
(get-current-mouse-state))
(if (or (memq 'left state)
(memq 'right state)
(memq 'middle state))
#t
#f))
I need the way to store some data globally in Clojure. But I can't find the way to do that. I need to load some data in runtime and put it to a global pool of objects, to manipulate with it later. This pool should be accessed inside some set of functions to set/get data from it like a some sort of small in-memory database with hash-like syntax to access.
I know that it might be bad pattern in functional programming, but I don't know other way to store dynamic set of objects to access/modify/replace it in runtime. java.util.HashMap is some sort of solution, but it couldn't be accessed with sequence functions and I miss flexibility of Clojure when I need to use this kind of collection. Lisps syntax are a great, but it's a bit stucks on purity even if developer doesn't need it in some places.
This is the way I want to work with it:
; Defined somewhere, in "engine.templates" namespace for example
(def collection (mutable-hash))
; Way to access it
(set! collection :template-1-id (slurp "/templates/template-1.tpl"))
(set! collection :template-2-id "template string")
; Use it somewhere
(defn render-template [template-id data]
(if (nil? (get collection template-id)) "" (do-something)))
; Work with it like with other collection
(defn find-template-by-type [type]
(take-while #(= type (:type %)) collection)]
Have someone a way I can use for tasks like this? Thank you
Have a look at atoms.
Your example could be adapted to something like this (untested):
; Defined somewhere, in "engine.templates" namespace for example
(def collection (atom {}))
; Way to access it
(swap! collection assoc :template-1-id (slurp "/templates/template-1.tpl"))
(swap! collection assoc :template-2-id "template string")
; Use it somewhere
(defn render-template [template-id data]
(if (nil? (get #collection template-id)) "" (do-something)))
; Work with it like with other collection
(defn find-template-by-type [type]
(take-while #(= type (:type %)) #collection)]
swap! is how you can updated the value of an atom in a thread-safe manner. Additionally note that references to collection above have been prepended by the # sign. That is how you get the value contained in an atom. The # sign is short for (deref collection).
The equivalent in a procedural language (e.g. in Java) would be local variables (or instance variables) declared outside of a loop whose contents use and update them. How can I do that in Erlang?
You pass the state as parameters in the recursive call. Example loop that receives N Msgs and returns them as a list:
loop(N) ->
loop(N, 0, []).
loop(N, Count, Msgs) when Count < N ->
receive
Msg -> loop(N, Count+1, [Msg|Msgs])
end;
loop(_, _, Msgs)
list:reverse(Msgs).
I hope it wasn't homework question but I'm confused with "two ways" in subject.
The most proper way, of course, is to extend recursive function definition with at least one argument to carry all needed data. But, if you can't use it, and you are sure only one instance of such recursive cycle will be in effect in a moment (or they will be properly stacked), and function invocations are in the same process, then process dictionary will help you. See put() and get() in erlang module, and invent unique terms to be used as keys. But this is definitely a kind of hack.
One could invent more hacks but all them will be ugly.:)