HNHacker News
TopNewBestAskShowJobs

lispm

1 karma · joined February 12, 2025

submissionscomments
lispm··on Big Tech to EU: "Drop Dead"
Wasn't there a war in the US because of leaving states? ;-) How was that "referendum"?
lispm··on Big Tech to EU: "Drop Dead"
"abolish European governments by merging them together into one superstate"

That wasn't the goal of the EU. Even now it isn't the goal. Nations and governments still exist.

lispm··on Big Tech to EU: "Drop Dead"
That's a very simplistic view.
lispm··on Big Tech to EU: "Drop Dead"
"Schumann declaration", 1950:

"By pooling basic production and by instituting a new High Authority, whose decisions will bind France, Germany and other member countries, this proposal will lead to the realization of the first concrete foundation of a European federation indispensable to the preservation of peace."

The European Federation was the goal.

lispm··on Big Tech to EU: "Drop Dead"
The ECSC (Treaty of Paris, 1951) started as one of the first projects for cooperation in post-WW2 Europe. The more important step towards as single market then was the EEC (-> Treaty of Rome, 1957).

https://en.wikipedia.org/wiki/European_Economic_Community

lispm··on Big Tech to EU: "Drop Dead"
> The purpose of is the EU single market

That's also a misconception. The EU single market is an important project, but there is a constant failure to understand the actual reason why the EU exists or also a purposeful misinterpretation. Countries joining the EU are requested not to join because of the single market, but because they want to join the political project of a more peaceful and an improving Europe.

At its core the EU is a project to bring Europe together, to cooperate instead of being in wars (... WW1, WW2, Cold War, ...).

The EU is even more a political project as it is an economic project. But there are many other projects. The market is not the EU, it's a large and important project, the EU can't be thought without it. But there is more. The main motive behind all that is the will to work together. Even the "single market" is at its core a political project.

We have seen it with Brexit. The UK never bought into the "political project". UK politicians also mislead the public about that. The EU is as much about social standards, political standards, environment, competition, building up the countries, joint research, joint infrastructure, a common law, common currency, being competitive in a larger world, ... and so on. During Brexit it was promised by some UK politicians for a short time that the UK would leave the EU, but not the single market. Misleading the public that this was a topic of economics, while the EU really is a political integration project, not just a project to build a single market.

France and Germany at war for many centuries, now have a common integration project (in a larger EU), free movement, no physical border, an EU passport, a single currency, joint projects, ... these are the things which moved us forward.

lispm··on Common Data Structures in Common Lisp
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.

lispm··on The evolution of a Scheme programmer (2020)
Too much visual clutter with very little actual benefit. I found that I don't need/want to find matching parentheses by a mix of position AND color.
lispm··on The evolution of a Scheme programmer (2020)
In Zmacs on the Lisp Machine, the s-expression under the mouse cursor gets an outline. This is updated while the mouse is moving.
lispm··on The evolution of a Scheme programmer (2020)
We might add an evolution of the display of parentheses...

B&W ()

B&W and optional bold ()

B&W and optional bold/larger ()

Full color rainbow parentheses.

B&W ()

One or two of the Lisp editors I use also support rainbow parentheses, but after an initial phase of experimentation, I have disabled that feature.

lispm··on Štar: an iteration construct for Common Lisp
For a Lisp user the s-expression variant would be more useful, because it is easier to write and read. It also helps that it is easier to indent / pretty print, because the usual pretty printer algorithms can be used. For LOOP one would need an indent / pretty printer with either some heuristics and/or knowledge of LOOP grammar.

Personally I use LOOP because it is built in. But generally I prefer something like ITERATE, which is similar powerful but fits better into the host language (-> Common Lisp).

lispm··on Štar: an iteration construct for Common Lisp
> I'd say that lem is an emacs. Emacs is a genus, not a species.

The question is what makes this species.

For example see https://www.finseth.com/craft/#c10.1

It's the command set (key bindings, extended commands, ...), buffers with modes and minor modes, the user interface for buffers, marks, the "cursor", extensibility, ...

For example in a typical Emacs the "cursor" / current mark is always visible, even in GUI versions. This is very different from other editors, where the current cursor can be non visible.

Basically there are a lot of similarities between the early Emacs editors (EMACS, EINE/ZWEI/ZMACS, Multics Emacs, ... and others).

Does LEM try to be similar to an EMACS editor or is it only emulating one on demand?

GNU Emacs use might also think of Emacs Lisp as an extension language, a GUI version, menubars with menus, self-documentation, ...

lispm··on Fast linked lists
As source code, but not necessarily as running code.

