Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Need some hellp understanding one of the examples given in the "The Tcl Programming Language"

62 views
Skip to first unread message

dave....@gmail.com

unread,
Jan 23, 2018, 10:01:48 AM1/23/18
to
Need some help understanding one of the examples given in the "The Tcl Programming Language"


I am new to TCL and have been trying to learn TCL using "The Tcl Programming Language: A Comprehensive Guide" and . I am confused with this particular example and am will highly appreciate if any of you can help me. The objective of this example is to redefine 'puts' command so that the modified puts command will output in upper case.

------------------------
rename puts builtin_puts

proc puts args {
set str [string toupper [lindex $args end]]
builtin_puts {*}[lreplace $args end end $str]
}
------------------------

What I am confused is with the command " set str [string toupper [lindex $args end]] ". I am wondering whats the significance of using [lindex $args end]] here. if [lindex $args end]] is printed inside the same function (
puts [lindex $args end]]), it prints the actual value passed to the function, not the value at the index. I am using TCL version => (Tcl8.6.5 / Tk8.6.5) on an Ubuntu box.

Can you please advise?

Thanks in advance

Gerald Lester

unread,
Jan 23, 2018, 10:17:33 AM1/23/18
to
Are you saying you changed the definition of the above puts proc? If
so, could you post what you changed it to (there is likely a something
wrong with the changes)?

In the above procedure, the [set str ...] uppercase what will be written
to the real puts, now called builtin_puts. The uppercase string is
substituted for the real string via the lreplace on the next line.


--
+----------------------------------------------------------------------+
| Gerald W. Lester, President, KNG Consulting LLC |
| Email: Gerald...@kng-consulting.net |
+----------------------------------------------------------------------+

Ralf Fassel

unread,
Jan 23, 2018, 11:06:08 AM1/23/18
to
* dave....@gmail.com
| proc puts args {
| set str [string toupper [lindex $args end]]
| builtin_puts {*}[lreplace $args end end $str]
| }
| ------------------------
>
| What I am confused is with the command " set str [string toupper
| [lindex $args end]] ". I am wondering whats the significance of using
| [lindex $args end]] here.

If you check the 'puts' manpage, you see that puts has several forms of
invocation:

SYNOPSIS
puts ?-nonewline? ?channelId? string

In your example, only the last argument 'string' is to be converted to
uppercase, not the "-nonewline" or the "channelId". Thus you pick that
by lindex end, replace it with the uppercase form, and the call the
original 'puts' with *all* arguments.

I.e. all of
puts string
puts stdout string
puts -nonewline stdout string
do The Right Thing.

| if [lindex $args end]] is printed inside the same function ( puts
| [lindex $args end]]), it prints the actual value passed to the
| function, not the value at the index.

Not sure what you mean by this. The index 'end' refers to the last
element in a list, which for a one-element list is identical to the only
element of the list.

HTH
R'

dave....@gmail.com

unread,
Jan 23, 2018, 11:33:24 AM1/23/18
to

> >
> >
> > I am new to TCL and have been trying to learn TCL using "The Tcl Programming Language: A Comprehensive Guide" and . I am confused with this particular example and am will highly appreciate if any of you can help me. The objective of this example is to redefine 'puts' command so that the modified puts command will output in upper case.
> >
> > ------------------------
> > rename puts builtin_puts
> >
> > proc puts args {
> > set str [string toupper [lindex $args end]]
> > builtin_puts {*}[lreplace $args end end $str]
> > }
> > ------------------------
> >
> > What I am confused is with the command " set str [string toupper [lindex $args end]] ". I am wondering whats the significance of using [lindex $args end]] here. if [lindex $args end]] is printed inside the same function (
> > puts [lindex $args end]]), it prints the actual value passed to the function, not the value at the index. I am using TCL version => (Tcl8.6.5 / Tk8.6.5) on an Ubuntu box.
> >
> > Can you please advise?
>
> Are you saying you changed the definition of the above puts proc? If
> so, could you post what you changed it to (there is likely a something
> wrong with the changes)?
>
> In the above procedure, the [set str ...] uppercase what will be written
> to the real puts, now called builtin_puts. The uppercase string is
> substituted for the real string via the lreplace on the next line.
>
>
> --



Many Thanks for the quick reply Gerald
Yes, this is the program exactly like whats given in the book

