libera/#commonlisp - IRC Chatlog
Search
7:09:36
asarch
If you move the cursor to a previous line and then press enter to use that line as the enter of the REPL, sometimes "forget" pieces of code specially when there are lots of )'s at the end of the expression
7:16:54
doomlist3
(format *query-io* "~a: " prompt) , (format *var* "~a " "data") here *var* shows it's no bound?
7:17:30
phoe
why do you put it in the FORMAT call where you are supposed to put the stream that you want to print to?
7:19:47
phoe
also, "data" is not a stream designator, so it is invalid to provide it as the first argument to FORMAT
7:21:03
doomlist3
if i replace prompt with a string "data" it won't accept *query-io* to be that string, but it accepts when the whole function is executed
7:23:02
doomlist3
*query-io* is a special lisp word, (format *q* "~a: " 3) variable unbound but not when *query-io* is used
8:21:07
phoe
jeosol: yes, I got a few reviewers. Another thing is that some more eyes on it will never hurt.
8:23:14
phoe
Yes; now that the most obvious typos have been found, I will want some review of the general flow of the book and the content.
8:28:54
jeosol
ok, I can volunteer some time. Is there some background material, e.g., what's the assumed programming proficiency of the reader, etc.
8:36:23
jeosol
I tried to cheat by copying an SBCL corefile from one linux machine to another to save on start time ... hmmm
8:37:47
jeosol
openSuSe, said something about core was built for runtime "localhost ..." but this is "second machine name" ...
8:40:45
jeosol
phoe: I just saved the image with executable set to nil. That only works for executable?
9:01:35
doomlist3
(read-line *query-io*) outs the *query-io* in string form but print and format show #<JUPYTER::STDIN-STREAM {10036D2EE3}>
9:04:35
beach
doomlist3: The very nature of a stream is that you can't tell what it provides until you read from it.
9:06:53
beach
doomlist3: Put differently, the operations provided on an object of type stream are operations such as reading/writing a character or a byte, perhaps peeking one item, and a few more operations, but that's it.
9:13:05
beach
doomlist3: And *query-io* is a variable whose value is a stream, not the string "song".
9:13:22
doomlist3
but when i format I get not "song" but (format t "~S" *query-io*) --> #<JUPYTER::STDIN-STREAM {1003B112A3}>
9:15:20
marcoxa
I want to READ a "form" which may contain "errors" (read: errors that variuos implementations signal in a very annoying "implementation dependent" way; sometimes by raising a READER-ERROR, sometimes signaling a I-DONT-CARE-ABOUT-YOU-THIS-IS-THE-ERROR-I-FU$&*NG-WANTH-TO-SIGNAL).
9:15:40
beach
doomlist3: You need to understand the basics of Common Lisp before you attack something as complicated as the project you are working on.
9:16:46
phoe
marcoxa: the only thing you can do is set *read-suppress*; if package OOOOPS doesn't exist, you cannot reference a symbol from that package
9:17:13
marcoxa
Most readers will keep the pointer right after the "oooops". I want to rolla back at the beginning of the form.
9:20:27
phoe
(let ((*read-suppress* t)) (read-from-string "(this is a (oooops::list))")) ;=> NIL, 26
9:22:58
marcoxa
Here is the code. It is already kludgy because of the imp-dep error signaling behavior of vairous implementations.
9:30:52
marcoxa
I guess there is no incatation to force an implmentation do what I want, lest use a re-implmentation of READ.
9:34:02
phoe
marcoxa: it's impossible in general, since the Lisp reader, in the general case, doesn't know when an expression is complete until it finishes reading that expression.
9:34:53
phoe
So in case of a reader error you can't show the full expression to the user because you don't have the full expression.
9:36:01
phoe
I'm asking because you seem to be solving a problem that might have a solution at another level
9:38:34
marcoxa
I know. My problem is somehow to ensure that the next form I am READing is marked as "inside" my original call to the READ-FORM function I posted.
9:40:18
phoe
beach has a concrete solution for that, a custom Lisp reader named Eclector, but I'll be boring; why skip over package errors?
9:41:23
phoe
more or less, yes; you can use the read functions it provides in place of the standard ones.
9:45:29
phoe
marcoxa: I'm curious, why are you trying to read it? Are you attempting some source manipulation or statistics or caching over that source code?
9:47:10
MichaelRaskin
9:47:12
phoe
beach: I just realized that Eclector could be a good tool for these people from Google who presented their work on ELS. The one about indexing Lisp source.
9:49:07
beach
Eclector has turned out to be a great abstraction for plenty of stuff. I came up with the idea, but scymtym has taken it way beyond my initial vision.
9:50:40
MichaelRaskin
I dunno, generally any solution for macroexpanding I can imagine, will be fine with standard read (then process and eval)
9:56:18
marcoxa
Ok. Looks like Eclector may be able to do the job. I'd like a more direct solution, but that's ok.
9:56:41
phoe
Eclector will then also preserve things for you that get lost during standard READ: indentation, comments, symbol casing, whitespace, et cetera.
10:00:05
marcoxa
My needs for the specifica case are not all that sophisticated. It looks like Eclector restart machinery will do. I will put adding it in my queue.
10:03:27
marcoxa
Ok. My English is messed up this morning. I meant: I will add to my queue the integration of Eclector in my code.
11:44:45
scymtym
marcoxa: if you plan to heavily use Eclector's error recovery, you have to use the master branch of the github repository since i pushed the (hopefully) final changes to that functionality just three days ago
12:01:57
phoe
minion: memo for Fare: done, added a subsubchapter to the book that you mentioned. Please review it to verify that I haven't made some bugs along the way; thanks.
12:49:41
boeg
Yesterday I believe it was phoe who told me to not use T -typespec in handle-case - its a code smell, be specific instead, IIRC. Good point, by now my question is; how do I go about making sure my handle-case handles all the signals a function could signal? I mean, I could look at the direct function I'm calling and see what it might signal, but other than that, maybe it calls something that calls something that might signal
12:55:07
_death
if you want to handle all conditions (for example, to have a thread terminate if an error bubbles to the top instead of breaking into the debugger) then indeed it's appropriate.. that is an exception to the rule
12:57:09
_death
if you want to perform some action, such as logging.. then T (all condition types) may be too general.. I use ERROR for that
13:00:24
boeg
I guess - my intuition would be, that one might specify the types that one is aware of, and then also include a catch all if the "end game" is, in my specific case, when the things I'm not specifically handling is signaled, the appropriate response would be to log it and throw a http 500 error
13:00:26
scymtym
SERIOUS-CONDITION is another possibility. memory-related conditions are SERIOUS-CONDITIONs but not ERRORs in some implementations
13:01:18
boeg
right, so error would be better suited I guess in my case as the "catch all" because I only want to catch errors I'm not handling and throw a 500
13:05:08
scymtym
_death: right, it certainly gets complicated. for example handling with HANDLER-CASE may have freed stack already. (handler-case (labels ((rec (x) (1+ (rec x) ))) (rec 1)) (serious-condition (c) (princ c))) has a chance of working
13:05:51
Nilby
I've used catching CONDITION (or effectively T) in a web console, so it can be appropriate for something that is effectively a REPL. But as soon as you run it under another REPL, you probably don't want that.
13:05:58
_death
boeg: just recently I had a bug like that, where I started threads for background processing and didn't have a catch-all, my server.. when things stopped working and I connected to swank I saw some 200 threads waiting in the debugger..
13:06:49
_death
boeg: with Lisp you have to avoid expectations like "on error the thread will terminate"
13:07:30
boeg
_death: indeed - i'm trying to learn about this all condition system, it's very different
13:08:17
phoe
boeg: the answer already happened there, handling SERIOUS-CONDITION should do the trick.
13:08:51
phoe
You should explicitly allow non-serious-conditions to be unhandled, since these may be signaled as a part of standard program operation.
13:10:39
boeg
phoe: makes sense, i'm just trying to figure out what the library i'm using is treating as a, say, SERIOUS-CONDITION. Like failing while persisting something - I want that to return a 500 error, not throw the program into the debugger
13:12:27
boeg
yeah, they inherit from error which inherits from serious-condition, so i believe that is the answer
13:14:30
phoe
serious conditions = errors + other non-error serious conditions, such as storage-conditions
13:14:50
phoe
basically, if a condition requires either handling or interactive intervention, it should be a serious condition
13:22:59
_death
(defmacro with-seriousness (&body forms) `(handler-bind ((silly-condition (c &aux r) (when (setq r (find-restart 'frown-and-ignore c)) (invoke-restart r)))) ,@forms)) ;; apply gensym as necessary
13:24:44
boeg
can I in slime go to the definition, or get shown the definition in some other way, of the symbol under the cursor? There's e.g. slime-inspect-definition, but it doesn't show me the actual code, and its also the function definition i'm currently inside, not the symbol under the cursor that it inspects
13:42:28
boeg
is using let* a code smell? I believe it says so in On Lisp, but I'm sometimes in situations where I think it makes sense - does that indicate my code is not written in the proper way that common lisp code should be written, or is Paul Graham just being a little to harsh on let* and it does indeed have some applications?
13:43:16
beach
I often use it to name intermediate results, which makes the code easier to understand.
13:43:29
phoe
it makes perfect sense when you have code that would otherwise be written as (foo (bar (baz (quux (frob (fred x)) :test :yes)) t) (cons 1 2))
13:44:13
phoe
it makes sense to instead (let ((frobbed-fred (frob (fred x))) (bazzed (baz frobbed-fred :test :yes)) ...) ...)
13:44:28
phoe
this also allows debugging on high DEBUG settings because you have intermediate variables.
13:45:14
phoe
there are some people who instead try to bind as few variables as they can; I consider that a very good golfing sport that should not intersect with code that is meant to be read, understood, and fixed
13:45:41
boeg
phoe: yeah, thats what I've found too - intermediate results makes a lot of things easier
13:47:40
phoe
mostly because it allows sane threading and splitting computation into meaningful steps, rather than having one heavily nested list
13:48:54
_death
PG's style is more functional, and in that style LET* is a code smell.. another reason is that, as you say, it is often used to name intermediate results.. it may be that you could factor your code differently, say by defining small functions (that have conceptual value) instead of having the computation done in-line with LET*
13:50:47
splittist
boeg: serapeum has a ~>. Clojure seems to love them https://clojure.org/guides/threading_macros
13:52:43
_death
the arrow macros, in addition to encouraging in-line computations like LET*, also remove the need to name the intermediate results, thus further discouraging thinking about small functions to factor the code
13:53:50
phoe
but that's a smaller issue if your code is functional enough, since pure functions can be much more easily tested
13:55:41
shka_
i takes a sequence of a clinical episodes and extracts vector of distinct diagnosis in those episodes
13:56:10
boeg
oh, its nice that multiple-value-bind just gives nils if there are more vars than values!
13:57:30
splittist
although serapeum:formals (sp?) is a version that errors, if that's what you'd prefer
14:01:46
phoe
_death: yes, but I found that article to be a good introduction to threading macros in general
14:02:50
_death
in my opinion, such macros are a crutch for people who can't keep up with Lispy style of design, which is sometimes taxing in thinking
14:03:33
phoe
_death: do note that the lispy style of design is "invent and/or use whatever language features you consider the best for your current problem domain"
14:04:20
_death
so instead of decomposing your problem, you keep your computations in-line with LET*, oh but names are hard, so you use an arrow.. since you handle multiple concerns in a function body, it becomes complex, and instead of decomposing it you turn to NEST so that it "looks better"
14:05:19
_death
that's why it can be taxing.. you need to decompose it in a way that has conceptual value
14:06:17
MichaelRaskin
Not everything is fully general, and «sorry Mario, the logic you are looking for is happenning somewhere else» is also not always a pleasant experience
14:07:13
_death
yes, abstraction has a cost.. what I'm saying is that these operators are often used as a crutch, and code using them can be much improved
14:09:25
MichaelRaskin
Well, sometimes san be improved, very often this improvement will make things worse
14:10:01
_death
this also applies to LOOP by the way.. of course, many times I also use LOOP and LET* (but not arrows, or for heaven's sake, nest).. but I keep in mind that it's often a crutch
14:10:32
MichaelRaskin
Well, computers are crutches because you just cannot calculate in your head fast enough
14:11:25
_death
I guess we're now talking past each other with generalizations.. time to do something else then :)
14:13:29
MichaelRaskin
If your task is not general enough to need that many extension points, just let all the related logic stay together
16:33:03
boeg
i only know realize that those functions - apropos, describe- - i know from emacs are available in common lisp too
16:41:06
adlai
... about Tabacum Indiscriminatory Leucocytopenia! sounds like a right nasty diagnosis
16:43:01
beach
ACTION is off to fix dinner for his (admittedly small) family and then spend time with her.
16:47:17
boeg
:P I think he did when he wrote "boeg: Great!" earlier to my message "beach: today i learned", phoe
16:55:43
boeg
All my questions seem to be answered in here, even though they are quite beginner questions
16:56:07
Shinmera
It annoys some people here when too many very obvious beginner questions are asked.
16:56:21
phoe
when #lisp is busy with non-beginner discussion, #clschool can be busy with beginner discussion
16:56:25
Shinmera
Some people would like deep insightful discussion of lisp, not the same questions noobs ask over and over.
17:02:18
theseb
I think I get how macros are to create code that generates code. How does that allow the code to do stuff that isn't possible in the language like change the evaluation recipe?
17:02:49
phoe
theseb: it isn't about the macro functions themselves, it is the fact that arguments are passed to macro functions without being evaluated
17:03:13
phoe
in (foo (+ 2 2)), if foo is a function, it gets 4 as its argument; if foo is a macro, it gets the three-element-list (+ 2 2) as its argument
17:03:53
phoe
that is what allows the macro to selectively evaluate its arguments in any order and under any conditions it'd like
17:04:29
phoe
a macro is just a function; what's interesting is what happens before that function is called and what happens after that function returns
17:07:14
theseb
phoe: when people add , and ,@ in macros....do those evals happen in the code generation phase?
17:07:34
theseb
phoe: or is that just specifying how to eval the expanded code later by the evaluator?
17:09:42
phoe
no, I'm saying that no evaluation takes place while reader-macroexpanding the quasiquote form
17:10:45
theseb
phoe: to use your example, so expansion will eval the right side and insert (list (+ 2 2) 4) in the code submitted to the evaluator?
17:11:15
ChoHag
theseb: ` is the same as ' (it quotes (doesn't evaluate) everything following it) except that ` allows any , it encounters to interrupt the 'don't-evaluate' rule.
17:13:05
phoe
this means that the result of calling the macro-function of FOO will be the list (list (+ 2 2) 4)
17:29:44
phoe
theseb: it's from the smallest meaningful macros that utilize backquote notation in some maybe-meaningful way
17:31:49
phoe
seok: some people have been playing with a portability layer for allegro webserver, which is kinda not what you're looking for I think
17:32:36
seok
I'm not counting on the portability atm, but just having a consideration as a viable stack commercially
17:33:04
seok
phoe: you are saying it runs on allegroCL but not reliable on other implementations right?
17:34:20
phoe
seok: I'm saying it's not meant to run on other implementations, and that portability layer makes it possible to run applications that depend on allegro webserver on other implementations
17:35:20
seok
I've done a fair amount of research on CL web development but I've only found this today
17:37:25
jackdaniel
aserve (the webserver) has been opensourced years ago: https://github.com/franzinc/aserve/
17:37:34
theseb
phoe: all the lisp masters on this channel....are they working for cool startups or doing their own projects on their own? how about you?
17:38:16
phoe
I'm working on my own projects in meantime while also working on a Lisp book (which, kinda, is a project, too)
19:02:23
theseb
Are these equivalent?.... 1. (defmacro foo () (list 'list '(+ 2 2) (+ 2 2))) ...... 2. (defmacro foo () `(,list (+2 2) ,(+ 2 2))) ?
19:03:57
adlai
theseb, why are you afraid of calling an equality predicate? not to mention, check the comma placement, lest you incur the wrath of an unbound variable