freenode/#lisp - IRC Chatlog
Search
21:54:29
jmercouris
void_pointer: a good way to test how good your code is to run it in a VM with low resources
21:54:56
jmercouris
it is very easy to deploy, and you can use something like vagrant with some provisioning system behidn it
21:54:59
aeth
I make one architecture assumption: 64-bit, with a large enough implementation fixnum size (60ish is fine; this is something that both 64-bit CLISP (48ish bits) and ABCL (uses 32-bit int) fail afaik)
21:55:09
void_pointer
aeth: on risc-v, more likely to see a cheaper board from sifive soon than lowrisc, I think
21:55:51
aeth
The problem with 32-bit is that the size of everything depends on fixnum, and 32-bit is a *much* lower fixnum size. Also, single-floats are boxed. There goes the performance of anything that uses single-floats.
21:56:08
void_pointer
aeth: I have used 64bit SUSE on a pi 3 already (port had a lot of work left to do, sadly)
21:56:33
aeth
I write double-floats with care, and at least SBCL knows that it doesn't have to box them if they're stored in arrays (or structs) of the right type and accessed the right way. I don't write single-floats with care, because that would be annoying.
21:56:55
aeth
So while stuff I write that use floats could run in 32-bit, it will absolutely destroy the GC if in a hot loop
21:57:07
void_pointer
jmercouris: a VM is useful for that, and I do plan on using some VMs for some more extensive tests across more processor families
21:57:53
void_pointer
jmercouris: though, one thing a VM doesn't provide, is a physical GPU, though admitedly the pi's is quite pathetic (which in some ways is ideal for what I am working with)
21:59:40
aeth
jmercouris: The big CL program I'm writing is a game engine. It's not CPU bound, it only uses about 2% to 8% (mostly on the low range) of my i7-4790k (might already be too slow for a pi3) because it runs the logic at 100 FPS and the rendering vsynced. (I don't have networking yet, but if used on a headless game server, it'd probably use a lot less CPU because the rendering takes up a lot of the CPU)
22:00:00
aeth
But it's a game engine, or possibly a game framework. Depends on how I market it in the end. The CPU overhead has to be low because that means that the users can do more things with it.
22:01:26
aeth
I'm told that the CPU% thing might not be 100% accurate because the modern computer might go into a lower power mode. And my engine might be low enough in CPU usage that it might send the computer into low power mode. Idk.
22:01:34
void_pointer
on a pi 3, it might work ok if game logic and graphics run on separate threads
22:02:03
aeth
FPS is too influenced by the renderer, and FPS only really tells you when it's under the cap.
22:02:38
void_pointer
aeth: funny coincidence, but that is the sort of project I am working on as well
22:03:34
aeth
void_pointer: Common Lisp seems to be increasingly popular, at least on Freenode, for this sort of thing. I even see it show up from time to time in #reddit-gamedev, not just in the Lisp-specific #lispgames (although I haven't seen it in #gamedev yet)
22:03:49
aeth
I guess people want something Pythonish, but without absolutely terrible performance for this sort of thing.
22:04:23
aeth
(The fast Schemes are not the Scheme with all of the libraries, at least at the moment.)
22:04:57
void_pointer
had similar reasoning here - that and a better package situation than scheme (honestly, would have preferred scheme otherwise)
22:06:34
jcowan
aeth: Chicken is plenty fast, though not as fast as Chez or Stalin, and is certainly not short of libraries
22:07:12
aeth
jcowan: Chicken is the only one where I'm not aware of a gamedev community. Racket obviously has games. And davexunit represents Guile in #lispgames and has actually made patches to Guile to improve its performance in gamedev
22:09:21
aeth
jcowan: I think that at least for the specific performance requirements of games, though, that source-to-source compiling r7rs Scheme to SBCL (with CCL as a backup implementation) will get the best performance.
22:09:38
void_pointer
jcowan: I did not think about that. That might be useful later on if I need access to various nvidia cards or older amds (got access to two intel integrateds, a newish high end amd, and well, what the pi 3 will have)
22:09:49
jcowan
I'd love to do that, although presumably one would need to take precautions around call/cc.
22:10:06
aeth
jcowan: My cl-scheme is essentially on hold until I can think of a fast, elegant call/cc
22:10:46
jcowan
I wrote a clean-room CL implementation of T years ago but had to punt on tail recursion (not commonly provided then) and call/cc.
22:10:47
void_pointer
also, might have to do chicken style MTA due to the recursion, which might not be pretty in common lisp (honestly have no idea, but wouldn't want to try it myself)
22:11:10
aeth
phoe: The way I do it in cl-scheme, it wouldn't matter. It's not like Pseudoscheme where it compiles to CL and drops the Scheme features that don't fit. It's more like... it adds a very small runtime so that it can handle all Scheme features.
22:11:44
aeth
At the moment, I use a trampoline to get tail recursion, although I guess I could make non-portable assumptions to bypass the trampoline. It's hard, though, because it's not a matter of implementations, it's a matter of implementations *and* optimization level
22:12:44
aeth
A trampoline to get tail recursion is actually very small in CL, maybe a dozen or two dozen lines, and it isn't noticably slower than actually doing tail recursion. (It probably is slower, it's just not slow enough to be detected when I benchmarked in SBCL)
22:12:53
jcowan
aeth: I think most non-CLISP implementations provide tail calling nowadays, though others here probably know better than I.
22:13:13
aeth
jcowan: The problem is that SBCL with (optimize (debug 3)) afaik turns that off, and a lot of people use debug 3.
22:13:40
aeth
And if the point of transpiling is maximum speed, the main focus will be getting it to work on SBCL
22:14:52
jcowan
"What would we think of a sailing enthusiast who wears his lifejacket when training on dry land, but takes it off as soon as he goes to sea?" --C. A. R. Hoare
22:15:05
aeth
I started out with an interpreter approach and quickly moved to source-to-source compilation, but if I return to the project I might add back the interpreter because apparently a lot of people (literally several!) were interested in the sandboxing aspects.
22:15:26
aeth
It might also be possible to (eventually) write a cl-cl with some common code with cl-scheme, to get a similar result but for CL
22:17:25
aeth
Iirc, the two things that stalled cl-scheme were (1) call/cc and (2) a mutable global lexical environment (which outside of the REPL is afaik optional, but probably nice to have).
22:17:40
jcowan
I'd like the reverse, the ability to compile CL to Scheme, but the main cost there is library cost.
22:17:56
aeth
By global I mean "global" because it would be contained to the cl-scheme runtime. I could just do something like wrap that in one big let, but then you can't add to it.
22:19:26
void_pointer
jcowan: well, if you can compile common lisp to emacs lisp, then you get pretty close since Guile can compile that into one of its intermediate representations which is scheme like and could possibly be compiled to scheme without that much effort
22:19:42
aeth
void_pointer: That sounds like a lot of performance would be lost, though. At every step.
22:20:35
void_pointer
jcowan: not that I know of. But emacs lisp is closer to common lisp than scheme is, so it should be easier
22:20:41
jcowan
CL itself (that is, the special forms) would be straightforward to compile to Scheme.
22:21:00
random-nick
guile doesn't do a really good job of compiling emacs lisp, since it doesn't have many optimisations for dynamic scope
22:21:40
jcowan
Bike: Yes, but for the purpose of providing a CL library so that CL code compiled into Scheme will get the environment it expects
22:22:14
aeth
What I want in the long run, although it's kind of on hold until I make significant progress in my game engine (I chose to prioritize that project), is a lot of languages running in one CL runtime. Starting with Scheme because it's close to CL, although it has some significant differences (nil vs. #f and '() is actually one of the more annoying ones to work with)
22:22:26
jcowan
If SICL were fully working it would just be a matter of replacing the SICL back end with one that generates Scheme.
22:22:30
aeth
Ideally, I could spin off a bunch of libraries from cl-scheme and other people could port languages that they want, like JavaScript or Lua.
22:22:41
void_pointer
if performance didn't matter at all, would take clisp which can make gnu lightning bytecode and then compile the resulting bytecode to scheme
22:24:34
aeth
jcowan: My solution is to make #f :false (although I will have to change that if I add keyword support) so I can completely use the host CL's lists without issue. This requires every CL predicate to be wrapped when called from Scheme, though.
22:24:46
aeth
jcowan: It has been a long time since I read about Guile's solution but I think I was inspired by it
22:25:40
aeth
In case anyone is wondering, this appears to be the page: https://www.emacswiki.org/emacs/GuileEmacs#toc7
22:26:24
aeth
jcowan: I think it's actually easier to do such a thing from a Scheme host instead of from a CL host
22:27:04
aeth
I want to use as many CL built-ins as possible, for performance. Anything that's built-in will probably be faster than anything I write myself. Or, at worst, equally as fast and much more concise to write.
22:27:29
aeth
It will also leave a clear path for using Quicklisp libraries. Just wrap them the same way as CL built-in functions/macros.
22:29:02
Bike
sicl is written in common lisp, so you need a common lisp implementation to build and to load it
22:29:07
aeth
As for the performance of :false, I think the disassembly is essentially identical in SBCL with comparisons to NIL. It just compares to a different magic number, representing :false, than the magic number representing NIL.
22:29:31
aeth
Any performance penalty would be at the conversion barrier when interfacing the two languages.
22:30:10
jcowan
Chicken, e.g., is distributed with both source code and compiler-generated C for that reason
22:34:05
jcowan
aeth: You're saying that (if (eq? foo :false) this that) compiles to the same thing, modulo a constant, as (if foo this that) in SBCL?
22:35:21
jcowan
Almost any Scheme would trivially provide all the SICL primops, from the list I saw, and it would already have a GC and so on.
22:35:38
aeth
(defun foo (foo this that) (if (eql foo :false) this that)) (defun bar (foo this that) (if (null foo) this that)) ; the only difference in disassemble is one line: ; 302: 4981F86FA94F20 CMP R8, #x204FA96F ; :FALSE vs. ; 92: 4981F817001020 CMP R8, #x20100017 ; NIL
22:36:49
void_pointer
Bike: I guess one criteria is whether it can, if you just download the source, whether it can be built without having to already have a built version or another common lisp implementation
22:36:54
rme
on some ccl ports, nil is just a really popular constant. on other ports, it has its own tag.
22:37:16
void_pointer
Bike: GCC, for example, requires a working C or C++ compiler to already be there
22:39:01
aeth
(defun foobar (foo this that) (if (not (eql foo :false)) this that)) (defun barfoo (foo this that) (if foo this that)) ; essentially the same, it's still testing against :FALSE or NIL
22:39:09
jcowan
ACTION remembers when NIL was internally represented as all-bits-zero and there were zeros at locations 0 and 2
22:39:57
void_pointer
Bike: depends on who one asks. There is this one project https://gitlab.com/janneke/mes whose part of a collection of tools whose goal is to bootstrap GCC from a small assembler (assembler to build minimal scheme implementation and C compiler (in scheme) to then build tcc and then try to build gcc)
22:41:13
aeth
There is an idiom where :false as #f is going to cause problems, though. You can type something in CL as (or foo null) and it'll behave exactly as you would expect it to behave. Either it's false or it's a foo.
22:43:02
jcowan
if you all you need for your new chip is an assembler sufficient to assemble a (macro-assembler version of) Scheme, you are in business
22:44:29
Bike
ok so anyway, clasp's problem is that it mostly builds from C++ without lisp, and along with a few other things this makes the build a stupid process
22:44:31
aeth
jcowan: I think "esolang" is a bit... lacking of a term. There are two kinds of esolang. "artistic/simplistic" ones and "malicious" ones. Brainfuck is a simplistic one, not an actively malicious one (although the way it jumps makes it hard to do anything useful)
22:45:36
aeth
Bike: The problem is that everything eventually becomes mathematically useful. Ask pure mathematicians.
22:46:05
aeth
(Well, that's a similar case... where pure math gets applications in comp sci or physics)
22:47:40
Bike
brainfuck didn't "become" useful anyway, it's essentially identical to P'', invented in 1964
22:48:22
aeth
I tried writing a CL in Brainfuck, but then I realized that it's at least 10x harder than writing one in asm, and asm would at least be useful to someone.
22:49:18
void_pointer
Bike: sounds like clasp's bootstrapping situation isn't that bad, unless it takes forever as C++ often does (now reminded of how bootstrapping Guile can take well over an hour)
22:49:24
aeth
Writing directly to some VM's register machine or stack machine is probably considerably easier than BF.
22:49:44
Bike
it would be far more sensible to build from something else, and i've done some work in that direction, but that's still hard
22:50:48
aeth
I think the only way to have useful BF as a compilation target is to move the world around some central area (so it's always close by) as you walk through the BF tape. Or perhaps have two BFs talk to each other.
22:52:41
aeth
C++'s focus is on adding very many "zero cost" (at runtime! not at compile time!) abstractions.
22:53:37
aeth
An extended macro system could probably do something very similar to what C++ does in a Lisp without the massive time penalties of C++ compilation.
23:01:14
rme
It bootstraps by writing a minimal image file (which it constructs in memory), and alsocompiling (or cross-compiling) additional source files that comprise the rest of the lisp. You can then start the bootstrap image, which will then load those fasl files. Then you save an image of the lisp you just made.
23:10:22
phoe
so basically, as soon as someone can create a minimal image file outside CCL, then CCL becomes sanely bootstrappable?
23:21:29
phoe
I looked at CCL's bootstrapping process some time ago and I wouldn't call it mad, if that's what I accidentally implied.
23:24:17
aeth
Ahah! At least in SBCL, I can do this: (deftype false () `(member :false)) and then these are essentially identical: (defun foo (x) (typep foo 'nil)) (defun foobar (x) (typep x 'false))
23:24:39
aeth
At least one more point in favor of using a keyword or symbol when embedding a language that requires separating false and '()
23:26:25
aeth
Ahah! At least in SBCL, I can do this: (deftype false () `(member :false)) and then these are essentially identical: (defun foo (x) (typep foo 'null)) (defun foobar (x) (typep x 'false))
3:19:37
jcowan
perhaps sbcl stands for sanely bootstrappable common lisp, at least some of the time?
8:39:58
shrdlu68
flip214: How did you solve the multithreading thing where different threads were writing to a stream?
8:41:19
flip214
I was stumbling about having :if-already-exists :append and did look at old data in that file.
8:57:53
jeosol
flip214: had similar problems with my parallel code, and used with (bt:with-lock-held ...)
9:17:54
MrMc
I am trying to use parenscript with the Chartist javascript library how do I get parenscript to emmit new Chartist.Line('.ct-chart', data);
9:20:17
MrMc
The challenge is that this is wrapped as a function returning new Chartist.Line('.ct-chart', data)