OmniAICreator/Qiita-1.07M huggingface dataset:
JdbcTemplateからJdbcClientに移行して嬉しかったこと2つ

# バージョン
- Spring Framework 6.1
- Spring Boot 3.2

# JdbcClientって？
Spring Framework 6.1（対応するSpring Bootは3.2）から`JdbcClient`インタフェースが導入されました。
内部的には`JdbcTemplate`および`NamedParameterJdbcTemplate`のラッパーです。
流れるようなインタフェース（Fluent API）が特徴です。

# Optionalが使いやすい
`JdbcTemplate`で主キー検索してその結果を何かのクラスの`Optional`にしたい場合、👇のようにちょっと面倒でした。

```java:JdbcTemplateでOptionalを返す例
public Optional<Hoge> selectById(Integer id) {
    try {
        Hoge hoge = jdbcTemplate.queryForObject("""
                SELECT id, name
                FROM hoge WHERE id = ?
                """, new DataClassRowMapper<>(Hoge.class), id);
        return Optional.of(hoge);
    } catch (EmptyResultDataAccessException e) {
        return Optional.empty();
    }
}
```

これが`JdbcClient`だと👇のように書けます。

```java:JdbcClientでOptionalを返す例
public Optional<Hoge> selectById(Integer id) {
    Optional<Hoge> hogeOp = jdbcClient.sql("""
                    SELECT id, name
                    FROM hoge WHERE id = ?
                    """)
            .param(id)
            .query(new DataClassRowMapper<>(Hoge.class))
            .optional();
    return hogeOp;
}
```

例外をキャッチする必要が無いのでスッキリですね！

# KeyHolderが使いやすい
INSERTした時にDBで自動生成された主キー値（PostgreSQLのシーケンスなどが使われている場合）を取得するには`KeyHolder`を使う必要があります。`JdbcTemplate`の場合、`PreparedStatement`を操作する必要があって面倒でした。

```java:JdbcTemplateでKeyHolderを使う例
public Hoge insert(Hoge hoge) {
    KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(connection -> {
        PreparedStatement statement = connection.prepareStatement("""
                INSERT INTO hoge(name)
                VALUES(?)
                """, new String[]{"id"});
        statement.setString(1, hoge.name());
        return statement;
    }, keyHolder);
    int newId = keyHolder.getKey().intValue();
    return new Hoge(newId, hoge.name());
}
```

`JdbcClient`では`update()`の引数に`KeyHolder`と主キー列名を渡すだけで済みます。主キー列名が配列ではなく可変長引数になっているのも嬉しいですね！

```java:JdbcClientでKeyHolderを使う例
public Hoge insert(Hoge hoge) {
    KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcClient.sql("""
                    INSERT INTO hoge(name)
                    VALUES(?)
                    """)
            .param(hoge.name())
            .update(keyHolder, "id");
    int newId = keyHolder.getKey().intValue();
    return new Hoge(newId, hoge.name());
}
```

