筋悪ですが、LINKステートメントとGOTOステートメントについて

SAS Technical News 2010 Autumn 「意外と知らない!? コロンの活用術をご紹介」は僕のお気に入りの号のひとつです。

http://www.sas.com/offices/asiapacific/japan/periodicals/technews/index.html#section=4

SASにおけるコロン「:」はトリッキーかつ結構いい働きをするやつで、これをうまく使えるかどうかで、コードの完成度に差がでると思っています。僕の中では桂馬みたいなイメージです。

で、だいたい上記の号の中でコロンの使いどころについて言及されているのですが、ちょっと勝手に感じたのが、やっぱりSAS的にはLINKステートメントやGOTOステートメントにおけるラベルコロンは紹介すべきではないと考えているのかなということでした。

LINKやGOTOステートメントは、プログラムの途中で指定箇所(ラベルといわれる)にぶっ飛ぶことができる危ない奴です。

GOTO文は筋悪というのは、多くのプログラム言語に当てはまることで、SASにとっても
上から下に流れるSASのシンプルな処理をぶち壊す、やっかいなステートメントです。

恐らく、ほぼ全てのケースにおいてGOTOやLINKを使わずに、目的の処理が果たせるコードはかけるはずなので、使用はお勧めしません。

ただ、コードを書く人も、読むであろう人も全員、熟練者であれば、相当複雑なネストを組む時に、全体をすっきりさせるために使用することはあるのかもしれません。

しかし、もしかしたら、運悪く、どこかで他人の書いたGOTO や LINKのコードに対峙することがあるかもしれません。そんな時の対抗手段として、基本的な挙動は知っておいて損はないと思います。

例えば以下のようなデータセットがあったとします。

data Q1;
do X=1 to 5;
 do Y=2 to 4;
  output;
 end;
end;
run;



















これに対して以下のコードを実行すれば

data A1;
 set Q1;
 by X;
 if first.X then Z=0;
  Z+Y;
run;



















となります。


これをLINKステートメント使って表現すると

data A2;
 set Q1;
 by X;
 if first.X then link FL;
  Z+Y;
 return;

 FL:
  Z=0;
 return;
run;

となりますFLというのがジャンプ先の目印になって
そこからジャンプ先での処理が行われて、returnで戻ってきます。

ちなみにlinkの部分をgotoにすると

data A3;
 set Q1;
 by X;
 if first.X then goto FL;
  Z+Y;
 return;

 FL:
  Z=0;
 return;
run;

returnで停止するので



















僕が知っているのも、ほんとこの程度までです。


4 件のコメント:

  1. データステップ外(マクロ内)で分岐に使えるlinkやgotoに相当するものはないでしょうか。
    私は次のようにしていますが、長いプログラムになると筋書きが見えにくいので、他の方法も知りたいと思います。
    %if ... %then %do;
    ...
    %end;
    %else %do;
    ...
    %end;

    返信削除
    返信
    1. お久しぶりです!
      ご質問有難うございます!

      マクロで使える、%goto文もありますが、通常のデータステップと少し書き方が違うので注意してください。

      data Q1;
      X=1;output;
      X=2;output;
      run;

      %macro samp;
      data _null_;
      set Q1 nobs=tobs;
      call symputx('M1',tobs);
      stop;
      run;

      %if &M1<5 %then %goto pr;
      proc univariate data=Q1;
      run;
      %return;

      %pr: proc print data=Q1;
      run;

      %mend samp;

      %samp


      上記のサンプルは、Q1というデータセットをunivariateプロシジャにかけるマクロです。
      ただし、Q1のオブザベーション数が5未満の場合は、univariateプロシジャにはかけずに、proc printするという分岐を含んだマクロです。

      %goto pr; の[pr]がマクロラベルというもので、適当な名前をつけることができます。[pr]という名前は僕が適当につけました。ここは何でもよいです。%prと間違って、%をつけないように注意してください

      そして %pr: proc print data=Q1;の部分、「%pr:」がgo toのジャンプ先になります、
      %マクロラベル名に「:」コロンをつけています。%をつけ忘れたり、コロンを忘れがちなので注意してください。 こっちには%がいります。

      もし、何かわからないことがありましたら、なんでも聞いてください。

      削除
    2. データステップ中でもgoto文は使ったことなかったので思いつきませんでした。
      %goto も同じような感覚で使えたんですね。
      ありがとうございます。 ・・・の上、こんなに速く、いいんでしょうか。

      削除
    3. いいんです!w

      SASいじりと将棋が趣味なので。
      それに今、ちょうど転職活動中・休暇中で、特に暇なので。

      %goto 、原理が単純なので、ジャンプ先の見方さえわかっていれば、それほど可読性を損なうとも思ってないので、使いやすいと思ってます。

      今後とも何かあれば、いつでもご連絡ください。

      もし、サンプルプログラムや出力物を伴ったご質問の場合や、コメントでなく直接の質問の場合は、
      以下のメールアドレスにファイルを添付して送っていただいても結構です。

      sasyupi@gmail.com

      削除