2016-11-11 1 views
0

프로그램을 리팩터링하기 위해 매크로로 추상화하고 배치하고자하는 복잡한 프로세스를 수행했습니다.SAS : 데이터 스텝 루프 내에서 매크로 호출하기

%macro BlackBox(); 
    data _null_; 
    put "This represents a complex process I want to abstract."; 
    run; 
%mend; 

과정은 연속적으로 여러 번 발생해야하므로 확실한 해결책은 루프 내에 배치하는 것입니다.

data _null_; 
    do i = 1 to 3; 
    %BlackBox(); 
    end; 
run; 

그러나이 오류는 다음과 같습니다.

ERROR 117-185: There was 1 unclosed DO block. 

무슨 일입니까?

SAS는 데이터 단계 내에서 데이터 단계를 실행하려고합니다.

매크로 내에서 루프를 감싸고 즉시 매크로를 호출하여이 오류를 피할 수 있습니다.

이 모든 것이 기본적인 프로그래밍 작업을 처리하는 원형적인 방법처럼 보입니다. 데이터 단계 접근 방식이 실패한 이유에 대해 더 자세히 배우려면이 작업을보다 우아하게 완료하는 방법에 대한 통찰력이 필요합니다.

이것은 발생하는 오류를 설명하기 위해 사용 된 단순화 된 예입니다. 매크로의 실제 인스턴스는 인수 또는 반환 값을 가질 수 있습니다.

답변

1

매크로 언어는 전처리 기입니다. SAS 코드를 생성하고 DATA 단계 코드가 컴파일되기 전에 실행됩니다. 코드와 함께 :합니다 (DO 루프가 실행 전에 개념적으로 DO 루프 외부에서 실행하기 때문에, 아니 세 번)

data _null_; 
    do i = 1 to 3; 
    %BlackBox(); 
    end; 
run; 

매크로의 %의 블랙 박스()를 한 번 실행됩니다. 그리고 데이터 단계 코드가된다 :

data _null_; 
    do i = 1 to 3; 
    data _null_; 
    put "This represents a complex process I want to abstract."; 
    run; 
    end; 
run; 

당신이 말하는 것처럼, SAS에서 다른 데이터 단계 내부의 데이터 단계를 실행 할 수 없습니다. 3 호선의 data _null_은 첫 번째 데이터 단계를 끝내고 닫히지 않은 do 블록 내에 남겨 둡니다.

@ Joe 's points에 동의합니다. 많은 매크로 호출을 생성하려면 매크로 DO 루프를 사용하여 매크로 호출을 수행하는 것이 좋습니다. 그의 논문은 매크로 호출 목록으로 해석되는 매크로 변수를 작성함으로써 데이터를 사용하여 매크로 호출을 생성하는 좋은 방법을 제공합니다.

다른 유용한 방법은 CALL EXECUTE입니다. 이렇게하면 데이터 단계를 사용하여 매크로 호출을 생성 할 수 있습니다. CALL EXECUTE는 데이터 단계가 실행될 때 매크로 호출을 생성하고 매크로는 데이터 단계 외부에서 실행됩니다 (아래의 % NRSTR을 사용할 때). 예를 들어, 언제나

NOTE: CALL EXECUTE generated line. 
1 + %BlackBox() 
MPRINT(BLACKBOX): data _null_; 
MPRINT(BLACKBOX): put "This represents a complex process I want to abstract."; 
MPRINT(BLACKBOX): run; 

This represents a complex process I want to abstract. 

2 + %BlackBox() 
MPRINT(BLACKBOX): data _null_; 
MPRINT(BLACKBOX): put "This represents a complex process I want to abstract."; 
MPRINT(BLACKBOX): run; 

This represents a complex process I want to abstract. 

3 + %BlackBox() 
MPRINT(BLACKBOX): data _null_; 
MPRINT(BLACKBOX): put "This represents a complex process I want to abstract."; 
MPRINT(BLACKBOX): run; 

This represents a complex process I want to abstract. 
2

가정은 정확합니다. SAS는 데이터 단계 내에서 데이터 단계를 실행하려고 시도하고 있습니다. 물론 그럴 수는 없습니다. (물론 가능하지만 복잡하게 만 ...)