# 参考資料
- [JdbcClientのJavadoc](https://docs.spring.io/spring-framework/docs/6.1.x/javadoc-api/org/springframework/jdbc/core/simple/JdbcClient.html)
連休フラグと連休N日目を作成する(SPSS Modeler データ加工逆引き1-16)

# 連休フラグと連休N日目を作成する

![スクリーンショット 2023-12-19 17.25.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/66db48c0-36b4-5908-7633-745896080e09.png)

祝日マスタを日付に紐づけて休日フラグを作成する場合には逆引き1-12を参照ください。

## 1.想定される利用目的

・連休の持つ目的変数への重みの算出
・回帰モデルによる時系列予測作成のための説明変数作成

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/blob/main/holiday_master2024.str

## 3.サンプルストリームの説明

![スクリーンショット 2023-12-19 17.31.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/22191fc7-ed94-f6bd-1adc-23a7b133d6df.png)

a.対象データは以下の通りです。

![スクリーンショット 2023-12-19 17.33.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/3f6ae6bd-4cca-0242-15db-7536632d5b35.png)

日付から休日を算出するaまでのプロセスは逆引き1-12を参照ください。

https://qiita.com/416nishimaki/items/19f91717c2df52211f81

b.[フィールド作成]ノードを編集します。列方向に参照するオフセット関数を利用します。[@&#xFFF0;OFFSET(フィールド,1)]でフィールドの値の1行上を参照します。
@&#xFFF0;OFFSET(休日フラグ,-2)=1 は２つ下の休日フラグが1であることを意味します。

![スクリーンショット 2023-12-19 17.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/b3982d4b-e13d-267c-507d-008e66d23e98.png)

c.[フィールド作成]ノードを編集します。
![スクリーンショット 2023-12-19 17.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9effc2c4-a1e8-b784-58dd-1b51c98ce438.png)

[テーブル]を表示します。

![スクリーンショット 2023-12-19 17.34.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/378fbeef-175a-cde0-48a2-62753acb7284.png)


#### 注意事項

2025年以降のカレンダーがストリームに含まれていないため、必要に応じて追加してください。

## 4.参考情報

#### 祝日マスタを日付で割り当て休日フラグを作成する

https://qiita.com/416nishimaki/items/19f91717c2df52211f81

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
2分法をElixirで実装してみた

授業で教えている2分法をElixirで実装してみましたので，報告します．

## 解答例

```elixir
fn f, {a, b}, e ->
  if f.(a) * f.(b) < 0 do
    Stream.unfold({a, b}, fn
      {a, b} ->
        c = (a + b) / 2.0

        if f.(a) * f.(c) < 0 do
          {{a, c}, {a, c}}
        else
          {{c, b}, {c, b}}
        end
    end)
    |> Stream.drop_while(fn {a, b} -> abs(a - b) / 2 > e end)
    |> Enum.take(1)
    |> hd()
    |> elem(0)
    |> then(&Tuple.append({:ok}, &1))
  else
    {:error, "Solution is not found."}
  end
end
```
脱Windows

# 脱Windowsでも困らない方法があります。
最近のWindowsは高いハードを買わないと使えないほど重くなっています。
そこで既存の中古PCにLinuxのUbuntu20.04LTSを入れて使う方法をご紹介します。

## 利用環境
１．ネットワーク環境は必修です。
２．クラウドの仮想PCを使います。
３．使うクラウドOSはWindowsServerです。

## 通常はUbuntuを使う
ブラウザの操作などはUbuntuで十分でローカルストレージも128GSSD環境で結構空きがあります。
Ubuntuで使うPCは10年ぐらい前のものCore-i5の４世代ぐらいのものなら十分でHDDでもSSDでもあまり差はないですがHDDは機械なのでSSDタイプをおすすめします。

## さくらのVPSとMicrosoft365を使う
以下、２０２３年１２月２７日現在の価格です。
さくらのVPSでW2Gプランを契約しましょう！・・・・・・月額２１１８円
Microsoft365 を契約します。・・・・・・・・・・・・月額１５６０円
合計３６７８円／月
でWindowsServerとOfficeが使えます。

## 使う方法
契約したユーザーでさくらの会員ページにログインしコンソールを起動することで使えます。
Microsoft365は5台までインストールできるので５台のサーバーを契約すれば１台あたりの金額を下げることができます。
ちゃんと設定すればVPNも使えるはず（やったことはないけれど）

## クラウドWindowsサーバーを使うと
WindowsサーバーはWindows10や11に比べると意外と軽いのでストレスなく使えます。
ストレージはMicrosoft365のOneDriveを主に使うようにすればクラウドなので端末からもすぐにファイルのやり取りが可能です。
Windowsのライフサイクルも通常のWindowsより長いです。
GraphAPI連携とUiPathで気を付けること２

　今回は、GraphAPIのAPIアクセス許可の項目がよくわからないものなのでMicrosoft社のドキュメントを参考に軽くまとめてみた。

 参考文献はこちら
Microsoft Graph のアクセス許可のリファレンス
 https://learn.microsoft.com/ja-jp/graph/permissions-reference

 　詳細の説明は上部に譲るとして、簡単に重要な項目をまとめてみた。
  
 １，基本的に、承認の種類は「委任」「アプリケーション」の２種類だが、どちらか片方のみの場合がある。
 例)
 ・Mail.Read.Shared（委任のみ）
 ・LearningSelfInitiatedCourse.ReadWrite.All（アプリケーションのみ）
 ・Calendars.ReadWrite.Shared（委任のみ）
 
２，Sharedはアクセスしたユーザーと共有部分も対象にできるもの。Allはアクセスしたユーザーの権限内でのすべてが対象につくことが多い。Sharedは委任のみのことが多い。

３，対象のアプリケーションは以下の通りらしい。
・Mail→Outlookのメール
・Calender→Outlookの予定表
・File→OneDriveなど
・site→SharePointなど
・Note→OneNoteなど

　以上、まだまだ奥が深いので研究していきたい。
ニュートン法をElixirで実装してみた

授業で教えているニュートン法をElixirで実装してみましたので，報告します．

## 解答例

```elixir
fn f, f_d, x0, n, e ->
  Enum.reduce_while(1..n, {x0, nil}, fn _, {x, _} ->
    t = f.(x) / f_d.(x)
    x = x - t
    ee = abs(t / x)
    if ee < e do
      {:halt, {x, ee}}
    else
      {:cont, {x, ee}}
    end
  end)
  |> then(fn {x, ee} ->
    if ee < e do
      {:ok, x}
    else
      {:error, "Solution is not found."}
    end
  end)
end
```

## 実行例

`f`に$f(x)$，`f_d`に$f'(x)$，`x0`に初期値，`e`に目標精度を与えます．

先ほどの関数を変数`newton`に代入し，$f(x) = x^2 - 16, f'(x) = 2x$としてみましょう．

```elixir
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 2, 0.1)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 3, 0.1)
{:ok, 4.009115285226041}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 3, 0.01)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 4, 0.01)
{:ok, 4.000010362438947}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 4, 0.001)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 5, 0.001)
{:ok, 4.000000000013422}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 5, 0.0001)
{:ok, 4.000000000013422}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 5, 0.00001)
{:ok, 4.000000000013422}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 5, 0.000001)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 16 end, fn x -> 2 * x end, 10, 6, 0.000001)
{:ok, 4.0}
```

$f(x) = x^2 - 2, f'(x) = 2x$としてみましょう．

```elixir
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 2, 0.1)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 3, 0.1)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 4, 0.1)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 5, 0.1)
{:ok, 1.4145256551487377}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 5, 0.01)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 6, 0.01)
{:ok, 1.4142135968022693}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 6, 0.001)
{:ok, 1.4142135968022693}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 6, 0.0001)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 7, 0.0001)
{:ok, 1.4142135623730954}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 7, 0.00001)
{:ok, 1.4142135623730954}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 7, 0.000001)
{:ok, 1.4142135623730954}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 7, 0.0000001)
{:ok, 1.4142135623730954}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 7, 0.00000001)
{:error, "Solution is not found."}
iex> newton.(fn x -> x ** 2 - 2 end, fn x -> 2 * x end, 10, 8, 0.00000001)
{:ok, 1.4142135623730951}
iex> :math.sqrt(2)
1.4142135623730951
```
pythonのライブラリやパッケージをインストールする際にエラーが出る


下記のようなエラーが出ました。

~~~
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
anaconda-project 0.11.1 requires ruamel-yaml, which is not installed.
ja-ginza-electra 5.1.3 requires spacy<3.7.0,>=3.2.0, but you have spacy 3.7.2 which is incompatible.
ginza 5.1.3 requires spacy<3.7.0,>=3.2.0, but you have spacy 3.7.2 which is incompatible.
conda-repo-cli 1.0.20 requires clyent==1.2.1, but you have clyent 1.2.2 which is incompatible.
conda-repo-cli 1.0.20 requires nbformat==5.4.0, but you have nbformat 5.5.0 which is incompatible.
conda-repo-cli 1.0.20 requires requests==2.28.1, but you have requests 2.31.0 which is incompatible.
~~~



# 原因

Copilotの回答は下記の通りでした。

>このエラーは、pipがインストールされているパッケージの依存関係を正しく解決できないことを示しています。pipは、パッケージをインストールするときに、そのパッケージが要求する他のパッケージのバージョンとの整合性をチェックします。しかし、時には、既にインストールされているパッケージとの競合が発生することがあります。この場合、pipはエラーメッセージを出力して、どのパッケージが競合しているかを教えてくれます。
>このエラーを解決するためには、いくつかの方法がありますが、一般的なものとしては以下のようなものがあります。
>競合しているパッケージのバージョンを変更する: 例えば、spacyのバージョンを3.7.2から3.2.0にダウングレードすることで、ja-ginza-electraやginzaとの競合を解消できます。この場合、pip install spacy==3.2.0というコマンドを実行します。ただし、この方法は、他のパッケージとの競合を引き起こす可能性がありますので、注意が必要です。
>競合しているパッケージをアンインストールする: 例えば、conda-repo-cliを使わないのであれば、conda-repo-cliをアンインストールすることで、clyentやnbformatやrequestsとの競合を解消できます。この場合、pip uninstall conda-repo-cliというコマンドを実行します。ただし、この方法は、必要なパッケージを削除してしまう可能性がありますので、注意が必要です。
仮想環境を使う: 仮想環境とは、Pythonのパッケージや設定を分離して管理するための環境です。仮想環境を使うことで、競合しているパッケージを別々の環境に分けてインストールすることができます。例えば、anaconda-projectを使うときは、ruamel-yamlをインストールした仮想環境を作り、ja-ginza-electraやginzaを使うときは、spacyのバージョンを3.2.0にした仮想環境を作ることができます。仮想環境の作り方や使い方については、[こちら]や[こちら]を参考にしてください。
以上が、このエラーを解決するためのコードに関する私の回答です。pipに関心を持っていただき、ありがとうございます。: [Pythonの仮想環境の基本 - Qiita] : [Pythonの仮想環境の使い方 - Python入門]

原因となったコードセルは下記の通り



~~~
!pip install yfinance

from yahoo_fin import stock_info
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import datetime
import pickle


~~~

~~~
!pip install yfinance
! pip install clyent==1.2.1 nbformat==5.4.0
! pip install --upgrade clyent nbformat
!pip uninstall clyent nbformat
!pip install clyent nbformat
! pip install requests==2.31.0
!pip install spacy==3.6.0
!pip install requests==2.28.1
~~~


下記はChatGPT3.5。

>このエラーメッセージは、依存関係に関する競合やバージョンの不整合が起きていることを示しています。これを解決するために、いくつかの方法があります。
>まず最初に、pipを使用してインストールされたパッケージのバージョンを調整してみてください。例えば、spacyやrequestsなどの特定のパッケージのバージョンを変更することで、依存関係の競合を解消できるかもしれません。

# 解決方法

!Pipの部分を全部消したら直りました。
すでにDLされているということはつまり２重にDLしたら進まなくなるよということなんですね。
chatGPTの活用

# 自己紹介
皆さん初めまして、ichimatsu_123と申します！
体調を崩してしまった関係でなかなか記事がかけず、ようやく書くことができました！遅くなってしまってゴメンナサイ…
hataさん(@awonohata) 、みやのさん(@kotmyn0812)が立ち上げ人として、リレーエッセイを書いていくという事で、マナビDXから得たものは大きかったなあということで、是非記事を書いてみたいと思いました。企画立ち上げ、誠にありがとうございます。
普段私は機械系の計量計測に関わる検査の仕事をしていて、DXとか全く関係ありません。
しかし、昔からプログラミングが好きだったり、今の業務でもデジタル化を推進するのは大好きで、これは「本格的に取り組んでみたい！」と思ってマナビDXに参加しました。

# chatGPTの活用！
### chatGPTってナンダ？
「chatGPTってナンダ？」これが私の最初のchatGPTに対する印象でした。
なんだかとにかくすごいらしい！と聞いて、無料アカウントを作ってみたものの、特に活用はせず…
たまに人生相談(笑)なんかをして終わりでした。
### 要約
PBLを進めるにあたって、多くの文章を読んで、問題点を洗い出さないといけない場面がありました。
そこで利用を始めたのがchatGPT。
「あなたは〇〇コンサルタントです。これから読み込ませる文章を〇〇字くらいで要約して下さい」
「先ほど読み込ませた文章を見て、この会社の課題はどんな所にあると思いますか？箇条書きで10個挙げてください」
などと依頼すると、かなり良い精度で解答を出してくれるのです。
これを使って打ち手の検討を行いました。

### プログラミング
もう一点大いに役立ったのがプログラミングです。
マナビDXで特にプログラムを作ることは無かったのですが、本職の方で役に立ちました。
業務でVBAを使うことが多いのですが、書いて欲しいプログラムを日本語で表現すると、その通りにコードを書いてくれる！すごすぎる。
あと役に立ったのは、他人が書いたコードを読み込ませて「解説して下さい」とお願いする。
色々な人がコードを書き加えるせいで、共用のプログラムって「誰にも中身が分からない秘伝のタレ」になりがちですよね。笑
そんな「秘伝のタレ」もchatGPTに読み込ませると、分かりやすく解説してくれる！感動。

# まとめ
まとめると、要約やポイントの洗い出し、プログラミングにchatGPTが活用できるということを私はマナビDX参加によって学びました。
多くの方にとっては「当たり前だよ！」という感じ(笑)かもですが、こんな小さなことでも学びを得られたのを嬉しく思います。

# おまけ
おまけとして、転職活動の話をします。
社内で簡単な業務改善にまつわるシステムを作ったことがキッカケで、DX化に取り組む仕事をしてみたいなあと思ったのが、2022年の秋頃。
その後、今の状態では勉強不足だと思い立ち…
2023年3月…G検定
2023年6月…基本情報技術者
と、資格を取りました。ちなみ、G検定を取得してCDLEに入会したことがきっかけでマナビDXクエストの存在を知りました。
2023年11月頃から転職活動を始めて、職務経歴書の自己PRとして、マナビDXのことを書きました。
それで面接に臨んだのですが、「意外とマナビDXのことを掘り下げられる」というのが率直な感想です。
どんなPBLをやっているかや、企業協働プログラムで、どんな企業に対してどんな取組を行っているかをお話ししました。
中には、面接官の部下がマナビDXに参加しているという方もいて…
「経産省主催の教育プログラム」という看板は想像以上に大きいのだなと実感しました。
現在は第一志望から内定を頂き、承諾するか悩んでいるところでございます。

以上、蛇足でした！ここまでお読み頂き、本当にありがとうございました。投稿遅くなり申し訳ありませんでした。
皆様良いお年をお迎えください。

ichimatsu_123
windowsでiverilog その141

# 概要　
windowsでiverilogやってみた。
uartのverilog見つけたので、テストベンチ書いてみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0f8e5fd7-85a3-9135-c3b4-e6a840527165.png)