SBCL:

    * (defun hello-world () (write-string "hello world"))
    HELLO-WORLD

    * (disassemble #'hello-world)
    ; disassembly for HELLO-WORLD
    ; Size: 36 bytes. Origin: #x100311C85C                        ; HELLO-WORLD
    ; 5C:       AA0A40F9         LDR R0, [THREAD, #16]            ; binding-stack-pointer
    ; 60:       4A0B00F9         STR R0, [CFP, #16]
    ; 64:       EAFDFF58         LDR R0, #x100311C820             ; "hello world"
    ; 68:       570080D2         MOVZ NARGS, #2
    ; 6C:       29EC80D2         MOVZ TMP, #1889
    ; 70:       BE6B69F8         LDR LR, [NULL, TMP]              ; WRITE-STRING
    ; 74:       DE130091         ADD LR, LR, #4
    ; 78:       C0031FD6         BR LR
    ; 7C:       E00120D4         BRK #15                          ; Invalid argument count trap
The actual code for this example is machine code (which references a string, which is a vector), here without linked lists.
lispm··on Homoiconic Python
> In most other language you can't even write syntactical extensions.

C? C++? Rust? Erlang? Scala? Julia? R?

> Such things are, generally, horrendous for readability. Like I said you can wield them effectively. But the average developer won't be able to.

Macros actually are widely used to improve readability. In Lisp that's one of its main purposes. It leads to more compact, declarative, domain specific code. Large programs usually benefit the most. Programs can be much short and more readable.

Take for example in Common Lisp the Common Lisp Object System. It has three layers: an object-layer at the bottom, then a functional layer and on the top is the macro layer. The macro layer is what the typical developer uses, which is compact and which shields the developer from the details of the lower layers. The Common Lisp Object System blends seamlessly into the rest of the language and the usual basics can be easily learned.

lispm··on Homoiconic Python
If there is an exception a matching error handler will be selected and called in the context of the error. A default handler could be a debugger, a break loop (which is a Lisp REPL), something which asks the user waht to do or it could be a handler provided by the software, which could do anything, including looking for restarts and using one.

For example the variable a is unbound and we try to add 3.

    CL-USER 37 > (+ 3 a)
CL shows an UNBOUND-VARIABLE error and provides Restarts. Restart 3 is a USE-VALUE restart.

    Error: The variable A is unbound.
      1 (continue) Try evaluating A again.
      2 Return the value of :A instead.
      3 Specify a value to use this time instead of evaluating A.
      4 Specify a value to set A to.
      5 (abort) Return to top loop level 0.

    Type :b for backtrace or :c <option number> to proceed.
    Type :bug-form "<subject>" for a bug report template or :? for other options.
We are now in a break loop, a REPL one level deeper, in the context of the error. Let's see what the condition (-> exception) is:

    CL-USER 38 : 1 > :cc
    #<UNBOUND-VARIABLE 8010002EC3>
we call one restart (listed above, number 3) interactively, it uses the new value and continues to compute the expression. It asks for a value. I enter 5 -> 5 + 3 = 8

    CL-USER 39 : 1 > :c 3

    Enter a form to be evaluated: 5
    8
We can do it also programmatically. HANDLER-BIND establishes a handler for UNBOUND-VARIABLE. It invokes the restart USE-VALUE with 4 -> 3 + 4 = 7

    CL-USER 40 > (handler-bind ((unbound-variable #'(lambda (c)
                                                      (invoke-restart 'use-value 4))))
                   (+ 3 a))
    7
All this is the default behavior. There is no special "debug mode", attaching a debugger or "instrumentation of code" needed.
lispm··on The Emacs Window Management Almanac
DWIM in Interlisp was an automated error handler for Lisp code. It would be triggered on errors and then tried to guess possible fixes at runtime (misspelled functions&variables could be corrected, ...).

Though one might expect a bigger picture: "interacting with an agent who attempts to interpret the user's request from contextual information" (Teitelman/Masinter, The Interlisp Programming Environment, 1981).

lispm··on Algebraic Data Types for C99
> You misquoted me. I said no philosophy, singular. In the programming language context, a philosophy is a convention or a standard. Just as many standards implies that there is no standard, many philosophies implies no philosophy.

That makes no sense.

> Hire 3 different programmers, one from each of the communities, and you might as well have 3 different programming languages.

Maybe not. They build on the same foundation, a language with a large standard, which is largely unchanged since three decades. A language which can be incrementally extended, without invalidating the rest. A language where extensions can be embedded, without invalidating the rest of the language or its tools. Many projects use SBCL (now itself 25 years old and only incrementally grown) and a bunch of core libraries for it.

> That’s not a standard. That’s not a philosophy. That’s anything goes!

Most languages support widely different software development practices. Take JavaScript: it includes imperative, object-oriented and functional elements (similar to Lisp). It has huge amounts of competing frameworks (many more than any Lisp), where many of them have been superseded and many of them are built on a multitude of other libraries. The developer can pick and choose. Each projects will be different from other projects, depending on which libraries and programming frameworks it uses - and which of those the developer re-invents.

Any half-way powerful language (C++ -> templates, Ruby -> meta objects, Java -> objects & byte code & reflection & class loader, Smalltalk -> meta objects, Rust -> macros, C++ -> language interpreters, Java -> external configuration languages, C -> macro processor, ...) has ways to adapt the language to a certain style & domain.

Any large Java framework defines new standards, new configuration mechanisms, new ways to use new Java features (lambdas, streams, ...). See the large list of features added to the Java language over time: https://en.wikipedia.org/wiki/Java_version_history For many of them there were competing proposals. Each Java code base will use some subset/superset of these features, depending on what is needed and what the personal preferences are. And then the Java architect in the project will not be satisfied and will invent yet another configuration system, this time not using XML or JSON for the syntax, but develop a new embedded scripting language for the JVM and integrate that with his software. I have seen Java architects which eventually didn't understand their own configuration system any more.

If you think a language like Common Lisp is special here, then in reality it is not. It's just slightly different in that it has extensibility as one of its philosophies and provides defined interfaces for that. There is one macro mechanism, which is powerful enough, that for decades it has not been replaced. Every syntactic extension mechanism will use this macro system, which is documented, stable and widely used.

lispm··on Algebraic Data Types for C99
> "anything goes" languages such as LISP have struggled to gain widespread adoption: with no philosophy every programmer becomes an island unto themselves.

There are already two misconceptions.

First: "Lisp has no programming philosophies" and styles.

Not every program starts by zero. Since Lisp exists since the end 1950s, it has seen quite a lot in programming styles over the years and it may contain traces of several. Generally it may support more than one programming paradigm. For example during the Common Lisp standardization there was a wish to have a standardized object system. So instead of the multiple possible approaches (actors, message passing, prototype-based, ...), Common Lisp has just one: CLOS, the Common Lisp Object System. So, much of the object-oriented code written in CL is implemented in one particular object system: CLOS. Object Lisp, Flavors, LOOPs, Common Objects, and a bunch of other once had thus been replaced by one standard.

CLOS also defines a bunch of user-level macros: DEFCLASS, DEFMETHOD, DEFGENERIC, ... Everyone using CL & CLOS will use those macros.

Second: "every programmer becomes an island unto themselves". If we look at the way CLOS was designed: there was a core group of six people from three companies. Around that there was a mailing-list based communication with a large group of interested people. Early on a prototype was implemented as a portable implementation of CLOS. This was widely distributed among interested parties: implementors, companies, research groups, ... Then reports about the language extension and its layers were published, books were published, application & library code was published.

One of famous books coming out of this effort: "The Art of the Meta-Object Protocol". It contained also a toy implementation of CLOS in Common Lisp. Book and the implementation of CLOS (both the larger prototype and the toy implementation) showed in excellent quality how to write object-oriented Lisp code.

https://mitpress.mit.edu/9780262610742/the-art-of-the-metaob...

So, there are communities, which share code and coding styles. Not every programmer is alone and starts from zero.

lispm··on Ointers: A library for representing pointers where bits have been stolen (2021)
The MIT has open sourced their Lisp Machine software.

https://tumbleweed.nu/lm-3/

lispm··on Ointers: A library for representing pointers where bits have been stolen (2021)
> Or they'd have turned Lisp machines from hardware into a "Lisp machine" OS or IDE/REPL/etc environment for other OSes succeeding.

That was a very different business model, very different offering into a different market. One could not move that business model easily, in an existing company to a different market. There were offices, factories, contracts, ... -> costs to get rid of. The thing collapsed, before anything usefully could be scaled down.

For example the Symbolics graphics products were very expensive, just the software. A new owner ported it to SGI and Windows NT machines. To be a technically viable product it used a commercial Lisp vendor. It survived a while in that market (modelling/animation/game tools for game studios, animation studios, ...), changed owners again and then died.

Lisp (the forbidden word during/after the AI Winter) was a part of the problem, but generally a new business model and customers for it wasn't found/searched. For example TI just closed its AI business and never cared about it from then on.

Something like Genera was a huge pile of Lisp code written during 1.5 decades. During its best times the OS and maintenance upgrades were already more expensive than a PC.

Applications from the Lisp Machine were ported away. One no longer needed the OS and no longer had the OS. Some applications died, some survived, some died later.

Some applications (or the development environment) survived for some years on emulators (-> Interlisp-D was ported to SUNs and PCs, Genera was ported to DEC Alpha).

lispm··on Ointers: A library for representing pointers where bits have been stolen (2021)
No, the reason for less than stellar performance of Lisp on the 32bit x86 CPUs were things like too few registers.

On 64bit Intel CPUs this is much less of a problem and Lisp runs roughly twice as fast in 64bit mode. I would think that this even holds without taking advantage of wider data words.

On other architectures this was less of a problem. 32bit CPUs had more registers on a RISC or some other CISC CPUs.

lispm··on Ointers: A library for representing pointers where bits have been stolen (2021)
Symbolics had its own PC implementation of Lisp: CLOE.

From the Lisp FAQ: "CLOE (Common Lisp Operating Environment) is a cross-development environment for IBM PCs (MSDOS) and Symbolics Genera. It includes CLOS, condition error system, generational garbage collection, incremental compilation, code time/space profiling, and a stack-frame debugger. It costs from $625 to $4000 and requires 4-8mn RAM and a 386 processor. "

Later they also ported Genera to DEC Alpha. Currently I have access to an implementation which runs on ARM64 and Intel x64.

lispm··on New iPad Pro with M4 chip and Apple Pencil Pro
True, the thing is from 2014.
lispm··on Superfest – The almost unbreakable East German Glass (2021)
Thanks for the comment!

Wikipedia describes that here (in German): https://de.wikipedia.org/wiki/SERO

lispm··on Superfest – The almost unbreakable East German Glass (2021)
Another company (Revisalt, an university spinoff in Freiberg/Germany) claims that time and cost for producing such chemical strengthened glass has been much improved:

https://www.cfh.de/en/neues-investment-revisalt-gmbh/

https://revisalt.com/en/

lispm··on Superfest – The almost unbreakable East German Glass (2021)
There was a recent kickstarter project from a German company for Glass bottles based on this technology:

https://www.soulbottles.de/en/ultraglass

https://www.kickstarter.com/projects/paulkupfer/ultraglass-s...

Recent update:

https://www.kickstarter.com/projects/paulkupfer/ultraglass-s...

The research for this was done at the University of Bayreuth: https://www.glas.uni-bayreuth.de/en/projects/strongbottles/i...

German TV reported about the background here, 20:45 onwards:

https://www.3sat.de/wissen/nano/240315-sendung-epigenetik-ar...

lispm··on A portable Common Lisp toolkit for building inspectors
> It was also during a time where keyboard interaction was still the primary means of interface. Even with the creation of the Lisp machines and their large graphic displays, those displays were dominated by "terminal" windows.

In Symbolics Genera a Lisp Listener (the window which runs a combination of a REPL and a command line interpreter) is a full graphics window with the same drawing capabilities as PostScript. It's also a command interpreter taking Lisp objects as arguments to commands.

The UI isn't using much direct manipulation with the mouse (like dragging a file between folder windows), though for example in the graphics editor one can do that for graphics objects. One also interacts with graphical scrollbars. Much of the UI is based on displaying textual and/or graphical objects AND running commands on them. Application windows all have a (often visible) command interpreter, where interacting with objects is done via commands on objects (and not only on text), using textual commands, mouse gestures or command menus.

The Listener (as do other applications) also records all output and keeps the relationship with the objects which a drawn/printed.

Thus the Genera UI does not use "toString", but calls PRESENT (or similar), a function which outputs Lisp objects in various ways, records the output (text and graphics) and keeps the relationship between object and output. Thus the Listener is not only a graphical stream, but also a graphical object store (-> it stores all output using a complex object-oriented framework). (similar -> McCLIM -> https://mcclim.common-lisp.dev -> example for tools/apps https://mcclim.common-lisp.dev/excite.html ).

One can return/print a data structure in the Listener and then one can point with the mouse at sub-objects and run commands on them (like 'describe'). This makes a separate inspector mostly unnecessary, though there is a inspector window. As there is a debugger window with backtrace, code display, etc. There is also a PEEK window, which is used to inspect things in the OS: Windows, File Systems, Memory, Processes, Network, ...

lispm··on The world's loudest Lisp program to the rescue
Lisp was developed at a time when space was more limited. Generally operators had short names. Page 147 of the Lisp I manual from 1960 has a function listing: https://bitsavers.org/pdf/mit/rle_lisp/LISP_I_Programmers_Ma...

Generally in Common lisp we have EQ, EQL, EQUAL, EQUALP -> from the most specific to the most general. The most specific has the shortest name: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node74.html

EQL is actually often used, since it is also the default equality test in Common Lisp. For example the named TEST argument has the default EQL. That information is slightly hidden. Example: (find 1 '(2 3 2 1 3)) is the same as (find 1 '(2 3 2 1 3) :test 'eql) , since EQL is the default test. One can pass a different equality test predicate, if needed.

Some background about naming and equality operators in Lisp: http://www.nhplace.com/kent/PS/EQUAL.html

Other languages for example use some of =, ==, ===, is, ... what may the difference be?

There were many different naming conventions in Lisp over the decades. One was, as mentioned above, the more specific/primitive operators have shorter names. Later (70s/80s, Lisp got a lot more operators and at some point there were operators with long names introduced. This was not liked by everyone, since one needed to type longer names - completion was often new then (or slow).

For example CLOS was added end 80s. Thus it uses names like UPDATE-INSTANCE-FOR-DIFFERENT-CLASS, instead of UPDINSTC ;-) .

Generally, a good Lisp IDE should make getting the documentation (and source code) for any operator easy.

lispm··on The world's loudest Lisp program to the rescue
On thing to keep in mind when you see the language, which evolved of several decades: it has low-level (go to, ...), mid-level (macros, ...) and high-level (CLOS + MOP) elements in one language. A reason for that: the low-level parts are code generation building blocks for the higher level parts. Example: The SERIES library (a higher-level way to think about loops and sequences) uses macros (mid-level) to transform code into efficient loops (-> low-level): https://github.com/rtoy/cl-series

So one reason for all this functionality is: the language is its own compilation target. One is not supposed to write all the code, but we can write code which writes the lower-level code.

lispm··on The world's loudest Lisp program to the rescue
There are a bunch of things to learn from Lisp:

* list processing -> model data as lists and process those

* list processing applied to Lisp -> model programs as lists and process those -> EVAL and COMPILE

* EVAL, the interpreter as a Lisp program

* write programs to process programs -> code generators, macros, ...

* write programs in a more declarative way -> a code generator transforms the description into working code -> embedded domain specific language

* interactive software development -> bottom up programming, prototyping, interactive error handling, evolving programs, ...

and so on...

The pioneering things of Lisp from the end 50s / early 60s: list processing, automatic memory management (garbage collection), symbol expressions, programming with recursive procedures, higher order procedures, interactive development with a Read Eval Print Loop, the EVAL interpreter for Lisp in Lisp, the compiler for Lisp in Lisp, native code generation and code loading, saving/starting program state (the "image"), macros for code transformations, embedded languages, ...

That's was a lot of stuff, which has found its way into many languages and is now a part of what many people use. Example: Garbage Collection now is naturally a part of infrastructure, like .net or languages like Java and JavaScript. It had its roots in Lisp, because the need arose to process dynamic lists in complex programs, getting rid of the burden of manual memory management. Lisp got a mark & sweep garbage collector. That's why we say Lisp is not invented but discovered.

Similar the first Lisp source interpreter. John McCarthy came up with the idea of EVAL, but thought it only to be a mathematical idea. His team picked up the idea and implemented it. The result was the first Lisp source interpreter. Alan Kay said about this: "Yes, that was the big revelation to me when I was in graduate school—when I finally understood that the half page of code on the bottom of page 13 of the Lisp 1.5 manual was Lisp in itself. These were “Maxwell’s Equations of Software!. EVAL is the E in REPL.

Then Lisp had s-expressions (symbol expressions -> nested lists of "atoms"), which could be read (R) and printed.

This is the "REP" part of the REPL. Looping it was easy, then.

People then hooked up Lisp to early terminals. In 1963 an 17 year old kid ( https://de.wikipedia.org/wiki/L_Peter_Deutsch ) wrote a Lisp interpreter and attached it to a terminal: the interactive REPL.

A really good, but large, book to teach the larger picture of Lisp programming is PAIP, Paradigms of Artificial Intelligence Programming, Case Studies in Common Lisp by Peter Norvig ( -> https://github.com/norvig/paip-lisp ).

A beginner/mid-level book, for people with some programming experience, on the practical side is: PCL, Practical Common Lisp by Peter Seibel ( -> https://gigamonkeys.com/book/ )

Both are available online at no cost.

← PreviousPage 13 of 34Next →