
You already use Lisp syntax - nathell
http://blog.danieljanus.pl/blog/2014/05/20/you-already-use-lisp-syntax/
======
captainmuon
Sure, you can write bash like that. Actually, if you shift the parenthesis a
bit, you can write almost any language like that:

    
    
        (add 4 (mul 2 5))  vs.
        add(4, mul(2, 5))
    

But that doesn't mean you should write bash like that. In fact, it is (IMO)
very bad style to nest $(). When people complain about Lisp syntax, it's only
partially about the RPN or the parens, its about the incredible amount of
nesting.

Funnily enough, of all things bash offers an alternative paradigm. Instead of
nesting, you use filters:

    
    
        # pseudocode
        echo 2 | mul 5 | add 4
    

For example, you can write:

    
    
        nerrors=$(mycommand | grep error | sort | uniq | wc -l)
    

instead of:

    
    
        # pseudocode
        nerrors=wc("-l", uniq(sort(grep("error", mycommand))))
    

I find this paradigm of "do A, then do B, then do C" much easier to think
about than the nested "do C on the result of doing B on A". I wish more
programming languages would embrace that kind of coding, which is basically
functional, but in imperative or data-flow order. You have aspects of that in
C# (LINQ), SQL, and some others. I know you can achive something like that in
Haskell though Monads and `do`, though it feels a bit bolted on as a
concession to having to do imperative stuff in a purely functional language.
(And as nice Haskell is, it will probably never have the use base that bash
has...)

~~~
jerf
"I know you can achive something like that in Haskell though Monads and `do`"

The closer equivalent to UNIX pipelining in Haskell is actually the simple "."
operator, function composition. That pipeline would generally look more like

    
    
        countLines = wc LineCount
    
        countLines . uniq . sort . grep "error" $ mycommand
    