# サンプルコード

```
module test();
	parameter CLK_FRE = 10;
	parameter UART_FRE = 115200;
	parameter ENG_NUM = 9;
	parameter CHE_NUM = 3;
	parameter DATA_NUM = CHE_NUM * 2 + ENG_NUM;
	localparam IDLE = 0;
	localparam SEND = 1;
	localparam WAIT = 2;
	reg[7:0] tx_data;
	reg[7:0] tx_str;
	reg tx_data_valid;
	reg[31:0] wait_cnt;
	reg[3:0] state;
	reg[7:0] tx_cnt;
	reg clk;
	reg rst_n;
	reg rx_data_ready;
	wire tx_data_ready;
	wire[7:0] rx_data;
	wire rx_data_valid;
	wire [DATA_NUM * 8 - 1:0] send_data = {"hello world!", 16'h0d0a};
	uart_rx# (.CLK_FRE(CLK_FRE), .BAUD_RATE(UART_FRE)) uart_rx_inst(.clk (clk), .rst_n (rst_n), .rx_data (rx_data), .rx_data_valid (rx_data_valid), .rx_data_ready (rx_data_ready), .rx_pin (uart_rx));
	uart_tx# (.CLK_FRE(CLK_FRE), .BAUD_RATE(UART_FRE)) uart_tx_inst(.clk (clk), .rst_n (rst_n), .tx_data (tx_data), .tx_data_valid (tx_data_valid), .tx_data_ready (tx_data_ready), .tx_pin (uart_tx));
	always@(posedge clk or negedge rst_n)
	begin
		if (rst_n == 1'b0)
		begin
			wait_cnt <= 32'd0;
			tx_data <= 8'd0;
			state <= IDLE;
			tx_cnt <= 8'd0;
			tx_data_valid <= 1'b0;
		end
		else
			case(state)
			IDLE:
				state <= SEND;
			SEND:
			begin
				wait_cnt <= 32'd0;
				tx_data <= tx_str;
				if (tx_data_valid == 1'b1 && tx_data_ready == 1'b1 && tx_cnt < DATA_NUM - 1)
				begin
					tx_cnt <= tx_cnt + 8'd1;
				end
				else if (tx_data_valid && tx_data_ready)
				begin
					tx_cnt <= 8'd0;
					tx_data_valid <= 1'b0;
					state <= WAIT;
				end
				else if (~tx_data_valid)
				begin
					tx_data_valid <= 1'b1;
				end
			end
			WAIT:
			begin
				wait_cnt <= wait_cnt + 32'd1;
				if (rx_data_valid == 1'b1)
				begin
					tx_data_valid <= 1'b1;
					tx_data <= rx_data;
				end
				else if (tx_data_valid && tx_data_ready)
				begin
					tx_data_valid <= 1'b0;
				end
				else if (wait_cnt >= CLK_FRE * 1000_000)
					state <= SEND;
			end
			default:
				state <= IDLE;
			endcase
	end
	always@(*)
		tx_str <= send_data[(DATA_NUM - 1 - tx_cnt) * 8 +: 8];
	always
		#1
			clk = ~clk;
	initial
	begin 
		$dumpfile("test.vcd");
		$dumpvars(0, test);
		clk = 0;
		rst_n = 1;
		rx_data_ready = 1;
	#2
		rst_n = 0;
		rx_data_ready = 1;
	#2
		rst_n = 1;
		rx_data_ready = 1;
	#50000
		$finish;
	end
endmodule





```


以上。
mindの研究 その54

# 概要
mindが、謎なので調べてみた。
練習問題やってみた。

# 練習問題
mindでweb serverを書け。getとpostを捌け。

# 方針
- getなら２００ok
- postなら４０４

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/ccc66315-ede5-4048-f292-5434a5194696.png)


# サンプルコード

```
レスポンス0とは
　変換後は　文字列実体　長さ　2048
　変換後を　クリア
　変換後に　「HTTP/1.1 200 OK」を　追加し
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　変換後に　「Content-Type: text/html」を　追加し
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　変換後に　「<html><head></head><body>」を　追加し
　変換後に　「<form method="POST" action="http://localhost:40001/"><input type="text" name="title"><input type="submit" value="submit"></form>」を　追加し
　変換後に　「</body></html>」を　追加し
　変換後を　返すこと
。

レスポンス1とは
　変換後は　文字列実体　長さ　2048
　変換後を　クリア
　変換後に　「HTTP/1.1 404 Not Found」を　追加し
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　変換後に　「Content-Type: text/html」を　追加し
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　０DＨを　変換後に　一文字追加し
　０AＨを　変換後に　一文字追加し
　変換後に　「<html><head></head><body>」を　追加し
　変換後に　「<h1>404</h1>」を　追加し
　変換後に　「</body></html>」を　追加し
　変換後を　返すこと
。

メインとは
　ホスト名は　文字列
　ポート番号は　変数
　待ちソケットは　変数
　データソケットは　変数
　エラーコードは　変数
　文字列１は　文字列
　文字列2は　文字列
　単語1は　文字列
　単語2は　文字列
　「localhost」を　ホスト名に　入れ
　40001を　ポート番号に　入れ
　ホスト名と　ポート番号と　１個で　ｌｉｓｔｅｎし　待ちソケットに　入れ
　エラー？
　ならば
　　エラー文字列で　重大エラー
　つぎに
　ここから
　　「start」を　一行表示する
　　待ちソケットで　ａｃｃｅｐｔし　データソケットに　入れ
　　エラー？
　　ならば
　　　「エラー：」を　エラー出力し　エラー文字列を　一行エラー出力し
　　　打ち切り
　　つぎに
　　ここから
　　　データソケットから　ハンドル指定で一行読み出し　文字列１に　入れる
　　　データ終り？
　　　ならば
　　　　「[EOF]クライアントが終了しました。」を　一行表示する
　　　　打ち切り
　　　つぎに
　　　文字列１から　単語切り出し　単語1に　入れ
　　　文字列１から　単語切り出し　単語2に　入れ
　　　もし　単語1が　「GET」に　等しい文字列
　　　ならば
　　　　「get」を　一行表示する
　　　　レスポンス0を　文字列2に　入れ
　　　　文字列2を　データソケットに　ハンドル指定で一行書き込み
　　　　打ち切り
　　　つぎに
　　　もし　単語1が　「POST」に　等しい文字列
　　　ならば
　　　　「post」を　一行表示する
　　　　レスポンス1を　文字列2に　入れ
　　　　文字列2を　データソケットに　ハンドル指定で一行書き込み
　　　　打ち切り
　　　つぎに
　　　「データ ＝ 」を　表示し　文字列１を　一行表示し
　　繰り返し
　繰り返し
。





```

# 実行結果

```
>webserver4
start
get
start
post
start
[EOF]クライアントが終了しました。
start

```


以上。
ガウスの消去法で連立方程式を解くElixirプログラム

連立方程式を解く代表的なアルゴリズムとして，授業で教えている，ガウスの消去法をElixirとNxで書いたので，報告します．

## 解答例

```elixir
defmodule GuessianElimination do
  def solve(a, b) do
    {n, n} = Nx.shape(a)

    {a, b}
    |> forward_elimination(n)
    |> backward_substitution(n)
  end

  defp forward_elimination({a, b}, n) do
    0..n-2
    |> Enum.reduce({a, b}, fn k, {a, b} ->
      k+1..n-1
      |> Enum.reduce(pivot({a, b}, n, k), fn i, {a, b} ->
        alpha = Nx.negate(Nx.divide(a[i][k], a[k][k]))

        {
          Nx.indexed_add(a, indices(n, i), Nx.multiply(a[k], alpha)),
          Nx.indexed_add(b, Nx.tensor([i]), Nx.multiply(b[k], alpha))
        }
      end)
    end)
  end

  defp backward_substitution({a, b}, n) do
    Enum.reduce(n-2..0, [Nx.to_number(b[n-1]) / Nx.to_number(a[n-1][n-1])], fn k, x ->
      r =
        k+1..n-1
        |> Enum.map(& {Nx.to_number(a[k][&1]), Enum.at(x, &1 - k - 1)})
        |> Enum.map(fn {a, b} -> a * b end)
        |> Enum.sum()

      [(Nx.to_number(b[k]) - r) / Nx.to_number(a[k][k]) | x]
    end)
    |> Nx.tensor()
  end

  defp pivot({a, b}, n, k) do
    Nx.transpose(a)[k]
    |> Nx.slice([k], [n - k])
    |> Nx.argmax()
    |> Nx.add(k)
    |> Nx.to_number()
    |> case do
      l when l != k ->
        {
          swap(a, {indices(n, k), k}, {indices(n, l), l}),
          swap(b, {Nx.tensor([k]), k}, {Nx.tensor([l]), l})
        }

      _ -> {a, b}
    end
  end

  defp swap(t, {indices_l, l}, {indices_k, k}) do
    t
    |> Nx.indexed_put(indices_k, t[l])
    |> Nx.indexed_put(indices_l, t[k])
  end

  defp indices(n, i) do
    0..n-1
    |> Enum.map(&[i, &1])
    |> Nx.tensor()
  end
end
```

