Hacker News new | past | comments | ask | show | jobs | submit login

> Common Lisp, Scheme, and Emacs Lisp all make use of types. They are, to a first approximation [0], all strongly typed and dynamically typed languages.

"Dynamically typed" is a contradiction in terms, at least if one is using the standard technical definition of the word "type". These languages offer runtime checks that have some things in common with a type system (in particular they have some of the same use cases), but they are not types and it is confusing to call them types (even if everyone in computer science agreed to talk about "dynamic types" and "static types" that would still cause confusion, because "static types" are types in the mathematical sense and "dynamic types" are not).

> But the structure of lisp (particularly its homoiconic nature) gives you a calculus over your programs syntax and semantics.

It's more a lack of structure, and a lack of syntax. In many lisps you have less control over syntax than in other languages - any embedded DSL has to be written in Polish notation. (You have reader macros but that's basically just having a program that operates on text strings, which you can do in any language - you can write a C program that preprocesses C source and it's effectively the same thing). I mean sure lisp lets you manipulate a tree of symbols arbitrarily, and then execute that tree with certain semantics. But there are a lot of languages you can do that in. The unique thing about lisp is that your program has to be expressed as a tree of symbols - which yes means that you have a calculus over it, but only by forcing its structure to be trivial. I'd rather have my program expressed as a richer structure, and a language that's powerful enough to manipulate rich structures in a structure-aware way.




> "Dynamically typed" is a contradiction in terms, at least if one is using the standard technical definition of the word "type". These languages offer runtime checks that have some things in common with a type system (in particular they have some of the same use cases), but they are not types and it is confusing to call them types (even if everyone in computer science agreed to talk about "dynamic types" and "static types" that would still cause confusion, because "static types" are types in the mathematical sense and "dynamic types" are not).

That is complete nonsense. Dynamically typed languages have types (many even treat them as first-class objects) and primitive expressions with types assigned to those expressions. What dynamically typed languages let you do is construct and evaluate terms that cannot be typed.

> You have reader macros but that's basically just having a program that operates on text strings, which you can do in any language - you can write a C program that preprocesses C source and it's effectively the same thing

This argument boils down to "you can write a huge compiler in any language you want! it's easy!" There is actually a Lisp meme about it: https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule

> I'd rather have my program expressed as a richer structure, and a language that's powerful enough to manipulate rich structures in a structure-aware way.

You are confusing program syntax with parse trees. All parse trees look the same ("here is a graph of your program"). You can keep things simple and have a syntax that is context-free, has an obvious mapping to the parse tree, has an obvious interpretation, and has tons of tooling support in hundreds of different tools and editors. Or you can decide that you really really like your whitespace to be very emo and sensitive - just write your own context sensitive parser, roll your own tooling, force everyone to learn it! It's easy!


Re embedded DSL as always Polish notation:

That's not accurate and it doesn't require a reader macro to change it. You do need to state the context in the first position, but any string of symbols after that can be manipulated by a macro. The order at that point is up to the macro designer. See the loop macro as an example.


Well sure, but at that point you're effectively implementing parsing it by hand - which I guess is better than implementing lexing by hand as you would with a reader macro, but not by much. You can take a string of symbols and then does something arbitrary with them, sure, but at that point your language isn't really doing anything for you (and again, you could do that in any language (if the point needs proving: apart from anything else, it's trivial to write a lisp interpreter in most languages) - the difference is that lisp doesn't allow you to do the more structured thing).


In what cases is a `richer' structure better? `Richer' to my ears sounds like `more complicated'. The basic function form of (fun arg1 arg2 ...) or fun(arg1, arg2) is adequate for most things and in lisp when you want to express something that doesn't work well in that form you write a macro to grok some structure (like cond). That all seems very structured to me, and I see no issue with the base structure being trivial. In fact I'd argue that's necessary to achieve a calculus over the code.


Some things just make more sense with infix or postfix notation. Not least of which being mathematical expressions.

I think Haskell handles it really well, where everything is just function application, but identifiers made of symbols apply infix (and there's syntax to switch between them). It's just enough syntax that you can usually structure things how you want, but the rules are still simple enough that it's easy see the tree structure.

Sometimes people go a bit crazy with adding their own operators, but for the most part I think the community is getting over that.


> Some things just make more sense with infix or postfix notation. Not least of which being mathematical expressions.

There are pretty much only four binary operators in modern mathematical notation that make sense infix (addition, subtraction, multiplication, and variable assignment) and only in very short, unambiguous expressions. Pretty much everything else is either prefix (function application, derivatives, summation, etc) or uses special layout formatting rules (division, exponentiation) or both (matrix multiplication).

Even with all of this modern mathematical notation is full of ambiguities. A great short discussion about this is in the preface to Sussman and Wisdom's _Structure and Interpretation of Classical Mechanics_: https://mitpress.mit.edu/sites/default/files/titles/content/... which despite being all about "mathematical expressions" somehow manages to have all of its code in Lisp...

I also recommend reading Munroe's _The Language of Mathematics_ for a better understanding of modern mathematical notation and its weaknesses.

Note also that this is only modern mathematical notation. There is nothing "natural" about infix operators and for most of mathematical history they did not exist (see for example Bashmakova and Smirnova's _The Beginnings and Evolution of Algebra_ or any other book on the history of algebraic notation).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: