Live data from Hacker News

The Idea of Lisp

dev.to

81–90 of 348 posts

Re: The Idea of Lisp

#81
post #51

Earlier quoted context omitted.

Rust also has (almost) everything being an expression - things like this aren't uncommon: let x = if something { foo() } else { bar() } Things which don't have a logical value evaluate to `()` (the empty tuple), I believe.

This example of "everything as an expression" doesn't take it as far as Tcl, though. In the above code snippet, the conditional body is surrounded by braces, which are syntax. In Tcl, the second argument to the 'if' command is also an expression, which only uses braces as a quoting mechanism, if it needs to.

I'm not sure I understand why it matters if the syntax requires braces or not. The things inside the braces are still expressions.

Re: The Idea of Lisp

#82
post #13

Nice article. Check out Paul graham's The Roots of Lisp for a similar exploration in which he shows how to build the metacircular interpreter. > John McCarthy wrote 6 easy things in machine code It was actually Steve Russel, McCarthy's grad student, who had the idea of writing McCarthy's eval function in machine code.

> It was actually Steve Russel I seem to recall reading that McCarthy was actually surprised to discover that Lisp _could_ be run by a real computer; he intended it to be a completely theoretical tool.

I have also heard that, but only from secondary sources. Here is a clip of Russell talking about the time he wrote the first lisp interpreter. He doesn't mention McCarthy being surprised, but he seems to imply that he, Russell, was quicker to grasp the idea of translating the functions McCarthy had been writing to machine code.

http://www.computerhistory.org/pdp-1/1020b307d766e0019de2b4a...

Re: The Idea of Lisp

#83

This great idea of Lisp (the simple syntax of function calls in round brackets) isn't much different than a good macro assembler even back in the 1960's. The only major difference was that more than 1 function could be defined in 1 source code line. (I think that machine code is nothing but a sequence of function calls where the function is the logic encoded in the CPU itself for each opcode.) Is it fair to compare t…

Agreed about linked lists; that virtually all functional languages make them the default/literal data structure is IMO a poor practical design choice (no matter how theoretically elegant) and is the primary culprit for their reputation for slowness. And the tendency for functional compile-to-JS langs to emulate linked lists in Javascript and keep them the default data structure is downright laughable.

(Singly linked) lists are a functional data structure. You can manipulate them efficiently without modifying the lists you started with. You can't do that easily with arrays. So if you base your language around arrays, you're better off making it imperative.

Lisp predated level 1 caches. I think it's better to design hardware around the software that runs on it (the Burroughs mainframe/Lisp machine approach), than design programming languages around the machines which run them (the C approach). In this case, it means finding a way to make non-local data references more efficient.

Lisp's original reputation for slowness predated the use of Level 1 caches, and was because many early implementations ran on interpreters.

Re: The Idea of Lisp

#84
post #48

Earlier quoted context omitted.

The if expression is not a persuasive example. C/Java/Algol/etc all have it as well. x = something ? foo() : bar();

I see two issues with the ternary operator. One, the syntax is much less readable, and two, the consequent and alternate are both single expressions, so you can't do something like: x = if(something) { a = foo(); baz(a); } else { b = bar(); baz(b); }

You compute baz in both branches, you can refactor.

    x = baz(if (something) foo() else bar())

Re: The Idea of Lisp

#85

This great idea of Lisp (the simple syntax of function calls in round brackets) isn't much different than a good macro assembler even back in the 1960's. The only major difference was that more than 1 function could be defined in 1 source code line. (I think that machine code is nothing but a sequence of function calls where the function is the logic encoded in the CPU itself for each opcode.) Is it fair to compare t…

You make some specific claims here that sound a little odd to this LISP and assembly language hacker. Assembly language doesn't provide any datatypes. LISP does. Assembly language doesn't provide any type checking. LISP does. Assembly language doesn't provide automatic storage reclamation. LISP does. Assembly language doesn't provide naming. LISP does. You also make a claim about L1 caches and locality of reference.…

He was talking about macro assemblers, which often do provide naming and some level of type checking (and pure assembly is arguably at a lower level of abstraction than type systems, with separate instructions and registers for integers, pointers, floating-point etc).

I agree it's a somewhat odd comparison.

There are of course plenty of obvious and non-obvious ways to optimize linked lists, but even still they have poor performance characteristics, space efficiency and cache locality compared to alternative structures like arrays and even immutable arrays.