関数`forward_elimination`は前進消去，関数`backward_substitution`は後退代入，関数`pivot`は，部分ピボット選択(対角成分の最も大きな行を選択する処理)です．

作るのもとても難しかったですが，できたプログラムコードを説明するのも，とても難しいです...
Ubuntu22.04にVOICEVOXを入れてみた話

# Ubuntu22.04にVOICEVOXを入れると・・・
ただ単に起動しないことがあるみたい。

## 原因を調べてみた

まずインストーラー（シェルスクリプト）でインストールするとユーザー環境にインストールされる。
（すべてのユーザーで参照される設定ではなく、個人環境にインストールされるという意味なのでroot権限不要でインストールできる）

通常はwhereisでインストールされたコマンドは、見つかるが見当たらないので cd でホームに移動しfindコマンドで調べてみる
find . -name 'voice*' -print
すると./local/shear/applocations にvoicevox.desktop という起動定義が見つかる
これによると ./voicevox/VOICEVOX.AppImage %U で起動するので手動で起動してみると
libfuse.so.2がないよと言われる。
要するに依存ライブラリがないので

sudo apt-get install fuse

で問題は解決する。

以上
asdfで共有用のkubectlを/optとかにインストールする

# TL;DR

普通に(Getting started通りに)インストールしたkubectl on asdfを`/opt/asdf`に移動して起動するとこまで構成変更したときのメモ。

# モチベーションとやったこと

おしごとでk8sを触るようになったのだけど、基本インターネットに直接出られない環境での操作なので、asdfと管理下のkubectlを好きなところにファイルで移植して使いたい。
どうやらasdfはインストールしたバイナリをディレクトリ内に持ってくれるようなので、開発環境でキッティングしてzipで固めて本番環境に持っていけないかな、と思い試行錯誤してみることにした。

## 素直なインストール

https://asdf-vm.com/guide/getting-started.html

Getting Startedに従ってインストール。

```bash:download & 環境変数セット
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1

cat <<'EOS' >> ~/.zshrc

# for asdf
. "$HOME/.asdf/asdf.sh"
EOS

cat <<'EOS' >> ~/.zshrc
# append completions to fpath
fpath=(${ASDF_DIR}/completions $fpath)
# initialise completions with ZSH's compinit
autoload -Uz compinit && compinit
EOS

source ~/.zshrc
```

ついで、kubectlパッケージ、kubectl 1.27.9をインストール（ふるいいうな！）

```bash:asdf add & asdf install kubectl 1.27.9
asdf plugin add kubectl
asdf install kubectl 1.27.9
```

## /opt下に移植してみる

### 移動させてrootにオーナー変更

```bash
sudo cp -pr .asdf /opt/asdf
sudo chown root:root /opt/asdf -R
```

### ~/.zshrc書き換え

```bash
sed -i.bk_`TZ=Asia/Tokyo date --iso-8601=seconds` \
  -e 's|$HOME/.asdf|/opt/asdf|' ~/.zshrc
source ~/.zshrc
```

## これだけでは期待したように動かないので対策する

asdf.shのパスを変えただけでは、asdfは`/opt/asdf`配下のものが使えるようにはなるけど、すでにインストールしたkubectlが見つからなくて使えない。
すくなくとも以下の2つを対応する必要がある。

- 環境変数の設定
    - `ASDF_DIR`, `ASDF_DATA_DIR`に`/opt/asdf`をセットする
- shimの更新
    - asdfは内部的にshimというのを使っていて、それがインストール時のPathに向いている。これを更新する。

### 環境変数の設定

https://asdf-vm.com/manage/configuration.html
こちらに必要な環境変数が書いてあった。

`asdf.sh`を読む前に`ASDF_DIR`と`ASDF_DATA_DIR`をセットするように修正してみる。

```bash
# まずは爽やかにドット実行行を消す
sed -i.bk_`TZ=Asia/Tokyo date --iso-8601=seconds` \
  -e 's|. "/opt/asdf/asdf.sh"||' ~/.zshrc
```

```bash
# exportしてからasdf.shを読むように変更
cat <<'EOS' >> ~/.zshrc

export ASDF_DIR=/opt/asdf
export ASDF_DATA_DIR=/opt/asdf

. "/opt/asdf/asdf.sh"
EOS
```

最終的にこんな感じになってればよさそう（以下はvimで書き換えているから順番とか違うけど）

```bash:~/.zshrc
# 略

export ASDF_DIR=/opt/asdf
export ASDF_DATA_DIR=/opt/asdf

#. "$HOME/.asdf/asdf.sh"
. "/opt/asdf/asdf.sh"

# append completions to fpath
fpath=(${ASDF_DIR}/completions $fpath)
# initialise completions with ZSH's compinit
autoload -Uz compinit && compinit
```



### shimの更新

```bash
sudo mv /opt/asdf/shims /opt/asdf/shims_bk
```

`~/.zshrc`で`asdf.sh`を読み込んでるとsudoするのがめんどい(環境変数引き継ぎ的な意味で)ので、suでrootになって環境変数設定してから`asdf reshim`を叩く（`/opt/asdf/asdf.sh`ができる)

```bash
sudo su -

export ASDF_DIR=/opt/asdf
export ASDF_DATA_DIR=/opt/asdf

. "/opt/asdf/asdf.sh"

asdf reshim
```

```bash
# そのままrootでも、もとのユーザでも
asdf global kubectl 1.27.9
kubectl --version
```

以下の通り、とりあえず使えそうに見える。

```text
LASTY@bounoki[969]% kubectl version --client
WARNING: This version information is deprecated and will be replaced with the output from kubectl version --short.  Use --output=yaml|json to get the full version.
Client Version: version.Info{Major:"1", Minor:"27", GitVersion:"v1.27.9", GitCommit:"d15213f69952c79b317e635abff6ff4ec81475f8", GitTreeState:"clean", BuildDate:"2023-12-19T13:41:13Z", GoVersion:"go1.20.12", Compiler:"gc", Platform:"linux/amd64"}
Kustomize Version: v5.0.1
```

# TODO

まだ実際にクローズな環境で動かしてみてないので、年内に試す。。
Pythonで「タプルの長さ(要素数)を取得する」の動作を確認してみた

# 概要

Pythonで「タプルの長さ(要素数)を取得する」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/tuple/index4.html

# 実装

以下のファイルを作成しました。
```sample.py
print(len(("Red", "Blue", "Green")))
print(len((10, 20, 30, 40, 50)))

animallist = ("Monkey", "Cat", "Dog", "Cow")
print("要素数は " + str(len(animallist)) + " です。")
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
3
5
要素数は 4 です。
```

# まとめ

何かの役に立てばと。
多項式を計算するホーナー法をElixirで実装する

授業で教えているホーナー法という，多項式を効率よく計算するアルゴリズムをElixirで実装してみましたので，報告します．

## 解答例

$a_0 x^n + a_1 x^{n - 1} + a_2 x^{n - 2} \cdots + a_{n - 2} x^2 + a_{n - 1} x + a_n$ を計算するのですが，リスト`a`として $[a_0, a_1, a_2, \cdots, a_{n - 2}, a_{n - 1}, a_n ]$ を与えます．

```elixir
fn [h | t], x ->
  Enum.reduce(t, h, fn a, y -> y * x + a end)
end
```

## 解説

ホーナー法は次のようなアルゴリズムです．

* $y_k = a_0 x^k + a_1 x^{k - 1} + \cdots + a_{k - 1} x + a_{k}$ と定義する．
* $y_k$は次の漸化式で表せる
    * $y_0 = a_0$
    * $y_k = y_{k - 1} x + a_k$