It's not a direct translation, because that is exactly neither legal Haskell
(I'm munging program vs. some sort of shell here), nor exactly how you'd
really do that in Haskell, however, pipelines of several functions composed
together is idiomatic and frequently-used.

"though it feels a bit bolted on as a concession to having to do imperative
stuff in a purely functional language"

It really isn't. IO is only one particular monadic thing; check out Parsec for
some more fun. It only looks bolted on if you look very superficially, and you
darned near have to bring the preconception in the first place to even briefly
come to that conclusion. That idea basically comes from the misconception that
"Haskell can't do side effects", then "Oh, well, this way of doing side
effects must be a bad idea or something"... the first statement is false.
Honestly, I _miss_ the way Haskell does IO in other languages far more than I
miss the way other languages do IO in Haskell. (To be clear, I do have both
feelings, but the former is way more common.)

~~~
thinkpad20
For what it's worth, I often do something like this:

    
    
        (!) = flip ($)
    

Which then allows me to do things like

    
    
        mycommand ! grep "error" ! sort ! uniq ! wc lineCount
        

Which is nice because it visually resembles `|` (which is a reserved symbol in
Haskell).

Similarly for fmap:

    
    
        (<!>) = flip (<$>)
        result <- get <!> table <!> lookup "foo"
        print result ! liftIO
    

Or for function composition:

    
    
        (~>) = flip (.)
        doStuff = reverse ~> head ~> negate ~> print
        doStuff [1,2,3]
    

That being said, lisp does seem far more suited to shell programming than
Haskell, because every function is variadic. What would probably be nice (and
probably has been done) is a Lisp with syntax extended to include a few
symbols to allow bash commands like |, >, etc:

    
    
        $ def nth-line (n) (read a | head -(n) | tail -n 1)
        $ ssh -i .ssh/some.pem (python show_servers.py | grep 'cool server' | cut -d ' ' 
          -f 3 | nth-line 1)

------
praptak
For me there were one and a half tricks to get Lisp syntax.

The first was the mental conversion to/from f(a,b,c) to (f a b c) which is
just moving the opening parenthesis one token to the left and seeing both
commas and whitespace as "something between the tokens that really matter".

The remaining half was starting with Clojure. It is a Lisp whose constructs
are really optimized towards dumping extraneous parentheses so it is easier
not to get lost in the nesting levels.

~~~
brudgers
To me, right now, I think the core difference between Clojure and other Lisps
is Clojure gets rid of memory management. Yes, other Lisps have automatic
deallocation, but the fundamental constructor, `cons`, is a raw memory
allocation. It`s `malloc`for linked rather than sequential memory.

Although Clojure still has a `cons` it has been replaced by `seq` as the
fundamental abstraction. Clojure takes advantage of being fully managed code
and in a sense is as much a Lisp as C# is a C [if we were inclined to think of
C as a genre, else Algol?].

It seems this, combined with a formally incorporating a DSL of the kind a
experienced Lisper (such as Hickey) might create for writing programs gives
Clojure it's syntax: e.g. [x y] is syntactically like a quoted list and
writing a macro is the sort of thing hubris drives lazy impatient Lispers to
do. In special forms [x y] is like a different more complex macro, but again
the sort of thing people would write for themselves. In other Lisps the ad hoc
nature of such macros however makes other people's code notoriously hard to
follow.

~~~
wes-exp
_`cons`, is a raw memory allocation. It`s `malloc`for linked rather than
sequential memory_

Yeah, cons is like malloc, except that the object it creates is automatically
memory managed / garbage collected. There is no corresponding "free" call.
Actually, that means cons is not like malloc.

 _Clojure takes advantage of being fully managed code_

Do you realize that Lisp uses automatic memory management (just like the JVM
or CLR)?

~~~
brudgers
Lisp's are high level languages. The JVM and CLR are virtual machines that
interpret and compile bytecode. Some Lisps utilize virtual machines, Clojure
being an example of one which does not use it's own, CMULisp and Racket are
examples of Lisps which use their own VM, and ClozureCL and SBCL are Lisps
which compile directly to native code. How Chicken Scheme fits into the whole
virtual machine model...well it's just too fine an ontological line for me to
call.

Why are there no Fortran machines or Algol Machines or C machines?

The `cons` cell is a raw memory structure, just one step removed from assembly
and originally accessed directly in machine code with `car` and `cdr`. It's
associated symbol is literally a pointer directly to a memory location. It's
so close to assembly language that thirty years ago implementing it directly
in hardware was considered practical.

~~~
wes-exp
_The `cons` cell is a raw memory structure_

 _It 's associated symbol is literally a pointer directly to a memory
location_

A cons is not "raw memory"; it is a typed data structure, and in Common Lisp
it is even considered an OOP object of the cons class. It is equivalent to
having a data structure called "pair" that can hold two things.

All memory-allocated data structures ultimately have an address of some kind,
so this whole discussion about pointers is utterly meaningless. For that
matter, arrays, strings, and basically every known memory data structure is
"raw" too. After all, they have an address.

The fact that cons/car/cdr can be implemented cheaply in hardware stems from
the fixed and small size of cons. That doesn't make it somehow inferior.

By the way, the Java stuff is implemented in hardware too, does that make Java
inferior?
[http://en.wikipedia.org/wiki/Java_processor](http://en.wikipedia.org/wiki/Java_processor)

------
arh68
Lisp... doesn't really have syntax. S-expressions have syntax: parens,
whitespace, symbols, comments. S-expressions are for data. Lisp is a subset of
the sexps.

Lisp adds just one rule: a Lisp program is an sexp whose root node is a
function symbol.

Naturally, since sexps nest, Lisp programs can nest.

The author demonstrates nested computation with bash's $( .. ) syntax. Lisp,
by the nature of the sexps, _is_ nested computations. I think the author
almost hits the nail on the head here:

> _Our two basic rules — program-name-first and $()-for-composition — allowed
> us to explicitly specify the order of evaluation, so there was no need to do
> any fancy parsing beyond what the shell already provides._

Sexps provide nesting/composition. Lisp just means _program-name-first_.

~~~
lispm
> Lisp adds just one rule: a Lisp program is an sexp whose root node is a
> function symbol.

Now you explain these three examples. All have a symbol at the start of the
list.

    
    
        * (let foo bar)
        ; in: LET FOO
        ;     (LET FOO
        ;       BAR)
        ; 
        ; caught ERROR:
        ;   Malformed LET bindings: FOO.
        ; 
        ; compilation unit finished
        ;   caught 1 ERROR condition
    
    
        * (lambda a b)
        ; in: LAMBDA A
        ;     (LAMBDA A B)
        ; 
        ; caught ERROR:
        ;   The lambda expression has a missing or non-list lambda list:
        ;     (LAMBDA A B)
    
    
        * (defun foo (a) (+ a 10) (declare (fixnum a))
        )
        ; in: DEFUN FOO
        ;     (DECLARE (FIXNUM A))
        ; 
        ; caught WARNING:
        ;   There is no function named DECLARE. References to DECLARE in some contexts
        ;   (like starts of blocks) have special meaning, but here it would have to be a
        ;   function, and that shouldn't be right.
    

Obviously the SYNTAX for LET, LAMBDA, DEFUN, ... is more complex than what you
think.

Looks like there is Lisp code where it is not sufficient to have a symbol at
the start of an s-expression. There seem to be more constraints to the allowed
s-expressions.

For example the syntax for LET is:

    
    
        let ({var | (var [init-form])}*) declaration* form*

~~~
arh68
Yeah you're right, it's _not_ turtles/functions all the way down. At some
point, your functions are defined in terms of special forms.

Your special forms will either be natively supported or they'll be written
with a defmacro in terms of native special forms. The definitions can't be
circular, of course: if defmacro was used to define _if_ , then _if_ cannot be
used in the definition of defmacro.

So my "rule" isn't really a hard rule. Macros/forms are the exception. But it
seems more intuitive for me to think in terms of functions whenever possible,
then to bend the rule when macros get involved.

~~~
lispm
No, Lisp has a set of built-in special forms with their specific syntax. In
many Lisps (incl. Common Lisp), there is no way to write new special forms for
the user.

Macros are not for implementing special forms.

> Macros/forms are the exception.

Common Lisp has around 30 special forms and many more macros. Some with a
special complex syntax, like LOOP.

Programming Lisp with only function call syntax is practically impossible.
LAMBDA, DEFUN, ... are already having additional syntax.

~~~
arh68
I'm being loose with my terminology. I guess that was a mistake. Look, I don't
even know what we're arguing over. Here's some words from CLtL2:

    
    
        5.1.3. Special Forms
    
        ...
    
        An implementation is free to implement as a macro any construct described
        herein as a special form. Conversely, an implementation is free to implement
        as a special form any construct described herein as a macro if an equivalent
        macro definition is also provided. The practical consequence is that the
        predicates macro-function and special-form-p may both be true of the same
        symbol. It is recommended that a program-analyzing program process a form
        that is a list whose car is a symbol as follows: 
    
        1)  If the program has particular knowledge about the symbol, process the
            form using special-purpose code. All of the symbols listed in table 5-1
            should fall into this category. 
    
        2)  Otherwise, if macro-function is true of the symbol, apply either
            macroexpand or macroexpand-1, as appropriate, to the entire form and
            then start over. 
    
        3)  Otherwise, assume it is a function call.

