首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >TCL:使代码从嵌套的if-语句中更清晰

TCL:使代码从嵌套的if-语句中更清晰
EN

Stack Overflow用户
提问于 2015-06-03 05:06:21
回答 2查看 539关注 0票数 1

这是linux上i3窗口管理器状态栏的一个项的过程。每秒钟跑一次。基本上是和调速器打交道。如果温度达到一定的数值,然后切换到省电模式,或者如果某个应用程序正在运行,例如蒸汽,或者笔记本电脑运行在电池上。如果温度达到一个较低的点,那么它将切换到性能等。

到目前为止,这个程序运行良好,没有任何问题。然而,代码有那么多嵌套的if-well语句,因此很难维护,每次我添加代码时,代码就变得更多了,嗯……嵌套的。

代码语言:javascript
运行
复制
proc cpu_freq {} {
    set app steam
    set cpu_power [exec sudo cpupower frequency-info | sed -ne /speed/p]
    set cpu_temp [exec sensors | grep Core | sed -n  {2p} | awk {{print $3}} | cut -c2-3]
    set battery [exec acpi]
    if {[string match *performance* $cpu_power]} {set cpu_freq HIGH; set color "$::green"}
    if {[string match *powersave* $cpu_power]}   {set cpu_freq LOW;  set color "$::red"}
    if {![file isfile $::i3dir/powersave.freq] && ![file isfile $::i3dir/performance.freq]} {
        set switch AUTO
    }
        # ON BATTERY 
    if {[string match *Discharging* $battery]} {
        # WHEN IN PERFORMANCE MODE
        if {[string match *performance* $cpu_power]} {
           if {![file isfile $::i3dir/performance.freq]} {
               # AND NOT IN MANUAL
               # SWITCH TO POWERSAVE 
               exec sudo cpupower frequency-set -g powersave
               set cpu_freq LOW
               set switch AUTO
               set color "$::red"
               set ::on_battery true
          } else { 
              # SWITCH TO MANUAL PERFORMANCE MODE
              if {[file isfile $::i3dir/performance.freq]} {
                  exec sudo cpupower frequency-set -g performance
                  set cpu_freq HIGH
                  set switch MAN
                  set color "$::green"
                  set ::on_battery true
              } else {
             if {[file isfile $::i3dir/powersave.freq]} {
                 # SWITCH TO MANUAL POWERSAVE MODE 
                 exec sudo cpupower frequency-set -g powersave
                 set cpu_freq LOW
                 set switch MAN
                 set color "$::red"
                 set ::on_battery true
              }
              }                
           } 
       } else {
       # WHEN IN POWERSAVE MODE (AUTO)
       # SWITCH TO MANUAL POWERSAVE
       if {[string match *powersave* $cpu_power]} {
          if {[file isfile $::i3dir/powersave.freq]} {
              exec sudo cpupower frequency-set -g powersave
              set cpu_freq LOW
              set switch MAN
              set color "$::red"
              set ::on_battery true
          } else {
       # SWITCH TO MANUAL PERFORMANCE
          if {[file isfile $::i3dir/performance.freq]} {
              exec sudo cpupower frequency-set -g performance
              set cpu_freq HIGH
              set switch MAN
              set color "$::green"
              set ::on_battery true
             }
          }
       }
    }
       # ON MAINS
    } else {
         # WHEN IN POWERSAVE MODE
         if {[string match *powersave* $cpu_power]} {
                # RUNNING APP OR MANUAL SWITCH
            if {[file isfile $::i3dir/powersave.freq]} {
                set cpu_freq LOW
                set switch MAN
                } else {
            if {[isRunning $app]} {
                set cpu_freq LOW
                set switch AUTO
                # DO NOTHING, KEEP RUNNING IN POWERSAVE MODE
                } else {
                # SWITCH TO PERFORMANCE AFTER RUNNING ON BATTERIES
                if {$::on_battery==true} {
                    exec sudo cpupower frequency-set -g performance
                    set cpu_freq HIGH
                    set switch AUTO
                    set color "$::green"
                    set ::on_battery false
                # SWITCH TO PERFORMANCE WHEN REACHING LOWER TEMPS
                } elseif {$cpu_temp <= 55} {
                    exec sudo cpupower frequency-set -g performance
                    set cpu_freq HIGH
                    set switch AUTO
                    set color "$::green"
                   }
                }
            }
         # WHEN IN PERFORMANCE MODE
        } else {
                # MANUAL SWITCH
            if {[file isfile $::i3dir/performance.freq]} {
                set switch MAN
                set cpu_freq HIGH
                # DO NOTHING, KEEP RUNNING IN PERFORMANCE MODE
                } else {
                # HOT TEMPERATURE OR RUNNING APP
                # SWITCH TO POWERSAVE
                if {$cpu_temp >= 75 || [isRunning $app] } {
                    exec sudo cpupower frequency-set -g powersave
                    set cpu_freq LOW
                    set switch AUTO
                    set color "$::red"
                } else {
                    set cpu_freq HIGH
                    set switch AUTO
                }
            }
        } 
    }
    set stdout {{"name":"cpu_freq","full_text":"$switch:$cpu_freq","color":"$color"}}
    set stdout [subst -nocommands $stdout]
    puts -nonewline $stdout
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-03 11:27:46

当我看到这样的东西时,我会立即想到有限状态机/状态转换图。您有一个启动状态,然后根据您在if语句中调用的procs的结果切换到其他状态,在某个时候,您将到达一个结束状态,从该状态不再可能发生进一步的转换。

因此,我将考虑重组,如下所示:

代码语言:javascript
运行
复制
# The value to process
set value "This is a big red ball"

# The starting state
set state 1

# The state transtions and the functions to implement them
set states [dict create "1,3" "IsRed" "1,2" "IsBlue" "2,4" "IsBig" "2,5" "IsSmall" "3,4" "IsBig" "3,5" "IsSmall"]

# Procs that implement the state transitions
proc IsRed {next} {
    global value state
    if {[string first "red" $value] != -1} {
        puts "red"
        set state $next
        return true
    }
    return false
}

proc IsBlue {next} {
    global value state
    if {[string first "blue" $value] != -1} {
        puts "blue"
        set state $next
        return true
    }
    return false
}
proc IsSmall {next} {
    global value state
    if {[string first "small" $value] != -1} {
        puts "small"
        set state $next
        return true
    }
    return false
}

proc IsBig {next} {
    global value state
    if {[string first "big" $value] != -1} {
        puts "big"
        set state $next
        return true
    }
    return false
}

# Proc to run the state machine until the state stops changing
proc runMachine { states } {
    global state
    set startState -1
    while { $state != $startState } {
        set startState $state
        foreach key [dict keys $states "$state,*"] {
            set next [lindex [split $key ","] 1]
            set res [[dict get $states $key] $next]
            # If the state changes then no need to do any more processing
            if { $res == true } {
               break 
            }
        }
    }
}

runMachine $states

这是一种可能的方法,它比您需要做的要简单得多,但是展示了基本的想法。字典显示允许的状态转换和要运行的proc,以便测试是否允许转换。我已经将我的处理代码( put语句)放在这个函数中,但是让另一个函数执行处理非常简单,或者直接调用,或者作为字典中的另一个值保存,然后从runMachine proc调用。

代码语言:javascript
运行
复制
set states [dict create 21,3" [list "IsRed" "RedAction"]]

这种方法可以将所有的操作和转换分离出来,并绘制一个状态转换图,清楚地显示正在发生的事情。

一个用于TCL有限状态机的快速google有限状态机展示了实现这一想法的许多其他方法。

票数 1
EN

Stack Overflow用户

发布于 2015-06-03 07:39:03

把它分解成一组函数。

Tcl有一个switch语句,有时可以提供帮助。它还提供了elseif来帮助减少嵌套。但是在所示的代码中,将其分解为带有合理名称的函数,您可以将其简化为一个处理逻辑的函数和一个处理在特定情况下发生的事情的集合。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30611237

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档