そこで，`t` すなわち リスト$[a_1, a_2, \cdots, a_{n - 1}, a_n]$に対して，初期値`h` すなわち $a_0$ を初期値として，漸化式 `fn a, y -> y * x + a` を累積する[`Enum.reduce/3`](https://hexdocs.pm/elixir/1.16.0/Enum.html#reduce/3) を計算します．

ホーナー法が，Elixirだとこんなにも単純に書けるのは，少し感動しますね．

## 応用

先ほどの式を変形して，次のように定義します．

```elixir
fn [h | t] ->
  fn x ->
    Enum.reduce(t, h, fn a, y -> y * x + a end)
  end
end
```

この関数を`f`とすると，次のようにすると，$g(x) = x^2 + 2x + 1$ を計算する関数`g`を得ることができます．

```elixir
g = f.([1, 2, 1])
```

```elixir
iex> g.(1)
4
iex> g.(2)
9
iex> g.(3)
16
```

ちなみに，このような手法をカリー化と言います．
DDDにおけるDomain Eventとは？

## ドメインイベントとは？

ドメインイベントとは、**業務においで〜が起きた**と言う意味だと思っている。


> ドメイン内での変更の副作用を明示的に実装するには、ドメインイベントを使います。 

マイクロソフトのドキュメントによると、こんな画像のように、Order（注文）のドメインに注文開始ということが起きた。起きたイベントはドメイン内でコンテキストを共有することなど。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491081/4d6db632-dfba-98ea-4750-d90373a12e64.png)


https://learn.microsoft.com/ja-jp/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation


### 例えば？

ユーザーを作成した
そのイベントを受けて、パスワード設定のためのメールを送る

ファイルをアップロードする
そのイベントを受けて、ファイルのベリデーションやストーレージバケツを移動するなど

:::note info
**要は〇〇をクリックしたとかではなく、業務的な意味を持つイベント**
:::


もう少し詳しい例を言うと、ファイルアップロードのフォームを想像してみてください
- フォームでは必要な項目、ファイルアップロード、そして登録ボタンが存在する
- 項目を入力して、ファイルをアップロードした
    - アップロードしたファイルは一時的に保存するStorageに保存される
- 登録ボタンを押して、ホーム画面に戻す
- アップロードステータスは`アップロード中`
- **業務において「ファイルアップロード」が起こった**
    - 位置的に保存するStorageから、普通のStorageに移動する 
    - ファイルアップロード結果をDBに保存する
    - 成功の場合はアップロードステータスを`成功`に変更する
    - ここの処理は非同期で行われる

では、なぜDomain Eventでやるのか？
- 理由は単純に、`アップロード中`→`成功`に変更するまでの処理は長い
- Domain Eventで実装しないとユーザーが登録ボタンを押すのに、変更が完了までAPIのレスポンスを返すまで長く待つことになってしまう


### メリット

実装方法や要件によって変わりますが、基本的には

- 非同期
    - イベント発行側では、処理にかかる時間は不明なので、完了まで待つのは非現実的
- 整合性を保てる
- 発行したイベントを別のマイクロサービスが処理できる
- 特定の言語にロックインされない


## 非同期処理のためのクラウドサービス

クラウドサービスを使って実装したい場合は、以下のサービスを使って実装できる

Amazon SQS / Cloud Tasks
- キューによる1:1のメッセージング

Amazon SNS / Cloud Pub/Sub
- Pub/Subによる1:Nのメッセージング

以下のような感じで実装できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491081/4cb3f09b-364f-9fd8-e57c-50bdd6617003.png)


## 補足

https://medium.com/@chaojie.xiao/domain-driven-design-practice-domain-events-15b38f3c58fc
闘魂Elixir ── Advent of code 2023 Day 8 Part 2 を Livebook で楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>

https://qiita.com/advent-calendar/2023/elixir

## はじめに

@torifukukaiou さんの ~~パク~~ リスペクト記事です

https://qiita.com/torifukukaiou/items/5361b81407b15e7c2f00

Elixir Livebook で Advent of Code 2023 の問題を解いてみます

https://adventofcode.com/2023

実装したノートブックはこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/aoc/2023/2023_day8_part2.livemd

問題はこちら

https://adventofcode.com/2023/day/8

Part 1 はこちら

https://qiita.com/RyoWakabayashi/items/18d5c8f374d48c22b243

## セットアップ

Kino AOC をインストールします

```elixir
Mix.install([
  {:kino_aoc, "~> 0.1.5"}
])
```

Kino AOC の使い方はこちらを参照

https://qiita.com/RyoWakabayashi/items/3d3abcf9134cee4dff05

## 入力の取得

Day 8 の入力を取得します

![スクリーンショット 2023-12-27 1.13.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/d4778371-3c46-e5a3-33da-1e4fb95c9300.png)

## 私の答え

私の答えです。
折りたたんでおきます。
▶を押して開いてください。

<details><summary>details</summary>

回答用のモジュールです

入力を扱いやすい形にするための `parse` と、回答を作るための `resolve` 関数を持っています

```elixir
defmodule Resolver do
  def parse(input) do
    [instructions | maps] = String.split(input, "\n\n")

    instructions = String.codepoints(instructions)

    maps =
      maps
      |> hd()
      |> String.split("\n")
      |> Enum.into(%{}, fn line ->
        parse_map(line)
      end)

    {instructions, maps}
  end

  defp parse_map(line) do
    [current, left, right] =
      line
      |> String.replace("=", "")
      |> String.replace("(", "")
      |> String.replace(")", "")
      |> String.replace(",", "")
      |> String.split(" ", trim: true)
      |> Enum.map(&String.reverse(&1))

    {current, %{"L" => left, "R" => right}}
  end

  def resolve(instructions, maps) do
    start_points =
      maps
      |> Map.keys()
      |> Enum.filter(fn key ->
        String.starts_with?(key, "A")
      end)

    start_points
    |> Enum.reduce(1, fn start_point, acc ->
      start_point
      |> step(maps, 0, instructions, 0)
      |> lcm(acc)
    end)
  end

  defp step("Z" <> _, _, _, _, acc), do: acc
  defp step(current, maps, inst_index, instructions, acc) do
    instruction = Enum.at(instructions, inst_index)

    next = maps[current][instruction]
    next_inst_index =
      if inst_index == Enum.count(instructions) -1 do
        0
      else
        inst_index + 1
      end

    step(next, maps, next_inst_index, instructions, acc + 1)
  end

  def lcm(a, b), do: div((a * b), Integer.gcd(a, b))
end
```

`parse` は Part1 とほぼ同じですが、パターンマッチで終了（ノード名が `"Z"` で終わる）を判定するため、ノード名を反転させています

`defp step("Z" <> _, _, _, _, acc), do: acc` のように、先頭でのパターンマッチは有効です

スタート地点は反転したので `"A"` で始まるノードになります

各スタートから移動して全てが同時にゴールするまで継続するため、答えは各スタートからゴールまでの移動回数の最小公倍数になります

`Integer.gcd` で最大公約数を求めることができるため、それを利用して最小公倍数を取得します

```elixir
def lcm(a, b), do: div((a * b), Integer.gcd(a, b))
```

</details>

## まとめ

問題は非常にややこしかったのですが、結果的には Part 1 に少し手を加えるだけで解けました
Tokioでworker

# Tokioでworker

あまり深く考えなくてもいいように簡単にまとめてみようということです。<br>
例えば別のスレッドで音を鳴らしたいけど同時に別の音を鳴らしたくない。
音を鳴らす以外に座標変換を一気にスレッド立ち上げてやってもらいたい等、<br>
```async main```で```#[tokio::main(flavor="multi_thread",workier__threads=1)]```などと
してしまうと融通が利かなくなってやだなーという場合によいのではないでしょうか。

## dependenceis
```toml
tokio = { version = "1.35.0", features = ["full"] }
futures = "0.3.30"
```
tokioとfuturesを利用します。<br>
バージョンは現在使える最新を使えば基本的には大丈夫だと思います。

## 基本形

### worker利用＆処理の終了を待つ
```main.rs```
```rs
use tokio::runtime::{Builder, Runtime};
use futures::stream::[FuturesUnordered, StreamEx};

async fn myfunc(index: i32) {
  println!("start {}", index);
  tokio::time::sleep(std::time::Duration::from_millis(500)).await;
  println!("end {}", index);
}

fn main() {
  let local_runtime = Runtime::new().unwrap();
  let runtime = Builder::new_multi_thread()
    .worker_threads(4)
    .enable_all()
    .build()
    .unwrap();
  
  // workerリスト
  let mut threads = FuturesUnordered::new();
  
  // workerの起動・登録
  for i in 0..5 {
    let thread = runtime.spawn(async move {
      myfunc(i).await;
    });
    threads.push(thread);
  }
  
  // 起動した全workerの終了を待つ
  local_runtime.block_on(async {
    while let Some(_result) = threads.next().await {};
  });
  
  println!("finished all!");
}
```
まずは簡単に。<br>
runtime.spawnで処理を呼びます、runtimeを初期化する際の``worker_threads``で同時に走るworkerの数を指定できます。<br>
*※mainをasyncにしていない点に注意してください。*

全てのworkerが処理を終えると```local_runtime.block_on(```を抜けてそれ以降のコードが実行されます。

## workerから値を返す

### i32を返しmainのVecに登録するパターン

ArcとMutexを利用する。
```rs
use std::sync::{Arc, Mutex};
```

myfuncが値を返すように変更 とりえず```index^2``` を返すということにしておく。
```rs
async fn myfunc(index: i32) -> i32 {
  ...
  let return_value:i32 = index * index;
  return_value
}
```

