I have been using tcl for almost more than 4.5 years and found it is
very powerful and I can get all I need from TCL. But I am wondering why
many people are using Python and Perl, not sure what are their
advantages, what is the difference from TCL? Any people with experence
of Python and Perl could share your experience? thanks in advance.
/zhenwu
I've written a fair bit of Perl over the years, and it's main advantage
over Tcl has consistently been its greater focus on being a handy
toolbox for sysadmins everywhere. This makes it much easier to do grungy
low-level stuff in Perl than in Tcl, and there continues to be a need
for such things.
Thankfully, not all code needs to be grungy low-level hacks and that's
when Tcl's more apt... ;-)
Donal.
Tcl is more in the way of "symbolic" programming languages like Lisp,
Scheme, Logo.
Most tasks can be done well with either type of language, so the choice
is partly just a matter of taste.
This is an old & sad topic and you will find many threads in this group
about it. Probably it will also start some kind of flame again...
My point of view is (and I did programming in Perl and Python as well):
You can use whatever scripting language you like. All of them will do
the job that scripting languages are supposed to do and there are
virtually almost no differences in technical terms.
Ok, you used Tcl in the past 4.5 years. When it gives you everything
you need and you are not forced to do it in a different way - then
there is no reason to switch to Perl, Python or whatever. Just stick to
Tcl's simplicity, reliable functionality, stability, consistance and
nice community - and concentrate on getting your job(s) done.
Just my 2c
Eckhard
thanks again!
/zhenwu
-Mike
z...@foundrynet.com writes:
I doubt if the speed difference has an impact in 99.9% of programs, and I
suspect that the succinctness results in hard to maintain code, subtle bugs,
and overall, less productivity than if done in Tcl. Just my opinion.
> I'm learning some Python now. It seems to be easy on the eyes,
> fast, and the better langague, of the three, in which to write
> larger programs.
What constitutes "larger programs", and why is Python the better language of
the three?
If you are churning out hard to read Perl code then I would look at the
coder and not the language.
Python has a "one better way to do it" mentality. Its OO system and
enforced indentation (arguably) lead to a better application "design"
that allows much larger programs to be created. I am not a Python
advocate. It is a good language with good design.
I like Python,
I am looking into Ruby,
I use Perl,
I would rather being doing Tcl.
Robert
"Earl Grieda" <eASQWER...@VADFWEFyahoo.comical> writes:
> "Michael Mellinger" <mel...@panix.com> wrote in message
> news:v5cslrc...@panix1.panix.com...
> >
> > Perl is faster and more succinct.
>
> I doubt if the speed difference has an impact in 99.9% of programs, and I
> suspect that the succinctness results in hard to maintain code, subtle bugs,
> and overall, less productivity than if done in Tcl. Just my opinion.
Certain things are nice in Perl.
($a,$b,$c)=split(/\s/,$_,3); # This idea works when talking to databases too.
@F = split(/\s/,$_,3); # Even less typing...
As for speed, Tcl seems to always rate near the bottom when the 3 are
compared. Hopefully, Tcl will improve with time.
> What constitutes "larger programs", and why is Python the better language of
> the three?
Larger would be several thousand lines where you will be looking at it
several months later and wish you hadn't taken every shortcut. i've
done programs of a few thousand lines of Perl and kept it clean with
no regrets (use strict) . I've done 10k+ lines of Tcl and it's easy
to go back and change. I wish I had Perl's 'use strict' in Tcl.
I'm not a Python expert having only written a handful of programs all
less than 1000 lines. However, it does provide a nice high-level of
abstraction with enough "short-cuts" and a fast implementation where I
feel comfortable that I could whip up a prototype in a few days then
actually grow a full-blown application over several months and have
fewer compromises.
Computers are fast enough that many types of applications can now be
written in scripting langagues. Tcl are both good Python, but I think
Python seems to have a little more going for it, at the moment.
-Mike
I am learning Tcl and Perl, and I would consider Ruby .... but I kind
of dropped Python from list.
There are several reasons that makes a person learn a language, usually
the more respected one is, that it is the language used where you work,
and in a way of a vicious cycle, people learn languages that are used
most at work places.
I don't work as a developer, but I wouldn't mind one day to evolve into
being one.
I am learning programming languages mainly to learn programming in
general.
This helps me in my job as a systems analyst (I collect/document
requirement, test software)
>From my experience, Tcl compared to both Perl and Python, was more fun
and interesting to learn. I do believe I got more insight into how
programming work, or should work, from learning Tcl compared to the
other languages.
The reason I looked into Perl is ... well, one more paradigm to learn,
plus, I imagine I will only need to write to write small programs, that
are a proof of concepts, and I thought that with CPAN and all the
framework being done with Perl, that it would be the most helpfull
As a language Tcl is a lot more logical and cleaner than Perl, program
with Tcl is the libraries, there not enough libraries, and some key
commands like the one used for regular expression are broken, I never
done serious regular expression but from my experience, Perl regex made
more sense.
Python, is neither as fun as Tcl or as practical as Perl, so I really
don't see much going on for it except maybe popularity in the work
place.
Ruby, I heard is fun, logical and is getting more popular than python
thanks to ruby on rails.
So in the end it really depend on you needs and the needs of the people
you intend to server, work for.
Since I am only interested in creating prototypes, and proof of
concepts software, popularity wasn't a big deal for me. Tcl and Perl
made sense. Tcl for GUI, Perl for the web (maypole, catalyst) and
databases (dbi).
> Certain things are nice in Perl.
>
> ($a,$b,$c)=split(/\s/,$_,3); # This idea works when talking to databases too.
> @F = split(/\s/,$_,3); # Even less typing...
Hmm.. I don't know where this is nice - looks like the figures in a
comic when they are cursing...
> [...] I wish I had Perl's 'use strict' in Tcl.
What do you need this silly concept for in Tcl? Tcl is "using strict"
by default.
Eckhard
My idea of an ideal script/program is: less than 72 LOC, so you can see
it all on one printed page; making good use of abstractions and
powerful packages (Img, tdom, ...), and with well-chosen variable
names, but employing underengineering wherever feasible, etc. Compare
this style
###################################
# iterate over the list, print each element #
###################################
for {set i 0} {$i<[llength $k]} {incr i} \
{
puts stdout [lindex $k $i];
} ;# for
to that:
foreach element $list {puts $element}
:^)
The combination of TCL and SQLITe is no slouch in the database field. A
real delight to use because of the tight integration, with capabilities
surprising for such a small package.
Gerry
lassign [regexp -all -inline {\S+} $data] a b c
> As for speed, Tcl seems to always rate near the bottom when the 3 are
> compared. Hopefully, Tcl will improve with time.
You are aware that it is extremely hard to construct a fair comparison?
The problem is, any time someone tries to do something in one language
and convert it to the others for comparison, the advocates of the others
say (correctly) "but you wouldn't do it like that in X". The devil is
entirely in the detail...
Donal.
I have no experience in Perl, so I can't offer any perspective there.
I have dabbled in Python but have always come back to Tcl/Tk. My main
interest is GUI programming, and I find the tight integration between
Tcl and Tk to be incredibly powerful. And deployment of Tcl/Tk
application via starkits/starpacks is wonderfully easy.
When working with Python for GUI programming, I've always found myself a
bit lost. Python has bindings to nearly every C/C++-based GUI toolkit
out there. That makes Python a wonderfully *flexible* tool, and if you
are coming to it from a systems language background (Qt, Gtk, wxWidgets,
win32, Cocoa), it must be very energizing to be able to work in a
higher-level language without having to learn a new GUI-programming
paradigm.
However, if you are starting out with Python, which tookit do you use?
That's where it's easy to get lost, and Python's flexibility becomes
something of a burden.
Now that I'm pretty proficient in Tcl/Tk, it would be pretty easy to
pick up Tkinter (Python's binding to Tk) and concentrate on learning
Python. However, moving to Python/Tkinter from Tcl/Tk doesn't make as
much sense as, say, moving from Gtk to PyGTK. In fact, using Python and
Tkinter seems like just a more indirect (and therefore more inefficient)
way to do what I'm already doing now.
Another thing I've observed about Python GUI applications is that they
are more complex to deploy--tools like py2exe/py2app have more "moving
parts" than starkits/starpacks. And (at least on the Mac) Python GUI
applications are generally *much* larger than Tcl/Tk applications,
because you are automatically wrapping up at least two large libraries
(the Python runtime + the GUI toolkit). A typical Python/Tkinter
application wrapped by py2app on the Mac is around 25 megabytes--and
that's just for the Python/Tcl-Tk frameworks. Starkits reduce that size
to around five megabytes.
This is not an argument against Python. It's a powerful and
well-designed language. But, at least for what I am doing, it offers
little advantage over Tcl/Tk.
--
Cheers,
Kevin Walzer, PhD
WordTech Software - "Tame the Terminal"
http://www.wordtech-software.com
sw at wordtech-software.com
Tcl is the de-facto standard language for software automation testing in the
computer networking industry. The major computer networking vendors must
have a combined total of tens-of-thousands of test cases written in Tcl.
Additionally, the 3rd party test tool vendors all provide Tcl APIs to help
automate their test equipment.
As a side-note, I have noticed that when I interview someone for an
automation position, and they are from a start-up that went under, or a
company that is on its last legs, invariably they say that they use Perl for
software test automation. When I ask why they chose Perl when Tcl is the
standard language for automation they say, "My manager said to use Perl." I
sometimes think that the management incompetence which results in a poor
technical decision might also be prevalent throughout the organization, and
could be why the company is failing to get a working product out the door.
Also, since Tcl is so important for the networking industry the language
needs to get IPv6 and HTTP 1.1 working ASAP.
In the case of Tcl itself, which is in the order of ten times that, it's
an asset.
Sometimes complexity is unavoidable.
--
David N. Welton
- http://www.dedasys.com/davidw/
Linux, Open Source Consulting
- http://www.dedasys.com/
There's already a TIP that proposes IPv6 (http://tip.tcl.tk/162) though
the associated patch could do with review by someone who knows
networking better than me before I call the vote. (It might be nice to
add a few extra bits to the [fconfigure] options while we're at it, e.g.
a simple spot for people to find out if the socket is a v4 or v6 one.)
Work is also needed on a Win implementation (I assume some version of
Win has v6 support, but might be wrong on this for all I know... ;-))
ISTR that there was someone working on a version of the http package
that understood 1.1, but don't remember the details or a reference.
Google thinks http://sourceforge.net/projects/tclhttp1-1/ is the right
spot though. Do they need encouragement?
Donal.
You mean: [chan configure]
:)
--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|
You mean you thought they were different? ;-)
Donal.
Python is in many ways a nice language though I have found it hard to
get used to the use of indentation for grouping. Ruby is nice too and
in some ways more consistent than Python in its object-orientation
though I am occasionally turned off by its Perl-isms.
I always wonder why Pike seems to have so little following. I would
think that the C-like syntax would make it attractive to people who
come from a C or Java background and want the benefits of a high-level
language without having to accustom themselves to a new syntax. Pike is
arguably the nicest of this class of languages when you need to deal
with nasty details of binary data, e.g. for bit-twiddling.
> Michael Mellinger wrote:
> > Certain things are nice in Perl.
> > ($a,$b,$c)=split(/\s/,$_,3); # This idea works when talking to databases too.
>
> lassign [regexp -all -inline {\S+} $data] a b c
I'll have to add this to my little bag of tricks. Which is more
intuitive to you?
-Mike
> Michael Mellinger wrote:
>
> > Certain things are nice in Perl.
> >
> > ($a,$b,$c)=split(/\s/,$_,3); # This idea works when talking to databases too.
> > @F = split(/\s/,$_,3); # Even less typing...
>
> What do you need this silly concept for in Tcl? Tcl is "using strict"
> by default.
Tcl does not have a "use strict" by default. For example, simply
having the option to catch variables that are referenced before they
are declared is very useful. Also, ever have your Tcl code silently
end in a callback because of a simple mistake?
-Mike
Except that such a concept would be completely contrary to the basic
fabric of how Tcl works. There is no "declaration" of variables, in part
because each command doesn't "declare" what's a variable and what isn't.
I've written procedures which parse the MIME headers from a message and
create variables like MIME_subject and MIME_content_type in the caller.
You could say
parse_headers $msg
if {$MIME_subject == "..."} { ... }
How would any tool know that parse_headers is going to create
MIME_subject there?
> Also, ever have your Tcl code silently
> end in a callback because of a simple mistake?
No.
Actually, I'm not sure how a callback would be consider "silently ending".
--
Darren New / San Diego, CA, USA (PST)
Crate & Barrel -
Furnishing Video Games Since 1962!
I've never seen Tcl come out on top on many comparisons. In fact, it
usually ends up being much slower. Don't get me wrong, I also believe
speed isn't the most important factor, but it would be nice to have it
all. :-) There's a Language Shootout somewhere on the net and in most
cases, Tcl loses to Perl and Python.
I quickly tried to look find some comparisons. I see that you've got
a page but some of the links are dead and it's not longer maintained.
http://phaseit.net/claird/comp.lang.misc/language_comparisons.html
-Mike
> I've written procedures which parse the MIME headers from a message
> and create variables like MIME_subject and MIME_content_type in the
> caller. You could say
> parse_headers $msg
> if {$MIME_subject == "..."} { ... }
> How would any tool know that parse_headers is going to create
> MIME_subject there?
Aren't you going to need a global declaration for $MIME_subject? All
Tcl variables are local by default.
proc foo {} {
global MIME_subjct; # Hey a typo
if { $MIME_subject == "A STRING comparison means put quotes around '$var' unless eq is used " } {...}
}
Now wouldn't it be nice to know that you screwed up? Also, what about
the quotes around "$MIME_subject"? I can't remember when you need
them. Let's tell the interpreter that you want a string comparison
(eq). I actually saw somethink like this "silently" fail once in a
market data callback for stock quotes, after having worked for months.
>
> > Also, ever have your Tcl code silently
> > end in a callback because of a simple mistake?
>
> No.
>
> Actually, I'm not sure how a callback would be consider "silently ending".
I can't easily reproduce one. However, the idea is that any
syntax errors generated will silently hang on any syntax errors.
-Mike
--
mmelli...@gmail.com
No. That's what upvar is for. That's precisely my point.
> Now wouldn't it be nice to know that you screwed up?
Sure would. But Tcl doesn't let you detect that before runtime, just
like Perl doesn't let you detect whether the file you're trying to open
actually exists before runtime.
Now, of course you find out you screwed up the very first time you run
that "foo" proc you declared. Shame on you for releasing code you've
never run.
> Also, what about the quotes around "$MIME_subject"? I can't remember when you need
> them.
The rules for when and which quotes are needed are pretty simple to learn.
> Let's tell the interpreter that you want a string comparison
> (eq). I actually saw somethink like this "silently" fail once in a
> market data callback for stock quotes, after having worked for months.
Yes? And? Programs that seem reliable can still have bugs?
> I can't easily reproduce one. However, the idea is that any
> syntax errors generated will silently hang on any syntax errors.
Syntax errors in Tcl are caught as soon as you try to load the file.
Runtime errors cause exceptions to be thrown, which you can catch and
handle as you see fit. I've not seen anything but logic errors cause
infinite loops. I'm not sure why you'd think a syntax error would
silently hang.
This will run forever (if not killed), because with non-numeric "max",
[for]/[expr] does string comparison, and any number, positive or
negative after integer wraparound, is < "bar" ... Simple solution:
proc foo max {
incr max 0
for {set i 0} {$i<$max} {incr i} {puts hello}
}
Should the user use a non-integer, he'll get the justified error
"expected integer but got 'bar'" right away, instead of waiting...
waiting...
> Sure would. But Tcl doesn't let you detect that before runtime, just
> like Perl doesn't let you detect whether the file you're trying to open
> actually exists before runtime.
> Now, of course you find out you screwed up the very first time you run
> that "foo" proc you declared. Shame on you for releasing code you've
> never run.
I think this is the characteristical thing of dynamic languages, to which Tcl
undoubtly belongs. You just need to get common with it that every piece of
code you wrote must be run and tested somehow. This has disadvantage that you
never know if this is correct until you run it, but it is also an advantage
that you must run every part of code before you release it and thanks to that
the whole code is tested.
In case of languages like C++ there is an explicit need that such a language
be compiled and many errors checked statically. Last time I spent about half
an hour to compile what I wrote in C++, but once I compiled, the program was
running since the first shot.
But C++ is NOT a dynamic language at all, and everything you can do
dynamically in that language is explicit and in most cases done with some
complicated ways. That's why such things are possible in C++.
Perl, unlike C++, has many dynamic parts, you can evaluate the script to be
run during runtime, and also most of the things are unable to be verified at
"compile time". So, if we have a scripting language, which is really a
DYNAMIC language, maybe it's better to just drop the compilation and do
everything in runtime? This way at least you don't feign to yourself that you
did any verification.
> > Also, what about the quotes around "$MIME_subject"? I can't remember when you need
> > them.
> The rules for when and which quotes are needed are pretty simple to learn.
As I remember, argument for 'expr' should contain quotes around every raw
text, which is not boolean constant or a math function name. Regardless of
what operators you use for them.
So I don't know, what is the advantage of using eq unstead of ==.
This is not reasonable for me, because In C++ I use == for both integer and
string comparisons.
But maybe it is reasonable for those, who use perl, in which "foo" == "bar"
evaluates to true.
;)
--
// _ ___ Michal "Sektor" Malecki <sektor(whirl)kis.p.lodz.pl>
\\ L_ |/ `| /^\ ,() <ethourhs(O)wp.pl>
// \_ |\ \/ \_/ /\ C++ bez cholesterolu: http://www.intercon.pl/~sektor/cbx
"I am allergic to Java because programming in Java reminds me casting spells"
I have already proposed that the "variable tying" should have the arguments in
the same order as "set" command, as well as that having variables not in any
list does not make anything easier. So I would use:
mset {a b c} [regexp -all -inline {\S+} $data]
And I think it's better that operations on regular expressions are collected
in a [regexp] command, rather than having a regular expression as a kind of a
new "data type". Or if I needed one...
proc splitre {data re} { return [regexp -all -inline $re $data] }
mset {a b c} [splitre $data \\S+]
which does not look like cursing in comics ;)
I agree that some new commands are, at least, making it
easy for errors:
The asymmetry of these is going to make things difficult to
people:
string repeat string count
lrepeat number element1 ?element2 element3 ...?
Also, when everybody is used to:
foreach "var1 var2 var3" $list break
This is going to be more difficult to remember:
lassign list varName ?varName ...?
Why not?
lrepeat element count
lassign "var1 var2 var3" $list
Do not take it as a criticism to anyone or anybody but as a
claim to find the best possible interface for every function.
I think that TCL8.5 is still in alpha an can include some
adjustments.
Regards,
Ramon Ribó
En Sun, 29 Jan 2006 14:24:32 +0100, Sektor van Skijlen
<etho...@com.gmail.address.such.no.com> escribió:
> Dnia 28 Jan 2006 23:05:35 -0500, Michael Mellinger skrobie:
>
>> "Donal K. Fellows" <donal.k...@manchester.ac.uk> writes:
>
>> > Michael Mellinger wrote:
>> > > Certain things are nice in Perl.
>> > > ($a,$b,$c)=split(/\s/,$_,3); # This idea works when talking to
>> databases too.
>> >
>> > lassign [regexp -all -inline {\S+} $data] a b c
>
>> I'll have to add this to my little bag of tricks. Which is more
>> intuitive to you?
>
> I have already proposed that the "variable tying" should have the
> arguments in
> the same order as "set" command, as well as that having variables not in
> any
> list does not make anything easier. So I would use:
>
> mset {a b c} [regexp -all -inline {\S+} $data]
>
> And I think it's better that operations on regular expressions are
> collected
> in a [regexp] command, rather than having a regular expression as a kind
> of a
> new "data type". Or if I needed one...
>
> proc splitre {data re} { return [regexp -all -inline $re $data] }
>
> mset {a b c} [splitre $data \\S+]
>
> which does not look like cursing in comics ;)
>
--
Compass Ing. y Sistemas Dr. Ramon Ribo
http://www.compassis.com ram...@compassis.com
c/ Tuset, 8 7-2 tel. +34 93 218 19 89
08006 Barcelona, Spain fax. +34 93 396 97 46
eq forces a string compare, == may do a string compare but will try to
do a numeric compare. This can be important:
set v1 "1"
set v2 "01"
if {$v1 == $v2} {puts "equal"} else {puts "not equal"}
if {$v1 eq $v2} {puts "equal"} else {puts "not equal"}
If you turned the arguments around, this could be simplified to:
interp alias {} splitre {} regexp -all -inline
> > What do you need this silly concept for in Tcl? Tcl is "using strict"
> > by default.
>
> Tcl does not have a "use strict" by default. For example, simply
> having the option to catch variables that are referenced before they
> are declared is very useful.
This is a common behaviour in dynamic languages. It has to be this way
- if you don't want it, you should in general consider using a
comnpiled language, like C or Java.
But very often it is already helpful to think disciplined about
variable naming and -usage - and catch such errors with
if {[info exists ...]} {}
or otherwise. When it comes to global variables that are used by many
procedures in a big program, you have to do a certain level of error
checking anyway. Of course it makes sense to balance overhead and
benefit.
Syntax checkers are also a great deal. Among other things, these nice
small programs check variable references and warn if the variable was
not set before.
> Also, ever have your Tcl code silently
> end in a callback because of a simple mistake?
No, never. That would be a very stupid mistake - no matter what
programming language I am using ;-).
Eckhard
Raw text (constants) yes, but variable references need not be quoted.
Uhhh, this is nasty. Is that filed as a bug already and|or fixed in 8.5
or so? I would expect to be not able to compare a string against a
number - this should rise an error!
> proc foo max {
> incr max 0
> for {set i 0} {$i<$max} {incr i} {puts hello}
> }
> Should the user use a non-integer, he'll get the justified error
> "expected integer but got 'bar'" right away, instead of waiting...
> waiting...
nice workaround, but it should not be necessary to do it this way...
Anyway, thank you for this info.
Eckhard
No - "everything is a string", numbers are too (or can receive a string
rep on demand). The philosophy for [expr] and other places with expr
language is:
- if both comparands are numbers, do it numeric;
- else do string comparison.
Normally it works very well - but this was one exception...
> Michael Mellinger wrote:
> > Now wouldn't it be nice to know that you screwed up?
>
> Sure would. But Tcl doesn't let you detect that before runtime, just
> like Perl doesn't let you detect whether the file you're trying to
> open actually exists before runtime.
Hmmm... We can compare apples to apples here, right? So why throw in
an orange? Perl does let you declare your variables and catch simple
typos. Static analysis can be done in Tcl to catch some problems
before the program is executed. No, when I'm programming on a team
with other Tcl programmers and we have thousands of lines of code to
maintain, wouldn't it be nice to have a little static analysis done?
Variables never used, etc.?
As for the orange, I don't think C, C++, Tcl, Perl, etc. detect before
runtime if the file you are trying to open actually exists?
> Now, of course you find out you screwed up the very first time you run
> that "foo" proc you declared. Shame on you for releasing code you've
> never run.
Well, you might not catch the typo the first time you run the program,
or the second, but sooner or later you will. Who said the code was
released before it was tested? How do you know you've got complete
coverage? How about this simple little program? It will run fine?
proc foo {x} {
if {$x eq "foo"} {
set q=1
} else {
set q 2
}
}
foo "bar"
puts "Do I have syntax errors?"
#
There are days when I'm writing Perl and Tcl. They can be painful!
> Syntax errors in Tcl are caught as soon as you try to load the file.
Please look at the above code. My mistake is not caught even after
the program is executed.
> Runtime errors cause exceptions to be thrown, which you can catch and
> handle as you see fit. I've not seen anything but logic errors cause
> infinite loops. I'm not sure why you'd think a syntax error would
> silently hang.
The above code will not produce any warning when I get callbacks from
an external event.
Yes. It's just not built into Tcl, just as lint is a separate program
from C compilers sometimes.
> No, when I'm programming on a team
> with other Tcl programmers and we have thousands of lines of code to
> maintain, wouldn't it be nice to have a little static analysis done?
> Variables never used, etc.?
Sure. Feel free. There are a number of programs to do that. Just don't
expect that it'll catch all undeclared variables.
> As for the orange, I don't think C, C++, Tcl, Perl, etc. detect before
> runtime if the file you are trying to open actually exists?
Right. My point is that Tcl doesn't detect undeclared variables *for the
same reason*. You generate variables dynamically as you run. It's quite
legal to try to reference a variable that doesn't exist. It throws an
error, you can catch the error, and do something intelligent. I've used
this technique, when using routines that generate variables dynamically
based on user input.
> puts "Do I have syntax errors?"
No. Perhaps you've redefined [set].
> There are days when I'm writing Perl and Tcl. They can be painful!
Indeed.
>>Syntax errors in Tcl are caught as soon as you try to load the file.
>
> Please look at the above code. My mistake is not caught even after
> the program is executed.
That's because it's not a syntax error. It's exactly as much a runtime
error as dividing by zero is.
> The above code will not produce any warning when I get callbacks from
> an external event.
I still don't know what a "callback from an external event" means in the
context of Tcl.
I think "thousands of lines of code" of Tcl is a bad precondition. Not
little of that was probably created by pasting, and creates maintenance
troubles of its own. I'd strongly suggest to strive for short code,
that one can conveniently overlook. 72 lines of code is a good metric -
makes one print page :^)
Especially when working in a team, defining well-encapsulated packages
with fixed interfaces, and modular test suites, is very important. A
good test suite reveals more problems than static analysis ever can, in
a dynamic language.
Make sure all the little parts work as they should, before putting them
together...
I have never used the interp, or eval, command since I have never needed it.
Of course, ignorance might be why I think I have never needed it. What does
the above do for me, how is it similar to the proc, how does it replace the
proc, and how do I use it?
More practical example: The Img package can capture widgets into a
photo widget. You can wrap it like this:
interp alias {} capture {} image create photo -format window -data
or like that:
proc capture {w} {
return [image create photo -format window -data $w]
}
As they are roughly equivalent, I like simpler better :)
Maybe I am being dense today, but I am still unclear on how to use this
interp capture command.
The proc useage is: set image1 [capture $w]
Is this interp capture used the same way? How is it written in a program?
set a 0
set p a
expr { $p == a }
syntax error in expression "$p == a": variable references require preceding $
In this case "variable reference" is a sequence of literal characters being a
name of the variable, to be consistent with the error desacription. So my
example was just trying your statement in practice.
If you mean that you can write $var (not "$var"), I would add that you don't
have also to place [command] i "[quotes]" and also you may put expressions
like "yes" in quotes (but don't have to).
A sequence starting from $ is a part of expression, like also anything in ""
or {} or []. Any sequence of literal characters used without these must be
either a boolean constant or a math function.
> If you turned the arguments around, this could be simplified to:
> interp alias {} splitre {} regexp -all -inline
Yes, but I wanted to keep the same syntax as for [split].
> Michael Mellinger wrote:
> > Hmmm... We can compare apples to apples here, right? So why throw in
> > an orange? Perl does let you declare your variables and catch simple
> > typos. Static analysis can be done in Tcl to catch some problems
> > before the program is executed.
>
> Yes. It's just not built into Tcl, just as lint is a separate program
> from C compilers sometimes.
C -> gcc -Wall
Python -> pychecker
Perl -> use strict; use warnings.
I do expect more from Tcl. It is not unreasonable to want to more
static checking. I shouldn't need to run the program to verify some basic
correctness.
> Right. My point is that Tcl doesn't detect undeclared variables *for
> the same reason*. You generate variables dynamically as you run. It's
> quite legal to try to reference a variable that doesn't exist. It
> throws an error, you can catch the error, and do something
> intelligent. I've used this technique, when using routines that
> generate variables dynamically based on user input.
>
> > puts "Do I have syntax errors?"
>
> No. Perhaps you've redefined [set].
Of course I may be doing some really slick stuff with the dynamic
language and in those cases I can just turn off my 'strict' syntax
checking. Most of the time I want to develop something rapidly and
grow it into an "enterprise" application where speed is important and
correctness is highly desirable. Use Java? Maybe? But doesn't
Tcl/Tk seem like a great option?
-Mike
The problem is you have incorrect assumptions about what is "correct" in
Tcl.
Here's a question:
proc foo {bar} {
do_something bar
do_other $bar
return [list $x $y]
}
foo [list x y]
Is that correct code? Will that throw an exception? Would you want your
static checking to complain about it?
How about this:
proc foo {bar} {
global xyz
return $xyz($bar)
}
Should your static checker tell you that $xyz($bar) might not be set?
Why is that a less common situation than misspelling a variable name?
How about these lines?
set x [array get y]
set x [array get $y]
set $x [array get y]
What about
if {[catch {incr i}]} {set i 0}
Should the tool complain about that?
What about
set a(x) 0
puts $a(x)
That'll throw an error if a write-trace on array a unsets a(x).
How about
proc foo {} {
set x {puts $y}
... lots of code ...
eval $x
}
How would you check whether that's right?
What about the line
return [set $x$y]
Is that going to get checked?
> Of course I may be doing some really slick stuff with the dynamic
> language and in those cases I can just turn off my 'strict' syntax
> checking.
Then you'd have it turned off for much of the code. There are any number
of places in Tcl where you pass the names of variables into user code
that creates those variables. The problem with automated mechanisms is
you wind up turning them off inappropriately because they're not
sophisticated enough. A much better method would be to have test
coverage checking, or to just test the code you wrote in the first
place. Catching in Tcl the sorts of things that Perl's "use strict"
catches is going to be able to catch very few of the bugs. Perl does
far more automagically than Tcl does, so there's far more room for Perl
code to accidentally be wrong because of a typo than Tcl is.
For example, my most common sorts of "typo" errors are along the lines of
if {[info exists $x]} {...}
when I meant to type
if {[info exists x]} {...}
and that's exactly where "use strict" is *not* going to help.
> Most of the time I want to develop something rapidly and
> grow it into an "enterprise" application where speed is important and
> correctness is highly desirable. Use Java? Maybe? But doesn't
> Tcl/Tk seem like a great option?
It does. And I use it all the time for such things. I've been doing
enterprise software in Tcl for 10+ years. It's just that "use strict" is
exactly the wrong kind of checking, and it essentially removes all the
benefits that Tcl provides. The powerful parts of Tcl are exactly the
parts the "use strict" can't check.
Because there was an existing [lassign] command in TclX, and breaking
compatability with that wasn't worth it, just as choosing something that
is functionally identical but gratuitously different in syntax also was
not a great choice.
> Do not take it as a criticism to anyone or anybody but as a
> claim to find the best possible interface for every function.
> I think that TCL8.5 is still in alpha an can include some
> adjustments.
Do not take it as a criticism to you or anybody else, but as a note that
you might not be considering the full range of input data when thinking
about possible interfaces for a command. :-)
Donal.
Robert
> The asymmetry of these is going to make things difficult to
> people:
>
> string repeat string count
> lrepeat number element1 ?element2 element3 ...?
I agree completely!
> Why not?
> lrepeat element count
Probably because they wanted the extra functionality of blocks
of repeated elements.
> lassign "var1 var2 var3" $list
Because lassign exists already with the other syntax.
They should have made an mset command or some such and not
touched "lassign".
Inconsistencies in the language definition is the second worst
thing that can happen to a language.
--
Donald Arseneau as...@triumf.ca
> The problem is you have incorrect assumptions about what is "correct"
> in Tcl.
>
> Here's a question:
>
> proc foo {bar} {
> do_something bar
> do_other $bar
> return [list $x $y]
> }
> foo [list x y]
>
> Is that correct code? Will that throw an exception? Would you want
> your static checking to complain about it?
Don't you think in a situation like this you might be trying to be a
little too clever for your own good. $x $y?
> How about this:
>
> proc foo {bar} {
> global xyz
> return $xyz($bar)
> }
>
> Should your static checker tell you that $xyz($bar) might not be set?
> Why is that a less common situation than misspelling a variable name?
You know as it turns out this kind of situation often does demand an
[info exists ]. What do you want to happen when $xyz($bar) is
undefined in a program that you deliver? I've written it your way
many times only to have to go back and put in a check.
> What about
> if {[catch {incr i}]} {set i 0}
> Should the tool complain about that?
Never written it that way. Isn't that a bit sloppy?
[More clever ways to confuse a checker deleted]
> Then you'd have it turned off for much of the code. There are any
> number of places in Tcl where you pass the names of variables into
> user code that creates those variables. The problem with automated
> mechanisms is you wind up turning them off inappropriately because
> they're not sophisticated enough. A much better method would be to
> have test coverage checking, or to just test the code you wrote in the
> first place. Catching in Tcl the sorts of things that Perl's "use
> strict" catches is going to be able to catch very few of the bugs.
> Perl does far more automagically than Tcl does, so there's far more
> room for Perl code to accidentally be wrong because of a typo than Tcl
> is.
Your job is to support 50,000 lines of Tcl/Tk? Don't you want as much
help from your tools as possible? What is more important to be as
clever as possible or to write your code so that it's easily
maintainable?
> For example, my most common sorts of "typo" errors are along the lines of
> if {[info exists $x]} {...}
> when I meant to type
> if {[info exists x]} {...}
> and that's exactly where "use strict" is *not* going to help.
Yep, I've done this myself. Why can't you have a warning for this?
You get a warning in C when you type
if (x=1) {...}
It's a valid statement but most of the time you don't mean it. We are
talking about something similar to Perl's
use strict; use warnings; # ?
> It does. And I use it all the time for such things. I've been doing
> enterprise software in Tcl for 10+ years. It's just that "use strict"
> is exactly the wrong kind of checking, and it essentially removes all
> the benefits that Tcl provides. The powerful parts of Tcl are exactly
> the parts the "use strict" can't check.
Yes, you can be clever and do some really cool things with a dynamic
language, but I disagree about removing all the benefits of Tcl.
You can also write some pretty "boring" code with Tcl/Tk
in a short period of time that is extremely functional.
-Mike
No. That's my point. That's perfectly normal Tcl code for me.
> You know as it turns out this kind of situation often does demand an
> [info exists ]. What do you want to happen when $xyz($bar) is
> undefined in a program that you deliver?
If I expect it always to be defined, I don't put in a check. What am I
going to do if the check catches something?
I have a top-level catch, I log the error, and I take the same exit I'd
get on any other kind of error, including the client code having a bug
that violates protocol.
> I've written it your way
> many times only to have to go back and put in a check.
And what do *you* do, that you wouldn't have done for some other kind of
error?
>>What about
>>if {[catch {incr i}]} {set i 0}
>>Should the tool complain about that?
>
>
> Never written it that way. Isn't that a bit sloppy?
Nope. Especially not when "i" is more complicated, like an array element.
> Your job is to support 50,000 lines of Tcl/Tk?
Yes. Author it, then support it. Run businesses on it, really.
> Don't you want as much
> help from your tools as possible? What is more important to be as
> clever as possible or to write your code so that it's easily
> maintainable?
I find that clever code *is* easily maintainable, because it's clever
enough I don't have to figure out how it works internally to use it.
>>For example, my most common sorts of "typo" errors are along the lines of
>> if {[info exists $x]} {...}
>>when I meant to type
>> if {[info exists x]} {...}
>>and that's exactly where "use strict" is *not* going to help.
>
> Yep, I've done this myself. Why can't you have a warning for this?
Because there's no way of looking at the code automatically and deciding
whether the user *meant* for "x" to be holding a value of interest, or
meant for "x" to be holding the name of a variable.
> You get a warning in C when you type
>
> if (x=1) {...}
>
> It's a valid statement but most of the time you don't mean it.
Yes. But if, in C, you write
if (*p != NULL) { ... }
and you meant
if (p != NULL) { ... }
then you're equally screwed and it's equally hard to catch, isn't it?
> Yes, you can be clever and do some really cool things with a dynamic
> language, but I disagree about removing all the benefits of Tcl.
> You can also write some pretty "boring" code with Tcl/Tk
> in a short period of time that is extremely functional.
Yes. Now program a tool to automatically distinguish clever code from
boring code. Note that many packages, such as the SMTP package in
TclLib, use things like I'm talking about to implement their OO-style
"tokens". For that matter, lots of OO packages do exactly this sort of
thing. Heck, Tk creates and destroys procedures on demand, let alone
variables. Haven't you seen someone do [set x [entry .me.type]] ?
For the simple case, there are tools to check. For the complex case,
tools can't check. Nor can tools easily distinguish simple from complex
cases. What you're complaining about just isn't really a problem. There
are far more common problems in Tcl than misspelling a variable name.
> Because there was an existing [lassign] command in TclX, and breaking
> compatability with that wasn't worth it, just as choosing something that
> is functionally identical but gratuitously different in syntax also was
> not a great choice.
It is astounding that regularity of language syntax would be considered
gratuitous.
The existing command in TclX matters to the extent that one shouldn't
use the same name "lassign" with an alternate syntax, but it does not
rate with maintaining backwards compatibility within Tcl. Once these
new commands are in the core, they are stuck that way forever.
--
Donald Arseneau as...@triumf.ca
It's also a bit amazing that you would anti-consider (there's probably a
better word for that) backward compatability so much. But then that's a
different constituency to the one you represent, isn't it?
> The existing command in TclX matters to the extent that one shouldn't
> use the same name "lassign" with an alternate syntax, but it does not
> rate with maintaining backwards compatibility within Tcl. Once these
> new commands are in the core, they are stuck that way forever.
I've seen the other proposals:
1) More arguments to [set]. (NO!)
2) Something like this:
<someCmdMaybeMset> {var1 var2 var3 ...} theList
That sucks if you're working with anything other than 100% literal
(including the element name in an array) variable names.
3) Something like this:
<someCmdMaybeMset> var1 var2 var3 ... theList
This is lassign, but in a different order with the variable part in
the middle of the list of arguments.
Option 1 is Right Out. Option 2 is better, but forces even more use of
the [list] command everywhere; to be (a little) facetious, it's the C
programmer's solution. It's also quite a bit trickier than the others to
get a good implementation from it in the face of the non-trivial quoting
requirements. Option 3 is a reordering of what actually went in the
core, but without the benefit of an existing codebase and userbase to
take advantage of it.
Sometimes you've got to make a judgement call. We thought there wasn't
much in it, and so went with compatability with deployed code.
Donal.
you realize this best, when teaching these inconsistencies in a course.
See as well:
http://groups.google.at/group/comp.lang.tcl/browse_frm/thread/d8e89f5f04daa8e7/8f18c91bfb62f83e?lnk=st&q=lassign&rnum=2&hl=de#8f18c91bfb62f83e
Why not?
lrepeat [lrepeat element1 count1] count2
or
lrepeat [list element1 element2] count
Regards,
Ramon Ribó
En Mon, 30 Jan 2006 02:58:03 +0100, Donald Arseneau <as...@triumf.ca>
escribió:
--
Compass Ing. y Sistemas Dr. Ramon Ribo
http://www.compassis.com ram...@compassis.com
c/ Tuset, 8 7-2 tel. +34 93 218 19 89
08006 Barcelona, Spain fax. +34 93 396 97 46
One interesting thing in Tcl is that the language definition (taken as
man Tcl(n)) does not enumerate commands - it only delares their
liberties: "The command procedure is free to interpret each of its
words in any way it likes, such as an integer, variable name, list, or
Tcl script. Different commands interpret their words differently."
So it's a matter of the implementer of a command how he sets up the
API, and sometimes there are conflicting styles (just compare [string
length] and [llength], for instance). Argument ordering may sometimes
surprise:
string first $substring $string
lsearch $list $element
I'm trying to explain this for myself linguistically, as adj-n or v-np
patterns:
(find the) first substring (in) string
resp.
search (the) list (for the) element
...
That's good for producing patterns like:
{a a a a} {a a a a} {a a a a}
or patterns like:
{a b c} {a b c} {a b c} {a b c}
but not like:
a b c a b c a b c a b c
If you see what I mean. While the real [lrepeat] can (with suitable
nesting in some cases) emulate all your cases, you can only emulate
[lrepeat] with an additional flattening step if you do not have the
ability to take multiple value arguments. IOW, it's that way because it
has to be to be most useful.
Donal.
>I've seen the other proposals:
>
> 1) More arguments to [set]. (NO!)
> 2) Something like this:
> <someCmdMaybeMset> {var1 var2 var3 ...} theList
> [...]
> 3) Something like this:
> <someCmdMaybeMset> var1 var2 var3 ... theList
> [...]
>
>Option 1 is Right Out. Option 2 is better, but forces even more use of
>the [list] command everywhere; to be (a little) facetious, it's the C
>programmer's solution. It's also quite a bit trickier than the others to
>get a good implementation from it in the face of the non-trivial quoting
>requirements. Option 3 is a reordering of what actually went in the
>core, but without the benefit of an existing codebase and userbase to
>take advantage of it.
>
>Sometimes you've got to make a judgement call. We thought there wasn't
>much in it, and so went with compatability with deployed code.
I should add that compatibility with TclX wasn't the only,
or even the primary, reason behind the decision -- a number
of people believed that [lassign]'s syntax stands on its own
merits.
It's also consistent with [scan] and [regexp], two other commands
that produce multiple values and can assign them to variables,
that was also a factor.
--Joe English
> 1) More arguments to [set]. (NO!)
> 2) Something like this:
> <someCmdMaybeMset> {var1 var2 var3 ...} theList
> That sucks if you're working with anything other than 100% literal
> (including the element name in an array) variable names.
> 3) Something like this:
> <someCmdMaybeMset> var1 var2 var3 ... theList
> This is lassign, but in a different order with the variable part in
> the middle of the list of arguments.
> Option 1 is Right Out.
Yes. It would add an overhead for any use of [set].
> Option 2 is better, but forces even more use of
> the [list] command everywhere; to be (a little) facetious, it's the C
> programmer's solution. It's also quite a bit trickier than the others to
> get a good implementation from it in the face of the non-trivial quoting
> requirements.
Seems like you are trying to find the best solution for every possible
situation. This is the wrong way; doing that you will not make everyone happy.
The good solution is to make the syntax comfortable for most uses, leaving a
bit of uncomfortability for unusual situations.
I know that, for example, it would look weird if you use:
mset [list [first_variable] $second[variable_used]] [get_values]
but how much time dou you use constructed variable names in such context? Ths
most common use of mset would be
mset {first second third} $values
For example, I use my own [mset] command (with well-known definition) in such
situations, when I have to get access to particular values of a list to treat
them separately. In all those uses these vriables are only temporary, local
variables. So the [mset] command is used only with explicit variable names
given in {}. It is also cleaner to use them and then copy these values to some
other places, maybe to some variables with constructed names.
> Option 3 is a reordering of what actually went in the
> core, but without the benefit of an existing codebase and userbase to
> take advantage of it.
I don't agree. The [lassign] command could stay where it was - in TclX. Moving
this command to the core you don't use any existing code/user-base, mostly
because if they used TclX to get advantage for the [lassign] command, they use
TclX also for other facilities. For these users providing [lassign] won't
change anything. And for users not using TclX it is just a new command.
[jumping into the middle of this thread]
This got me thinking:
2)
proc mset {varList valueList} {
if {[llength $varList] == 0} {
error "must specify at least one variable name"
}
uplevel 1 [list foreach $varList [linsert $valueList end {}] break]
return [lrange $valueList [llength $varList] end]
}
3)
proc mset {args} {
if {[llength $args] < 2} {
set procname [lindex [info level 0] 0]
error "wrong # args: should be \"$procname var ?...? list\""
}
set varList [lrange $args 0 end-1]
set valueList [lindex $args end]
uplevel 1 [list foreach $varList [linsert $valueList end {}] break]
return [lrange $valueList [llength $varList] end]
}
Is there anything obviously wrong with the above?
--
Glenn Jackman
Ulterior Designer
How about using the foreach syntax for mset cmd but without the need to
specify break:
mset var1 val1 var2 val2 var3 val3 ...
or
mset {var1 var2} {val1 val2} var3 {val3 valueX} {var4 var5 var6} {val4}
where valueX is not assigned to any variable and var5 and var6 are
initialized to null.
Hemang.
> This got me thinking:
Why not
proc mset {vars vals} {
uplevel [list foreach $vars $vals break]
}
?
Checking for non-empty var list is not necessary. In this case just no action
will be taken.
It's to protect against an unexpected error message in an edge case:
proc your_mset {vars vals} { uplevel [list foreach $vars $vals break] }
your_mset {} {this is some real data} ;# empty variable list
# error! "foreach varlist is empty" -- huh?
Also, I explicitly return unused values to mimic [lassign]
set unused [mset {v1 v2} {1 2 3 4}] ;# unused = {3 4}
I neglected to reference http://wiki.tcl.tk/lassign in my earlier post,
which is where I picked up the [linsert $valList end {}] bit.
Arrays are the most common case. And "constructing a variable name"
includes referring to an element of an array where the name of the
element is not constant. Not that having [lassign] stops you from
creating [mset] in a tiny amount of code:
proc mset {vars values} {
uplevel 1 [list lassign $values {expand}$vars]
}
Donal.
> It's also consistent with [scan] and [regexp],
Don't get me started on scan and regexp!
scan string pattern variables
regexp pattern string variables
lassign vs set is small potatoes compared to this shining example
(which is number two on my list).
The fact that arguments are personal to each command seems to have
repressed considerations of argument-list regularity throughout
the life of Tcl.
That's not to say that everything is bad! But the occasional bad
examples have a long history.
--
Donald Arseneau as...@triumf.ca
Of course you could do both. Static analysis may not find *all* bugs,
but that doesn't mean that it will not find *any*. After all, a test
suite itself can be seen as a form of "static" analysis, albeit not a
strictly syntactic method (such as a type system).
-- Neil
Yes, it is used in exactly the same way. See
http://www.tcl.tk/man/tcl8.5/TclCmd/interp.htm#M8 for details.
Basically, a call like:
interp alias {} $name {} cmd arg...
is equivalent to:
proc $name {args} {
uplevel 1 [linsert $args 0 cmd arg...]
}
The extra {} arguments to interp alias are where you can specify
interpreters -- {} means the current interpreter. [interp alias] is
quite a useful command to know as it can be used to specialise commands,
e.g.:
% proc add {a b} { expr {$a + $b} }
% interp alias {} succ {} add 1
succ
% succ 1 ;# equivalent to add 1 1
2
% succ 41 ;# equiv to add 1 41
42
-- Neil
hehe :)
I always get confused by
string match pattern string
as well. At least it matches [regexp].
--
WL
real mail: wliao at sdf loSnPesAtarM org
(remove the uppercase letters...)
> [interp alias] defines a command, just like [proc] does, but it's
> lighterweight in memory, stack usage, and probably also slightly
> faster.
> As they are roughly equivalent, I like simpler better :)
Query: I'm aware that [rename] causes (may cause?) all existing
bytecode to be discarded. Does the same thing happen with
[interp alias]?
--
Donald Arseneau as...@triumf.ca
Potentially, yes. The discard of all bytecode (other than that made
available by tbcload) in an interpreter happens if you cause to be
deleted or renamed any command that is compiled. That's a fairly short
list of core commands. Once the bytecode is thrown away, bytecode is
transparently regenerated as code is executed. (Strictly, the discard
doesn't happen immediately either; it's postponed until the next time
that particular piece of bytecode is executed when there's a check to
see if the "compilation epoch" matches.)
Donal.
> Potentially, yes. The discard of all bytecode (other than that made
> available by tbcload) in an interpreter happens if you cause to be
> deleted or renamed any command that is compiled.
Thanks!
--
Donald Arseneau as...@triumf.ca
This is the most sensible order of arguments if you consider creating
specialised commands (something I do reasonably often):
interp alias {} isurl {} regexp $urlre
if {[isurl $url -> protocol host port path]} { ... }
Likewise, it is also useful when using higher-order programming techniques:
proc filter {func list} {
set ret [list]
foreach item $list {
if {[invoke $func $item]} {
lappend ret $item
}
}
return $ret
}
proc invoke {cmd args} { uplevel #0 $cmd $args }
Which you can then use like:
% filter {string match xotcl*} [package names]
xotcl::upvar-compat xotcl::store::persistence xotcl::comm::imap
xotcl::test xotcl::comm::ftp xotcl::script xotcl::wafecompat
xotcl::store::jufgdbm xotcl::serializer xotcl::staticMetadataAnalyzer
xotcl::mixinStrategy xotcl::xodoc xotcl::store::mem xotcl::package
xotcl::metadataAnalyzer xotcl::store::textfile xotcl::store::multi
xotcl::comm::httpd xotcl::store::tclgdbm xotcl::comm::mime
xotcl::comm::connection xotcl::scriptCreation::recoveryPoint
xotcl::scriptCreation::scriptCreator xotcl::comm::ldap
xotcl::comm::httpAccess xotcl::comm::dav xotcl::trace
xotcl::comm::pcache xotcl::store xotcl::htmllib
-- Neil
Rereading that, it comes across slightly wrong. Renaming/deleting a
command that involves a normal round trip through the command invoker
code does not cause recompilation. It's only the case where a command
can be inlined (i.e. has a non-NULL compileProc field in the internal
structure; it's a cheap check) that causes an epoch bump.
That's what I meant before, but it could be read like all procedures
behave like that too, which isn't true at all. :-)
Donal.
But how many things you can verify by static analysis, depends on the nature
of the language. It is a normal thing among compiled languages, so these
languages should be prepared to verify all possible things at compile time
(like it is in case of C++ and moreover in case of various statically-typed
functional languages).
This also bring a lot of other consequences. For example, programs in C++ are
compiled slowly, but run very fast. And not only the fact that it is a
compiled language is what matters here, but also the syntax is especially
prepared for that. A scripting language must have simple syntax so that the
parsing performance does not matter much in the performance at all.
The nature of Tcl is such that doing a static analysis is practically
impossible. Such a static checking shall not be even compared to a static
analysis done by compilers, but rather a form of 'lint' checking.
> Arrays are the most common case. And "constructing a variable name"
> includes referring to an element of an array where the name of the
> element is not constant.
I knew you'd say that ;)
> Not that having [lassign] stops you from
> creating [mset] in a tiny amount of code:
> proc mset {vars values} {
> uplevel 1 [list lassign $values {expand}$vars]
> }
I've always been for that providing extension facilities is much better than
providing specific features, but Tcl has that in itself ;)
> It's to protect against an unexpected error message in an edge case:
> proc your_mset {vars vals} { uplevel [list foreach $vars $vals break] }
> your_mset {} {this is some real data} ;# empty variable list
> # error! "foreach varlist is empty" -- huh?
One of the most important things in Tcl is that it handles most exceptions in
the most appropriate way. Checking the arguments you will still receive the
error message, but maybe with another text.
> Also, I explicitly return unused values to mimic [lassign]
> set unused [mset {v1 v2} {1 2 3 4}] ;# unused = {3 4}
Loox nice, but I don't think it's useful. I would rather like:
mset {l1 unused} [lsplit {1 2 3 4} 2] ;# lsplit returns {1 2} {3 4}
mset {v1 v2} $l1
Obviously some languages are more suited to static analysis than others.
> This also bring a lot of other consequences. For example, programs in C++ are
> compiled slowly, but run very fast. And not only the fact that it is a
> compiled language is what matters here, but also the syntax is especially
> prepared for that. A scripting language must have simple syntax so that the
> parsing performance does not matter much in the performance at all.
>
> The nature of Tcl is such that doing a static analysis is practically
> impossible. Such a static checking shall not be even compared to a static
> analysis done by compilers, but rather a form of 'lint' checking.
It really depends what you count as Tcl and what you count as a static
analysis. You appear to be discounting "lint" checkers from static
analysis, which is at odds with Wikipedia, which says
(http://en.wikipedia.org/wiki/Lint_programming_tool) "Lint-like tools
generally perform static analysis of source code." Tcl does have
lint-like static checkers and they find a variety of errors. Again, just
because these checkers may not find as many errors as, say, the type
system of a language like Haskell, doesn't mean that they are not useful
tools.
-- Neil
They don't. Witness the number of production C++ programs with bugs in
that are out there... :-)
Donal.
Depends on how you write programs.
If the program is written in C style and all generic things are done in
runtime, you lose most of the static checking.
Yes. I just want to say that the static analysis can't be done by the
interpreter because errors found by interpreter disqualify the program from
running. Mind that even compilers also report dangerous situations by
warnings, being not sure about incorrectness of the program.
Perl has static checking and still detect less errors in program than they can
be detected in other languages. Compare the OO programming realized by
CamelPOOP in Perl and IncrTcl in Tcl. How do you check in Perl that the method
has been correctly called?
Perl also has warnings, which seems to be inevitable in static checking.
Warnings in interpreted language. Very funny.
Some language designers, such as the designer of the Eiffel language,
deem that warnings are a sign of bad design. If the language is
confusing enough that you might accidentally be doing something wrong
that you thought was right, fix the language. :-)
--
Darren New / San Diego, CA, USA (PST)
Crate & Barrel -
Furnishing Video Games Since 1962!
Not really. As we know from computability theory, there's an infinite
number of possible levels of abstractions, and Goedel and Turing tell us
that we cannot write programs that understand general programs in their
entirety. Given these facts, there is no possibility of performing a
static check that detects all possible bugs that might be in a program.
Which isn't to say that static checks are worthless. They just are not a
cure-all. (Note that the fact that the checks are static is pretty much
beside the point.)
Put it a different way. You can write a Tcl interpreter in C++ (after
all, people have done so in both C and Java) and have that be a correct
implementation, and yet that still won't stop your Tcl scripts from
possibly having bugs. :-)
Donal.
So instead of one non-trivial command call and a simple [set](*), you
propose to use three non-trivial command calls? And you're doing so in a
way that requires people to count things instead of just writing
directly what they mean?
<sarcasm> Seems like a good idea to me! </sarcasm>
BTW, what do you propose to happen with your model of [mset] if I were
to do:
mset {a b} {1 2 3}
or
mset {a b c} {1 2}
Donal.
(* I just realized that I tend to forget to count [set] as a command
call for some reason; I just seem to read it directly... :-))
Google language shootout
>
> I quickly tried to look find some comparisons. I see that you've got
> a page but some of the links are dead and it's not longer maintained.
>
> http://phaseit.net/claird/comp.lang.misc/language_comparisons.html
>
> -Mike
>
> --
> mmelli...@gmail.com
> Not really.
Why not really? I just wrote "all possible things". If you use dynamic
facilities (and you really use and really need them), the static checking is
just inapplicable for that.
> As we know from computability theory, there's an infinite
> number of possible levels of abstractions, and Goedel and Turing tell us
> that we cannot write programs that understand general programs in their
> entirety. Given these facts, there is no possibility of performing a
> static check that detects all possible bugs that might be in a program.
Stating that if you added 5 to some number, while you needed to add 10, you
made a bug. But for a programming language it does not make a difference if
you added 10 or 5.
With such a statement, you could clearly say that, of course, no static
checker can peek your mind, the design, the requirements and the base
conditions and say you write your program incorrectly. Moreover, if they
existed, there would be no such job "programmer".
Things that Turing, Goedel and others stated in this case seem not so
significant against the above statement.
> Put it a different way. You can write a Tcl interpreter in C++ (after
> all, people have done so in both C and Java) and have that be a correct
> implementation, and yet that still won't stop your Tcl scripts from
> possibly having bugs. :-)
Possibly, sometimes it can help, if you, for example, use incorrect command,
which will be correct in my interpreter ;)
> So instead of one non-trivial command call and a simple [set](*), you
> propose to use three non-trivial command calls?
Yes, because it's more readable than this one non-trivial command call.
> And you're doing so in a
> way that requires people to count things instead of just writing
> directly what they mean?
I don't understand. What things do they have to count?
> <sarcasm> Seems like a good idea to me! </sarcasm>
Your complaints look reasonable lol ;)
> BTW, what do you propose to happen with your model of [mset] if I were
> to do:
> mset {a b} {1 2 3}
> or
> mset {a b c} {1 2}
If you state that this is a simple translation of an empty foreach command,
you know the answeer.
Thes same things happen, when you read a value and do not write it anywhere,
and like indexing a list out of bounds. In particular, it's consistent with
other things in Tcl.
> Donal.
> (* I just realized that I tend to forget to count [set] as a command
> call for some reason; I just seem to read it directly... :-))
What is more simple with using [set]?
I think you're just plain wrong there.[*]
> If you state that this is a simple translation of an empty foreach command,
> you know the answeer.
So, to be absolutely clear, you're saying that you intend the following
two lines to be exactly equivalent?
mset $a $b
foreach $a $b {}
You could do that I suppose, but I don't think it is a good idea. :-)
> Thes same things happen, when you read a value and do not write it anywhere,
> and like indexing a list out of bounds. In particular, it's consistent with
> other things in Tcl.
It's consistent with *some* other things in Tcl, but not others. Most
"extract bits from a value and put them into variables" commands use the
[lassign] pattern (e.g. [regexp], [scan], [binary scan].)
Donal.
[* No point in debating this, as I doubt either of us is likely to
change his mind. ]