~~~
lispm
Okay, I'll explain that in detail:

> Yeah you're right, it's not turtles/functions all the way down. At some
> point, your functions are defined in terms of special forms.

Functions are defined in terms of special operators, built-in functions, user-
level functions, built-in macros, user-level macros and data.

> Your special forms will either be natively supported or they'll be written
> with a defmacro in terms of native special forms.

DEFMACRO can't define special operators. It can only define macros. Common
Lisp lacks the facility to define special operators.

> The definitions can't be circular, of course: if defmacro was used to define
> if,

IF is a built-in special operator. No macro.

> then if cannot be used in the definition of defmacro.

Generally it could. Macros can be recursive, for example.

> So my "rule" isn't really a hard rule. Macros/forms are the exception. But
> it seems more intuitive for me to think in terms of functions whenever
> possible, then to bend the rule when macros get involved.

Macros and special forms are everywhere in Lisp.

~~~
arh68
:D thank you for posting

You seem to have laid it all out exactly, your attention to detail exceeding
mine. What you've been saying is exactly how it works in Common Lisp.

Again, I do appreciate you explaining the specifics here, so let me just
ramble why I think you're right and I still think "Lisp has no syntax". I did
not take a Compilers course, but I call em like I see em. _proceed at your own
boredom_

I guess my real problem is that I can't write down the line between syntax in
Lisp and semantics. Many things are mere consequences of particular
implementations, so I'll just list 3 scenarios.

