Tcl/Tk 8.6 released (now stackless, w/coroutines, tailcalls, and more)
tcl.tkTcl Rule 1: Everything is a string. Tcl Rule 2: See rule 1. Tcl Rule 3: Not joking.
While the EIAS philosophy is true in Tcl, at the real guts level, the actuality is "Everything must be representable as a string". EMBRAAS it! There is an object system underneath which handles native or user defined types.
It's worse than that, unfortunately. Everything is implicitly convertible to a string, and every string is implicitly convertible to any other type. So, if you pass a dictionary into your function that expects a list, it will happily convert between types for you. I do not like this sort of behavior in my dynamic type system.
(Apologies in advance, I'm just thinking out loud here, not meaning to troll.)
So you like strong typing. I do too, but I like it even more at compile time. If you're doing without the compile time error checking, why not go all the way and do without type errors at runtime as well? Sounds like a choice between:
1. type errors at compile time,
2. data-dependent type errors at runtime, or
3. data-dependent corruption and/or non-type errors at runtime.
> I do not like this sort of behavior in my dynamic type system.
Why? [Other than for performance reasons]
I keep repeating this point in every Tcl thread. Tcl was meant to be used to enable command line shells for programs written in C.
Btw, being able to treat a list as a dict has been useful to me. I (developer) write a routine to be used by a non-developer, who may not be a great programmer. The list notation is easy in Tcl. I can just tell them to make a list with keys and values alternating. And for a one-time conversion cost, I get to use it as a dict.
Also works the other way around: I can return a dict. And if a Blub user is processing it, he's free to ignore my documentation that it's a dict and process it as a list (again for a one-time cost).
YMMV.
> Why? [Other than for performance reasons]
Because it becomes very hard to reason with what you have at hand, and in my experience the "helpful" conversions, rather than actually help, mostly hides errors and bugs in the code and delays there effect, making them much harder to diagnose than a stricter handling.
Tcl's EIAS can be annoying at times, but it also allows for an amazingly easy to use language that provides for some amazingly powerful abilities. For example, the ability to build arbitrary control structures with little effort. Most other languages, dynamic or not, can't come close to it's flexibility and some of the things you can do with it.
But a dict is a list of paired elements? I do like the fact that you can convert freely between string/list/dict. It removes a lot of boilerplate type conversion. Want to serialize a dict? In most languages that's boring code. In Tcl it's so easy you do it all the time.
> But a dict is a list of paired elements?
Not really. A dict is an unordered set of keys where each key has a value associated with it. If you try to access a dict as a list, you might expect to get a list of key-value pairs or a list of values or possibly a list of keys. And in what order will the elements in the list be?
Tcl dicts are ordered, so you have a defined order for this. http://www.tcl.tk/man/tcl/TclCmd/dict.htm#M27
Depends on the language, but I prefer the Python approach here. Python is a dynamically (but strongly) typed language. If you want a list from a dict, get a new list via casting ie. list(the_dict), or get a list from either side via the_dict.keys() or the_dict.values(). Weakly typed languages that will do implicit type conversion for you such as TCL and Perl seems prone to mistakes and confusion from this stuff as code complexity of the project grows. I don't think Python gets it right here either though really, as in the end explicit types save so much headache and stupid bugs by finding problems for you at lint or compile time.
It's not a problem in Bash, why is it a problem here? Right tool for the job...
It's not a problem - it lets you do some really neat things that you just can't do in other languages easily. But it is a very very true thing about Tcl.
I was generating functions procedurally, and I was having a scoping problem with one of the inner variables. Naturally, the suggested solution was to do a string replace on your newly created function. Seems obvious in retrospect. :)
Because most people have enough sense to keep bash scripts to a few hundred lines at most and switch to a saner language for anything more complex. In a language like TCL intended for larger-scale development it's just a bugfest waiting to happen.
It's kind of a moot point though. Javascript is unstoppable in the extension language space now.
Really? I've never seen it used as an actual extension language. I've seen Lua, I've seen Scheme, at work we do everything in Python (but that's more extending than embedding), but I've never seen JavaScript as a "extend this C or C++ application" language.
I'm not counting node, because it only exists to run JavaScript. Nor am I counting web browsers, for similar reasons.
Can you give some examples? PDF is the only one I can think of. Most of the existing JavaScript engines seem too heavy-weight to be used as extensions.
Since I'm not in the web-developer bubble, I just don't see JavaScript all that often.
Embedding Javascript is fairly easy with Qt[1], so I assume that many applications built on top of it may use it.
Thanks for the link; I'd forgotten about Qt and JavaScript, which is funny, since I was just thinking about learning it.
The explicit tail calls look pretty neat. All languages should include this, or something like it, I think; tail calls come in handy for all sorts of things. Making it explicit sidesteps complaints about how it will impede debugging, and ensures programmers will definitely get it where they want/expect.
I think this would be a chance to rehabilitate the much-maligned GOTO keyword. But "tailcall" is probably just as good.
I think this would be a chance to rehabilitate the much-maligned GOTO keyword.
Perl has used "goto &foo" for that exact purpose for ages. It just became yet another random feature that experts know about, regular programmers ignore, and critics use to show how terrible the language is.
And there are a few CPAN modules for those who are squeamish about using goto :)
Python language creator Guido von Rossum prevents CPython from having tail call optimization because he doesn't want people to use it.
http://neopythonic.blogspot.com/2009/04/tail-recursion-elimi...
Well, to be trollish :), he also didn't want it because:
1 - With TCO, there would be no more "recursiveFunction recursiveFunction recursiveFunction" x 1000 stack traces. Which apparently is bad. Might force someone to use a debugger, you know.
2 - Non-standard Python implementers won't be competent enough to code it, so it's best he doesn't force them to.
3 - He doesn't believe in recursion. He doesn't like it. I mean, the look of it. It's too nerdy.
4 - He made a bad choice in basing his language in dynamic binding. He recognises it, says it's horrible style, un-pythonic, but won't make it go away because users, users, yadda yadda. All this from someone whose job description is BDFL ;)
Yeah, I'm bitter about some minor quirk no one cares about, but... you know, I might have preferred a "I can't be arsed to do it" answer. Those arguments are pretty laughable.
I wonder if he would claim the same argument today as he does in this[1] comment, in particular the paragraph "On side effects being bad <..>".
I would dare to claim that there's some trend to do things more side-effectlessly not only in programming, but also in general, people in IT are finally realizing* that the more isolated, light-weight and modular things are (think of increased interest in functional programming (pure functions), dominance of cloud-based/inspired solutions (spinning up small instances of VMs)) the better. Somehow this particular mindset helps at all levels.
Hah, there's actually a term for what I'm trying to describe: Shared nothing architecture[2]. Allowing side-effects on any level implies "sharing" to me.
[*]: of course you could say "this has always been the case", but somehow some years ago Java and the friends seemed like the only "enterprise level" solution to most businesses and the general fat-stack+vertical-scaling seemed somewhat reasonable.
[1]: http://neopythonic.blogspot.nl/2009/04/tail-recursion-elimin... [2]: http://en.wikipedia.org/wiki/Shared_nothing_architecture
I don't think the world of software development changed at all since 2009. It takes about 15 years to see noticable shifts in practices.
Also, shared-nothing "architecture" goes back to the 60s with the first investigations into concurrency. In fact, if I were being pedantic, I would say it predates computing itself: logic is all side-effect free.
Sure, theoretical investigations on things begin many years earlier than anyone starts actually using them, but somehow "concurrency" wasn't something available to your everyday Joe back in 60s, right? Multi-core wasn't the norm, there was no elastic cloud, what so on.
And I am not really claiming that software development changed much in 3 years, but I think people's mindsets are changing faster than that, especially of those who are actively involved in thinking about these things.
Fair point.
I clicked that link ready to laugh, but he makes a persuasive argument. I feel like I've been tricked.
His choice, he is the BDFL after all.
Congrats, Tcl/Tk team! A long wait, but it seems to be worth.
Is this the programming language that works without a lexer/parser and a grammar? Why aren't there more programming languages written this way? Seems easier to implement.
The parser's behavior is not specified except in the implementation, which is messy C. I was once loosely involved in a project that tried to reimplement it, which turns out to be extremely difficult, and was laughed at by Brent Welch. Indeed, it failed on countless edge cases. lex and yacc (or whatever) at least isolate this part of the language, making it much easier to have more than one implementation.
Tcl's syntax is completely specified in the man page: http://www.tcl.tk/man/tcl8.5/TclCmd/Tcl.htm (well, nearly completely -- there are couple of minor details left out -- but the man page is complete enough to fully understand the syntax. More people should read it.)
Messy C? Most people who've worked on it seem to think it's rather clean. (Not the bytecode compiler though -- that is indeed a mess. But most of the implementation is solid, readable code.)
Tcl's C implementation is far from messy. Its actually one of the best commented C based language code bases i have ever seen. But your project was doomed by false assumptions. (oh, and Tcl has more than one implementation, e.g. there is a version based on Parrot for example, http://code.google.com/p/partcl/ or the JACL interpreter based on the JVM).
the point is not so much ease of implementation (a parser for a reasonable grammar is usually an insignificant part of a language implementation) as is homoiconicity, and thus easy extensibility. in this regard tcl is similar to lisp and forth (despite all three having different foundations).
that's an impressive set of changes for a minor release! :o)
is there a paper that describes the underlying implementation (with the new stackless stuff)?
I don't know of a paper, but on the Tcl wiki there is some discussion of the "non-recursive evaluation" (NRE) engine that enables these features [1]. More formal descriptions of the new coroutine [2] and tailcall [3] commands are listed, among others, here [4].
1. http://wiki.tcl.tk/37253#pagetocbefb5a57
2. http://www.tcl.tk/cgi-bin/tct/tip/328
3. http://www.tcl.tk/cgi-bin/tct/tip/327
Update: more details on the NRE implementation are available here [5] at the contributing author's site; anonymous login required.
Tcl's "minor" or point releases are bigger than most languages'. 8.6 has been in development for about four years. 8.5 was also in development at least that long. Contrast Python, which does a point release every 18 months or so.
The TIP#257[1] (Tcl Improvement Proposal) explains how rich and thought-out the TclOO component is. Endless possibilities. It's a nice read to learn more about OO-concepts like filters, mixins and meta-classes.
Some might ask how TclOO compares to iTcl's. For one the performance is in another league.[2](Version 0.3)
I lurk on the core list so I got to watch discussions relating to 8.6 stuff. It was pretty cool. There was a lot of thought about what went in and what needed to to be tweaked.