freenode/#lisp - IRC Chatlog
Search
15:00:00
muyinliu
megachombasss: You REALLY need Emacs with rainbow-delimiters, take a look at this: http://pasteall.org/pic/index.php?id=123935
15:01:25
zazzerino
Are there really universities that require Common Lisp for projects but don't allow students to install or use emacs? I find it hard to believe, but I didn't study programming in school...
15:02:34
ghard
Worse - dropping someone into CL straight from imperative languages without giving an initial course first.
15:05:16
rumbler31
There's no way this user hasn't had a lead up of some kind to have to use lisp for their final project. There's no fooling us in that regard. But it is not uncommon for departments to set up hosted machines where students must save and submit their work.
15:12:20
muyinliu
rumbler31: This online-editor is quire poor, without auto-indent or colorful parentheses...
15:13:13
rumbler31
its not great. but its better than gedit, and I can't find the other ones that were fully featured
15:15:11
sebastien_
which GTK+ binding would you recommend for a new application? cl-cffi-gtk or gtk-cffi?
15:16:31
sebastien_
the difference between the two is not obvious at first glance, though cl-cffi-gtk seems more maintained
15:20:22
zazzerino
sebastien_: I don't personally have experience with either, but I know nEXT browser (https://github.com/next-browser/next) uses cl-cffi-gtk
15:25:58
muyinliu
I wrote a Common Lisp CFFI wrapper for GraphicsMagickWand: https://github.com/muyinliu/cl-graphicsmagick
15:29:16
muyinliu
And a CFFI wrap of fswatch, a cross-platform file change monitor: https://github.com/muyinliu/cl-fswatch
15:31:45
rumbler31
I've always wanted to wrap native libs but it seems intimidating. how did you get started? did you leveerage any automatic header file parsing?
15:34:18
zazzerino
rumbler31: cffi has excellent documentation. Something that's nice about wrapping libs in cl is you can do it interactively, and can start with just the functions you need.
15:37:12
rumbler31
shinmera: speaking of which, I know that wrapping c++ libs is a different beast. how did you learn what you needed to know to make it happen?
15:38:19
Shinmera
If you do need to do it though the strategy is simple: write a C library that exposes all constructors, methods, functions, and structs. Then bind that. It's extremely tedious though, so I'd never do it myself.
15:38:44
muyinliu
zazzerino: The demo in CFFI's doc is not complete(especially about how to wrap Windows libs). I have to try my best to collect info from everywhere :(
15:43:35
zazzerino
I found it useful to look at examples in the domain I'm currently working on (audio programming). Tito Latini wrote some relatively simple wrappers for a few c libs for his Incudine library. You can find them at https://sourceforge.net/p/incudine/incudine/ci/master/tree/contrib/
15:48:40
Shinmera
Anyway, even CommonQt didn't really bind C++, it used Smoke which is an autogenerated C wrapper for Qt.
15:51:09
rumbler31
and on another note, I feel that linking c++ libs is more complicated than simply implementing the correct name mangling
15:52:20
Shinmera
And if you want exception handling, you'll need to handle that as well (good luck with that one)
15:53:05
Shinmera
But, even with just name mangling (and thus static dispatch) you can get pretty far.
15:54:56
rumbler31
so if you want to call a constructor for classes with heirarchies and dynamic dispatch, you have to do all that yourself, call the base class constructors in order, wire up the vtables.
15:56:04
Shinmera
if I remember correctly constructors are override unless they explicitly call super or whatever, so you don't need to implement that bit.
16:14:07
beach
It would probably be faster to use my generic dispatch technique than to use vtables.
16:14:42
Shinmera
Yeah, if you replicate the type hierarchy on the lisp side you can implement the dispatch yourself.
16:15:44
Shinmera
Well, the type hierarchy and method attachment (which classes even define a method of their own)
16:16:51
beach
It would be somewhat ironic, though, if the fastest C++ implementation would use a dispatch technique from Common Lisp.
16:18:39
Xach
i would still like to use it to try to make a js interface for non-cl users to customize cl software.
16:19:05
rumbler31
that doesn't help if the library code needs to call the virtual methods, does it?
16:20:14
rumbler31
if library code calls a virtual method on an object you passed it, the resolution of the final function call comes from a callback in lisp, right?
16:24:16
Bike
making generic functions static seems like a bit of an endeavor. And you'd either get a combinatorial explosion or have to assume some aspects of the class hierarchy don't change (you have to assume that anyway, of course)
16:24:19
rumbler31
because the object has a pointer to the vtable, if the library code makes calls to virtual functions, the compiler would have baked in the pointer lookups to the correct call. so what gets given to the library would need to be an object with a pointer to a table of function pointers, and if those pointers resolve to functions in lisp then they'd need to be callbacks
16:30:38
rumbler31
I've typed up several lines. But the only common response among them is "I don't know"
16:32:54
Shinmera
I don't know how exactly it works in C++, but typically a method call with dynamic dispatch works as follows: dereference the object to get the vtable, load the value from a fixed offset in that table for the specific method you want to call, then simply call that value (address) with the rest of the arguments.
16:35:05
Shinmera
If you know 1) what the class hierarchy is 2) which classes define which methods, and 3) what type an object has at runtime, you can replicate the dispatch without needing to even look at the vtable.
16:36:09
rumbler31
hold pointers to the library methods in lisp, dispatch in lisp to the correct calls
16:41:59
TMA
beach: not necessarily faster. it is three instructions (two memory fetches and one indirect call) in the case of single inheritance; it is more involved in the multiple inheritance case and in case of virtual base classes, but it is hard to beat the performance of the simple case
16:50:26
TMA
beach: I think I have read someone verifying the speed of lisp's generic function dispatch and c++ vtable lookup dispatch, but that was a long time ago and moreover not entirerly the same thing. (so yes, someone would have to verify that)
16:51:11
beach
If you read it a long time ago, then the Common Lisp way was using hash tables which is slower than my technique.
16:51:30
zazzerino
Does anyone know of a common lisp library similar to clojure's hugsql? (https://github.com/layerware/hugsql)
16:54:45
beach
rumbler31: scymtym has some benchmarks showing that it is significantly faster than the PCL technique, which is used by SBCL among others.
16:55:40
Shinmera
scymtym: Speaking of SICL dispatch in SBCL, what are the roadblocks to getting that merged in?
16:56:59
beach
Shinmera: The SICL technique as documented requires classes to have unique numbers (that change when the class is redefined). SBCL doesn't have that. So, as I recall, scymtym is using the address of the class metaobject instead.
16:57:10
rumbler31
iqubic: no but installing anything with quicklisp might, such as the slime-helper
16:57:53
beach
Shinmera: So, either you convince the SBCL maintainers to introduce class numbers, or you make them swear that classes will never move. None of which is going to happen.
16:58:24
rumbler31
iqubic: or more esoterically, if for some reason you've brought your loopback interface down, you'll have silent errors that will confound you for a little while, so don't do that ;-)
16:59:33
scymtym
beach: it's more nuanced than that in both regards. as i said at time, the benchmarks are not ideal and it cannot be concluded that (my variation of) fastgf is significantly faster in all cases. secondly, the dispatch i implemented uses multiple kinds of decisions, based on lowtags, widetags, layout addresses, EQ-comparisons and EQL-comparisons
16:59:58
rumbler31
iirc the symptom is that there is no error when opening the socket, so swank starts fine, but nothing can connect, so slime connect fails.
17:02:10
iqubic
loli: My main issue is wanting to pass a list to a function that only takes &rest params.
17:03:01
scymtym
beach: it wasn't, of course. and i'm not denying that fastgf is or can be faster than PCL. in fact i believe that is the case. i'm just saying that the benchmarks i did so far are not sufficient evidence for that conclusion
17:03:27
Bike
(apply #'+ (number-sequence 1 100)) can be better done as (/ (+ (* 100 100) 100) 2), natch
17:05:37
beach
scymtym: Do you share my sentiment that it would be hard to convince the SBCL maintainers to do what it takes to support a good version of my dispatch technique?
17:07:08
Bike
reduce works if the function is associative and such, but in general, if you have a list you want to pass to a function as arguments, that is what apply does
17:11:06
scymtym
beach: since i am an SBCL maintainer, i could, in theory, undertake that myself and i don't think anybody would object. that said, this would probably be the biggest and most invasive change since i started working on SBCL and i often had trouble getting much smaller things to a point where i could merge them
17:11:58
Bike
i was under the impression that sbcl classes had "layouts" that can be used similarly for obsolete instances. could you see how it goes just using eq comparisons of those instead of small integers?
17:12:14
scymtym
beach: maybe when some other implementation completely embarrasses SBCL in terms of generic dispatch performance, stassats could become interested
17:16:06
scymtym
i think, layouts already have a CLOS hash or similar in them. so that could be used. but doing any sort of range optimization would be out of the question
18:46:10
warweasle
rumbler31: They didn't want to take time to make it. Programmer's will just have to walk to the lab.
20:25:32
Xach
Does anyone here have a project in quicklisp and want to monitor its build failures through RSS?
20:32:59
specbot
Additional Constraints on Externalizable Objects: http://www.lispworks.com/reference/HyperSpec/Body/03_bdd.htm
20:34:55
pjb
jasom: I guess you could write a make-load-form for hash-table. Also, the keys and values would have to be externalizable.
20:37:08
jasom
pjb: well if ABCL allows defining make-load-form and all other implementations don't need make-load-form, I have a workable solution
20:42:03
jasom
pjb: actually in this case load-time-value is the exact opposite of what I want. I want it to be evaluated at compile time, not at run-time.
20:42:11
pjb
megachombas: also, you may want to finish output with a newline, and to flush the buffer with a call to (finish-output).
20:43:22
pjb
Notice that hash-tables have attributes that are not always visible, such as :size, :rehash-threashold, etc.
20:43:46
megachombas
actually i want to know what is passed as param in a fuction, to be able to copy this parameter and load that fuction by hand
20:45:24
pjb
megachombas: the advantage of print is that it returns its first argument so you can use it in expressions: (if (print (= (print a) (print b))) (print 'same))
20:46:01
pjb
The inconvenient is that it only prints the argument, so if you have a lot of them it may be confusing.
20:47:14
pjb
I have a macro (com.informatimago.common-lisp.interactive.interactive:show expression) that prints expression = value and returns value so it can be used as print, but its output is clearer.
20:53:45
pjb
megachombas: in C, would you write: print(list a,b,c) or print(list(a,b,c))? Would you forget the inner set of parentheses?
20:59:27
pjb
megachombas: Call the function list with as arguments 'foo a b and c is written ( =call list 'foo a b c )=end of arguments.
20:59:56
pjb
call print with as arguments (list 'foo a b c) is written (print (list 'foo a b c)) not (print list 'foo a b c)!
21:02:22
pjb
clisp contains a good tutorial: https://sourceforge.net/p/clisp/clisp/ci/default/tree/doc/LISP-tutorial.txt
21:08:40
jasom
Consider the output of this form with *print-circle* set to t and nil: (let ((x (gensym))) (list x x))
21:13:33
jasom
whatever you are interacting with is generating output that includes uninterned symbols. These are confusing if you are new to lisp, so just enable *print-circle* for now if you want to be able to paste the output and have it read in correctly.
21:18:34
jasom
megachombas: just set it to true at the toplevel before you run whatever it is that prints stuff out.
21:23:59
TMA
megachombas: the difference is that in the (let ((*print-circle* t)) (print (list 'load-machine vm asm)))) version you do not set the variable permanently, you change the value just for the print inside
21:28:17
jasom
megachombas: okay, in C, will the following expressin be true or false: "foo" == "foo"
21:29:05
jasom
megachombas: not necessarily; the compiler could in theory generate two different string literals and then it would be false because they would have different addresses
21:29:28
TMA
megachombas: not necessarily. the standard permits it to be true, but does not mandate it
21:32:20
jasom
right, when you read this in lisp, it will always generate an identical symbol named "FOO" in whatever the current package is. No matter how many times you read it, only one symbol will be created: 'foo
21:33:17
jasom
however, if you put #:foo it creates a new symbol with no package whatsoever. Since there is no package when you get another #:foo it creates another symbol with the same name, so you have two different symbols
21:34:32
jasom
now the reader has a specail tool that lets you drop objects that have already been read into the same place. You mark an object you want to include later With #N= (where N is a number) and then anywher thereafter you can put #N# and it drops the identical object there
21:35:59
Xach
Shinmera: I restructured things a little for the rss feeds. There's now http://report.quicklisp.org/feeds/author/Shinmera.rss as well as http://report.quicklisp.org/feeds/project/chirp.rss (for example)
21:36:20
Xach
they include some of the log (the part immediately before and after the start of the backtrace)
21:43:34
Xach
megachombas: the important distinction between internal and external representation is at play here
21:44:14
megachombas
because my objective is eliminate the function that generate that list, and directly read that list from a file
21:55:28
Shinmera
Well you're probably getting mad because you jumped right into the icey water and are now confused why it's so cold, instead of easing yourself in slowly.
21:56:14
Shinmera
Everything is difficult if you try to accomplish a non-trivial task in an unfamiliar environment.
21:57:02
megachombas
'Everything is difficult if you try to accomplish a non-trivial task in an unfamiliar environment.' definition of the fresh university system
22:05:57
TMA
if you do that, the |finTest7794| will be a symbol in the current package, which means (as jasom has written here already (22:32 < jasom> right, when... and following messages)) that you will probably not need the #4= (as every |finTest7794| will be read equal to other |finTest7794|) [[I am simplifying greatly, you could make it so that it will no longer true, but it would require additional effort to change it]]]
22:09:37
pjb
megachombas: you have to distinguish the textual representation from the actual data structures.
22:12:36
megachombas
so if i so (read ((move r0 r1)(move r2 r3))) that will transform it into the correct list
22:12:57
pjb
megachombas: now, the thing is that symbols are usually interned. Which means that when the same symbol name is read twice, the same and unique symbol is obtained. So there's no need for ## and #= when you read sexps containing multiple occurences of the same symbol: (a a a) is a list with 3 cons cells, each pointing from their car to the same symbol named "A".
22:13:14
pjb
(read-from-string "((move r0 r1)(move r2 r3))") #| --> ((move r0 r1) (move r2 r3)) ; 26 |#
22:14:32
TMA
megachombas: could you show me the piece od code that constructs the (@ #:|finTest7794|)? is it a code you have written?
22:14:41
pjb
Notice that the REPL uses PRINT to do the inverse transform, from lisp data structure to textual representation, so when you read ((move r0 r1)(move r2 r3)) at the repl, it prints it, and you get back ((MOVE R0 R1) (MOVE R2 R3)) ; notice the space inserted in the normalized representation! And the uppercase, if you don't have (setf *print-case* :downcase).
22:15:22
pjb
#: prevents interning the symbol, so #= ## are needed if you have several occurences of a uninterned symbol in the sexp.
22:15:45
megachombas
TMA: https://github.com/thibaudcolas/clisp-compiler-vm/blob/master/compilateur/cas/conditions.lisp
22:16:05
pjb
megachombas: you can use gentemp instead of gensym to generate interned temporary symbols so you don't have this problem with the textual representation.
22:17:52
pjb
https://github.com/thibaudcolas/clisp-compiler-vm/blob/master/compilateur/cas/conditions.lisp
22:21:15
megachombas
i will only present VM tomorrow, as i cant even explain everything that it does, as for example i dont understant what (MOVE (LOC -1 0) (:R0)
22:21:46
TMA
megachombas: the compiler uses gensym. therefore the compiler result contains the result of the gensym evaluation
22:22:53
TMA
megachombas: if the gensym was replaced by gentemp there, the compiler result will have no #: when printed and you would have no problem with it
22:23:34
pjb
megachombas: no, in lisp we never use plaintext. Instead we use lisp objects, data structures, what we call SYMBOLIC EXPRESSIONS, sexps.
22:24:35
pjb
megachombas: when you use plaintext, you get code injection problems, and you need tons of PhD theses to find complex solutions and round abouts to avoid them. ANd you get a whole cottage industry to develop tools to test and avoid them.
22:24:55
pjb
megachombas: instead, you can use 60 years old technology called lisp, which uses data structures, and therefore the problem doesn't exist in the first place.
22:26:08
pjb
megachombas: when you use a language like C, you get buffer overflow, memory leaks etc, and you need tons of PhD theses about program verifications, sophisticated debugging tools such valgrind, and a whole cottage industry of tools and security audits to detect those problems and avoid them.
22:26:41
pjb
megachombas: instead, you can use 60 years old technology called lisp, which uses a garbage collector and run-time cheks, and therefore the problem doesn't exist in the first place.
22:28:15
pjb
megachombas: just to say, that it's worth learning it, to avoid all the dumb mistake the industry keeps doing over and over.
22:29:32
pjb
(defun |()| (\(\)) (if (null |()|) () (|()| (cdr |()|)))) (|()| '(\(\) |()| (\(\)) |()|)) #| --> nil |#
22:29:35
nirved
todays computer programs are so bloated, that the equivalent lisp machine running on the same hardware would be faster
22:34:15
aeth
With Lisp you can get self-documenting function names, e.g. (defun |Hello, world!| () (format t "Hello, world!~%"))
22:41:57
Shinmera
restarts aren't the magic part, you can get them with exceptions too. The magic juice is handler-bind.
22:42:28
dim
as in e.g. https://github.com/dimitri/pgloader/commit/25152f605495fbd3e3bdae555f8ca142490a6d65 ;-)
22:44:23
pjb
megachombas: perhaps it's too late for you, and you should go to sleep? WHen you have a function name read-from-STRING, why do you pass it a list?
22:44:53
pjb
megachombas: also we've explained that reading operations consist into transforming a TEXTUAL representation into lisp data.
22:44:58
rumbler31
I think he was planning on passing it the original form with the #1= reader macros
22:45:11
pjb
megachombas: so both on the count of READ and of -FROM-STRING you should give it a STRING, and not a list!
22:46:13
pjb
megachombas: but I'm trying to activate processes in your brains so you don't have to try twice before finding the right solution!
22:49:12
megachombas
pjb: it has been around 6 damn hours im trying to figure out what does the (move (loc -1 0) :R0)
22:49:46
megachombas
the loc is generated by the compiler here : https://github.com/thibaudcolas/clisp-compiler-vm/blob/master/compilateur/cas/fonctions.lisp
22:54:21
pjb
When it's positive, it skips the return address and stack frame, to get at the parameters.
22:54:50
pjb
How the parameters are passed, and what is pushed on the stack in addition to them and the return PC.
22:55:16
pjb
Usually, there's a FP link saved on the stack. You seem to have two more slots since it adds 4.
22:55:39
pjb
This is probably described in the documentation/specification of the VM and/or the compiler.
23:05:38
aeth
It doesn't look like particularly well-written Lisp in the first place. Unless the style got messed up in the cut and paste.
23:06:09
aeth
It violates every style guide I know of, which makes it harder to read that it should be.
23:08:54
Shinmera
I've seen enough mind boggingly awful template code from university lectures that I'm entirely ready to believe someone wrote this who just doesn't know lisp either.
23:09:41
megachombas
tried to wrote my own. but at arrrived at a point where i didnt understand lisp at all. found this one that was functional, so i tried to understand it to do mine
23:10:06
megachombas
but i arrived at a point where im still trying to understand this one, and bassicly doing small modifications
23:10:33
aeth
megachombas: If you need to pick up functional Lisp-style programming in a short amount of time, work through The Little Schemer (formerly The Little Lisper). It's in Scheme, but most of the lessons would carry over imo.
23:12:10
aeth
Do not put assignments off to the last minute. I tried doing this in college, and it ruined my health, possibly permanently.
23:12:42
|3b|
ACTION just put things off until past the last minute, much better for health (bad for grades though)
23:13:09
aeth
|3b|: If there are grace periods, and you're good enough to consistently be able to get an A even with the -10% penalty or whatever, it can still work
23:13:29
Shinmera
I try to do things as early as possible, but then I just get stressed out to all hell towards the end anyway.
23:14:02
megachombas
found this http://www.lirmm.fr/~lafourcade/ML-enseign/Compilation/compil-GenCode.HTML
23:15:38
aeth
megachombas: My recommendation to you would be to pick up processing things with cond. It's fast enough that you could pick it up quickly enough. A lot of functional-style Scheme and Lisp uses that basic style. (There's no time for fancier techniques.)
23:16:36
megachombas
yes, just i discovered those instructions today ,and he NEVER EVER give it to us
23:20:11
aeth
megachombas: COND is basically an if/elseif/elseif/.../else block, except that it is a form that also returns values so you can use it just like a very elaborate ternary operator if you wanted
23:20:21
aeth
This is its documentation: http://www.lispworks.com/documentation/HyperSpec/Body/m_cond.htm
23:21:10
aeth
megachombas: You should make sure you understand COND first, because you're probably going to need it in your program if is going to have any elaborate conditionals in it. It's simpler than fancier alternatives.
23:26:13
aeth
I would personally try to build something useful from the very simple basics of Lisp rather than trying to dissect an existing Lisp program. Build up from a toy program and gradually add the features you need.
23:27:08
aeth
It's very important, at least the way I program, to have a completely working program at every step of the way.
23:27:57
aeth
If your teacher actually didn't explain things properly, then don't panic. If it's a large class, lots of people will probably do worse than you, and the grades might be adjusted upward.
23:30:31
pjb
(get-newFP 2) returns the frame pointer of the caller of the caller of the current function.
23:30:59
pjb
This is why there's this loop and it updates the LOCAL variable newFP. But it doesn't modify (get vm :FP) the actual frame pointer!
23:31:06
aeth
megachombas: Is the assignment to build a register machine like on the website you linked to?
23:33:23
aeth
Well, if there's more freedom of choice, then choose a stack machine. They're (afaik) simpler, especially in languages that have stacks (CL has two built-in stacks). That might not be an option, though.
23:39:20
pjb
(get-loc-src vm expr) reads the memory containing the value of the local variable number EXPR in the current frame.
23:39:59
aeth
megachombas: Is the assignment something like this? Given the instructions, do the operations.
23:41:14
megachombas
the asignment is 'make a VM in lisp that use 4 registerys and a lisp compiler "
23:50:36
aeth
(And if your requirement is to compile a standard Lisp or Scheme, then you're doomed.)
23:58:32
aeth
I'm not sure any Lisp resources will be helpful. The assignment itself, even to those who know Lisp, will probably take more than one day to write.
0:01:05
aeth
(And no one is going to do your homework for you, so you'd have to add the time it would take to learn Lisp.)
0:03:05
pjb
aeth: for a student, yes. I would do it in a day, I already done it several times, including an assembler, a disassembler, etc.
0:03:33
aeth
pjb: I would estimate 3 days for someone doing it the first time, student or not. Obviously doing something more than once makes you write it a lot faster. Sorry, I could have been clearer.
0:04:15
aeth
A minimum of two calendar days because sometimes you get to a point where you get stuck and only sleep can solve things.
0:09:32
whoman
i am sorry to hear,i hope your health and quality of life returns to normal and/or improves
0:17:25
drmeister
Is there a lisp function that waits for the user to hit enter or a key - something that will work in slime.
1:26:22
pransninja
True to form, the Chapter 13 of PCL took me as long as every other chapter before it, the chapter title: Beyond Lists: Other Uses for Cons Cells
1:27:43
aeth
Lisp has multidimensional arrays, hash-tables, and other things that aren't cons cells.
1:30:39
aeth
Syntactically, everything's cons cells. The actual data structures that you create are not, though.
1:31:37
aeth
closures, hash tables, multidimensional arrays, structs, standard-objects, etc., couldn't be efficiently implemented with cons cells.
1:37:36
aeth
vectors (including strings) will have an O(1) length and an O(1) elt (or aref). lists will have an O(n) length and an O(n) elt (or nth)
1:38:05
aeth
Vectors have different performance characteristics. And even if they're expressed as lists in source code, they will (usually) be turned into vectors at compile time.
1:39:48
aeth
CL's hash-tables have a different performance trade-off than plists or alists. In theory, plists might be faster for very short things, but hash-tables will win for large data sets.
1:43:18
pjb
Last time I benchmarked, for implementations compiling to native code the break-even point was about 5 entries (<= 5 entries, a-list or p-list are faster; >5 entries, hash-tables are faster), and for byte-interpreted implementations such as clisp, the break-even point is more like 35 entires!
1:44:09
pjb
If you can bound the number of elements, to a small number, it may be even better to use a vector than a hash-table.
1:45:58
aeth
pransninja: You can't expect all implementations to behave exactly the same because maybe one day someone will finish JSCL or write a popular JIT bytecode CL.
1:46:21
aeth
pransninja: But hash tables are in the standard, as are vectors. And a lot of the same optimizations apply to all of the current major implementations.
1:46:49
aeth
e.g. unless you're using clisp, you can pretty much assume that you can make single-float and double-float specialized arrays.
1:47:22
aeth
That's what the standard says about hash tables (or at least one entry point into what it says)
1:48:28
aeth
Vectors will win more often than you think when numbers are involved because they can be specialized
1:49:26
aeth
There aren't any typed lists or typed hash tables (well, they all store type T), so vectors often give more information to the compiler
1:51:25
aeth
Most information is probably specific to SBCL (and/or CMUCL), but a good deal of that will also apply to CCL and possibly even ECL.
1:54:33
aeth
Most optimizations are imo a waste of time. Generally you want to (declare (optimize (speed 3))) and declare any types that are numeric or arrays (if you can provide length information for the array type, that can really help because the compiler may replace repeated bounds checking with one type check at the beginning of the function)
1:56:11
aeth
If everything is of the same numeric type, you can use :element-type in make-array, e.g. (make-array 3 :element-type 'single-float :initial-element 0f0) or (make-array '(2 2) :element-type 'double-float :initial-contents '((0d0 0d0) (0d0 0d0)))
1:56:41
aeth
If things aren't of the same type but are numbers or arrays, typed slots in a struct (defined with defstruct) might work
1:57:32
aeth
If something is trivial and probably never going to change, inlining can help the compiler. Above the function you can do this: (declaim (inline the-function-name-goes-here))
1:59:07
aeth
Not every implementation will use all of the optimization information you give it, e.g. CLISP doens't have single-float or double-float specialized arrays, and just makes them T arrays. I think almost every implementation does accept single-float, double-float and a large number of integer types (e.g. (unsigned-byte 8) and (unsigned-byte 32))
1:59:24
aeth
Only character and bit are required by the specification, but (unsigned-byte 8) is heavily assumed by many libraries.
2:00:52
pjb
aeth: on the other hand, clisp has short-float that will fit immedately into arrays of T!
2:01:27
aeth
pjb: The arbitrary-precision long float is the one reason to use CLISP for code that deals with numbers, afaik.
2:02:31
pjb
pransninja: you can reason with clisp, you just need to know what CL functions are implemented in C and what are implemented in lisp!
2:02:52
pjb
If you write your function to process your data with CL functions implemented in C, then it'll be fast. If you do it in lisp, it'll be slower.
2:03:56
pjb
So what's funny is that basically you must adopt a style opposite to what you'd do in sbcl to write efficient code in clisp :-)
2:04:32
aeth
pransninja: For advanced optimizations, you might be interested in specialization-store. https://github.com/markcox80/specialization-store/
2:05:27
pransninja
at this point, I would like to learn the basics of how you go about optimizations in lisp
2:06:03
pransninja
Though, the fact that optimizations depends on the compiler, which is fair, but still, makes it hard.
2:06:55
pjb
pransninja: it goes like this: you write code that works, without having to deal with memory management or array overflow, because this is controled by the implementation. Once you have something that works, since you've spent 1/10 the time you'd have spent in C, you are left with 9/10 of the time to think about better algorithms. So you can implement them and obtain faster results.
2:13:00
shrdlu68
pransninja: When compiling with slime you get optimization tips (at least using SBCL)
2:13:54
aeth
pransninja: The list I gave is pretty much all you need, except perhaps with the added advice to preallocate things before large loops. Consing (heap allocation) in large loops might hurt performance.
2:14:17
aeth
CL is not a pure functional programming language. People are fine with using things like setf when it helps performance
2:15:45
Pixel_Outlaw
I think it's less /functional/ to mandate a single style at the expense of the programmer's style.
2:15:54
aeth
Most of the advice is about providing array or number type information to the compiler. That's because functions like + and map are type-generic, but can be inlined by the compiler if the type is known. A lot of type information will be given to the compiler just by the function call. e.g. you can only use car on a cons cell
2:19:09
aeth
(Providing the array types can potentially also do two other things: remove bounds checks and tell the compiler the type of the thing that it gets with aref)
2:33:20
aeth
pransninja: What are you interested in optimizing, btw? If it's a program that essentially uses no numbers anywhere, almost all of the advice I just gave is worthless.
2:36:05
aeth
Generally, I optimize on SBCL and hope it works on the other CLs because they just don't expose as much useful information. An almost-complete implementation called Clasp (a C++ and LLVM CL) might, though. And SICL (not anywhere near complete afaik) is designed to be very easy to debug.
2:37:24
aeth
Only optimize the parts that matter, though. You can spend literally forever getting an extra few percent, and the more specific the optimizations are, the less likely they are to be portable away from SBCL.
2:41:14
aeth
(I think the point where you've gone way too far is probably if your code has implementation-specific optimizations all over the place. And if you're inlining assembly...)
2:50:51
aeth
Afaik, for anything that can be expressed as a specialized array, vectors will win unless you construct those benchmarks carefully to have lists win. Lots of inserting in the middle, maybe?
2:52:35
aeth
For the best performance with arrays, though, you'll want known length and you'll want an :element-type that actually gets used (not just a T array).
2:55:03
aeth
So the most dramatic wins for vectors over lists would probably be something like 4x4 matrix multiplication.
2:56:32
aeth
(especially when the matrix has the :element-type defined as single-float or double-float)