freenode/#lisp - IRC Chatlog
Search
19:47:38
stacksmith
Or any macro that wants to do something more interesting than just expand stuff right there.
19:48:20
Bike
well, there aren't too many of those, and usually you can use macrolet or such to get similar effects even with advanced ones
19:48:34
_rumbler31
so a given implementation can fully know what a given set of code can do, but because there is enough implementation specific behavior, there is no such thing as a general "call graph" because a walker would have to know what a final implementation would do
19:58:57
pjb
you can still make a call graph, only you cannot label the nodes by the name of the functions, you have to label them by the function themselves.
19:59:47
pjb
(let ((i 0)) (loop repeat 10 for closure = (lambda () (incf i)) collect (funcall closure))) #| --> (1 2 3 4 5 6 7 8 9 10) |# in this code, the call graph calls 10 different closures.
20:01:01
pjb
(declaim (notinline foo)) (let ((i 0)) (loop repeat 10 for fun = (defun foo () (incf i)) collect (foo))) #| --> (1 2 3 4 5 6 7 8 9 10) |# in this code, the call graph calls 10 different functions from (foo)!
20:03:11
pjb
(let ((i 0)) (let ((closure (lambda () (incf i)))) (loop repeat 10 collect (funcall closure)))) #| --> (1 2 3 4 5 6 7 8 9 10) |# ; in this code, the call graph calls 1 (ONE) single closure!
20:04:07
pjb
(let ((i 0)) (flet ((foo () (incf i))) (loop repeat 10 collect (foo)))) #| --> (1 2 3 4 5 6 7 8 9 10) |# just like in this one. In this case, the call graph could have a node named foo. but notice it would be a different foo each time this expression is evaluated!
20:11:35
stacksmith
Right. You can only speak for the image at the point in time you looked at it...
20:19:07
jasom
otwieracz: also the write-lock code looks wrong; usually rwlocks allow one writer or many readers; this appers to allow many writers or many readers
20:23:34
jasom
otwieracz: yeah, I see it now. Were you able to get it to work with condition variables?
20:25:04
jasom
semaphores and condition variables have a large overlap; it's easy to implement one with the other, and they are used for similar things
21:34:45
Shinmera
Implementing that should not be too hard -- crawl through the slime/swank sources and tear out the relevant parts.
21:35:29
Shinmera
And for the interface it would probably just be an eval-in generic function taking a frame and a form.
21:44:44
jasom
I may investigate. Right now my geany plugin runs emacs to drive swank as I found that to be easier than implementing all the parts of slime that are elisp
21:47:09
Shinmera
I also have an inspector written, but that's currently tied to Trial. Should export it to QUI some time. https://www.youtube.com/watch?v=w70XyHBrUDI&list=PLkDl6Irujx9Mh3BWdBmt4JtIrwYgihTWp&index=27&t=0s
21:52:37
Shinmera
Need to make more videos. And more articles. And more libraries. More of everythign!
22:05:33
stacksmith
Is there any reason top-level def forms have a lambda-list like (name lambda-list &body body) instead of something that indicates destructuring, like (name (&rest lambda-list) &body body)? Is there any point in passing a non-list as a lambda-list?
22:08:10
stacksmith
It disambiguates the structure. Otherwise, an entity looking at the first lambda-list and a parameter list may just as well assume it's a function call returning a single value lambda-list.
22:08:19
mepian
is it possible to upgrade ASDF from 2.010 to 3.3.1 with install-asdf.lisp on Clozure 1.6-r14468M?
22:09:27
Bike
(defun (setf foo) ...) is ok, but nothing analyzing code can go "ah, it's a call to the function 'setf'"
22:10:49
Shinmera
stacksmith: What are you going on about? It's a lambda-list. You can't just go ahead and make up rules willy nilly about how you want to read things.
22:11:11
Bike
whereas you can have a macro like (defun foo (form) form), and then in (foo (setf foo)) there is in fact a call to the function 'setf'
22:11:44
Bike
what i'm saying, stacksmith, is that you're attributing more semantics to lambda lists than they actually have
22:13:01
Bike
for another example, you could also give defun the lambda list (name lambda-list &rest body)
22:13:31
Bike
if the semantics could be summed up in the lambda list we wouldn't need the actual macro function
22:16:29
stacksmith
Is there anything semantically different with (name (&rest lambda-list) &body body)?
22:18:50
Shinmera
I object to (&rest lambda-list) for a different reason: a lambda list is a structure in itself. It is not really applicable to what &rest means: an enumeration of items.
22:21:57
mepian
ASDF went from one file (asdf.lisp) in 2.010 to multiple directories of sources, that's quite a growth
22:22:07
Shinmera
I have. My joke is that most clients are so old and well-trodden that a crash is very peculiar.
22:22:36
stacksmith
Bike: I thought &rest can be in an inner destructuring list along with dotted notation...
23:01:34
emaczen
pjb: can you show me map-reduce with #'map #'reduce bt:make-thread and bt:join-thread?
23:21:51
mepian
wow, I somehow completely misunderstood the process of upgrading ASDF - I should have just downloaded the new asdf.lisp and load it instead of mucking around with the tarball
3:19:56
krwq
I've today encountered this: https://github.com/GrammaTech/sel does any of you helped with this? :)
3:21:44
krwq
haven't had time to familiarize with what's possible but overview of the project sounds pretty cool
3:31:45
krwq
can't find it right now over there but either there or in one of the blackhat videos comment
3:43:23
pfdietz
https://www.prnewswire.com/news-releases/grammatech-releases-automated-software-engineering-library-into-open-source-300586264.html
3:58:39
antonv
if there was a subset of their functionality (say without custom macro characters) working fater, that would be good
4:09:53
pierpa
can you use vectors instead of lists? reading vectors with included length prefix should be faster than reading a list.
4:16:03
antonv
pfdietz: yes, for readability. But I'm ready to give it up for good speed improvement.
4:16:41
pfdietz
cl-store does serialization in a form that's optimized for speed and compactness, not human readability, if that's helpful.
4:17:20
antonv
I was looking for somethe serialization librarty, but had impression that none of them is fast
4:25:40
pierpa
to see where time is spent could also try to compare the time needed for reading the same data written as a vector with length prefix #12349556(k1 v1 ...)
4:28:42
Bike
like, if your slot is called foo, you can just have (foo :initform blablabla) and itll keep the accessors and stuff from parent classes.
4:29:29
specbot
Inheritance of Slots and Slot Options: http://www.lispworks.com/reference/HyperSpec/Body/07_ec.htm
4:29:39
Bike
"The default initial value form for a slot is the value of the :initform slot option in the most specific slot specifier that contains one. "
4:31:49
specbot
Sharpsign Left-Parenthesis: http://www.lispworks.com/reference/HyperSpec/Body/02_dhc.htm
5:01:47
beach
jasom: Are you referring to a real debugger (where you can set breakpoints, step by form, trace, examine data, etc), or what we habitually call a debugger but that really isn't?
5:03:17
beach
jasom: And I have a specification for one of the former type, but it will require support from the implementation that most implementations may not have yet.
5:10:02
beach
If you don't want to have a slot writer (which often happens to me), then you can use REINITIALIZE-INSTANCE instead.
5:10:23
beach
I mean, you call REINITIALIZE-INSTANCE inside the :AFTER method on INITIALIZE-INSTANCE.
5:13:39
beach
It has nothing to do with CLOS. It is the same in every language. Slots (or fields, or data members) are implementation details that may change in the future.
5:13:46
krwq
beach: I think I'll pass with this for now, slot-value works - I'll likely get to that point where I understand the advantage
5:14:03
beach
Accessors are part of the documented protocol (or interface, as most other languages call it).
5:14:44
krwq
beach: I see - this is meant to be implementation detail, I do not want any accessor here
5:15:35
beach
You typically still want an accessor. It is what is called an "internal protocol", i.e. even in your module implementation code, you want to be somewhat modular.
5:16:44
beach
Here is another reason: It is possible that in your implementation, SLOT-VALUE, (SETF SLOT-VALUE) etc. are slower than slot accessors.
5:17:22
beach
Not in SBCL though, which basically converts SLOT-VALUE with a constant slot name to a kind of slot reader.
5:18:35
krwq
beach: I might gradually get to the better design but haven't thought through the internal protocl yet
5:18:38
beach
I mean that your Common Lisp may have to do more work with slot-value, because it first has to figure out where the slot is stored in the object, given the class of the object and the name of the slot. This procedure can easily be bypassed in a slot accessor, and less easily with slot-value.
5:19:10
beach
Sure, you don't think of that in the beginning. But it is good to prepare for them by not using slot-value or with-slots.
5:19:50
beach
It's easy. Just stick a :reader or :accessor in there with a name that is not exported.
5:20:44
beach
So, stick a reader or accessor in there, use those to access the slot, or use WITH-ACCESSORS where you would otherwise use WITH-SLOTS.
5:22:41
beach
In my code, the name of the slot serves only two purposes: The primary purpose is so that when the DEFCLASS form is re-evaluated, the Common Lisp implementation knows that it is the same slot as before. The secondary purpose is so that the Common Lisp implementation knows that when a slot is mentioned in both some class and some subclass, I meant for it to be the same.
5:26:58
beach
That way, I don't have to mention slot names explicitly, and the code continues to work even when slots are added or removed.
5:27:31
krwq
beach: I had hard time with that when the library I used added some slots I didn't want with the metaclass
5:28:52
beach
That is when the pairs initarg/accessor are useful. I often use a registration mechanism so that the relevant pairs are available by a call to a generic function.
5:29:30
beach
For example, when I save an object to a file, it is saved as [<class-name> :initarg1 value1 :initarg2 value2...]
5:30:00
beach
That way, I can reload the file even after my implementation has changed, so that some slots are added or removed.
5:31:21
beach
https://github.com/robert-strandh/SICL/blob/master/Code/Cleavir/Abstract-syntax-tree/general-purpose-asts.lisp#L28
5:32:49
beach
No, it is simple. Less than 100 lines of code: https://github.com/robert-strandh/SICL/blob/master/Code/Cleavir/Input-output/io.lisp
5:35:32
beach
All I need to do in order to read an object saved that way is a reader macro on #\[ that does (apply #'make-instance (read-delimited-list ...)).
5:41:46
beach
Most of the code is there. I am working on the bootstrapping procedure. Also, Bike is working on Cleavir, and probably heisig as well pretty soon. Right now I am working on indentation in the editor.
5:43:00
beach
Well, Climacs already exists, and I am working on version 2 of it, which is planned to have much better functionality for editing Common Lisp code.
5:44:53
krwq
clim can display on everything and I assume your implementation is using clim interface
5:47:04
beach
The plan is to propose a set of tools for Common Lisp programming that are an order of magnitude better than the Emacs-based tools we have today.
5:48:04
krwq
beach: fair enough but if you've proved the point of clim universality by making it work with emacs it would gain in popularity much faster and likely gain contributors faster
5:48:54
krwq
don't want to sidetrack or anything but that sounds like a nice hackathon project or something you could give to a student
5:49:16
beach
Yes, but that is not my primary goal. My primary goal is to have a comfortable Common Lisp-based environment, and to have my effort to create it count as research.
5:50:51
krwq
good point but note that if you did it this way then you could reverse the dependencies by making emacs work with clim as well and those emacs modes could eventually work with climacs
5:52:01
beach
Yes, well, someone who is interested in working that way could do it. I'll work on what I am good at. In particular the hard parts that require fresh research.
5:53:04
beach
No, because (first) Climacs is not as good as Emacs, even for Common Lisp programming. This is why I am working on Second Climacs.
5:53:54
krwq
beach: I'll be interested to test it once it is usable and fairly convenient. I write most of my stuff in CL either way
5:57:14
smokeink
speaking of decent debugging, I've found this overly complicated https://www.youtube.com/watch?v=q_ARlVo-J5Q how come it's so difficult to access the local vars during debugging?? Is this feature really that unimportant ?
5:59:01
krwq
I'm seeing clim has a lot of potential, currently feel like some defaults look ugly but each time I try it it feels much better and things like clim-debugger are proving it
6:01:31
smokeink
you can break and display the local vars, but what if you need to interact with them? You need to play around with them, to see where they fail to behave as you were expecting..
6:02:19
smokeink
Personally I use a little trick that I've stolen from the book LetOverLambda : https://paste.ofcode.org/9ShVACskzbYG68W7X44RsT
6:02:52
beach
krwq: Yes, McCLIM is steadily improving, thanks to jackdaniel and several recent contributors. I am very happy with the way things are going.
6:04:08
beach
smokeink: It is hard, because Common Lisp implementations take advantage of the freedom the Common Lisp HyperSpec give them to optimize lexical variables.
6:05:22
beach
smokeink: Information about the location, type, etc, of lexical variables must be made available at runtime in order for a debugger to use this information. And it must be done in a way that does not hamper performance.
6:07:24
beach
For one thing, the compiler typically reduces the scope of lexical variables. They are not kept around after their last reference. So the programmer may want to examine the variable, but the compiler has eliminated it at that point.
6:08:27
beach
Suppose (g y) signals an error. The stack frame of this expression no longer contains X because it is no longer live.
6:10:31
beach
Different problem: (let ((x ...)) (declare (type fixnum x)) (f x) (g x)). Suppose (f x) signals an error. The programmer uses the debugger to alter X so that it is a string instead of a fixnum. The call to G may then fail by having your Common Lisp crash.
6:11:51
beach
The technique suggested in that video slows down the code a lot, so it is only acceptable as a temporary solution.
6:13:33
smokeink
okay: my point is maybe pandoric macros can be of help, perhaps a less cumbersome solution using pandoric macros is possible - it's an interesting thing to research
7:11:23
smokeink
krwq: (declaim (optimize (debug 3))) (let ((v1 2) (v2 3)) (incf v2) (break) ) ; krwq can you eval in frame and get v1 or v2's value?
7:15:07
krwq
yes, but I'd put (declaim (optimize (debug 3))) in your .sbclrc or whatever config file you use
7:16:28
smokeink
ok, I already had (declaim (optimize (safety 3) (debug 3) (space 0) (speed 0))) in my .sbclrc , but I can't evaluate v1 or v2 in frame... It always says they're unbound
7:39:52
pjb
Try with: (declaim (optimize (debug 3))) (let ((v1 2) (v2 3)) (incf v2) (break) (values v1 v2))
7:41:18
beach
smokeink: I think that's what I said before. The compiler eliminates variables that are not live, independently of the scope defined by the programmer.
7:42:05
beach
Suppose (g y) signals an error. The stack frame of this expression no longer contains X because it is no longer live.
7:42:35
pjb
Even if the variable was live, it could be eliminated, eg. if it is used only once, and side effect order wouldn't be changed by replacing its use by its initial expresion.
7:44:00
smokeink
it's good to know that one can add a (values v1 v2 ... ) at the end, then the (break) can be put anywhere in the let body
7:44:38
beach
smokeink: If the LET is in a context where its values are not needed, the compiler can remove those too.
7:44:48
phoe
which might be a bit overkill to work with vectors since it's meant for any-dimensional arrays
7:45:26
phoe
smokeink: in general, the compiler is free to optimize everything that doesn't affect the final outcome of the function.