5 ms·
Yes. That's a consequence of language design - unboxed arrays of structs mean no object identity, which means that operators like SETF and EQ no longer have the
by phoe-krk 3y ago
Yes. That's a consequence of language design - unboxed arrays of structs mean no object identity, which means that operators like SETF and EQ no longer have their invariants satisfied when performing assignment to such arrays.
- foldr 3y agoSure, there may be reasons for it, but it means you can’t really build zero cost abstractions. For example, you can’t make a simple 2D vector object with the standard operations defined over it and then store those vectors in flat arrays. This is something that can trivially be done in C++, Rust, etc.
- phoe-krk 3y agoProbably the best workaround for this is going into the foreign memory land - grab some raw memory, define operators over it, manage all that yourself. CFFI works across enough implementations for this to be feasible.
- lukego 3y agoYeah. Common Lisp has quirks and you need to adapt your abstractions to those. Sometimes it's easy, sometimes it's rewarding, sometimes it's just annoying. This week I'm scaling back some abstractions, writing more Fortran-like code on specialized arrays than individual objects, for the sake of zero cost. I appreciate a little bit of a headwind against inventing new abstractions too casually. But it does remind me of programming in C or Forth. That's not everyone's cup of tea.
- foldr 3y agoThis one isn’t a quirk, it’s a fundamental constraint on the kind of code that you can write in CL. C++, Rust, Go (and even Java to some extent, with all the wizardry in Hotspot) all allow you to build a 2D vector abstraction without requiring you to box your vectors. In CL you simply can’t do this. Just look at the kind of bonkers workarounds my comment gave rise to: https://news.ycombinator.com/item?id=35855576 https://news.ycombinator.com/item?id=35855576
- lukego 3y agoI don't really see the problem. If you want to define the bit layout of your objects then you define them using FFI. Support for FFI objects is comprehensive. It is exactly the tool for the job in Common Lisp. Same for LuaJIT. I've spent years happily writing high-level Lua code that's actually operating on objects whose bit layout is explicitly defined using FFI at the C level of abstraction. It doesn't feel much different to objects or dictionaries to me. Sure, it is great that those other languages have native support for inlining storage of structs into various containers, but the lack of such in Common Lisp only makes me write quirky code and doesn't really hold me back.
- foldr 3y agoIt’s not a problem if you don’t need zero cost abstractions (which indeed you may not, depending on your domain). But if you do, then using the FFI to define unboxed arrays of a simple 2D point class is considerably less attractive than writing struct Point { float x, y }; Point points[10]; If you really can’t see this then I think we’re at an impasse.
- kazinator 3y agoIn Lisp, we can embed a lower-level language, and macro over it. Like the defx86lapfunction forms in this file: https://github.com/Clozure/ccl/blob/master/level-0/X86/x86-array.lisp https://github.com/Clozure/ccl/blob/master/level-0/X86/x86-a... It would be useful to have a more abstract, portable form of this (vaguely analogous to WebAssembly): a way to write code for a low level virtual machine that translates to native code.
- foldr 3y agoYou're basically describing C++. Nothing in your link suggests a practical way of constructing unboxed arrays of structs in CL. And even if it did, it would presumably be one that worked only on a specific architecture.
- pjmlp 3y agoThat isn't what Bjarne means by zero cost abstractions. It means the abstractions produce the same code as having written the same manually without the abstraction, e.g. having a class with virtual methods versus having a struct with function pointers as fields.
- foldr 3y agoI interpret the term compostitonally. But CL doesn’t have zero cost abstractions in that sense either. Take the example I mentioned. Say that you’re looping through an array of pairs of 2D vectors and calculating the dot product of each pair. In C++ you can use your 2D vector class without any additional cost. In CL you either need to remove that abstraction (and deal with flat arrays of scalars) or incur the cost of boxing. More generally, if every object with its own methods requires a boxed representation, then that severely limits the range of zero cost abstractions that you can create. If using the abstraction requires boxing then it’s not zero cost. (If Bjarne disagrees on that point, then I disagree with him!) Anyway, I’m sure you know all this, so I’m not really sure what point you’re trying to make here. I don’t think anyone would suggest that CL is a good language for building zero cost abstractions, whatever the precise definition of the term.
- pjmlp 3y agoGenera, TI and Xerox thought otherwise. Unfortunely all of them messed up on management, and fighting against free UNIX source tapes. "What you don’t use, you don’t pay for. And further: What you do use, you couldn’t hand code any better."
- foldr 3y agoMy original comment talked about 'portable CL'. I am interested though: how would you define an unboxed array of structs in Genera's dialect of Lisp? Your quote clearly applies to my example. You can avoid the boxing by hand coding the dot product computation over flat arrays; you can't avoid the boxing if you use a 2D vector abstraction (in CL).