freenode/#lisp - IRC Chatlog
Search
6:10:21
beach
Today I'll try to figure out whether the problems with my sound have to do with the microphone or with OBS.
6:57:41
beach
phoe: There is nothing wrong with my microphone. I just used Audacity to record my voice and the sound is quite good. So the problem is with OBS then.
7:01:00
easye
Morning all. Is there a pure ANSI CL library someone might recommend to convert JSON to YAML?
7:22:03
easye
MichaelRaskin: moments ago I just learned this from p_l Still digesting the various libraries.
7:22:34
easye
My ultimate need is a JSON Schema validator in pure ANSI that works well for recursively defined schemas.
7:25:13
easye
What I mean by ANSI CL is sort of a shorthand for saying "portable across contemporary ANSI CL implementations)
7:25:38
easye
Lycurgus: the full twitch stream is available, for which you have to seek to the right spot.
7:26:04
easye
The ad-hoc ELS tech crew will be editing it into bite-sized YouTube chunks as time permits.
8:07:55
asarch
How would you remove entirely a SBCL that has been compiled/installed using the tarball from the project site?
9:57:23
Shinmera
Our first Lisp game is now available for purchase on Steam! https://store.steampowered.com/app/1605720/Eternia_Pet_Whisperer/?beta=0
10:13:54
nij
Hello! I hope to launch a thread that should run indefinitely. It doesn't seem that there would be an unhandled case. But no one can be 100% on this, I think. So, what should I do for it to move on if it happens to have any conditions, and log every thing in the same time?
10:15:07
phoe
(loop (tagbody :continue (handler-bind ((error (lambda (c) (log-error c) (go :continue))) (do-thing)))
10:18:52
flip214
wouldn't be a problem with tail calls... lifetime of the universe will stop most things eventually
10:23:52
nij
The point is that I want them to run indefinitely, without my paying attention to it constantly.
10:25:11
phoe
if a condition is passed to the ERROR function, which does SIGNAL and then INVOKE-DEBUGGER
10:25:21
nij
Uh.. I must misunderstand something. Aren't errors in CL yet another condition, which is some object people can create?
10:26:28
phoe
unless someone does silly stuff like calling SIGNAL with an error condition that should not proceed with execution
10:27:11
phoe
so: yes, only unhandled errors can cause the thread to enter the debugger unless the code explicitly does something extraordinary
10:27:58
nij
Maybe this is what I want - I want to suppress all debuggers and just let it logged. Is that possible?
10:29:26
nij
However, when a debugger is supposed to be on, usually it will present a list of options. Which option should I let my thread choose automatically in order to proceed?
10:31:40
phoe
if you tell your *debugger-hook* to perform a jump then you'll never enter the proper debugger
10:33:03
nij
Before doing that, I just want to make sure it's not obviously done yet.. as I think it should be there already..
10:33:38
nij
So a service is just a wrapped function, which will be fired as a thread. But after it's fired, it must log every output to some file, and does the error handling stuff I say above.
10:41:47
nij
Is there a "safe" thread, meaning a thread that completely logs all output, and skip (but log) any errors when it's running?
10:43:22
nij
By a "safe" thread I mean a thread that does (1) all logging (2) all things I asked above automatically.
10:45:32
nij
This ==> (loop (tagbody :continue (handler-bind ((error (lambda (c) (log-error c) (go :continue))) (do-thing)))
10:49:00
phoe
there's a variant of handler-case that I described in one of the TCLCS appendices that executes the handler and only then unwinds, but it's not standard
12:28:44
beach
jnewton: Here is the link to the document about a Lisp OS that I mentioned on the phone: http://metamodular.com/closos.pdf
12:48:10
pjb
nij: if log error doesn't use implementation specific API to collect and report the backtrace, then you can use handler-case instead of handler-bind. (loop (handler-case (do-thing) ((error (c) (log-error c)))))
12:54:29
nij
Is there a tiny project that uses CFFI? I'm new to it and hope to see it working in action. Thanks :)
12:55:32
pjb
nij: https://github.com/informatimago/lisp/tree/master/clext/pkcs11 might be an example.
12:56:21
pjb
nij: it wraps a pkcs11 library in a low-level lisp package and a high-level lisp package, which is rather a classic way to do it.
12:57:36
pjb
nij: and pcks11.lisp wraps the low-level C function calls in lisp calls, processing error handling and parameter conversions, etc.
12:59:09
pjb
nij: notably, when you have a library with a consistent API, you can write macros to perform the work in a consistent way, so wrapping over is easy: https://github.com/informatimago/lisp/blob/master/clext/pkcs11/pkcs11.lisp#L2011
13:00:12
pjb
nij: an example of usage of this library is in https://github.com/informatimago/scquery (sources-cl, not sources, which contains the C version).
13:01:49
pjb
nij: I guess we could give a hello world example, but this wouldn't teach you anything more than the cffi manual.
13:03:02
nij
semz you mean this? https://common-lisp.net/project/cffi/manual/cffi-manual.html#Tutorial
13:03:24
beach
kali123: Like: /nick my-new-nick and be sure the slash is the first character on the line.
13:04:10
beach
nij: I strongly recommend you use Common Lisp exclusively if you possibly can. Using FFI makes everything much harder.
13:05:01
splittist
nij: how is asking questions about it on irc going to help you? I usually find trying things out - and with lisp that's usually very easy - much more likely to illuminate the particular areas of ignorance I want to address.
13:07:17
nij
splittist: I never know. Sometimes on some topics there will be super helpful advises. Sometimes no..
13:07:49
pjb
nij: for example, there's a clock() -> long (actually clock_t but it's a long) function in libc. (cffi:defcfun (clock "clock") :long) #| --> clock |# (clock) #| --> 147584979 |# (- (clock) (progn (sleep 1) (clock))) #| --> -110 |#
13:10:15
pjb
nij: another example, always in libc, there's a int chmod(const char*path,int mode) function: (cffi:defcfun (change-file-mode "chmod") :int (path :string) (mode :int)) (change-file-mode "/tmp/foo.c" #o444) #| --> 0 |# ls -l /tmp/foo.c # --> -r--r--r-- 1 pjb wheel 29 May 4 05:08 /tmp/foo.c
13:11:28
pjb
So you would have to read the C header file, or write a little C function to get it: #include <time.h> long clocks_per_sec(){return CLOCKS_PER_SEC;} and use cffi to call it.
13:12:18
pjb
nij: C APIs are often not designed to be used in foreign code, so they use things like C macros and other stuff that goes thru difficultly. You may have to write some C portability code sometimes.
13:13:09
pjb
nij: of course, there are more complex cases, eg. out or inout parameters. Then you may have to allocate temporary storage for them, and convert the data. See the pcks11 example for that.
13:13:58
nij
In the first example you gave, the output was an integer, which is easy to translate to Lisp.
13:14:20
pjb
nij: but there are special cases. For example, macOS uses some structures with #pragma packed , and cffi doesn't deal with that.
13:14:36
nij
I see. Say I'm using a function in some C library, I need to translate the structures defined in that C library by myself?
13:14:43
pjb
nij: so I find it easier and safer, to refer structures are mere memory blocks, and specify the offsets to the fields myself.
13:16:03
pjb
nij: an example with defcstruct forms: https://gitlab.com/patchwork/CoreMIDI/-/blob/master/coremidi-cffi.lisp
13:17:42
nij
Nilby: yeah. but most of the time I must translate the structures in to Lisp by using defcstruct, right?
13:20:22
Nilby
nij: You don't have to translate. But it depends how you want to use them. If you want to use them conveniently in Lisp code that doesn't use CFFI, then yes. Usually one would provide a higher level interface to C code.
13:23:09
pjb
It depends on the C API really. Sometimes, they use complex structures to be created by the client code, then it's more convenient to do that in lisp, and provide code to convert between lisp an C structures. Sometimes they use function calls to manipulate an internal state, and then it is easier, you just have to deal with the functions.
13:23:58
pjb
void* make_point(); void point_set_x(void* pt,int x); void point_set_y(void* pt,int y); int point_x(void* pt); int point_y(void* pt);
13:24:46
pjb
vs. typedef struct point {int x,y; } point_t; point_t* make_point(); void use_point(point_t* pt);
13:25:22
pjb
using point_set_x is simplier from a FFI point of view than having to know how the struct point is laid out, and how to store or read it.
13:26:23
pjb
Also, in terms of API, when the structure point evolves (they may add fields, or want to reorder them), code using point_set_x will always work, while code setting directly a structure may become incompatible.
14:10:21
jmercouris
however, this forces recompilation of systems on disk which are in NOT writable directories
14:15:14
jackdaniel
you may want to try harder to provide a reproducible test case; ("foo" "bar") is indeed an illegal function call
14:16:01
jackdaniel
asdf claims that it does some magic parsing of asd files, but it in reality reads them
14:19:26
Nilby
I've been living with the same problem for years. It's especially trouble when your not in control of the filesystem or quicklisp setup for the resulting images, and the REPL user may _want_ to reload some systems. I figured someday I would force asdf to do what I want.
14:27:55
delta
Hello! I am trying to spawn multiple infinite-running processes and then, at an input from a user, send sigint to all of those processes and then exit the program. Can I get some help? I've found inferior-shell to launch processes and bordeaux-threads to make threads, but I'm not sure how to achieve exactly what I want.
14:31:08
beach
delta: Presumably, to fork a process from a Common Lisp image, you would need to use some implementation-specific function, like the POSIX interface of SBCL.
14:31:27
delta
Right, but I can make a thread and then spawn a process from that thread using inferior-shell, right?
14:31:58
delta
Perhaps I'm getting myself turned around and should move back to square one and just spawn a regular unix process.
14:32:16
beach
I don't know what inferior-shell is. Sorry. You would typically have a Common Lisp REPL, and you don't have to create a thread from there to fork a process.
14:32:52
beach
So you are not trying to "spawn a regular unix process"? What other kinds of processes are there?
14:34:40
delta
inferior-shell is just a library I found from googling how to run a shell command basically. I am trying to spawn a regular unix process, I'm just trying to execute an infinitely running process and interrupt it when I choose to. I think I reached for Bordeaux too quickly because it seems to be the de facto multiprocessing thing, but really what I wanted all a long was to just fork and store the PID to eventually send SIGINT to.
14:35:57
beach
I see no reason to use a shell at all. You should be able to use the implementation-specific POSIX system to fork the Common Lisp process itself.
14:37:31
Nilby
With sbcl you can use run-program with :wait nil which usually puts them in the background, save the process-pid, and then call sb-posix:kill on them
14:38:24
jmercouris
I used (alexandria:define-constant ..) and now I want to override it in the REPL
14:38:58
Bike
you want to set it to an actually different value? your implementation might offer a restart for it
14:39:16
Bike
redefining a constant is dicey because the compiler might be using the value, i.e. previously compiled code referencing the constant will still be using the old value
14:45:18
Nilby
I seem to end up using the constant changing restart a lot. It doesn't always work. Worse, if you save images a lot it's possible to multiple generations of different wrong constants.
14:54:16
pjb
π, e, c are constants. (note PI, E and C are not, in implementations when the size of long-floats can be changed at run-time ;-))
15:03:31
Nilby
There's only a few standard Lisp character names, so I was surprised when one day instead of beeping I saw: 🔔
15:11:39
jnewton
I heard someone (don't remember who) that someone (don't remember who) claimed to be working on a Common Lisp like condition system in Python. Who said it and who said it?
15:15:33
beach
jnewton: Are you also aware that phoe gave a presentation to the Webassembly people concerning the control structures that are needed for a condition system?
15:18:05
jnewton
@beach, no but I recently realized that I don't understand the condition system when trying to figure out how to implement it in Scala. I wanted to have something in Scala to present to Scala experts to demonstrate why there are important exceptional situations other than Errors.
15:21:40
agumonkey
phoe recently said he might rewrite it a bit (after some voices saying the style needed work)
15:21:48
jnewton
I saw an announcement for the CL algorithms book, but I've never seen an announcement for the Condition System book. I sense that keeping it a secret on IRC is counterproductive
15:22:47
beach
jnewton: It is easy (but unproductive) for IRC-ers to assume that when it has been announced here, everybody knows it.
15:24:11
jackdaniel
beach: your friendly neighborhood moderator looked it up for you on the vast internet: https://www.apress.com/gp/book/9781484261330
15:24:54
jackdaniel
jnewton: that's not how real conversations work, is it? :) no, it is not slack, no time travel nor annotations of past messages
15:25:01
jnewton
@beach: I found the book on amazon. and apparently there's also a new lisp blockchain book.
15:25:51
beach
jnewton: The @ convention is not used on IRC, just type the nick of the person (using completion) followed by `:'.
15:28:07
jnewton
is there enough info in the book to implement the condition system in a JVM hosted language? If so, it could be really practical.
15:30:58
jnewton
is there a way to make the condition system work with lazily evaluated code? I.e., you might define an anonymous function within a certain stackframe, but when the function is called, the stackframe is long gone. This is one of the problems with dynamic variables and also of exception handling in both Scala and Clojure.
15:33:59
Odin-
Huh. I was not aware of that book, which is nevertheless very much within my field of interest.
15:52:24
agumonkey
not sure it's right what you asked for jnewton but https://github.com/IGJoshua/farolero is a condition system for clojure
15:57:57
jnewton
as I understand agumonkey, there are many conditions systems for clojure, many of which are inspired by CL. The problem (as I understand) is they are not compatible with each other, therefore no library wants to use one. If Library A used one, then the user might also include library B which uses a different one.
15:58:11
Nilby
srandon111: I don't know, but I do have lots of other trouble running sbcl on netbsd.
15:58:21
Nilby
Java has throw and catch, which is really all that's required. CL style conditions have to be able to be sometimes handled before the throw, which is of course possible, just not what Java usually does.
16:00:02
Nilby
They help, but you could simulate them with global variables, or any variables if need be.
16:00:15
jnewton
nilby: you need to somehow be able to look up the stack to find handlers and restarts.
16:01:13
jnewton
There is a Scala class called DynamicVariable which uses sort of an unwind-protect mechansims. the variables are lexical, so you can only reference them within a scope where it is lexically visible, but the value is dynamic.
16:02:02
beach
jnewton: When you want to bind a dynamic variable, you assign its value to a lexical one and then you modify the global value.
16:02:05
jnewton
There are two reasons I wanted to implement it. 1. because I'd like to show it to other Scala programmers. and 2. because implementing it would make me understand it.
16:03:02
beach
It doesn't work so well for implementing the full semantics of Common Lisp dynamic variables in the presence of threads.
16:04:49
Nilby
Even if you just have catch and throw, unwind-protect is just like a todo list before you throw or after normal return.
16:05:56
White_Flame
beach: or modify the thread-local one on write, and on read check if the thread-local one is unbound (some unique default singleton) and read the global value if it is
16:06:03
jnewton
The reason I stopped was because I didn't know what type all the objects needed to be. You need to somehow do it so the code is well typed. the task was beyond my capacity at the time. I'd on my list of things to revisit.
16:08:45
White_Flame
and of course another wrinkle in java would be the unwind mechanics around the binding scope
16:11:35
beach
And I don't know why Krystof said "almost 20 years". I am pretty sure he was there in 2000, which would make it 21 years this year.
16:14:10
White_Flame
but anyway, given java's thread local storage, is there any material difference to SBCL's strategy in implementing special variable bindings?
16:14:29
jackdaniel
cache invalidatation and off by one errors are three of the hardest problems in programming
16:15:23
Odin-
ACTION thought there were only two hard problems: Naming things, cache invalidation and off-by-one errors.
16:16:56
nij
Without reading phoe's book.. here am I asking a dumb question directly. I intend to let the error be echoed (using format) without triggering the debugger. But that's not the case. Why? https://bpa.st/6ZGQ
16:18:11
jackdaniel
nij: handler-bind allows you to do things in a dynamic context of the error and carry on with handling the error
16:18:48
Odin-
jnewton: You could think of it as an ephemeral shared append-only text file, rather than as similar to the modern bells-and-whistles systems.
16:18:57
jackdaniel
basically to continue after the error you must wrap each place so the program knows where to resume
16:19:30
beach
jnewton: Probably. It might be a bit overwhelming when there are multiple discussion threads going on simultaneously.
16:19:40
nij
Hmm.. what should I do for it to proceed without debugger, but report any info that a debugger would provide?
16:20:14
jackdaniel
(progn (handler-case (/ 1 0) (serious-condition (c) (Print c)) (print "after!"))
16:20:34
beach
jnewton: Oh, and one more important thing. You quickly learn what people are likely to say things you are interested in, and what people you can safely ignore.
16:21:11
jackdaniel
(progn (block hi! (handler-bind … (lambda (c) (print c) (return-from hi!)))) (print "bye")
16:22:14
jackdaniel
nij: you could have a macro that wraps each form in the body in such handler-bind, but it doesn't make much sense
16:22:37
jackdaniel
because when your form errors then it means, that your program basically doesn't work and requires special attention
16:26:16
nij
=> (progn (block hi! (handler-bind ((error (lambda (c) (print c) (return-from hi!)))) (/ 1 0))) (print "bye"))
16:27:56
Odin-
If you want to _generally_ just print the condition object and carry on, couldn't you intercept the debugger entry?
16:33:18
jackdaniel
(defmacro with-foolhardy-forms (&body body) `(let ((*debugger-hook* (lambda (c s) (print c s) (throw :foo)))) ,@(loop for form in body collect `(catch :foo ,form))))
16:33:29
Nilby
Just please don't mess with the global value of the *debugger-hook* or you could disble people's debuggers.