SBCL could, _ostensibly_ , update IF to be a compiler macro (defined with,
say, COND). Gasp, I know. Would that break any code? Or would it just break
the ANSI standard? Speed aside, how much does it matter?

SBCL could also change IF so the true & false parts are swapped. A criminally
stupid move, sure. Then it's definitely not Common Lisp anymore. They'd've
changed the _calling convention_. Note that the lexer wouldn't change at all,
just the parser (pretend there's a separate lexer/parser, even though popular
Lisps are all self-hosting). This seems to me a change in semantics, though I
understand why one might argue it's a change in _syntax_.

SBCL could also do a third stupid thing: change IF so the test-case is wrapped
with square braces, like (if [> 2 3] x y). This would be a major change, of
course, and it wouldn't be Common Lisp. But the reader could be rewritten to
handle the new characters and all the source code could be changed. This would
definitely change the syntax. Note that the lexer needs tweaking, but the
parser remains exactly the same (you don't even need new tokens).

If the syntax changes, the lexer changes. If the semantics change, the parser
changes. The interface between the lexer and the parser is the List.
Presumably, one could write a Lisp program in & a runtime for JSON lists
instead of sexp lists, but I fail to see the benefit. Sexps are nearly the Ur-
language for lists, unless you aren't trying to be a subset of ASCII (e.g.
binary encodings). C-style arrays are no fun:

    
    
        ----main.lisp
        {"defun", "factorial", {"n"}, 
            {"if", {">", "n", 0"},
                {"*", "n", etc},
                {etc}}}
    

What a terrible syntax on such a beautiful semantics.

Anyhow I've been thinking about Lisp a lot today, and now my brain is kinda
tired, so I'm going to go take my dogs for a walk. Thanks for the thought-
provoking discussion.. :)

------
lispm
Lisp syntax is quite a bit more than prefix operators + postfix arguments.

* s-expressions are a syntax for data

* Lisp syntax is expressed on top of s-expressions, reusing s-expression syntax for data

* Lisp has built-in syntax for several constructs: lambda, let, block, setq, if, ...

Many programming languages have some form of prefix operators.

Btw., some Lisps allow to omit outer parentheses in a Listener (aka REPL):

    
    
        CL-USER 30 > delete-file "/Lisp/foo"
        NIL

~~~
arethuza
Speaking of leaving parentheses out of lisp - you can go the whole way and
have a whitespace lisp:

