I got to write some of the updates in this 2nd edition regarding the C interface:
https://www.oreilly.com/library/view/tcl-and-the/97803216017...
Too much code being rewriten from Tcl into C for performance and scalabity reasons, and it still doesn't have a proper JIT.
Now as a way to script C code, it is even easier than CPython.
(we did exactly this for networking code about 30 years ago: C for the data plane and Tcl for the control plane. That architecture remained in service for decades.)
31 points|pmarin|16 years ago|17 comments
https://news.ycombinator.com/item?id=389107
181 points|zeitg3ist|12 years ago|110 comments
https://news.ycombinator.com/item?id=4920831
131 points|throwaway344|11 years ago|45 comments
https://news.ycombinator.com/item?id=7069642
182 points|goranmoomin|2 years ago|79 comments
This means that "" and {} are expected to work a certain way from C and when you hit Tcl you are HORRIBLY confused.
It's especially confusing as {} is simply quoting and has nothing to do with scope. The fact that Tcl is written such that {} is used with indentation in if-statements muddies the issue even further.
I suspect that a choice of ` (backtick) for Tcl " and " instead of Tcl {} would have made Tcl way less confusing to the vast majority of programmers.
I understand why things weren't done that way--having the ability to know that your quote has different characters for open vs close is very valuable for efficient parsing.
Nevertheless, the Tcl choices were unfortunate given the way history played out.
Scopes are special syntactic forms that delegate variable substitution to the associated procedures. For example, a "for" statement evaluates the body of the function after substituting the loop variable. In a string based language, that's basically the same as expressing the scope in a string form where the string content is passed verbatim as an argument without variable substitution or function invocation.
Having used Tcl extensively back in the day, I am not sure that this syntactic cleverness really was a major impediment to adoption. It was just something to learn. Same was true with [] meaning lisp-like function calling rather than array definition.
Baseline Tcl's biggest challenge, in my opinion, was providing mechanisms to write modular code for larger programs and data encapsulation. Core Tcl put off decisions about the appropriate mechanisms to do so by only providing "namespaces" as a building block for higher level third-party syntax. That led to fragmentation at a time when other languages were gaining popularity.
I don't know if something about tcl's design precluded lexical scoping and a normal "var" keyword. But "upvar" definitely seems like a smell.
Unfortunately most fall for the more popular Clean Code and it's derivatives.
Edit: The book is "A Philosophy of Software Design"
Reading through this article, the memoize implementation does have an issue which is if the memoized command wants to call uplevel or upvar it'll get the wrong stack frame. If I were writing this I'd structure it so it's used like
proc myMemoizingProcedure { ... } {
memoize {
... the rest of the code ...
}
}
such that it can just `uplevel` the code. Or better yet I'd make `memoize` replace the `proc` keyword (or perhaps `memoize proc myMemoizingProcedure …`).EDIT: I suppose memoizing makes no sense in a procedure that wants to use upvar or uplevel though, because memoizing only works for pure functions.
https://wiki.tcl-lang.org/page/Closures
https://wiki.tcl-lang.org/page/Emulating+closures+in+Tcl
TCL 9 has surely fiddled with tcl_ObjType I hope, but it doesn't seem like it from a glance.
type Point struct {
X int
Y lnt
}
Where "struct" maybe could just be a basic macro, but maybe it could also be smart enough to tell the compiler that "lnt" around "Y lnt" is not a type and suggest that maybe you meant "int".I think a lot of this ground was treaded with modern JS compilers (that had to infer a lot of this kind of information from very little context), or efforts like Python type annotations. Dynamic languages are still cool, and even cooler when the compiler can still somehow actively help you.
The last implementation in https://wiki.tcl-lang.org/page/Closures is pretty nice.
https://linux.die.net/man/1/expect
I really like that it, like the article mentions, just looks like config for basic scripts but also scales to whatever you need it to do.
https://github.com/athas/EggsML/blob/master/concieggs/hooks/...
A line that contains a regex pattern for matching regex patterns.
TCL was chosen here because its regex engine isn't too powerful.
Uh, not sure I see the significance but wouldn't that make Tcl less apt for this than something else? Why would you purposely choose a less powerful regex engine?
As a self-taught novice programmer that started with QBasic and had moved on to Turbo Pascal, I found Tcl to be very confusing and it left a rather negative impression.
Reading this page now though, it seems a lot more logical and reasonable than it appeared at the time.
array set foo {
a 1
b 2
c 3
}
If the inability to comment out entries here is a problem, that's also something you can fix, you can write something like proc decomment body {
…
}
such that you can then write the following and it will remove commented lines: array set foo [decomment {
a 1
# b 2
c 3
}]
For a long while, when I might have used Tcl/TK, I instead used Runtime Revolution/Livecode (a cross-platform HyperCard clone) which had a very nice system for interactively drawing programs.
I'd really like for there to be an agreed-upon standard option for graphical program development which was interactive and cross-platform.
Wish also has an interactive mode, not point and click but results are instant, great for learning Tk. No idea if it can work with tkinter though.
It is a bit surprising since it seems like you could use Tcl/Tk to write it.
The Tk canvas makes writing simple drawing programs fairly easy, and a GUI editor seems like it wouldn't be terribly difficult.
I wish there were more of these, preferably open source (and, since I'm dreaming, native and web versions.) ;-)
If you've seen Decker previously you might find it useful to know that it has recently acquired several "escape hatches" for interoperating with software and APIs outside its usual sandbox: http://beyondloom.com/decker/decker.html#thedangerzone
I live in a HiDPI, color world but the 1-bit vintage Mac-style GUI and fonts look nice to me.
https://hypercard.org also has some interesting links.
I think the sandbox/doesn't play well with others issue has affected the use cases of environments from HyperCard to Lisp to Smalltalk. Tcl/Tk seems designed for connecting to other software.
To maintain fidelity between the capabilities of web-decker and native-decker, the constraints of web browsers need to be treated as a common denominator. Some of the ways that conventional webapps circumvent these constraints are not an option for web-decker, because it's designed to function without a server-side component; this avoids dependencies on centralized infrastructure. (There are also some features intentionally left out because they would be inaccessible on e.g. touch-based devices which lack a physical keyboard or the ability to register "hover" events from a pointing device.)
To center user-empowerment, Decker should be "safe by default" and require affirmative consent for things like sending information to remote servers or accessing the local filesystem. If a user understands the risks, they can deliberately shift Decker into a more permissive mode of operation which lets it interoperate directly with local resources, raw browser APIs, etc. By default, Decker can safely run applications written by untrusted third parties, and in "dangerous" mode it is more comparable to a conventional automation tool or scripting environment. This approach may not please everyone, but it is a carefully-considered compromise.
Decker does have paletted color support; many decks produced by users apply this to great artistic effect: https://itch.io/games/tag-decker
Still annoyed about their changing course and removing the Community Edition.
Edit: Just remembered that Tcl/Tk: A Developer's Guide by Flynt has a chapter on self contained executables and the various tools for making them. Have not looked into this book much so can't comment on it.
There is a tutorial on the Tcl wiki which should be reasonably up-to-date - https://wiki.tcl-lang.org/page/Tcl+Tutorial+Lesson+0 .
If you were going to handle "untrusted input", that's how you would do it in tcl.
Note: this is separate from tcl's multithreading capability, where it can also run individual interpreters per thread , with thread safe channels between them. (btw, you can mix & match both approaches - multithreading & nested interpreters)
That's where it gets really criminal: Dynamic scoping rules. There is no lexical scoping and hence no closures. If you use `uplevel`, your procedure works or doesn't, depending on the caller. There is a reason Tcl is the last language that uses this braindead mechanism.
That’s a hot take for one language with basically a sheet to describe it[0], and another whose “rules” are best described by “whatever this implementation does.”