# テンソル内包表記ガイド

TL言語は、Haskellのリスト内包表記にインスパイアされた、強力で表現力豊かなテンソル内包表記（Tensor Comprehension）を提供します。これにより、テンソルの作成、要素ごとの変換、およびリダクション（集約）を簡潔に記述できます。

## 構文の概要

基本的な構文は以下の通りです：

```rust
[ <indices> | <clauses> { <body> } ]
```

*   **`<indices>`**: 出力テンソルの次元を表す変数のリスト（カンマ区切り）。
*   **`<clauses>`**: ジェネレータ（範囲指定）または条件式（フィルタ）のリスト（カンマ区切り）。
*   **`{ <body> }`**: 各要素の値を計算するブロック式。省略された場合、文脈から推論されるか、デフォルトで 0.0 になります。

---

## 1. ジェネレータ (Generators)

ジェネレータは、インデックス変数が取りうる値の範囲を定義します。

### 明示的な範囲指定
`<-` を使用して、インデックスの範囲を明示的に指定できます。

```rust
// サイズ5の1次元テンソルを作成: [0, 1, 2, 3, 4]
let A = [i | i <- 0..5 { i }];
```

### 暗黙的な推論
出力 `<indices>` で使用されている変数のジェネレータが省略された場合、`<body>` 内で使用されているテンソルの形状から範囲を推論しようとします。

```rust
// 'i' の範囲は A の形状から推論されます
let B = [i | { A[i] * 2 }];
```

---

## 2. 条件式 (Conditions / Filtering)

`<clauses>` セクションにブール式を含めることで、計算をフィルタリングできます。

*   条件が **真 (true)** の場合、その反復（イテレーション）の計算が実行されます。
*   条件が **偽 (false)** の場合、その反復はスキップされます（値は 0.0 のままか、リダクションに加算されません）。

```rust
// 偶数のインデックスのみ値を持つテンソル（他は0.0）
let Evens = [i | i <- 0..5, (i % 2) == 0 { i }];
// 結果: [0, 0, 2, 0, 4]
```

複数の条件を書くことができ、それらは論理積 (AND) として扱われます。

```rust
let C = [i | i <- 0..10, i > 2, i < 8 { i }];
```

---

## 3. リダクション (Reductions)

`<clauses>` で定義されているが、出力 `<indices>` に **含まれない** 変数は、**リダクション変数** として扱われます。これらの変数について総和（Sum）が計算されます。

```rust
// 内積 (Dot product)
// 'k' は出力 [] に含まれないため、リダクション変数となります。
// 'i' はスカラー出力（サイズ1）のためのダミーインデックスです。
let dot = [i | i <- 0..1, k <- 0..N { A[k] * B[k] }];
```

### 条件付きリダクション
条件式を使用して、特定の要素のみを合計することができます。

```rust
// 0から9までの偶数の合計
let SumEvens = [i | i <- 0..1, k <- 0..10, (k % 2) == 0 { k }];
// 結果: [20] (0 + 2 + 4 + 6 + 8)
```

---

## 4. その他の例

### 行列積 (Matrix Multiplication)
```rust
// C[i, j] = Sum_k ( A[i, k] * B[k, j] )
// 'k' は共有次元に対応し、集約されます。
let C = [i, j | i <- 0..M, j <- 0..P, k <- 0..N { A[i, k] * B[k, j] }];
```

### マスキング / ReLUのような操作
```rust
// 値が正ならそのまま、そうでなければ 0
let ReLU = [i | i <- 0..N, A[i] > 0 { A[i] }];
```

### 対角成分の抽出
```rust
// 行インデックスと列インデックスが等しい要素を抽出
let Diag = [i | i <- 0..N, j <- 0..N, i == j { Matrix[i, j] }];

---

## 5. ボディの省略 (Optional Body)

**ボディブロック** `{ ... }` を省略した場合、以下のような **「スマートな暗黙的ボディ」** が生成されます：

1.  **インデックスが1つの場合:** そのインデックス変数を値として生成します。
    ```rust
    // A = Tensor[[5], f32]: [0, 1, 2, 3, 4]
    let A = [i | i <- 0..5];
    ```

2.  **インデックスが複数の場合:** そのインデックス変数からなる **ベクトル（座標）** を生成します。これにより、テンソルのランク（次元）が1つ増加します。
    ```rust
    // T = Tensor[[N, M, 2], f32]
    // Shape(N, M) のグリッドの各点に、ベクトル [i, j] が配置されます。
    let grid = [i, j | i <- 0..N, j <- 0..M];
    
    // 具体例:
    // [i, j | i <- 0..2, j <- 0..2]
    // 結果:
    // [
    //   [[0, 0], [0, 1]], 
    //   [[1, 0], [1, 1]]
    // ]
    // (Shape(2, 2, 2) のテンソル)
    ```

これにより、`grid - center` のようなベクトル場に対する演算が直感的に行えるようになります。
この挙動は、Haskellのリスト内包表記がフラットなリスト `[(0,0), (0,1)...]` (Shape(N*M)) を返すのと対照的です。TLではテンソルの多次元構造（トポロジー）を維持することを重視しています。
```