共有メモリを定義
```rs
let array_data = Arc::new(Mutex::new(Vec::new()));
```

関数をspawnする部分を修正し、値をarray_dataへ格納する。
```rs
for i in 0..10 {
  let ad = Arc::clone(&array_data);
  let thread = runtime.spawn(async move {
    let response = myfunc(i).await;
    ad.lock().unwrap().push(response);
  });
  threads.push(thread);
}
```

finished allの後に結果を表示
```rs
println!("{:?}", *array_data.lock().unwrap());
```

戻り値を利用したい場合は ```let ad = array_dat.lock().unwrap()``` などとする。

### HashMapに値を入れたい場合。

Vec利用からHashMap利用に修正する

HashMapを使えるように
```rs
use std::collections::HashMap;
```
myfuncがHashMapを返すように。 ```{n: n^2}``` という値が返るようにしている。
```rs
//async fn myfunc(index: i32) -> i32 {
async fn myfunc(index: i32) -> HashMap<i32, i32> {
  ...
  let mut result = HashMap::new();
  result.insert(index, index*index);
  result
}
```

共有メモリを定義
```rs
//let array_data = Arc::new(Mutex::new(Vec::new()));
let aray_data = Arc::new(Mutex::new(HashMap::new()));
```

関数をspawnする部分を修正し、値をarray_dataへ格納する。
```rs
for i in 0..10 {
  let ad = Arc::clone(&array_data);
  let thread = runtime.spawn(async move {
    let response = myfunc(i).await;
    //ad.lock().unwrap().push(response);
    let mut data = ad.lock().unwrap();
    for (key, value in response {
      data.insert(key, value);
    }
  });
  threads.push(thread);
}
```

## まとめ

専門のcrateがあるし簡単にできるだろうと思って実例探したりしたらあまりジャストなものがなくて苦労したのでメモ程度に書いてみました。<br>
crateを作るまでではない、crateにはしづらいようなこういった処理パターンについてスニペット的にドキュメントを作っておくのはアリだと感じました。<br>
今後も何かあればやってみようと思います。
Prometheus 調査/まとめ

# Prometheusの概要
Prometheusは、オープンソースのシステムモニタリングおよびアラートツールであり、Cloud Native Computing Foundation（CNCF）のプロジェクトの1つです。Prometheusは、KubernetesやDockerなどのコンテナ化された環境で特に人気がありますが、他のさまざまなシステムにも適用可能です。

## 機能/詳細
1. メトリクス収集: Prometheusは、エージェントを使用してシステムやアプリケーションからさまざまなメトリクスを収集します。これには、CPU使用率、メモリ使用量、ネットワークのスループットなどが含まれます。Prometheusは、PromQLと呼ばれる柔軟なクエリ言語を使用してこれらのメトリクスを照会することもできます。

2. メトリクスの保存と処理: 収集したメトリクスは、Prometheusサーバー内の時系列データベースに保存されます。これにより、メトリクスのヒストリカルデータを保持し、さまざまなデータ処理操作を実行できます。

3. 監視ルール: Prometheusには、設定可能なアラートルールが組み込まれており、特定のイベントや条件（例：メトリクスがしきい値を超える）を監視できます。これにより、問題が発生したときにメール、Slack、PagerDutyなどの通知を送信し、迅速な対応を促すことができます。

4. グラフィカルなダッシュボード: Prometheusはさまざまなデータ可視化ツールと統合できます。特に人気があるのは、Grafanaとの統合です。Grafanaを使用すると、収集したメトリクスを豊富なグラフやチャートで表示できます。

## なぜ必要か
Prometheusは、高度にスケーラブルなシステムの状態を監視し、問題を早期に検出するための重要なツールです。以下に、Prometheusの必要性をいくつかのポイントで示します。

- プロアクティブな対応: Prometheusは、リアルタイムでメトリクスを収集し、監視ルールに基づいてアラートを生成します。これにより、問題が発生する前にそれを把握し、プロアクティブに対応できます。

- スケーラブルな監視: コンテナ化された環境やクラウドインフラストラクチャでは、システムのモニタリングが特に難しいです。Prometheusは、このようなスケーラブルな環境でシームレスに動作し、必要なメトリクスを適切に収集できます。

- パフォーマンスの最適化: Prometheusの収集したメトリクスを分析することで、システムのパフォーマンスを評価し、ボトルネックや負荷の問題を特定できます。これにより、システムの調整や最適化が可能になります。

## まとめ
Prometheusは、オープンソースのシステムモニタリングおよびアラートツールであり、多くの大規模なコンテナ化環境で使用されています。Prometheusの主な機能には、メトリクス収集、メトリクスの保存と処理、アラートルール、およびグラフィカルなダッシュボードがあります。Prometheusは、プロアクティブな対応、スケーラブルな監視、パフォーマンスの最適化など、システム運用における重要な要素をカバーしています。
ポリモーフィズムが理解できてなかったのでまとめ

ポリモーフィズムは、異なるクラス（サブクラス）が共通のインターフェース（スーパークラスで定義されたメソッド）を持ちながら、それぞれ異なる振る舞いを実装することを指す。

例として、図形というスーパークラスがあり、四角形、円といったサブクラスがある場合を考える。これらのサブクラスは、図形クラスから継承され、面積を計算するという共通のメソッドを持つが、その計算方法はクラスによって異なる。

```java
class 図形 {
    double 面積を計算する() {
        return 0;
    }
}

class 四角形 extends 図形 {
    double 幅;
    double 高さ;

    四角形(double 幅, double 高さ) {
        this.幅 = 幅;
        this.高さ = 高さ;
    }

    @Override
    double 面積を計算する() {
        return 幅 * 高さ;
    }
}

class 円 extends 図形 {
    double 半径;

    円(double 半径) {
        this.半径 = 半径;
    }

    @Override
    double 面積を計算する() {
        return 半径 * 半径 * Math.PI;
    }
}
```
この例では、四角形と円は、それぞれ異なるフィールド（幅、高さ、半径）を持ち、面積を計算するメソッドをオーバーライドして独自の計算を行う。しかし、どちらのクラスも図形クラスのサブクラスであるため、図形型の変数として扱うことができる。

```java
図形(型) ある図形;

ある図形 = new 四角形(10, 5);
System.out.println("四角形の面積: " + ある図形.面積を計算する());

ある図形 = new 円(7);
System.out.println("円の面積: " + ある図形.面積を計算する());
```
このように、ポリモーフィズムを使用することで、異なる型のオブジェクトを同一のインターフェース（この場合は面積を計算するメソッド）を通じて操作することができる。
ログオン・起動スクリプト

### 環境
WindowsServer2019
Windows10
ドメインの機能レベル Windows Server 2016


# スクリプトの設定

```php:test.bat

echo "test"

set logdate=%userprofile%\desktop\date.log

echo %date% %time% >> %logdate%

@rem pause
pause
```

WindowsServerの下記フォルダにbatファイルを配置する
`C:\Windows\SYSVOL\sysvol\DCのドメイン名\Policies\GPOのID\User\Scripts\Logon`
`C:\Windows\SYSVOL\sysvol\DCのドメイン名\Policies\GPOのID\User\Scripts\Logout`
スタートアップ/シャットダウン時に起動したいスクリプトもCドライブ下に配置する。

グループポリシーオブジェクト配下から適当なGPOを右クリック→「編集」でグループポリシー管理エディターを開く。
スタートアップ/シャットダウン時にスクリプトを起動させる場合は赤のスクリプト、ログオン/ログアウト時は青のスクリプトに設定する。
<img width="500" alt="スクリプト１.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/ccbc0b33-bbb8-a7f5-4ca0-64a0fd81e2a4.png">


ユーザーに対してスクリプトを設定する場合（ユーザーの構成）は、【グループポリシーの管理】の設定したポリシーに紐づいているOUと【Active Directoryユーザーとコンピューター】で先程と同じOUにユーザーオブジェクトを紐づける必要がある。（ログオンスクリプト）
Clientマシンに対してスクリプトを設定（コンピューターの構成）する場合は、【グループポリシーの管理】の設定したポリシーに紐づいているOUと【Active Directoryユーザーとコンピューター】の同じOUに紐づいているのがコンピューターオブジェクトでないと動作しないから注意。(スタートアップスクリプト)
<img width="500" alt="スクリプト２.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/95c1900d-e606-1304-2dd6-3b0609929c04.png">


ログオンかログオフをクリック→【ログオンのプロパティ】が開かれるので、「追加」クリック→【スクリプトの追加】で参照をクリック→batファイルを選択して「開く」をクリックするとプロパティ画面に戻るので「適用」をクリック。
<img width="500" alt="スクリプト３.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/555f82f2-ae25-6558-978e-2fa189196600.png">


ログオンスクリプトを設定した場合、
「コンピューターの構成」→「管理用テンプレート」→「システム」→「スクリプト」→「ログオンスクリプトを同期的に実行する」をクリック。「有効」にチェックして「適用」→「OK」クリック。
<img width="500" alt="スクリプト４.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/9e1997b6-56c9-f8d3-6470-6bf40535ec13.png">
<img width="500" alt="" src="">


