문제

TCL과 함께 일하면서 전략 패턴. TCL 기능에서 출력을 인쇄하기 위해 "전략"을 전달하고 싶으므로 화면으로 인쇄와 로그 파일로 인쇄하는 것 사이를 쉽게 전환 할 수 있습니다. TCL 에서이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

도움이 되었습니까?

해결책

TCL을 사용하면 프로 시저 이름을 변수에 저장 한 다음 해당 변수를 사용하여 프로 시저를 호출 할 수 있습니다. 그래서

proc A { x } {
   puts $x
}

set strat A
$strat Hello

Proc A에게 전화하여 인쇄 할 것입니다

다른 팁

절차를 변수에 할당하는 방법을 보여주는 답변 외에도 절차 이름을 다른 절차에 인수로 전달할 수도 있습니다. 간단한 예는 다음과 같습니다.


proc foo { a } {
   puts "a = $a"
}

proc bar { b } {
   puts "b = $b"
}

proc foobar { c } {
   $c 1
}

foobar foo
foobar bar

이것은 a = 1이고 b = 1 인쇄됩니다.

전략 패턴을보다 명확하게 설명 할 수있는 위에 나열된 내용의 약간 확장 된 예.

proc PrintToPDF {document} {
<snip logic>
}

proc PrintToScreen {document} {
<snip logic>
}

proc PrintToPrinter {document} {
<snip logic>
}


set document "my cool formatted document here"

set printMethod "printer"


switch -- $printMethod {
    "printer" {
        set pMethodName "PrintToPrinter"
    }
    "pdf" {
        set pMethodName "PrintToScreen"
    }
    "screen" {
        set pMethodName "PrintToPDF"
    }
}

$pMethodName $document

Proc를 사용하는 것 외에도 실제로 코드 블록을 대신 사용할 수 있습니다. 이것에 몇 가지 변형이 있습니다. 첫 번째는 가장 분명합니다 evaling.

set strategy {
    puts $x
}

set x "Hello"
eval $strategy
unset x

이것은 작동하지만 몇 가지 단점이 있습니다. 먼저, 두 코드 모두 인수에 대한 공통 명명을 사용하는 것과 충돌해야합니다. 이것은 하나의 네임 스페이스 두통 (Procs)을 다른 (현지인)로 대체합니다. 더 나쁜.

덜 분명한 것은 평가가 바이트 코드를 컴파일하지 않고 의도적으로 인수를 해석한다는 것입니다. 이는 평가가 동적으로 생성 된 것으로 추정되는 것으로 가정되기 때문에, 일반적으로 고유 한 인수, 바이트 코드로 컴파일하는 것이 바이트 코드가 즉시 블록을 해석하는 것만으로만 한 번만 사용되는 경우 비효율적입니다. 이것은 수정하기가 더 쉽기 때문에 여기에 관용구가 있습니다.

set x "Hello"
if 1 $strategy
unset x

if,와 달리 eval, 코드 블록을 컴파일하고 캐시합니다. 만약 $strategy 블록은 단지 하나 또는 소수의 다른 가능한 값 일뿐입니다. 그러면 이것은 매우 잘 작동합니다.

이것은 로컬 변수가있는 블록에 인수를 전달하는 멍청함에 전혀 도움이되지 않습니다. 그 주위에는 많은 방법이 있습니다. 대체 같은 방식으로 TK는 명령 인수를 대체합니다. %'에스. 당신은 UP을 사용하여 해킹적인 일을 시도 할 수 있습니다 uplevel 또는 upvar. 예를 들어이 작업을 수행 할 수 있습니다.

set strategy {
    puts %x
}

if 1 [string map [list %% % %x Hello] $strategy]

통과 된 인수가 크게 바뀌지 않을 가능성이 높으면 바이트 코드 컴파일 측면에서 잘 작동합니다. 반면에 논쟁이 자주 바뀌면 사용해야합니다. eval 대신에 if 1. 어쨌든 논쟁의 관점에서 이것은 훨씬 나아지지 않습니다. 특별 구문을 사용하고 있기 때문에 통과 된 것과 그렇지 않은 것에 대한 혼란의 가능성이 적습니다. 또한 코드 블록을 반환하기 전에 변수 대체를 사용하려는 경우에도 도움이됩니다. set strategy "$localvar %x".

다행히도 TCL 8.5는 있습니다 진정한 익명 기능, 사용 apply 명령. 적용 명령에 대한 첫 번째 단어는 마치 그 주장이 proc 들어 올렸다. 나머지 인수는 즉시 인수로 익명 명령으로 전달됩니다.

set strategy [list {x} {
    puts $x
}]

apply $strategy "Hello"

가변 함수를 사용하는 것은 어떻습니까? 나는 많은 TCL을 기억하지 못하지만 (오랜 시간이 지났다 ...) 아마도 이것들 중 하나는 당신이 필요한 것을 할 것입니다.

  • $ var param1 param2
  • $ var] param1 param1
  • $ var param1 param2

내가 틀렸다면 누구든지 나를 자유롭게 바로 잡을 수 있습니다.

% set val 4444
4444

% set pointer val
val

% eval puts $$pointer
4444

% puts [ set $pointer ]
4444

% set tmp [ set $pointer ]
4444

Jackson의 방법이 작동하는 이유를 명확히하려면 TCL에서 기억하십시오. 모든 것 문자열입니다. 문자 그대로의 문자열, 함수, 변수 또는 무엇이든 작업하든 모든 것 문자열입니다. "데이터 포인터"를 할 수있는 것처럼 "함수 포인터"를 전달할 수 있습니다.

위에서 언급 한 내용, 네임 스페이스에서 네임 스페이스로 이동할 때는 통과로 사용할 수 있습니다. [namespace current ]::proc_name, 당신이 휴식을 취하지 않도록하기 위해.
OO 메소드의 경우이 스레드의 내용을 따라야합니다.TCL에서 특정 객체의 메소드를 입력 인수로 전달합니다.
Godspeed.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top