[http://draketo.de/light/english/wisp-lisp-indentation-
prepro...](http://draketo.de/light/english/wisp-lisp-indentation-preprocessor)

~~~
lispm
Stuff like that exists for decades:

For example RLISP:

    
    
        SYMBOLIC PROCEDURE SMEMBER(U,V);
           %determines if S-expression U is a member of V at any level;
           IF U=V THEN T
            ELSE IF ATOM V THEN NIL
            ELSE SMEMBER(U,CAR V) OR SMEMBER(U,CDR V);
    

Which would be in Lisp:

    
    
        (defun smember (u v)
         "determines if S-expression U is a member of V at any level"
          (cond ((equal u v) t)
                ((atom v) nil)
                (t (or (smember u (car v))
                       (smember u (cdr v))))))
          
    

RLISP has been developed somewhere in the 60s/70s as a parentheses free
notation for Lisp on top of Standard Lisp. Much of the computer algebra system
REDUCE is written in RLISP.

~~~
qu4z-2
This strikes me as a much bigger and less obvious transformation than the one
suggested by the grand-parent (although interesting none-the-less).
Specifically, this seems to take semantics into account whereas the suggested
representation is apparently purely syntactic. For instance, the
transformation from

    
    
        IF U=V THEN T
    

into

    
    
        (cond ((equal u v) t))
    

would seem to require an understanding of the IF construct and a mapping of
infix operators to lisp functions at the least.

Now, maybe this syntactic transformation has been around for decades too (the
fact that I've independently toyed with the same idea suggests it's not
uncommon to play with), and alternative Lisp syntaxes are quite interesting in
their own right, but I do feel that the whitespace-lisp suggestion has merit
in its own right (but again, I'm clearly biased). Essentially, it's an
alternate syntax for s-expressions, not lisp.

------
pdpi
Perhaps it's meant as a joke, but "prefix-RPN" grinds my gears. Just call it
"Polish Notation", instead of "prefix Reverse Polish Notation".

~~~
VLM
Look on the bright side, when HP48 calculators were more common so RPN was
better known, I heard a lot of "Reverse RPN"

~~~
Jtsummers
Some of us just said that as a joke. Like the day we finally thought about the
banks telling us to enter our PIN numbers and decided to embrace the
redundancy and repetition.

------
Dylan16807
That sure does look like lisp. It also looks like a way I would definitely not
use to do arithmetic if I could avoid it.

This is more of a cautionary tale of going too far in making programs do 'one
thing' than it is an endorsement of lisp.

------
kermitdance
I prefer comparisons of XML and LISP syntax to counter people complaining
about the latter, while happily applying the former to pretty much everything
under the Sun (application configuration, data exchange, dependency mgmt,
build mgmt, scripting...) I'm not saying LISP is good and XML is bad; but I've
seen some baffled faces when pointing out the similarities.

------
Monkeyget
Stopping at the syntax when talking about Lisp is pretty narrow-minded and
completely misses what makes Lisp so great. It's like saying to a car driver
that motorcycles are nice because they only have two wheels and thus take less
parking space. Technically true but not what makes them exciting. When you
describe to the coffee-drinking radio-listening commuter about taking corners
and being one with the road he won't understand what the point is. But if he
were to drive a bike around a circuit, oh boy! I'm probably going to fail
miserably but let me attempt to explain cornering and being one with the road
in Lisp.

What's so great about Lisp? : its extreme malleability in the way you write
code and the data it uses.

Code and data are the exact same things in lisp. They are represented the same
way : lists represented with braces around them who can be nested. It's called
s-expressions and they are in the form (<operator> <operand1> <operand2>
<operand3>). There is no fundamental difference between code and data they are
just list represented as s-expressions:

    
    
      (list 1 (list 2 3))
      (+ 1 (+ 2 3))
    

Another example :

    
    
      (task 
        (time 14 00)
        (log "beginning of task")
        (job (backup-files (important-files-in (list-files))))
        (job (delete (list-files))))
    

Quick, what's that above, code or data? How about both?

The one nice thing about s-expressions (sexp) instead of classical curly
braces is that the code written in sexp IS ITSELF the abstract syntax tree of
that code.

For example, think of a function function add(a, b){return a+b;}

You could convert this function into its syntax tree like this :

    
    
      (define-function (name add) (parameters a b)
      (body (return (+ a b))))
    

If we simplify things a bit we end up with :

    
    
      (defun add (a b)
        (+ a b))
    

Lo and behold, the example above IS Lisp code. Is that code or data? How about
both?

The syntax of Lisp is the same as its internal represention. That's called
homoiconicity.

What's so great about that? Well, mix that with macros whose language is Lisp
itself and can do anything with s-expressions and you end up wielding great
powers.

A simple example. Let's go back to our task example. We can treat it as data :

    
    
      //not actual lisp code but you get the point
      var my-task = (task 
        (time 14 00)
        (log "beginning of" )
        (job (backup-files (important-files-in (list-files))))
        (job (delete (list-files))))
    

my-task is now a list containing sub lists representing a task. What if we did
this now :

    
    
      //not actual lisp code
      (defun time (hour minutes) (print "%d:%d" hour minutes))
      (defun log (string) (print string))
      //we say that task is a function
      //that should call each list it contains as a function
      (defun task () /*execute each list it contains*/) 
      //...
    

Now we can just do:

    
    
      (my-task)
    

What do you think is going to happen? Yes, the data, the task is being
executed.

Now for the last touch : add to Lisp a powerful macro system that can take any
s-expression (any list) and transform it any way it see fits and you end up
yielding great power. What's that language? It's Lisp itself. Code is data.
Lisp code evaluting other lisp code. I am so enlightened.

Not enlightened? Didn't get anything out of my post? Then give Lisp a try! You
have to dive into Lisp to be able to get it. As Eric raymond put it : "Lisp is
worth learning for the profound enlightenment experience you will have when
you finally get it; that experience will make you a better programmer for the
rest of your days, even if you never actually use Lisp itself a lot." \- ESR

~~~
Denzel
For the past few months I've been studying Lisp, reading SICP, and just trying
to become more familiar with the concepts. Like many people, I was put off by
Lisp's seemingly arcane syntax, which now feels beautiful to me. I can't fully
explain it, but for years I had been searching for a way to reduce and
abstract duplication in the structure of my code. (There's a fundamental
difference between this, and simply pulling something out into a function or
method.) It wasn't until I came across a great explanation of homoiconicity
and macros that I became "enlightened." Lisp was what I was looking for all
along.

One day, I tried explaining it to my manager, and he just couldn't get it. It
wasn't clicking. Until I showed him a demo of symbolic differentiation (a la
SICP), at which point he said, "Holy shit," and sat there for a few minutes
considering all the implications. That was one of the greatest moments we ever
shared together.

~~~
Jach
For those who aren't so lucky to have an understanding manager (though you
didn't say your manager then agreed to let you start writing everything in a
lisp...), I just wanted to bring out the punchline of this hilarious and
melancholy comment[1] from a couple months ago: "And yet: the money guys are
offering money. Just swallow your pride, play 'Stairway to Heaven' at the
wedding, and pretend you've never had crazy eyes when talking about
homoiconicity, and the rent will be paid."

