In order to run a CLIM UI, the generic function clim:run-frame-top-level must be invoked, however this function blocks until the UI exits. This would seem to require all application control be handled via the CLIM top level.
Is it possible to structure an application differently such that a control-flow outside of the CLIM top level is established and which simply interacts with the application-frame as needed?
Most Common Lisp implementations that support CLIM have a way to run functions as a separate thread (usually called a PROCESS in Lisp).
In many Common Lisp implementations this function is called PROCESS-RUN-FUNCTION. See the documentation of your Lisp.
CLIM itself has a function MAKE-PROCESS. This is implementation independent and works on CLIM implementations on top of a multithreaded Lisp like Allegro CL, LispWorks, MCL, Genera, ...
Something like (example in the CLIM-USER package).
(make-process (lambda () (run-frame-top-level ...)))
should run the toplevel in its own thread.
This would allow you to run multiple frames, have other Lisp processes with REPLs, etc.
Related
There are contexts like coming across a scheme library that I'd like to play around with or reuse in Julia, or implementing a recursive algorithm that could benefit from tail call optimization, etc. Assuming the scheme file is perfectly compatible with femtolisp, how can the scheme file be used from within Julia code?
Currently, I'm developing 2 web-based tools for my own need with hunchentoot.
Before starting hunchentoot, I want to set some special variable with let so there values will be available while hunchentoot is running.
Like :
(let ((*db-path* "my-db-file"))
(start-hunchentoot))
But, once the handlers get invoiced, they don't seam to be in the let anymore and db-path falls back to its global state (which is nil).
At the moment I'm resolving this by writing the let in every handler.
But, I want a more general approach so I will be able to run both applications with different db-path in one run-time.
Is it possible to set db-path in a way so it will be valid for one instance of hunchentoot and not the other?
The used environment is SBCL 1.2.4 on Debian Jessie.
Around method
Adding db-path as a slot in the acceptor might be a suitable option. However, you can also write an around method for handle-request. Assuming *my-acceptor* is globally bound:
(defmethod hunchentoot:handle-request :around ((acceptor (eql *my-acceptor*)) request)
(let ((*db-path* "my-db-file"))
(call-next-method)))
Of course, you don't need to specialize with EQL, you can define your own subclass instead. The advantage of an around method over storing a configuration variable in the class instance is that you keep the benefits of using special variables, i.e. bindings are visible from everywhere in the dynamic scope.
Here is what the documentation string, visible on Lispdoc, says about handle-request (emphasis mine):
This function is called once the request has been read and
a REQUEST object has been created. Its job is to actually handle the
request, i.e. to return something to the client.
Might be a good place
for around methods specialized for your subclass of ACCEPTOR which
bind or rebind special variables which can then be accessed by your
handlers.
I encourage you to read Hunchentoot's documentation.
Special variables and threads
The behavior you observe is because:
The server is running in another thread.
Dynamic bindings are local to each thread, as explained in the manual:
The interaction of special variables with multiple threads is mostly as one would expect, with behaviour very similar to other implementations.
global special values are visible across all threads;
bindings (e.g. using LET) are local to the thread;
threads do not inherit dynamic bindings from the parent thread
If you make your own threads, you can build a closure which binds variables as you want. You can also rely on the portable bordeaux-threads library which takes a list of bindings to be effective inside a thread.
We know that pure functions:
Always return the same result for a given input
Produce no side-effects
This leads us to referential transparency - where an expression can be replaced with a value without changing the behaviour of the program.
This tells us that a program can be said to be purely functional if it excludes destructive modifications (updates) of entities in the program's running environment.
This commentator wrote:
grappling with what "pure" in an FP setting actually means, considering application itself is a protocol for mutation (the stack)
My question is: What does 'pure' in functional programming mean if an application mutates the stack?
The fact that the function mutates the stack is a consequence of the implementation of the machine. It doesn't matter for defining pure, just as the fact that using a 'value' requires mutating a register in the processor core doesn't matter.
If a function doesn't mutate (or depend on) anything external to its own stack frame (e.g. global variables, io, randomness), it can still be viewed as pure.
Can functions that take non-pure functions as arguments be considered pure if they do not change/store state directly, don't reference global variables etc?
Where and how do we draw the line on what is pure and what is not, is it solely on the function's in question code or do we take into account the effects of invoking the arguments?
E.g. imagine this scenario, where the pure function represents a stateless workflow and takes as arguments a few actions to be executed during this workflow. One of these actions changes some state somewhere. So if I'm looking strictly at the implementation of my workflow, it seems pure, but eventually it does modify state by invoking this parameter function that modifies state.
I'm tempted to speculate the workflow is also non-pure, but passing in a different argument that does not change state will make it pure, so I'm confused.
Any help will be much appreciated. Thank you.
(define (its-not-me launch-rockets)
(lambda ()
(launch-rockets)))
is indeed pure. It doesn't launch rockets, it just constructs a computation that will, if called. But no side effects are caused by merely constructing such computation.
(define (it-is-me launch-rockets)
(launch-rockets)
((its-not-me launch-rockets)))
does indeed launches the rockets, twice. Whether directly or indirectly, doesn't matter. If it causes side effects during its execution, it causes side effects during its execution.
And if we have
(define (launch-rockets)
(if (prime? (random-integer))
(do-actually-launch-rockets)
(list 'do-nothing)))
nothing changes. The first is still pure, constructing a computation which is potentially causing side-effects, is impure.
Even
(define (launch-rockets)
(if (prime? (random-integer))
(list 'i-am-only)
(list 'kidding)))
isn't a pure function, as it uses a non-pure effect, the randomness. Pure functions always return same result for the same arguments.
The R7RS report on the programming language Scheme describes two ways of running Scheme code in a Scheme system:
1) A scheme system can run a program as described in section 5.1 in the report.
2) A scheme system can offer a read-eval-print-loop, in which Scheme code is interpreted interactively.
My question is on how these two ways of running Scheme code can be reflected inside a Scheme system with what's included in the R7RS report.
There is the eval library procedure eval, which executes Scheme code inside a running Scheme system so eval looks like what I am searching for.
However, the only guaranteed mutable environment I can plug in eval is the environment returned by the interaction-environment repl library procedure. With this, however, I cannot reliably simulate a REPL (point 2) from above) because a REPL allows the import form, which the eval procedure does not have to.
Also, I cannot use the interaction environment for evaling a full Scheme program by other reasons: It is generally not empty, in particular it contains all bindings of (scheme base).
For realising 1) inside a running Scheme system, the eval library procedure environment looks promising as it allows to import libraries beforehand (which is part of running programs). However, the environment is immutable, so I cannot evaluate defines inside the environment. A way out would be to wrap the body of the program to be run in a lambda form so that define would define local variables. However, this also doesn't work: Inside a lambda form all defines have to come at the beginning of the body (which is not true for the top-level of a Scheme program) and inside a lambda form library bindings can be lexically overwritten, which is not possible by top-level bindings.
As Scheme is Turing-complete, I can, of course, simulate a Scheme system inside a running Scheme system but I am wondering whether it is possible just by using the eval procedure. One reason for my interest is that eval might be optimized (e.g. by a JIT compiler backend), so using this procedure might give near native speed (compared to writing a simple interpreter by hand).
R7RS-small is not intended for this sort of reflective implementation. R7RS-large will provide a library that supports user-created mutable environments.