## 更新後の確認
スタートアップスクリプトで設定した場合はgpresult /zで確認出来るが、ログオンスクリプトで設定した場合だと確認の仕方が不明。
以下の出力はコンピューターの構成に設定したスクリプトが適用されているかを確認している。
```php:C:\Windows\system32>gpresult /z
    コンピューターのポリシーの結果セット
    -------------------------------------

        ソフトウェア インストール
        -------------------------
            N/A

        スタートアップ スクリプト
        -------------------------
            GPO: test2
                名前:         test.bat
                パラメーター:
                最終実行:     このスクリプトはまだ実行されていません。

        シャットダウン スクリプト
        -------------------------
            GPO: test2
                名前:         test.bat
                パラメーター:
                最終実行:     このスクリプトはまだ実行されていません。
```


## ログオンスクリプトが動作しない
以下を参照。
windows10では高速ログオンの設定を変更するにはドメインユーザー側の管理者権限でgpeditを開く必要がある。
WaitForNetwork、GpNetworkStartTimeoutPolicyValue もドメインユーザー側のregeditを管理者権限で開き、設定を追加。
低速リンクの検出の無効化はDC側で設定可能。

https://pkiwithadcs.com/not_executing_logon_script/


## 挙動確認
ログオン・ログアウトするたびにタイムスタンプが記録されていることが確認出来る。
<img width="500" alt="スクリプト5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/60a8738d-40b1-5e8e-b43d-fafa9844a0c2.png">
vpsで起動したjupyter notebookをローカルマシンから使う（さくらvps,ubuntu20.04）



vpsで起動したjupyter notebookをローカルマシンから使えるようにします。
サーバーのOSインストールからの手順を説明しています。

# 前提条件
・さくらvps（メモリ1Gプラン）
・ubuntu20.04（サーバーOS）
・Mac OS Mojave（ローカルマシン）

# OSインストール

VPSコントロールパネルからOSインストールします。設定は以下のとおりです。

・OS ubuntu20.04 amd6
・「パケットフィルターを利用しない」

（参考）

https://knowledge.sakura.ad.jp/8218/


# サーバーマシンの初期設定

サーバーにsshでログインします。「xxx.xxx.xxx.xxx」はvpsのipアドレスです。


```sh
$ ssh ubuntu@xxx.xxx.xxx.xxx
```

一般ユーザーを作成します。


```sh
$ adduser test_user
```

作成した一般ユーザーにsudo権限付与します。

```sh 
$ sudo gpasswd -a test_user sudo
```

test_userにログインしておきます。
（以下、この一般ユーザーで作業します。）

```sh 
$ sh - test_user
````


# python(Anaconda)とJupyterのインストール

pythonおよびjupyterのインストールを行います。

ここでは、Anacondaで環境構築します。

まずは、イントーラをダウンロードします。

```sh 
$ wget https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-x86_64.sh
```

上記のURLはバージョンの変更により変わるので、公式サイトで確認してください。

>https://www.anaconda.com/download
>64-Bit (x86) Installer (1015.6 MB)

インストーラを実行します。ファイル名はバージョンにより適宜変更してください。

```sh 
$ bash Anaconda3-2023.09-0-Linux-x86_64.sh
```

規約を読まされるので、

>Last updated February 25, 2022

等が出た直後あたりで、

>Do you accept the license terms? [yes|no]

ときかれるのでyesを入力する。prefixはデフォルトでOK。



Anacondaのインストールが終わったら、test_userに再ログインすると、
condaコマンドが利用可能になります。

環境を作成します。ここでは、python3.6をpy36という名前で作成します。

```sh 
$ conda create -n py36 python=3.6
```

作成した環境をアクティベートします。

```sh
$ conda activate py36
```

jupyterのインストールします。

```sh
$ conda install jupyter
```

<<<秘密鍵・サーバー証明書の作成>>>

https通信を行うため、秘密鍵とサーバー証明書の作成を行います。
まず、Anaconda環境にopensslが入っていることを確認。

```sh 
$ which openssl
```

>/home/test_user/anaconda3/envs/py36/bin/openssl

以下のコマンドを実行します。

```sh
$ cd /home/test_user/.jupyter
$ openssl genrsa 2048 > server.key
$ openssl req -new -key server.key > server.csr
$ openssl x509 -req -days 3650 -signkey server.key < server.csr > server.crt
```

実行後には、`/home/test_user/.jupyter`に`server.key`,`server.csr`,`server.crt`が生成されていることを確認してください。
詳しくは、以下のサイトも参考にしてください。

https://weblabo.oscasierra.net/openssl-gencert-1/

<<<秘密鍵・サーバー証明書の作成（おわり）>>>



さて、jupyterの設定ファイルのデフォルトをつくります。

```sh 
$ jupyter notebook --generate-config
```


>Writing default config to: /home/test_user/.jupyter/jupyter_notebook_config.py


設定ファイルを編集するため、viで開きます。

```sh 
$ vi ~/.jupyter/jupyter_notebook_config.py
```

編集内容は以下のとおりです。
（コメントアウトされている行を有効化してください。）

```
c.NotebookApp.ip = '0.0.0.0'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8888
c.NotebookApp.certfile = '/home/test_user/.jupyter/server.crt'
c.NotebookApp.keyfile  = '/home/test_user/.jupyter/server.key'
```

jupyter notebookのパスワードを設定します。ローカルマシンからjupyter notebookにアクセスする際に入力するものになります。

```sh 
$ jupyter notebook password 
```

jupyterを起動します。単に、

```sh 
$ jupyter notebook
```

としてもよいですが、nohupで起動しっぱなしにしておきましょう。こうしておけば、 sshをexitしてもOKです。

```
$ nohup jupyter notebook >> jupyter.log 2>&1 &
```


ここまでで、サーバー側の準備は完了です。ローカルマシンでブラウザを開き、

`https://xxx.xxx.xxx.xxx:8888/`

にアクセスします。

# 参考サイト

以下のサイト様を参考にさせていただきました。

https://chalow.net/2020-03-31-1.html

https://weblabo.oscasierra.net/openssl-gencert-1/
【React】childrenの数を数える方法

以下のように`Children.count()`を使用することで`children`の要素の数を数えることができます。

```jsx
import { Children } from 'react';

function RowList({ children }) {
  return (
    <>
      <h1>Total rows: {Children.count(children)}</h1>
      ...
    </>
  );
}
```
DataikuでSignateに投稿するCSVファイルを出力する方法


# モデルをデプロイし、Scoreで予測結果がでました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550964/232153e3-1f80-3a44-072a-1c817dfddc65.png)


# Signateへ投稿できるCSVフォーマットを出力します。

## 1.Prepareレシピで不必要な列を削除します。 

①右上の『COLUMNS』をクリック
②削除する列にチェックを入れる
③左上の『ACTION』→『DELETE』
④左下の『RUN』をクリックし処理を実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550964/d2fb662f-ee9f-c607-9fdf-0cc7ee99b02b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550964/58a95474-c2ff-af12-acf6-062aa637a7df.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550964/3865f330-5548-1bb4-200e-2f4e629637c4.png)


## 2.データをExportする
①出力するデータをクリック
②右上のメニューから『Export』をクリック
③With headerのチェックを外して『DOWNLOAD』をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550964/e1322d52-64e6-8444-b681-df9042548b4e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550964/2fd27df1-fbd8-7b99-c8a5-99c00a5569f7.png)


これでヘッダーなしでCSVがダウンロードできました。こちらのファイルをSIGNATEのページから投稿してください。メモ欄に『Dataiku』と入力するのを忘れず！　Good Luck!
アウトプットの重要性と多様性

# はじめに
「こんにーちわー！！」

最近錦鯉をYoutubeで見てからか、この声が頭の中でエンドレスしてます。ちびまろです。
最近奥歯インプラントのために何百万かけたらしいです。

...っとそんな話は置いといて、今回は<font color="red">**「みんなもっとアウトプットしよー！」**</font>という話です！

ちびまろは去年まで「私なんかがアウトプットしても...」という後ろ向きな気持ちを持っていました。
誰の役に立つのか。こんな基本なこと皆知ってるよな。とか。正直、**めっっっちゃ後悔してます。**

そこでマインドセットほど大したことではありませんが、「もっとハードルを下げてもいいんだよ。」と言うことや、
私がアウトプットするようになった経緯などを伝えられたらいいなと思ってます！

もしかしたら私だけでなく、トレンドにランクインするような方々も最初は同じことを思っていたかもしれませんね😉

# アウトプットする時はハードルを低くしていいんやで
もうみなさん耳にタコができるくらい色々なサイトや記事などで<font color="red">「インプットよりアウトプットが大事」</font>という言葉を見たり聞いたことがあるかと思います。

きっとアウトプットしていない人はまだ実感が湧かなかったり、気付いていても中々できない...という感じかなと私なりに考えてまとまりました。

そこで少しでもハードルを下げるアウトプットの方法を私自身のアウトプットも兼ねて紹介します！