[1] Don't upvote me:
[https://news.ycombinator.com/item?id=7423626](https://news.ycombinator.com/item?id=7423626)

------
zokier
I though a pipeline would be more idiomatic way of doing this in bash. But my
initial attempt resulted quite unreadable mess:

    
    
        $ cat <(echo 2) <(cat <(cat <(echo 10) <(echo 4) | +) <(echo 7)| d) | x
        4
    

Is there any way of making that more readable? My variation of the C utility
source code is here:
[https://gist.github.com/zokier/c55e9c9736009981b494](https://gist.github.com/zokier/c55e9c9736009981b494)

~~~
captainmuon
Let the operators take one argument?

    
    
        # 2*((10+4)/7)
        $ echo 10 | add 4 | divide-by 7 | times 2
        4

~~~
zokier
I do like that, it also makes the utility more filter-like. Here is that
implemented in C:
[https://gist.github.com/zokier/6b43032afb248bef68b7](https://gist.github.com/zokier/6b43032afb248bef68b7)

------
ben0x539
hey guys i think haskell is a lisp too

~~~
nox_
Why was this downvoted when it clearly shows how this article is misguided?
Just because a language uses parentheses for some of its constructions doesn't
mean we can call Lisp syntax.

------
theothermkn
I don't know if Rich Hickey said it first, but he said it well when he noted
that programmers get really upset when the parenthesis is on the left side of
the function name, instead of the right side.

DoSomething(an_arg, another_arg);

vs.

(DoSomething an_arg another_arg)

I'm not sure the second is markedly less readable than the first.

------
robin_reala
In Fish shell backticks for evaluation are replaced by parentheses. One step
closer I guess.

~~~
jimktrains2
$() = `` in bash and zsh too. Bonus that $() can be nested.

------
davidw
From that point of view, Tcl is even more lispy.

    
    
         set foo [somefun $a $b]

~~~
networked
I recently discovered Tcl and it immediately struck me as a refinement of the
"stringly typed" design behind the Unix shell.

I've been wondering if it would be a good idea to try building a modern fish-
style [1] shell aimed primarily at interactive use and one-liner
expressiveness based on a Tcl interpreter. (I tried eltclsh and it's close but
not quite that out of the box.)

[1] [http://fishshell.com/](http://fishshell.com/)

------
basdp
Well, if you limit yourself enough, almost any language is a 'lisp'. Maybe we
should stop calling anything with parentheses a 'lisp'.

------
smoyer
The filters you specify for LDAP searches were probably inspired by Lisp
syntax too:

(&(|(uid=smoyer)(uid=swm))(mail=redacted@gmail.com))

To be honest, I'm not sure why the test expressions are infix while the
logical operators are prefix. My guess is that it allows a filter to be
specified without whitespace.

~~~
zokier
Wouldn't it be whitespace-free with prefix test expressions too?

    
    
        (&(|(=(uid)(smoyer))(=(uid)(swm)))(=(mail)(redacted@gmail.com)))

~~~
smoyer
Wow ... I hadn't pictured it with parenthesis but you're right! I still don't
know why the tests were infix then ;)

------
ktg
L++ is a programming language that transcompiles to C++. It uses Lisp-like
syntax. Macros are supported via Racket's macro system define-syntax, define-
syntax-rule and defmacro.

L++ | [https://bitbucket.org/ktg/l](https://bitbucket.org/ktg/l)

------
espadrine
In Scheme, SRFI 105[1] gives the ability to do math with infix operators.
There's no reason you can't have your cake and eat it too!

[1]:
[http://srfi.schemers.org/srfi-105/srfi-105.html](http://srfi.schemers.org/srfi-105/srfi-105.html)

------
richardwhiuk
By that argument Objective C is using Lisp syntax [a b:1 c:2].

Besides, if you want to persuade me to use Lisp, then starting by comparing
the syntax to the shell is probably a bad idea, as others have said.

~~~
spion
Yup. See [http://clochure.org/](http://clochure.org/)

------
jlas
This is silly, sh/bash natively support arithmetic operations with infix
notation. He writes a contrived arithmetic solver in C to support his
argument.

------
tomp
Oh god, another barely valid non-argument about the superiority of LISP
syntax.

Well, guess what. Function name, followed by arguments, is not LISP, it's
_Mathematics_. `A x` has meant applying a linear transformation to a vector
(i.e. matrix multiplication) for a very long time.

Furthermore, saying "it's like LISP but without parenthesis around it" is like
saying "it's like Java but without parenthesis around arguments and commas
between then" when you actually mean to say "it's just like ML".

Finally, bash has infix operators (like `|` and `;`), which make it infinitely
more readable than it would be without them. Really, if we can compare bash
with any other programming language, it's ML.

~~~
grayclhn
There's more prefix notation in math than you think:

∑ᵢ xᵢ

∫ x² dx

etc. And `A x` is more likely to be written as `(A x)` than `A(x)` in your
example. I don't necessarily agree with the article, though...

~~~
sp332
tomp's point is that "LISP syntax" is actually math syntax. I think you're in
violent agreement...

