News for hackers. Stuff that matters.
Re:The Idea of Lisp by agentgt on Friday December 16, 2016 @08:41AM (#13193136)
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 (I think the ternary operator is hideous).

Re:The Idea of Lisp by DonHopkins on Friday December 16, 2016 @04:23PM (#13196983)
Expressions are limited, because they can only return one result. In stack based languages like Forth and PostScript, any function can take and return any number of parameters. In fact they can decide at runtime how many to take and return.

PostScript is a lot like Lisp in that it's purely and simply homoiconic: PostScript code is just normal PostScript data. The "ifelse" operator takes a boolean and two expressions (executable PostScript polymorphic arrays, or any other PostScript object, executable or not -- non-executable objects are just pushed onto the stack), and executes one or the other depending on the value of the boolean parameter.

I think Lisp's multiple-value-bind is an inelegant hack, compared to the simplicity of PostScript.

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @06:52PM (#13197978)
PS seems like a nice language. Such a shame it's stuck on the printer: it seems like it would be a good alternative to FORTH in less memory-constrained environments.
Re:The Idea of Lisp by DonHopkins on Friday December 16, 2016 @09:08PM (#13198719)
NeWS is a Network extensible Window System developed by James Gosling at Sun in the 80's, which used PostScript not just to draw on the screen (like NeXT), but also (unlike NeXT but like AJAX) to implement entire window managers, user interface toolkits, applications, and intelligent responsive front-ends to networked applications, all in the NeWS window server (like a web browser).

NeWS was architecturally similar to what is now called AJAX, except that NeWS coherently:

+ used PostScript code instead of JavaScript for programming.

+ used PostScript graphics instead of DHTML and CSS for rendering.

+ used PostScript data instead of XML and JSON for data representation.

http://www.donhopkins.com/drupal/node/97

See the PSIBER and PizzaTool code I posted in the message above for an example of what was possible with NeWS!

Re:The Idea of Lisp by qwertyuiop924 on Saturday December 17, 2016 @06:18AM (#13200221)
Yes, NeWS was cool. But NeWS no longer exists, sadly.
Re:The Idea of Lisp by agentgt on Friday December 16, 2016 @06:27PM (#13197844)
Almost all FP languages typically have a solutions for this... it is called a tuple. With Lisp it is a list or cons cell.

ML languages have true tuples and I have to say is superior to output function variables and allows pattern matching.

Your the first I have seen to ever give a compliment to PostScript the language. I'll have to relook at Postscript (and other stack based languages).

Re:The Idea of Lisp by DonHopkins on Friday December 16, 2016 @08:19PM (#13198492)
I love PostScript! I haven't written (or stroked) a line of it in years, but it's still fun to think in. I used to do a lot of Forth programming before that, but PostScript is a lot higher level and Lispier (and NeWS's object oriented programming system was very Smalltalky).

Here's a metacircular PostScript interpreter:

http://donhopkins.com/home/archive/NeWS/ps.ps.txt

Also check out Glenn Reid's PostScript Distillery, a partial evaluator for PostScript programs that reads in an input PostScript program that draws text and graphics to print a document, and it partially evaluates it against the PostScript stencil/paint imaging model, and then writes out another canonical output PostScript program that draws the exact same document, but optimized, all in the same default user coordinate system, with redundant graphics state changes removed.

Distillery was the initial idea and working proof of concept that led to PDF, Adobe Acrobat and its Distiller which converts PostScript to PDF.

Of course if the input PostScript program that draws the document is procedural and has loops or recursion, the optimized output program has all the loops unwound and may actually be much larger! But the whole point of PDF and the Distiller is to strip out the programming language parts of PostScript and just represent the effective drawing commands.

http://donhopkins.com/home/archive/postscript/newerstill.ps....

And here's a paper about a visual PostScript programming and debugging environment for NeWS, which discusses the metacircular evaluator and PostScript distillery:

The Shape of PSIBER Space: PostScript Interactive Bug Eradication Routines - October 1989: http://www.donhopkins.com/drupal/node/97

The Metacircular Postscript Interpreter

A program that interprets the language it is written in is said to be "metacircular". [Abelson, Structure and Interpretation of Computer Programs] Since PostScript, like Scheme, is a simple yet powerful language, with procedures as first class data structures, implementing "ps.ps", a metacircular PostScript interpreter, turned out to be straightforward (or drawrofthgiarts, with respect to the syntax). A metacircular PostScript interpreter should be compatible with the "exec" operator (modulo bugs and limitations). Some of the key ideas came from Crispin Goswell's PostScript implementation. [Goswell, An Implementation of PostScript]

The metacircular interpreter can be used as a debugging tool, to trace and single step through the execution of PostScript instructions. It calls a trace function before each instruction, that you can redefine to trace the execution in any way. One useful trace function animates the graphical stack on the PSIBER Space Deck step by step.

The meta-execution stack is a PostScript array, into which the metacircular interpreter pushes continuations for control structures. (forall, loop, stopped, etc...) A continuation is represented as a dictionary in which the state needed by the control structure is stored (plus some other information to help with debugging).

It is written in such a way that it can interpret itself: It has its own meta-execution stack to store the program's state, and it stashes its own state on the execution stack of the interpreter that's interpreting it, so the meta-interpreter's state does not get in the way of the program it's interpreting.

It is possible to experiment with modifications and extensions to PostScript, by revectoring functions and operators, and modifying the metacircular interpreter.

The metacircular interpreter can serve as a basis for PostScript algorithm animation. One very simple animation is a two dimensional plot of the operand stack depth (x), against the execution stack depth (y), over time.

Printing Distilled PostScript

The data structure displays (including those of the Pseudo Scientific Visualizer, described below) can be printed on a PostScript printer by capturing the drawing commands in a file.

Glenn Reid's "Distillery" program is a PostScript optimizer, that executes a page description, and (in most cases) produces another smaller, more efficient PostScript program, that prints the same image. [Reid, The Distillery] The trick is to redefine the path consuming operators, like fill, stroke, and show, so they write out the path in device space, and incremental changes to the graphics state. Even though the program that computes the display may be quite complicated, the distilled graphical output is very simple and low level, with all the loops unrolled.

The NeWS distillery uses the same basic technique as Glenn Reid's Distillery, but it is much simpler, does not optimize as much, and is not as complete.

PSIBER source: http://donhopkins.com/home/archive/psiber/cyber/litecyber.ps...

The source includes a twisty little version of QuickSort implemented in PostScript by Don Woods, who also wrote Adventure!

PSIBER is a terribly ugly example of 7775 lines of PostScript code that draws and edits and debugs other PostScript code, but here's some better code that is well commented and meant to serve as a programming example, which configures, draws and orders pizzas:

PizzaTool source: http://donhopkins.com/home/archive/NeWS/pizzatool.txt

PizzaTool man page: http://donhopkins.com/home/archive/NeWS/pizzatool.6

Re:The Idea of Lisp by mroll on Friday December 16, 2016 @09:35AM (#13193457)
If you like everything being an expression, check out tcl. A lot of ideas from lisp show up in tcl, especially the idea of everything as an expression. Tcl embodies this idea while also having the look of an algol-like language. Funny it can pull this off while having basically no syntax.
Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @10:04AM (#13193681)
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.
Re:The Idea of Lisp by virtualwhys on Friday December 16, 2016 @10:55AM (#13194087)
> 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*).

Re:The Idea of Lisp by killercup on Friday December 16, 2016 @11:43AM (#13194508)
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).
Re:The Idea of Lisp by virtualwhys on Friday December 16, 2016 @01:35PM (#13195528)
The point is that both void and Unit can only produce a side effect. In everything-is-an-expression based languages Unit is exactly equivalent to void in C*.
Re:The Idea of Lisp by munificent on Friday December 16, 2016 @03:33PM (#13196517)
Re:The Idea of Lisp by jimktrains2 on Friday December 16, 2016 @11:13AM (#13194215)
It's the same thing. It's a type with only a single value.
Re:The Idea of Lisp by theseoafs on Friday December 16, 2016 @01:46PM (#13195625)
`void` in C does not have a value. You can't make a variable and put a void in it because there is no such object as "void".
Re:The Idea of Lisp by Ericson2314 on Saturday December 17, 2016 @10:18AM (#13200989)
That is an artificial restriction if C. Also see how ! In Rust is also loosing it's artificial restrictions.
Re:The Idea of Lisp by lomnakkus on Tuesday December 20, 2016 @06:16AM (#13218916)
Indeed, and there has been some talk of removing this restriction in C++ because it makes certain kinds of metaprogramming a lot more cumbersome than they should be.
Re:The Idea of Lisp by jimktrains2 on Friday December 16, 2016 @03:51PM (#13196689)
Yes, and () isn't void; the poster above me is wrong. Void is...the absence of a type? It's awkward.

However, () and Unit are.

Re:The Idea of Lisp by virtualwhys on Friday December 16, 2016 @01:29PM (#13195477)
It's not the same thing, a value of type Unit can only produce a side effect (or do nothing at all).
Re:The Idea of Lisp by dllthomas on Friday December 16, 2016 @02:15PM (#13195886)
How is that different from a value of type "empty tuple"?
Re:The Idea of Lisp by virtualwhys on Friday December 16, 2016 @03:12PM (#13196352)
True, neither are useful as values, though Unit typically conveys programmer intent (to produce a side effect), whereas the empty tuple is, in Scala at any rate, quite rare.

The empty tuple:

    scala> val empty = Tuple1(())
    empty: (Unit,) = ((),)
vs. Unit:

    scala> val empty = ()
    empty: Unit = ()
Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @03:17PM (#13196389)
Isn't that a tuple containing a unit, and therefore not empty?
Re:The Idea of Lisp by virtualwhys on Friday December 16, 2016 @04:43PM (#13197149)
It's the closest you can get in Scala to represent an empty value whose type is `Tuple`.
Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @06:29PM (#13197850)
The difference between an empty tuple (also known as unit) and void becomes obvious when you deal with vaguely complex trait impls. For example, if you have a trait:

    trait Foo {
        type ErrorType;
        fn bar() -> Result<u8, Foo::ErrorType>;
    }
How would you specify that your type implements Foo in such a way that bar() cannot return an error? If you were to implement it using the empty tuple (unit), like this, it could actually return an error:

    struct Abc{}
    impl Foo for Abc {
        type ErrorType = ();
        fn bar() -> Result<u8, ()> {
            Err(()) // oops, we don't want to be able to do that!
        }
    }
Instead, you can use Void here:

    enum Void{}
    struct Xyz{}
    impl Foo for Xyz {
        type ErrorType = Void;
        fn bar() -> Result<u8, Void> {
            // No way to create a Void, so the only thing we can return is an Ok
            Ok(1)
        }
    }
Aside from the obvious power to express intent (can we return an error without any information attached, or can we not error at all?), this would allow an optimizing compiler to assume that the result of Xyz::bar() is always a u8, allowing it to strip off the overhead of the Result:

    fn baz<F: Foo>(f: F) {
        match f.bar() {
            Ok(v) => println!("{}", v),
            Err(e) => panic!("{}", e)
        };
    }
    ...
    baz(Xyz); // The compiler can notice that f.bar() can never return a Result::Err, so strip off the match and assume it's a Result::Ok
A super-smart compiler would even make sure it's not storing the data for "is this an Ok or Err" in the Result<u8, Void> at all.

Finally, similarly, you can specify that certain functions are uncallable by having them take Void as a parameter.

Re:The Idea of Lisp by dllthomas on Friday December 16, 2016 @08:26PM (#13198532)
I don't think anyone is claiming Void in Scala/Haskell/Rust is equivalent to Unit in Scala/Haskell/Rust.

The question here was Unit vs empty tuple.

Up-thread was the question of whether C "void" is more like S/H/R Unit or S/H/R Void.

Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @08:32PM (#13198562)
Upthread was:

> If Rust follows Scala then `()` is not the empty tuple, but rather Unit (void in C*).

The implication is that () == Unit == void. The empty tuple and unit are essentially equivalent aside from name, void is something else.

Re:The Idea of Lisp by dllthomas on Friday December 16, 2016 @08:46PM (#13198609)
Regardless of who is right, you are arguing the wrong bit of it. I contend that, to a person, everyone saying "C void is Unit" doesn't think C void is Void. Arguing that Void is not Unit is just completely spurious. Of course Void is not Unit. No one disagrees.

In truth, C void is not exactly either Void or Unit. Like Void, you can't exactly make one... but you can call functions declared to take it and write functions that return it, and really it just means "I have no information to pass" - which is more like Unit.

Re:The Idea of Lisp by Sharlin on Friday December 16, 2016 @05:35PM (#13197521)
Type names are irrelevant here. Unit could be called "Tuple0", or be defined as a synonym of a type named such. The semantics are identical.
Re:The Idea of Lisp by joliv on Friday December 16, 2016 @04:08PM (#13196861)
> For historical reasons and convenience, the tuple type with no elements (()) is often called ‘unit’ or ‘the unit type’.

https://doc.rust-lang.org/reference.html

Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @11:16AM (#13194236)
void in C can't be created, used, or passed around - () can.
Re:The Idea of Lisp by shakna on Friday December 16, 2016 @01:26PM (#13195450)
But void pointers can, and are often used.
Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @02:29PM (#13196003)
So in Rust, the equivalent of void* with references instead looks like:

    enum Void{}
    fn foo(v: &Void){ ... }
    let bar : Void;
    fn abc() -> &Void{ ...}
    fn xyz() -> Void{ ... }
You can't create a Void, and you can't cast to it either - it's not a bottom type. So you can't put anything in bar. And as a result, you can't create a reference to a Void, so you can't call foo. And abc and xyz just can't be implemented in the first place.

On the other hand, you can do all of these just fine:

    fn foo(v: ()){ ... }
    fn bar(v: &()){ ... }
    ...
    let v = ();
    bar(&v);
    foo(v);
The fact that you can create and use an empty tuple as a value shows that it is not equivalent to Void.

(All statements here are made within the safe subset of the language - unsafe allows access to intrinsics that would allow a Void to be made, and a reference to Void.)

Re:The Idea of Lisp by kbp on Friday December 16, 2016 @03:59PM (#13196761)
void * isn't related to void (or this discussion), they just reused the keyword.
Re:The Idea of Lisp by mroll on Friday December 16, 2016 @10:27AM (#13193858)
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.
Re:The Idea of Lisp by wtetzner on Friday December 16, 2016 @11:26AM (#13194324)
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 by mroll on Friday December 16, 2016 @11:44AM (#13194524)
It matters because if the braces are not syntax, you can decide what code to execute as the condition body at runtime.

    set condition-body {puts "Hello, world"}
    if { $condition } $condition-body
To get this to run, you need to splice in the condition-body like so,

    if { $condition } {*}$condition-body
But you get the point.
Re:The Idea of Lisp by wtetzner on Friday December 16, 2016 @04:50PM (#13197206)
But the "then" and "else" parts of the Rust "if" are expressions. What you're talking about doesn't seem to be related to which things are expressions, it's more like being able to eval code at runtime.
Re:The Idea of Lisp by qznc on Friday December 16, 2016 @10:11AM (#13193752)
The if expression is not a persuasive example. C/Java/Algol/etc all have it as well.

x = something ? foo() : bar();

Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @11:11AM (#13194201)
The difference is that C/Java/Algol have different syntaxes for things-as-expressions and things-as-statements, and you can't put blocks in the things-as-expressions. In Rust, blocks are also expressions and so have a result (the result of the last expression in the block), so your expressions inside the if can be as complex as you like.

Since functions also have a block, and the return value of the function is the result of the block, this is much more consistent.

Re:The Idea of Lisp by kazinator on Friday December 16, 2016 @01:44PM (#13195608)
In GNU C, you can use a brace-enclosed statement block as an expression.

Funny story; years before I became a C programmer, and at a time when I didn't yet study ISO C properly, I discovered and used this extension naturally.

I wanted to evaluate some statements where only an expression could be used so I thought, gee, come on, can't you just put parens around it to turn it into an expression and get the value of the last expression as a return value? I tried that and it worked. And of course, if it works it's good (standards? what are those?)

Then I tried using the code with a different C compiler; oops!

Anyway, this GNU C feature doesn't have as much of an impact as you might think.

Re:The Idea of Lisp by coderzach on Friday December 16, 2016 @10:16AM (#13193788)
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); }

Re:The Idea of Lisp by kazinator on Friday December 16, 2016 @01:50PM (#13195675)
It should work in GNU C:

  x = (something) ? ({ a = foo(); baz(a) }) : ({ b = bar(); baz(b); });
However, since all your forms are actually expression statements, we can happily just use the ISO C comma operator:

  x = (something) ? (a = foo(), baz(a)) : (b = bar(); baz(b));
If C provided operators for iteration, selection and for binding some variables over a scope (that scope consisting of an expression), everything would be cool. E.g. fantasy while loop:

  x = (< y 0) ?? y++ : y;   // evaluate y++ while (< y 0), then yield y.
Variable binding:

  x = let (int x = 3, double y = 3.0) : (x++, x*y);
The problem is that some things can only be done with statements.

The ternary operator is not actually lacking anything; with the comma operator, multiple expressions can be evaluated. What's lacking is the vocabulary of what those expressions can do.

Re:The Idea of Lisp by heywire on Friday December 16, 2016 @11:12AM (#13194205)
I've always read ternary statements to myself as a question.

  some_condition ? this : that
some_condition? then this, otherwise that

Typing this, I realize how hard it is to explain without speaking it :)

Re:The Idea of Lisp by lawpoop on Friday December 16, 2016 @12:57PM (#13195229)
Is the color red? If so, this; otherwise, that.

It's a little tricky, because in the above, the `if` keyword appears after the question mark.

Is the color red? Yes-- this: no-- that.

Trying to make a parsimonious English sentence while maintaining the syntax elements : P

Re:The Idea of Lisp by kbutler on Friday December 16, 2016 @02:58PM (#13196234)
> some_condition ? this : that

Just read it as:

  IF some_condition THEN this ELSE that
Re:The Idea of Lisp by junke on Friday December 16, 2016 @11:32AM (#13194402)
You compute baz in both branches, you can refactor.

    x = baz(if (something) foo() else bar())
Re:The Idea of Lisp by tacostakohashi on Friday December 16, 2016 @12:10PM (#13194763)
If you insist on the assignments:

x = something ? ((a=foo()), baz(a)) : ((b = bar()), baz(b));

Otherwise:

x = something ? baz(foo()) : baz(bar());

Re:The Idea of Lisp by vertex-four on Friday December 16, 2016 @01:27PM (#13195468)
a and b have to be defined before the statement containing the terniary expression here. And the point is that you can embed arbitrary multi-statement logic in your if expressions in Rust in the same way you'd do it anywhere else.
Re:The Idea of Lisp by pg314 on Friday December 16, 2016 @01:49PM (#13195666)
Tcl does have a lispy feel to it, but s-expressions in Lisp are much more elegant than strings in Tcl, imho. Greenspun called Tcl the Lisp without a brain[1], which can be taken both as a compliment or an insult.

[1] http://philip.greenspun.com/tcl/introduction.adp

Re:The Idea of Lisp by jjnoakes on Friday December 16, 2016 @02:08PM (#13195822)
Tcl commands are lists, not strings. Or more precisely, they are coercible to strings or lists, but a well-formed Tcl command string is always coercible to a well-formed Tcl list (not all Tcl strings are coercible to lists).
Re:The Idea of Lisp by pg314 on Friday December 16, 2016 @05:02PM (#13197292)
Thanks for the correction. It's been a while since I used Tcl and my memory of it was incorrect.
Re:The Idea of Lisp by kevin_thibedeau on Friday December 16, 2016 @10:23PM (#13199005)
It used to be strings all the way down before the object system was implemented in 8.0.

That incidentally is part of the reason why the expr command was created to process infix expressions since it would be too costly to keep converting sub-expressions back and forth from strings to numbers.

http://www.tcl.tk/software/tcltk/8.0.html

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @09:38AM (#13193474)
TCL, while it has its warts, is a really cool language. I mean, it even basically has fexprs, something most Lisps put by the wayside years ago.

When you don't actually care about speed, you can do some pretty cool stuff.

Re:The Idea of Lisp by pjmlp on Friday December 16, 2016 @09:49AM (#13193555)
Yes, I worked on a startup that did pretty much something like Ruby on Rails, but with TCL, inspired by AOLServer.

The speed critical parts were written in C and loaded as TCL extensions.

Back in the first .com wave.

It also taught me to never again use a programming language without JIT/AOT compiler on their standard toolchain for heavy loads.

Re:The Idea of Lisp by vram22 on Friday December 16, 2016 @11:43AM (#13194511)
Interesting. There was this company called Vignette (in the same period). They too were doing .com projects for clients, and, IIRC, using AOLServer which I read was in Tcl. Tcl was used for the projects.
Re:The Idea of Lisp by pjmlp on Friday December 16, 2016 @12:23PM (#13194894)
Yep, some of our guys went to work for them in projects across the Iberian Penisula.
Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @10:27AM (#13193863)
That's a good idea.

Although they've been working on TCL perf (and even compilation) and there have been some improvements, especially when you're not doing metaprogramming. But still, using it on heavy loads isn't a great idea...

(I mean, honestly. I'm starting to think picolisp might be faster, and picolisp has 3 types and one data structure. Haven't run the benches yet, though.)

Re:The Idea of Lisp by jabl on Friday December 16, 2016 @11:48AM (#13194550)
Hmm, was that the one headed by Phil Greenspun? Arsdigita or something like that...?

Back in the day, aolserver w/ TCL + (open)acs + pgsql/oracle was teh awesomeness compared to LAMP that everyone else was doing. Oh well... :(

Re:The Idea of Lisp by pjmlp on Friday December 16, 2016 @12:22PM (#13194885)
No, in Portugal.

We were eventually acquired by a company doing helpdesk and CRM software.

Re:The Idea of Lisp by mroll on Friday December 16, 2016 @09:45AM (#13193526)
Yeah the level of dynamicness (dynamism?) you can get in tcl is unparalleled as far as I can see. Having no types or syntax and access to the entire runtime at any point in the program opens up all kinds of crazy doors. But you're right, that slows it down.

But you might be interested to know there is currently an effort to get Tcl to compile to native/near-native code. Here is a paper on the new techniques being developed and a link to a talk given by one of the lead tcl core team members.

http://www.tcl-lang.org/community/tcl2015/assets/talk14/TheT...

https://www.youtube.com/watch?v=RcrqmZV88PY&t=38s

Re:The Idea of Lisp by goatlover on Friday December 16, 2016 @01:42PM (#13195585)
I believe IO lets you do the same. Everything is a prototype with slots, communicating via messages.

I guess Self was the same way. Self & Smalltalk also give you access to the entire runtime.

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @02:03PM (#13195774)
But TCL actually goes beyond that.

Most languages of this sort, like Smalltalk, Lisp, and especially slower, more liberal implementations like PicoLisp, allow for compile-time and/or runtime AST transformation, and other sorts of metaprogramming.

in TCL, everything is a string. Or at least, everything behaves like a string in the proper context. When you pass code blocks into a command (like if, or while, or whatever), you're not passing code objects: you're passing unevaled strings. This is why expr works in TCL: there's nothing special about expr, it's just actually implementing a DSL (sort of) rather than evaling your code straight up.

The practical upshot of this is that unlike smalltalk (I think: Can an ST user actually answer this?), and to a greater degree than LISP and FORTH (;immediate and readtables are a lot more painful to wrangle), you can not only modify the semantics of the language: you can modify the syntax.

Re:The Idea of Lisp by pjmlp on Friday December 16, 2016 @02:18PM (#13195908)
Smalltalk just like Lisp has very little syntax, almost everything is built on messages, including data type creation, conditionals and loops, among other things.

Also you can at any time just completely replace one object by other via the becomes: message.

There are also some cool tricks when metaclasses are used, many of each one can see in Python as well.

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @02:37PM (#13196081)
However, IIRC, unlike Lisp, ST doesn't have any AST transformation or parsing hooks (macros and readtables, in Lisp parlance), so while ST has a lot of the semantic extension capabilities of Lisp (indeed, it's more semantically extensible than some of the less Object Oriented Lisps), it lacks the syntactic capabilities for extension.

However, you know ST better than me. Am I right?

Re:The Idea of Lisp by pjmlp on Friday December 16, 2016 @03:01PM (#13196255)
As far as I can remember no (Smalltalk was long time ago for me, 1995).

But I think there is already quite a few things possible via messages and metaclasses, even if one cannot do actual AST transformations.

After all, the whole image is accessible, so you can dynamically ask any object for its definition, or even compiled code (bytecode or JIT) and change them.

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @04:19PM (#13196949)
>But I think there is already quite a few things possible via messages and metaclasses, even if one cannot do actual AST transformations.

That's true. In fact, there are things that messages and metaclasses can do that you can't do with AST transformations without implementing those abstractions.

>After all, the whole image is accessible, so you can dynamically ask any object for its definition, or even compiled code (bytecode or JIT) and change them.

I still miss this in Lisp. Some Lisps had that, once, but it's uncommon nowadays. it happens in the commercial CLs, but those are expensive. OS CL implementations rarely have good image support (in SBCL, image saving actually corrupts the RAM state to the point of nonrecoverability, and the docs recomend fork(2)ing if you want to save an image and continue your app).

Aside from the proprietary CLs, PicoLisp is the only modern lisp environment that has this kind of dynamic capability AFAICT (and while it does sort of have images, in the form of external symbols, the language doesn't encourage using them like this. Also, calling it modern is a stretch: it has more in common with LISP 1.5 than, say, CL). And the Schemes? Don't make me laugh. Scheme has many strengths, but reflection isn't one of them. It's something that I really wish the Lisps had.

One of the reasons I want to try my hand at implementing Lisp on the Spur VM at some point.

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @10:28AM (#13193871)
Picolisp can match it in dynamism.

Seriously, Picolisp is absolutely insane.

Re:The Idea of Lisp by mroll on Friday December 16, 2016 @10:38AM (#13193949)
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.

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @12:42PM (#13195086)
The functions you're looking for are called `up` and `run` in picolisp.

And before you ask, yes, picolisp has list interpolation (or quasiquoting, in lisp parlance), so you can control which parts of a certain chunk of code will be run when, and in which contexts. It also includes the `macro` fexpr, which makes interpolation more convenient.

Re:The Idea of Lisp by mroll on Friday December 16, 2016 @12:50PM (#13195157)
Wow, very interesting. Thanks for pointing out picolisp!
Re:The Idea of Lisp by vram22 on Friday December 16, 2016 @11:40AM (#13194471)
>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 by mroll on Friday December 16, 2016 @11:56AM (#13194640)
Yes, everything is a string. But you can pass data around anywhere you like without worrying about coercing. A command will receive its data in string representation and treat it however it likes. So when you go to do math with the 'expr' command, 'expr' will treat its arguments as numbers.

    set x 5
    expr { $x + 3 }
'expr' receives x as the string 5 but knows to treat it as an int.

I'm not sure that's a great explanation. Maybe a decent summary of the concept of 'no types' is "the language does not presume to tell you how you can or cannot use your data."

Re:The Idea of Lisp by vram22 on Friday December 16, 2016 @12:32PM (#13194980)
Thanks. Yes, I get it. I had read part of the Ousterhout book. And also Don Libes' Expect book uses Tcl, since Expect is written in it. Had read a lot of that too. Both very good ones. Didn't get to use Tcl in projects though. I'd read some years ago that Tcl was used heavily in the electronics / EDA industry.
Re:The Idea of Lisp by jhbadger on Friday December 16, 2016 @10:40AM (#13193966)
Pity that it became so associated with the Tk GUI toolkit -- half the Linux GUI apps in the 1990s were in Tcl/Tk, and when Tk fell out of favor so did Tcl.
Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @02:05PM (#13195798)
...And with TTK, you can finally have easy-to-write cross-platform UIs that actually look native.

Seriously. If you want a decent cross-platform UI system with minimal effort, which has bindings in just about every language, TK is really worth your time now.

Re:The Idea of Lisp by rogual on Friday December 16, 2016 @03:01PM (#13196263)
Tk UIs will never be acceptably native as long as scrollbars remain a separate control from the thing being scrolled. This stops OSes deciding where the scrollbars should go based on input device and locale.

On OSX in particular, Tk UIs always stick out like a sore thumb for this reason, even with TTK.

Re:The Idea of Lisp by mamcx on Friday December 16, 2016 @02:17PM (#13195898)
I have looked at it but don't find examples that truly look convincing,and the info in the official page look very sad.

http://wiki.tcl.tk/9485

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @07:12PM (#13198103)
That's outdated and unofficial. Look at some examples with ttk.
Re:The Idea of Lisp by mamcx on Friday December 16, 2016 @08:32PM (#13198556)
Ok, but where?

TTK is something new?

Re:The Idea of Lisp by goatlover on Friday December 16, 2016 @01:45PM (#13195615)
Should have been made available on the web by some browser vendor in the 90s. Netscape invented a language, Sun wanted to embed Java, but went with the applet approach in lieu of Netscape, Microsoft put vbscript in IE.
Re:The Idea of Lisp by dopamean on Friday December 16, 2016 @11:24AM (#13194299)
Correct me if I'm wrong but doesn't Ruby have everything (maybe just most?) things be an expression. I always liked

    x = if condition
          something
        else
          something_else
        end
Re:The Idea of Lisp by stormbrew on Friday December 16, 2016 @12:29PM (#13194955)
Everything is an expression in Ruby, yes. Even `class` and `def` and `module`, for example. Though class, as a specific example, returns nil, so it's not terribly useful that it is one.
Re:The Idea of Lisp by junke on Friday December 16, 2016 @01:43PM (#13195593)
In Lisp, "def..." macros, like defclass, defun, etc. return the symbol to which is bound the definition. Not essential, but useful at times. I tend to find Lisp is full of details like this.
Re:The Idea of Lisp by kazinator on Friday December 16, 2016 @01:57PM (#13195730)
Well, Common Lisp!

In the Scheme language, many imperative forms have an unspecified result. For instance, see R7RS 4.1.6: "the result of the set! expression is unspecified".

Also, a related misfeature is that function arguments can be evaluated in any order.

Re:The Idea of Lisp by qwertyuiop924 on Friday December 16, 2016 @07:11PM (#13198097)
Yes, this is one of the things that I really want to punch the SSC for. Assignment should have a useful return value: even C, so often said to do The Wrong Thing, got that right.

But for those of you who aren't scheme programmers, it gets worse: because when RnRS says that the result of something is "unspecified" many implementations take it literally. That's right: in many Schemes, `set!` returns the literal value #<unspecified>. I swear I'm not making this up. It's awful.

To quote Jonathan Gabriel of Penny Arcade: "Baby, why you always gotta make me hit you?"

Re:The Idea of Lisp by junke on Friday December 16, 2016 @02:08PM (#13195824)
Yes, sorry, Common was implied (not claiming it should always be, but here I wrote it without thinking about others). Scheme's unspecified results are annoying indeed.
Re:The Idea of Lisp by bch on Friday December 16, 2016 @09:24PM (#13198785)
Your profile says "Ask me about Tcl".

How?

Re:The Idea of Lisp by mroll on Saturday December 17, 2016 @12:01AM (#13199310)
I don't know many other tcl hackers, and I'm really interested in what the community looks like right now. I put that there to drum up conversation with a tcl hacker.
Re:The Idea of Lisp by bch on Saturday December 17, 2016 @01:23AM (#13199576)
You can reach me via my profile.
Re:The Idea of Lisp by lemming on Friday December 16, 2016 @09:41AM (#13193500)
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.
Re:The Idea of Lisp by corecoder on Friday December 16, 2016 @11:59AM (#13194659)
An easy to follow example is Coffeescript (where everything is an expression), which transpiles in javascript (where not everything is).
Re:The Idea of Lisp by wtetzner on Friday December 16, 2016 @11:39AM (#13194460)
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 by adwn on Friday December 16, 2016 @09:14AM (#13193316)
In Rust, if-else is an expression, and there's no separate ternary operator.
Re:The Idea of Lisp by agentgt on Friday December 16, 2016 @09:18AM (#13193348)
Yep I know. Rust although syntactically looks like an Algol [1] like language it actually barely is one :) . It is more akin to a ML language [2].

[1]: https://en.wikipedia.org/wiki/Generational_list_of_programmi...

[2]: https://en.wikipedia.org/wiki/Generational_list_of_programmi...

Re:The Idea of Lisp by clarkd99 on Friday December 16, 2016 @10:37AM (#13193943)
My current project is over 90,000 lines of C and I have programmed in C since the 1970's (as well as many other languages). I have never used a ternary operator and I think it reads quite poorly. I just use a few lines of easily read code instead. I also never use a do/while construction with the condition at the bottom of the loop. When I need such a construct I just put in an "if" and "break" where ever needed instead. I don't think C should be dissed because of a few unneeded and probably unused features. In C, you can put more than 1 statement on a line if they are separated by a ';' but I have never done that in hundred's of thousands of lines of C code.
Re:The Idea of Lisp by flogic on Friday December 16, 2016 @12:41PM (#13195072)
I don't program in C but I use the ternary operator quite regularly. It's quite handy when you're populating large data structures. For limited use in that case I don't find the readability that diminished maybe even enhanced.
Re:The Idea of Lisp by arethuza on Friday December 16, 2016 @09:48AM (#13193551)
It's been a while since I used Common Lisp but isn't it recommended to use "if" for conditional expressions and "when"/"unless" for conditional statements?
Re:The Idea of Lisp by TeMPOraL on Friday December 16, 2016 @10:01AM (#13193661)
It's a matter of code readability. "when" and "unless" are expressions too, but they look the best when they're used instead of "if" for single-branched conditionals when you don't care about return value.
Re:The Idea of Lisp by arethuza on Friday December 16, 2016 @10:11AM (#13193751)
Yes - from what I recall it definitely helped to make things clearer to use "if" and "when" appropriately.
Re:The Idea of Lisp by kazinator on Friday December 16, 2016 @12:03PM (#13194697)
The choice exists only if you have a single form to evaluate subject to the condition. If there are two or more, of course this is imperative programming and (when condition form1 form2 ...) recommends itself over (if condition (progn form1 form2 ...)). If there is only form1, either one will do, so then it's down to a decision based on whether form1 returns a useful value and/or performs a side effect.
Re:The Idea of Lisp by Retra on Saturday December 17, 2016 @02:27AM (#13199744)
Probably a bit off-topic: I always get frustrated with C++ because `if` is not an expression, you can't do conditional initialization under RAII easily.
Re:The Idea of Lisp by sorokod on Friday December 16, 2016 @09:50AM (#13193565)
if-else is an expression in Kotlin ( https://kotlinlang.org/docs/reference/control-flow.html )