Search code examples
ctcl

Navigating to an element in a list using Tcl C API


Accessing an sub-element in a Tcl list is fairly easy with the lindex command. Here's my list :

set myList {Y {FUNCTION {{KEY1 KEY2 KEY3}}}}

My objective is to be able to retrieve this sub-list :

KEY1 KEY2 KEY3.

Side Tcl, with lindex command I can do that : lindex $myList {1 1 0}.
With Tcl C API, I think I need to use this function Tcl_ListObjIndex, but it doesn't allow you to add several indexes to select elements from sublists. Here's my C code :

Tcl_Obj* first_list  = Tcl_NewObj();
Tcl_Obj* sub_list    = Tcl_NewObj();
Tcl_Obj* subsub_list = Tcl_NewObj();

Tcl_ListObjIndex(interp, myList, 1, &first_list);
Tcl_ListObjIndex(interp, first_list, 1, &sub_list);
Tcl_ListObjIndex(interp, sub_list, 0, &subsub_list);

return subsub_list;

It works, but I've just tried translating my Tcl code into C code and I don't know if that's very efficient or correct.


Solution

  • While there is an internal API for doing the exact operation you are talking about (TclLindexFlat()), it isn't exposed because it is a bit clunky (there's a few semi-onerous side requirements on reference count management and non-aliasing between the list and indices — that's something the wrapping as a command handles for you). And calling Tcl_ListObjIndex() multiple times like that is pretty efficient; there's very little overhead. Awkward and not a big win? Not exposed!

    It would matter a lot more if you were wanting an equivalent to lset, as that can't be so easily composed out of basic ops while remaining efficient. (TclListObjSetElement() isn't documented, and the multi-index version — TclLsetFlat() — isn't exposed at all...)

    If you want these sorts of things to be exposed you really should contact the Tcl Core Team properly to explain your use case(s) to persuade us to clean things up to go knto the public API.