jimtcl icon indicating copy to clipboard operation
jimtcl copied to clipboard

Strange results (duplicates) from [info commands]

Open aryler opened this issue 3 years ago • 6 comments
trafficstars

$ cat ictest.tcl
proc q {} { puts &[info commands *::acmd]& }
namespace eval a {
  proc z {} { puts ^[info commands *::acmd]^ }  
  namespace eval b {
    proc x {} { puts @[info commands *::acmd]@ }  
    namespace eval c {
      proc acmd {} {}    
      puts ![info commands *::acmd]! 
      ::a::z
      ::a::b::x
      ::q
    }
  }
}
puts %[info commands *::acmd]%
$ jimsh ictest.tcl  
!a::b::c::acmd!
^b::c::acmd a::b::c::acmd^
@c::acmd a::b::c::acmd@
&a::b::c::acmd&
%a::b::c::acmd%

aryler avatar Aug 18 '22 00:08 aryler

Thanks for the report. The issue is that there are two names that acmd can be known by in these namespaces. Either name will work, but they are the same proc. I'll have a think about if/how to resolve this.

msteveb avatar Aug 18 '22 00:08 msteveb

My inclination is to leave it as is, but I'm open to other suggestions

msteveb avatar Aug 20 '22 05:08 msteveb

I don't think "commands reachable" should be considered the same as "commands available".

$ cat ictest2.tcl
namespace eval a {
  namespace eval b {
    proc getcmds {pat} {
      return [info commands $pat]
    }
    proc q {} { return 1 }
    namespace eval c {
      proc q {} { return 2 }
    }
  }
}
foreach cmd [a::b::getcmds *::q] {
  puts $cmd![$cmd]!
}
$ jimsh ictest2.tcl
ictest2.tcl:13: Error: invalid command name "c::q"
at file "ictest2.tcl", line 13

aryler avatar Aug 20 '22 11:08 aryler

$ cat ictest3.tcl
namespace eval a {
  proc getcmds {pat} { info commands $pat }
  namespace eval b {
    proc getcmds {pat} { info commands $pat }
    namespace eval c {
      proc getcmds {pat} { info commands $pat }
    }
  }
}
# ok
set pat ::*::getcmds
# notok
set pat *::getcmds
puts [a::getcmds       $pat]
puts [a::b::getcmds    $pat]
puts [a::b::c::getcmds $pat]
puts [info commands    $pat]
$ jimsh ictest3.tcl
b::c::getcmds b::getcmds a::getcmds a::b::c::getcmds a::b::getcmds
c::getcmds a::getcmds a::b::c::getcmds a::b::getcmds
a::getcmds a::b::c::getcmds a::b::getcmds
a::getcmds a::b::c::getcmds a::b::getcmds

aryler avatar Aug 20 '22 12:08 aryler

I'm not sure I follow you. [info commands] returns commands that are reachable from the scope where it is invoked. Why would those be callable from another scope (such as the global scope in your first example)?

Consider:

namespace eval a {
  proc getcmds {pat} { info commands $pat }
  proc testing {pat} {
    foreach name [info commands $pat] {
        puts "from a::testing: $name => [$name getcmds]"
    }
  }
  namespace eval b {
    proc getcmds {pat} { info commands $pat }
    namespace eval c {
      proc getcmds {pat} { info commands $pat }
    }
  }
}
a::testing *::getcmds

Gives:

from a::testing: b::c::getcmds => getcmds
from a::testing: b::getcmds => getcmds
from a::testing: a::getcmds => getcmds
from a::testing: a::b::c::getcmds => getcmds
from a::testing: a::b::getcmds => getcmds

So each of those commands is callable from the 'a' namespace, although some are ultimately aliases of others. But it doesn't mean you could call 'b::getcmds' from the global namespace.

msteveb avatar Aug 21 '22 01:08 msteveb

Perhaps also consider:

proc aa {} {}
alias aa2 aa
puts [info commands aa*]

Gives:

aa2 aa

We wouldn't expect 'info commands' to de-duplicate these even though aa2 is simply an alias of aa.

msteveb avatar Aug 21 '22 01:08 msteveb

I'm going to close this issue as "possibly unexpected but not wrong"

msteveb avatar Feb 24 '23 03:02 msteveb