매크로 루프 방법은 전적으로 합리적입니다. 다른 프로그래밍 언어는 기본적으로 당신이 할 일이라고 주장 할 것입니다. draw_box 메서드를 작성하여 C#의 화면에 상자를 표시 한 다음 draw_box을 세 번 호출하여 화면에 세 개의 상자를 표시하는 draw_three_boxes 메서드를 작성합니다. 이 세 개의 상자를 그리기, 하나의 일을하고 만있는, 그래서 왜 그냥 원래 draw_box을하지 않았다

지금, 그것은 바보 보이는 이유는 draw_three_boxes 방법은 매우 제한되어 당신이 지라 나쁜 프로그래밍 디자인을 가지고있다 방법은 처음부터 그렇게합니까?

아마도, 당신이해야 할 일은 draw_box이라고 쓰고 그 다음에 draw_boxes(int count, int xpos, int ypos)이나 그와 비슷한 것을 쓰십시오. 맞습니까? 여기 같은거야. 루프를 수행 할 횟수를 하드 코딩했기 때문에 PerformDoLoop() 매크로를 작성하면 안됩니다.

대신 왜 3 번 실행하는지보십시오. 실제로 알기도하고 데이터가 아닌 경우 %PerformDoLoop(count=)을 입력 한 다음 %PerformDoLoop(count=3)으로 전화하십시오. 또는 원래 매크로에 %do 루프를 포함하고 count 매개 변수를 기본값으로 사용하십시오.

가능성이 더 높습니다. 데이터를 처리해야하는 이유가 3 번 있습니다. 당신은 3 개의 주를 가지고 있습니다. 당신에게는 3 개의 클래스 학생들이 있습니다. 도대체 무엇이. 이것을 사용하여 %BlackBox에 대한 호출을 생성하십시오. 그렇게하면 프로그램에서 그렇게하지 않기 때문에 최상의 결과를 얻을 수 있습니다. 데이터가 변경되면 즉시 2 ~ 4 개의 전화를받습니다.

내 최근 발표 한 논문 인 Writing Code With Your Data을 SESUG 2016에서 볼 수 있습니다. 자세한 내용은 해당 방법을 참조하십시오.

+0

, 조 감사합니다 :

data _null_; do i = 1 to 3; call execute ('%nrstr(%BlackBox())'); end; run; 

세 가지 매크로 호출을 생성합니다. 내 행동을 설명하기 위해 매크로 '% PerformDoLoop'은 루프를 수행하는 메소드를 작성하는 것과 유사하지 않습니다. 말 그대로 루프 자체를 수행하는 것입니다. 다른 언어에서는 열린 코드에서 루프를 호출 할 수 있습니다. SAS에서는 그렇지 않습니다. 대신에 루프는'data _null_' 또는 매크로 - 멘드 - 호출 블록 내에서 위와 같이 싸여 야합니다. 실제로, 나의 BlackBox는 논쟁을합니다. 다른 인수에 대해 BlackBox를 호출해야하기 때문에 의사 배열 (pseudo-array)로 매크로 목록을 만들었습니다. 그런 다음 BlackBox는 배열을 사용하고 루프 인덱스를 사용하여 다른 인수를받습니다. –

+0

@LoremIpsum 그렇다면 루프 매크로를 작성하지 않을 것입니다. 매개 변수의 매크로 목록을 작성하는 대신 BlackBox에 대한 호출의 매크로 목록을 작성하십시오. SAS가 개방 코드에서 루프를 갖지 않는 것이 특별히 독특하지 않다고 제안합니다. C에서 그렇게 할 수는 없습니다. 특히 명백한 예를 들면, 서브 루틴에 있어야합니다. SAS와 마찬가지로 코드 캡슐화가 시행 된 것입니다. 즉, SAS 9.5에서는 매크로 외부에서 매크로 흐름 제어 ('% do' 등)를 허용하는 것처럼 보이지만, 좋은 일이라고 확신하지는 않습니다. – Joe

+0

흥미로운 점 9.5. 나는 SGF에서 열린 선언문이 9.5에오고 있다고 들었다. 그리고 나는 그것이 좋은 것임을 확신하지 않는다. 구현 방법에 대한 초기 기사를 보셨습니까? – Quentin