Check-in [0b38fa0683]

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Split out the discussion.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0b38fa068347f284e0352624bbb4609c50d4fa9c292a6ae6d7cd2845fe4b9804
User & Date: dkf 2018-03-08 14:19:26
Context
2018-03-08
14:24
More formatting tweaking check-in: 072c7a281d user: dkf tags: trunk
14:19
Split out the discussion. check-in: 0b38fa0683 user: dkf tags: trunk
2018-03-05
22:30
Updated TIP #496 (-placeholder option) according to recent discussions on tcl-core check-in: ad2ce4f845 user: fvogel tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added tip/490-discussion.md.








































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# Discussion for TIP #490
See [TIP #490](490.md) for the context of this.

## Issue 1: are really all oo use-cases covered ?

Gosts like multiple inheritance, mixins, filters whatever are calling...

## Issue 2: All backward compatibility issues covered ?

I see the following covered ones:

* no oo -> `uplevel 1 namespace current` is used, o.k.
* oo with explicit `namespace eval` -> o.k.

Are there eventually other cases not discussed here?

## Issue 3: performance loss

There is a performance penalty due to the modification described in "implementation".

To not decrease performance would require to introduce new commands, what I think is not good.
We would loose the flexibility and backward compatibility to just insert a 3rd party package, which may call "uplevel 1 msgcat::mc tag", and it works.

For performance enthusiasts, one may use "mcn", which may be little faste than former msgcat.

## Issue 4: does not work for tcl 8.6

The `self` command does not work for tcl 8.6 within class definition scripts.

It returns the error message:

<verb>
wrong # args: should be "self arg ?arg ...?"
</verb>

# Alternatives

## Use a mixin

Proposed by Donal Fellows

Each class which wants to use message catalogs require a call to `mixin msgcat::MessageCatalogAware`.

Then, the following commands are available and correspond to the `msgcat::` commands:

* my mc
* my mcmax
* my mcexists

All other mc-commands are not available within classes and should be used outside of a class.

# Examples

Within the following example, the message catalog for the package is loaded outside the method definitions.

A class "Foo" is created and the msgcat capabilities are activated by the mixin.

Then, a method is defined, which uses the message catalog of the namespace.

<pre>
namespace eval ::foo {
    msgcat::mcload $dir/msgs
    oo::class create Foo {
        mixin msgcat::MessageCatalogAware
        method printMessage {x y} {
            puts [my mc "FooPrintMessage(%d,%d)" $x $y]
        }
    }
}
package provide foo 1.0
</pre>

The implementation is in tcl fossil in branch
[tip490-msgcat-oo](https://core.tcl.tk/tcl/timeline?r=tip490-msgcat-oo).

## Use own commands for getting and setting message catalogues

Eric Boudallier proposed a solution on [Wiki page "msgcat and TclOO"](http://wiki.tcl.tk/39430)

There is also an addendum by Donal Fellows with an alternate implementation.

## mixin solution where superclass and subclass may not be in different namespaces:

Donal Fellows also provided this solution.

The key then is how to make `msgcat::mc` work (and a few related commands as well). The trick I've thought of is to use the magic powers of `apply` and `tailcall`; here's what we're looking for:

<pre>
namespace eval ::foo {
    msgcat::mcload $dir/msgs
    oo::class create MessageCatalogAware {
        forward mc apply {args {tailcall ::msgcat::mc {*}$args} ::foo}
        unexport mc
    }
    oo::class create Foo {
        mixin MessageCatalogAware
        # ...
    }
    oo::class create Bar {
        mixin MessageCatalogAware
        # ...
    }
}
package provide foo 1.0
</pre>

(I'd use a mixin for this; it's not really about the class itself; it's just about making a capability available.)

It'd be nice to have a way to make that bridging class automatically. Here it is.

<pre>
oo::class create ::msgcat::oobridge {
    superclass oo::class
    self method create {name args} {
        set cls [next $name {*}$args]
        set ns ::[namespace qualifiers [namespace which $cls]]
        foreach cmd {mc mcmax mcexists} {
            oo::define $cls forward $cmd apply [list \
                {cmd args} {tailcall $cmd {*}$args} $ns] \
                ::msgcat::$cmd
            oo::define $cls unexport $cmd
        }
        return $cls
    }
}
</pre>

Now our little package would become:

<pre>
namespace eval ::foo {
    msgcat::mcload $dir/msgs
    msgcat::oobridge create MessageCatalogAware
    oo::class create Foo {
        mixin MessageCatalogAware
        # ...
    }
    oo::class create Bar {
        mixin MessageCatalogAware
        # ...
    }
}
package provide foo 1.0
</pre>

Alternatively, we could plug the capabilities into `oo::define`; the principles of the code are largely the same but the details are little different.

I've been thinking about this more, and I've realised that there is a subtle problem: a superclass and a subclass could be in different namespaces in different packages, and so could reasonably want to use different message catalogs. This means that the bridging code always needs to look up what the context namespace is at runtime, which in turn means that there's no need for clever class manufacturing, and it can all be done with (see section "Implementation" above).

Changes to tip/490.md.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
125
126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
    oo::class create Foo {
        ...
    }
}
package provide foo 1.0
</pre>

# Documentation

There are 4 use-cases to consider (which may be intermixed in the same package):

(with 'Servus!' as translation for 'Hi!')

## Use-Case 1: the package does not use OO

<pre>
namespace import msgcat::*
namespace eval ::N1 {
    mcload $dir/msgs
    proc m1 {} {
        puts [mc Hi!]
    }
}

% N1::m1
-> Servus!
</pre>

## Use-case 2: msgcat is called within a class definition script

<pre>
% namespace import msgcat::*
% namespace eval ::N2 {
    mcload $dir/msgs
    oo::class create C1 {puts [mc Hi!]}
}
-> Servus!
</pre>

## Use-case 3: msgcat is called from a method in an object and the method is defined in a class

<pre>
namespace import msgcat::*
namespace eval ::N3Class {
    mcload $dir/msgs
    oo::class create C1
    oo::define C1 method m1 {
        puts [mc Hi!]
    }
}

# The class object may be used in another namespace
namespace eval ::N3Obj {
    set O1 [::N3Class::C1 new]
}

% $N3Obj::O1 m1
-> Servus!
</pre>

## Use-case 4: msgcat is called from a method of a classless object

<pre>
namespace import msgcat::*
namespace eval ::N4 {
    mcload $dir/msgs
    oo::object create O1
    oo::objdefine O1 method m1 {} {
        puts [mc Hi!]
    }
}

% N4::O1 m1
-> Servus!
</pre>

## Use-case 1 may be emulated in Use-case 2 to 4 using "namespace eval"

Before this extension, a programmer for use-case 2 to 4 must have used "namespace eval" to explicitly specify the package namespace:

<pre>
namespace import msgcat::*
namespace eval ::N4 {
    mcload $dir/msgs
    oo::object create O1
    oo::objdefine O1 method m1 {} {
................................................................................

% N4::O1 m1
-> Servus!
</pre>

This should still work with the new extension for compatibility reasons.

# Usage

There are 4 proposed extensions to current msgcat 1.6.1:


## Extension 1: Extend all msgcat commands to support all 4 use-cases.

So any **msgcat** command will detect the scenario on its own and extract the package namespace automatically.

The commands which are packet-namespace related are: **mc**, **mcexists**, **mcpackagelocale**, **mcforgetpackage**, **mcpackagenamespaceget** (new command, see below), **mcpackageconfig**, **mcset** and **mcmset**.

This has the following advantages (compared to the alternatives):

* no new commands, no learning
* if another foreign procedure is called and the procedure wants to use the callers message catalog, it may just use "uplevel 1 {msgcat tag}" and does not need to know if it is a class or not.

Here is an example for the second advantage:

The tklib package "tooltip" may invoke `msgcat::mc msg` for all textes to get eventual translations (it does something like that but I don't understand it, IMHO broken).
The package namespace of the caller should be used (not the one of the tooltip package).

So:
<pre>
proc ::tooltip::tooltip {widget message} {
    ...
    set message [uplevel 1 {::msgcat::mc $message}]
}
</pre>

This will work in all use-cases, e.g. if `tooltip::tooltip` is called by a method following use-case 1 to 4.

## Extension 2: new command to get package namespace

The "magic" to extract the package namespace is exposed by the command:

<pre>
mcpackagenamespaceget
</pre>

................................................................................
    }
}

% N4::O1 m1
-> ::N5
</pre>

Remark, that in most real cases, one will explicitly specify "::N4" instead "::N5", as this is the package namespace.
"::N5" was chosen in the example to show the fact, that the "namespace eval" overwrites any class-magic.

## Extension 3: new command to get a translation with a package namespace as argument

A new command is proposed to get a translation with an explicit namespace:
<pre>
mcn ns src args...
</pre>
with the arguments:
* ns: package namespace to do the translation for
* src: the translation source string (like mc command)
* args: eventual arguments to contained format patterns (like mc command)

This command is identical to the `mc` command, with the difference, that the package namespace is not found by an implicit call to `mcpackagenamespaceget`, but may be explicitly specified as first argument

Then, the mc command may be expressed like:
<pre>
mcn [mcpackagenamespaceget] src args...
</pre>

There are the following purposes for this command:
* foreign packages. The package namespace is known (for example by a call to `mcpackagenamespaceget`). The translation may be retrieved by a call to `mcn` without any `namespace eval $ns` around it.
* Authors of C packages required to specify the namespace explicitly.
................................................................................
proc ::tooltip::show {widget messagenamespace message} {
    ...
    set message [::msgcat::mcn $messagenamespace $message]
}
</pre>


## Extension 4: Command "mcexists" should get a parameter -namespace to explicitly specify the namespace

The command `mcexists` has currently the syntax:

<pre>
mcexists ?-exactnamespace? ?-exactlocale? src
</pre>

A switch ?-namespace ns? is added to specify the namespace explicitly:

<pre>
mcexists ?-exactnamespace? ?-exactlocale? ?-namespace ns? src
</pre>

This may be useful in similar situations as the `mcn` command.

................................................................................
    }
}
</pre>

The implementation is in tcl fossil in branch
[tip490-msgcat-oo-2](https://core.tcl.tk/tcl/timeline?r=tip490-msgcat-oo-2).

There are tests but no man page changes jet.
Please use this text as man-page.

# Discussion

## Issue 1: are really all oo use-cases covered ?

Gosts like multiple inheritance, mixins, filters whatever are calling...

## Issue 2: All backward compatibility issues covered ?

I see the following covered ones:

* no oo -> `uplevel 1 namespace current` is used, o.k.
* oo with explicit `namespace eval` -> o.k.

Are there eventually other cases not discussed here?

## Issue 3: performance loss

There is a performance penalty due to the modification described in "implementation".

To not decrease performance would require to introduce new commands, what I think is not good.
We would loose the flexibility and backward compatibility to just insert a 3rd party package, which may call "uplevel 1 msgcat::mc tag", and it works.

For performance enthusiasts, one may use "mcn", which may be little faste than former msgcat.

## Issue 4: does not work for tcl 8.6

The `self` command does not work for tcl 8.6 within class definition scripts.

It returns the error message:

<verb>
wrong # args: should be "self arg ?arg ...?"
</verb>

# Alternatives

## Use a mixin

Proposed by Donal Fellows

Each class which wants to use message catalogs require a call to `mixin msgcat::MessageCatalogAware`.

Then, the following commands are available and correspond to the `msgcat::` commands:

* my mc
* my mcmax
* my mcexists

All other mc-commands are not available within classes and should be used outside of a class.

# Examples

Within the following example, the message catalog for the package is loaded outside the method definitions.

A class "Foo" is created and the msgcat capabilities are activated by the mixin.

Then, a method is defined, which uses the message catalog of the namespace.

<pre>
namespace eval ::foo {
    msgcat::mcload $dir/msgs
    oo::class create Foo {
        mixin msgcat::MessageCatalogAware
        method printMessage {x y} {
            puts [my mc "FooPrintMessage(%d,%d)" $x $y]
        }
    }
}
package provide foo 1.0
</pre>

The implementation is in tcl fossil in branch
[tip490-msgcat-oo](https://core.tcl.tk/tcl/timeline?r=tip490-msgcat-oo).

## Use own commands for getting and setting message catalogues

Eric Boudallier proposed a solution on [Wiki page "msgcat and TclOO"](http://wiki.tcl.tk/39430)

There is also an addendum by Donal Fellows with an alternate implementation.

## mixin solution where superclass and subclass may not be in different namespaces:

Donal Fellows also provided this solution.

The key then is how to make `msgcat::mc` work (and a few related commands as well). The trick I've thought of is to use the magic powers of `apply` and `tailcall`; here's what we're looking for:

<pre>
namespace eval ::foo {
    msgcat::mcload $dir/msgs
    oo::class create MessageCatalogAware {
        forward mc apply {args {tailcall ::msgcat::mc {*}$args} ::foo}
        unexport mc
    }
    oo::class create Foo {
        mixin MessageCatalogAware
        # ...
    }
    oo::class create Bar {
        mixin MessageCatalogAware
        # ...
    }
}
package provide foo 1.0
</pre>

(I'd use a mixin for this; it's not really about the class itself; it's just about making a capability available.)

It'd be nice to have a way to make that bridging class automatically. Here it is.

<pre>
oo::class create ::msgcat::oobridge {
    superclass oo::class
    self method create {name args} {
        set cls [next $name {*}$args]
        set ns ::[namespace qualifiers [namespace which $cls]]
        foreach cmd {mc mcmax mcexists} {
            oo::define $cls forward $cmd apply [list \
                {cmd args} {tailcall $cmd {*}$args} $ns] \
                ::msgcat::$cmd
            oo::define $cls unexport $cmd
        }
        return $cls
    }
}
</pre>

Now our little package would become:

<pre>
namespace eval ::foo {
    msgcat::mcload $dir/msgs
    msgcat::oobridge create MessageCatalogAware
    oo::class create Foo {
        mixin MessageCatalogAware
        # ...
    }
    oo::class create Bar {
        mixin MessageCatalogAware
        # ...
    }
}
package provide foo 1.0
</pre>

Alternatively, we could plug the capabilities into `oo::define`; the principles of the code are largely the same but the details are little different.

I've been thinking about this more, and I've realised that there is a subtle problem: a superclass and a subclass could be in different namespaces in different packages, and so could reasonably want to use different message catalogs. This means that the bridging code always needs to look up what the context namespace is at runtime, which in turn means that there's no need for clever class manufacturing, and it can all be done with (see section "Implementation" above).

# Credits

* René Zaumseil: initiative and partial implementation
* Eric Boudallier: alternate implementation
* Donal Fellows: implementation and examples
* Ashok P. Nadkarni: teach me oo by his excellent book


# Copyright

This document has been placed in the public domain.






|



|

|

|
|
|
|
|
|
|
|

|
|
|

|

|
|
|
|
|
|
|
|

|

|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|

|

|
|
|
|
|
|
|
|
|

|
|
|

<
<
|







 







|

|
>

|








|



|












|







 







|
|

|












|







 







|







|







 







|




|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<











36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111


112
113
114
115
116
117
118
119
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
...
364
365
366
367
368
369
370
371
372
373
374
375
376
377
















































































































































378
379
380
381
382
383
384
385
386
387
388
    oo::class create Foo {
        ...
    }
}
package provide foo 1.0
</pre>

# Key Use Cases

There are 4 use-cases to consider (which may be intermixed in the same package):

(with _'Servus!'_ as translation for _'Hi!'_)

1. The package does not use OO

	<pre>
	namespace import msgcat::*
	namespace eval ::N1 {
	    mcload $dir/msgs
	    proc m1 {} {
	        puts [mc Hi!]
	    }
	}

	% N1::m1
	-> Servus!
	</pre>

2. msgcat is called within a class definition script

	<pre>
	% namespace import msgcat::*
	% namespace eval ::N2 {
	    mcload $dir/msgs
	    oo::class create C1 {puts [mc Hi!]}
	}
	-> Servus!
	</pre>

3. msgcat is called from a method in an object and the method is defined in a class

	<pre>
	namespace import msgcat::*
	namespace eval ::N3Class {
	    mcload $dir/msgs
	    oo::class create C1
	    oo::define C1 method m1 {
	        puts [mc Hi!]
	    }
	}

	# The class object may be used in another namespace
	namespace eval ::N3Obj {
	    set O1 [::N3Class::C1 new]
	}

	% $N3Obj::O1 m1
	-> Servus!
	</pre>

4. msgcat is called from a method of a classless object

	<pre>
	namespace import msgcat::*
	namespace eval ::N4 {
	    mcload $dir/msgs
	    oo::object create O1
	    oo::objdefine O1 method m1 {} {
	        puts [mc Hi!]
	    }
	}

	% N4::O1 m1
	-> Servus!
	</pre>



Note that use-case 1 may emulate Use-cases 2 to 4 using `namespace eval`. Before this extension, a programmer for use-case 2 to 4 must have used `namespace eval` to explicitly specify the package namespace:

<pre>
namespace import msgcat::*
namespace eval ::N4 {
    mcload $dir/msgs
    oo::object create O1
    oo::objdefine O1 method m1 {} {
................................................................................

% N4::O1 m1
-> Servus!
</pre>

This should still work with the new extension for compatibility reasons.

# Proposal

There are 4 possible proposed ways of extending msgcat to support
this. _We intend to implement the first option._

## Option 1: Extend all msgcat commands to support all 4 use-cases.

So any **msgcat** command will detect the scenario on its own and extract the package namespace automatically.

The commands which are packet-namespace related are: **mc**, **mcexists**, **mcpackagelocale**, **mcforgetpackage**, **mcpackagenamespaceget** (new command, see below), **mcpackageconfig**, **mcset** and **mcmset**.

This has the following advantages (compared to the alternatives):

* no new commands, no learning
* if another foreign procedure is called and the procedure wants to use the callers message catalog, it may just use `uplevel 1 {msgcat tag}` and does not need to know if it is a class or not.

Here is an example for the second advantage:

The tklib package "tooltip" may invoke `msgcat::mc msg` for all text to get eventual translations (it does something like that but I don't understand it, IMHO broken).
The package namespace of the caller should be used (not the one of the tooltip package).

So:
<pre>
proc ::tooltip::tooltip {widget message} {
    ...
    set message [uplevel 1 {::msgcat::mc $message}]
}
</pre>

This will work in all use-cases, e.g. if `tooltip::tooltip` is called by a method following use-case 1 to 4.

## Option 2: new command to get package namespace

The "magic" to extract the package namespace is exposed by the command:

<pre>
mcpackagenamespaceget
</pre>

................................................................................
    }
}

% N4::O1 m1
-> ::N5
</pre>

Note that in most real cases, one will explicitly specify "`::N4`" instead "`::N5`", as this is the package namespace.
"`::N5`" was chosen in the example to show the fact, that the `namespace eval` overrides any class-magic.

## Option 3: new command to get a translation with a package namespace as argument

A new command is proposed to get a translation with an explicit namespace:
<pre>
mcn ns src args...
</pre>
with the arguments:
* ns: package namespace to do the translation for
* src: the translation source string (like mc command)
* args: eventual arguments to contained format patterns (like mc command)

This command is identical to the `mc` command, with the difference, that the package namespace is not found by an implicit call to `mcpackagenamespaceget`, but may be explicitly specified as first argument

Then, the `mc` command may be expressed like:
<pre>
mcn [mcpackagenamespaceget] src args...
</pre>

There are the following purposes for this command:
* foreign packages. The package namespace is known (for example by a call to `mcpackagenamespaceget`). The translation may be retrieved by a call to `mcn` without any `namespace eval $ns` around it.
* Authors of C packages required to specify the namespace explicitly.
................................................................................
proc ::tooltip::show {widget messagenamespace message} {
    ...
    set message [::msgcat::mcn $messagenamespace $message]
}
</pre>


## Option 4: Command "mcexists" should get a parameter -namespace to explicitly specify the namespace

The command `mcexists` has currently the syntax:

<pre>
mcexists ?-exactnamespace? ?-exactlocale? src
</pre>

A switch, **-namespace** _ns_, is added to specify the namespace explicitly:

<pre>
mcexists ?-exactnamespace? ?-exactlocale? ?-namespace ns? src
</pre>

This may be useful in similar situations as the `mcn` command.

................................................................................
    }
}
</pre>

The implementation is in tcl fossil in branch
[tip490-msgcat-oo-2](https://core.tcl.tk/tcl/timeline?r=tip490-msgcat-oo-2).

There are tests but no man page changes yet.
Please use this text as man-page.

# Discussion

See [this page](490-discussion.md) for further discussion.

















































































































































# Credits

* René Zaumseil: initiative and partial implementation
* Eric Boudallier: alternate implementation
* Donal Fellows: implementation and examples
* Ashok P. Nadkarni: teach me oo by his excellent book


# Copyright

This document has been placed in the public domain.