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

Making public/private tcl proc pairs

452 views
Skip to first unread message

Thomas MENEZ

unread,
May 30, 2012, 8:17:02 PM5/30/12
to
Hi there !
I am trying to find a generic way to implement public/private proc
pairs.
What do you think of my solution below ?

namespace eval toto {

proc tutu { a b } {
[namespace current]::_[namespace tail [lindex [info level 0] 0]]
{*}[lrange [info level 0] 1 end]
}

proc _tutu { a b } {
puts "called with a=$a b=$b!"
}
}

::toto::tutu a1 b1

Thanks

Thomas

menez....@gmail.com

unread,
May 30, 2012, 8:25:47 PM5/30/12
to
I have made some benchmarks. My above solution is more than an order of magnitude (10x) slower than the following code :

(...)
proc tutu { a b } {
return [::toto::_tutu $a $b]
}
(...)

How uncool is that !? Is there any better solution ?

Gerald W. Lester

unread,
May 30, 2012, 9:04:30 PM5/30/12
to
Why not just call ::toto::_tutu a1 b1

There is no such thing as private procs in "base" Tcl.


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

Gerald W. Lester

unread,
May 30, 2012, 9:05:37 PM5/30/12
to
Yes, just call ::toto::_tutu directly!

There is no such things as private procedures in base Tcl.

Uwe Klein

unread,
May 31, 2012, 5:49:16 AM5/31/12
to
Gerald W. Lester wrote:
> On 5/30/12 7:17 PM, Thomas MENEZ wrote:
>
>> Hi there !
>> I am trying to find a generic way to implement public/private proc
>> pairs.
>> What do you think of my solution below ?
>>
>> namespace eval toto {
>>
>> proc tutu { a b } {
>> [namespace current]::_[namespace tail [lindex [info level 0] 0]]
>> {*}[lrange [info level 0] 1 end]
>> }
>>
>> proc _tutu { a b } {
>> puts "called with a=$a b=$b!"
>> }
>> }
>>
>> ::toto::tutu a1 b1
>
>
> Why not just call ::toto::_tutu a1 b1
>
> There is no such thing as private procs in "base" Tcl.
>
>
Maybe thomas thought about interp / save interp and linking via interp alias ..
?

uwe

Thomas MENEZ

unread,
May 31, 2012, 8:11:57 PM5/31/12
to
Not at all, it was the usual private/public c++ notion...

I have figured out a handy solution by using an
ancillary proc defProc.

proc defProc { namespace procName } {
eval "namespace eval $namespace { \
proc $procName { args } {\
return \[${namespace}::_$procName {*}\$args\]\
}\
}\
"
}

which actually builds the above advocated &
simpler & faster code. Here is my typical
namespace def :

namespace eval toto {

defProc toto tutu1
defProc toto tutu2
defProc toto tutu3
defProc toto tutu4

(...)

proc _tutu1 { a b } {
puts "called with a=$a b=$b!"
}

(...)
}

Hence, only tutu1/2/3/4 will be called from outside
the toto namespace.

My purpose is to have a clean list of the namespace
API at the top of the namespace definition file.

Namespaces won't allow to do much more...
I will move on to tcloo soon I guess.
Regards,
Thomas


Uwe Klein

unread,
Jun 1, 2012, 3:12:03 AM6/1/12
to
I feel dense.

Isn't that what [namespace export]/ [.. import] provides ?
>

namespace eval a {
namespace export x y z

proc x args {
puts x:[list $args]\ ns\ [namespace current]
}

x a b c d e
}

namespace eval b {
namespace import ::a::x

x 1 2 3 4 5
}

uwe

Thomas MENEZ

unread,
Jun 1, 2012, 7:17:32 AM6/1/12
to
I never want to have the ability to avoid using
the originating namespace as a prefix, so that
I never use import/export commands.
To me, using the originating namespace
as prefix is good practice for code
legibility.

Gerald W. Lester

unread,
Jun 1, 2012, 9:58:47 AM6/1/12
to Thomas MENEZ
> simpler& faster code. Here is my typical
> namespace def :
>
> namespace eval toto {
>
> defProc toto tutu1
> defProc toto tutu2
> defProc toto tutu3
> defProc toto tutu4
>
> (...)
>
> proc _tutu1 { a b } {
> puts "called with a=$a b=$b!"
> }
>
> (...)
> }
>
> Hence, only tutu1/2/3/4 will be called from outside
> the toto namespace.

Really?

Have you tried: toto:_tutu1 a b

Because for me, the following works:
% ::toto::tutu1 a b
called with a=a b=b!
% ::toto::_tutu1 a b
called with a=a b=b!
%

