freenode/#lisp - IRC Chatlog
Search
20:14:09
borodust
I'm not sure if Ron is right here atm (i think im running out of apologies today), but here he is doing AMA thread atm: https://www.reddit.com/r/lisp/comments/a7156w/lisp_and_the_remote_agent/ebzkgwe/
20:25:32
aeth
You can't just write a program that simply translates JavaScript to Common Lisp because even though Common Lisp is much faster than JavaScript the resulting implementation would be much slower than JavaScript because JS is semantically designed for JIT and the fast CL implementations are AOT, with fast programs giving lots of extra hints to the compiler where that makes sense.
20:26:01
aeth
I think you would have to use runtime compilation to recompile the JS and essentially JIT it.
20:29:25
aeth
e.g. Every number in JavaScript is a double. This is very bad (and would be pretty slow with a naive translation to CL because of the boxing). So JS implementations have to know when to make something not a double.
20:36:39
verisimilitude
I figure a rather naive implementation would be more than good enough, aeth.
20:56:39
aeth
JavaScript the language was thrown together in a hurry and patched around to try to fix it ever since then. JavaScript the code you'll actually see in practice assumes a JIT implementation to be fast.
20:59:35
no-defun-allowed
Also yes, XQuartz is very laggy and only got 100 rectangles/second on the rectangle drawing benchmark.
21:00:10
aeth
Common Lisp is a language designed to be efficiently implemented. Languages like JS and Lua aren't, so you can't just do a naive translation and expect to be anywhere near competitive in performance.
21:00:31
aeth
Of course, if your only goal is to run JS, and it doesn't matter if it's 20x to 300x slower, then that doesn't matter.
21:02:47
verisimilitude
Considering that implementations of JavaScript in WWW browsers have deoptimized in order to avoid memory timing attacks, scraping the pixels of a page with CSS, and other nonsense, that wouldn't really be a bad thing.
21:27:49
eminhi_
Why does trace output print arrays, even after setting *print-array* to nil? Are they on different threads?
21:31:35
ralt
I am trying to display a PNG image in an CLX/xlib window. I've found thousands of ways to take an xlib window and save it in an image, but not the other way around. I'm not well versed enough in the png specifications to figure out how to massage a png file into the data that clx expects.
21:33:18
jackdaniel
ralt: you need to create a pixmap and convert your pixel array to the format of that pixmap
21:34:40
jackdaniel
if you want to have example which actually reads png and puts it on a screen you may look at how McCLIM does this
21:35:53
jackdaniel
but generally the idea is as follows: you load png with opticl, allocate pixmap and write data in this pixmap format as it is written in this demo
21:36:15
ralt
this whole displaying a png image thingie is just a small part of what I want to do, and it looks like it's the most time-consuming part, which has been fairly demoralizing so far
21:36:51
ralt
(it's actually a PDF page I want to show, but I gave up on that and use pdftoppm to convert the pdf into a png)
21:37:50
ralt
yeah, I want to render a pdf to the screen though, rendering a pdf to file is something every other lib seems to know how to do :)
21:38:02
jackdaniel
(see Examples/drawing-tests.lisp and see how all demos are written to these files)
21:39:12
ralt
err, I just want to do something that will let me select a part of a PDF and put a signature in there. i.e. electronically "sign" PDF files.
21:39:56
jackdaniel
ah, I thought that you are baking a PDF viewer in CL (something I have in plans for distant future:)
21:43:37
ralt
jackdaniel: just fyi, I don't want to pursue this further _right now_, but trying to load mcclim is showing this error: "no translation for #P"SYS:DEFLATE.FAS"". The system has been downloaded so I can read the source, but I thought I'd let you know.
21:44:57
jackdaniel
this 1. looks like ECL, 2. looks like not all files from the ecl compilation are installed
21:45:10
jackdaniel
or that they are installed in a different directory than claimed when it was compiled
21:45:58
jackdaniel
(so this "no translation" is not related to the system, rather ECL installation)
21:48:03
jackdaniel
but since it is not ECL and it is highly unlikely it has anything to do with McCLIM, I'll call it a day and wish you a good luck :)
22:31:46
pjb
ralt: actually, there's an opportunity to do something with all those "nightmarish" projects such as a PDF viewer. With CL, we could implement better software than with other programming languages. Building better tools, we should be able to sell them to demanding customers.
22:46:41
aeth
pjb: I think the past 20 years of software has shown that people will gladly accept something that's inferior but $0
23:12:56
phoe
How can I split a list into sublists? I have (1 x 2 3 x 4 5 x 6 x 7 x 8) and I want to get ((1) (2 3) (4 5) (6) (7) (8)) as a result.
23:16:35
aeth
phoe: (loop :for foo :on (list 1 2 3 'x 4 5 6 7 8) :until (eql (car foo) 'x) :collect (car foo) :into bar :finally (return foo))
23:17:12
aeth
The loop I gave splits it to (X 4 5 6 7 8) and (1 2 3) except I forgot to also return bar
23:19:20
aeth
phoe: This splits on one X, and since it returns the second part, it's easy to extend it to split until NIL. (loop :for sublist :on (list 1 2 3 'x 4 5 6 7 8) :until (eql (car sublist) 'x) :collect (car sublist) :into first-part :finally (return (values first-part (cdr sublist))))
23:19:52
phoe
aeth: I think I got it. It's too late for me to write that loop correctly though. I need to sleep first.
23:26:56
aeth
In case you want to make this sequence-generic, the vector version is actually easier: (let ((i (position 'x v))) (if i (values (subseq v 0 i) (subseq v (1+ i))) (values v (vector))))
23:28:02
aeth
This would copy more, though, so you'd probably want to split it all in one function, instead of repeatedly applying a simple split.
23:31:42
aeth
oh, oops, in case anyone reads my code later, you actually would want (valus v (subseq v (length v))) for the case if there is no match so that the empty vector is the same type (not counting length) as the provided one, e.g. (type-of (subseq (make-array 3 :element-type 'single-float :initial-contents (list 1f0 2f0 3f0)) 3)) => (simple-array single-float (0))
23:37:11
aeth
phoe: you can get rid of the setf by starting the loop with the line :for list := list :then tail
23:37:32
aeth
(unless loop doesn't know that list refers to the outer scope, in which case you'd have to call the variable list*)
23:40:00
aeth
i.e. (loop for list* := list :then tail until (endp list*) for (head tail) = (loop for sublist on list* until (eql (car sublist) delimiter) collect (car sublist) into first-part finally (return (list first-part (cdr sublist)))) collect head)
23:44:39
aeth
phoe: until (endp list) can go after the first for, unless that's SBCL-specific behavior
23:47:00
aeth
Works in SBCL, CCL, and ECL. Either way, it shouldn't make a difference, though, because the split should be able to handle being run on an empty list.
23:47:51
aeth
yeah, it'll add one tiny check (the inner loop terminating right away on '()) but not really noticable if you profile it
23:49:46
pjb
phoe: (split-sequence:split-sequence 'x '(1 x 2 3 x 4 5 x 6 x 7 x 8)) #| --> ((1) (2 3) (4 5) (6) (7) (8)) ; 13 |#
0:03:09
permagreen
It's kind of crazy to me that of all the things in the standard, there is no split-sequence equivalent. I guess it was different time. When real programmers split their own sequences. Or something
0:06:09
verisimilitude
It caused a mess when it was pulled from a repository and thousands of programs broke.
0:07:05
aeth
That's apparently because when you bundle it into the browser, you don't want to include anything you're not using, and the easiest way to treeshake is one-function-per-project
0:09:00
aeth
phoe: And it's not even written properly. It uses my subseq vector implementation, and not my loop-over-sublist list implementation, so it will only be efficient for vectors, where indices are cheap
0:10:14
aeth
Any sequence function needs to be written like this (etypecase sequence (list (%list-version sequence)) (sequence (%vector-version sequence)))
0:10:33
aeth
(you do sequence, not vector, in case the implementation has extensible sequences. It's better to have slow support than no support)
0:12:02
phoe
the way in which you dispatch doesn't really matter here - if it's generic dispatch or typecase dispatch
0:12:03
aeth
It's easy to wrap a function with defmethod if you want to. It's a higher level interface.
0:12:08
verisimilitude
Making code that provides an interface which needs to behave differently based on the class of object isn't appropriate?
0:12:53
aeth
verisimilitude: You can inline the outer function that does the etypecase and then it does inline dispatch and removes the dispatch at compile time if the type is known. You can't do that for defmethod
0:13:25
phoe
Also when your interface is not exposed to the outside world and therefore fully internal.
0:13:33
aeth
When you only have two, and can only have two, the function is better, and if you need to define a method interface you can defmethod on sequence (rather than list and vector or whatever)
0:14:43
verisimilitude
I mean, sure, ETYPECASE is a good way to do it for several reasons, but I don't think that entirely discounts dispatch. I was thinking about having generic functions that are eventually extended for more than just those two, though, which influenced this.
0:14:50
aeth
In fact, you probably should also provide a method, defined on a sequence, and performance won't be hurt because the one line function call is (probably) inline
0:15:41
aeth
verisimilitude: Imo you use ETYPECASE/CTYPECASE when it's trivial dispatch, like exactly two possibilities dispatching on one argument. You use defmethod when you start getting into combinations, like dispatching based on two arguments and with many types of classes, especially if the user is expected to extend them
0:16:25
aeth
(Even for type dispatch where defmethod's class-based dispatch won't work, you can use something like specialization-store in the latter case of complicated combinations)
0:16:58
verisimilitude
I don't really see much opportunity to use CLOS is part of why I'd try to reach for it, I suppose.
0:17:14
verisimilitude
I have a program planned that should benefit from it, but I just avoid using it for almost everything.
0:18:20
aeth
If you're writing for sequences it can be reasonable to assume just list or sequence, where sequence is probably a vector unless their implementation handles sequences extensibly.
0:18:35
aeth
But if you're writing for your own class you can't possibily anticipate what the user could add
0:19:04
verisimilitude
Yes; it would've been nicer, I think, if SEQUENCE functions had been defined as generic functions, instead; do you think so as well, aeth?
0:20:56
no-defun-allowed
sbcl exports a way to hook into the sequence interface, do other implementations do that?
0:21:03
aeth
verisimilitude: Well, that's tricky because you would need generic functions to be inlinable, and you might want that to work not just based on class but also based on type in the case of the generic functions for arithmetic and sequences.
0:21:22
aeth
verisimilitude: So you'd need a more robust implementation for that to work as it does now without hurting performance
0:22:04
aeth
For type dispatch, mostly useful for arrays and numbers, there's this library: https://github.com/markcox80/specialization-store/
0:22:24
aeth
Kind of an oversight imo that this sort of behavior isn't even standard or as optimized as it could be.
0:22:54
verisimilitude
As it stands, you can still just do it yourself by shadowing the relevant symbols, so it's hardly out of reach, just relatively inconvenient.
0:23:15
Bike
also the protocol is kind of weird. like you return a bunch of functions as values for some reason
0:24:04
aeth
Recently I had to use both package local nicknames and sb-mpfr. In fact, I had to use the former because of the latter. "sb-mpfr" is, well, it's not easy to type because it's just a bunch of random letters to me. "mp" is much nicer.
0:25:32
aeth
(because sometimes it's easier to just take something to 200 digits and then round the result)
0:28:31
aeth
I think this is different, though, because an extensible sequence is something you want to use in a library, but this was just a one-off thing.
2:25:44
clintm
It would seem that I'm missing something fundamental with reguard to arrays. Either that, or I've never completely understood them to begin with. (defparameter *t* (make-array (list 10 10))), (setf (aref *t* 10 10) "1"). I'm missing some intuition about why this is.
2:39:02
clintm
I see my confusion. For some inconceiveable reason, I was thinking dotimes starts a 1
4:00:39
aeth
stylewarning: sb-mpfr's API isn't very good. e.g. it has a dynamic global that's named like a constant (iirc, precision) and it's fairly hard to extend it with shadowing so +'s generic
4:25:51
PuercoPop
pfdietz: afacit you are mutating the code as if everything is made up of cons cells. Have you run into any problems due to SBCL's quasiquote represenation?
5:05:59
ealfonso
I am considering using Puppeteer but was wondering if someone knows of an equivalent library in CL?