6 ms·
The difference between adding symbols to a language with product types (i.e. consing) and simply having algebraic data types in your language is that symbols ar
by gue5t 10y ago
The difference between adding symbols to a language with product types (i.e. consing) and simply having algebraic data types in your language is that symbols are untyped, and so you're allowed to compare apples and oranges (they're inequal).
This isn't terribly useful, as it's almost always a mistake to do it. If you do have a context in which you want to compare apples and oranges, algebraic datatypes force your hand to declare which types of things you'd like to compare across (e.g., specify that you're comparing any fruits, and that apples and oranges are fruits). This clarity helps form a clear mental model of how your software works and avoid bugs.
Lisp is the "hold my beer, I know what I'm doing" of functional programming languages. It, like other languages that take this stance, should be laid to rest. Time has demonstrated that programmers do not know what we're doing, and need all the machine-provided help we can get.
- deleted 10y ago[deleted]
- sedachv 10y ago> The difference between adding symbols to a language with product types (i.e. consing) and simply having algebraic data types in your language is that symbols are untyped, and so you're allowed to compare apples and oranges (they're inequal). This isn't terribly useful, as it's almost always a mistake to do it. You are taking one trivial use case of Lisp-style symbols (enums) and completely ignoring their value as first-class identifiers that come as part of the language. > Lisp is the "hold my beer, I know what I'm doing" of functional programming languages. Lisp is not a functional programming language.
- msdos 10y agoLisp is not a functional programming language. ?
- somethingsimple 10y agoIt's a multi-paradigm language. You can use it for functional programming, but it's not strictly a functional programming language.
- jwdunne 10y agoYes. In fact, the point with symbols and code as data is that you can implement different paradigms in the language itself. A program implementing prolog, for instance, is an example program in books.
- jfoutz 10y agoI generally agree with you, at least as far as i want all the machine-provided help i can get. Programmers do not know what we're doing is a little harsh. People can get a lot done in python for example. As things grow, it gets tougher and tougher to do the right thing all the time. But there's certainly room for that quick, fluid interaction of a less constraining language.
- rbanffy 10y agoWhile sometimes I don't, the times I do, I prefer a language that can hold my beer and allow me to do what I want. I want the machine to help me as much as I need, but no more. I also don't want to do its job.
- taeric 10y agoThis is... unproductive. Time has demonstrated that language is just one part of the tooling story when it comes to developing software. It is easily one of the most talked about, but ultimately it is just another tool. That LISP structured languages have not died despite many instances of people insisting they should have died already is almost evidence on its own that this is a non-starter. For more relevant disputes, consider https://docs.racket-lang.org/ts-guide/ https://docs.racket-lang.org/ts-guide/. Specifically, you can use tooling to get types into a LISP.
- gue5t 10y agoI have no dogma about where you implement your typechecker; all I assert is that it's better to have one. The LISP philosophy is (in my impression from the literature) that with powerful enough abstractions, one writes so little code that there is hardly any room for mistakes to sneak in, so typecheckers could provide little benefit. In one sense this thesis is plausible: at some level you either stop encoding the specification of your intended functionality into your types, or you end up programming in a theorem-proving language like Coq or Agda, which everyone seems to agree is bad for productivity. But I think we should be trying to move toward more specifications, not fewer, and solve the ergonomics problems as we encounter them. Unrelatedly, I have worked in Typed Racket and the performance is so poor that I can't advocate its use. Of course you can profile and optimize anything, and avoid writing code which typechecks slowly, but such static analyses seem the sort of thing where incremental computation (caching, and amortization across executions of the typechecker) should make even very powerful analyses finish quickly. And Racket doesn't take advantage of the results of its typing analyses to optimize runtime representations of datatypes, so even after typechecking your code runs very slowly and uses a lot more memory than it needs.
- Jtsummers 10y ago> I have no dogma about where you implement your typechecker; all I assert is that it's better to have one. You seem to be suggesting that types are absent from lisp, that's not the case. 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. Since you're not dogmatic about the where of it, try computing: (+ 2 'atom) In your favorite common lisp. It will result in an error, specifically a `SIMPLE-TYPE-ERROR`. You can also specify types in function declarations in Common Lisp: (defun double-integer (x) (declare (type integer x)) (* 2 x)) This will only accept integers now. Other types passed in as a parameter to `double-integer` will result in an error. You can apply this at any level once you start building up your own types as well (structs, classes, etc.). The benefit here is that you can leave your code wide-open to allow for many cases at some stages, while optimizing or constraining it in others. This malleability is fantastic in lisps. While I'm certainly a great fan and proponent of static type checking, the benefits of lisp's concepts (the malleability of its semantics and syntax), make it a great force-multiplier for component users. A great number of concepts become practically trivial when given the level of abstraction that lisps permit. A good type system can give you something akin to a calculus of types. A good functional language (here I'll include lisps even though many these days seem to discard them as such) give you a sort of calculus over computation. But the structure of lisp (particularly its homoiconic nature) gives you a calculus over your programs syntax and semantics. [0] The places where they may be considered weakly typed are places where it's somewhat "natural". Such as in Common Lisp where there's the numeric tower. Technically your number does stay a number, but it moves from an integer to, say, a rational when you perform a division by a non-divisor integer. It maintains the highest level of precision/accuracy possible. So `(/ 1 3)` doesn't become some 32-bit float version like `0.3333334`, but rather `1/3`, nor does it do the C thing and turn it into 0.