Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Advantages of Tcl over Lisp (2005) (tcl.tk)
75 points by tonyjstark on Oct 29, 2017 | hide | past | favorite | 41 comments


> For example in order to use a number as argument of a string manipulation function, there is to convert from one type to the other.

ah yes, the coercion of everything into everything that depends on order of application. best feature ever.

another "gem":

> many thinks like HTML, XML, Networking Protocols, are about strings more than they are about lists

all these things are about a very structured often deeply nested pieces of data. pretty much a direct opposite of the string type.


"Tcl is a programmable programming language like Lisp, in both you can write new control structures, and more generally it's possible to specialize both the languages. But while in Lisp is usually needed to write macros, in Tcl you have to write normal procedures."

You can write normal procedures in Lisp too -- for new control structures even. In fact, macro use in Lisp is usually discouraged unless you really need them, and in most cases you really don't. When you really do, they're nice to have, though. It's too bad that when you really need them in other languages, they're not there.

"Lisp has types, more or less like Python and Ruby. For example in order to use a number as argument of a string manipulation function, there is to convert from one type to the other."

I'm not sure I see the point. You have to convert strings to numbers and numbers to strings in Lisp too. Lisp has types. You can even get static types in Lisp, if you want them - like with Typed Racket.[1]

"In Tcl serialization just happens for many types because almost everything has a string representation. You can write a Tcl list in a file just with: puts $fd $list. This is not possible in Lisp, where you need to perform serialization."

You can write a TCL list to a file? You mean a TCL string to a file? Lisp can just write strings to files too.

"Lisp central data type is the list, while Tcl central data type is the string. Tcl also makes a lot of use of lists that are just special strings. In today's world, to have strings as base type is usually more useful, because many thinks like HTML, XML, Networking Protocols, are about strings more than they are about lists. To deal with strings in Lisp is not as natural as with Tcl."

The thing is, you don't necessarily want to deal with strings in Lisp (and arguably even in TCL). You want to deal with higher level abstractions such as tags, elements, and so on. The underlying representation as string or list is less important, and can sometimes even get in the way (such as in some languages which allow buffer overflows when dealing with strings).

[1] - http://docs.racket-lang.org/ts-guide/index.html


The need to write macros rather than procedures in Lisps for meta-programming is a conscious one. Once upon a time, in ancient Lisp, it was done in the TCL way. A programmer-defined function called a "fexpr" would be called by the interpreter to handle an unknown form. Having access to its syntax, it could give it any meaning.

