Advantages of Tcl over Lisp (2005)
wiki.tcl.tk
wiki.tcl.tk
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.
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).
No - and I think this is entirely what the comment about Lisp was about.
In tcl, there is no distinction.
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!!!!" 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.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.
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."
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).
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.
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.
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.
See;
http://www.shenlanguage.org/lambdassociates/htdocs/blog/bipo...
I think Lisp lives way too far from the "proper" engineering practices to fir in the reading grid.
And this essay is such baloney I don't even know where to start.
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.
>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 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!
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.
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.
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.