I've never gotten the hang of car/cdr and dotted pairs.
(alist->hash-table '((foo . 1) (bar . 2)))I don't understand that.
> Association lists, which can be represented as literals, are persistent and provider faster lookup, despite being {snip}
Those look like like they could be useful, but I don't see how they can replace hashmaps --- for one thing, they allow duplicate "keys" (the first element of each pair).
I'd use a lisp, and don't mind the lisp/parens syntax, but to be useful for me it must provide easy access to and use of hashmaps and sets.
Introducing state into programs makes them harder to reason about, thus Scheme programmers generally discourage the use of mutable data structures when a persistent data structure would have worked.
>Those look like like they could be useful, but I don't see how they can replace hashmaps --- for one thing, they allow duplicate "keys" (the first element of each pair).
The way alists are used, only the first pair to contain the desired key is considered. Thus, you can "overwrite" a key/value pair by consing a new pair onto the head of the list.
>I'd use a lisp, and don't mind the lisp/parens syntax, but to be useful for me it must provide easy access to and use of hashmaps and sets.
I had the same initial complaints about the lack of reader syntax for hash table. It's a common complaint, actually. However, I found that as I learned more about how to write Scheme, I stopped using hash tables in any place where I used to want literal syntax for them. I learned that people reach for mutable hash tables far too frequently when there are better options available.
What languages even have literal syntax for sets? I can't think of any, but I'd like to know.
Reader syntax varies in each language, but I hope you can see that this really isn't a big problem at all.
> > I don't understand that.
> Introducing state into programs makes them harder to reason about, thus Scheme programmers generally discourage the use of mutable data structures when a persistent data structure would have worked.
Oh, maybe you typoed and meant to say that traditional hashtables are mutable data structures? In that case, I see what you mean; in Clojure, hashmaps, vectors, sets, and lists are all immutable and persistent. In Scheme, which data structures are persistent, or mutable/immutable?
> The way alists are used, only the first pair to contain the desired key is considered.
Ok, I see now. The function creates a hashmap from an alist.
> I learned that people reach for mutable hash tables far too frequently when there are better options available.
{raises hand} They're very easy to work with. In Clojure, I found myself doing extra work to work around the immutability. I'm sure it's a benefit for larger and multithreaded programs, but mine were neither.
> What languages even have literal syntax for sets? I can't think of any, but I'd like to know.
Clojure and Python. I suppose I could live without literal set syntax, but hashmap/hashtable syntax is extremely handy.
The MIT Lisp Machine from the late 70s implemented hash tables and used them widely:
Not trying to start an argument, but that's my view from a C#'er who tried Lisp a while ago. I often see Lisp talked about on HN as though it's the solution to all our problems, but it's really not. Syntax is a big deal in programming languages, with lots of trade offs between human readability and unambiguous parsing by the computer, and s-exps aren't some magic bullet for this.
That's a really funny question in a thread about another new programming language.
By being able to bend a Lisp to your will, you trade your ability to standardize the language and build a community of libraries and tools around it. That being said, there's nothing like having a language which eventually becomes the best tool for solving the problem you're facing for at hand (as your Lisp will tend to evolve appropriately).
1) Invent a new useful macro.
2) Package it as a library
3) Document it.
4) advertize it
Since macros are written in a standard language and many cab be written in a portable way, it just another way of meta programming.
Stuff like DEFCLASS, DEFMETHOD, ITERATE, WITH-GENSYMS, etc. started as portable libraries.
What one has to learn: the language does not have a fixed amount of syntax. That's the price to pay: learning a new level of programming: linguistic meta programming.
Car, cdr, and cons take very little time to understand, but yes their meaning is steeped in history. "car" returns the first element of a pair, "cdr" (pronounced like "could-er") returns the second element of a pair, and "cons" creates pairs. Not that bad. However, today's Lisps put more emphasis on using pattern matchers than manually car/cdring down lists.
>Why are there so many dialects?
That's like asking "Why are there so many ALGOL derivatives?" Lisp classifies a family of languages, not a single language. It's like saying something has C-like syntax.
>Can you not agree on something that works?
Given the above misunderstanding, this question is no longer relevant.
>Where is your IDE with error underlining and autocomplete list that comes up with each keystroke?
A lot of Lisp hackers use Emacs with a few extensions. I am a Guile Scheme user, so I can only speak for my setup: Emacs, Paredit, and Geiser. Paredit provides efficient, and powerful structured editing support for s-expressions. Geiser provides REPL integration. Geiser can autocomplete symbols, jump to the definition points of variables, display documentation for a procedure or macro, show the values of variables under the cursor in the modeline, show function signatures in the modeline, and allow instant evaluation of arbitrary expressions with a simple keystroke (including jumping to the debugger when things go wrong), and probably some other things that I'm forgetting. It is the nicest development environment I have ever used. Common Lisp users also like Emacs and Paredit, but they typically use SLIME for REPL integration.
> And finally s-expressions, which make you twist your mind in order to write and don't give clear structure of the code meaning to the reader, and not even considering macros...
We'll have to disagree here. S-expressions are very nice, once you get used to them, which can be a bit difficult if your background is using C-like languages with infix notation. They remove complexity, make the language more regular (the operator is always the first element of a list, things that are operators in some languages like +, -, etc. are normal procedures that can be used as values), and allow for syntactic abstraction. Not only can you quote arbitrary expressions like '(+ 1 1) and manipulate symbols directly, the macro systems available in various Lisps allow for the creation of new syntax which is one of the most useful features a programming language could have. One of Paul Graham's essays talks about "top down, bottom up" design where the "bottom up" part involves defining new syntax when patterns emerge in your problem domain that you'd like to express in a more readable and less redundant way. Lisp allows you to build the language suitable for your problem. You seem to imply that macros are bad, but I think that languages that do not offer a macro system are fundamentally limited in the problems they are suited for solving.
I by no means claim that s-expressions are a magic bullet, but I think you are biased in saying that they are inherently less readable than more complex syntaxes. There's a lot of mystique and misunderstanding around Lisp, and I hope I have cleared up a thing or two.
I never bought this argument, based on my intuition, but now Julia has proved this argument to be invalid. Insisting only S-expressions allow macros is simply intelectually dishonest. Go check how Julia does metaprogramming; all the power of Lisp with none of the wierdness.
I would love to see and example of LISP being as fast as C++ with multi-threading and cache coherency taken into account, using the same amount of memory, with no pauses from the gc that would affect interactivity. If it hasn't happened in the last half century though, I don't think it's going to happen at all.
Still people can do interesting stuff. For example the Crash Bandicoot games for the early Playstation were written in a low-level Lisp dialect with an external compiler implemented in Common Lisp. It ran on a tiny Playstation with cute graphics and sold very well.
There are always trade-offs. GC is a win because manual memory management is terrible and error prone, but a lose because you have to learn how to tune it to behave the way you need. But no matter the language some things stay the same: learn to anticipate what code your compiler is going to generate, check what the optimizer is doing, check the disassembly, use the profiler. Good GCs and compilers play all the same games with cache locality and such, and some are better than others. I think you are underestimating the advances in compiler design. Maybe you think C/C++ are fine languages, and that's OK, but personally they are the absolute last resort for when I reach limitations of my language's compiler and runtime.
C and C++ are two separate things.
> manual memory management is terrible and error prone,
The choice isn't between C style malloc and GC, it is a matter of how a language handles ownership. Look at move semantics or Rust's ownership. These are deterministic and controllable methods of memory allocation that aren't terrible or error prone.
> I think you are underestimating the advances in compiler design.
I would love to see an example like I said before, but you aren't giving any hard information to back up what you are saying.
This is how my WIP (verrrry WIP) game engine written in Guile Scheme works. It is built explicitly to enable iterative, live development.
2 year old video of a precursor to the current project: https://dthompson.us/functional-reactive-programming-in-sche...
Simple example program: https://git.dthompson.us/sly.git/blob/HEAD:/examples/simple....
More complicated minesweeper example: https://git.dthompson.us/sly.git/blob/HEAD:/examples/mines/m...
Home page: https://dthompson.us/pages/software/sly.html
Hoping to get a 0.2 release out the door in time for the Lisp Game Jam coming up in April.
Also if you are selectively executing parts of files, how is it that you are editing the live running source code?
I'm sure more people around here have the same dream about their favorite language :-)