【问题标题】:How to save result of a TCL proc in a list?如何将 TCL proc 的结果保存在列表中?
【发布时间】:2016-04-11 05:37:54
【问题描述】:

我的 TCL 脚本是这样的:

proc foo {var1} {
    ;# some code which finds a value (say bar) and recursively call the same proc (foo) on bar until it reaches end of data.
}

现在我想将所有值(栏)保存到一个列表中。

当我在 proc 中设置一个列表时,它会在每次递归调用 proc 时重置。当我在 proc 之外设置时,它找不到它并说变量不存在。

我如何做到这一点?

谢谢。

编辑:

下面是示例代码:

set mylist {}

proc myproc {var} {

set exception {tesla}
set var1 [#some script to fetch a data string using proc variable]

foreach item $var1 {
    set var2 [#script to get another data depending on item]

    if {$var1==2 || $var2=="tesla"} {

        set var3 [#script to get some data using var2]

        puts "debug value $var3"
        lappend mylist $var3
        myproc $var3
    }
  }
}

【问题讨论】:

    标签: tcl proc


    【解决方案1】:

    解决方案 1

    proc foo {var1 resultVar} {
        upvar $resultVar result
        if {$var1 == 1} {
            lappend result 1 
            return $result
        } else {
            lappend result $var1
            foo [expr $var1 - 1] result
        }
    }
    
    set myResults []
    foo 10 myResults
    puts "From foo: $myResults"
    

    解决方案 2

    proc bar {var1} {
        global barResults
        if {$var1 == 1} {
            lappend barResults 1 
        } else {
            lappend barResults $var1
            bar [expr $var1 - 1]
        }
    }
    
    set barResults []
    bar 10
    puts "From bar: $barResults"
    

    输出

    sharad@ss:~$ tclsh my.tcl 
    From foo: 10 9 8 7 6 5 4 3 2 1
    From bar: 10 9 8 7 6 5 4 3 2 1
    sharad@ss:~$ 
    

    【讨论】:

    • 谢谢,这正是我想要的。
    【解决方案2】:

    通常,当您通过搜索步骤处理这样的列表时,通常会更新列表,使其仅包含剩余要搜索的元素。列表本身存储在调用者的一个变量中,该变量提供给被调用的例程;如果它在局部变量中,则不会影响外界。 name-provision 与upvar 一起使用,因此内部搜索过程不需要在其调用者中具有关于变量命名的内置知识(因为那将是 terrible 风格) .如果需要,调用者可以将列表复制到局部变量中

    proc innerSearch {listVariable} {
        upvar 1 $listVariable theList
        set idx [...];            # Get index of thing we found
        set resultValue [...];    # Thing that we will return
        set theList [lrange $theList [expr {$idx + 1}] end]
        return $resultValue
    }
    
    proc outerSearch {} {
        global foobar
        set myList $foobar;       # Copy here! Actually does efficient magic behind the scenes
        set results {}
        while 1 {
            set foundThing [innerSearch myList];   # Note: we pass the variable *NAME*
            if {$foundThing eq ""} break;          # Terminate the loop if not found
            lappend results $foundThing
        }
        return $results
    }
    

    另一方面,如果您还需要知道找到该元素的索引以便处理它,您可以将前一个索引安排在存储的变量中,然后将列表通过价值。

    proc innerSearch {list indexVariable} {
        upvar 1 $indexVariable idx
        # Use old index to start search        
        set idx [...];            # Get index of thing we found
        set resultValue [...];    # Thing that we will return
        return $resultValue
    }
    
    proc outerSearch {} {
        global foobar
        set index -1;             # Before any element
        set results {}
        while 1 {
            set foundThing [innerSearch $foobar index];   # Note: we pass the variable *NAME*
            if {$index == -1} break;          # Terminate the loop if not found
            lappend results $foundThing
        }
        return $results
    }
    

    如果您使用当前推荐的 Tcl (8.6) 版本,您可能能够将简单的搜索转换为 lmap 调用。我不知道这里是不是这样。

    【讨论】:

      【解决方案3】:

      您将需要lappend 来存储每次递归调用的输出。

      proc glob-r-dir {{dir .}} {
          set res {}
          foreach i [glob -nocomplain -dir $dir *] {
              if {[file type $i] eq {directory}} {
                  lappend res $i
                  eval lappend res [glob-r-dir $i] ;# recursive call to function
              }
          }
          set res
      }
      

      打电话的时候可以这样打电话,

      set dirs [glob-r-dir "/home/abc"]
      

      在这里,您将在dir 变量中获得返回值。

      我在“递归全局部分”Click on This 中找到了这个

      【讨论】:

      • 感谢 AxT,但我无法让它工作它返回空列表。我尝试了类似的方法,但每次调用 proc 时都会调用 set res {}。我做错了吗?
      猜你喜欢
      • 2013-04-24
      • 2016-07-12
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 2022-08-11
      • 1970-01-01
      • 2022-07-01
      相关资源
      最近更新 更多