[HN Gopher] Common Data Structures in Common Lisp
       ___________________________________________________________________
        
       Common Data Structures in Common Lisp
        
       Author : djha-skin
       Score  : 44 points
       Date   : 2024-05-18 23:10 UTC (23 hours ago)
        
 (HTM) web link (blog.djhaskin.com)
 (TXT) w3m dump (blog.djhaskin.com)
        
       | nomilk wrote:
       | I started learning common lisp this week. Instead of jumping
       | straight into code/syntax as I would with other languages, I
       | spent the first 3 days reading about (and trying to understand)
       | homoiconicity.
       | 
       | The tl;dr is it's metaprogramming made extremely convenient. In
       | other languages metaprogramming might involve regex to parse
       | string representations of code, perhaps string interpolation, and
       | eventually pass strings to eval() or similar. But since lisp code
       | _is_ its own data structure (not just a string as in other
       | languages), the ways of interacting with and altering lisp code
       | programatically are every bit as robust as the methods for
       | altering any other data structure (like a list or array).
       | 
       | For obvious reasons, I'm proceeding with caution, as some
       | practices are best exercised judiciously or infrequently (or
       | never e.g. ruby continuations).
       | 
       | But my early thoughts are that now that I know of this concept it
       | seems odd that it's not feature of every programming language. I
       | guess languages can still be highly productive without
       | metaprogramming as a first class citizen. And, funnily, it's
       | probably a good thing if tools like metaprogramming (and
       | properties like homoiconicity) are a not obvious first choices
       | for solving problems.
        
         | skydhash wrote:
         | Almost every time I try to reach to meta-programming, on second
         | thought, I found out that writing a method was the simpler way.
         | I'm not a LISP expert, but IMO, if you're not building a
         | library, meta-programming is an exotic paradigm. And that's
         | because you're defining a new language, not adding new words in
         | a dictionary.
         | 
         | I think it's quite nice if you're building tooling though. Like
         | creating a web framework to write web apps, or translating
         | business queries to SQL.
         | 
         | Writing imperative code always felt like transporting buckets
         | of water. But CL (and other functional languages) feels like
         | building a pipe system. Much more knowledge required upfront,
         | but getting nicer the further you progress.
         | 
         | ADDED:
         | 
         | That's why there are so many frameworks, especially in the web
         | dev world. It's nice to have someone carry the buckets to your
         | room, even though you need to get it inside. The trouble starts
         | when you want water somewhere not serviced. You have to figure
         | the service routes to take it of at the most convenient place.
        
           | citizen_friend wrote:
           | For typical projects you just need a handful. In other
           | programming languages that means code generation or macro
           | hell. So it is nice that it's built into the language to do
           | it properly, even if you only use it for those few things.
        
           | lispm wrote:
           | Let's imagine we want to program some kind of state machine
           | machinery.
           | 
           | We can ask ourselves questions: what should it do? how should
           | it work? what kind of features would it need to provide? From
           | what parts would we like to build it? How can we integrate it
           | into the programming language we use? How can we make it
           | fast? How can we deal with errors?
           | 
           | There is a question we haven't been asking yet: how do we
           | want to write them down? What would be a compact notation,
           | verifiable for a state machine?
           | 
           | That's something which one can ask very early in Lisp: How
           | should my code look like? How can I make sure I understand
           | the state machine itself (not the low-level programming)
           | months, years later and make changes to it?
           | 
           | One way to answer that would be to add a syntax extension for
           | state machines to Lisp. That would be embedded into the
           | language. One can experiment with that, without the need to
           | write too complex scanner&parser combinations. Just write the
           | state machine as a list of state descriptions. A macro could
           | transform it at compile-time into (efficient) low-level
           | operations.
        
         | pjlegato wrote:
         | If you like CL, try Clojure -- all the Lispy goodness, but with
         | access to modern, industrial-use libraries.
         | 
         | Common Lisp is largely abandonware at this point -- e.g.
         | there's no standard way to open a TCP socket!
        
           | djha-skin wrote:
           | I actually switched from Clojure to CL.
           | 
           | I switched because I was making command line tools and
           | clojure's startup time is abysmal. Babashka doesn't have all
           | the libraries and GraalVM's native image requires herculean
           | effort to work even a little bit and spits out monstrously
           | huge binaries.
           | 
           | Common Lisp is actually a lot more popular than I thought it
           | was. I think perhaps it doesn't look that way, but it's very
           | strong I assure you. Join us on the lisp Discord!
           | 
           | It is possible to create relatively small binaries out of the
           | box with nearly instant startup time. There's plenty of
           | libraries and a strong community. There's also a great number
           | of implementations.
           | 
           | A lot of the things that are not standardized in the standard
           | have been standardized via implementation agreement and
           | libraries abstracting away different implementation
           | differences, such as cffi and bordeaux-threads. I defy
           | closure to have anything nearly as feature complete for
           | parallelization as parallels, blackbird, and CL-async.
           | Speaking of which, the C FFI story is strong enough with lisp
           | that any major missing library or language feature usually
           | has a wrapping list Library around that feature written in C.
           | While it's not standard, all the major implementations have
           | adopted gray streams and people use flexi streams to open
           | sockets. It's the same kind of du jour standard that Clojure
           | relies on.
           | 
           | The standard is flexible enough to have several different
           | implementations on several different platforms. If I need to
           | interface with jvm languages, I can use armed bear common
           | lisp. If I need just a really strong implementation that
           | works in most situations I can use CCL or sbcl. If I need to
           | integrate heavily with C or C++ code I can use ecl or clasp.
           | 
           | It is clunkier because it takes the view that agreement
           | between programmers is more important than clean syntax. The
           | standard was created to unite the different lisp
           | implementations instead of divide them. I value this view.
        
           | lispm wrote:
           | https://usocket.common-lisp.dev/
        
           | hcarvalhoalves wrote:
           | I've been working with Clojure for the past 8 years, and
           | while I can vouch for it, I wouldn't say it has _all_ the
           | Lispy goodness of CL:
           | 
           | - it lacks a robust debugger (where you can step, redefine,
           | continue...)
           | 
           | - it uses the GC of the host VM
           | 
           | - can't save interpreter images
           | 
           | - is designed to be a hosted language, meaning many
           | implementation details are left to the host VM (JVM or JS)
           | 
           | - type checking
           | 
           | - performance
           | 
           | Also, wouldn't call CL abandonware, since it's a standardized
           | language. Abandonware by my definition is all the Python 2 or
           | JS code that you can't run on a current implementation.
        
           | phoe-krk wrote:
           | There is - USOCKET:SOCKET-CONNECT.
           | 
           | If we end up in petty and unproductive nitpicking like that,
           | then there's no standard way to open a TCP socket in Clojure
           | either. Mostly because Clojure, unlike Common Lisp, does not
           | have a standard to talk of.
        
       | phoe-krk wrote:
       | It's weird to see singly linked lists, adjustable arrays, and
       | hash tables implemented in Common Lisp in such a post. All three
       | of these data structures are _always_ already implemented in
       | Lisp, as mandated by the standard.
        
       ___________________________________________________________________
       (page generated 2024-05-19 23:02 UTC)