--- title: 16.2.1 tags: The Racket Guide slideOptions: theme: white slideNumber: 'c/t' center: false transition: 'none' keyboard: true width: '93%' height: '100%' --- <style> /* basic design */ .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p { font-family: 'Meiryo UI', 'Source Sans Pro', Helvetica, sans-serif, 'Helvetica Neue', 'Helvetica', 'Arial', 'Hiragino Sans', 'ヒラギノ角ゴシック', YuGothic, 'Yu Gothic'; text-align: left; line-height: 1.8; letter-spacing: normal; text-shadow: none; word-wrap: break-word; color: #444; } .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5 {font-weight: normal;}, .reveal h6 {font-weight: bold;} .reveal h1, .reveal h2, .reveal h3 {color: #2980b9;} .reveal th {background: #DDD;} .reveal section img {background:none; border:none; box-shadow:none; max-width: 95%; max-height: 95%;} .reveal blockquote {width: 90%; padding: 0.5vw 3.0vw;} .reveal table {margin: 1.0vw auto;} .reveal code {line-height: 1.2;} .reveal p, .reveal li {padding: 0vw; margin: 0vw;} .reveal .box {margin: -0.5vw 1.5vw 2.0vw -1.5vw; padding: 0.5vw 1.5vw 0.5vw 1.5vw; background: #EEE; border-radius: 1.5vw;} /* table design */ .reveal table {background: #f5f5f5;} .reveal th {background: #444; color: #fff;} .reveal td {position: relative; transition: all 300ms;} .reveal tbody:hover td { color: transparent; text-shadow: 0 0 3px #aaa;} .reveal tbody:hover tr:hover td {color: #444; text-shadow: 0 1px 0 #fff;} /* blockquote design */ .reveal blockquote { width: 90%; padding: 0.5vw 0 0.5vw 6.0vw; font-style: italic; background: #f5f5f5; } .reveal blockquote:before{ position: absolute; top: 0.1vw; left: 1vw; content: "\f10d"; font-family: FontAwesome; color: #2980b9; font-size: 3.0vw; } /* font size */ .reveal h1 {font-size: 5.0vw;} .reveal h2 {font-size: 3.0vw;} .reveal h3 {font-size: 2.8vw;} .reveal h4 {font-size: 2.6vw;} .reveal h5 {font-size: 1.8vw;} .reveal h6 {font-size: 2.2vw;} .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p {font-size: 2.2vw;} .reveal code {font-size: 1.6vw;} /* new color */ .red {color: #EE6557;} .blue {color: #16A6B6;} /* split slide */ #right {left: -18.33%; text-align: left; float: left; width: 50%; z-index: -10;} #left {left: 31.25%; text-align: left; float: left; width: 50%; z-index: -10;} </style> <style> /* specific design */ .reveal h1 { margin: 0% -100%; padding: 2% 100% 4% 100%; color: #fff; background: #fffa5e; /* fallback for old browsers */ background: linear-gradient(-45deg, #f7f439, #54ffa4, #23A6D5, #238ed5); background-size: 200% 200%; animation: Gradient 60s ease infinite; } @keyframes Gradient { 0% {background-position: 0% 50%} 50% {background-position: 100% 50%} 100% {background-position: 0% 50%} } .reveal h2 { text-align: center; margin: -5% -50% 2% -50%; padding: 3% 10% 1% 10%; color: #fff; background: #fffa5e; /* fallback for old browsers */ background: -webkit-linear-gradient(to right, #c74646, #fffa5e); /* Chrome 10-25, Safari 5.1-6 */ background: linear-gradient(to right, #c74646, #fffa5e); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ } .reveal h4 { text-align: center; } </style> --- ## 16.2.1 構文オブジェクト マクロトランスフォーマの入力と出力(ソース形式と置換形式)は、構文オブジェクトとして表されます。構文オブジェクトには、式の引用形式に本質的に対応するシンボル、リスト、定数値(数字など)が含まれます。例えば、式(+ 1 2)の表現には、記号「+」と数字の「1」と「2」がリストに含まれています。この引用された内容に加えて、構文オブジェクトはソースロケーションと語彙結合情報をフォームの各部分に関連付けます。ソースロケーション情報は、構文エラーを報告するときなどに使用され、語彙結合情報は、マクロシステムが語彙の範囲を維持するために使用されます。この追加情報に対応するため、式 (+ 1 2) の表現は単なる '(+ 1 2) ではなく、'(+ 1 2) を構文オブジェクトにパッケージ化したものになります。 リテラルのシンタックスオブジェクトを作成するには、シンタックスフォームを使用します。 ```ocaml > (syntax (+ 1 2)) #<syntax:eval:1:0 (+ 1 2)> ``` ' が quote を省略するのと同じように、#' は syntax を省略します。 ```ocaml > #'(+ 1 2) #<syntax:eval:1:0 (+ 1 2)> ``` シンボルだけを含むシンタックスオブジェクトは、識別子シンタックスオブジェクトです。Racketは、識別子を検出するidentifier? 特に、free-identifier=? は、2つの識別子が同じバインディングを参照しているかどうかを判断します。 ```ocaml > (identifier? #'car) #t > (identifier? #'(+ 1 2)) #f > (free-identifier=? #'car #'cdr) #f > (free-identifier=? #'car #'car) #t > (require (only-in racket/base [car also-car])) > (free-identifier=? #'car #'also-car) #t ``` シンタックスオブジェクト内のリスト、シンボル、数字などを見るには、 syntax->datum を使用します。 ```ocaml > (syntax->datum #'(+ 1 2)) '(+ 1 2) ``` syntax-e関数はsyntax->datumと似ていますが、ソースの位置と字句の文脈の情報を1層だけアンラップして、独自の情報を持つサブフォームをシンタックスオブジェクトとしてラップしたままにします。 ```ocaml > (syntax-e #'(+ 1 2)) '(#<syntax:eval:1:0 +> #<syntax:eval:1:0 1> #<syntax:eval:1:0 2>) ``` syntax-e関数は、シンボル、数値、その他のリテラル値で表現されるサブフォームの周りに、常にシンタックスオブジェクトのラッパーを残します。余分なサブフォームをアンラップするのは、ペアをアンラップするときだけで、その場合、シンタックス・オブジェクトがどのように構築されたかに応じて、ペアのcdrが再帰的にアンラップされることがあります。 syntax->datumの反対は、もちろんdatum->syntaxである。'(+ 1 2)のようなデータに加えて、datum->syntaxは語彙的な文脈を提供するために既存のシンタックスオブジェクトを必要とし、またオプションとしてソースロケーションを提供するために別のシンタックスオブジェクトを必要とします。 ```ocaml > (datum->syntax #'lex '(+ 1 2) #'srcloc) #<syntax:eval:1:0 (+ 1 2)> ``` 上の例では、新しいシンタックスオブジェクトには #'lex のレキシカルコンテクストが使われ、 #'srcloc のソースロケーションが使われています。 datum->syntaxの第2引数(すなわち "datum")にシンタックスオブジェクトが含まれている場合、それらのシンタックスオブジェクトは結果にそのまま保存されます。つまり、結果をsyntax-eで分解すると、最終的にdatum->syntaxに与えられたシンタックスオブジェクトが生成されるのです。