freenode/#lisp - IRC Chatlog
Search
16:39:43
jackdaniel
mcclim was structured by previous caretakers (beach included); I only fix typos in the code and such
16:41:13
beach
People here should know that what jackdaniel just said is a gross underestimation of his role in McCLIM development.
16:44:41
beach
In my opinion, it is largely thanks to jackdaniel that McCLIM has been transformed from a useful but incomplete hack with tons of bugs to a serious library. He didn't do all the transformations himself, of course, but he was the one who took on the maintenance after years of no activity on McCLIM.
16:46:19
beach
I don't follow #clim closely enough, so I am not going to attempt a list of all the contributors, but I know that scymtym has dont quite a lot of things. I am sure jackdaniel can tell us who the others are.
16:48:05
jackdaniel
there is longi-sh authors list in the codebase; I'm too afraid that I'll forget about someone important while enumerating
16:49:12
jackdaniel
from top of my head scymtym, loke, slyrus, nsahmad, john-a-carroll, pwerkowsky; but there are more
16:49:50
jackdaniel
(half of the mentioned names are people who contribute by insightful bug reports)
17:28:19
lukego
hurray for all of you :) it's exciting to me to be starting to actually use CLIM having had CLIM-envy for a couple of decades
18:48:05
pjb
rpg_away: but this is ridiculous. Why don't you just take advantage of Lisp ability to have newlines in strings literals?
18:53:37
rpg_away
We want to allow people to have layout that will look good in source code and when displayed.
19:07:42
pjb
rpg_away: you can still indent literal strings; It's just a matter of bound box for the lisp object representation.
19:15:46
pjb
rpg_away: note: this is only a presentation. The string would be full flushed to the left (no prefix spaces on the lines). But the editor would align them to a rectangular box instead of the indented area, and would fill the left with a filler color or character to indicate it's not part of the source code. It could be the same face as the fringe, if it was distinct from the background.
19:17:38
pjb
rpg_away: this could even be implemented easily enough in emacs, when you type RET in a string literal, it would automatically indent with those ░ characters with an overlay or a compose-region or something… The source code wouldn't include them.
19:49:36
albusp
I thought reader will still use the keyword package for :cl, or does it still intern it in the current package when it encounters it? Is that why we do #:cl so that it is not interned?
19:50:09
jackdaniel
albusp: this is to inform the person who reads the code, that the symbols itself has no meaning - only the name in this context matters
19:54:47
albusp
ah, ok thanks for the answers! I further checked it on repl now, and see the difference:
19:54:47
albusp
(boundp #:testme) --> enters debugger saying testme is unbound, so the reader doesn't intern the symbol in the keyword package
19:54:47
albusp
(boundp :testme) --> T (which means it first creates the :testme symbol in the keyword package)
19:56:07
jackdaniel
symbols in the keyword package are exceptional because their value is always their name
19:57:12
pjb
and try: (values (boundp '#:testme) (setf (symbol-value '#:testme) 42) (boundp '#:testme))
19:58:12
pjb
and try: (let ((testme 42)) (values (boundp 'testme) (setf (symbol-value 'testme) 33) (boundp 'testme) testme (makunbound 'testme) (boundp 'testme) testme)) #| --> nil ; 33 ; t ; 42 ; testme ; nil ; 42 |#
19:59:16
pjb
albusp: #:foo is an uninterned symbol. But it's a symbol like any other. If you try to evaluate, CL will try to return its value slot. If that's not bound an error occurs.
20:00:10
pjb
albusp: in the case of the lexica LET testme, this doesn't bind the value slot of the symbol. With lexical let, the symbol is only used as a name to a lexical variable that is bound. Not the symbol itself.
20:00:36
pjb
But you can both bind the value slot of the symbol, and the lexical variable named by the symbol! Hence the results 42 and 33 in the example.
20:03:11
pjb
albusp: note that with defpackage, the reader know that the elements are string designators. The difference between :use cl, :use :cl, and :use #:cl are only in the interning and in what package the symbol is interned. :use cl interns a symbol named "CL" in the current package. :use :cl interns a symbol named "CL" in the package named "KEYWORD". :use #:cl doesn't intern any symbol, it just creates an uninterned symbol named "C
20:04:05
pjb
albusp: the difference being that the interned symbols are not garbage collected once the compilation is finished, since the packages are still refrenced in (list-all-packages). But the uninterned symbol (or the strings, when you :use "CL") can be garbag collected.
20:05:55
pjb
albusp: the difference between (:use cl) (:export a b c) vs (:use :cl) (:export :a :b :c) is not with (:use cl) (:export a b c) now the current packages has a whole bunch of symbols interned in it: (cl a b c), and if uou try to use the package that you just defined, you will get name conflict, between the exported symbols and the interned symbols that have the same name, but are not the same!
20:06:27
pjb
albusp: with keywords, you would get name conflicts if you tried to use the package in the "KEYWORD" package, but nobody does that, so no problem.
20:06:53
pjb
albusp: the best is to use #:foo or "FOO", I prefer the later since that makes less memory to allocate and garbage collect at compilation time.
20:13:44
pjb
albusp: Now, you can have: (defun f () (declare (special var)) var) ; note no variable named var is defined. (let ((var 42)) #| lexical variable |# (list var (let ((var 33)) (declare (special var)) #| dynamic variable var |# (list var (f))) var)) #| --> (42 (33 33) 42) |#
20:14:48
pjb
albusp: so during the execution of the inner, dynamic let, the scope of the lexical variable var of the outer, lexical let, is shadowed, and the _dynamic_ variable can be accessed even outside of the lexical scope, in the function F.
20:16:53
pjb
(let ((var 42)) #|lexical|# (setf (symbol-value 'var) 22) (list (list var (f)) (makunbound 'var) var)) #| --> ((42 22) var 42) |# here, we don't bind dynamically a dynamic variable var, but we directly set the symbol value, (it's where dynamic variable values are stored), so it can be read by F.
20:55:34
jcowan
beach: What happens when you are running CLOSOS and so am I, and I want to reuse parts of your iaage?
21:01:03
jcowan
FASLs are isomorphic to source files (or at any rate multiple files constituting a single compilation unit, whreas (frozen) Lisp images have it all.
21:03:06
phoe
jcowan: to put it another way - sounds like a need to serialize a part of the object tree of one image to a file, and intern it/merge it into the other image later
21:39:27
no-defun-allowed
The Self people had a transporter for getting objects between images. A careful reading suggests the transporter framework is just a convenient way to create methods on MAKE-LOAD-FORM.
0:12:22
White_Flame
hmm, the slime highlight in emacs doesn't work for #+not-found #p"foo". It shows the #p in comment color, but highlights the string in regular colors
0:14:19
White_Flame
paredit also considers the #p and the string to be 2 separate entities when moving parens
2:42:03
no-defun-allowed
I thought there was something in usocket which let you poll/select connections, but I can't find it. There are libraries for nonblocking IO, but they undoubtedly put you in callback hell.
2:44:58
no-defun-allowed
From memory the only way to do non-blocking IO on files involves the POSIX asynchronous IO stuff which isn't commonly used.
2:46:16
no-defun-allowed
I'm not kidding when I say this - I think the nicest way to write non-blocking IO code is to use ABCL on a Java 17 preview with the Loom extension. That way you have green threads and asynchronous IO with straight-line programs.
2:46:46
no-defun-allowed
I think libev uses another thread pool for file IO. Or maybe that was Erlang/OTP. Perhaps both.
3:14:28
beach
jcowan: What phoe and no-defun-allowed said. There would have to be some way of "serializing" part of the object graph in a way that makes sense when it is de-serialized on the other end. I haven't worked out the details yet, because that's not the (to me) interesting part of CLOSOS.
3:18:36
no-defun-allowed
See https://bluishcoder.co.nz/self/transporter.pdf for an idea of how one can transport objects between images. Some of it would not be relevant to CLOS, as it assumes a prototype-based single-dispatch and message-passing language, whereas CLOS is class-based with generic functions with multiple dispatch. But it should give an idea of what would be done to make transporting work.
3:21:27
beach
In several places, including the saving/loading of ASTs in Cleavir, I have used an idea i basically got from the CLIM specification, which is that the class structure should not be used. Instead I rely on the relevant protocol items, namely initargs and accessors.
3:21:57
beach
Doing it that way has the additional advantage that it is less sensitive to updates of the class hierarchy.
3:23:23
beach
This mechanism is used for saving an AST to file and from creating an AST from a file, but we use it also to clone an AST in memory.
3:25:24
beach
The format of the serialization is particularly simple and it works quite well. We use Common Lisp PRINT and READ. The reader is programmed so that the charater #\[ has special meaning. The format is [<package>::class-name :<initarg1> :<value1> ... :<initargn> :<valuen>]
3:26:41
beach
The reader macro for #\[ simply does (apply #'make-instance (read-delimited-list #\[ <stream>))
3:27:30
no-defun-allowed
Yes, "abstract initialization" is also a topic of the paper. Though it also handles preserving object identity (unless marked as unnecessary by the programmer), and transporting code.
3:28:52
no-defun-allowed
Hm. Would (#1=[blah] #1#) give you a list with the same object (by EQ) in the list twice?
3:28:54
beach
The technique I described preserves object identity automatically within a "file" through the use of #= and ##.
3:30:32
no-defun-allowed
The code generator maintains a table of temporary bindings for objects and reuses them. A written out Self module is a program which installs it into the system.
3:31:08
beach
But the mechanism requires the user to explicitly say, for each class involved, what initargs are relevant, and what accessors to use to fetch values for those initargs.
3:32:02
beach
That kind of mechanism would be excellent to use in order to install viruses and other stuff on your system.
3:32:04
no-defun-allowed
Indeed. That is quite similar to the "annotations" used in Self, and generally the transporter design struck me as a slightly more abstracted-away MAKE-LOAD-FORM.
3:33:10
no-defun-allowed
Yes, you probably would not want to do transporting exactly like that if you don't trust the author of the module.
3:34:22
beach
Exactly. So some slightly safer mechanism would be preferable. The one we use for ASTs does not execute arbitrary code.
3:36:24
no-defun-allowed
(The other approach, which I always mention when someone tells me that running random bytecode in a client program is going to lead to the client getting hacked, is to sandbox the program and put limits on execution time and space.)
3:38:07
beach
Sure but that technique doesn't always work. For instance, if what you are loading into your system is just data that you want to use in some other code, like a text document or a music score.
3:43:26
no-defun-allowed
Right. As I see it, a safe version of the transporter would return the objects produced, allowing them to be used outside the sandbox.
3:47:32
no-defun-allowed
If we allow for transporting code still, we could still produce objects which do undesirable things. For example, an attacker might write out code to subclass MUSIC-SCORE, then define a method specialized on that subclass, for a generic function which the score reader calls.
3:47:55
no-defun-allowed
Then the transporter would return an instance of that new class. However, in my opinion, that is an argument for running the score reader (and really any program) with as few capabilities as possible.
3:50:42
beach
It is a bit too early for me (I haven't finished my morning coffee yet) to think through all cases. But it is an interesting problem, and I will be happy to include a chapter in the CLOSOS specification if someone would like to work out the details.
4:21:29
no-defun-allowed
Most proposals for readable hash tables I've seen forget about the test function.
4:21:52
no-defun-allowed
Not to say that adding somewhere to put a test function isn't easy, but most people forget it.
4:23:05
Nilby
and implemntation specific things like :weakness, and that it won't work with *read-eval* nil