## あくまで「自分のためやで！！！」というメンタル
最初から完璧に書ける人はいません！私もそうです！間違った情報を載せてしまうことがあるかもしれません。

もちろん間違いがないようにしたいですが、プログラミングを始めた頃はそうもいきません。

意外とどこかで間違えていたりします(笑)
この記事も一旦書き終えた後5〜6回は自分で読み直して修正しながら書いています(笑)

書いている途中でも、ふと思い出した時にでも良いので、是非定期的に書いた記事を見返してください。
「あれ、この日本語変だな」「この文章だともう少し上手く伝わりそう」などと
フィードバックすることでどんどんスキルが蓄積されていきます。

後々自分で見返した時に、「あ！ここ間違えてるじゃん！」や、「いやいや、こっちの方がいいでしょ！」となった時に編集して、取り消し線引いて、追記したらいいんです！

これらは私が以前書いた記事です


https://qiita.com/Chibimaro/items/91a2e2e021675736084b


既に4回くらい編集をしています(笑)
本当はアップする前に確認したほうが良かったんですが...そこは何も言わないでください...(笑)


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431046/7d8721c0-d610-45b1-81ae-a79bacfdf27b.png">

それに間違いやもっと良い表現が思いついた場合、あなたが成長したってことです😁

という感じで、最初はハードルを下げましょう！
⇩のように、自分でコーディングした時のバグの内容やそれを解決した方法を載せるのもおすすめです！（参考にしたサイトなどのリンクも忘れずにね〜）

```plain
# 問題
 - xxxoxoxxxxoxxxx

# 解決策
 - ooxxxxxoxoxoxo

# 参考サイト
 - [リンク１]()
 - [リンク２]()
```

# 最後に
初心者の方々へ向けた記事ですのですぐ読める短めの記事にしてみました！
私自身のハードルも下げます(笑)
アウトプットは少しずつできるようになりましたが、長くなってしまうと集中力が持ちません(笑)

まぁこれからもっともっと書いていくことで、~~恐らく~~アウトプットが好きになっていくかなと考えているのでその未来に期待します！！

ちびまろがんばれーーーー！

はい(笑) 最後まで読んでいただきありがとうございました！
なでしこのアドベントカレンダー2023最終日

# はじめに
なでしこのアドベントカレンダー2023最終日が昨日ついに到来しました！１日遅れですみません、メリークリスマス！:tada::santa_tone2:

https://qiita.com/advent-calendar/2023/nadesiko

この記事はなでしこアドベントカレンダー2023の記事としたいところですが、カレンダーはすべてうまっておりますので、ふとっぱらのMindカレンダー2023シリーズ2にまだ空きがありますので、その他の日本語プログラミング言語ユーザーの方もどうぞという呼びかけを拡大解釈して、登録させていただきました。

# なでしことの関わりの１年を振り返る

今年の夏くらいからQiitaに参加した以上はMindとRe:Mindのアドベントカレンダーぜったいやろうと考えていたのですが、11月1日から開設できるということはぜんぜん知らなくて、ブラウザ版のQiitaもヘッダに出現しているの気づかなくて、たまたま11月2日にスマホ版のQiitaアプリを入れたらなんかの表紙にどば～んとアドベントカレンダーのクリスマスレッドのタイトルが出現して気づいたのでした。

そして、カレンダーのカテゴリのプログラミング言語をみていると、なんと @snowdrop89さんがもうなでしこのカレンダー開設されているではないですか！

しかもカレンダーのご案内内容が秀逸で、とてもにぎやかでたのしげな感じにたいへん感銘をうけました。たぶんすぐになでしこカレンダーには参加予約させていただいたと思います。

Mindはちょっと調整確認の後と考えておりましたので、すぐにRe:Mindのアドベントカレンダーを開設させていただきました。はっきりいってかなり@snowdrop89さんバージョンのぱくりです。ごめんなさい。すみません。だって、にぎやかそうなんだもんと。

Mindのを開設する際は今年年末は実質40周年の1年前なので、プレイヤーと勘違いしていまして、より@snowdrop89さんバージョン的なかざりつけとさせていたいております。

すみません、カレンダー開設の話ばかりになってしまいました。実はなでしこ書いたのは今年初めてでした。これがうわさに聞く知名度No.1の日本語プログラミング言語かいとたいへん緊張いたしました。

いろいろリサーチすると、なでしこ3ってもしかしてトランスコンパイラ？とか、みょうな親近感をもったりしたり。

今年のアドベントカレンダーでは記事にできませんでしたが、わたしが注目しているのは、未完の大器なでしこ2です！来年は絶対記事にします！

# スペシャルサンクス
@snowdrop89さん、てなわけでたいへんありがとうございました。来年は５年目となでしこパッドに出るとよいですね。

@Osaneさん、@avaiceさん、ご縁があってなでしこカレンダーにお誘いする機会を与えられ、たいへんうれしく感じます。

# おわりに

来年も参加させていただきます。よろしくお願いいたします。
[C++] ラムダ式でハマった話

## はじめに

C++ でラムダ式を書いていたらハマったのでメモ．

単刀直入に言うと，**局所変数の参照をラムダ式のキャプチャリストに書くな** というだけ．

## 症状

C++ で書いた実行ファイルを，コマンドラインから実行した場合と，Python の [subprocess](https://docs.python.org/ja/3/library/subprocess.html) から実行した場合で結果が異なるという現象に遭遇した．

さらに，Debug ビルドと Release ビルドでも結果が異なった．

何事かと思ったら，ラムダ式に問題があった．

## 原因

ラムダ式を使用する部分で，こんなコードがあった．

```c++
std::function<int(int)> f;
if (foo) {
    int bar = /* some value */ 0;
    f = [&](int a) {
        // bar を使った処理
        return a + bar;
    };
}
```

`if` ブロックの中でローカル変数 `bar` を宣言したあと，キャプチャリストに参照 `[&]` を指定してからラムダ式内部で `bar` を使用している．

当然，`if` ブロックを抜けた後は，変数 `bar` にはアクセスできなくなるので，ラムダ式実行時に `bar` の参照が示す値は未定義となる．

変数 `bar` があった場所の値をいつ書き換えるかは OS 次第なので，Debug 時は動作していても Release ビルドすると不具合になったり，他のプロセスから実行すると結果が変わったり，というような再現性のないことになる．

警告も何も出してくれないので要注意．

## 対処法

キャプチャリストを参照ではなくコピーにするだけ．

```c++
f = [=](int a) { // [&] ではなく [=] とする
    return a + bar;
};
```

`[bar]` と書いても良いし，他の変数は参照でキャプチャしたい場合は `[&, bar]` とも書ける．`std::vector` など比較的大きいデータの場合は，なるべく参照でキャプチャしたい．

## 関連

局所変数の参照という点に関連して，よく問題になるコードがこれ．

```c
int* func() {
    int v = 0;
    return &v; // ダメ
}
```

**ローカル変数のポインタを返すな**，というもの．
こちらの方がいささか有名だが，セットで押さえておきたい．

## おわりに

C++ に慣れている人にとっては常識かもしれませんが，自戒のため記事にしました．
ラムダ式をあまり使わない人や，脳死で `[&]` を書いてしまう人は留意してください．
Visual Studio Codeで C# Dev Kitを使ってみる

# 1. はじめに
* Visual Studio Codeの拡張機能「C# Dev Kit」を使いたい
* ソリューションプロジェクトを作成して、簡単なコンソールプログラムを動かしてみたい

# 2. 開発環境
*  Visual Studio Code
* C#
* .Net 7
* C# Dev Kit (拡張機能)

# 3. 事前準備
* Visual Studio Codeから「C# Dev Kit」をインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/c4c96cc2-afe3-3533-6085-fca4077b650d.png)

# 4. .NETプロジェクトの作成
## 4.1. .NETプロジェクトを作成ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/8150f9de-8b69-3839-6640-1a7d16b6a054.png)

## 4.2. クラスライブラリを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/4ef3aa69-0fca-70de-3a2c-7f58c5fcb529.png)

## 4.3. 出力するフォルダを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/c2e2b400-bd17-40c8-a3ff-a2ffa3171aa8.png)

## 4.4. プロジェクト名を記入する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/c086d38a-77a1-0f7d-cf7b-cafdd6eb70cd.png)

## 4.5. .NET プロジェクトが作成できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/72a3432a-0939-a7d2-5bbe-2aa29a6df0ec.png)


# 5. サンプルプログラムの実行
## 5.1. ```Program.cs```を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/8a888d2b-530a-8176-a936-9cf95ca72f17.png)

## 5.2. デバッグから実行とデバッグボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/4a333705-a1fe-4a3f-1b80-fb67f13f735f.png)

## 5.3. デバッガを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/6b1e180a-7ce7-e521-ad55-71fd77294e93.png)

## 5.4. サンプルプログラムが実行できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/b4d54dcf-2525-a43b-8cf5-037f2c5e0745.png)

# 6. 参考文献

https://zenn.dev/tnagata012/articles/play-csharp-dev-kit-2e404533dd7e99

https://zenn.dev/tnagata012/articles/play-csharp-dev-kit-2e404533dd7e99