freenode/lisp - IRC Chatlog
Search
23:01:26
jmercouris
I'll probably pilfer a bunch of code from Lispkit for the GTK port, so in a way, it will live on :D
23:03:18
jmercouris
I have your License located here https://github.com/nEXT-Browser/nEXT/tree/master/documents/external
23:03:19
AeroNotix
Cool. I'll star next and see where it goes. When it gets to the point of `make && make install` I'll probably switch to it. As I said, day job is just too demanding at the minute for anything deep and dark with non-work related programming if you get me
23:08:02
jmercouris
Your last name also didn't seem Polish, but I figured maybe you had ancestors from another country or something
23:08:35
AeroNotix
I am not sure about my surname. My mum did some ancestry stuff a few years ago and couldn't figure it out
23:10:41
rme
I need a better profile picture. I was trying to be artistic, but now I think it looks dumb.
23:12:18
jmercouris
rme: You know, that's an interesting name, we have a U Bahn Station here in Berlin named "Bellevue" it's pronounced "Bell Voo"
23:12:57
AeroNotix
Where I grew up in the UK we have a pub at the bottom of my mum's road called The Bellevue
23:16:38
runejuhl
For numbers 21-99 we say the last digit first, so 21 would be twenty-one in English and en-og-tyve (lit. one and twenty) in Danish
23:18:07
runejuhl
jmercouris: the worst thing is that kids in Danish schools have a harder time learning numbers (and math) because of the language
23:18:41
jmercouris
In literally every other language I know, numbers are consistent, except for the germanic derivatives
23:18:46
runejuhl
I've heard about teachers using the "correct" way of pronuncing numbers even though it's not valid Danish
23:19:54
runejuhl
There are a bunch more oddities about numbers in Danish. The system used to be based on multiples of 20, so 60 is "tres" (3 x 20) and 50 is "halvtreds" (2 x 20 + one half 20)
23:23:05
runejuhl
I better get to bed and catch a few zzzzs before my fever-ridden offspring decides to wake up and terrorize me...
0:46:28
AeroNotix
jasom: you should really pare that down to a very small example, I can't run that code you've given me without libraries/etc
1:21:14
earl-ducaine
Lisponians! Re: style (and maybe functionality), is there ever a reason not to use iterate over loop if you're so disposed?
1:21:15
earl-ducaine
e.g., iterate no longer mainted, not as reliable, not as fast, some think it looks barbaric, ambigously defined, keeps you from learning loop, as God intended, etc.
1:23:10
nyef`
If you're willing to pay that price, plus the price of inconveniencing anyone who doesn't use/know/like iterate that might want to hack on your code, feel free.
1:24:18
earl-ducaine
nyef`: Which is not trivial issue, as I'm learning trying to get Garnet to work on a second, non-sbcl CL, so I can get it accepted into quicklisp. Total dependancy hell.
2:02:23
aeth
earl-ducaine: If you want idiomatic Lisp instead of that loop language, what tends to work is to just write macros on top of do, do-foo, etc. Even occasionally mapfoo, e.g. I wrote a do-hash-table on top of maphash.
2:03:10
aeth
What I find is that loop is usually only necessary (as in, a fast alternative will be a mess to write) for collect. There are also possibly a handful of other, very rare forms in loop that I've never encountered.
2:03:59
aeth
do isn't really that bad, it's basically let with two additions: an optional step clause (which is functional, so use 1+ instead of incf, etc.) and a terminating condition with an optional return clause after that.
2:04:23
aeth
Unfortunately, nearly everyone uses loop, so if you directly use do, people will complain, even though do is perfectly readable if you're used to it.
2:05:22
aeth
I suspect iterate will be even worse than do in terms of complaints because at least do's built into the language and is in related languages like Scheme, too.
2:07:12
basket
In Scheme it's implemented over lambda application, but the CL version is just a C-style for loop
2:07:42
aeth
Even though under the hood it is using tagbody with go and setting the step each iteration, it behaves nearly exactly equivalent to Scheme's do form (afaik, the only difference is the implicit tagbody for local gotos, which only exists in CL), which is implemented tail-recursively.
2:08:37
basket
aeth: It isn't any more 'functional' than a C-style for loop; it's functional to the extent that the C equivalent is
2:08:38
aeth
basket: but, anyway, I treat any do without a body (which can easily be half of them, except maybe some type declarations or temporary print statements) as purely functional.
2:09:03
nyef`
On the one hand, clearly I don't use it enough. On the other, clearly its syntax and semantics aren't memorable enough.
2:10:27
basket
It is 100% like C except it implicitly assigns a single variable for you whereas in C you have to do it explicitly
2:11:12
aeth
Imo, this is a pure functional (and inefficient) way to generate the number 43: (do ((i 0 (1+ i))) ((> i 42) i))
2:11:32
aeth
There is no explicit setting there, and even though do is implemented imperatively, it could easily be implemented other ways as well. The actual under-the-hood details of the macro don't matter.
2:12:45
basket
It is working with mutable variables in ways that are a part of its visible semantics
2:13:56
aeth
basket: the difference is that in the C case, you're quite explicitly repeatedly incrementing the variable i. In the CL do case, you're returning the result of an expression.
2:14:07
nyef`
Only, you know, as an anonymous function that is immediately called with 0 as a parameter.
2:14:36
aeth
The i is internal to the do expression, and since it is not being explicitly set, I do not consider that as imperative.
2:15:23
nyef`
... Somewhere or other there needs to be a paper (or article) titled "The evolution of scopes in Lisp".
2:17:07
basket
It being implicit about it doesn't mean it isn't happening, and it isn't hard to write programs that show it's happening
2:17:30
basket
Similarly, it's not hard to write C programs that would work whether or not it worked as in Scheme with rebindings
2:19:29
aeth
If you write a program that shows that it's happening, then you're no longer using do in a functional way.
2:20:15
aeth
It's not hard to produce useful do programs without any visible side effects. Sure, the variables still implicitly mutate, but they mutate in controlled ways, which is pretty much how functional programming works under the hood anyway.
2:20:24
basket
Yes, but the fact that DO exposes an imperative interface, and it's your responsibility to only use it in a way that does not take advantage of that, means that calling DO a purely functional operator is nonsense
2:20:52
basket
It is an imperative construct that produces visible side effects as a result of operating on mutable state
2:20:59
aeth
That's how you do purely functional programming in CL. You can override it, but you show discipline and don't.
2:21:04
basket
You can use it in a functional way, the same way you can use anything in a functional way
2:22:01
aeth
You can't really write functional C to any meaningful extent. You'll be combating the langauge every step of the way.
2:23:16
aeth
And if you do that by some miracle, it'll be pretty slow because the langauge isn't made for that.
2:25:15
basket
I thought your argument was that you can use it in such a way that the mutable state is localised and presents an immutable interface, like your specific DO example
2:27:12
basket
If you're ok with hiding what's going on in CL, why would you stop at a C-style for loop but with return values?
2:28:24
aeth
I'm just demonstrating something that you can do trivially in a pure FP way in CL, but afaik cannot do trivially in a pure FP way in C.
2:28:42
aeth
Multiple return values are quite useful. C idioms to emulate this don't really mix well with FP.
2:29:59
aeth
Idiomatic C is afaik to do something equivalent to multiple return values is pass by reference and mutate. I suppose a potentially pure alternative is to return a data structure that holds the multiple values, but because C isn't GCed, you now have to manage that.
2:31:13
aeth
Actually, I think most Schemes do have multiple return values. And it even made its way into the standard document. It's there in r7rs at the very least.
2:31:45
aeth
The specification for Scheme is quite picky about what it lets in because people want it to be minimal.
2:32:08
basket
Does the standard include it because you can't implement it with lambda application, then?
2:35:26
aeth
Anyway, while FP doesn't require multiple return values, I use multiple return values all the time, *especially* in my functional CL code. If you return multiple non-boxed values (e.g. fixnums or (in 64-bit implementations) single-floats), you don't heap allocate. So it's very useful in CL pure functions.
2:36:21
_death
usage of DO constitutes of two styles, those with a body and those without.. the latter is usually functional
2:37:54
aeth
You can technically create side effects in the other forms like the return form or the step parts of the variable bindings. But this is rare, and if you're doing this, you'll probably be better off just making a regular style do with a body.
2:37:59
basket
aeth: I would argue that multiple return values are more common in imperative code than functional code, in the form of out parameters. That's certainly an imperative interface, like DO, but you can use it in a functional way, like you can with DO, so I don't see how you could defend DO as functional but object to those as imperative
2:39:02
aeth
basket: Multiple return values enforce immutability when you're using them with basic things like numbers.
2:40:00
aeth
If you return (values 42f0 42f0 42f0) it's guaranteed pure. If you return (list 42f0 42f0 42f0) someone can (setf (car l) 41f0) or something once it's returned.
2:41:15
aeth
basket: You're missing the importance here. If you're returning values, and then using those values in multiple-value-call, etc., you're ensuring that the whole section of code is purely functional because you're not using a data structure where discipline is keeping it from mutating. And, of course, if you're using data structures in CL, mutability will probably be more efficient, too.
2:41:55
basket
aeth: But you said DO was ok because you can write code that doesn't take advantage of the mutation. DO does not enforce that you don't
2:42:00
aeth
An entire section of code that works on multiple values, as returns and as parameters to a new function call, is pure. No way to cheat.
2:42:11
_death
(that is, a macro that expands to iteration in the form of self-referncing functional call..)
2:45:25
basket
It is still an imperative construct built on jumps and mutable assignment, and that mutable assignment is part of its visible semantics
2:45:25
aeth
That is a huge difference. for loops statements are necessarily used for their side effects while do is an expression
2:46:11
basket
I don't understand how you can defend DO because you can write code that is oblivious to the mutable semantics, but you simultaneously write off out parameters because they allow writing code that takes advantage of it
2:46:31
basket
DO also allows writing code that takes advantage of it, and you can also write code that is oblivious to the mutability in out parameters
2:49:16
aeth
Using multiple return values of non-mutable objects like numbers enforces purely functional code in that section of the program. The performance overhead isn't high, and afaik most of that performance overhead is already paid for by implementing support for multiple return values in the first place, whether or not you use them. Inline those pure functions and good compiler magic can happen.
2:50:05
basket
When you were talking about out parameters, you explained why your argument about DO was faulty
2:50:23
_death
here is a simplistic functional DO: https://gist.github.com/death/3ca4dab9770ffce2910f853f08ad1b66
2:50:27
aeth
Using do directly isn't perfect. It's much better to write a macro on top of do if you can get away with it.
2:51:06
aeth
It's not a contradiction to make different design compromises in different parts of the program. It's idiomatic CL to do so. CL is incredibly multi-paradigm, perhaps the most multi-paradigm language out there.
2:52:04
aeth
do, like many parts of the CL standard, can be used in a functional way but is not required to be used in a functional way. This is especially apparent in iteration, e.g. map.
2:54:02
basket
Mutating the object being traversed in a call to map is explicitly undefined behaviour in the standard
2:55:10
basket
The fact that you can pass an impure function to MAP is not the same thing as MAP's interface *forcing* you to use mutable state
2:55:40
aeth
"map nil" pretty much forces you to use a mutable state, just not the sequence(s) being iterated over.
2:56:37
basket
It calls a function that it's passed; the body of that function is not part of MAP's definition
2:56:48
aeth
It has everything to do with how map works. "map" provides support for a "nil" return so you can use it for dirty, impure things.
2:58:46
aeth
map nil is essentially CL's foreach, especially since the other equivalent, dolist, only works on lists, not sequences in general.
3:01:35
aeth
Is "for foo in foobar" pure if the language makes it UB if you mutate foobar? And if it's not pure, is there really that much of a difference between a lambda in map nil and a statement body in a for each statement?
3:03:54
basket
aeth: Yes, the specified part of its semantics are pure, provided that `foo` is a fresh binding on each iteration
3:04:48
basket
It could be implemented as a macro on top of pure lambda application; it does not take advantage of mutable state
3:06:09
aeth
The do operator is more of a super-iteration thing that wants to make everything possible. If you want to build your own iteration, pure or impure, and restrict it, you can directly use do, or use macros that probably directly use do like dotimes or dolist (although they're not required to use do)
3:07:52
basket
aeth: And you can implement mutable semantics on top of lambdas, too; that's just turing completeness
3:10:31
aeth
CL is basically a language for writing (mostly) efficient declarative languages, while not itself being declarative (which wouldn't really be possible, there are many kinds of declarative languages)
3:11:08
aeth
I'm using the definition of declarative that includes FP under declarative. Wikipedia uses this definition.
3:12:31
aeth
Another possible phrase other than 'declarative languages' would be 'fifth-generation programming languages'. This is sufficiently archaic enough that it might have been an explicit goal of CL.
3:13:47
whoman
some people like to work with limbs, some like to play with guys. others prefer the clothings or outer garments, while others yet freely form their style
3:14:01
aeth
You want ugly mutability to be possible in something like CL's do because you might need it when writing an interpreter or compile-to-CL compiler or whatever you're writing. If you want it to be functional, either restrict your use of do (through discipline) or build a pure macro on top of do (trivial)
3:15:47
whoman
when skeleton protrudes flesh, we have horns and other undesirable jagged and bony features. it is good that the system works right all together with itself. CL is ultra-powerful about that
3:16:53
dmiles
aeth: speaking of mutibility.. i have be struggling within DO deciding between compiling to prolog to use a mutable loop vs a non mutable loop :) non mutable loops are ugly to look at and debug
3:19:10
tko
which lisp do you guys prefer , I've been using clojure and at times elisp but I'm about to try common lisp
3:19:46
nyef`
tko: This is a Common Lisp channel, so the argument here will be about particular Common Lisp implementations. SBCL being the best, of course. d-:
3:20:14
dmiles
aeth: well i started out basing everything on tagbody compiel design for a worsecases jumping arround.. but indeed i might simplify it
3:20:15
tko
aha oh ok, this is about my first time on irc, I'm connecting through emacs and just searched "lisp"
3:21:04
aeth
tko: #lisp is for Common Lisp and possibly direct historical precursors to Common Lisp, ##lisp is for the Lisp family of languages.
3:23:23
nyef`
tko: Also, whatever version of SBCL you just installed is probably out-of-date already. Last release was SBCL 1.4.2. Current git HEAD is 1.4.2.215 or so.
3:24:00
aeth
dmiles: What I personally find useful for advanced things (and Prolog would count) is to write a lot of macros, and perhaps use those macros in other macros.
3:24:06
dmiles
not that nayone aked but this is my DO / DO* https://github.com/TeamSPoon/wam_common_lisp/blob/master/prolog/wam_cl/block.pl#L86-L103
3:25:25
nyef`
tko: But don't let that stop you. My primary installed SBCL is 1.3.8.26 or so, and I keep a 1.0.23 around for some things.
3:27:54
dmiles
aeth: i write in imperative prolog about 50/50 from declarative.. i think they only teach declaritive
3:29:11
dmiles
aeth: my favorite cartoon: http://www.pathwayslms.com/swipltuts/teacher/images/cartoon_08.png
3:29:38
nyef`
tko: Fair enough. I'm looking forwards to the 1.4.3 release, as a bug that I really need fixed just got fixed recently. As in within the last twelve hours.
3:30:37
aeth
dmiles: I guess people who learn Lisp in school think it's about purely functionally processing lists (which is wrong on multiple levels) and people who learn Prolog in school probably think it's... sort of like SQL for classical logic, I guess. Define some relations and deduce things in a query.
3:32:46
aeth
nyef`: If you like abuse of SQL, wait until I complete the transitioning of my entity-component-system to an in-memory database. Then you'll see some fun abuse of queries.
3:34:51
aeth
dmiles: Does the MOP let you abstract over the concept of a slot completely? I might make an "ORM" of sorts to make things easier to debug and inspect interactively.
3:35:46
dmiles
so far as a can tell so far, it does let me abstract over the concept of as slot (or field)
3:36:58
aeth
well, if I can just say that the slot foo is really (aref whatever (id-to-index 42)) and slot bar is really (array-row-of-4 something-else (id-to-index 42)) then nothing's stopping me from writing an "ORM" of sorts.
3:37:38
dmiles
teh difficult part for me (when putting objects into the cold storage of the database) is when people are messign with cones suppoedly in a slot
3:38:37
dmiles
i have to keep such a CONS in warm livving memory.. and make the coldly stored slot value a ppointer to live memory
3:39:04
aeth
In case I was unclear, (array-row-of-2 some-array some-index) returns (values (aref some-array some-index 0) (aref some-array some-index 1)) and the setter is similar, except it'll take in n values (2, 3, or 4 depending on which one)
3:40:30
aeth
dmiles: That's not an issue for me, since my "database" is just going to be abstractions over 1D or 2D arrays, depending on what's being stored (i.e. either a simple value or an array row)
3:41:20
aeth
It can, of course, be written to disk for persistence, such as saving a game, although maybe save-lisp-and-die should be the only way to save a game :-p
3:43:17
aeth
Types will be a bit of a problem because only character and bit arrays are guaranteed. In fact, with my approach, character arrays themselves are problematic.
3:43:21
dmiles
what is returned by (values (aref some-array some-index 0) (aref some-array some-index 1)) going to be the values copied over or more liek places?
3:44:01
aeth
At the moment, I only put in things that are (probably) specialized arrays so I don't have to worry about it. e.g. single-float or various integers or bits
3:44:25
aeth
If I want to support more types, I'll have issues, and I'll also have to wrap around check-type in places etc.
3:46:35
aeth
I'm pretty sure the only time you copy in CL is explicitly, e.g. copy-foo (a struct foo automatically define a copy-foo) or copy-seq
3:47:50
dmiles
before you said specialized typed arrays i was sorta was imagining that you were copying a reference .. like a pointer to the nth index of the array
3:49:56
dmiles
i was thinking about how in some situations seeing what is even there at that refenrce is not needed until it was needed
3:52:17
dmiles
Bike any thoughts on aeth's and my question? <aeth> dmiles: Does the MOP let you abstract over the concept of a slot completely?
3:52:47
Bike
i'm not sure what that means. you can definie pretty different slot concepts, at least.
3:52:52
aeth
Well the actual use right now is to essentially copy with-accessors, but with the addition of an index because the accessors all have an additional index, with three possibilities: (aref foo index) (aref foo index another-index) (array-row-of-n foo index) where n is 2, 3, or 4 at the moment (doing it generally cannot be as efficient). The first two return a value, the third returns n values. The first two set one value, the third sets n val
3:53:17
aeth
the third sets n values. (These are accessors, setf array-row-of-n is defined for sizes 2, 3, and 4)
3:54:03
beach
dmiles: Your recent questions make me more and more convinced that you don't know the semantics of Common Lisp.
3:55:23
beach
Well, not a question this time, but things like "like a pointer to the nth index of the array".
3:56:18
aeth
an example of my abstraction in its current state: (with-selection ecs (entity-id) ((location (old-location old-location :row-of 3) (location location :row-of 3))) (setf old-location location))
3:57:59
aeth
accessors can be ":row-of n" where n is 2, 3, or 4. These work with multiple values (either providing them or requiring them in the setf). It can also be e.g. "1" such as (location.y location 1) and it can also be something simple if it's not a 2D array, e.g. (foo? foo?) where foo? is, unfortunately a bit of 1 or 0 instead of a boolean. This is one place where the abstraction leaks. bit arrays are optimized, boolean ones are not.
3:59:57
aeth
An object abstraction over this would probably be to get everything that's defined for some ID, and pretend that it's one object so it's easy to do something like e.g. print the object or inspect it in slime. This would be very easy if slots can return and set multiple values. I'm not sure if they can. And if they can, would it break the SLIME inspector?
4:02:21
aeth
That's not that big of an issue because there are two ways to access the 2D arrays, either one slot at a time (like my example where I bind a location.y) or as multiple values
4:04:01
aeth
I may have to define official names for them, though. At the moment any slot names for a slot in a 2D array are only bound at the accessor level, i.e. (location.y location 1) binds (aref location some-index 1) to location.y in a symbol-macrolet not unlike with-accessors
4:04:14
aeth
dmiles: Well, not really, since that would require bounds checking and this is for a game engine.
4:05:39
aeth
dmiles: I defined array-row-of-2, array-row-of-3, and array-row-of-4 as accessors (both to get values and set values). You can use them improperly. If you e.g. (setf (array-row-of-2 some-array-with-length-four-rows 42) (values 1f0 2f0)) it'll just set the two fields. If you do the reverse and do array-row-of-4 on something with length-two rows, it will fail with a runtime error unless safety is 0, which no one should ever use.
4:07:10
Bike
i don't understand what multiple values have to do with slots. you defined some multiple value accessors, no big.
4:08:10
dmiles
aeth: oh, i hear you, you are thinking about wether or not it is sensible to create an accessor
4:08:34
aeth
Bike: If I can abuse the MOP to work somewhat like this as well, I create an alternative interface into the database that's more first-class within the language, so I could have more debugging power.
4:08:59
dmiles
aeth: sensible in the sense that there is at least some translation in which debugging would be livable
4:09:28
Bike
i don't see what multiple values adds to debugging. they're not fun to debug, in my experience.
4:09:51
Bike
if you were dedicated, you could probably define an alternate standard-object with a completely overriden allocate-instance so that slot values are stored in an array or whatever.
4:10:34
jasom
anyone know of a decent library for making a fininte state machine in lisp? something like a LABELS inside LOOP would be nice. Mutually recursive functions work with proper optimization settings, but I've been told not to do that in common lisp :P
4:11:06
aeth
Bike: well, I was wondering if I could make a similar interface through CLOS, although I guess I *can*, just as accessors, rather than as slots, and the slots would have to use the direct one-value accessor.
4:11:31
Bike
yes. that's what i'm saying. i don't understand why you want multiple value slots when you already have multiple value accessors.
4:12:41
aeth
The main thing I'd want from CLOS is a way to see an ID as an object rather than a bunch of arrays that mostly contain irrelevant values. It doesn't even need to be efficient, since ideally it'd only be used for debugging purposes like defining a print-object.
4:13:48
jasom
nyef`: well I find tagbody looks good for writing out longhand, but labels with a loop has the logic inside-out and is problematic to indent automatically.
4:14:39
aeth
Bike: Yes, but what I would want is a CLOS object that can have slots called e.g. location.x, location.y, location.z, etc. And then if I inspect that object, location.x will show the value of (aref location (id-to-index entity-id) 0) and location.y would show the value of (aref location (id-to-index entity-id) 1) etc.
4:15:30
aeth
It is an entity's position in the world. 3 single-float values, normally. Some systems use double-float if the worlds are massive.
4:16:15
Bike
so you want an object that doesn't actually store its position, it just stores an index into some global array.
4:18:04
aeth
But I would like to be able to use the SLIME inspector, have defined print-objects, etc.
4:18:18
dmiles
having slots is so you can at least feel like you are holding an object in your hands?
4:18:22
aeth
i.e. I would like to make a CLOS object whose slots are accessors, if that's at all possible
4:19:59
dmiles
having slots is so you can at least feel like you are holding an object in your hands? I see yes.. so you can use things like print-object can even change values on the target if needbe
4:20:06
jasom
" defstruct without a :type option defines a class with the structure name as its name. The metaclass of structure instances is structure-class. "
4:20:28
aeth
Bike: I can have an entity with the label cube which is mapped to the ID 42 which is mapped to the index 37 (well, I haven't written the third part quite yet, but that's coming very soon... at the moment IDs are the indices). The entity doesn't exist. There are many arrays.
4:21:49
Bike
perhaps i should be more explicit. there is no need for you to use print-object for printing some non-object. you can have your own printing function to print it. this is no loss to you since nothing could possibly call print-object on your object because there is no object.
4:22:28
Bike
if you wanted, you could define a kind of proxy object that just stores 37 and defines a bunch of accessors, but you haven't, which presumably you have some reason for.
4:22:35
aeth
Well, I could (if I modify my query system to allow for an "all") write something called print-entity that queries all of the places where 37 is a valid index, and prints it as if it's one object.
4:24:58
aeth
But I'm wondering how deep I can go in making a proxy object, which could have uses where the query macro(s) fail, although the performance would probably not make it anything useful outside of debugging.
4:25:27
Bike
you can obviously define a proxy object and define a print object method on it that prints whatever you want, and the object having data in its slots is immaterial.
4:25:28
aeth
If I could actually have proxy slots instead of proxy accessors, I could use the SLIME inspector itself.
4:26:40
Bike
i think swank has some kind of interface you can customize, but it might not be exported.
4:28:00
aeth
It would be very useful (more useful than just a print, which I can do through a query macro with some small changes) if I could somehow inspect an object and see the slots as if it was an object, even though they're just slots in various arrays.
4:35:10
aeth
Bike: thanks, looks like going beyond that it's defmethod all-slots-for-inspector ((object standard-object))
4:36:06
Bike
shorter version: if you want to inspect weird things, you don't need to parlay that into sweeping ideas about clos
4:38:56
aeth
It looks like swank uses the MOP, so if the MOP is powerful enough to change the concept of what a slot is, I should be able to make it SLIME inspectable without having to modify swank. i.e. if I can make a slot a call to an accessor (well, actually two since I don't actually know what the index is, only what the ID is)
4:40:59
aeth
The inspector is just what I know would be useful now. If I use the MOP, it's possible that there's a future use to the object abstraction.
4:49:22
aeth
One thing I could do that's probably easier and even less efficient is to have a query object, i.e. query into an object or something.
4:49:42
aeth
This is probably the first thing that I would have thought of in a less powerful language without a MOP
4:55:12
aeth
i.e. instead of having the object constructed via the MOP to directly access the slots, I construct an object in a similar way that I would do something like print-entity, except returning an object with populated slots from the accessors instead of writing to a stream.
4:58:36
tko
hmm I just started CL a few minutes about coming from Clojure but I'm curious what this convo is all about
4:59:00
tko
I don't know anything about MOP / CLOS, although CLOS is one of the first things I wanted to look into with common lisp
5:01:24
aeth
tko: I have a very elaborate data structure. Because it's elaborate, it's not easy to inspect the contents in an intuitive way.
5:02:09
aeth
One way to inspect the contents in an intuitive way would be to allocate a temporary standard-object (i.e. an object that's created with a CLOS defclass) that somehow has the same contents because those are trivial to inspect.
5:03:24
aeth
Things are inspected through SLIME, the CL IDE for Emacs. swank is the protocol that SLIME uses to talk to a running CL.
5:04:17
aeth
Technically, other editors and IDEs can write their own SLIME-like thing using swank, but nearly everyone programs CL in Emacs+SLIME.
5:05:35
tko
so the temporary standard object would be like an object that contains all the values of your structure (or less) and that is organized in a way thats easier to read or interpret?
5:06:30
aeth
It would combine all of the pieces of data that represent an entity into one object. Which would be 1/2500 of the data structure, if it's filled to the arbitrary constant cap I set for it.
5:09:26
aeth
I think Bike's alternative approach would be to define methods that swank uses that are ultimately used by the SLIME inspector, i.e. create new things that swank will dispatch on as various relevant defmethods
5:09:40
nyef`
aeth: Or you could "just" declare for SBCL and unportability and implement an INSPECTED-PARTS method.
5:10:54
Bike
i mean, with the whole novel clos thing you're still relying on the inspector working in some particular way with slots
5:11:21
aeth
Would that work, though? I want to inspect one particular ID stored in a large data structure. A simpler example would be e.g. inspecting one node in a tree by providing the tree and what to look up into the tree.
5:13:11
aeth
But since it's only used for debugging it doesn't need to be efficient. I could just allocate an object from a query and then inspect that. Although then if I'm inspecting it live I'd have to do some trick to avoid filling the heap.
5:15:08
aeth
Bike: Hmmm... Or... I could be really lazy and make an object that encapsulates two objects...
5:15:46
Bike
so that you can take advantage of all the standard customization facilities that arne't real, makes sense to me
5:16:24
aeth
Bike: however non-standard things are, my own solution would be even more non-standard and even less supported
5:17:16
Bike
well, my main advice is to try something out rather than write a dissertation over the course of two hours, i'd do well to remember that
5:24:10
dmiles
aeth: well i am glad that I was correct in imagining that you were copying a reference setf-able place
5:29:36
aeth
dmiles: Well, I'm making local bindings to arrays (which does not copy the arrays themselves), and then using symbol-macrolet over accessors that are too complicated for with-accessors (such as aref or my custom array-row accessors)
5:31:40
dmiles
you know for these synthesized objects you are thinking about there is a system for synchronising them.. https://bitbucket.org/tarballs_are_good/cl-locatives
5:32:37
dmiles
you point the object at your proxy and your real thing.. when your proxy changes.. so does the real thing
5:33:03
earl-ducaine
Out of fairness to other CLs and the libraries in the Quicklisp repo, the problem that I described as 'dependancy hell' (for ccl) was only that I was using the wrong CLX library. Once I installed a compatible one using ASDF everything else worked.
5:34:28
aeth
with accessors is the thing that can turn (foo some-object) into foo, so you can (setf foo 42) and it's really (setf (foo some-object) 42)
5:36:10
dmiles
hrrm the package i was thinking of was actually was more in depth.. pjb suggested it to me the other week)
5:36:47
aeth
I took the recommended way of implementing with-accessors and modified it to work on (aref a 42) (aref a 42 0) and my custom array row accessors
6:10:05
aeth
dmiles: proxy with-accessors? as in an object that can call with-accessors (or, actually, with-entity-accessors in this case) on itself every second or something, to keep a somewhat up to date picture of what's going on? Could become a threading mess, though.