As I keep saying, THERE IS NO SUCH THING AS A PRIVATE PROCEDURE IN TCL.

Gerry Snyder

unread,
Jun 1, 2012, 11:08:42 AM6/1/12
to
On 6/1/2012 4:17 AM, Thomas MENEZ wrote:
>
> I never want to have the ability to avoid using
> the originating namespace as a prefix, so that
> I never use import/export commands.
> To me, using the originating namespace
> as prefix is good practice for code
> legibility.

Tcl is not as good as some other languages at keeping folks who want to
write bad code from doing so.

It is much better at allowing folks who want to write good code to do so.


Gerry


Erik Leunissen

unread,
Jun 1, 2012, 12:32:10 PM6/1/12
to
On 01/06/12 02:11, Thomas MENEZ wrote:

>
> Not at all, it was the usual private/public c++ notion...
>

Are you looking for an object oriented language implementation or
features thereof ?

See: http://wiki.tcl.tk/970

Erik.
--
leunissen@ nl | Merge the left part of these two lines into one,
e. hccnet. | respecting a character's position in a line.

Thomas MENEZ

unread,
Jun 1, 2012, 3:53:08 PM6/1/12
to
On Jun 1, 3:58 pm, "Gerald W. Lester" <Gerald.Les...@KnG-
> | Email: Gerald.Les...@kng-consulting.net                                |
> +------------------------------------------------------------------------+

Yes it does indeed, I have no problem with that, but as per my coding
rules, I never use "_" prefixed _procs in my code.

Thomas MENEZ

unread,
Jun 1, 2012, 3:54:26 PM6/1/12
to
As I said earlier in this thread, I am trying out tcloo these days...

Andreas Leitgeb

unread,
Jun 2, 2012, 5:06:30 AM6/2/12
to
Thomas MENEZ <menez....@gmail.com> wrote:
>> > proc defProc { namespace procName } {
>> >    eval "namespace eval $namespace { \
>> >    proc $procName { args } {\
>> >            return \[${namespace}::_$procName {*}\$args\]\
>> >    }\
>> >    }\
>> >    "
>> > }

proc defProc {namespace procName} {
set callTo [list ${namespace}::_$procName]
namespace eval $namespace [list proc $procName args "$callTo {*}\$args"]
}

is a shorter and safer (against uncommon namespace or proc names) version.

Or let it obtain the outer namespace itself, and do the export, too:

proc defProc {procName} {
set namespace [uplevel 1 namespace current]
set callTo [list ${namespace}::_$procName]
namespace eval $namespace [list proc $procName args "$callTo {*}\$args"]
namespace eval $namespace [list namespace export $procName]
}

For later versions of Tcl, you may also want to change callTo:

set callTo [list tailcall ${namespace}::_$procName]

Donal K. Fellows

unread,
Jun 5, 2012, 5:25:01 PM6/5/12
to
On 01/06/2012 20:54, Thomas MENEZ wrote:
> As I said earlier in this thread, I am trying out tcloo these days...

Well, it does do concealment of methods (defaulting to "only make a
method public if it starts with a lower-case letter") but isn't very
serious about it. It also turns out to be very useful to not be super-
strict with enforcement, as that makes doing callbacks of various sorts
much easier. ("Concealment" is probably the best word for what is going
on, as non-public methods are just not advertised.)

Another scheme you could use for public/private methods is to put the
private methods in a separate namespace and use [namespace path] to make
them visible when *in* the public namespace, but not *via* it. That
sounds very complicated, but isn't. (The downside is that the two don't
share where they keep their variables; [namespace upvar] helps.)

namespace eval toto {
proc tutu { a b } {
_tutu $a $b
}
namespace export *
namespace eval private {
namespace import ::toto::*
proc _tutu { a b } {
puts "called with a=$a b=$b!"
}
}
namespace path ::toto::private
}
toto::tutu 1 2 ;# works
toto::_tutu 3 4 ;# error, no such command

Tcl's *real* mechanism for making things shrouded is by partitioning
between interpreters and using aliased and hidden commands to link
between. I suspect you're working too hard though. :-)

Donal.

Thomas MENEZ

unread,
Jun 7, 2012, 7:55:36 AM6/7/12
to
On Jun 5, 11:25 pm, "Donal K. Fellows"
Hello Donal

That sounds very clever, and that also might
allow me to have one tcl "header" file for the upper
namespace and procs declarations and a tcl "core" file
with the lower namespace and proc definition.
Nice suggestion.

Thomas
0 new messages