freenode/#lisp - IRC Chatlog
Search
2:24:18
HighMemoryDaemon
Does most people's Lisp programming session (At least Emacs users) start by doing the follow? : Open Emacs, Open your project's ASD file, M-x slime, C-c C-c l (load file to Slime), (cl:quickload 'my-project)
2:36:22
HighMemoryDaemon
oni-on-ion: You don't need to 'C-c C-c l' the ASD file if you are in the folder that contains all your projects?
2:41:53
HighMemoryDaemon
Very nice, so changing directories with eshell wouldn't even matter since QuickLisp looks in the local-projects folder by default.
3:22:55
drmeister
I gave two talks in the last two days in the Bay Area with “Common Lisp” in the title.
3:25:09
drmeister
I think I’ll use the term “flexible compiler for a compiled dynamic language” in the future.
3:33:53
no-defun-allowed
i don't think FOSS writers do much CUDA, it's a proprietary language and only useful on nvidia machines unfortunately
3:39:36
no-defun-allowed
I am looking to make cl-vep use GPGPU, but it'll probably be in OpenCL/oclcl. The interfaces for oclcl and cl-cuda are fairly similar so it could be possible to port it anyway.
3:51:34
no-defun-allowed
funny you bring it up, beach and i have been poking at (presumably) amdgpu crashing and halting our computers
4:05:33
no-defun-allowed
he's not working on it, but we've both had problems with it freezing recently
4:06:16
no-defun-allowed
nothing happens before it freezes, but then it becomes unusable and doesn't respond to the usual TTY changes, SysRq keys, etc
4:06:42
no-defun-allowed
my motherboard has lights which indicate when something went terribly wrong, and the GPU one lights up when that happens though
8:54:44
makomo
does anyone know of anything like MAP-INTO, but that would additionally let me specify the maximum number of elements i want to map over
8:55:16
makomo
i know the destination is an array, but the source can be *any* sequence, which is why i turned to MAP-INTO, instead of TYPECASE/LOOP
8:55:43
makomo
and i want to COERCE every element from the source to a specific type before assigning it to its corresponding destination element
9:07:09
beach
(block foo (let ((counter 0)) (map-into .. (lambda (destination source) (when (> (incf counter) max) (return-from foo ...) ...)) ...)))
9:07:27
makomo
oh wait, MAP-INTO has the same behavior regarding multiple sequences as MAPCAR, etc. (stops at the shortest sequence) and it **includes** the destination sequence
9:07:46
makomo
for some reason i thought it wouldn't take the destination sequence's length into account
9:09:01
makomo
beach: pretty much, but i'm trying to understand what you wrote, or rather, the way you interpreted my question
9:09:41
beach
I thought you max number of elements processed was unrelated to the length of either sequence.
9:10:46
makomo
beach: in that case, my max would still have to lower than either of the lengths, right? otherwise MAP-INTO would stop early
9:13:03
makomo
i went to see what ITERATE has, but it uses ELT, which wouldn't be too good for lists
9:19:42
makomo
beach: in this case my max is the length of the shorter sequence, and that is already handled by MAP-INTO nicely
9:22:16
makomo
beach: one thing i'm wondering though. i wanted to delegate the typecase i would have to write to MAP-INTO. now, it would be the best to do the typecheck only once, and then blast through the sequence knowing what the type is (instead of calling ELT for example which has to do the typecheck every time). is this a correct assumption i'm making, that MAP-INTO usually does such a thing and that ELT has the
9:23:20
makomo
(how they're implement is an implementation detail in general, but would this be the logical thing to do? could a compiler try to optimize an ELT call if it knew the type of the sequence?)
9:24:07
makomo
and i just typo'd the correction as well, oh dear. s/implement/implemented/ instead of the above
9:26:13
makomo
ggole: right and what about calling ELT on an array (instead of AREF for example)? ELT in general has to figure out the type of the sequence first, and it would in general have to do that for every access. could a compiler optimize that into an AREF directly for example?
9:32:21
pjb
makomo: beach: in those cases, I would use a displaced array: (map-into r (lambda (s1 s2) …) (make-array (- end1 start1) :displaced-to v1 :displacement-offset start1) (make-array (- end2 start2) :displaced-to v2 :displacement-offset start2))
9:33:46
beach
makomo: The compiler would have to replicate the loop for that optimization to take place.
9:35:44
beach
If MAP-INTO dispatches on the type of the sequence(s), then the loop is already replicated. But given that MAP-INTO takes several sequences, that might become complicated to pull off.
9:37:08
jcowan
Inline caching is designed to deal with exactly this problem, based on the fact that at a particular call site, typically only one or a few of the types that a procedure can accept are actually ever passed to it.
9:38:22
jcowan
Combined with dynamic recompiling, this allows a monomorphic call site to be maximally efficient, making the simplest possible test: is this the type we had before? Mildly polymorphic call sites can handle a few types with type dispatching; only intensely polymorphic sites need a full dispatch.
9:39:01
no-defun-allowed
does anyone know of any alternatives to neural networks for machine learning?
9:39:04
jcowan
In this way a procedure like elt can be compiled in two forms, one for lists and one for vectors, with the correct one being called based on call-site dispatching.
9:40:24
makomo
beach: yes, that's exactly what i was thinking about -- just like i would have to do if i was going to do it manually
9:42:03
makomo
beach: hm yeah, since MAP-INTO takes a variable number of lists, can it even be done in general? would you have to resort to run-time compilation or something?
9:43:14
jcowan
And the difference between most-efficient list iteration and vector iteration is drastic.
9:43:39
pjb
For lists, you can easily use nth-cdr to start from where you want, and count on the length of other sequences to stop it.
9:45:04
makomo
jcowan: that's very interesting. do any implementations do that (for any function, not necessarily ELT and the like)?
9:45:46
jcowan
No idea. Historically the idea arose in the Smalltalk community and has been used for other OO languages as well.
9:46:15
makomo
i also read about SynthesisOS, an OS that would recompile parts of itself on the fly to make itself more efficient
9:47:52
jcowan
https://gist.github.com/twokul/9501770 explains its use in JavaScript, a language without overt classes.
9:48:57
jcowan
ggole: If you are JIT compiling anyway, inline caching isn't that much more expensive.
9:52:04
pjb
There was an OO system that would also recompile the methods specially for each instance (thus duplicating the code), letting use relative addressing and other tricks, since they were directly attached to the object data.
9:55:08
heisig
jcowan: Thank you for sharing that. It could be interesting to use inline caching to bypass the discriminating function in CLOS. Though ggole is right, there are certainly some hairy corner cases.
9:55:55
beach
makomo: If I were to write map-into, I would probably define a few special cases, like at most three sequences, and replicate the loop for those.
9:58:26
pjb
ggole: since relative addressing use shorter opcodes, the methods were smaller and faster, so it was worth the duplication.
10:01:36
heisig
jcowan: But how does inline caching preserve what Alan Kay calls "extreme late binding of all things"? I would think there must be at least two conditional branches: One to check whether the types are the same, and one to check that no metaobjects have changed.
10:02:44
jcowan
Yes, that's true. But such a check is still cheaper than a full dispatch. You can put the check at the head of the method, and provide two returns, a successful return in which the method ran, and a failure return which triggers recompiling
10:03:05
pjb
This is the advantage of having the compiler available at run-time: you can recompile and optimize for the current data.
10:03:37
ggole
Usually a check would not be on the type, but a token that represents all the assumptions that you wished to optimise based upon
10:03:54
ggole
If something invalidates those assumptions, you update the token and you no longer pass the check.
10:05:12
ggole
For example, you might want to assume that a global variable has not been written to, because you make use of its current value in some way.
10:07:04
jcowan
AFAIK the first JIT compiler was HP APL back in 1977, which compiled APL line by line. The code for each line involved a check that the rank and shape of every variable referenced in the line was the same as before, and the line was compiled to a set of nested loops with fixed endpoints (so-called "hard compilation"). If a line failed the check, it was compiled again, this time assuming only rank constancy ("soft compilation").
10:07:57
jcowan
So since variables polymorphic in rank are not common in any language, most lines were compiled once or at most twice and then ran almost at full AOT speed while keeping the dynamic nature of APL.
10:41:06
heisig
jcowan: Thank you for posting that HP Journal! This dynamic APL compiler is definitely something I should mention in my thesis.
12:44:26
jmercouris
so, the printer prints objects that can be read, but some of them cannot be read, for example, hash tables, why is that?
12:45:19
jmercouris
why wouldn't the default behavior be a printable form of the key/value? I mean it is built-in object after all
12:48:58
pjb
jmercouris: the read syntax was defined (long) before hash-tables were introduced into the language.
12:49:19
pjb
jmercouris: they ran out of time and money to further standardize hash-table read syntax. (and a lot of other things).
12:50:23
jmercouris
beach: definitely possible, but you can imagine that for all built-in objects used as keys/values the modele would be relatively straightforward
12:50:49
pjb
(let ((h (make-hash-table :test 'equal :rehash-threshold 0.5))) (setf (gethash :hi h) 1 (gethash "Hi" h) 2) (com.informatimago.common-lisp.cesarum.utility:print-hashtable h)) #| #.(HASHTABLE :TEST (FUNCTION equal) :SIZE 2
12:51:54
jmercouris
that is interesting I've seen some other libraries as well that do the same for arbitrary CLOS objects using their slots and the like to create printable and readable representations, though the name is currently eluding me
12:52:02
pjb
If you don't want to rely on a library to read the hash-table, you can generate something like: #.(let ((h (make-hash-table :test 'equal :rehash-threshold 0.5))) (setf (gethash :hi h) 1 (gethash "Hi" h) 2) h) #| --> #<hash-table :test equal size 2/63 #x30200227747D> |#
12:54:48
jmercouris
because you could emit a set of sexp when eval'd that would reproduce the hash table, not necessarily with the same eq as alluded above, but with the same general contents keys/values
12:56:13
pjb
For example, you could define a reader macro: Ɦ((:test equal :rehash-threshold 0.5) :hi 1 "Hi" 2)
12:59:05
beach
jmercouris: The Common Lisp HyperSpec says: The :reader slot option specifies that an unqualified method is to be defined on the generic function named reader-function-name to read the value of the given slot.
12:59:25
pjb
Or you can use both :reader and :writer when the names are different, vs. a :accessor that use the same name for both.
13:01:05
pjb
(defclass account () ((solde :type integer :reader balance :writer in-the-bank))) (let ((a (make-instance 'account))) (in-the-bank 42 a) (balance a) ) #| --> 42 |#
13:02:12
pjb
Also, indeed, you can define methods behaving like readers, writers or accessors, without a slot.
13:02:20
jmercouris
I'm basically asking why does :reader exist, if :accessor exists, and I guess the answer is to make a slot-value read only?
13:02:37
pjb
(defmethod interest ((a account)) 0.0) (interest (make-instance 'account)) #| --> 0.0 |#
13:02:48
Bike
or to give the reader and writer different names, like for example if only one is exported
13:03:03
shka_
jmercouris: also, sometimes you want to have reader and writer, and export just a reader
13:03:31
jmercouris
so here's another thing though right, can't any client just redefine your class and add an accessor to get access to whatever you are hiding?
13:05:03
jmercouris
so far, I have been programming common lisp entirely without any sort of "enforced" encapsulation, but this might be a good idea for exposing interfaces to 3rd parties
13:06:45
jmercouris
so, let's say you have a slot that only has a reader, you can then only use slot-value to set its value, right?
13:06:57
jmercouris
so then, if you are saying, don't use slot-value, and you only have a reader, what should you do?
13:07:26
jmercouris
make a writer but not export its symbol outside of your package? is that basically your only course of action?
13:07:29
makomo
jmercouris: you define a writer (or both a reader and a writer by using :accessor) separately with a different name
13:07:32
beach
jmercouris: Wow, you have to distinguish between client code and code for your own module.
13:07:59
beach
jmercouris: Client code may only see the reader, whereas you can have a writer for your module implementation.
13:08:10
shka_
jmercouris: i for instance always name reader to be read-foo, writer write-foo and accessor access-foo
13:09:25
jmercouris
is it just a class that we only initialize and then that's it? we can never set it?
13:10:08
shka_
jmercouris: essentially, it is like saying that java class without public members can't be used
13:10:45
jmercouris
ok, it is making more sense to me now, and I now see why there is no writer here
13:10:47
beach
jmercouris: For example, if you create an instance of PERSON, you can put the date of birth in there. It won't ever change.
13:11:10
jmercouris
here is a case of enforced immutability in common-lisp, that's something quite new to me!
13:11:47
jmercouris
without a writer function, I imagine the author is strongly implying, don't write to this slot
13:12:02
makomo
jmercouris: it is not enforced, you can always use slot-value. the thing you were getting at with "enforced encapsulation" is an important point
13:12:23
makomo
jmercouris: it's just like python. you have access to everything, but you really don't want to access the implementation details of the class
13:12:35
jmercouris
I guess nothing in lisp is really ever enforced, we can always :: to get at a symbol anyway
13:13:04
beach
jmercouris: Luckily. Otherwise debuggers and inspectors would not be possible to write.
13:13:19
shka_
jmercouris: it is interactive, and it is hard to work (program, debug) in interactive envs if there are walls everywhere
13:13:46
makomo
jmercouris: "what if" in the sense, "what if my client changes this variable, oh no!"
13:15:00
jmercouris
beach: I remember you saying you don't like the usage of the word self within a defmethod, does it bother you that it appears in the hyperspec so?
13:15:24
jmercouris
I think you had said it bothered you because it was a remanant of single dispatch object oriented systems
13:17:10
jmercouris
I guess the problem is, if you are specializing on multiple classes, you can't just say "self" for all of them, so there will be this inconsistency
13:17:33
jmercouris
what if instead of self you write something like classa-instance classb-instance, would that appeal to you more?
13:19:37
jmercouris
I can't think of anything better, and I'm sure many people have spent already many hours thinking about it :D
13:21:30
jmercouris
phoe: yeah, I get that, that's what I was trying to say above, albeit, far more ambiguously
13:23:11
jmercouris
I wrote a project recently for a client, in Lisp, and the developer taking over the project was asking me, "why did you do it in lisp"? Felt kind of like an accusation, like I had burdened them in some way by picking this arcane language that they would now have to work on
13:23:57
jmercouris
I told them why I picked the language, why it was faster for me, but it felt like trying to win a holy war, in which I had comitted an atrocity, and had to atone or something, not sure how to explain it, but without them knowing the language, I couldn't articulate to them why I had chosen it
13:24:42
jmercouris
so, perhaps more appropriate for #lispcafe, but the question is, how do you explain your decision to those who question you in a way that they can understand, when they don't know the language
13:26:35
russellw
Be careful of assuming everything has to be about explanations and understanding. Most human interactions are more about social status. So the real point of an answer to something like that is replying in such a way to make it look like, you, your language and your community are at least as high status as his
13:28:42
jmercouris
interesting, so you are saying it is more of a "tribal war" type query than one of genuine interest in understanding?
13:29:20
phoe
russellw: "it works the best for me as a programmer and I can deliver the most value in this language"
13:30:07
jmercouris
that is more or less what I said, I couldn't think of what else I could tell them that would make sense without a lot of context and background
13:30:11
russellw
phoe, good start, but allows too much possibility that another language might be better for the majority of people
13:30:32
russellw
I would say something more like "best tool for the job" or "most powerful language anyone has yet come up with"
13:30:40
phoe
russellw: sure, that's actually true - Lisp isn't a good choice for a lot of programmers and they'll produce more value in other languages
13:31:06
jmercouris
I wanted to find some sort of appeal to authority where I could say "X is in Lisp" to demonstrate that it has been shown to be capable for application in the domain of the application that I wrote
13:31:29
russellw
But it's not just about the words, it's also about the tone. Your tone needs to suggest that your answer is really obvious formality, and not subject to debate
13:32:06
pjb
jmercouris: there's an important point here. In C or C++, since you can write random pointers, you can write randomly into any object very easily. But in lisp you cannot make random references, so it's impossible to write to an object unintentially.
13:32:09
phoe
russellw: I think that "works the best for me" is an obvious formality enough - you can't really debate with that
13:32:40
russellw
If you really have to bring first-person pronouns into it, at least say something like "I find it the best tool for this kind of project"
13:32:52
phoe
it's simply stupid to say "but you're more proficient in Java++, I know it for some reason" if you're a customer
13:33:27
russellw
phoe, I was talking about the presented scenario where the challenge did not come from the customer but from another programmer
13:33:40
pjb
And you still have the god-mode access to slots with slot-value, unless it's overriden for your class or your object ;-)
13:33:43
russellw
If it comes from the customer, then that is a different scenario. He who pays the piper calls the tune
13:34:17
jmercouris
I wonder how hard it would be to make a lisp --> java compiler that produces sensible looking code
13:34:22
russellw
So if the customer asks about your choice of language, say something like "I believe this is the best tool for this job, but it's your call"
13:34:23
phoe
as for the programmers, I'd say it's the bendiness of the language - allowing to tailor the language towards the problem instead of only having the option of hammering the problem into the language
13:35:13
russellw
jmercouris, as far as I know, no one has ever written an x->y compiler that produces readable code for any x,y
13:35:30
phoe
jmercouris: it'll be tough, since you'll need to reinvent a big amount of mechanisms. multiple inheritance, conditions, dynamic variables all don't exist in Java or even the JVM.
13:36:09
jmercouris
multiple inheritance could be circumvented through the use of protocols that multiple classes implement
13:37:56
phoe
the trouble begins when you start trying to compile actual features of CL as a language.
13:38:43
phoe
you suddenly get to embed chunks of the Lisp runtime in that language to be able to support them.
13:39:04
phoe
and be able to bend and modify the control flow in the language in case of conditions and CLOS dispatch.
13:40:05
phoe
which, at some point, stops being readable at all, unless you start abstracting things away.
13:41:47
jmercouris
I mean for example, in the example I mentioned above, imagine if my CL could have been compiled to python
13:42:18
phoe
if anything, embed a Python runtime in your Lisp image and use that python as a scripting language for your Lisp image.
13:42:44
jmercouris
it wasn't the customer, just the developer who is taking over the project for the customer, after my initial implementation
13:43:11
russellw
But you described a scenario where the customer was happy and it was a rival programmer who would've preferred Python. In that scenario, you need to get more confident and better at winning status fights
13:43:36
jmercouris
so they had been working on this project for like 6 months, and in Lisp I did it in literally one week
13:43:58
phoe
jmercouris: are you working in some kind of company? are you a freelancer? a consultant?
13:43:58
jmercouris
the customer was replacing me because I do not have the time to give them, there are other projects that demand my attention
13:44:09
russellw
Well of course the rival programmer was not convinced! You made him look like an idiot!
13:44:42
phoe
yep - tell them that this project is in Lisp and they'll need to learn it to be able to develop/maintain it, just like with any other project
13:44:59
jmercouris
I told them yes, I linked them to PCL, Portacle, and wrote some pretty thorough documentation
13:45:11
jmercouris
Josh_2: don't worry, you're not alone, it won't launch on most people's machine, unless they are on a Mac :D
13:45:57
jmercouris
Josh_2: Yes, I am sorry about that, we are working hard on the new GTK version using the Lisp Core -> Dumb GTK front-end architecture we previously discussed in this channel, so it should work for you, hopefully within a couple months
13:50:30
jmercouris
Josh_2: basically we have a program written in pure lisp that uses xml-rpc to control a client written in c/c++ gtk/qt
13:50:49
jmercouris
that client needs to respond to some basic commands like make-window, delete-window, make-buffer, set-visible-buffer-for-window, etc
13:51:35
jmercouris
this adds greater stability, significantly more consistent cross-platform performance and support, and a more reliable/reproducible build process
13:52:02
jmercouris
whatever technology GUI framework/web engine comes out in the future, it will be easy to port to because of this API that the LISP core and the GUI will use to communicate to each other with
13:53:41
jmercouris
thank you, it was not my idea, all credit to beach , it is however a huge pain to implement and very challenging :D
13:54:24
jmercouris
even just thinking about what is the minimal API needed to control the GUI application was an incredibly time consuming task
14:01:05
jmercouris
If there was a de-facto GUI framework / web engine port for Linux, it'd be an easier target
14:04:09
lukego
Suppose you have a static programming language with relatively weak abstraction capabilities. So you make an S-expression representation of its source code and then write programs using CL macros. Final step is to generate readable code in the target language with no dependency on Lisp. What's the best example of this approach?