<ixelp>
CLHS: Function WRITE, PRIN1, PRINT, PPRINT...
<beach>
Otherwise, the best we have is Emacs+SLIME. Not great, but it works most of the time.
<mi6x3m>
beach, yeah I know this but I mean more like "> format --inplace code.lisp"
<pjb>
mi6x3m: Another way to do it, is to use load-time-value: (defun foo () (let ((static (load-time-value (cons 0 nil)))) (incf (car static)))) (loop repeat 10 collect (foo)) #| --> (1 2 3 4 5 6 7 8 9 10) |#
<beach>
mi6x3m: I know of no such thing.
<mi6x3m>
ayeaye
<mi6x3m>
interesting pjb
<beach>
mi6x3m: It is rarely needed if you write the code right in the first place.
<pjb>
mi6x3m: but in general, you will prefer to avoid private state, if only for debugging reasons.
<mi6x3m>
well i'm writing a function that checks a system property but it's expensive so i wanna do it every N seconds otherwise use a cached result
<beach>
mi6x3m: There is also nothing wrong with using a global variable. You would make it internal to your own package, so it won't be part of the API.
rgherdt has quit [Ping timeout: 240 seconds]
rgherdt has joined #commonlisp
greaser|q has joined #commonlisp
greaser|q has quit [Changing host]
rgherdt has quit [Ping timeout: 240 seconds]
<jackdaniel>
visibility is one issue, but global variables are often bad for concurrency and reentrance
<pjb>
jackdaniel: but the same can be said for closures and load-time values.
<pjb>
if your function can be called from multiple threads, you need to mutex all of them.
<jackdaniel>
pjb: that depends on how the function is written
<hayley>
As a wise hacker once said, "mutation is for chumps".
<jackdaniel>
each thread may have local-global state (thread-local bindings of special variable), that would prevent race conditions
<jackdaniel>
(as an example)
<hayley>
That still fails re-entrancy in the one thread.
<jackdaniel>
yes
<pjb>
Indeed. So global variables (dynamic bindings) actually may be better for concurrency and reentrance, because implementations may have thread-specific dynamic variables.
<jackdaniel>
thread-safety and reentrance is not a feature that may be slapped on top of existing design, it is the architecture decision
<pjb>
The opposite of what you wrote.
<jackdaniel>
and some choices are very common pitfalls - i.e global variables
<jackdaniel>
pjb: global and special variables are not the same concept
<jackdaniel>
although it may not be obvious from the common lisp standard perspective
<pjb>
Just list them in make-thread! (defvar *foo*) (bt:make-thread (function foo) :initial-bindings '((*foo* . 42)))
<jackdaniel>
that's not a global variable then; that said I think I've elaborated enough. I feel motivated to do something useful today so I'm resuming work on polyclot
<pjb>
There's no such thing for (let ((foo)) (defun foo () …)) (bt:make-thread (function foo) …) or for load-time-value.
<pjb>
Note how the function foo is written using a global variable *foo*, and it's only when creating a thread, that we bind it temporarily, for the time line of the thread.
<pjb>
So it IS a global variable!
mi6x3m has quit [Read error: Connection reset by peer]
f065e1 has joined #commonlisp
f065e1 has quit [Remote host closed the connection]
wilfred has quit [Quit: Connection closed for inactivity]
cage has joined #commonlisp
lucasta has quit [Remote host closed the connection]
karlosz has joined #commonlisp
rgherdt has joined #commonlisp
mi6x3m has joined #commonlisp
rgherdt has quit [Ping timeout: 240 seconds]
rgherdt has joined #commonlisp
anticomputer has quit [Ping timeout: 240 seconds]
anticomputer has joined #commonlisp
pranavats has left #commonlisp [Disconnected: Hibernating too long]
_cymew_ has joined #commonlisp
rgherdt_ has joined #commonlisp
rgherdt has quit [Ping timeout: 240 seconds]
Lycurgus has joined #commonlisp
Lycurgus has quit [Quit: Exeunt: personae.ai-integration.biz]
chrcav has quit [Ping timeout: 240 seconds]
random-nick has joined #commonlisp
mi6x3m has quit [Ping timeout: 240 seconds]
* jackdaniel
wonders whether if the form does not return (i.e error), can we infer the return type to be NIL?
mi6x3m has joined #commonlisp
mi6x3m has quit [Client Quit]
igemnace has joined #commonlisp
<semz>
You should be able to, but I think this mostly just amounts to special casing functions that are known to never return normally
<semz>
not implying that this is a bad thing; you'd then have a way to declare that a function never returns
<semz>
(values) could possibly cause a few problems though
<jackdaniel>
how so?
<jackdaniel>
btw there is a limited number of operators that do not return (and the type inference is often not perfect)
<pjb>
go return-from return throw signal error, etc.
<semz>
signal can return
<semz>
jackdaniel: There are a few select situations where the result of (values) is not treated like NIL, and I'm not sure if these would have to be handled differently
<jackdaniel>
I would expect the type inferencer for cl to handle multiple values
<Nilby>
Is there some way to tell asdf have system dependencies satisfied even if their files have disappeared? E.g. (asdf:load-system "bar") (save-lisp-and-die), start on a another system where all files gone. load "foo" which depends on "bar" and have it succeed? I've tried all the asdf:clear-* things.
<Bike>
(values) has a return type of (values), whereas error has a return type of (values nil). completely different
<semz>
hm, right.
<jackdaniel>
Nilby: change the system class to preloaded-system
<jackdaniel>
(or whatever it is called)
<jackdaniel>
perhaps there is a designated operator for that
<jackdaniel>
there is also immutable-system, the difference is according to the name
<Nilby>
jackdaniel: Ah thanks! I didn't see that. I'll give it a try
<jackdaniel>
sure, good luck
kevingal has joined #commonlisp
<Nilby>
This seems to work: (dolist (s (asdf:registered-systems)) (asdf:register-preloaded-system s) (asdf:clear-system s))
<jackdaniel>
ship it! ;)
<Nilby>
Yes! in this case "it" is only a very loaded lisp running on a bare kernel
nij- has joined #commonlisp
<jackdaniel>
oh, that's cool! does it run as pid 0 from userspace or its something akin nolibc and runs in the kernel space?
<jackdaniel>
do you interact with the kernel with ioctl or you mount /dev /proc etc and talk through it?
<Nilby>
it's the only process in userspace, but pid 1 it seems
<jackdaniel>
right, pid 1
<Nilby>
yes many many ioctls, like first turn caps lock into ctrl
<jackdaniel>
sounds like fun; CL/Linux go! ;)
<jackdaniel>
(known as "Alien")
<Nilby>
given what a joke it is i've called it "lol"
<jackdaniel>
mezzano and (imaginary) lispos does not put a barrier between the kernel and the userspace, so quite different I think
<Nilby>
pjb: thanks, I was inspired to do my current batch of work by your article, but I cut out the emacs with it's huge pile of C code & libraries
<pjb>
You may want to use ecl, to generate small executables, with libecl as a shared library.
<Nilby>
jackdaniel: yes, the barrier between the kernel and the userland is horrible, but then I don't have to write device drivers which seems even more horrible to me
<White_Flame>
Nilby: yay, yet another lol collision with land of lisp and let over lambda :)
<pjb>
Nilby: Then you may want to diverge from unix. You may get some inspiration of what is possible looking at Android, and its Java userspace.
<Nilby>
pjb: i'm going for only one executable, so it's gonna be big, and my code is too darn slow for ecl
<pjb>
perhaps you could use ROTF?
<pjb>
Nilby: ok.
<nij->
What is such barrier thing you're talking about @@?
<Nilby>
pjb: what's ROTF?
<jackdaniel>
Nilby: there is nolibc that is used to write programs that run within kernel; I don't know how feasible that is but perhaps you could use it?
<jackdaniel>
nij-: contemporary operating systems right now have a monolithic kernel which is separate from so-called "userspace programs", so when the userspace program terribly crashes it may be simply removed from the system, instead of crashing the computer
<Nilby>
jackdaniel: i could, but I'd have to pick a kernel, and i'm not fond of linux internals and kernel debugging, and this way it can also run on bsd or whatever. also I'd still have to convert object to C conventions. I'm having enough trouble just with video driver bugs
<beach>
nij-: It is done that way so that we can write application programs the same way we wrote them when computers didn't have any memory-management unit, so that all application programs were loaded at physical address 0.
<jackdaniel>
Nilby: makes sense
<jackdaniel>
but ioctl numbers surely differ between bsd and linux?
<jackdaniel>
there's also a very clever concept of rump kernels but for some reason it did not gather much traction (maybe it will(!))
<nij->
beach What do you mean by "that way"?
<beach>
nij-: What jackdaniel said.
<beach>
nij-: We separate user space/mode from kernel space/mode.
<nij->
jackdaniel Isn't that the good thing? And which part is the "barrier"? Is Nilby trying to remove the barrier?
<jackdaniel>
nij-: I have ambiguous opinion about whether it is a good or bad thing - certainly it has some advantages and disadvantages; and according to what Nilby he is not trying to remove "the barrier"
<beach>
nij-: This isolation between the kernel and the applications and between applications is necessary because we program computers the same way as in the 1960s. But it creates lots of problems when applications need to communicate. So it is overkill.
<jackdaniel>
to what Nilby said, *
<beach>
nij-: You can read about this in the Closos document I wrote. It has an entire chapter on the problems with current operating systems.
<nij->
Read that twice. And I am going to read that the third time now :D
<White_Flame>
I also state the problem as blind execution of arbitrary machine code blobs
<White_Flame>
if the actual machine code generator (eg compiler) is a trusted intrinsic part of the system, then you can trust its code, vs having who knows what unsafeties running
<White_Flame>
typical operating systems do the latter and spend a bunch constructing fences around those unknown unsafe programs
<White_Flame>
and just give them a fenced off slice of the computer to do whatever they want
<beach>
Exactly, and which mimics the way we used to program computers, i.e., there was only one program in memory at any point in time.
<White_Flame>
another big problem from a developer and power user perspective is that there's no way to introspect a process in that typical OS model, except for where it intersects the OS APIs (eg open files, memory footprint)
<nij->
Nilby what will you do after you replace unix userspace with Lisp?
<jackdaniel>
nij-: the good news is that you may have your own private lispos at the process boundary - just start your implementation and run separate applications in different threads
<Nilby>
nij-: I'll probably be dead by then
<White_Flame>
and thus it's very difficult to automate processes in typical OSes
<jackdaniel>
Nilby: your legacy will live on!
<nij->
But since we're still using unix like kernel, the concept of process must remain.
<nij->
So the idea is that we only run a single process (lisp), and let all other things run in lisp, and so for example the communication problem can be lifted?
<jackdaniel>
nobody prevents you from running a single process and all "applications" in it, then you have all sharing you want
<nij->
lifted/resolved/..
<jackdaniel>
except for recompiling drivers at runtime, but oh well, you have to start somewhere
<nij->
Nilby pjb had emacs running as PID 1; I'm pretty sure you can have the same with Lisp before your death.
<Nilby>
doubtful, i really have done more than what an average embedded system with busybox does, but it just seems much better with a lisp repl than a static C shell
<jackdaniel>
Nilby: how do you process events (i.e keyboard input)? and how do you print data (i.e on the screen)?
<Nilby>
nij-: i'm getting old and emacs is over 40
<nij->
But just to make lisp run as PID 1 won't be too hard, no?
<nij->
What's hard is to make the following things work too.
<Nilby>
jackdaniel: just using the tty driver for now, but i do have a terminal emulator and framebuffer stuff, but some recent change in linux made my framebuffer code fail
<jackdaniel>
Nilby: I smell a janky mcclim backend then ,)
dcb has joined #commonlisp
<jackdaniel>
mcclim-on-canes
nij- has quit [Quit: Using Circe, the loveliest of all IRC clients]
dcb has quit [Quit: MSN Messenger v2.16.1]
rgherdt_ has quit [Remote host closed the connection]
tyson2 has joined #commonlisp
kevingal has quit [Ping timeout: 256 seconds]
Perflosopher has joined #commonlisp
<phoe>
could go nice with cobol-on-wheelchair
jonatack has quit [Ping timeout: 265 seconds]
nij- has joined #commonlisp
mi6x3m has joined #commonlisp
<mi6x3m>
hey, pjb, still around for a question?
Lycurgus has joined #commonlisp
mi6x3m has quit [Ping timeout: 265 seconds]
masinter has joined #commonlisp
Gleefre has quit [Ping timeout: 245 seconds]
nij- has quit [Ping timeout: 240 seconds]
Lycurgus has quit [Quit: Exeunt: personae.ai-integration.biz]
nij- has joined #commonlisp
johnjaye has quit [Ping timeout: 240 seconds]
mi6x3m has joined #commonlisp
mi6x3m has quit [Client Quit]
kevingal has joined #commonlisp
Gleefre has joined #commonlisp
chrcav has joined #commonlisp
attila_lendvai has joined #commonlisp
mi6x3m has joined #commonlisp
glaucon has joined #commonlisp
dcb has joined #commonlisp
_dcb_ has joined #commonlisp
dcb has quit [Read error: Connection reset by peer]
<mi6x3m>
I wanna use this macro as: (defn foo () (cache-for (5 :seconds) (do-expensive-op)))
_dcb_ has quit [Quit: MSN Messenger v2.16.1]
dcb has joined #commonlisp
waleee has joined #commonlisp
<Bike>
seems ok, though the ltv trick might be worth an explanatory comment
<Bike>
oh and you probably meant to initialize it to (cons nil nil). or (cons nil 0) and then you can avoid the runtime OR
<gilberth>
There is no ,(get-internal-time-units-per-second) but there is ,(progn internal-time-units-per-second)
<ixelp>
(get-internal-time-units-per-second) ERROR: Undefined function GET-INTERNAL-TIME-UNITS-PER-SECOND called with arguments () . , also (progn internal-time-units-per-second) => 1000
<Bike>
you can also break up the lambda list as (duration . units) instead of just interval, and then skip the car cdr and make it clearer
<gilberth>
And (< ,elapsed-time interval) looks bogus. A comma missing. And can this interval be any expression re-evaluated at runtime? What about the unit :seconds? Can that be computed anew a runtime too? Or is the interval supposed to be a constant?
<gilberth>
In either case it may be more efficient to not not divide by internal-time-units-per-seconds, but multiply the interval by it. This will keep you using integers, perhaps even fixnums and not cons a ratio.
trev has left #commonlisp [#commonlisp]
<mi6x3m>
thanks Bike and gilberth !
<mi6x3m>
this really helps me a lot :)
<mi6x3m>
let me fix the smallish stuff
<mi6x3m>
gilberth, the interval is supposed to be a constant and the :seconds is just for readibility
lucasta has joined #commonlisp
<gilberth>
Then you can ASSERT at macro expansion time and calculate the effective interval in internal time units at macro expansion time as well. Less work to do at runtime.
<gilberth>
And you can say (defmacro cached-for ((interval unit) &body body) ...).
<gilberth>
You'd get some syntax checking for free. And documentation.
<mi6x3m>
ah, i can destructure in the arg list?
<mi6x3m>
nice
<gilberth>
Yes, it can. Like destructuring-bind.
<mi6x3m>
thank you so much i didn't know that
nij- has quit [Ping timeout: 240 seconds]
attila_lendvai has quit [Ping timeout: 240 seconds]
cmack has quit [Remote host closed the connection]
attila_lendvai has joined #commonlisp
rgherdt has joined #commonlisp
tyson2 has quit [Remote host closed the connection]
cage has quit [Quit: rcirc on GNU Emacs 28.2]
tyson2 has joined #commonlisp
<mi6x3m>
gilberth, is internal time in seconds gonna be the same at expansion time and run time?
NicknameJohn has quit [Ping timeout: 240 seconds]
<Bike>
it's a constant, so it had better be
<mi6x3m>
I mean it depends on the execution environment no?
lucasta has quit [Quit: Leaving]
_cymew_ has quit [Ping timeout: 240 seconds]
mi6x3m has quit [Quit: Leaving]
<Bike>
it's gonna depend on the implementation
glaucon has quit [Read error: Connection reset by peer]
rgherdt has quit [Remote host closed the connection]
rgherdt has joined #commonlisp
kevingal has quit [Ping timeout: 240 seconds]
luna-is-here has quit [Quit: luna-is-here]
luna-is-here has joined #commonlisp
pve has quit [Quit: leaving]
shka has quit [Ping timeout: 240 seconds]
attila_lendvai has quit [Ping timeout: 250 seconds]
tyson2 has quit [Remote host closed the connection]