[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.12 機能条件式

cond-expandマクロ

しばしば、実装やプラットフォームがどういった機能を提供しているかに 応じてコードを切り替えたいことがあります。例えば、ネットワークが使えるか どうかで振る舞いを変えるとか、ほぼポータブルなコードの一部だけに 特定の実装に依存するコードを入れたいとかいう場合です。

C言語なら、#ifdefのようなプリプロセッサディレクティブを、 Common Lispなら、#+#-のようなリーダマクロを使うところです。 Schemeでは、こういう時にはcond-expandを使います。

Macro: cond-expand (feature-requirement command-or-definition …) …

[SRFI-0][R7RS] プラットフォームがfeature-requirementに示される機能をサポートしていれば、 このマクロはcommand-or-definition … へと展開されます。

feature-requirement は以下のような構文でなければなりません。

 
feature-requirement
  : feature-identifier
  | (and feature-requirement …)
  | (or  feature-requirement …)
  | (not feature-requirement)
  | (library library-name)

このマクロは feature-requirement を順にテストし、そのひとつが 満たされたら、対応する command-or-definition … に展開されます。

最後の節のfeature-requirementの部分にはシンボルelseを 置くこともできます。他の節のfeature-requirementが満たされなかった場合に その節が展開されます。

feature-identifier は機能を示すシンボルです。その機能が現在のプラットフォームで サポートされているなら、それは、feature-requirement を満たします。 より複雑な条件を構成するために、feature-requirement のブール代数による 組み合わせを用いることが出来ます。

(library library-name)という形式はR7RSで追加されたもので、 指定されるライブラリが使える場合に条件が満たされます。 これはR7RSの形式なので、ライブラリ名はリスト形式で指定します (gauche.netのかわりに(gauche net)等)。

例えば、Gauche、Chicken Scheme、ChibiSchemeに依存するコードを 入れたいとしましょう。現代の多くのScheme実装は、自分自身を示す feature-identifierを定義しているので、条件付きのコードは次のとおり書けます。

 
(cond-expand
 [gauche  (gauche-specific-code)]
 [(or chicken chibi) (chicken-chibi-specific-code)]
 [else    (fallback-code)]
 )

cond-expandの条件はマクロ展開時に全て処理され、 不採用だった節のコードは捨てられる、という事実は重要です。 このおかげで、例えば実装によって認識されないマクロ呼び出しや言語拡張を command-or-definitionに含めることができます。 また、グローバルな束縛を条件によって定義したりしなかったりすることができます。

これをcondと比較してみましょう。condは条件を実行時に調べます。 もし条件節の中に、あるプラットフォームではサポートされないマクロ呼び出しを 書いた場合、たとえその節が現実には決して実行されないものであるとしても、 マクロ展開時にエラーになってしまうかもしれません。 また、condを使って条件的にグローバルな束縛を定義することはできません。

ただし、マクロ展開した結果をどうにかして保存しておいて、 別のプラットフォームでそれを走らせる、ということをする場合は注意が必要です。 条件選択はマクロ展開をするプラットフォームの機能に応じて行われ、 それはコードを実行するプラットフォームの機能とは一致しないかもしれません (これはもちろん、クロスコンパイルで常に問題となることです。)

Gaucheで使えるfeature identifier一覧は下を見てください。

Gauche特有のfeature identifier

gauche
gauche-X.X.X

Indicates you’re running on Gauche. X.X.X is the gauche’s version (e.g. gauche-0.9.4), in case you want to have code for specific Gauche version. (Such feature identifier is suggested by R7RS; but it might not be useful if we have means to compare versions. Something to consider in future versions.)

gauche.os.windows
gauche.os.cygwin

Defined on Windows-native platform and Cygwin/Windows platform, respectively. If neither is defined you can assume it’s a unix variant. (Cygwin is supposedly unix variant, but corners are different enough to deserve it’s own feature identifier.)

gauche.ces.utf8
gauche.ces.eucjp
gauche.ces.sjis
gauche.ces.none

Either one of these is defined based on Gauche’s native character encoding scheme. See section マルチバイト文字列, for the details.

gauche.net.tls

Defined if the runtime supports TLS in networking.

gauche.net.ipv6

Defined if the runtime supports IPv6.

gauche.sys.threads
gauche.sys.pthreads
gauche.sys.wthreads

If the runtime supports multithreading, gauche.sys.threads is defined (See section gauche.threads - スレッド). Multithreading is based on either POSIX pthreads or Windows threads. The former defines gauche.sys.pthreads, and the latter defines gauche.sys.wthreads.

gauche.sys.sigwait
gauche.sys.setenv
gauche.sys.unsetenv
gauche.sys.clearenv
gauche.sys.getloadavg
gauche.sys.getrlimit
gauche.sys.lchown
gauche.sys.getpgid
gauche.sys.nanosleep
gauche.sys.crypt
gauche.sys.symlink
gauche.sys.readlink
gauche.sys.select
gauche.sys.fcntl
gauche.sys.syslog
gauche.sys.setlogmask
gauche.sys.openpty
gauche.sys.forkpty

Those are defined based on the availability of these system features of the platform.

R7RSで定義されたfeature identifiers

r7rs

Indicates the implementation complies r7rs.

exact-closed

Exact arithmetic operations are closed; that is, dividing an exact number by a non-zero exact number always yields an exact number.

ieee-float

Using IEEE floating-point number internally.

full-unicode

Full unicode support.

ratios

Rational number support

posix
windows

Either one is defined, according to the platform.

big-endian
little-endian

Either one is defined, according to the platform.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated on July 19, 2014 using texi2html 1.82.