There's a reason Java, C#, Python etc store strings as immutable arrays; not only do they start from a generally better performance baseline than lists, but they too have well-understood optimization characteristics.

Re: The Idea of Lisp

#86
post #19

Earlier quoted context omitted.

While ML was the meta language for a theorem prover. Funny how these were side effects.

If there's one thing I've learned from programming it's that to build anything good you have to be driven by real use cases.

It's not clear if your comment approves or disapproves the one you've commented.

Re: The Idea of Lisp

#87

This great idea of Lisp (the simple syntax of function calls in round brackets) isn't much different than a good macro assembler even back in the 1960's. The only major difference was that more than 1 function could be defined in 1 source code line. (I think that machine code is nothing but a sequence of function calls where the function is the logic encoded in the CPU itself for each opcode.) Is it fair to compare t…

You make some specific claims here that sound a little odd to this LISP and assembly language hacker. Assembly language doesn't provide any datatypes. LISP does. Assembly language doesn't provide any type checking. LISP does. Assembly language doesn't provide automatic storage reclamation. LISP does. Assembly language doesn't provide naming. LISP does. You also make a claim about L1 caches and locality of reference.…

I was only talking about the 'list of function calls' aspect of assembler and Lisp, not the type system. I agree that Lisp has a type system and assembler doesn't. Forth is another language that also has very simple syntax that approximates the 'list of function calls' style that I would say isn't unlike a macro assembler either.

I am writing a new language with built-in garbage collection that I think is quite superior to other languages. I have created a full standard library with almost 1,000 built-in functions and none of my data structures (lists, maps, trees, stacks, indexes, tables etc) contain pointers or linked lists (that use pointers). I sold over 30,000 copies of a language/database system in 1987 so I think your last comment is quite inappropriate. I have know about Lisp since I started CS in University in 1975.

Linked lists are horrible data structures when being used as well as when being freed (your garbage collection comment). I use simple dynamic multi-typed arrays instead of linked lists (pointers) and they can be freed in 1 chunk or a bigger version can be freed with a few memory de-allocations. I get full cache locality and improved speed of allocation and de-allocation.

I would love to see an incremental GC that can copy all linked lists nodes into contiguous memory automatically. Nice trick if you can do it but that doesn't help you if your linked list doesn't cause a GC.

Re: The Idea of Lisp

#88
post #27
post #2

The conditional expression or more specifically everything being an expression is my favorite thing about Lisp. I did not know that McCarthy pushed to add it to Algol which apparently today is the ternary operator for most languages. It is annoying that so many languages (C, Java, C#, etc) have both a conditional statement (if-else) and conditional expression (ternary ?:). Really the if-else should be an expression (…

Is there any literature on how to translate languages where everything is an expression to ones where it isn't, for example when compiling/transpiling to java? If/then can be translated to the ternary operator, but terms like try/catch are trickier.

Usually when I'm faced with putting a try/catch in an expression in Java, I end up wrapping it in it's own method.

It's not the nicest solution, but it would allow targeting Java without disrupting the code structure too much.

Re: The Idea of Lisp

#89
post #61

Earlier quoted context omitted.

Picolisp can match it in dynamism. Seriously, Picolisp is absolutely insane.

I just read a bit of documentation from the Picolisp page. It looks really cool, but can it reach arbitrarily far up the call stack? That's the quality of tcl that I don't see other places. The capabilities of 'upvar' and 'uplevel'. [Edit] I should say "one of the qualities." The other important one is that Tcl has no types. Even all the lisps I know have types.

>The other important one is that Tcl has no types.

Is it that it has no types or that everything is a string? asking, not stating.

Re: The Idea of Lisp

#90

Earlier quoted context omitted.

Rust also has (almost) everything being an expression - things like this aren't uncommon: let x = if something { foo() } else { bar() } Things which don't have a logical value evaluate to `()` (the empty tuple), I believe.

> Things which don't have a logical value evaluate to `()` (the empty tuple), I believe. If Rust follows Scala then `()` is not the empty tuple, but rather Unit (void in C*).

The empty tuple/unit is not the same as void. It has exactly one possible value, void has zero possible values. A way to write it in Rust is `enum Void {}` (an enumeration with no options).
Post reply on HN