freenode/#lisp - IRC Chatlog
Search
22:00:46
skidd0
or, how can i directly manipulate the lack.response reesponse structure before sending?
22:15:28
jcowan
Well then, why bother to have external symbols at all and require a (slightly) more verbose syntax to access them from other packages? (This is not a rhetorical question.)
22:34:02
skidd0
to get access to the lack.response, would I want to do something :around the CALL method?
22:56:39
Bike
skidd0: it doesn't replace, but if your :around method doesn't call-next-method the original method will not be called
23:56:10
skidd0
I'm getting an error where hunchentoot doesn't know how to handle options http requests
1:28:34
kooga
(setf (lack.response:response-headers *response*) '(:access-control-allow-origin "*"))
1:29:52
skidd0
also, i figured out that I needed to add a options verb to the routing library i'm using (snooze)
4:00:27
beach
In a first-class global environments, I have a table called slot-readers and a table called slot-writers. These tables are indexed by symbol names.
4:00:29
Bike
in ecl and clasp direct instances of standard object use a hash table from slot names to locations.
4:01:19
beach
... then those tables work like the function entries in the first-class global environment.
4:02:22
beach
slot-value with a constant slot name gets rewritten to (funcall (car (load-time-value (find-reader-cell <name>))))
4:03:19
beach
I think SBCL must do the same, modulo the first-class global environment, and the function cell.
4:08:29
Bike
also wait, what happens if you have like (defclass foo () ((x :reader foo-x))) (defclass bar () ((x :reader bar-x))) (slot-value some-object 'x)
4:11:46
beach
In my scenario, (slot-value some-object 'x) would be translated to something like (funcall (car (load-time-value (find-reader-cell 'x))) some-object) and the cell would contain a generic function that dispatches on the class of some-object.
4:11:55
Bike
if the effective method just calls the accessor method, the discriminating function just reads from or writes to the slot directly
4:15:22
Bike
also the fast path i mentioned only happens if it's an object standard enough to not have custom slot-value-using-class methods possible. forgot that caveat
4:15:35
beach
Also, until a few years ago, I used slot-value for "internal" access, and slot accessors only for the public interface.
4:16:29
Bike
i'm not sure what the main reader method can do besides calling slot-value-using-class, i guess
4:18:17
beach
He had classes where slots were implemented as special variables so as to make it thread safe.
4:18:55
aeth
What I tend to do for internal setting is :accessor %foo :reader foo because that way I can use with-accessors on %foo without surprising behavior (i.e. only being able to set)
4:20:59
beach
So, in that case, SLOT-VALUE can not be optimized to do a direct slot access, of course, since there is no slot-location.
4:21:36
Bike
i have been thinking on and off about adding more interdependencies between methods in fastgf. for example, within a method body replace accessors with direct slot reads when possible, and then recompile the method if there's a change so it works transparently
4:21:50
Bike
i bet it would make it faster, but it would be pretty involved to maintain everything correctly
4:26:01
beach
So, I think I'll have to add SLOT-READERS and SLOT-WRITERS to the SICL first-class global environments.
4:31:02
beach
This stuff is frequently done "manually": (defgeneric foop (x) (:method (x) nil) (:method ((x foo)) t))
4:33:03
beach
Bike: Let me take a break and think about that idea. I think better when I am not at my computer.
4:56:57
beach
minion: memo for Bike: This is totally brilliant. I am convinced that it works. 1. Figure out whether any implementation does it. 2. If not, figure out what happens to the methods and call history as a result of DEFCLASS, and DEFTYPE. 3. Write it down. 4. Submit to ELS.
4:59:20
beach
minion: memo for Bike: There would be three kinds of methods: always false, always true, and requiring some action (for example if there is a DEFTYPE that expands to a compound type).
8:12:34
makomo
hah, today is the day when i finally used a full spec instead of just a symbol for ONCE-ONLY
8:30:57
jackdaniel
. is just a notation for a data structure (like #(1 2 3) is for vector), it is not a function
8:34:01
no-defun-allowed
if you do (a (. b c)) you break the expectations of depth - is it (a b . c) or (a (b . c))?
8:35:13
aeth
If it was anything else it'd probably be #.(a b) but then you wouldn't have it combined with the list representation and (a b . c) wouldn't be an obvious representation for a dotted list
8:36:56
oni-on-ion
perhaps i dont see the purpose of (a b . c) aside from being a bit strange considering lispisms
8:39:05
oni-on-ion
phoe: yeah, but its just syntax for cons isnt it? thats the point here, why its in between a and b and not prefix like everything else of lisp system
8:39:12
phoe
(x y z a . b) denotes the same thing, except three conses are consed on top of that to form an improper list, with CARs X, Y, and Z
8:39:50
no-defun-allowed
*when you're parsing, you see a paren. ooh, a list! let's see the first element. A it is. see the rest and stuff it into a cons. you see a B. see the rest again. you see...oh god a period! just return the C. cons B and C, you have (B . C). cons A to it, you finish with (A B . C)
8:40:52
ggole
Seems like confusion between reader syntax, which directs the reader to construct list structure, and the functions used to construct it
8:42:43
phoe
once, to read the cons with CAR A, once, to read the cons with CAR B, once, to read the cons with CAR C
8:43:10
phoe
. tells the reader "okay, you don't need to cons more, just stuff this thing after the period in the CDR and you're done"
8:43:26
oni-on-ion
so there is purpose to it being the syntax in the form of "(a . b)" and not "(. a b)" ?
8:45:30
oni-on-ion
ahh =) i think i get it now =) thanks. i was just trying to sleep and thought of this. quite cool actually ^_^ always really liked linked lists.
8:47:21
phoe
the concept of . is lost by the time you leave the reader and you get the read expression
8:48:21
phoe
you can only infer that there was a . somewhere by parsing the lists made up of the conses, and by noticing that some CDR is a non-null atom
8:48:56
phoe
and in this case, there's no difference between the result of the function call (CONS 'A 'B) and the result of the reader reading "(A . B)"
8:49:30
phoe
so the same result, a cons whose CAR is A and CDR is B, can come both from a #'CONS call and from the reader's operations.
8:51:36
makomo
what does everyone think of the following "problem": say i want to swap two rows of a matrix and i want a neat set of places for my interface. so i define something like (mrow mat i) which returns a fresh vector representing mat's i-th row, and ((setf mrow) vec mat i) which sets a mat's i-th (receiving a vector as a value and doing it element-wise).
8:51:39
makomo
but then, let's say i want to swap a mat's rows without creating an intermediary vector. (rotatef (mrow mat i) (mrow mat j)) would create a fresh vector since it evaluates (mrow mat j) before assigning. i could define my own (swap-row mat i j) but then that doesn't play nicely with places.
8:51:41
makomo
in general, the problem is that setf isn't "fully composable", because the expansion for a place cannot depend on the the form that produces the value to set. for example, i would like for (rotatef (mrow mat i) (mrow mat j)) to expand into a fully in-place swap of the rows (composition of smaller rotatefs). (rotatef (mrow mat i) (get-some-vec)) however would behave just as before.
8:51:43
makomo
so basically, we would have the ability to analyze the value-producing forms as well and generate expansions of places using that information.
8:55:21
makomo
i don't know whether this would make SETF better or worse. you get more composability and flexibility but perhaps SETF would become irregular, as you would have no proper separation of (1) eval the value-producing form and (2) set the place's value using its expansion and the produced value
8:58:32
makomo
so you could encode any conceptual "assignment operation" into a SETF call, and let the expander generate code that would do that work
9:00:09
makomo
phoe: yeah, but that's what the thought experiment is about. the ordering between individual assignments would still stay, but there would be no separation between the two phases of getting the value and putting the value somewhere
9:00:59
makomo
because an expansion might be able to do a better job when there is no separation (in this case, i wouldn't have to cons a new vector just to swap 2 rows)
9:01:11
phoe
theoretically you have control over SETF in form of define-setf-expander, but I think it would be somewhat confusing.
9:01:33
makomo
phoe: that's still not enough, because a setf expander doesn't have access to the value-producing form
9:01:53
phoe
for example, the expansion of (setf (subseq #(0 1 2 3) 0 2) (subseq #(5 6 7 8) 0 2)) also conses up a new vector.
9:02:18
phoe
this could be replaced by a very small and efficient loop, but SETF is too limited to be able to do that.
9:05:52
aeth
Notice that (1) the row size is in the name of the setf and (2) I use multiple values as the input
9:05:56
makomo
i thought about VALUES as well, but it won't work with "compound objects" that have a large number of "components"
9:09:26
aeth
Swapping a row is pretty simple if you're willing to put it in a function. Very elegant, actually, since you can just swap the elements via PSETF in a loop.
9:09:35
makomo
the cool thing is that this "composable setf" could also expand into further such setfs, etc.
9:10:34
makomo
aeth: true. that's what i ended up doing in the end, but it doesn't play nicely with places. also, i have NxN matrices, so i can't use PSETF
9:10:54
makomo
unless you were thinking of using PSETF for the swapping of the individual elements, in which case you can just use ROTATEF
9:13:16
makomo
now imagine a composable ROTATEF, you could swap literally anything without inducing overhead. swapping two matrix rows would just expand into multiple ROTATEFs between the individual elements
9:15:46
aeth
(let ((m (make-array '(2 4) :element-type 'single-float :initial-contents '((1f0 2f0 3f0 4f0) (5f0 6f0 7f0 8f0))))) (rotatef (array-row-of-4 m 0) (array-row-of-4 m 1)) m) => #2A((5.0 6.0 7.0 8.0) (1.0 2.0 3.0 4.0))
9:16:02
russellw
If I do (setq x 1) at the top level with no previous declaration of x, it actually works, to my surprise. What kind of variable does that create? Is it a special variable, the kind that would be created by defvar?
9:17:39
makomo
russellw: it probably does ""the right thing"" and proclaims the variables special, but i don't know for sure
9:18:16
makomo
aeth: that's a nice trick for a small number of components, but for larger Ns, you're back at consing and what not
9:18:21
aeth
makomo: https://gitlab.com/zombie-raptor/zombie-raptor/blob/b90f23cf6168f892fce8fd980649eaf882662acb/util/array.lisp
9:18:23
heisig
makomo: You could use a compiler macro for (setf mrow) that eliminates the intermediate copy if given a call to mrow as an input.