freenode/#lisp - IRC Chatlog
Search
9:18:22
phoe_
I am making instances of some class via MAKE-INSTANCE. These instances are named, in a way similar to class metaobjects - each instance has a name, and they are referred to by their names.
9:18:58
phoe_
At the moment, I have an INITIALIZE-INSTANCE :AFTER method that automatically registers each instance after it's created, but it doesn't seem right to me.
9:19:47
phoe_
For example, this doesn't allow me to make anonymous instances, and seems inconsistent with how I can do (MAKE-INSTANCE 'CLASS) that doesn't seem to have any side effects.
9:20:27
phoe_
Should I instead write it so MAKE-INSTANCE only returns the instance, and the task of "registering" that instance is delegated to some macro?
9:20:29
pjb
phoe_: it is perfectly right for a class to keep track of its instances. This can be done with this :after method.\
9:21:10
pjb
phoe_: the question for you, is whether you may need to have several trackings, if you need different sets of those instances.
9:21:41
pjb
If you just want all the instances of that class (and subclasses), then tracking them from initialize-instance :after is ok.
9:21:46
phoe_
pjb: I don't think so, the way I think of it is, a symbol is going to name one and only one instance ever.
9:22:11
pjb
or initialize-instance, rather, because I would reserve :after and :before to the client of a class or library, but it's just an API choice.
9:23:54
pjb
(let ((i (make-instance 'class))) (register i :name 'foo :namespace 'china) (register i :name 'jean-pierre :namespace 'france))
9:24:32
pjb
And define-named-class-instance can expand to (register (make-instance 'class) :name name :namespace 'global)
9:25:26
pjb
Do you want also to have bindings? I would use a define macro only if it created a (variable or symbol-macro) binding.
9:26:09
pjb
Once I parsed a mail.log, and bound all the data about a given message to variables named after the message-id (in a specific package).
9:26:36
_death
I think a macro is ok here.. it could expand to (setf (find-foo ...) ...) or ensure-foo that does it
9:28:50
jmercouris
so in reading Gentle introduction to symbolic computation I came across this: "FUNCTION returns the functional interpretation of its unevaluated argument"
9:30:54
pjb
it means that you cannot write (function (intern "FOO")) but you have to write (function foo).
9:31:37
pjb
but when QUOTE returns the argument as-is, FUNCTION returns the actual function object that is named by the argumnet.
9:32:11
shka
the only thing in common, really is that they are both special, and both won't evaluate it's argumetns
9:32:45
pjb
jmercouris: now, the difference is when you have local functions (ie. closures). (funcall (quote foo)) will always call the global function named foo, stored in (symbol-function 'foo). On the other hand, (funcall (function foo)) will call the local function foo, when there is one.
9:33:36
pjb
jmercouris: (defun foo () 'global) (flet ((foo () 'local)) (list (funcall (quote foo)) (funcall (function foo)))) #| --> (global local) |#
9:34:16
_death
there is also the case of (function (lambda ...)) which returns a functional object for the lambda expression
9:34:21
pjb
jmercouris: so outside of a lexical scope where you have local functions, using 'foo or #'foo is mostly semantically equivalent.
9:34:51
pjb
(function foo) makes reference to the flet foo. (quote foo) makes reference to the defun foo.
9:35:36
jmercouris
beach: I remember the conversation we had, which is why I was wondering about this as well
9:36:04
jmercouris
the author again goes on to say, "If the argument is a symbol, it generally returns the contents of the symbol's funciton cell."
9:36:16
pjb
jmercouris: read again, global is just a symbol. The returned result after "-->" is data.
9:36:34
beach
jmercouris: (function bla) returns the function with the name bla. There does not have to be any function cell.
9:37:13
pjb
jmercouris: notaly, as a special operator function creates closure objects: (let ((y 42)) (function (lambda (x) (+ x y)))) #| --> #<ccl:compiled-lexical-closure #x302002617AEF> |#
9:42:25
jmercouris
the PDF is freely available on the CMU website I believe, I wonder if it would be legal to publish a set of revisions based on the book
9:42:41
jackdaniel
afaik he responds to emails; someone asked me how to fix clx for some Gentle example and he has asked the author if he can modify his code before that (with positive answer)
9:46:17
_death
I think it's a pedagogical style where simplicity is more valued than correctness.. where they don't want to "bog you down with the details".. this may work for some people, especially if they don't rely on it as the only source of information.. the CLHS is the authoritative source nowadays (with small exceptions agreed upon by community and implementations)
9:46:52
jmercouris
since ASDF is not part of the spec (I believe), why was it integrated into most popular implementations?
9:47:17
_death
and it may be that the misconception will be corrected later on in the book.. if you're bothered by such things, gentle may not be the right book for you.. I think PCL tries to be more strict in that regard
9:48:33
_death
jmercouris: because it solved a real problem and had many users.. then it evolved into a little monster :)
9:49:45
jmercouris
_death: I like this book, even if it would be potentially simplifying things for me, it is a nice cover to cover read
9:50:35
jmercouris
_death: I'm on page 226, and I still manage to read every day, since it isn't so heavy
9:51:08
jmercouris
jackdaniel: the difference here is that MAKE is a separate program, not part of the C++ compiler
9:51:12
_death
jmercouris: that's good.. so like I said, just treat it as one of several sources of information
9:52:19
jmercouris
beach: I assumed it was some extension added to SBCL, CCL, ETC, I didn't realize that it was a separate program that just ships with them when you install them
9:52:21
jackdaniel
LdBeth: I'm confused now, so I'll cease to read to avoid further confusion towards my day :-)
9:52:47
beach
jmercouris: You are not considering something a separate program if and only if it is in a separate Unix executable file do you?
9:53:12
jmercouris
beach: that is what I consider a separate program, otherwise I consider them part of the same system, and just different functionalities
9:53:21
beach
jmercouris: That would be silly because then all of the tools of Genera would be one single program.
9:53:34
jmercouris
is the save routine within a text editor a different program than the routine that handles inputting a keystroke?
9:54:50
_death
jmercouris: yes, you can consider it a different program with inputs and outputs implicitly specified
9:55:00
TMA
jmercouris: think of busybox for a moment -- busybox is a shell that can serve as a ls, cat, ... as well
9:57:03
TMA
jmercouris: do you see the trap you have cornered yourself into? even you are making a distinction between a process and a program -- so a program does not necessarilly correspond to process in 1:1 manner
9:57:39
jmercouris
I usually always think of programs as standalone executables, whether I can fork and run another program is not the point
9:58:47
phoe_
jmercouris: an answer to that question is an answer to your issue with program nomenclature
10:01:20
pjb
jmercouris: for example, on a unix box, when you run a "program" you are generally running several processes!
10:02:49
pjb
jmercouris: programs may be compound objects, and if you have a X11 GUI, then your program runs in the X11 server, will often have a X11 client GUI, and other back-end programs. As a user you would only see windows on the screen, but this just hides the complexity of such compound programs.
10:03:54
pjb
jmercouris: and on the other hand, when you run programs on iOS, where fork is disabled for user applications, you could have a single program running in a single process that is composed of several normal unix programs (eg, gzip, git, gcc, emacs, etc, all embedded into a single program and a single process).
10:05:03
pjb
jmercouris: So, I would say, it's not bad to try to understand things from what you know, but for this you have to really know well what you know. The problem is not so much that you assume lisp would be like unix, as the fact that you don't really know unix either in the first place.
10:05:22
pjb
jmercouris: there's no difference between a routine, a subroutine, a procedure, a function, or a program.
10:06:03
pjb
jmercouris: there may be different technical ways to call one from another, different instructions, but this doesn't change fundamentally what they are. Basically, just functions.
10:06:57
pjb
But it is quite remote to the technical aspect that everything is code or data in the computer.
10:07:27
pjb
From a user point of view, a program will be a unit of interaction and data manipulation = a user task.
10:08:01
jmercouris
https://www.merriam-webster.com/dictionary/program "a sequence of coded instructions that can be inserted into a mechanism"
10:08:12
_death
a program is a specification for a machine.. our machines can mimic other machines, and we write our specifications so that the machines we have will mimic the machines we want
10:08:23
pjb
jmercouris: this is very powerful: this allows you to define any abstraction you want at any level, using just lisp functions!
10:08:47
pjb
jmercouris: so you can write programs (several of them) in a single lisp image. You can write whole operating system in a lisp image.
10:10:46
_death
another way to think of it is that a program is a description of a process, which gives a more dynamic view
10:13:35
pjb
jmercouris: notice that 1- in lisp, we have some separation of addressing spaces, since if you give a function a reference to one object, it cannot manipulate this reference to access to any other object. and 2- in unix one important idea is that programs shall be small units doing one thing well, and process creation is optimized so that you can protect the execution of each of those small program and combine them easily and
10:14:16
_death
LdBeth: memory is an abstraction that is made concrete by the OS and hardware, which may include multiple machines
10:15:34
pjb
Basically, this is the same thing, implemented in two different ways. in lisp we have a controled execution model, so we can combine small programs that cannot access the data of other small program because they can't compute addresses, and we combine them easily by mere function calls. In unix we have a lower level execution model, where processes can compute addresses and crash, but they are protected by the hardware (MMU), and
10:16:09
pjb
LdBeth: consider also the memory from the point of view of the unix kernel. It's like a lisp image.
11:02:10
jmercouris
the only thing that comes to mind is having another slot in my objects that corresponds to the type of object, but that seems dumb
11:04:05
jmercouris
so currently I have: (encode-json (make-instance 'event :key-code "code")) -> "{\"keyCode\":\"code\"}"
11:07:21
jmercouris
well, sounds like everyone is unanimous agreement that there can be no better engineered solution :D
11:08:12
tfb
jmercouris: I think you could have type objects (not just names of them) but you need to ship them across as names I think
11:10:40
random-nick
since you're sending it to JS code which wouldn't understand the classes anyway
11:11:16
jmercouris
random-nick: because the JS code must use the classes to determine HOW to render the data
11:12:44
random-nick
why not determine that in lisp code and only send to JS code exactly how you want it rendered
11:16:09
tfb
jmercouris: that was what I meant by the type object: the JS objects would have a type object slot, and the type object contains the information JS needs to render them. But I think those objects need to exist only on the JS side and have names, and it's the names that get shipped from the Lisp side. (So I'm agreeing with your approach I think!)
11:18:14
random-nick
jmercouris: well, I'm thinking more like having classes on the JS side whose JSON representations you send from lisp code
11:19:05
jmercouris
random-nick: Yeah, it is the same idea, just a difference of where the class definitions are stored
11:19:19
jmercouris
in any case, if you give some JSON to the JS that doesn't have a class available, it will not render
12:26:08
jmercouris
I'm getting strange behavior with a macro: https://gist.github.com/1bc275b5bfbe54cd2603331ebb76384d
12:40:31
jmercouris
I'm just saying, any time a signal is raised due to some error, I have no idea what all the things in SBCL mean
12:40:44
_death
there's no need to read the backtrace in this case.. it's enough to read the error text: The variable ATHENA::DEFINE is unbound.
12:51:15
flip214
jmercouris: don't worry, reading backtraces is one of the harder things in CS - in any language.
12:51:50
flip214
you need to know enough about all the things in use to determine which frame might be the real cause, and which ones are just noise.
12:52:39
jmercouris
flip214: Yeah, I would agree with that, I can't say I've ever been so truly enlightened in any language as to grasp immediately a backtrace
14:02:35
shka
anyway, as others pointed out, there are different strategies for implementing remove-duplicates
15:49:21
jmercouris
I'm getting an interesting stream error when I'm trying to return an image from my lisp web server: https://gist.github.com/36f339d186996b2f8c40cab099739366
15:57:48
jmercouris
or what is it? more like a buffer? excuse my ignorance, as I still don't know what streams are :\
16:02:48
eminhi
jmercouris: https://stackoverflow.com/questions/7441992/how-to-create-a-binary-stream-not-a-file-in-common-lisp
16:04:31
tfb
I'm the wrong person to answer this but traditionally streams either deal with (a subtype of) character, or (a subtype of) integer. And CL-the-standard is missing some stuff around this I think
16:07:21
tfb
Somewhere there is stuff (also not in the standard) about bivalant sreams which are streams which can contain both characters and bytes, and which I think you really kind of need for webby stuff
16:08:30
eminhi
tfb: we can use *open* with different :element-type, when finer control over stream is needed
16:08:33
tfb
(and. doh, flexi-streams is 'Flexible bivalent streams for Common Lisp': I should have looked at it!)
17:56:58
jasom
skidd0: If nobody mentioned it, EXIT should not be in the CL package, so if you don't use CL-USER there should be no conflict...
17:58:31
jasom
cl-user is an implementation-defined superset of the CL package; it has non-portable but useful things (most implementations define QUIT for example; SBCL defined EXIT in addition to QUIT because they changed the interface IIRC)
18:05:40
skidd0
the general user story is "I want to add a task." > "I execute 'to-do-binary --add-task'"
18:06:10
skidd0
which, in code would then open a connection (since the binary doesn't live in memory and thus can't maintain an open connection)
18:07:09
skidd0
so in my understanding, every db op (like add-task) would need to be wrapped in the with-connection
19:47:47
jasom
skidd0: that is correct. I would recommend doing a with-connection around your main function though (assuming *most* invocations of your program will need to connect to the database).
19:48:51
skidd0
well the "main" function that the end-user interacts with is a cli function with CLON
19:49:48
jasom
skidd0: assuming the commands are functions, just put it in the body of those functions.
19:50:17
jasom
I'm just suggesting you not do (with-connection <lookup some data>) (with-connection <modify some data>) ... or something stupid like that
19:51:38
skidd0
and for each command line option from clon, have a with-connection at the start of that commands function body
19:52:36
skidd0
so i'm thinking it'd be better to wrap each of the functions in the to-do package rather than the functions in the cli