freenode/#lisp - IRC Chatlog
Search
15:28:44
vtomole
beach: Replacing LLVM in Clasp seems like a huge project. Good luck to those involved! Why is it slow?
15:29:28
beach
Luckily, we don't have to replicate all of LLVM. Having said that, I am convinced that it would be much easier to write something like that in Common Lisp than in C++.
15:30:16
beach
I often say "it is impossible to write a C++ program that is both modular and fast", and here is another data point in that direction.
15:30:46
beach
astalla: That's what I would have thought, but drmeister says that he can handle that.
15:34:39
djeis[m]
Generating code to access C++ directly is a lot more complicated than just what you can get with CFFI, because C++ is all kinds of nonsense at the ABI level.
15:35:17
astalla
vtomole: as far as I know, to properly link to C++ code without second-guessing whatever compiler was used to compile it, you need a C++ parser, and C++ syntax is complex enough that a proper parser is very hard to write and basically it requires a whole C++ compiler.
15:36:34
djeis[m]
Not just a C++ parser, you have to replicate the name mangling proceedure of whatever C++ compiler that lib was compiled with.
15:36:46
beach
I had assumed that LLVM was a requirement for such interoperability to work, but I only recently learned that drmeister had plans to generate x86-64 code directly.
15:38:11
djeis[m]
I'm fairly certain that LLVM would still be needed for the interop itself, but there's no reason that codegen for the bits that don't involve interop could be done using some other compiler.
15:48:01
beach
djeis[m]: drmeister (who is my house guest at the moment) says that all that is required is to follow the calling convention, which is fairly easy.
15:54:32
ggole
For instance, there's a trick which clang(?) does where if every override for a virtual function returns a constant, they replace the function pointer with the relevant constant in the vtables
15:55:07
ggole
If you have to reverse-engineer that sort of implementation quirk, you'll be in for quite a ride.
16:39:33
Shinmera
razzy: please try not to keep off-topic chatter going, especially when it's politically charged.
16:40:13
russellw
what's the best way to test a variable for being equal to one of several strings? with symbols it's (member x '(a b c)) but that uses eql so doesn't work with strings
16:42:54
shka_
data frame implementation i am working on, will use copy on write logic to only copy parts of data frame that are actually changed
16:43:40
shka_
however, obviously, it would be beneficial to check if operation on frame actually changes it
20:30:04
Myon
svillemot: Hi, are you taking over cl-nibbles from dim, or should I try uploading the fixes for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=908641 ?
20:31:27
drmeister
On reflection, generating code directly from cleavir will probably require figuring out how to set up unwinding and to generate DWARF metadata.
21:30:39
housel
In another channel I'm in (#dylan), it is always morning by convention; makes it easier to choose a greeting across time zones
22:12:43
White_Flame
(defun make-multiplier (x y) (let ((scale (* x y))) (lambda (in) (* in scale)))
22:20:32
aeth
What I mean about not optimized is that given a sufficiently smart compiler both (defun foo () (mapcar (alexandria:curry #'* 2 3) '(1 2 3))) and (defun foo () (quote #.(mapcar (alexandria:curry #'* 2 3) '(1 2 3)))) would be compiled to constantly return '(6 12 18) but that's clearly not the case, at least in SBCL.
22:21:30
aeth
(well, actually it should return (list 6 12 18) in the former case. Slightly different in that modifying the quoted version is undefined and could have unexpected behavior)
22:21:55
oni-on-ion
i did disasm (mapcar (lambda (x) (* x 8)) '(1 2 3 4)) its only a page, that julia was about 4-5 pages....
22:23:05
aeth
I then have to quote it because it tries to evaluate (6 12 18) as a function with two arguments and the name 6
22:23:27
oni-on-ion
so ur telling me that lisp is the perfect balance and harmony between man and machine
22:24:01
aeth
oni-on-ion: No, I'm saying that even here Lisp is incorrect because given entirely constant data, a sufficiently optimizing compiler will compile it to a constant return value, without needing a hack like evaluating that at read time
22:24:48
aeth
In fact, I wouldn't be surprised if the equivalent multiplication in LOOP on the quoted list *does* return a constant
22:26:07
aeth
are you disassembling the reader version in SBCL? for me it returns '(6 12 18) in 23 bytes
22:28:10
aeth
oni-on-ion: (disassemble (lambda () (quote #.(mapcar (lambda (x) (* x 8)) '(1 2 3 4)))))
22:31:17
aeth
oni-on-ion: this won't be as concise as the reader version because I'm using LIST instead of QUOTE: (defmacro times-eight (list-of-numbers) `(list ,@(mapcar (lambda (x) (* x 8)) list-of-numbers)))
22:32:25
aeth
You can get the same thing with (defmacro times-eight* (list-of-numbers) `(quote ,(mapcar (lambda (x) (* x 8)) list-of-numbers)))
22:33:58
aeth
The *disadvantage* of the macro approach is that even though it's more general than the reader approach, it still won't always give you want you want.
22:34:47
aeth
e.g. a list of (1 2 (* 2 2) 4) will fail. If you wanted to be totally general, you'd have to walk through, see if something is a number, if it's a number apply the multiplication, and if it's not a number, make sure the multiplication is attempted at run time.
22:35:16
aeth
oni-on-ion: Putting the ` and ,@ in the lambda itself is doing the operation at run time each time the function is called, even though your data is constant
22:35:27
aeth
oni-on-ion: The ` and ,@ in the macro will do the computation once, when compiling it.
22:35:29
oni-on-ion
i think im just attacking code translation. reason i mentioned balance and harmony earlier, getting to it..
22:35:53
oni-on-ion
aeth: oh! i didnt know that. when to get macros eval'd at compile? eval-when obviously then ?
22:36:16
oni-on-ion
for some reason i didnt lose any marbles by assuming ` and @ were compile time or even just eval time.
22:37:00
aeth
oni-on-ion: this is the full version you want, btw. (defmacro times-eight (list-of-numbers) `(list ,@(mapcar (lambda (x) (if (numberp x) (* x 8) `(* ,x 8))) list-of-numbers)))
22:37:33
aeth
oni-on-ion: If it's a number at macro-expansion time (i.e. a literal number like 42) it will do the multiplication then. If it's not a number (e.g. the list (* 3 4)), then it will attempt to do the multiplication at run time
22:38:46
aeth
the macro is essentially taking in '(1 2 3 4 (* 3 4)) and returning '(list 8 16 24 32 (* (* 3 4) 8))
22:39:38
aeth
and it will even work with variables. (macroexpand-1 `(times-eight (1 2 3 4 foo))) => (LIST 8 16 24 32 (* FOO 8))
22:40:52
aeth
Now there still is a generic-* but it's only applied once, to the variable foo, instead of on every item, which are mostly constant. We turned the naive map into the most efficient thing we can do.
22:44:36
aeth
oni-on-ion: the only catch is that we're not really working on a list. (1 2 3 4 foo) is syntax. (times-eight foo) won't work because it will see the symbol foo instead of a list there, at macro-expansion time.
22:45:11
aeth
Because that's misleading we can express the macro like this: (defmacro times-eight (&rest list-of-numbers) `(list ,@(mapcar (lambda (x) (if (numberp x) (* x 8) `(* ,x 8))) list-of-numbers)))
22:46:48
aeth
Alternatively, we could attempt to parse the argument in the macro and have a slow version for when it's not what we want. Then we could have (times-eight (list 1 2 3 4)) as the API, and for everything that's not a list that begins with LIST we can provide the slow, runtime route.
22:48:57
aeth
This would be the implementation: (defmacro times-eight* (list) (if (and (listp list) (eql (car (list)) list)) `(list ,@(mapcar (lambda (x) (if (numberp x) (* x 8) `(* ,x 8))) list)) `(mapcar (lambda (x) (* x 8)) ,list)))
22:49:56
aeth
But essentially the idea is that if the list is known at compile time, handle it in an optimal way. If it's unknown, just do the mapcar like you would have done.
22:54:52
oni-on-ion
right =) i will get used to swapping between compile and run time , glad the syntax is super small for it
23:07:44
jasom
also consider that for when you might want to behave as a function or a macro depending on your arguments.
23:12:52
aeth
jasom: You can use "list" everywhere but you still might accidentally use the wrong list
23:15:31
aeth
This is the correct version: (defmacro times-eight* (list) (if (and (listp list) (eql (car list) 'list)) `(list ,@(mapcar (lambda (x) (if (numberp x) (* x 8) `(* ,x 8))) (cdr list))) `(mapcar (lambda (x) (* x 8)) ,list)))