------
rename puts builtin_puts

proc puts args {
set str [string toupper [lindex $args end]]
builtin_puts {*}[lreplace $args end end $str]
}
------

--RUN---
% puts "Hello, World!"
HELLO, WORLD!


It works exactly like author says in the book. The modified puts takes as string and output Upper Case string. Where I am confused is the use of "[lindex $args end]". Say for example if I modify the above program by removing lindex and lreplace, it works the exact way.

rename puts builtin_puts

proc puts args {
set str [string toupper $args]
builtin_puts {*}$str
}

--RUN---
% puts "hello world"
HELLO WORLD


Also I tried to understand how lindex works on function arguments by writing a simple program and can see that index is not applied at all. Please see below.

proc testIndex args {
builtin_puts [lindex $args end]
}

--RUN---
% testIndex "Program to test tcllindex"
Program to test tcllindex


I was expecting only the word at the last index to be printed which is "tclindex".

dave....@gmail.com

unread,
Jan 23, 2018, 11:52:51 AM1/23/18
to
Thanks Raif. I think I am confused with the behaviour of lindex.
From tclsh if I do this,

% set s "This is from tclsh"
% lindex $s end -> "tclsh"

But if same string is passed as an argument to a function in which lindex is applied on the argument, the behaviour is different and the entrie string is printed.

proc testIndex args {
puts [lindex $args end]
}

--RUN--
% testIndex "This is from tclsh"
This is from tclsh


May be I should go deep in to the other chapters to get a deeper understanding.

Rich

unread,
Jan 23, 2018, 12:32:33 PM1/23/18
to
Yes, you likely have not reached that part of the book yet. The "args"
parameter is special on Tcl procs. It provides you a "list" of all
remaining arguments, rather than a "string" holding the value of just
one argument.

In your second example, where you quote the string "This is from tclsh"
you receive in "args" a list containing one element, that one element
being the string "This is from tclsh". Then when you do lindex--end on
args, you get the last element of the list, which is the string "This
is from tclsh".

In your first example, you passed a string directly into lindex. When
you do that, Tcl will attempt to convert the string into a list, and
when it does that automatically, it converts each run of non-whitespace
characters into a separate list element [1]. So what you have given
lindex, after Tcl converts the string to a list for you, is a list with
four elements:

s[0] = This
s[1] = is
s[2] = from
s[3] = tclsh

And when you ask for the "end" element, you get s[3]'s contents, which
is "tclsh".

If you change your "textIndex" proc's definition to "proc testIndex {s}
{" [1] and then change "$args" to "$s" inside the lindex, you'll get
the same result both times.


[1] This is not the "full" story, but it good enough for the point you
have reached in your Tcl book at this time.

Also, you should be warned that relying on Tcl's magic conversion from
string to list can be dangerous, and while it does happen, you should
be careful to only make it happen when you really know it is what you
truly want. You can achieve some odd, input data dependent, error
messages if it happens and you had not planned for it to happen.


Robert Heller

unread,
Jan 23, 2018, 1:06:14 PM1/23/18
to
In the case of testIndex, the argument args is a *list* of its arguments.
Specificly, testIndex is being passed one argument, but could have any number
of arguments. The argument name "args" has special meaning -- it is always a
*list* of all of the [remaining] arguments passed.

In the case of:

% set s "This is from tclsh"
% lindex $s end -> "tclsh"

The variable s is set to the string "This is from tclsh", which gets converted
to the list {This is from tclsh} when passed to lindex, the last element of
which is the string "tclsh".

Check out this snippet:

% proc testIndex1 {s} {
puts [lindex $s end]
}
% testIndex1 "This is from tclsh"
tclsh

And this:

% proc testIndex args {
puts [lindex $args end]
}
% eval testIndex "This is from tclsh"
tclsh

>
>
> May be I should go deep in to the other chapters to get a deeper
> understanding.
>

--
Robert Heller -- 978-544-6933
Deepwoods Software -- Custom Software Services
http://www.deepsoft.com/ -- Linux Administration Services
hel...@deepsoft.com -- Webhosting Services

dave....@gmail.com

unread,
Jan 23, 2018, 4:24:30 PM1/23/18
to
@Rich and @Rober Heller. Thanks heaps for the detailed reply and your time. Much appreciated. It clears all the doubts I have.
0 new messages