freenode/#lisp - IRC Chatlog
Search
1:05:49
mfiano
Ok. I'm not very familiar with the MOP. What will give me the lambda list for reinitialize-instance?
1:08:07
Bike
you need the lambda lists for the methods of reinitialize-instance relevant to the particular class you're looking at
1:09:10
Bike
you can calculate those methods with compute-applicable-methods(-using-classes), then use mop:method-lambda-list
1:11:02
no-defun-allowed
how does the CLIM listener handle drawing graphical representations of values?
1:18:53
mfiano
Bike: I can get c-a-m to work, but I can't figure out how to get c-a-m-u-c to work. I just get a no applicable method error. Can you provide an example of using this?
1:20:02
aeth
I can parse function lambda lists except for &aux. It wouldn't take much to add method support because I designed it for my extended lambda list syntax that basically is the defmethod lambda list for types instead of classes and with the addition of &key and &optional support, which defmethod doesn't support.
1:20:38
aeth
It would take some work to librarify it, though, because I basically use it for define-function and related things, like local function bindings with the same syntax.
1:27:05
fiddlerwoaroof
no-defun-allowed: it uses a thing called "presentations" to associate a value with a particular display on the screen
1:27:26
fiddlerwoaroof
I'm not quite sure how the default representation of, e.g., repl results is handled
1:28:28
fiddlerwoaroof
Because WITH-OUTPUT-AS-PRESENTATION associates a value with the arbitrary display produced by its body, iiuc
1:31:17
mfiano
Bike: Stupid question. Why do I get an applicable method specialized on SB-PCL::SLOT-OBJECT in addition to the class specializer when computing methods for reinitialize-instance?
3:19:59
|3b|
there is sb-kernel:get-lisp-obj-address if you want to poke into internals (and understand that you will probably break things, and it can change at any time, unsupported, etc)
3:20:29
|3b|
keep in mind GC can move things around at any point, so for most objects that can change unpredictably
3:25:30
|3b|
(string-trim "#<>{} " (with-output-to-string (s) (print-unreadable-object (nil s :identity t)))) or something
9:03:50
asarch
In the lines #29, 45, 51, 59, 62 where *application-frame* appears, are they closures?
9:05:26
beach
asarch: *application-frame* is a special variable that contains an instance of a standard class.
9:14:04
asarch
Why when you declare a new class: http://paste.scsys.co.uk/582762?ln=on&submit=Format+it%21
9:16:48
asarch
I mean, when it is defined, you do something like (p1 point) at line #24, first the "instance" var and then the name of the class
9:17:19
asarch
And, in the line #44 of http://paste.scsys.co.uk/582761?ln=on&submit=Format+it%21 you do the opposite, (slider value)?
9:18:19
beach
It means define a method on the generic function DRAW that is only applicable when its parameter P1 is an instance of the class POINT.
9:19:31
beach
It means: Define a function named COLORS-SLIDER-DRAGGED with two parameters. The first parameter is named SLIDER and the second parameter is named VALUE.
9:20:15
beach
The reader of the code might guess that the value of the SLIDER parameter is indeed an instance of the class SLIDER.
9:20:47
asarch
I still have a lot of C in my mind that confuses me a lot with Common Lisp way of life :-(
9:30:57
asarch
So, the only way to "declare" a function with an instance of a class as one of its parameters is with DEFMETHOD?
9:32:51
beach
There is no need for anything like that, since classes do not imply encapsulation in Common Lisp.
9:33:44
beach
asarch: Maybe in your case, it is best to try to forget what you know about C or C++ when you work with Common Lisp.
9:33:57
TMA
asarch: that does not mean that a function defined by DEFUN is unable to accept arguments of the desired type. it is just that there is no discrimination on the type of the passed argument, unless you write the discrimination yourself
9:35:14
schweers
On the topic of encapsulation: is there a way to do proper encapsulation in Lisp? Not that I even found a need for it ...
9:36:24
schweers
goood question. I guess having some value which cannot be seen or even set by "outside" code?
9:36:49
schweers
I know and it has always been enough for me. But the hiding is based on convention, the language doesn’t enforce it.
9:37:13
beach
schweers: You define those things in a separate package and you don't export their names.
9:37:18
schweers
I do, I’ve never had the need for such a thing. But many people want it. Also, I’m curious. Hence my question
9:39:51
|3b|
closures tend to hide things in a way that is hard to get to, so you could use them if you really wanted to
9:40:13
schweers
So if a C++ or Java person were to come on here and ask how to do private members in CLOS or lisp in general, you’d rather explain why it’s misguided to enforce it in the first place?
9:40:22
heisig
schweers: Proper encapsulation sounds like you have to give up root permissions on your own computer. Even then, you could still physically destroy the computer :)
9:40:23
shka__
schweers: furthermore, it would be really difficult to have C++/java style encapsulation in dynamic language like Common Lisp
9:40:55
jackdaniel
schweers: if you want to encapsulate interfaces there is an easy solution for that: you put all in a package and export only "public" things
9:41:27
jackdaniel
as of preventing from direct slot access, you may name your slots with gensym (macro is needed) and enforce proper method interface via readers/writers/accessors
9:41:35
schweers
I think my question has been answered :) To be clear: I’m with you all, I was asking this as a hypothetical
9:43:03
jackdaniel
also that, connected with backtrace capabilities: you would be able to see who calls your method and see, if it is a "friend"
9:44:30
|3b|
also hard to compare features between languages. is the #define trick, or accessing 'private' slots with pointers comparable to accessing unexported symbols, or using MOP?
9:45:30
schweers
I have a feeling that accessing unexported symbols or even using MOP is more stable. But anyway, it was a hypothetical question anyway
10:04:51
shka__
it is very much used, and it is somewhat helpfull in some projects, but it comes with downsides and make dynamic style of programming PITA
10:05:44
shka__
but i used to work in crappy C++ corpo-projects full of outsourcing programmers and there encapsulation had it's place
10:51:58
ogamita
schweers: for private members or methods, we could talk about the % naming convention. A symbol starting or ending with a % could be considered "private" and "dangerous to use, know what you're doing". But nothing prevents you to use such symbol, even if they're not exported from a package.
10:52:39
ogamita
schweers: it is assumed that the lisp programmer is smart and knows what he's doing.
10:53:34
schweers
Exactly, nothing prevents others from using this. I’m fine with this and I do this (I think I saw this convention in some code written by beach). I was just wondering if a more strict enforcement was possible. Not because I want to use it, but just as a hypothetical question because I’m curious.
10:53:43
ogamita
with packages, there's the notion of exported symbols and non-exported symbols. The later can be considered "private".
10:53:55
schweers
ogamita: doesn’t every language community assume that their members are smart and know what they are doing?
10:54:32
ogamita
schweers: the only difference is that expored symbols can be accessed direct when the package is used, or qualified with a single colon, while the non-exported must be qualified with two colons: foo:exported-sym foo::non-exported-sym.
10:55:00
ogamita
schweers: perhaps, but the difference is that most lispers do, while most Cer or C++er don't.
10:55:48
ogamita
cf. shka__'s comment: <shka__> but i used to work in crappy C++ corpo-projects full of outsourcing programmers and there encapsulation had it's place
10:59:48
schweers
Especially the java community seems to do it, but they also seem to jump though an awful lot of hoops to do so.
11:02:59
shka__
if you are encapsulating everything, if you are not starting from the tests, you are likely to write untestable code
11:04:08
schweers
You can still test the public interface. But yes, testing the more low-level stuff is difficult in such a scenario.
11:05:59
schweers
Well, java doesn’t even have C++’s broken MI. I’m still not sure which is better in that regard.
11:17:03
jackdaniel
when you acquire tao of programming you patiently wait for problems to fade away due to changed requirements, then you achieve the goal without even touching the keyboard ;-)
11:19:41
ogamita
(but then of course, it's Russian dolls: the internals are also decomposed into public API and clients, so you can test the internal APIs too).
11:20:54
ogamita
But the more internal the code, the more often it can change. The point of having API and distinguishing implementation from interface, is that you can change the implementation anytime, without breaking the rest of the program, since it only uses the public API.
11:21:19
ogamita
So if you test internal, as soon as you change it, you have to throw away the tests and write new tests for the new internals.
11:33:03
jmercouris
e.g. how can I go from (list :a "fish" :b "salmon") -> (list :a "fish" :b "carp")
11:36:27
shka__
alternative approach, sometimes usefull is to simply insert :b "carp" into front of the list
11:41:16
heisig
jmercouris: There is (let ((plist (list :a "fish" :b "salmon"))) (setf (getf plist :b) "carp") plist). But you are right, it is dirty.
11:51:42
beach
jmercouris: Since a plist is not an abstract data type, you should not expect anything better.
12:03:22
beach
What I am saying is that neither list not plist is an abstract data type, so you can't expect them to have identity-preserving abstract operations on them.
12:04:14
beach
Lisp provides excellent concrete data types, but you have to create the abstract ones yourself (mostly).
12:05:32
jmercouris
I don't get to choose the data type I'm working on without some complex transformations
12:05:33
beach
and a plist is but one possible concrete data type to build upon in order to create a dictionary ADT.
12:06:21
schweers
jmercouris: well, you could put the data into a hashtable or something similar, do your processing and create a new plist again (if needed).
12:07:26
heisig
jmercouris: The only reason to ever use plists is that their printed representation looks pretty. For anything else, use alexandria:plist-[alist,hash-table].
12:08:40
jmercouris
within the loop, my "product" is updated, but it is not updated within the products list...
12:09:29
schweers
I don’t think you can do that, as PRODUCT comes rom PRODUCTS. If you push to PRODUCT, that will not change the list PRODUCTS
12:10:03
jmercouris
so it stands to reason that modifying a PRODUCT within PRODUCTS will change PRODUCTS
12:10:41
schweers
If I’m not mistaken, PUSH creates a new cons, and sets the reference (in your case PRODUCT) to this new cell.
12:11:04
schweers
This will not change the list from which you are taking the list you are “pushing to”
12:12:19
schweers
you could collect the PRODUCT values into a new list, if you want to keep the rest of your code the same.
12:13:14
jmercouris
shrdlu68: pushing to the beginning of an alist when there is an existing entry with the same "key" means that the old key/value pair is still there
12:14:04
beach
jmercouris: What is the result of this code: (defparameter *l* '(1 2 3)) (let ((l *l*)) (push 234 l)) *l*
12:15:30
beach
jmercouris: Besides, you are not allowed to alter a list being iterated over in a LOOP.
12:20:16
beach
If TAX-PAYER inherits from PERSON then a tax payer (i.e. an instance of TAX-PAYER) is a person (i.e. and instance of PERSON).
12:20:19
schweers
beach: I’d like to thank you for your precise definitions. They may seem like nitpicking at first, but I am very glad you do this.
12:21:05
schweers
Of course it is, but not everyone knows all the details by heart (I certainly don’t).
12:21:25
jmercouris
I used to get angry at it, but I see the value in it now, at least within the context of a programming dicsussion, my significant other seems to disagree with regard to other topics...
12:21:28
shka__
shrdlu68: in this case list could be :initform '(:a "b") in defclass, and so it would be created during read time
12:23:50
beach
shka__: Which is why you hide the entire mutation behind an API so that you can make sure that the CONS cells you mutate are the ones you created yourself.
12:25:07
shka__
shrdlu68: lists are often created at the read time and also multiple lists tend to share tails
12:26:08
shka__
as beach said, if you need to mutate state you are better of making some kind of API
12:29:15
shrdlu68
I never thought about that, but I feel like this is a lesson about creating standard object...
12:51:19
jmercouris
so READ, it takes an input stream, so if you have a stream you have to make an input-stream and then pass it
12:52:08
jmercouris
sorry there was a typo above, I meant to say "so READ, it takes an input stream, so if you have a *STRING* you have to make an input stream and then pass it"
12:53:03
jmercouris
jackdaniel: ok, I read some misinformation on stack-overflow which made me not investigate, should have checked CLHS, thanks for tip!
13:00:18
jmercouris
and they come with corresponding functions/methods for manipulating those data structures
13:00:40
jmercouris
however I don't think there is a de-facto library, if there is, I am not aware of it, then again I'm not a good source, as I am not aware of a lot of things