libera/#commonlisp - IRC Chatlog
Search
9:11:04
lisp123_
What new concepts are taught in AMOP that are not an application of Macros or other basic programming concepts?
9:15:03
rudi
but in the end, it's all macros and basic programming concepts ... I don't know what to tell you except to look at the table of contents and introduction chapter :)
9:15:32
lisp123_
Because (from my very rudimentary understanding), objects can be represented by closures - so I get that CLOS etc. are well refined object oriented systems, but is there any new programming concepts in AMOP? I only say this because eveyrbody says its one of the best books in CL, I have a copy but haven't started reading
9:16:08
loke[m]
Possibly, but I don't understand the question. AMOP is about topics which are absolutely not just functions and macros. It's about object orientation, and a specific implementation of it based on generic functions.
9:16:34
ecraven
this is the same as saying "I understand assembly language, does any other language add anything useful beyond that"? and the answer is (for probably any language): yes, there are valuable new things to be learned ;)
9:18:07
ecraven
CLOS offers a very interesting model of extending object orientation in various directions. for example, generic functions are a very useful concept (which is not very widespread outside of a few specific languages)
9:18:38
lisp123_
loke[m]: Okay, so basically there's a lot more to object orientation, which I seem to be missing, hence I don't fully get why its not "more advanced" version of the basic concepts I've learnt so far
9:18:57
ecraven
loke[m]: fortunately, I haven't had to deal with python in detail, I haven't seen anything I didn't see in other languages too
9:20:10
ecraven
closures might be an implementation technique for OO, but the concepts are unrelated to closures
9:20:40
loke[m]
`struct` in C is basically a container of values, which can be emulated uing a closure.
9:24:18
loke[m]
In fact, in CLOS, the ability to arrange members (called slots) in classes is probably the least interesting aspect of it.
9:25:16
loke[m]
People should probably learn CLOS by using generic functions and the standard datatypes. and look at defclass later.
9:27:14
lisp123_
What stood out to me in the intro of AMOP was this - "Rather than supplying the user with a fixed, single point in the space of all language designs and implementations, we would instead support a region of possible designs within that overall space"
9:27:47
lisp123_
So I figured the status of the book as one of the very best in CL came from that, and hence the original question
9:29:11
loke[m]
lisp123_: I'm currently implementing some code in Kotlin which does not have generic functions, and trust me, the when-tables I have to create for every single function is ridiculous. While it's certainly possible to replicate the behaviour using essentially if-statements everywhere, it's similar to arguing that you don't need support for floating point numbers because you can just use NAND.
9:29:12
lisp123_
Like the above sentence to me sounds more than just a very good book on OO, but rather something even more fundamental to all of computer science
9:31:19
rudi
it describes ways of subclassing classes, slots, generic functions, etc., and implement different behaviors when you use such a class, call such a function, etc.
9:33:52
lisp123_
So looks my takeaways are - OO is a much important concept than just its surface level definitions and (b) taking an OO approach to writing programs in the sense of 'Metaobjects' is profoundly better than the basic approach we get taught first in terms of everything is just building upon procedures and functions
9:34:46
_death
lisp123_: it is about introducing points of extension for the user (application programmer) so that a variety of decisions can be made.. it is done in a principled way to allow for efficiency and consistency in the face of different extensions.. the usual choice would've been to disallow extension (closed systems)
9:36:28
lisp123_
_death: Thanks for that. Do you have examples of extensions? Is that something like evaluation order (e..g for functions evaluate all arguments before the function)
9:40:18
_death
lisp123_: the AMOP book has examples.. for example it's easy to write an object browser (an example of MOP giving means of introspection) or a system allowing persistent instances.. being able to change the evaluation order is also a good example, if you apply MOP principles to your evaluator (the Paepcke book I mentioned has a paper about this)
9:41:17
beach
I think everyone missed the totally essential part of the AMOP namely that it implements CLOS using CLOS.
9:45:14
beach
This aspect is what makes Common Lisp bootstrapping interesting, to me at least. It means that the best way to describe how Common Lisp works is that it is the result of executing Common Lisp code. And then the best way of implementing Common Lisp is by extension actually executing some Common Lisp code. Which is exactly how we do it in SICL bootstrapping.
9:47:51
lisp123_
That sort of sounds like an advanced (compound?) version of how lisp is said to be/have a meta circular evaluator?
9:48:44
beach
Yes, but the typical metacircular evaluator is only concerned with ordinary functions, and it doesn't handle classes.
9:48:59
lisp123_
(if lisp allows for primitives to be evaluated meta circurlarly, then MOP/CLOS is for compound objects)
9:49:24
lisp123_
Okay, that's pretty cool and I guess what I was after in terms of what's special about AMOP
9:49:39
beach
I wouldn't say that. As many pointed out, generic dispatch is very useful for built-in classes as well, like numbers.
9:51:25
beach
Now, at the end of the book, and also in their PCL implementation, they tweak the otherwise metacircular code to make it operational. As it turns out, it is already operational, provided you execute it in a host Common Lisp system with an existing CLOS implementation. Which is what we do in SICL bootstrapping.
9:53:22
beach
So we can evaluate forms like (defclass t () () (:metaclass built-in-class)) and (defclass standard-class (...) ...)
9:54:51
lisp123_
So you define your own SICL implementation, and then run it within an existing CLOS implementation?
9:55:26
lisp123_
And afterwards, somebody else can create their own implementation by redefining CLOS in your SICL implementation?
9:56:26
_death
AMOP taught me that (most of) CLOS is simple and elegant, even if production-quality implementations and some corners are hairy
9:56:56
beach
As I wrote in one of my papers, the entire chapter "Living with circularity" is not necessary.
9:58:06
beach
_death: Sure, but most warts are due to their assumption that CLOS is going to be added to a pre-ANSI Common Lisp implementation. We fixed those warts.
9:59:52
beach
That won't teach you much, as my (defclass t... example shows. The tough part is bootstrapping.
10:00:28
lisp123_
beach: I figured it would be somehow "better" to bootstrap from SICL than from another implementation, even if they could just simply repeat what you did
10:02:18
beach
_death: Well, there is also stuff like generic dispatch, which is an implementation detail, but an important one for performance.
10:03:30
lisp123_
Okay, so my conclusion are as follows. (1) Book on Algorithms -> Teaches basic, primitive ideas of how to code directly with hardware & how to write efficient code. (2) SICP -> Teaches the value of abstraction and building compound objects / higher order functions etc. (and various discussions on that), AMOP -> Teaches the value of organising software / implementations in an 'object' style and the various considerations for that (i.e. for l
10:03:30
lisp123_
arge projects, this organisational advantage of OO code should not be discounted and regarded just as a set of procedures / macros over the basic primitives)e value of organising software / implementations in an 'object' style and the various considerations for that (i.e. for large projects, this organisational advantage of OO code should not be discounted and regard
10:04:20
_death
beach: right, some of the hair in production-quality implementations is due to making things efficient
10:06:35
lisp123_
( rudi & loke[m] - no not for homework, just wanted to have a quick summary in my head as I went about reading things. I will hopefully get to reading AMOP soon, saving it for a nice holiday)
10:06:57
_death
beach: I meant that, e.g., Closette was a simple program and it shows a simplified CLOS.. other treatments implementing CLOS-like object systems are too far away from it
10:10:56
mfiano
lisp123_: Object orientation covers more ground in CLOS than class-centric OO languages. Generic functions, which are represented by class metaobjects, form the primary way of [re]defining behavior, and this system is integrated into the core of the language. AMOP is a nice book for all of the reasons already mentioned. It is however, a technical book, and the writing style and number of errors
10:16:11
lisp123_
mfiano: Thanks for that. Yes, it was a bit hard to read so I put it off for just now. It does seem like I need to have more appreciation for generic functions than I have thus far, so that's one of my takeways
10:18:12
mfiano
I didn't have an appreciation for generic functions or the rest of CLOS until I actually started working on my own projects.
10:22:09
mfiano
Playing around with generic functions to see how they work, even if it's just using the "on-stage" (AMOP metaphor) interface, and then integrating them into a real project, is also eye-opening.
10:23:53
lisp123_
I had some experience when I was writing some card games in Swift (for example a generic sort function which then is specialised on which type of cards one is using or what are the rules of the particular game) - that was definitely a great experience for me
10:25:28
lisp123_
I moved away from CLOS recently, but now I think that was just because I designed the objects badly
10:25:37
mfiano
I am not familiar with that language, but generic functions in CL, even without getting into meta-stuff, is very flexible, with auxiliary methods, method-combination, etc
10:27:07
lisp123_
One thing that tripped me up with axuiliary methods was that they didn't have access to lexical scope
10:27:35
lisp123_
within the main method or other auxiliary methods -> but now that I have learnt macros, I can implement that myself
10:29:09
mfiano
Well, :around methods are for when you need to replace the primary method, which can optionally call out to the primary method, so you can lexically bind it's result and refer to it
10:31:51
mfiano
Well unlike :before and :after that runs before or after the primary method, an around method _replaces_ the primary method...the return value of the around method is used.
10:35:17
Shinmera
? it doesn't replace the primary method. It goes around all of the other methods, including :befores and :afters
10:36:35
mfiano
I guess that was worded poorly. I was referring to this official passage: "An around method specifies code that is to be run instead of other applicable methods, but which might contain explicit code which calls some of those shadowed methods (via call-next-method)."
10:38:33
Colleen
Clhs: section 7.6.6.2 http://www.lispworks.com/documentation/HyperSpec/Body/07_ffb.htm
10:39:48
Shinmera
lisp123_: https://upload.wikimedia.org/wikipedia/commons/4/43/Method-combination.png
10:40:43
rain3
https://lispcookbook.github.io/cl-cookbook/clos.html "Think of it as an onion, with all the :around methods in the outermost layer, :before and :after methods in the middle layer, and primary methods on the inside."
11:31:39
lisp123_
I am having issues copying a vector which has a fill pointer, and then doing vector-push-extend on the new vector
11:33:56
lisp123_
If sequence is a vector, the result is a fresh simple array of rank one that has the same actual array element type as sequence.
11:34:25
lisp123_
looks like the :adjustable property doesn't get copied across, but I don't see particular mention of that above?
11:36:17
lotuseater
so write yourself a COPY-VECTOR or so which checks if it has fill-pointer and/or is adjustable
11:48:54
lotuseater
yesterday I asked something in #clojure and the discussion went to that someone said "pattern matching 100% doesn't belong in a library, it's a 'fundamental' feature" ○_∘
11:51:12
lotuseater
with sentences like that someone shows well how less things are really understood
11:52:45
jackdaniel
it is not that wiring a functionality in a library make its users comprehend the topic more compared to a built in feature
11:53:34
hayley
I really don't like non-extensible pattern matchers, which so happen to usually be inbuilt pattern matchers.
11:54:26
lotuseater
yes just because something *looks* like "built-in" whereelse cause you're locked out from the beginning doesn't mean it really is
11:54:51
hayley
To a zeroth approximation, a modular pattern matcher would let you provide any accessor functions to destructure an object.
11:55:57
hayley
Of course, Clojure programmers shy at encapsulation and the use of data structures which aren't persistent vectors and maps, so it is a non-issue for them.
11:57:34
hayley
Extensible pattern matching is how DEFINE-TYPE in <https://github.com/telekons/one-more-re-nightmare/blob/master/Code/re-types.lisp> works for example.
11:57:49
lotuseater
and even more, it's a thing you don't want to have in a real language spec, cause there are too much possibilities and variations, like with regular expressions in general
11:58:50
hayley
Once I wrote that pattern matching and hash tables seemed like old ideas, but for which people can't stop inventing new implementations of. So I wouldn't want to maintain a pattern matcher really.
11:58:53
jackdaniel
I doubt that this would make a strong point when comparing clojure with commonlisp (which has quite a few "wired" behaviors, most notably for sequences)
11:59:58
hayley
.oO(Everything I don't like is anti-modular: the hayley's guide to language features)
12:01:06
rain3
Shinmera: I'd like to port https://github.com/rainthree/manardb to windows , this mmap layer is almost fine: https://github.com/Shinmera/mmap/blob/master/windows.lisp#L222 but its api accepts only pathnames , not file descriptors, while the code that has to be ported calls open-file then mmap on the descriptor . Do you allow me to clone your code and modify it as I want , or would you prefer me to fork then submit pull
12:01:06
rain3
requests? (in this case I will have to bother you about changes and you may not agree to the changes I want to make and we will waste time)
12:03:24
Shinmera
rain3: It seems like it would be simpler to me to change the code you're porting to just use the mmap library instead of open-file and mmap separately.
12:06:23
Shinmera
The mmap api does return the fd (kinda) in its second argument, so if you absolutely need it for something you can get it from there, too.
12:16:20
lotuseater
so that lisp123_ works through it but also is aware of a general function in a lirary which does it
12:27:40
lisp123_
mfiano: Thanks, I'm trying to avoid alexandria as much as possible (minimise code dependency surface)
12:28:14
rain3
Shinmera: by "too high level" I meant that it does two things (1. opening a file , 2. mmapping it) , so in the original code to accommodate to that, at this line for example https://github.com/rainthree/manardb/blob/5d8fc843057b70e831ca1bfc4912ae2b24ab73d4/src/mtagmap.lisp#L168 I will have to do an extra remap (or munmap + mmap for systems that don't have remap) . It can be done, but another way would be to make a separate
12:28:14
rain3
layer library (in which I may steal/inspire few lines from yours) that also has open-file exposed in the public api, along with other apis (that don't have anything to do with mmap)
12:29:03
rain3
*an extra remap before truncating the file because it will be already mmapped and truncate won't work before first remapping with the new length
12:37:09
Shinmera
rain3: It must do two things in order to stay properly portable across systems. The semantics of opening a file and mapping are quite different on windows vs unix.
12:59:33
hayley
Well, for the key objects for which EQUAL and EQL hash tables are equivalent, EQUAL conceptually calls EQL. So EQL might be faster?
13:01:01
didi
So let's go a step further: Should GETHASH be faster for hash tables with test EQL and testing integers than with test EQUAL and testing strings?
13:02:25
hayley
Now it depends on if EQ would work; are the integers fixnums and are EQUAL string keys EQ (possibly by some other interning)?
13:03:52
hayley
If one is true but the other isn't, the true one will be faster. If both are true, they're probably the same. If neither is true, no one knows.
14:57:25
pjb
didi: basically a eql hash-table will use as hash value either the address of the object, or (if a moving gc is used), a unique ID.
14:58:18
pjb
didi: while with an equal hash-table, for objects where that makes a difference, the hash-function will have to process the object value (eg. make an sum of some of the hash of the slots in a vector or list).
15:02:39
pjb
eg. if your keys are numbers, then equal uses eql which tests if the numbers are of same type and = ; but if your keys are string then equal uses (every 'equal str1 str2) to test each character. O(n)… Sometimes you may want to use a hash-table :test eql with strings, but in general you don't, you want the :test equal.
15:11:38
doyougnu
Hi all, does anyone have a reference or link to get started on NixOS? I'm getting errors when looking for foreign libs like libssl.so
15:33:14
doyougnu
I was just seeing if there was anyone else in here that used NixOS. I found some NixOS related posts about it, looks like PACKAGE_CONFIG_PATH needs to refer to where nixos stores binaries
15:35:43
dualinverter[m]
doyougnu: I am pretty new to common-lisp, am not using any packages so far; but this flake file works without problems:... (full message at https://libera.ems.host/_matrix/media/r0/download/libera.chat/c755c59039ee186f1a6a9dc98f018ce91ee78e71)
15:37:28
etimmons
doyougnu: Doesn't actually answer your question, but if you don't really need SSL support in hunchentoot you can push :hunchentoot-no-ssl to *features* before loading it
15:37:34
doyougnu
dualinverter[m]: thanks for the input. I'll toy around with some derivations. I suspect i'll have to wrap SLIME in a nix-shell to get it working.
18:05:48
akater[m]
Should (map-into #(0 0 0) #'identity) error? SBCL errors here due to invalid number of arguments but it does not error e.g. on (map-into #(0 0 0) #'identity nil nil).
18:09:48
scymtym
(map-into … … nil nil) does not call the function. (map-into (vector 1 2 3) #'identity '(1) '(2)) signals an error due to wrong number of arguments
18:11:06
scymtym
but i don't think the compiler is supposed to figure that out without calling the function
18:21:46
akater[m]
Elements are set to successive values of (funcall f). That's what should indeed happen.
18:22:12
didi
akater[m]: #'f doesn't accept arguments; #'identity does. The surprise, for me, is that `map-into' applies the function even if there is not sequence.
18:25:32
pjb
akater[m]: there's no point in naming a function with f !!! Use lambda: (map-into (make-list 3) (lambda () (random 3))) #| --> (2 2 2) |#