HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
quil-lang
cmu-infix
Common Lisp2017–2025
quil-lang / cmu-infix

cmu-infix

Updated infix.cl of the CMU AI repository, originally written by Mark Kantrowitz

4Distinct people
16Mentions
0Explicit recommenders
39GitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Updated infix.cl of the CMU AI repository, originally written by Mark Kantrowitz

GitHub

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 5:04:57 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year16 dated mentions

Observed mentions: 2017-05-02 19:01:22 UTC to 2025-02-26 11:43:03 UTC.

0123452017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 5 mentions; 0 submissions, 5 comments20172018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20212022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 5 mentions; 0 submissions, 5 comments2023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC505
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC000
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC202
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC000
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC202
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC505
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC000
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC101
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC101

What Hacker News says

16 sources
A late reply but it's worth addressing one way of doing this. First, your concern about object not being a valid function or macro isn't relevant at read time. Second, note that Lisp already has similar syntax: '(1 . 2) is essentially (cons 1 2). Implementing this type of syntax is not a privilege of the implementation alone. You're allowed to redefine your own reader for left paren. In SBCL: CL-USER> (get-macro-character #\() SB-IMPL::READ-LIST You can write `(set-macro-character #\( 'sb-impl::read-list)` and everything continues to work just fine. You can also jump-to-source and modify it if you want -- though it's cleaner to just copy it out to your own project, that's what I did for a quick hack/proof of concept. Essentially I added before the existing (when...) which handles the special dot syntax: (when (and (eq first
Read the rest
char #\-) (eq (peek-char t stream t nil t) #\>)) (read-char stream t) ; actually read the nextchar > to discard it (let ((next-obj (read stream))) (sb-impl::flush-whitespace stream rt) (return `(slot-value ,@listtail ',next-obj)))) I won't claim this is good or proper, but it shows that it's quite feasible. We've turned (foo -> bar) into (slot-value foo 'bar). CL-USER> (defclass vec2 () ((x :initarg :x) (y :initarg :y))) #<STANDARD-CLASS COMMON-LISP-USER::VEC2> CL-USER> (defparameter vec (make-instance 'vec2 :x 3 :y 4)) VEC CL-USER> (vec -> y) 4 CL-USER> (read-from-string "(print (vec -> x))") (PRINT (SLOT-VALUE VEC 'X)) 18 Personally I wouldn't use this even if it was more properly/carefully implemented. (There's really no reason to replace the default left-paren reader, and no reason we have to have a space surrounding the "->". One thing I like about the infix reader macro package https://github.com/quil-lang/cmu-infix is that it doesn't care about spaces, I can write #I(1+1 + 4) and get 6.) I'm quite happy putting my class in its own package, and thus getting the primary tab-completion behavior I care about. e.g. "(ma:<tab>" could complete to "(math:" and then "(math:v<tab>" could complete to a list of options like "vector-x" "vector-y" or so on. I also like the somewhat unusual approach of naming my accessors with a dot prefix, e.g. (.x vec) and (.y vec), or even (math:.x vec) if I haven't imported the symbol.
In These years in Common Lisp: 2023-2024 in review
Yup, but when you have to integrate with things you can't control, the advantages are fewer, especially compared to something purpose-built for that thing and the trade-offs can easily turn away from Lisp. e.g. you're going to have a much easier time making a game in plain Godot than you would trying to mix CL with Godot's native API, or if you're crazy doing an entire 3D engine + game in CL. Even in that last approach, integrating with the graphics stack on modern systems is going to be nuts. Going further into OS-facing stuff like sound, rendering text, handling multiple languages, handling inputs from mice/keyboards/controllers, dealing with multiple monitors, microphones... it's a good thing Common Lisp has a decent FFI (it's even possible, though more difficult, to integrate with pure C++ stuff using SBCL and not having to switch to
Read the rest
Clasp, but it's nice that Clasp exists in the same way it's nice ABCL exists to more easily integrate with Java stuff) because you will be using native libraries for some things, and it will suck to some degree because those are written in the world and mindset of dead, static programs. But the pure Lisp side will be great, and you'd be using those libraries or something like them anyway if you switched Lisp out. An underrated Hickey talk is his Effective Programs one: https://github.com/matthiasn/talk-transcripts/blob/master/Hi... It's another entry in my personal (and useless time-wasting) fascination with wondering what could have been if CL won in the 90s. No need for Java to come around and "get C++ programmers half-way to CL", with excruciatingly slow followups year after year that finally by Java 8 and after got us something (when also using additional things like a giant IDE with good refactoring tools and simple code generation (no manually writing getters/setters or managing a giant list of imports), Spring, JRebel, and sometimes AOP frameworks) actually not too unpleasing compared to a CL experience. But most things were always there in the CL experience in the 90s, especially if you could shell out for the commercial systems, it really is just Java playing catch-up. And then you get in that talk and elsewhere a story about how non-technical decision making didn't even give Lisp systems a chance in production, so as a last resort Lisp was put on top of the JVM which was accepted. Clojure is a great achievement, and ABCL came too late, but it's kind of a shame either has to exist. Still, the thousands upon thousands of man-years have been spent, and because of that Lisp's advantages are fewer. However the Lisp world itself hasn't been static since the 90s either, and so the counter-advantages of vastly larger ecosystems have grown fewer as well. For example, it took until as late as 2010, but finally quicklisp was made and the problem of libraries and finding/getting them was dramatically lessened. For comparison, Perl's CPAN is from the 90s, Python's PyPI is from 2003, Maven 2004... Lisp was late. But the last 10 years of Lisp seem to be going a lot better than the 10 before, and while there are still problems, they don't really look like uniquely Lisp problems, and supposedly unique ones like supposedly not being able to do infix arithmetic are addressed with slow education to the contrary (while I'm here might as well link for the nth time, the solution available since 1993: https://github.com/quil-lang/cmu-infix). It was such education years ago from a HN comment that made me give CL another look and then never look back at Clojure/Scheme/etc. (though Java is still my preferred breadwinner should I find myself suddenly needing more income). (The comment was simple, just showcasing that yes in fact CL has typing support, the compiler is available at runtime, and with SBCL the compiler can report not just about wrong types / typos but dead code elimination and failures to apply optimizations. Cool stuff. Made me realize I never knew CL at all. Even CLOS, the OOP system, had some pleasant surprises when I finally got around to learning it and seeing it's far more than what other langs offer.) Meanwhile the advantages are still there.
In Ask HN: 30y After 'On Lisp', PAIP etc., Is Lisp Still "Beating the Averages"?
And if you're really desperate to write infix notation in Lisp, you can use CMU-INFIX [1]: #I( (-b + sqrt(b^^2 - 4*a*c))/(2*a) ) That is completely valid Lisp if you need it. In fact, you can change your editor to highlight #I(...) if you want it to stick out a little more since it's "different" than usual prefix notation. Suffice it to say, a binary expression like (+ b (* m x)) probably doesn't warrant bringing in a library, but if you're calculating orbital dynamics of the solar system, then perhaps having the above library would be useful. [1] https://github.com/quil-lang/cmu-infix
In From Common Lisp to Julia
> my little brain doesn't think far enough ahead to naturally use prefix math Nor mine, it's the only Lisp-ism I choose not to try and integrate apart from trivial expressions. (I do rather like not having to type extra +s when I'm adding multiple things together.) Similarly I disliked my dad's postfix HP calculator apart from trivial things. But this is Lisp, and my worries were solved when I was still just a toddler: https://github.com/quil-lang/cmu-infix Being in my .sbclrc file I can always use infix math whenever I need, and it's trivial to add it as a dependency to an asdf system.
In New blog about my journey to develop a Common Lisp 3D software
To be fair, other non-Lisp languages have come a long way. Still, I'll offer a few things that might pique your interest. For a while in the development of Common Lisp, a sort of joke acceptance test for implementations was in three parts: 1) you type T and enter into the REPL, it responds T 2) you define the factorial function and calculate (/ (factorial 1000) (factorial 999)) and it responds 1000 3) You try (atanh -2) and if it returns a complex number it passes (extra credit for the correct complex number). Lisp has a great numerical tower. Besides being able to deal with huge and complex numbers, you also have convenient syntax for specifying numbers in base 2 and 16, and you can do things like bitwise operations on bit-vectors: (bit-and #*00110100 #*10101010) -------> #*00100000 For macros, there's a lot of cool
Read the rest
ones. Unlike C macros that just do string substitution, Lisp macros let you use the full Lisp language to write code that does something with expressions passed to the macro. A nifty one that's part of basically every implementation with uiop:nest is described here https://fare.livejournal.com/189741.html The problem it solves is that sometimes in Lisp you'll have a lot of nested forms, and your code begins to attack the bottom right corner of your screen. e.g. (multiple-value-bind (a1 b1 p1) (foo1) (with-open-file (f1 p1 ...) (let ((x1 (read f1))) (when x1 (multiple-value-bind (a2 b2 p2) (foo2) ... The macro lets you rewrite that as (nest (multiple-value-bind (a1 b1 p1) (foo1)) (with-open-file (f1 p1 ...)) (let ((x1 (read f1)))) (when x1) (multiple-value-bind (a2 b2 p2) (foo2)) ... The macro definition is really straightforward: (defmacro nest (&rest r) (reduce (lambda (o i) `(,@o ,i)) r :from-end t)) (The list of forms are passed, unevaluated and at compile time, to nest, which rewrites them using a right fold to nest things properly.) Somewhat similar is the arrow macro that Clojure popularized, which lets you get rid of (deep (nesting (like (this ...)))) where you have to remember evaluation order is inside-out and replace it with a flatter (-> (this ...) like nesting deep). Or (loop (print (eval (read)))) -- which will indeed give you a primitive REPL within Lisp -- with the more readable (-> read eval print loop). Its implementation is also easy -- many macros are easy to write because Lisp's source code is itself a list data structure for which you can write code to process and manipulate just like any other lists. Another cool macro that's been around since 1993 is https://github.com/quil-lang/cmu-infix which lets you write math in infix style, e.g. #I( C[i, k] += A[i, j] * B[j, k] ) where A, B, and C are all matrices represented as 2D arrays. It's a lot more complicated than the nest macro, though. There are some other things that still make Lisp great in comparison to other languages, but they don't exactly have one-line code examples like [::-1] and so I'll just describe them qualitatively. Common Lisp has CLOS, the first standardized OOP system. It's a lot more powerful than C++'s system. It differs from many systems in that classes and methods are separate; among other things this gives you multiple dispatch (you can define polymorphic methods that don't just dispatch to different code depending on the first argument (the explicit 'self' in Python, implicit 'this' in other langs) but all arguments). One thing it can be useful for is to get rid of many laborious uses of the Builder and Visitor patterns. e.g. the need for double dispatch is a common reason to use the Visitor pattern, but in Lisp there's no need. CLOS also does "method combination", which lets you define :before, :after, and :around methods that operate implicitly before/after/around a call. This gets rid of the Observer pattern, supports design-by-contract, and jives well with multiple inheritance in that you can create "mixins" that classes can "inherit" from with the only behavior being some :before/:after methods. (e.g. logging, or cleaning up resources, or validation.) Everything is truly dynamic -- an object can even change its type at runtime, which may be an acceptable solution to the circle-ellipse problem, or just super convenient while developing. More fundamentally, "compile" is a built-in function, not something you have to do with a separate program. "Disassemble" is built-in, too, so you can see what the compiler is doing and how optimized something is. You have full flexibility to define and redefine how your program works as it's running, no need to restart and lose state if you don't want to. Besides being killer for development (and all the differences in development experience comprise a big part of why I still think Lisp is great compared to non-Lisp), this gives you a powerful way to do production debugging and hot-fixing too -- a footgun you might not necessarily want most of the time, but you don't have to do anything special for it when you do want it. It can be very useful, e.g. if you've got a spacecraft 100 million miles from Earth https://flownet.com/gat/jpl-lisp.html I've also put some hobby stuff on a server, just deployed as a single binary, but built so that if I want to change it, I can either stop it, replace the binary, and start again, or just SSH in and with SSH forwarding connect to the live program with my editor and load the new code changes just like I would when developing locally, and thus have zero downtime. Lastly, Lisp's solution to error handling goes beyond traditional exception handling. Again this ties into the development experience -- you have some compile-time warnings depending on the implementation (e.g. typos, undefined functions, bad types) but you'll hit runtime errors eventually, Lisp provides the condition system to help deal with them. It can be used for signaling non-errors, which has its uses, but what you'll see first are probably unhandled errors. By default one will drop you into a debugger where the error occurred, the stack isn't immediately unwound. Here you can do whatever -- inspect/change variables on different stack frame levels, recompile code if there's a way to fix things, restart computation at a specific frame... You'll also be given the option of "restarts", which might include just an "abort" that unwinds to the top level (possibly ending a thread) but can include custom actions as well that could resolve the error in different ways. For example, if you're parsing a CSV file and hit a value that is wrong somehow (empty, bad type, illegal value, bad word, whatever), your restarts might be to provide your own value or some default value (which will be used, and the computation resumes to parse the next value in the row), or skip the whole row (moving on to the next one), or skip the whole file (moving on to the next file, or finishing). Again this can be very useful while debugging, but in production you can either program in default resolutions (and a catch-all handler that logs unhandled errors, as usual) or give the choice to the user (in a friendlier way than exposing the debugger if you please).
In Why Lisp? (2015)
You don't have to give up on anything, that's the beauty of Lisp. Here's a library from 1993: https://github.com/quil-lang/cmu-infix Though personally I don't particularly find (+ 1 2 3 4 5) less readable than 1+2+3+4+5, and since most of my programs don't have math expressions much more complicated than that, even without cmu-infix or alternatives (Maxima is great when you need to do real math, and for other related things I might as well link https://github.com/CodyReichert/awesome-cl#numerical-and-sci...) I'd find the rest of the tradeoffs worth it, much like once I thought despite Python not having i++ or ++i it was still worthwhile. (In Lisp, by the way, one would use (incf i).)
In An Intuition for Lisp Syntax
> Lisp has minimal syntax It hasn't. It just works differently. S-expressions define syntax for data: lists, strings, numbers, symbols, vectors, arrays, ... Plus a bunch of abbreviations (quote, function quote, ...) and some extras (templates, reader control, ...). One can program that part with reader macros. Then Lisp usually has around three (or more) syntax classes for prefix forms: 1) function calls 2) special forms like LET, ... 3) macros like DEFUN, DEFCLASS, WITH-SLOTS, ... Special operators and macro operators introduce syntax. See the Scheme manuals or the Common Lisp spec for the EBNF definitions of these syntax operators. This can be simple or relatively complex (LOOP macro would be an example, but also something like DEFSTRUCT, ...). The user can write macros to extend the syntax. Now if we want infix/mixfix arithmetic, we ca
Read the rest
n embed it via the reader #i( fib(n - 1) + fib(n - 2) ) or as a macro: (infix fib (n - 1) + fib (n - 2)) Problem: it's not built-in and not that common. > I’m adding numbers... Now one would have a bunch of options: 1) live with the Lisp syntax as it is, improve it where possible 2) use syntax extensions for mathematical code, may have tooling drawbacks 3) use a different surface syntax for Lisp or a specialized syntax (see Macsyma and similar) 4) use a different language with the usual mix of prefix, infix and postfix operators Libs: https://github.com/ruricolist/infix-math https://www.cliki.net/infix https://github.com/peey/ugly-tiny-infix-macro https://github.com/rigetti/cmu-infix http://readable.sourceforge.net
In Hy
Lisp has several time phases that may or may not interleave, so yeah it can be confusing.. but keeping things simple and mostly only thinking about macros at compile time or read time can still go a long way. Ultimately an important and practical high level effect is macros let you create new syntax, not just computation at compile time to save some function calls at runtime. Want infix math? You can have infix math: https://github.com/rigetticomputing/cmu-infix Going crazy with lexical nesting (similar to callback hell, but imagine each callback needs to close over the environment it's called from, not just defined in)? A one-liner might help: https://fare.livejournal.com/189741.html Want powerful looping constructs, powerful OOP, pattern matching, etc? Of course you can stick with simple macros that are little more than function wrapper
Read the rest
s, but you can do a lot more.
In Lisp at the Frontier of Computation [video]
Lacking infix syntax out of the box is a problem, though not hard to add as a sibling mentioned; for those curious I like linking to this gem dating back to '93 since it's part of quicklisp now https://github.com/rigetticomputing/cmu-infix The rest of the syntax being somewhat alien-ish is also a problem, but it goes away with practice. (https://www.thejach.com/imgs/lisp_parens.png) But I don't think syntax alone is enough to explain Lisp's apparent languishing (though only apparent since it seems to be on the rise again), because we have Clojure. Clojure has the same syntax issues as Lisp (ok a bit fewer because of no reader macros and there's an argument that bracket variety is more pleasant to read) yet it's very popular all things considered. And because Clojure has a BDFL, if lacking infix OOTB was really an issue (I don't think it's
Read the rest
come up in any of the annual surveys), RH could just include one of the libraries for it out of the box. SBCL could do that for Lisp, but it would be non-standard. To me there are several stronger drivers for language adoption than anything the language itself offers. Here are three: having a BDFL (Python, Perl, PHP, Clojure... not Lisp), having big corporate backing (Swift, Objective C, C#, Go, arguably Java but driven by more than 1 megacorp... not Lisp), being the lingua franca of a very widespread platform (Javascript (web), PHP (shared web hosts), Bash, C/C++ (unix, windows), Java (android)... not Lisp, maybe if the Lisp Machine had won but it didn't).
In Lisp Machine Manual (1984)

Showing the 15 most recent of 16 sources. Enable JavaScript to search and browse every indexed mention.

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.