freenode/#lisp - IRC Chatlog
Search
20:58:34
aeth
Well, I can use them *in the REPL* rather than in the program, such as (defparameter *window* (function-call-that-returns-a-window)) and then I can use method calls on the window object
21:00:20
aeth
didi: Iirc: defparameter overwrites it, though. If I do defvar, wouldn't the first one have to be the defvar, and then subsequent ones setf?
21:01:10
didi
aeth: Yeap. It's more of a concept thing, I read. defparameter if for program definitions, defvar for variables.
21:01:47
aeth
In the REPL I always use defparameter because defparameter is what I expect (especially since I mostly use backwards history search in the REPL)
21:02:13
onion
hm yeah. this is also something that writing a C lisp runtime with SDL , could solve. for eg. it would take care of any globals that need to be around, like the SDL window, audio context
21:02:27
_death
when there's pervasive context, use of special variables makes sense.. also makes for a much better experience when using the repl.. other languages tend not to have special variables, so there's no comparison
21:03:52
aeth
onion: I put the things that need to be around in one window object (e.g. the SDL window, the GL context, etc.).
21:05:16
aeth
It's very, very easy to wind up with way too many things in general, so I heavily use both CLOS objects and structs all over the place, and probably need at least twice as many as I do use because there are just too many things. I think at one point, one function said something like "function foo expects twenty-one arguments but only twenty were provided", but I think I've halved it since then
21:05:44
aeth
Yeah, globals could probably help, too, but it doesn't actually tidy up the mess: it puts the mess in 20+ globals
21:07:29
onion
aeth: i think that is what i will do as well. i only really need the GL/AL context and SDL stuff
21:07:49
onion
...not that any apps make more than one SDL window or anything else... overdesigned i think =)
21:08:31
aeth
onion: That's one reason I write my own stuff instead of using libraries. Libraries have to handle every case, my own stuff on the raw CFFI only need to handle my case, and are about equally verbose.
21:08:45
aeth
More than one SDL window? Nope! I can say that will absolutely never be permitted, at least for now.
21:09:22
aeth
If you handle more than 1 use case when there is more than 1 possibility, you will never get past that area, and you probably won't test all code paths.
21:09:24
onion
im just saying it seems like an overdesign for SDL2 to just about force globals "just in case" someone needed more SDL in the same thread
21:10:15
aeth
_death: In CL, large seems to start at around 7k. I'm absolutely astonished when I see some CL things above 100k (SBCL?) because that's probably equivalent to about 5M in other languages.
21:10:49
aeth
Although I expect that when it's finally working it will be around 25k. I spent about 2 years around 5k, though, because with macros it's hard to actually have forward progress in line count.
21:13:26
aeth
But it's not really line count in CL, it's what you're doing. There's a lot of stylistic freedom.
21:14:01
Shinmera
Doing a primitive line count on my projects directory (which doesn't have everything) I get around 200'000 lines. Neat.
21:16:41
aeth
Running "cloc ." on my outdated SBCL git checkout (cloc cuts out comments and blank lines, but not the docstrings) says SBCL is 401130 lines of Lisp and 26921 of C and 3817 of C headers and 3681 of sh and 2382 of asm
21:19:43
aeth
Well, of course most Lisp in the wild is Emacs Lisp, and probably a lot of that eventually makes its way into Emacs itself.
21:20:16
aeth
(and iirc cloc doesn't distinguish between EL and CL, so it might not be 100% accurate for projects that have Emacs modes in their source tree)
21:20:54
aeth
Emacs Lisp isn't particularly well-written Lisp, though. In general. I think a lot of it is working around the limitations of the language, and a lot of it is Lisp written by people who have no CL or Scheme experience.
21:21:09
aeth
I'm not sure how the standard of the core compare to some of the horrifying add-ons whose source I've read, though
21:22:33
aeth
If you're normally a C programmer and you write an EL file, you're probably not going to abstract as much as a seasoned CL programmer writing a CL application. And many common abstractions might introduce too much of a runtime penalty in EL vs. in SBCL or CCL.
21:24:01
aeth
If you know how to make an AOT compiled CL perform, you can get away with writing a lot of "zero cost" abstractions that probably don't work in other Lisps.
21:25:33
onion
i did cl-bench on SBCL and ECL the other day , i dont see what it gains; they could just compile with SBCL. =)
21:25:55
aeth
I generate GLSL strings from CL macros at compile time. It probably wouldn't take *that* much to also support C given the major similarities.
21:29:10
aeth
onion: SBCL is an order of magnitude more popular than CCL, which is an order of magnitude more popular than the rest.
21:31:07
aeth
Personally, I only try to support SBCL, CCL, and ECL. The other popular FOSS ones are CLISP and ABCL, which are both problematic in various ways when making assumptions that work on the rest (especially on SBCL and CCL). And for LispWorks/Allegro, well, they can always pay me if they want me to support their really expensive implementations. Or at least give me free copies.
21:31:58
aeth
It's probably hard to judge the relative popularity of the long tail but still used implementations (ECL, ABCL, CLISP, LW, Allegro)
21:38:28
aeth
Oh, I might have been unclear. SBCL is an order of magnitude more popular than CCL, which is an order of magnitude more popular than any remaining individual implementation... Not necessarily an order of magnitude more popular than all of the rest combined.
21:39:27
aeth
And no matter what it'd probably undercount commercial implementations, which are kind of in their own world.
21:39:32
void_pointer
When I first heard that, I found it quite surprising. I was under the impression that the gaps between 2nd and 3rd was much narrower, and 1st and 2nd a bit narrower
21:40:06
aeth
void_pointer: Things were probably narrower 10 years ago when CLISP was extremely popular. Years of no release has made it decline significantly afaik
21:40:37
_death
aeth: if you think about the primary feature of ECL, being embeddable, then the number of users (developers) is also more tricky to determine
21:41:01
void_pointer
that would explain it. I had tried picking up common lisp a first time back in 2013 and then put it down until just late last year
21:41:20
aeth
I'm guessing 10 years ago CLISP was up there with SBCL and LW might have been up there as well
21:41:34
aeth
It's really hard to compete with SBCL, though. It's both the fastest *and* the most informative.
21:41:54
aeth
(In general, of course. I still catch things that SBCL tolerates and CCL does not, for instance.)
21:42:24
aeth
jmercouris: CLISP is a bytecode implementation, so it's probably the first to every new platform. (Not a big deal when everyone is on x86-64 or ARM, and maybe RISC V in the future.)
21:42:28
jmercouris
aeth: I find it the other way around, SBCL is constantly complaining about things that CCL accepts unquestioningly, what platform are you running on?
21:43:21
void_pointer
ECL has some major advantages when working with lots of C code back and forth. That is one area where SBCL has some disadvantages
21:43:36
aeth
It also takes a *long* time for accurate and up to date information to spread. A lot of old material tells people to use CLISP or the free LW.
21:44:05
aeth
The common wisdom today is probably something along the lines of: "Try SBCL then CCL then ECL in that order." That wasn't the advice from 1998 to 2010. And those sites and books are still there.
21:45:18
aeth
Fedora has SBCL and ECL, and maybe one or two more obscure ones. But does not have CCL.
21:45:21
void_pointer
phoe: yes, in its various facets. Different GC helps a lot, even though it hurts performance in many ways.
21:45:34
aeth
Pretty much every Linux (or other Unix) distro that has a packager who cares about CL is going to have SBCL
21:45:35
phoe
aeth: I do not think any Linux has CCL in its repos. not from the popular ones at least.
21:46:29
void_pointer
if for no other reason than to make sure my code runs on multiple implementations OK
21:47:15
void_pointer
GNU/Linux, but the project I am working on would target other OSes as well - specifically Windows, Max OS X, and possibly FreeBSD
21:47:16
aeth
I use roswell to get the latest SBCL and ECL and CLISP (hah, like they'll update it), and to get any access to CCL, ABCL, Clasp (roswell fails to compile it, which is annoying because the failure happens after at least 10 minutes; maybe it works now), etc.
21:47:47
aeth
I develop on Fedora's SBCL, though, because it's recent enough. Fedora seems to treat every SBCL release as potentially breaking, so it only updates when the distro updates, which is every 6 months. Current enough, though.
21:48:27
phoe
void_pointer: just grab a ccl package from the website and ln /opt/ccl/lx86cl64 /usr/bin/ccl
21:49:02
void_pointer
between that and having to worry about both amd64 and arm, I have to stay rather flexible with respect to implementation still
21:50:36
didi
ACTION keeps forgetting `:initial-value nil' and no :initial-value are different for reduce
21:51:38
aeth
I've been waiting for a cheap (< $250), low power RISC V for years at this point (lowRISC used to say that it would release sometime in 2017). It's close enough to MIPS that I think CCL and SBCL will support it fairly quickly.
21:53:59
void_pointer
funny thing, just ordered one yesterday - pi 3 B+. Getting it for common lisp development actually. Want project to run on low end ARMs with decent enough performance. If it can work well enough on it, then it will work quite a bit better on higher end ones. Also, reduce ISA assumptions
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.