Macros work under compilation, and handle interpretation situations too. (Though not all of them; certain trompe d'oeil tricks are possible with fexprs, since they can have access to the contents of the run-time lexical environment, and the syntax, simultaneously, making it possible to interpret the syntax in a way that depends on the run-time value of a variable.)

You're not going to make anything better than Lisp in a programming language by resurrecting hacks that were consciously discarded as a bad design decades ago.


I agree with your specific point, but it's important to remain open to exceptions to the general point.


Re: "Lisp has types, more or less like Python and Ruby

The point is probably that the author regarded it as a disadvantage if a language has types other than the character string.

"Hey look, TCL is better than Lisp for some of the same reasons it is better than Ruby and Python: no damn types."


> You can write a TCL list to a file? You mean a TCL string to a file? Lisp can just write strings to files too.

No, the point is that almost all TCL values are represented as strings which are also valid literals for those values. This is where the similarity with Lisp comes from: Lisp is a language where the syntax is the representation (you write the AST), whereas TCL is a language where the representation is the syntax (you operate on the string).


So all func calls are actually calls to eval?


Again TCL kind of has the opposite perspective: all evaluation is text substitution.


apply actually, which is the eval form for functions. Calls a function with a list of arguments


yes, although there are compilers which statically deconstruct as much as they can


> You can write a TCL list to a file? You mean a TCL string to a file? Lisp can just write strings to files too.

To expand upon this, Lisp can write its lists to files (and most other things out of the box) which it can then read back from files and then eval. This is what Lisps mean by a printable/readable object.

In Clojure:

    (spit "foo.clj" '(defn foo [] "CONGRATS! YOU CALLED FOO!!!"))
    (load-file "foo.clj")
    (foo) ; => "CONGRATS! YOU CALLED FOO!!!"
In Common Lisp:

    (with-open-file (f "foo.lisp" :direction :output)
           (pprint 
             '(defun foo () 
                "CONGRATS! YOU CALLED FOO!!!!") f))
    (with-open-file (f "foo.lisp" :direction :input)
           (eval (read f)))
    (foo) ; => "CONGRATS! YOU CALLED FOO!!!!"


Serializing code like this is a bad example, because you need to introduce eval into the loop, which is another step entirely from printing and reading objects. Consider this example, from REPL interaction:

  CL-USER> (with-open-file (f "/tmp/makapaka"
                            :direction :output
                            :if-exists :supersede)
             (pprint '(a potentially (complex data structure)
                       mixing lists #(and vectors) 2/3
                       #C(2 5) and stuffs) f))
  ; No value

  CL-USER> (with-open-file (f "/tmp/makapaka")
             (read f))
  (A POTENTIALLY (COMPLEX DATA STRUCTURE) MIXING LISTS #(AND VECTORS) 2/3 #C(2 5)
   AND STUFFS)
In this example, I printed and read back a list containing symbols, lists, vectors, rationals and complex numbers.

Basically: the reader converts strings to Lisp objects[0]. The printer converts Lisp objects into strings. When we say that an object has a "readable representation", it means that if you feed the result of the printer into reader, you get the same object back.

The evaluator (which I didn't use here, but OP did) evaluates Lisp objects (not strings!), and can e.g. introduce a new function to the environment when evaluating a defun form, i.e. a list of form (defun name (args...) "docstring" code). It is not needed (in fact, it is discouraged[1]) when all you care about is writing and reading back Lisp objects.

--

[0] - Note it's the same reader that actually reads your code when you compile/load file or use a REPL.

[1] - The usual eval-on-untrusted-data code execution vulnerability. Note that since the reader is mostly used to process code, by default it allows you to use the #. read-time-value reader macro. If you READ a string like: "(1 2 #.(* 2 2))", you'll get a Lisp list (1 2 4), since #. basically means "pipe the next s-expression to eval, and return that". When you use reader/printer for serialization/deserialization, you usually want to disable #. for those invocation of read function, by setting

  *READ-EVAL*
variable to NIL.


> You can write a TCL list to a file? You mean a TCL string to a file?

No - and I think this is entirely what the comment about Lisp was about.

In tcl, there is no distinction.


I was surprised when I started working at aol a few years ago how much of the legacy infrastructure runs on tcl. They had a configuration management and process load balancing system that was written in the 90s that as far as I know is still being used to push out updates to stuff like AIM to this day.

It might be interesting to hear one of the old school aol guys talk about it now that they’re decomming a lot of that finally. There was a lot of interesting stuff there that should have been open sourced decades ago and never was.



Some more information...

AOLServer was actually bought by AOL; originally it was NaviServer. It was open sourced in 1999 by AOL.

It's a fantastic server, imo, and some of the technology developed for it were eventually brought into the Tcl core (not exactly, but the general approaches) when multi-threading was added. At least, that's my understanding.


AOLServer was great! I used it for a ton of stuff, the most complex being a marketplace for data. It was almost trivially easy to do fast, maintainable, programmable business logic as part of a complex web site. Having to switch over to the likes of Flask on Apache (not that Flask isn't a decent framework) was a major step back for development, testing and maintenance.


Wow, that takes me back! Wrote a fair bit of code on AOLserver.


Yeah I know about that, but there was a lot more sort of devops before devops was a thing tools written in tcl as well there.


What sorts of things did these tools do?

I'm obviously aware you can't be precisely specific, but I imagine that the level of detail you _can_ share is probably still very interesting.


One of the most popular "devops before devops was a thing" tools was Expect, which simulated an interactive session over Telnet or SSH. It effectively allowed ops to automate anything that could be done in a terminal.


Expect is a great tool and was widely used for such automation (including by EDA companies - along with Tcl), I've read. I tried it some and read the book about Expect by Don Libes, Expect's creator. A very good book, with a unique writing style, that I somewhat can't find words to describe well.


Do you know anyone at AOL who might be receptive to a request to open source their legacy Tcl code?


This may or may not be what you're looking for (you may already be aware of this), but check out the sibling comment in this subthread.


As I recall, a fairly generic critique of lisp is that as a language of incredible power and open structure, you wind-up with many implementation of many functionalities in many libraries but few of them are finished and the API for these tend to not be very well defined.

See;

http://www.shenlanguage.org/lambdassociates/htdocs/blog/bipo...


You are describing any open source library written in someone's spare time.

And this essay is such baloney I don't even know where to start.


I find it helps starting with the most egregious issue/concern first. Otherwise your argument is merely an appeal to self-declared authority.


That's what the essay is doing. But in my more than 10 years (not 20) of using Lisp I have seen nothing to support the hypothesis, let alone to diagnose a psychiatric condition to a group of people.

Then there is this gem "If you read many posts discussing Lisp (including one in comp.lang.lisp called Common Lisp Sucks)" ... " The problems are soluble (Qi is a proof of that for God's sake), but when you're down everything seems insoluble. Lisp is doomed and we're all going to hell."

Lisp is doomed because nobody likes his pet project or appreciates his insults. This essay is just one big insult, I'd prefer people stop disseminating it.


1++


There's an article about graph processing in java from the early 2000s. Author tried a few java libraries with exhaustive APIs, all were cumbersome, cemented and incomplete. He ended up hacking a better one out of cons lists that did more faster and shorter.

I think Lisp lives way too far from the "proper" engineering practices to fir in the reading grid.


I also love Lisp and I understand your point of view about the way Lips is not so nice with strings, which are the main data of the web. What do you think of such an approach based on strings and regular expressions: http://lambdaway.free.fr/ ?


This is so misleading that i don't know where to start. Don't get me wrong, i wish more people would take a look at Tcl, because it has clever tricks. But this page is puzzling:

>But while in Lisp is usually needed to write macros, in Tcl you have to write normal procedures

Well, in Lisp, macros are written... basically in the same way as normal procedures/functions. The difference is minimal: Use the quasiquote and comma operators (for something that can be described as "code templating"), and make sure to use "gensym" whenever you need to generate a symbol (and don't want it to collide with other existing symbols.) That's it.

The rest is just as if writing a normal function.

>Lisp has types, more or less like Python and Ruby. For example in order to use a number as argument of a string manipulation function, there is to convert from one type to the other.

This is because Lisp is strongly typed, which is universally regarded today as a Good Thing.

>strings as base type is usually more useful, because many thinks like HTML, XML, Networking Protocols, are about strings more than they are about lists.

There are many things wrong here. In Lisp, if you need to deal with HTML or XML, instead of having to be losing time doing string operations, you just write HTML or XML directly in your code as s-expressions (take a look at most of the libraries for outputting HTML in Lisp).

Thus, you do it the high-level way.

>The Tcl world is less fragmented. There aren't a big number of implementations of Tcl

I wonder if this is truly an advantage for Tcl. Common Lisp has a dozen implementations and your code will run unchanged in all of them, as long as you don't use implementation-dependent features (And for them, there are already many portable libraries, so those features are not implementation-dependent anymore.)


> I wonder if this is truly an advantage for Tcl.

I wonder whether it's even true of Tcl. Tcl has had moving target semantics over its lifetime so in fact there are multiple implementations of Tcl. How well does the current Tcl emulate previous versions, so that code can run unmodified, and how far back does that go?

Here is a Tcl page that lists some semantic changes from 7 to 8:

ftp://ftp.tcl.tk/pub/tcl/doc/compiler.html

Even though many of the changes are for the better, yikes!


Personally I found Lisp and scheme (I'm lumping them together for their similarities) confounding to get into. There are many, many different implementations, and it seemed to me you are adopting a culture and specific ecosystem more than anything. To my mind, it was difficult. Tcl seemed much less fragmented to me. There is one canonical implementation of Tcl, managed by the Tcl Core Team (TCT). There is (at least) one popular re-implementation (Jim Tcl), interestingly enough originally implemented by the author of the original article we're discussing here.

Re: backward compatibility... I'd say Tcl is remarkably stable. A core tenet is "everything is a string" (EIAS), and logically, this has been honoured. Originally (before Tcl 8, or 8.4(?)) internal components of Tcl were literally strings. As in C "char " strings. It is (and has been) byte-coded for a long time now, and uses Tcl_Obj internals, with a string representation, and a high-performance "native" representation as well. It does still logically behave as if EIAS, though.

That cited doc you mention doesn't actually seem to have a bearing in reality for some of its assertions, to my eyes. It would perhaps have "gotchas" for authors/users of scripts, but doesn't invalidate the EIAS core tenet. Additionally, that document was last edited 20 years ago. It's ancient, as is Tcl < 8.0.


>found Lisp and scheme (I'm lumping them together for their similarities) (...) there are many, many different implementations

You are lumping them together, as you mention, but they are very different precisely on this regard: Scheme has a lot of very different implementations but code portability is an issue, while Lisp (Common Lisp) has a dozen implementations but code written in CL will generally compile and run straight away in any of them, due to language standarization.

Another lisp-like language to consider is Clojure, in its JVM implementation.


Thanks. I was actually more attracted to scheme, then did become a bit confused, but maybe I should just head over to lisp and check harder to see what's what.


Scheme is good, easy to learn and flexible; don't get me wrong: i just wanted to remark that it isn't very portable.

It isn't difficult to jump from Scheme to Lisp and viceversa; they are similar in many aspects.

If you want a quick comparison between Common Lisp and Scheme it would go like this: Common Lisp is a standarized, extremely powerful and flexible programming language; while Scheme is a do-it-yourself kit for creating your own extremely powerful and flexible programming language.


That all said, Tcl isn't fragmented.


TiVo chose Tcl and in fact started as a Tcl house when I was there, cutting tons of Tcl and still do to this day.


iirc, the very first version of redis was written in tcl, wasn't it?


Yes, and the author of the linked article is the author of Redis.




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

Search: