[/TCL]
This proc is supposed to calculate the immediate following Saturday of
the week, however, between November and April it gives me Friday; if I
up the date by 86400, it then gives me Sunday from April until
November.
I've tried for years to get this to be accurate and fail every time;
can someone please help me with this? I need to always get the next
immediate following Saturday.
Thanx
Phil
Uhm, does [clock scan Saturday] do what you want? Or if you need
the next Saturday after a given date,
[clock scan Saturday -base [clock scan $date]]
I'm not quite following the Tcl code that you posted, but suspect
that you're trying to reinvent one of the idioms above.
--
73 de ke9tv/2, Kevin
Problem is that it has to also be the next Saturday from the last
previous value of $expDate, so that if the very last value in the XML
row points to the date being 11/25/2006, the next one must be
12/2/2006, however, if the last one is 12/2/2006, the next one after
that must be 12/9/2006 and so on and so on
Phil
Whoa! Too much work.
set midnightNow [clock scan "00:00"]
> set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
> {expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
> $triviaAttrCount) - 1))}]]
> set expDate [clock scan [clock format $expDate -format "%m/%d/%Y"]];
And then:
set saturday [clock scan Saturday -base $expDate]
I know of no other language that makes date arithmetic this easy.
> # ROUND FOUND EXPDATE IN XML GROUP TO MIDNIGHT
> if {$hasPassedTrivia} {
> incr expDate [expr {7 * 86400}]
> while {$expDate <= $midnightNow} {incr expDate [expr {7 * 86400}]; #
> INCREASE BY ONE WEEK}
Never assume a day equals 86400 seconds. Always use the clock command
to manipulate time. If you want a time 7 days from another time:
set expDate [clock scan "7 days" -base $expDate]
> }
> return $expDate
> }
>
> [/TCL]
>
> This proc is supposed to calculate the immediate following Saturday of
> the week, however, between November and April it gives me Friday; if I
> up the date by 86400, it then gives me Sunday from April until
> November.
Doesn't that sound suspiciously like you're getting bit by
standard time vs. daylight savings time? Some days have more/less than
86400 seconds.
--
Glenn Jackman
Ulterior Designer
You've got to be kidding, it can't be that easy! :(
>
> > set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
> > {expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
> > $triviaAttrCount) - 1))}]]
> > set expDate [clock scan [clock format $expDate -format "%m/%d/%Y"]];
>
> And then:
> set saturday [clock scan Saturday -base $expDate]
>
> I know of no other language that makes date arithmetic this easy.
Except that this will give me a fixed Saturday date. I want the
immediate following Saturday from the very last date found in the last
XML row in the XML file, which could be 11/25/2006 or 12/2/2006 or
12/9/2006 or...
>
>
> > # ROUND FOUND EXPDATE IN XML GROUP TO MIDNIGHT
> > if {$hasPassedTrivia} {
> > incr expDate [expr {7 * 86400}]
> > while {$expDate <= $midnightNow} {incr expDate [expr {7 * 86400}]; #
> > INCREASE BY ONE WEEK}
>
> Never assume a day equals 86400 seconds. Always use the clock command
> to manipulate time. If you want a time 7 days from another time:
> set expDate [clock scan "7 days" -base $expDate]
I can't see how this will work when I need to find the very next
following Saturday after the very last date in the last XML row with
the expDate attribute. Sorry, your code is easy to understand but I
have no idea how to implement it.
Phil
When I had to do something similar to this in PHP, and I was under a
time crunch to get the code working (before the first billing cycle,
basically ;-), I took simple but fairly inefficient algorithm:
# Untested:
set nowish [clock scan $yourdateofinterest]
while {"Sat" != [clock format $nowish -format "%a"]} {
incr nowish 10800 ; # Don't get greedy! 3 hours
}
If you try to skip an entire day or week ahead, you risk timezones or
DST skipping you right over the date of interest. At the end of this
loop, nowish is at or after your date from the XML file, and it's
Saturday. Adjust appropriately to meet your requirements. If you need
it at midnight, format it as a date string and scan it back in, with the
appropriate timezone.
Of course, if you're pushing the envelope on CPU load, you probably want
to figure it out right, but given you're using Tcl and XML, I'd guess
that isn't the limiting factor here.
(My job was finding the start and end of the billing cycle the customer
was in, so it was the same thing only with days of the month instead of
days of the week.)
--
Darren New / San Diego, CA, USA (PST)
Scruffitarianism - Where T-shirt, jeans,
and a three-day beard are "Sunday Best."
Oh, ok, so add a day to your -base:
set expTime [clock scan $expDate]
set expTimeTomorrow [clock scan tomorrow -base $expTime]
set expTimeSaturday [clock scan Saturday -base $expTimeTomorrow]
puts [clock format $expTimeSaturday]
Using a -base of your date + 1 day seems to do the trick, or am I
missing something?
% clock format [clock scan Saturday -base [clock scan "11/23/2006 + 1 day"]]
Sat Nov 25 00:00:00 CST 2006
% clock format [clock scan Saturday -base [clock scan "11/24/2006 + 1 day"]]
Sat Nov 25 00:00:00 CST 2006
% clock format [clock scan Saturday -base [clock scan "11/25/2006 + 1 day"]]
Sat Dec 02 00:00:00 CST 2006
%
>
> Except that this will give me a fixed Saturday date. I want the
> immediate following Saturday from the very last date found in the last
> XML row in the XML file, which could be 11/25/2006 or 12/2/2006 or
> 12/9/2006 or...
like this:
% set reftime [ clock scan 12/2/2006 ]
1165014000
% clock scan "next saturday" -base $reftime
1165618800
% clock format 1165618800
Sat Dec 09 00:00:00 CET 2006
uwe
Um, ok sorry to sound stupid but I will anyway..
My timestamp in expDate attribute will be something like "1164949026",
how do I use that?
Phil
> %
clock format $expDate
you may want to use the -format option to clock format to specify the way
you want the date/time to look.
--
+--------------------------------+---------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+
Ok I'm really sorry, but I cannot follow what you guys are telling me
to do, I'm completely lost. Here is my original proc:
proc CALCULATE_XML_EXPDATE {triviaAttrs triviaAttrCount
hasPassedTrivia} {
set midnightNow [clock scan [clock format [clock scan now] -format
"%m/%d/%Y"]]
set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
{expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
$triviaAttrCount) - 1))}]]
set expDate [clock scan [clock format $expDate -format "%m/%d/%Y"]];
# ROUND FOUND EXPDATE IN XML GROUP TO MIDNIGHT
if {$hasPassedTrivia} {
incr expDate [expr {7 * 86400}]
while {$expDate <= $midnightNow} {incr expDate [expr {7 * 86400}]; #
INCREASE BY ONE WEEK}
}
return $expDate
}
I need to change the proc so that I ensure that I always get the next
Saturday following the value in the very last expDate="[0-9]" in the
XML row in trivia.xml. What you guys are telling me to do is great,
but for me with ADD you're going all over the map and trying to get me
to drink from a firehose.
Sorry, guys, but I still need help
Phil
I'm sorry I am not getting it at all
puts [clock format [clock scan Saturday -base [clock scan "1165035600 +
1 day"]]]
unable to convert date-time string "1165035600 + 1 day"
% puts [clock format [clock scan Saturday -base [clock scan "[clock
scan "1165035600" -format "%m/%d/%Y"] + 1day"]]]
bad switch "-format": must be -base or -gmt
I at this point don't know when or if I'll get it because I can't seem
to process how to do it.
Phil
When you are working with dates in Tcl, there are two kinds of time
values:
1. an epoch time (the number of seconds since jan 1, 1970, which looks
like a 10-digit number), or
2. a datetime string (such as "11/25/2006" or "tomorrow", etc)
When you have an epoch time, that's the value you use in [clock
format ...] or the "-base" value in [clock scan ...]
When you have a datetime string, that's what you use in [clock scan ...]
You can't treat an epoch time as a datetime string, which is what you're
trying to do above. Also, you don't need to chain [clock format]s and
[clock scan]s together.
So:
set expdate 1165035600
set tomorrow_epoch [clock scan tomorrow -base $expdate]
# the above command means: when the time was $expdate, what will
# the time be tomorrow?
set next_saturday_epoch [clock scan saturday -base $tomorrow_epoch]
puts "starting time: [clock format $expdate]"
puts "the next day: [clock format $tomorrow_epoch]"
puts "the following saturday : [clock format $next_saturday_epoch]"
OK - clock scan is to convert human readable dates into internal clock
values (generally number of seconds since epoch, i.e. 1970) If you
already have a clock value, you can use it directly as your base without
the extra scan stuff (you'll still have the outer scan that handles the
relative day stuff.
(assume variable val holds the numeric time value
you already have from earlier processing)
set nextSat [clock scan "Next Saturday" -base $val]
now I can't test this at the moment, so I don't know if the next
modifier handles it the way you want, but if this gives you the same
day if $val happens to be on a Saturday and you need to do the +1 day
thing you can do that with another scan (but still use your value as
the original base
set nextSat [clock scan "Next Saturday" -base \
[clock scan Tomorrow -base $val]]
or perhaps more readable as 2 statements instead of nested all together
set tomorrow [clock scan Tomorrow -base $val]
set nextSat [clock scan "Next Saturday" -base $tomorrow]
Bruce
What do you mena "fixed Saturday"? The code works as advertised for me.
Assuming your expDate is already in epoch time:
set saturday [clock scan Saturday -base $expDate]
should be ok. Oh, except that it doesn't handle if the date is already
a Saturday. Then Kevin Kenny's version should work:
set expTimeTomorrow [clock scan tomorrow -base $expDate]
set saturday [clock scan Saturday -base $expTimeTomorrow]
Test it out on a few dates you gave as example:
foreach day {11/25/2006 12/2/2006 12/9/2006} {
# convert date to epoch time in expDate:
set expDate [clock scan $day]
# increment by 1 day:
set expTimeTomorrow [clock scan tomorrow -base $expDate]
# ask Tcl for saturday's time:
set saturday [clock scan Saturday -base $expTimeTomorrow]
puts [clock format $saturday -format "%m/%d/%Y"]
}
On second thought, Uwe's answer is much more elegant, straight-forward
and human readable. I forgot that Tcl's clock command understands
"next":
set saturday [clock scan {next Saturday} -base $expDate]
ok, now, this is where it gets a bit bad, but I just don't know how to
do this
How do I calculate 12:00AM Saturday immediately after the avlue
116035600
I'm sorry I just don't know this stuff
Phil
** UPDATE**
I took a wild, wild guess and came up with this:
[TCL]
proc CALCULATE_XML_EXPDATE {{triviaAttrs {}} {triviaAttrCount 0}
{hasPassedTrivia 1}} {
if {[string length [info procs {IS_LIST}]] == 0} then source
./tcl_string_tools.tcl
if {![info exists triviaAttrs] || ![IS_LIST $triviaAttrs] || [llength
$triviaAttrs] == 0} then \
return [clock scan {next Saturday} -base [clock scan now]]; # RETURN
THE NEXT SATURDAY SINCE NO expDate COULD BE FOUND
# SINCE $triviaAttrs HAS TO BE AN EXISTING LIST WITH llength > 0 TO
GET HERE, JUST MAKE SURE $triviaAttrCount REFLECTS THAT
if {[expr {$triviaAttrCount == 0}]} then $triviaAttrCount = [expr
{[XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs]}]
# GET THE LAST expDate ATTRIBUTE VALUE IN $triviaAttrs
set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
{expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
$triviaAttrCount) - 1))}]]
# WILL RETURN THE FOLLOWING SATURDAY AFTER $expDate ROUNDED
AUTOMATICALLY TO 00:00
return [clock scan {next Saturday} -base $expDate]
}
[/TCL]
Sorry I can't test it. I have no idea how to get this to work in
Windows but it seems to work in UNIX. Help and review appreciated
Phil
> now I can't test this at the moment, so I don't know if the next
> modifier handles it the way you want, but if this gives you the same
> day if $val happens to be on a Saturday and you need to do the +1 day
> thing you can do that with another scan (but still use your value as
> the original base
>
> set nextSat [clock scan "Next Saturday" -base \
> [clock scan Tomorrow -base $val]]
>
> or perhaps more readable as 2 statements instead of nested all together
>
> set tomorrow [clock scan Tomorrow -base $val]
> set nextSat [clock scan "Next Saturday" -base $tomorrow]
if you want the first Saturday in a Timeframe starting with a certain
date and excluding that day this will suffice:
set datetime [ clock scan $datestring ]
set nextSat [ clock scan "Next Saturday" -base $datetime ]
uwe
If you post code, make sure it is suitably formatted for posting on
the Web:
- lines no longer than 70 chars, otherwise they will get wrapped and
thus are no longer valid TCL code
- continuation lines properly wrapped
- proper syntax for the mentioned language in the first place
The code you posted shows up here like this:
| proc CALCULATE_XML_EXPDATE {{triviaAttrs {}} {triviaAttrCount 0}
| {hasPassedTrivia 1}} {
| if {[string length [info procs {IS_LIST}]] == 0} then source
| ./tcl_string_tools.tcl
| if {![info exists triviaAttrs] || ![IS_LIST $triviaAttrs] || [llength
| $triviaAttrs] == 0} then \
| return [clock scan {next Saturday} -base [clock scan now]]; # RETURN
| THE NEXT SATURDAY SINCE NO expDate COULD BE FOUND
|
| # SINCE $triviaAttrs HAS TO BE AN EXISTING LIST WITH llength > 0 TO
| GET HERE, JUST MAKE SURE $triviaAttrCount REFLECTS THAT
| if {[expr {$triviaAttrCount == 0}]} then $triviaAttrCount = [expr
| {[XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs]}]
|
| # GET THE LAST expDate ATTRIBUTE VALUE IN $triviaAttrs
| set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
| {expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
| $triviaAttrCount) - 1))}]]
| # WILL RETURN THE FOLLOWING SATURDAY AFTER $expDate ROUNDED
| AUTOMATICALLY TO 00:00
| return [clock scan {next Saturday} -base $expDate]
| }
| [/TCL]
No way this will run in *any* TCL interpreter, neither Windows nor
Linux.
Things to keep in mind:
- if/then/else:
You usually require parens around the 'then' part.
This will not work as expected:
if {[string length [info procs {IS_LIST}]] == 0} \
then source ./tcl_string_tools.tcl
Instead of sourcing the file it will trigger an syntax error.
You almost always need parens for the 'then' clause (and the
elseif/else as well):
if {[string length [info procs {IS_LIST}]] == 0} \
then { source ./tcl_string_tools.tcl }
Only exception is when the 'then' clause is *one* *word* only.
if {$something} then continue
if {$something} then break
But even that I would prefer to write as:
if {$something} then { continue }
if {$something} then { break }
- TCL is not Perl: your code
if {[expr {$triviaAttrCount == 0}]} \
then $triviaAttrCount = \
[expr {[XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs]}]
is not TCL syntax. You want:
if {$triviaAttrCount == 0} then {
set triviaAttrCount \
[XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs]
}
(no 'expr' necessary inside 'if' clauses, parens around the 'then'
clause, proper variable assignment syntax).
- called functions may fail:
| set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
| {expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
| $triviaAttrCount) - 1))}]]
The lsearch above may fail to find a match. If it does not find a
match, it returns -1. Is the calculation still valid then?
Shouldn't you handle a failure?
HTH
R'
Forgot an important one:
| if {![info exists triviaAttrs] || ![IS_LIST $triviaAttrs] || [llength
| $triviaAttrs] == 0} then \
| return [clock scan {next Saturday} -base [clock scan now]]; # RETURN
Especially with 'return' statements, the parens in the 'then' clause
are vital.
if {$something} return 0
will *not* return '0' if '$something' is true, it will return an empty
string. The '0' is executed as command if the condition is false, and
will most likely trigger a no-such-command error.
This is why I insist on parens around the then/else clauses here
during code reviews. We had maintenance edits which changed
if {$yadda} return
into
if {$yadda} return 0
In heavy duty review mode, those are likely to pass by the reviewer
since they *look* ok on the first glance. Searching for those later
is a nightmare.
R'
I'm sorry but why? I was told by other TCL developers that you do *NOT*
need "parens" (you mean braces, right?) around the "then" clause as it
is valid TCL syntax, in fact, I've always used braces around "if-then"
clauses in TCL, but other people here do not, so I was trying to compat
with their standards so I don't seem too dumb on here
>
> Only exception is when the 'then' clause is *one* *word* only.
> if {$something} then continue
> if {$something} then break
> But even that I would prefer to write as:
> if {$something} then { continue }
> if {$something} then { break }
Is this TCL coding standard or something else? Now I'm just plain
confused
>
> - TCL is not Perl: your code
> if {[expr {$triviaAttrCount == 0}]} \
> then $triviaAttrCount = \
> [expr {[XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs]}]
>
> is not TCL syntax. You want:
>
> if {$triviaAttrCount == 0} then {
> set triviaAttrCount \
> [XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs]
> }
>
Actually I was thinking not in Perl but in PHP; I barely know Perl.
> (no 'expr' necessary inside 'if' clauses, parens around the 'then'
> clause, proper variable assignment syntax).
[XML_GET_ELEMENT_ATTR_COUNT] returns an integer, but I had to be sure
it was an integer in this case else it would throw an "expected integer
but got.." TCL error. Don't know how to cast in TCL, sorry, in PHP
it's a breeze.
>
> - called functions may fail:
> | set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
> | {expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
> | $triviaAttrCount) - 1))}]]
>
> The lsearch above may fail to find a match. If it does not find a
> match, it returns -1. Is the calculation still valid then?
> Shouldn't you handle a failure?
>
I thought I logically did that by ensuring that $triviaAttrs has listed
content, otherwise, it wouldn't even get to that step.
> HTH
> R'
I updated the proc:
[TCL]
proc CALCULATE_XML_EXPDATE {{triviaAttrs {}} {triviaAttrCount {0}}
{hasPassedTrivia {1}}} {
if {[string length [info procs {IS_LIST}]] == 0} {
source [file join [file dirname [info script]]
tcl_string_tools.tcl]; # FAILS ON MY WINDOWS BOX
}
# RETURN THE NEXT SATURDAY SINCE NO expDate COULD BE FOUND
if {![info exists triviaAttrs] || ![IS_LIST $triviaAttrs] || [llength
$triviaAttrs] == 0} {
return [clock scan {next Saturday} -base [clock scan now]]
}
# SINCE $triviaAttrs HAS TO BE AN EXISTING LIST WITH llength > 0 TO
GET HERE,
# JUST MAKE SURE $triviaAttrCount REFLECTS THAT
if {$triviaAttrCount == 0} { set triviaAttrCount
[XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs] }
# GET THE LAST expDate ATTRIBUTE VALUE IN $triviaAttrs
set expDate \
[lindex $triviaAttrs \
[expr {[lsearch $triviaAttrs {expDate}] + 1 + \
($triviaAttrCount * (([llength $triviaAttrs] /
$triviaAttrCount) - 1)) \
}\
]\
]
# WILL RETURN THE FOLLOWING SATURDAY AFTER $expDate ROUNDED
#AUTOMATICALLY TO 00:00
Because that is how the if statement is documented to work (like you,
I'm assuming that Ralf meant "braces" rather than "parens").
Look at the man page for "if" and you'll see this:
if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ... ?else? ?bodyN?
the thing after "then" is "body1" and must be a Tcl word. That means
either a single (human) word, or a collection of words that are joined
together with a quoting mechanism, typically curly braces.
>I was told by other TCL developers that you do *NOT*
> need "parens" (you mean braces, right?) around the "then" clause as it
> is valid TCL syntax, in fact, I've always used braces around "if-then"
> clauses in TCL, but other people here do not, so I was trying to compat
> with their standards so I don't seem too dumb on here
>
>> Only exception is when the 'then' clause is *one* *word* only.
>> if {$something} then continue
>> if {$something} then break
>> But even that I would prefer to write as:
>> if {$something} then { continue }
>> if {$something} then { break }
>
> Is this TCL coding standard or something else? Now I'm just plain
> confused
Remember that Tcl quoting is a tool, not a rule. [1] You never *have* to
use curly braces. They exist as a way to group several words (in the
human sense) together into a single "word" (in the Tcl sense).
I think as a general rule, people don't use curly braces for a
single-word body of an if statement simply because it reads better. From
the perspective of the interpreter though, the following are all
functionally identical:
if {$something} continue
if {$something} {continue}
if {$something} "continue"
if {$something} [some command that returns "continue"]
if {$something} then continue
if {$something} then {continue}
... and so on ...
The choice of when or if to use quotes, and what type of quotes, is
entirely up to the programmer, generally dictated by context. I'm
convinced that once someone fully understands that single fact, all
their Tcl quoting problems will vanish forever.
[1] http://www.tclscripting.com/articles/jan06/article3.html
The man page was Greek, but your link totally spoke my language, much
more simplistically. Thanx I will remember the rule about braces vs
not-braces vs. then vs quotes vs whtever else
> The choice of when or if to use quotes, and what type of quotes, is
> entirely up to the programmer, generally dictated by context. I'm
> convinced that once someone fully understands that single fact, all
> their Tcl quoting problems will vanish forever.
It's not snappy or funny, thus not QOTW material, but what he said
needs to be highlighted, restated, and taken to heart by anyon who hopes to
have any chance of calling themselves competent in Tcl. If quotes are
voodoo magic that get thrown at a problem, one is not doing software
engineering, nor computer science. If one truly understands the reason for
each and every use of quotes (even if its "to make the code clearer to
human readers" or "because a maintenance programmer might need to change my
bareword to a string containing a space"), that's a scientific and
engineering approach to the problem at hand.
The snappy/funny version is "you only need curly braces when you need
curly braces" :-)
> The snappy/funny version is "you only need curly braces when you need
> curly braces" :-)
You need braces when crutches don't keep you upright anymore ;-)
uwe
North American version:
You need braces when your code lacks bite.
British version:
You need braces when your code is caught with its trousers down.
And they say comedy is hard. Pshaw!
Yes, of course 'braces'. I always mix them up in speech.
Sorry for the sloppy wording in a response which was meant to
clarify.
| > But even that I would prefer to write as:
| > if {$something} then { continue }
| > if {$something} then { break }
|
| Is this TCL coding standard or something else?
There is no general world wide 'TCL coding standard' as such
-- or at least none that I'm aware of. It is my own personal
preference derived from 15+ years of TCL usage and maintenance.
And from one long night debug session where the culprit line turned
out to be
if {$foo} return 0
at which I looked several times and did not recognize the problem.
| > [expr {[XML_GET_ELEMENT_ATTR_COUNT $triviaAttrs]}]
--<snip-snip>--
| [XML_GET_ELEMENT_ATTR_COUNT] returns an integer, but I had to be
| sure it was an integer in this case else it would throw an "expected
| integer but got.." TCL error.
'expr' will not turn the return value of XML_GET_ELEMENT_ATTR_COUNT
into an integer. It will try to use the return value as an expression
and make the best of it if it is not a plain number.
For example with a floating point value:
expr 1.0
=> 1.0
it simply returns the number as-is. 0.0 is false, everything else is true.
Or with booleans:
set foo true
expr {$foo}
=> true
set foo false
expr {$foo}
=> false
If you then use these boolean true/false or floating point return
values of 'expr' in places where an integer is expected, it will fail
with exactly the error message you quoted.
If you need to turn a _number_ into an integer, indeed 'expr' is the
way to go (expr {round($number)} or expr {int($number)}), but these
will also complain if $number is not a number, but some arbitrary
text.
To check if $something can be used as a number, use
string is integer -strict $something
string is double -strict $something
| > - called functions may fail:
| > | set expDate [lindex $triviaAttrs [expr {[lsearch $triviaAttrs
| > | {expDate}] + 1 + ($triviaAttrCount * (([llength $triviaAttrs] /
| > | $triviaAttrCount) - 1))}]]
| >
| > The lsearch above may fail to find a match. If it does not find a
| > match, it returns -1. Is the calculation still valid then?
| > Shouldn't you handle a failure?
|
| I thought I logically did that by ensuring that $triviaAttrs has
| listed content, otherwise, it wouldn't even get to that step.
I haven't checked the code too closely, but a llength of > 0 does not
automatically mean that the list indeed contains a 'expDate' element.
But of course this depends on the input data. It may well be that a
llength > 0 always implies an 'expDate' element in the list with your
input data. Personally, I prefer to code on the safe side and catch
those cases where the lsearch fails for whatever reason.
HTH
R'
Eventually, everyone learns how to avoid such things.
And people ask why I write comparisons like
if {0 == $x} {...}
instead of
if {$x == 0} {...}
:-)
I am going to ask! Why do you? (0 == $x) confuses the crap out of me
Phil
Because in C, both
if (x == 0)
and
if (0 == x)
are legal and mean the same thing.
if (x = 0)
means something entirely different, and compiles.
if (0 = x)
doesn't compile.
Especially in ill-defined languages like C, one tends to develop all
kinds of habits, and they sometimes carry over.
I also never use > or >=, but that's just because it's more readable (at
least for people who write left to right) to always have the bigger
value on the right. So (a < b & b < c) reads as "b is between a and c".
Let awareness bloom:
http://www.tcl.tk/doc/styleGuide.pdf
http://wiki.tcl.tk/2?tcl+style+guide
That does explain things, as I never really learned C. I went straight
from HTML to Javascript to Perl to Tcl to PHP to Java, skipping C
altogether. So of course to me "if (0 == x)" is simply bizarre and
would never write "if (0 = x)" since in my ASP days it would be "if x =
0 then"
Phil
> if (x = 0)
> means something entirely different,
Note that it always evaluates to *false*. Ironically, the comparison
x == 0 is definitely *true* after that test.
--
Donald Arseneau as...@triumf.ca
And that's usually how one notices, methinks. "Why doesn't the printf()
right at the start of the 'then' branch even print??"
in what language? In PHP it would evaluate to a parse error
In C, as we already discussed. :-) Obviously I don't have to worry about
making the same mistake in Tcl.
Sorry never learned C. I went from the HTML camp to Javascript to some
Java to Perl to ASP to Tcl to PHP.
Thanks!
R'
Thanks as well. I printed it out and will study it thoroughly
Phil
In which case you'll appreciate that it's the same in Java and Perl
(both languages inherit behaviors from C since well.. back then
everybody knows C!)
Example perl code:
my $x = 1;
if ($x = 0) {
print "Never going to execute this!";
}
print "And now \$x is $x\n";