Wikibooks jawikibooks https://ja.wikibooks.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8 MediaWiki 1.44.0-wmf.3 first-letter メディア 特別 トーク 利用者 利用者・トーク Wikibooks Wikibooks・トーク ファイル ファイル・トーク MediaWiki MediaWiki・トーク テンプレート テンプレート・トーク ヘルプ ヘルプ・トーク カテゴリ カテゴリ・トーク Transwiki Transwiki‐ノート TimedText TimedText talk モジュール モジュール・トーク C言語 0 850 263751 250933 2024-11-18T09:12:56Z Ef3 694 * [[/改廃された技術|改廃された技術]] 263751 wikitext text/x-wiki <small>[[情報技術]] > [[プログラミング]] > C言語</small> == 目次 == === 入門的な内容 === * [[/開発環境|開発環境]] {{Hlist|class="hlist hlist-comma" | [[/開発環境#開発手順|開発手順]]、[[/開発環境#開発環境を整える|開発環境を整える]] }} * [[/基本的なプログラム|基本的なプログラム]] {{Hlist|class="hlist hlist-comma" | [[/基本的なプログラム#Hello, World!を実行する|Hello, World!を実行する]] }} * [[/基礎知識|基礎知識]] {{Hlist|class="hlist hlist-comma" | [[/基礎知識#記法|記法]] | [[/基礎知識#main関数|main関数]] | [[/基礎知識#データ型と変数|データ型と変数]] | [[/基礎知識#定数|定数]] | [[/基礎知識#算術演算子と代入演算子|算術演算子と代入演算子]] | [[/基礎知識#標準ライブラリ|標準ライブラリ]] }} * [[/制御文|制御文]] {{Hlist|class="hlist hlist-comma" | [[/制御文#論理型|論理型]] | [[/制御文#演算子|演算子]] | [[/制御文#選択文|選択文]] | [[/制御文#繰り返し文|繰り返し文]] | [[/制御文#分岐文|分岐文]] }} * [[/記法|記法]] {{Hlist|class="hlist hlist-comma" | [[/記法#文字集合|文字集合]] | [[/記法#字句|字句]] | [[/記法#キーワード|キーワード]] | [[/記法#文|文]] }} * [[/データ型と変数|データ型と変数]] {{Hlist|class="hlist hlist-comma" | [[/データ型と変数#データ型と変数の基本|データ型と変数の基本]] | [[/データ型と変数#ローカル変数とグローバル変数|ローカル変数とグローバル変数]] | [[/データ型と変数#記憶域クラス指定子|記憶域クラス指定子]] | [[/データ型と変数#型指定子|型指定子]] | [[/データ型と変数#型修飾子|型修飾子]] }} * [[/配列|配列]] {{Hlist|class="hlist hlist-comma" | [[/配列#配列の基本概念|配列の基本概念]] | [[/配列#配列の宣言と初期化|配列の宣言と初期化]] | [[/配列#配列の操作|配列の操作]] | [[/配列#配列の使用例|配列の使用例]] | [[/配列#多次元配列|多次元配列]] | [[/配列#配列とポインタ|配列とポインタ]] | [[/配列#文字列と文字配列|文字列と文字配列]] | [[/配列#配列の制約と注意点|配列の制約と注意点]] | [[/配列#章末問題|章末問題]] }} * [[/文字と文字列|文字と文字列]] {{Hlist|class="hlist hlist-comma" | [[/配列#文字の表現|文字の表現]] | [[/配列#文字型と文字の入出力|文字型と文字の入出力]] | [[/配列#文字列リテラル|文字列リテラル]] | [[/配列#文字列操作関数|文字列操作関数]] | [[/配列#配列と文字列|配列と文字列]] | [[/配列#文字列リテラルの格納場所|文字列リテラルの格納場所]] | [[/配列#可変長文字列の動的メモリ確保|可変長文字列の動的メモリ確保]] | [[/配列#文字定数と文字列リテラル|文字定数と文字列リテラル]] | [[/配列#ワイド文字列|ワイド文字列]] | [[/配列#char8_t, char16_t, char32_t型|char8_t, char16_t, char32_t型]] | [[/配列#char8_t型|char8_t型]] | [[/配列#文字エンコーディング|文字エンコーディング]] | [[/配列#文字列をあつかうユーザ定義関数|文字列をあつかうユーザ定義関数]] }} * [[/演算子と式|演算子と式]] {{Hlist|class="hlist hlist-comma" | [[/演算子と式#演算子と式の基本|演算子と式の基本]] | [[/演算子と式#算術演算子と代入演算子|算術演算子と代入演算子]] | [[/演算子と式#比較演算子|比較演算子]] | [[/演算子と式#論理演算子|論理演算子]] | [[/演算子と式#増分及び減分演算子|増分及び減分演算子]] | [[/演算子と式#その他の演算子|その他の演算子]] }} * [[/関数|関数]] {{Hlist|class="hlist hlist-comma" | [[/配列#はじめに|はじめに]] | [[/配列#関数の基本構造|関数の基本構造]] | [[/配列#関数の作成と呼び出し|関数の作成と呼び出し]] | [[/配列#引数と戻り値|引数と戻り値]] | [[/配列#スコープとライフタイム|スコープとライフタイム]] | [[/配列#標準ライブラリ関数|標準ライブラリ関数]] | [[/配列#再帰関数|再帰関数]] | [[/配列#関数ポインタ|関数ポインタ]] | [[/配列#実践例|実践例]] | [[/配列#演習問題|演習問題]] | [[/配列#まとめ|まとめ]] }} * [[/構造体|構造体]] {{Hlist|class="hlist hlist-comma" | [[/配列#構造体の基本|構造体の基本]] | [[/配列#構造体の使用|構造体の使用]] | [[/配列#構造体と配列|構造体と配列]] | [[/配列#ポインタと構造体|ポインタと構造体]] | [[/配列#ネストした構造体|ネストした構造体]] | [[/配列#構造体と関数|構造体と関数]] | [[/配列#構造体とファイル操作|構造体とファイル操作]] | [[/配列#高度な構造体の使用|高度な構造体の使用]] | [[/配列#練習問題と実践|練習問題と実践]] | [[/配列#附録: 構造体リファレンス|附録: 構造体リファレンス]] }} * [[/共用体|共用体]] {{Hlist|class="hlist hlist-comma" | [[/配列#共用体の基本概念|共用体の基本概念]] | [[/配列#共用体の宣言と使用|共用体の宣言と使用]] | [[/配列#共用体のメンバーの利用方法|共用体のメンバーの利用方法]] | [[/配列#共用体の初期化|共用体の初期化]] | [[/配列#共用体の応用例|共用体の応用例]] | [[/配列#共用体と列挙型(enum)との組み合わせ|共用体と列挙型(enum)との組み合わせ]] | [[/配列#共用体の注意点と使用上の考慮事項|共用体の注意点と使用上の考慮事項]] | [[/配列#共用体の実装例と演習問題|共用体の実装例と演習問題]] | [[/配列#まとめ|まとめ]] }} * [[/ポインタ|ポインタ]] {{Hlist|class="hlist hlist-comma" | [[/配列#はじめに|はじめに]] | [[/配列#ポインタの基本|ポインタの基本]] | [[/配列#ポインタと配列|ポインタと配列]] | [[/配列#ポインタと関数|ポインタと関数]] | [[/配列#ポインタの応用|ポインタの応用]] | [[/配列#ポインタの注意点|ポインタの注意点]] | [[/配列#まとめ|まとめ]] | [[/配列#練習問題|練習問題]] }} === 比較的高度な内容 === * [[/C11の変更点|'''C11'''の変更点]] * [[/C23の変更点|'''C23'''の変更点]] * [[/改廃された技術|改廃された技術]] * [[/プリプロセッシングディレクティブ|プリプロセッシングディレクティブ]] {{Hlist|class="hlist hlist-comma" | [[/プリプロセッシングディレクティブ#プリプロセッサの概要|プリプロセッサの概要]] | [[/プリプロセッシングディレクティブ#基本構文|基本構文]] | [[/プリプロセッシングディレクティブ#条件付きディレクティブ|条件付きディレクティブ]] | [[/プリプロセッシングディレクティブ#ソースファイルのインクルード|ソースファイルのインクルード]] | [[/プリプロセッシングディレクティブ#バイナリリソースの埋め込み|バイナリリソースの埋め込み]] | [[/プリプロセッシングディレクティブ#マクロの定義と置換|マクロの定義と置換]] | [[/プリプロセッシングディレクティブ#行制御|行制御]] | [[/プリプロセッシングディレクティブ#診断ディレクティブ|診断ディレクティブ]] | [[/プリプロセッシングディレクティブ#プラグマディレクティブ|プラグマディレクティブ]] | [[/プリプロセッシングディレクティブ#ヌルディレクティブ|ヌルディレクティブ]] | [[/プリプロセッシングディレクティブ#事前定義されたマクロ名|事前定義されたマクロ名]] | [[/プリプロセッシングディレクティブ#プラグマオペレーター|プラグマオペレーター]] | [[/プリプロセッシングディレクティブ#まとめと実践問題|まとめと実践問題]] }} * [[/データ型と変数の高度な話題]] (typedef,enum, const など) * [[/中級者向けの話題|中級者向けの話題]] (プログラム仮引数, inline, 再帰 など) * [[/ストレージクラス指定子|ストレージクラス指定子]] {{Hlist|class="hlist hlist-comma" | <code>auto</code> | <code>constexpr</code> | <code>extern</code> | <code>register</code> | <code>static</code> | <code>thread_local</code> | <code>typedef</code> }} * [[/定数式|定数式]] {{Hlist|class="hlist hlist-comma" | [[/定数式#整数定数式|整数定数式]] | [[/定数式#算術定数式|算術定数式]] | [[/定数式#アドレス定数|アドレス定数]] }} * [[/属性|属性]]<sup>'''C23'''</sup> 非推奨化、フォールスルー禁止、非復帰など * [[/型推論|型推論]]<sup>'''C23'''</sup> * [[/typeof演算子とtypeof_unqual演算子|typeof演算子とtypeof_unqual演算子]]<sup>'''C23'''</sup> * [[/標準ライブラリ|標準ライブラリ]] {{Hlist|class="hlist hlist-comma" | [[/標準ライブラリ/assert.h|診断機能<assert.h>]] | [[/標準ライブラリ/complex.h|複素数計算<complex.h>]]<sup>'''C99'''</sup> | [[/標準ライブラリ/ctype.h|文字操作<ctype.h>]] | [[/標準ライブラリ/errno.h|エラー<errno.h>]] | [[/標準ライブラリ/fenv.h|浮動小数点環境<fenv.h>]]<sup>'''C99'''</sup> | [[/標準ライブラリ/float.h|浮動小数点型の特性<float.h>]] | [[/標準ライブラリ/inttypes.h|整数型の書式変換<inttypes.h>]]<sup>'''C99'''</sup> | [[/標準ライブラリ/iso646.h|代替つづり<iso646.h>]]<sup>'''C95'''</sup> | [[/標準ライブラリ/limits.h|整数型の特性<limits.h>]]<ref><limits.h>は、C99では"Sizes of integer types"、JISCでは、"整数型の大きさ" でしたが、C23では"Characteristics of integer types"となったので、<float.h>の/Characteristics of floating types/浮動小数点型の特性/ にならって "整数型の特性" の訳をあてました。</ref> | [[/標準ライブラリ/locale.h|文化圏固有操作<locale.h>]] | [[/標準ライブラリ/math.h|数学<math.h>]] | [[/標準ライブラリ/setjmp.h|非局所分岐<setjmp.h>]] | [[/標準ライブラリ/signal.h|シグナル操作<signal.h>]] | [[/標準ライブラリ/stdalign.h|アライメント<stdalign.h>]]<sup>'''C11'''</sup><ref name="jtc1-sc22-wg14-n1570-7.15">{{cite book | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf | title = N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x | page=268, §7.15 ''Alignment <stdalign.h>'' | publisher = ISO/IEC}}</ref> | [[/標準ライブラリ/stdarg.h|可変個数の実引数<stdarg.h>]] | [[/標準ライブラリ/stdatomic.h|アトミック<stdatomic.h>]]<sup>'''C11'''</sup><ref name="jtc1-sc22-wg14-n1570-7.17">{{cite book | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf | title = N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x | page=273, §7.17 ''Atmics <stdatomic.h>'' | publisher = ISO/IEC}}</ref> | [[/標準ライブラリ/stdbool.h|論理型及び論理値<stdbool.h>]]<sup>'''C99'''</sup> | [[/標準ライブラリ/stdbit.h|ビット・バイトユーティリティー<stdbit.h>]]<sup>'''C23'''<ref name="jtc1-sc22-wg14-n3054-7.20">{{cite book | url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3054.pdf | title = N3054 working draft — September 3, 2022 ISO/IEC 9899:2023 (E) | page = 314,§ 7.20 ''Checked Integer Arithmetic'' | publisher = ISO/IEC | date = 2022-09-03 }}</ref></sup> | [[/標準ライブラリ/stddef.h|共通の定義<stddef.h>]] | [[/標準ライブラリ/stdckdint.h|チェック付き整数演算<stdckdint.h>]]<sup>'''C23'''<ref name="jtc1-sc22-wg14-n3054-7.18">{{cite book | url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3054.pdf | title = N3054 working draft — September 3, 2022 ISO/IEC 9899:2023 (E) | page = 305,§ 7.18 ''Bit and byte utilities'' | publisher = ISO/IEC | date = 2022-09-03 }}</ref></sup> | [[/標準ライブラリ/stdint.h|整数型<stdint.h>]]<sup>'''C99'''</sup> | [[/標準ライブラリ/stdio.h|入出力<stdio.h>]] | [[/標準ライブラリ/stdlib.h|一般ユーティリティ<stdlib.h>]] | [[/標準ライブラリ/stdnoreturn.h|_Noreturn<stdnoreturn.h>]]<sup>'''C11'''</sup><ref name="jtc1-sc22-wg14-n1570-7.23">{{cite book | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf | title = N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x | page=361, §7.23 ''_Noreturn <stdnoreturn.h>''<!-- 章タイトル『_Noreturn』はキーワードなので、項目名も [[/標準ライブラリ/_Noreturn]] としました。 --> | publisher = ISO/IEC}}</ref> | [[/標準ライブラリ/string.h|文字列操作<string.h>]] | [[/標準ライブラリ/tgmath.h|型総称数学関数<tgmath.h>]]<sup>'''C99'''</sup> | [[/標準ライブラリ/threads.h|スレッド<threads.h>]]<sup>'''C11'''</sup><ref name="jtc1-sc22-wg14-n1570-7.26">{{cite book | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf | title = N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x | page=376, §7.26 ''Threads <threads.h>'' | publisher = ISO/IEC}}</ref> | [[/標準ライブラリ/time.h|日付及び時間<time.h>]] | [[/標準ライブラリ/uchar.h|Unicodeユーティリティ<uchar.h>]]<sup>'''C11'''</sup><ref name="jtc1-sc22-wg14-n1570-7.28">{{cite book | url = http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf | title = N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x | page=398, §7.28 ''Unicode utilities <uchar.h>'' | publisher = ISO/IEC}}</ref> | [[/標準ライブラリ/wchar.h|多バイト文字及びワイド文字拡張ユーティリティ<wchar.h>]]<sup>'''C95'''</sup> | [[/標準ライブラリ/wctype.h|ワイド文字種分類及びワイド文字大文字小文字ユーティリティ<wctype.h>]]<sup>'''C95'''</sup> }} * [[/概念モデル|概念モデル]] * [[/おわりに|おわりに]] == C言語の歴史 == [[Image:Ken Thompson and Dennis Ritchie.jpg|frame|ケン・トンプソン(左)とデニス・リッチー(右)]] C言語の起源は1969年頃にさかのぼります。当時ベル研究所でUNIXの開発が進められていましたが、システムを効率的に実装するための適切なシステムプログラミング言語がありませんでした。そこで当時ベル研究所に在籍していたケン・トンプソンが、MITで開発されたBCPL言語に影響を受けて、新しい言語「B言語」を作り出しました。 1972年頃になると、デニス・リッチーがB言語をベースに「C言語」の開発を開始します。C言語ではB言語になかったデータ型の概念を導入し、構造体なども追加されました。また、ポインタと配列の関係性に特徴的な設計がなされました。当初はUNIXの開発に利用されましたが、徐々に普及が広がっていきました。 1977-78年頃には、ポインタ規則の厳格化や<code>unsigned</code>型の追加などの改良が行われ、1978年にはブライアン・カーニハンとデニス・リッチーによる「''The C Programming Language''」という書籍が出版され、C言語の事実上の権威ある解説書となりました。 1980年代に入ると、C言語の標準化の必要性が高まり、1983年にANSIによるC標準化委員会が発足しました。そして1989年に最初のANSI C標準が公開されることとなります。この標準化作業で言語仕様がさらに明確化され、<code>const</code>、<code>volatile</code>といった新しい機能も追加されました。 以降、C言語はUNIXをはじめとするOSでメインのシステムプログラミング言語として幅広く利用されただけでなく、アプリケーション開発でも広く使われるようになりました。また、[[C++]]などの後継言語の基盤ともなりました。単純でありながらも力強い表現力を持つC言語は、今日にいたるまで重要な役割を果たしてきました。 == 参考文献 == * {{cite book | url=https://www.open-std.org/jtc1/sc22/wg14/www/projects.html | title= C - Project status and milestones | publisher=ISO/IEC | date = 2024-03-05}} * {{cite book | url=https://www.open-std.org/jtc1/sc22/wg14/www/wg14_document_log.htm | title= ISO/IEC WG 14 Document Log | publisher=ISO/IEC | date = 2024-04-28 }} * {{cite book | url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf | title= C2y: ISO/IEC 9899:2024 (en) — N3220 working draft | publisher=ISO/IEC | date = 2024-02-22}} * {{cite book | url=https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf | title= C23: N3096 working draft — April 1, 2023 ISO/IEC 9899:2023 (E) | publisher=ISO/IEC | date = 2023-04-01}} * {{cite book | url=https://www.iso.org/obp/ui/#iso:std:iso-iec:9899:ed-4:v1:en | title=ISO/IEC 9899:2018(en) Information technology — Programming languages — C | publisher=[[W:国際標準化機構|ISO]]/[[W:国際電気標準会議|IEC]] | date = 2018-07-05}} ** {{cite book | url = http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf | archiveurl = https://web.archive.org/web/20181230041359/http://www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf | archivedate = 2018-12-30 | title = N2176 C17 ballot ISO/IEC 9899:2017 | publisher = [http://www.open-std.org/jtc1/sc22/wg14/www/projects ISO/IEC JTC1/SC22/WG14]}} * {{cite book | url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf | title= C11: WG14/N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x | publisher=ISO/IEC | date = 2011-04-12}} * {{cite book | url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf | title= C99: WG14/N1256 Committee Draft — Septermber 7, 2007 ISO/IEC 9899:TC3 | publisher=ISO/IEC | date = 2007-09-07}} * {{cite book | url=http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf | title= C99: ISO/IEC 9899:TC2 Committee Draft — May 6, 2005 WG14/N1124 | publisher=ISO/IEC | date = 2005-05-06}} * {{cite book | url= | title= JIS X 3010:2003『プログラム言語C』 | publisher=日本工業標準調査会<ref>当時、現:日本産業標準調査会</ref> | date = 2003-12-20}} {{---}} 1999 年に第 2 版として発行された ISO/IEC 9899:1999,(Programming languages―C) 及び Technical Corrigendum 1 (2001)について,技術的内容を変更することなく日本工業規格<ref>当時、現:日本産業規格</ref>として採用するために作成されたもの<ref>ISO/IEC 9899:1999 (IDT)</ref>。 == 脚註 == <references/> == 外部リンク == {{Wikipedia|C言語|C言語}} {{wikiversity|Topic:PG学習法C言語初級|C言語初級}} * [https://www.bell-labs.com/usr/dmr/www/chist.html The Development of the C Language*](英語) {{DEFAULTSORT:Cけんこ}} [[Category:C言語|*]] [[Category:プログラミング言語]] {{NDC|007.64}} gbkrbde3eb8axs68ihic34c6c7ofgum 経済学基礎 0 862 263738 232042 2024-11-18T03:28:22Z ~2024-14526 84963 /* 社会保障制度 */ 使用者責任が問われ、民事上の損害賠償責任が課せられることになります。 263738 wikitext text/x-wiki {{Pathnav|経済学|frame=1|small=1}} ここでは、経済学の基礎的事項について確認しながら、世界経済における経済の動向に配慮した経済学的解説に努めることにする。[[高等学校政治経済]]のテキストも参照せよ。 == 経済変容と現代社会 == 現代社会の変容は、工業化・IT化に続く。 === 経済の変容 === * [[経済学/経済とは何か|経済とは何か]] ==== 世界経済の変容 ==== * [[双子の赤字]] {{進捗|100%|2013-10-08}} * [[経済学/バブル崩壊|バブル崩壊]] * [[経済学/アジア通貨危機|アジア通貨危機]] * [[経済学/改革開放|改革開放]] * [[経済学/アジア経済|アジア経済]] * [[経済学/インド経済|インド経済]] * [[経済学/EU統合|EU統合]] ==== 日本経済の変容 ==== * [[戦後]] {{進捗|75%|2013-10-08}} * [[経済学/高度経済成長|高度経済成長]] * [[経済学/通貨危機|通貨危機]] * [[経済学/石油危機|石油危機]] * [[経済学/プラザ合意|プラザ合意]] * [[経済学/失われた10年|失われた10年]] * [[経済学/情報化社会|情報化社会]] * [[経済学/産業の空洞化|産業の空洞化]] == 現代経済の仕組み == === 世界経済 === * [[経済学/資本主義経済|資本主義経済]] * [[経済学/社会主義経済|社会主義経済]] * [[経済学/経済システム|経済システム]] * [[経済学/グローバル化経済|グローバル化経済]] === 経済学 === * [[経済主体とその活動]]:経済主体が相互作用の中で貨幣を廻している。{{進捗|75%|2013-10-08}} * [[経済学/金融機関|金融機関]]:銀行は何をする? 銀行のストックが減ると世に貨幣が増える。 * [[経済学/財政|財政]]:税金は何に使おう? 払いたくない^^;;;? * [[経済学/国民生活|国民生活]]:人間の行為は大抵生産、それをお金に換えたら経済になる。 * [[経済学/国民所得|国民所得]] * [[国民経済生産]]:GDPの値は国家の生産を示しているはず。{{進捗|100%|2013-10-08}} == 社会保障制度 == 年金や健康保険から公衆便所まで。 * [[経済学/過労死|過労死]]:使用者責任が問われ、民事上の損害賠償責任が課せられることになります。 * [[経済学/福祉国家|福祉国家]]:福祉は必要だよね? しかし昔の方がやはり不備は多かったか…最も今でも… * [[経済学/社会保険年金制度|社会保険年金制度]]:年金制度は必要だが、経済的に破綻しないように運営するのはかなり困難。 == 世界経済 == 日本経済の国際化による日本と海外の国々との関係とこれからの課題について学習しましょう。 * [[経済学/貿易|貿易]]:貿易はやはりバランスが大事か? * [[経済学/国際収支|国際収支]]:貿易で赤字になった国があるの? * [[経済学/為替|為替]]:1ドル=1円じゃ駄目? === 世界経済の変容と発展 === * [[経済学/国際経済体制|国際経済体制]]:IMFとかGATTとかって? ==== 世界経済の発展 ==== * [[経済学/多国籍企業|多国籍企業]]:ウォルマートとかエンロンとかトヨタとか・・・ * [[経済学/ユーロ|ユーロ]]:ユーロだけじゃない? * [[経済学/サブプライムローン問題|サブプライムローン問題]]:アメリカ経済を気にするのはなぜ? * [[経済学/国際協力|国際協力]]:アフリカ、ラテンアメリカ、南アジア、中東その他の国の状況は? == 環境問題 == 自然環境問題を経済で解決できるでしょうか。 * [[経済学/都市と環境|都市と環境]]:ごみ問題、大気汚染、水質汚濁、渇水、オゾン層の破壊、こうした問題を私たちは解決できるのでしょうか。 * [[経済学/持続可能な発展|持続可能な発展]]:「宇宙船地球号」 * [[経済学/生態系と環境|生態系と環境]]:生態系を守ることこそ、私たちの未来に必要です。 {{stub}} == 未分類 == ===資源の希少性=== 原則としては、資源とは有限のものでしょう。むしろ無限と考える方が不自然だし、実際にはだれも考えていない。 しかし例えば再生可能エネルギー、太陽光なんかはほぼ無限と見なしていますよね。しかしシビアに考察すると、やはりそれも有限。 例えば水なんかはどうでしょうか。これは地球上を循環しているもので、現実的には無限とみていますが、やはり手に入りにくい地域はありますし、シビアに考えると有限ですよね。 クルーグマンやスティグリッツやマンキューなど、多くの経済学者も、彼らの教科書で、資源の希少性が経済学の前提であると説明している。(なお、日本の高校の「公共」教科書でも、たとえば帝国書院(教科書会社のひとつ)の検定教科書で、「資源の希少性」を紹介している。) なお、経済学・商学などで「希少性」は英語で scarcity である<ref>『ビジネス基礎』、実教出版、令和2年12月25日検定、令和4年1月25日発行、P61</ref>。 また、人々が望んだからと言って、それを生産できるとは、かぎらないと、マンキューは説明している。 たとえば医薬品として、エイズの完全治療薬を望んでも、それは現状の医学では生産不可能。 数百年前の時代を上げれば、たとえば結核や らい病 の治療薬のなかった時代もあった。この話も、誰もがあっさりと納得、あるいはいまさら言うなという感じでしょう。 また、資源を超えた量の生産も不可能。 この「資源の希少性」は、よく経済学の教科書で、「経済学の原理」のひとつとして挙げられている。 ===法則? 原理?=== 需要と供給の法則、なんて経済学では出てくるでしょうが、そもそも「法則」law とは、なんでしょうかね? 例えば、「現在でも、よくある傾向」、だという指摘もある。ある程度の多くの国で、ある程度の長期や複数回にわたって、よく発生する現象で、今でもよくある現象の事、要するに緩やかな決まりで、法則に当てはまらない例外もある。 たとえば、「需要と供給の法則」の例外のひとつとして「メニューコスト」という概念もあり、生産者側の価格改定には費用が掛かるので価格改定が後回しにされやすい、と。 つまり、どちらかというと法則どおりの現象のほうが遭遇しやすいだろうという、多数の経済学者の信念がある。 その国の言語の違いという問題もある。英語の law 、法律も法則も英語では law です。 例えば物理学では「法則」はかなり厳密な決まりで、基本的に例外は許さない。 しかし本当に例外はないのかという疑問は持てる。何らかの超自然的な理由で、時々は物理法則をキャンセルできるかもしれない。 自然科学の実験をしている時、気にして観察している時だけその法則が満たされるとか… 例えば量子力学には観測問題とか、不確定性原理、そして物理現象の確率的解釈というのもある。 勿論現代の物理学は、観測者自身を系に組み込んだり、確率の数学的記述を厳密化したりと、厳密な法則記述のための工夫がさまざまなされている。 例えば原理 principle なんて言葉があったり、数学では定理、公理、公準なんて言葉も使う。 経済学でいう「原理」principle とは何ですかね? 文脈や論者にもよりますが、「原理」とは普通の場合、いくつもある「法則」のうち、なかでも基本となる少数の法則のことです。 数学で言えば公理や公準に近いものですかね。 「資源の希少性」の原理と、「需要と供給の法則」なんて言いますが、むしろ「資源の希少性」は法則というよりは、前提事実と言ったところでしょうか。 「原理」と「原則」はともに英語では principle、根源的な法則、事実を示すものでしょう。 法則の厳密性は当然、学問分野で変わってきます。そしてそれはそれぞれの学問者の、感覚や経験などで、誰もが知って身に着けている事でしょう。 == 合成の誤謬 == 合成の誤謬とは、個人や個々の企業にとっては合理的な行為でも、社会全体としては、不合理で意図しない結果に至ることですね。 例えば企業が経営の健全化を目指して、人件費を削減する。すると個人の収入は減るから、個人消費は減る。景気は低迷し、企業の売り上げも減る。 家庭の節約はどうでしょうか。 個人消費は減るし、節約対象の商品は売れなくなる。景気は悪くなるし、消費されないから生産もしない。 個人スケールで見た場合の合理的な行動と、国家規模の全体的な規模で考えた場合の合理的な行動は異なる。 しかし国家規模の合理的な行動とは何でしょうか? 先ず、国家という集団の化け物の実在性を認めるか? それとも国家とは何らかの方便なのだろうか? おそらく国家規模の合理的な行動とは、その構成員である国民の幸せに結びつくものでしょう。 限界消費性向を低下させる(つまり限界貯蓄性向を高める)ことは、GDPの低下をまねく可能性がある<ref>滝川好夫『図解雑学 ケインズ経済学』、ナツメ社、2010年11月21日初版発行、P180、</ref>。つまり国家全体の生産が低くなるわけですが、生産とは仕事をすることそのものでしょう。仕事をすればするほど幸せという訳ではない。 GDPはとりあえず上昇させたいという固定観念はあるが、これ自体どこまで妥当か。 国際競争を考えると、国家の経済力は必要だが、GDPを上げることを盲目的に目指す以外に、国家の安寧を満たす方法はないのか。 == 誰かの支出は誰かの収入 == 誰かが貨幣を支払ったら、それは他の誰かの収入になっているでしょう。 それは一国の通貨だけではなく、各国、世界全体でその関係が成り立つ。 我々がアメリカ人から貿易として何かを買いたい場合、先ず、円で払うか、ドルで払うかが問題になりますよね。相手が円の受け取りを拒否するなら、自分が外貨を持っていないなら、両替商に円をドルに換えてもらうことになる。 そうすると自分が払った円は両替商の収入になる。そして我々はアメリカ人から商品を受け取る。アメリカ人はドルで収入を得るが、それは両替商が支払ったお金。両替商は商売として貨幣の交換をしているわけだから、払ったドルより受け取った円の方が価値が高いものになっているでしょう。 複数、多数の主体があって、それぞれが一定の数値を持っている。そしてその数値をお互いにやり取りできるなら、その数値の総体、総数は保存されるでしょう。一番の典型例は、物理学のエネルギー保存則。 しかし現実には貨幣の総量が一定である保証はない。 変わり者がお札を燃やしたら、総量は減りますよね。一方政府がお札を印刷して、その分を回収することなく放逸に使ったら、その国の貨幣の総量は増えていく。 ==会計学から考えてみる== ===経理の初歩=== 幾つか、費用に関する用語を説明します。 *人件費 会社、法人が雇用者、労働者に支払う給料は、人件費ですね。従業員のために支払われる費用です。 *固定費 固定費というのは、企業の生産量や売り上げの増減とは関係なく発生する、一定の費用の事です。地代、減価償却費、固定資産税、などですね。債券の利子も会計分野では固定費に含めるという。 *変動費 反対語は変動費ですね。変動費用。生産量や売り上げによって増減する費用。原材料費、外注費、運賃、など。 人件費は固定費か変動費か? 会計に詳しいらしい前編集者も言及を避けているので、たいして詳しくない現編集者ももちろん知りません。 *減価償却費 事業用の建物、機械設備、備品などの取得費用ですが、会計上は普通耐用年数によって、徐々に費用として計上します。つまり購入したときにお金は払ったとしても、会計上毎年その費用を分けて少しづつ計上する。 逆に少しずつお金を計上して費用にした結果、耐用年数が来ますので、費用が完全に計上された時点でその設備の価値は0円になると見ていい。つまり備品の資産価値が減っていく、その部分の支払いをしたと会計上見なすわけです。 減価償却の基準は(つまり購入費を毎年どう計上するか)省令や法律や業界の制度などによって、あらかじめ決まっているので、経理の際には、その制度に従って経理処理する。 ===国民経済計算=== 国民経済計算の指標として知られるGDP(国内総生産)やGNP(国民総生産)から、その国の資産の減価償却の金額を差し引いた金額のことをネットDPまたはネットNPといい、それぞれNDP(国内純生産)またはNNP(国民純生産)と略記します。 つまり、 :NDP = GDP - 減価償却費 :NNP = GNP - 減価償却費 です。 Net domestic product. 正味の、純粋な国内の生産。net はフランス語由来の形容詞で cleanを意味し、「網」を意味する同じ綴りで古英語由来の net とは別系統の英語のようです。 国内総生産は、国内の事業者の売り上げから、原材料費(中間財・サービス)の支出を引いた物を積算したもので、国の生産、事業や労働で生み出した付加価値を示していると考えています。 一方減価償却費は、その間に建物、車両、産業機械が劣化し、それを現状に戻すための価格を示していて、生産分からその分消費、減耗しているともみなせるので、NDP は国内の生産の状態を知るための別の指標として提示されています。 GDP やGNP の頭文字G はグロスの略で、Gross は、会計でいう粗利(あらり)を示す形容詞です。会計学でいう「粗利」とは、売上高から売上原価(その商品をつくるために掛かった費用)を差し引いたものです。 人件費は引かず、支払う税金も引かず、原価(原材料)だけ売上高から引き算する。それが粗利(あらり)です。 粗利を英語で gross profit と言います。 profit とは「利益」「利潤」という意味です。 つまり仕事をして生産した分だけ利益になると見ていいと思います。 GDPの算出式は、 :GDP = 家計による支出+企業による支出+政府支出+(輸出-輸入) :GDP = C + I + G + (X − M) 、[[w:en:Gross domestic product]]、[[w:国内総生産]]、などを参照してみてください。 C とG とI は最終財・サービスに対して行われた支出を数えます。事業者が行った生産の積算は、最終的には最終財・サービスに対する支出になります。 家計はほぼすべて、最終財・サービスに対して支出しているでしょう。 企業は、中間財・サービスに支出してそれをもとに生産し、一方で最終財・サービスを購入することもあるでしょう。 中間財にしろ最終財にしろ、輸出したものは国内の支出には含まれませんね。 C + I + G + X に含まれる中間財、最終財(最終財はそれまでの中間財の生産価値を含んでいる)のうち、輸入したものは国内の生産には含まないでしょう。 GDPの計算基準は国際連合が決めたものがあり、定期的に改訂される。[[w:2008SNA]]等の記事も参照してみて下さい。 C + I + G + X と M が同額なら、事実上 GDPはゼロだが、この場合は輸入したものをすべて消費し、さらに輸入したものをそのまま輸出していることになるから、矛盾ではない。 なんらかの生産行為が行われているなら、事実上GDP がゼロになる事は無いだろう。 しかし、経済分析として、前編集者の指摘が完全に無意味だという訳ではない。 分析の精密さのためには貸借対照表のように複式簿記的に扱うべきであるという意見はある。 家計による国内消費額の総計、企業支出の総計、政府支出額の総計、輸出額の総計、輸入額の総計、といった金額をそれぞれ個別に計測して、それらの金額を比較することにより、複式簿記的に分析することにも意義はあるだろう。 前編集者の指摘として、経済分析において、 :産業関連表、 :資金循環表、 :国民貸借対照表、 :国際収支表、 などの統計表を、経済系の省庁は作成する事が望ましい、という(※ 参考サイト [http://www.keikyo-center.or.jp/old/tool/pdf/sna.pdf 国民経済計算の見方、使い方] 財団法人 日本経済教育センター)。 GPD と産業関連表を関連付ける、複式簿記にたとえて議論する、などの発想は、各種書籍にも記述されているという<ref>塩澤修平『経済学・入門』、有斐閣、2021年、4月30日 第3版 第5刷 発行、P202、P258</ref>。 ===確定申告、減価償却、国民純生産=== 国民純生産を計算するためには企業の減価償却の金額の情報が必要でしょう。この金額において、経済全体で固定資本の減耗分は測定しづらい、正しく推定できないという主張もあります。 企業も確定申告するので、自社の減価償却費もその時点で税務署に申告します。 減価償却費に応じた税金の控除もあります。建物、車両、産業機械は必要経費ですからね。 減価償却の計算のルールは、日本の国税庁などの省令や、または経理業界などの制度によって、厳密に定められています。 税に関する申請は虚偽があると罰せられるので、その意味では、企業の減価償却費のデータはおおむね正確だろうと考えられます。 なお、個人でも企業でも確定申告は2種類ある。 :比較的に簡単に計算できるが(税の)控除の特典の少ない「白色申告」 :事前の申し出が必要でさらに計算方法も厳密で難しいが控除の特典が多く、多くの場合納税額が少なくなる「青色申告」 多くの企業が基本青色申告を利用している。 ===フローとストック=== フロー(英: Flow)とは、一定期間内に流れた量をいい、ストック(英: Stock)とは、ある一時点において貯蔵されている量をいう。以上Wikipediaから引用。 ある関数がある時、その微分がフロー、その関数を積分して元に戻すとストック、と、いう事も言えるかもしれません。ただし積分は積分定数を持つので、フローからだけではストックを作れません。 この節では前編集者が試みた経済学を会計学と関わらせて語るという試みを、現編集者が多少修正して記述している。 簿記(ぼき、英語: bookkeeping)とは、企業などの経済主体が経済取引によりもたらされる資産・負債・純資産の増減を管理し、併せて一定期間内の収益及び費用を記録することである。再びWikipediaから引用。 普通高校では簿記の学習はない。主に資格取得としての学習だというイメージはある。 ====お金に関するフローとストック、具体例==== 例えば… Aさん:貯金が10億円あって1億円の家に住んでいるが、就職していなくて給料の収入が0円。 Bさん:貯金は1000万円で3000万円の親元の実家に住んでいる、会社勤めしていて年収が500万円。 話を簡単にするため、AさんもBさんも株投資や不動産投資はしていないとする。 経済学や経営学では、貯金や、保有する不動産や保有株式そのものの相場での購入費用などの金銭的価値などを合わせてストックとする。 いっぽう、収入や、株の配当益、不動産などを他人に貸したときの賃貸収入などの運用益はフローですね。 つまりAさんはストックが11億円で、フローは日々の支出という事になります。 Bさんは、まあ、ストックは4000万程度、日々の収入や支出がフローになる。 AさんBさんの生活、どちらがうらやましいか、意義がある生活か、豊かか、などの議論は無意味でしょう。人生いろいろ、お金も色々経済もいろいろ。 ===会計との関係=== 複式簿記などの会計の勉強をするときは、簿記では「フロー」と「ストック」という用語こそ使ってないものの、フローとストックを区別することになります。 GDP や GNP はフローについて語っていると見ていいですよね。 経済計算ではフローに関する話題の方が多いでしょうか。 例えば国家全体に関するストックを見るには、まず国家貨幣がどのくらい流通しているか、そしてその他に金銭的価値を持つものとして、土地、建物、証券、各種動産不動産、機械類や芸術品、貴金属・宝石など、価値のあるものはすべて資産としてのストックになるでしょう。 過去のある年度から現在までの各年ごとのGDPの累積額をストックとする計算法もあります。 しかしGDPとは生産その物で、生産物には資産として残るものもあるが、一方でその場で消費されるもの、無形の行為も生産の一つではある。 固定資産、建物や機械設備などの減価償却によって、ストックの資産価値は下がっていくと見れるから、ネット計算で、つまり国民純生産(NNP)の累積額で計算する方式をとる方が良いかもしれない。 ==諸概念== === 機会費用 === 経済学上の概念の一つとして、機会費用(opportunity cost<ref>『ビジネス基礎』、実教出版、令和2年12月25日検定、令和4年1月25日発行、P62</ref>)、というものがあります。 端的に解説すると、ある状況で最善の選択をした時に、残されたほかの可能性で最善の物の価値を言います。 例えば… 大学4年生が今年卒業だったはずなのに留年してしまった場合… ならばその年は普通就職して200万円くらい年収があったはずなので、これが機会費用になりますね。 つまり留年というのはそれほど最善手ではありませんが、図らずもしてしまった場合は、200万の機会費用を費やして、その状態に至ったと見る。 そして留年した場合はさらに学費もかかりますね。これは一般的には機会費用ではなく、学業のための費用になります。 しかしこれはあまりいい例ではないように思える。 前編集者の記述に基づいてこの例を書いたが、そもそも機会費用の議論というのは、経済行為のうちの収益が多い最善手を見つけ出したいがための議論だろうし、いくつかの行為の可能性を見た上で、どれが最善手か知るための議論でもあるだろう。仮に機会費用が多くかかっても、その行為に意味があると見なす場合もある。 ===パレート最適=== Pareto efficient. 他の誰かの状態を悪化させることなしに、ある主体の状態を改善できないこと。つまりその主体の現在の状態は改善できる可能性はあるのだが、それは必ず他の主体の状況の悪化が必要になるので、これ以上は改善を試みないのが正解、社会的に最適な状態とみる。 イタリアの経済学者、パレートが提唱した概念。 パレート効率と呼ぶこともある。つまり個人では最適ではないが社会的には効率の良い、いい状態だという事だろう。 パレート効率的な状態、具体的には、100人の民間人がいてある生活を続けている時、 政治家が特定の主体の状況を良くしたくて政策を変えたとして、どう政治行動しても、その100人の誰か一人以上に不利益・不満などを与えてしまう事になるのなら、経済政策を変える前のもとの状態がパレート最適、パレート効率的という事になる。 しかしパレート最適な状態にある時、それが本当に一般的な意味で最適、最高の状態であるわけではないだろう。 とりあえず状況を変えると誰かが必ず悪い状態になるのだが、Aが多少悪い状態になったとして、Bが少しでも良い状況になる方が必要、危急かもしれない。 そもそも最初の時点でAが不当に良い状態で、Bが不当に悲惨な状態かもしれない。 そしてパレート最適な状態も複数ある。この効率を得ているのは一種の平衡状態だが、最善ではない。徹底的に最善を求めた時、必ずパレート最適の複数のうち一つになるだろうか? そもそも最適な状態とは何? 誰にとって? 社会にとって? 社会とはだれのこと? そこに含めていない人はいない? 経済学者スティグリッツは、パレート効率的とは単に効率的でない状態よりは多少ましな状態に過ぎないだろうと書いている。経済学で言う「効率」とは、通常パレート効率の事だろう、という。出典、『スティグリッツ入門経済学』(和訳は東洋経済から)。 しかし最初の定義に戻ると、ある特定の主体の状態が問題になるわけだから、その特定の主体の状況を改善させる必要がどうしてもあるなら、パレート平衡を破って他の主体の状態を悪化させることになるだろう。 === 価格統制 === 経済政策の経験則として、(独占市場ではなく)競争市場における価格統制は、結果的に混乱をもたらすことが多いとされ、あまり好ましくないという。クルーグマンやスティグリッツやマンキューなど、多くの経済学者も、彼らの教科書で、それを説明している。 クルーグマンは、ベネズエラ国のチャベス政権での食料価格統制の結果として、ベネズエラ国で食糧難が実際に起きたと主張している。 価格を低く強制するなら、供給は減るだろう。 スティグリッツは、価格統制という方針は政府の市場介入としては悪手だ、という。 むしろ買い手に補助金を与えては?、という事だが…。 クルーグマンは独占市場では、価格統制も世の中に不利益を与えないという。 一方現実では、ニューヨーク、借家業界では家賃の価格統制が行われている。クルーグマンやマンキューは、この家賃の(上限)価格統制により、おそらく修繕などの費用が削減されて、低品質な住宅が供給されている、と指摘している。 価格の上限、価格統制、行政などが、超えてならない価格を設定することを英語では price ceiling といい、日本語では「価格の上限」または「上限価格」と訳す。 下限価格(price floor)規制もまた、別の問題を引き起こす。輸入品が極端に安価になると、自国の農業を助けるために価格の下限を決めるが、供給過剰になり、政府の買い上げなども起きる。 買い上げた後の廃棄なども起きるだろう。事実上売れなかったり、価格暴落を下げるため、最も下限価格はあるのだが、市場の自然な圧力は発生する。 下限価格により、自然な状態より値が高いので、過剰品質やオーバースペックなサービスの付加にもつながる、と、クルーグマンなどは説明する。 === 失業 === ====フィリップス曲線==== フィリップス曲線という理論が知られていて、インフレ率と失業率は、おおむね反比例すると主張されている。 これは、日本の1950年代~1990年代まではよく当てはまる<ref>福田慎一・照山博司『マクロ経済学・入門』、有斐閣、2016年3月30日第5版第1刷、299ページ</ref>。 しかし、第二次大戦後から2000年までのアメリカ合衆国はこれに当てはまらない<ref>福田慎一・照山博司『マクロ経済学・入門』、有斐閣、2016年3月30日第5版第1刷、302ページ</ref>。 インフレ率と失業率を加算した指標のことをミザリー指数(misery index)(ミザリーとは「悲惨な」というような意味の英語)というが、第二次大戦後のアメリカ合衆国ではこの指数は通常10%前後だが、1975年と1980年にミザリー指数が上昇して数か月~1年程度のあいだ20%近くになり、悪化した。 フィリップス曲線はもともとは、失業率と貨幣賃金上昇率に関する議論だったが、これが後に物価上昇率に関しても言われ始め、さらにT.フリードマンは、ここでは実質賃金上昇率について考えるべきだと主張し、さらに、予想物価上昇率も加えた新しいフィリップス曲線を提唱した。 ====構造的失業、摩擦失業、需要不足失業==== 構造的失業(structual unemployment)。企業が求める労働者の性質や地域、と労働者側の状況、条件が異なっているために、景気や需給関係では解消されない慢性的な失業。求人ニーズと求職者ニーズが一致せず、ミスマッチが起きている。 需要不足失業。求人が減っている、景気後退期に起きる。 摩擦的失業(frictional unemployment)。次の仕事を見つけるための過渡期、仕事自体は簡単に見つかるが、そこに就くまでに失業状態がある。 世の中の傲慢な愚か者たちの間では、失業するのは本人に何らかの問題があるから、能力や適性がないから、との考えが根強いようで、とりあえず公共の失業対策では、いい加減な講師による職業教育、訓練がなされるが、基本的には馬鹿げたことだろう。 勿論特定の職業実践に有効な、訓練や学習は確実に有意だが、現実にはそれが適切に提供されているとはいいがたい。 例えばこれはフィクションではあるが、カンヌ映画祭でパルムドールを獲得した、『[[w:わたしは、ダニエル・ブレイク]]』などを観ると、この問題の周辺でいかに馬鹿げたことが現実に起きているか良く解るだろう。 基本的に失業問題で公共がする一番の、そしてあるいはひょっとしたら唯一の重要事は、求職者と求人者の間の関係、橋渡しを上手に作る事だろう。 ;完全雇用 full employment. 現行の賃金水準で就業を希望する人、そして就業に適した状態にあるすべての人が雇用されている状態。ケインズは非自発的失業、摩擦的失業、自発的失業の3つの分類を語り、求人需要が十分で非自発的失業の無い状態を完全雇用と考える。 ;季節的失業 たとえばアメリカでは、建設業では、冬はほぼ毎年、仕事が減るのでその業界での失業者が増える。特定の季節にだけ失業者が増える業界があり、このような定期の失業のことを季節的失業という。 ====自然失業率==== natural unemployment rate. 期待インフレ率と現実のインフレ率が一致し,実質賃金による労働力需給の調整が達成されるような長期均衡状態において成立する失業率。 …というのは、ブリタニカ小項目事典からの引用だが、 この文章からだけでは、どういう事か理解するのは難しいだろう。 前編集者は実際にはあまり「自然」に見えない、と記述しているが、本来の、短期ではなく長い目で見ると行き着くであるだろう、失業率、という意味で、自然という言葉がそれほど"不自然"、な訳ではない。 基本的には多少の失業者はいるものだろう、摩擦的失業や、自発的失業、そして口では働きたい働きたいと言いつつ、実際には人間はあまり働きたくない^^;;;、何となく失業者になりたがっている^^;;;;;…。 自然失業率という概念は、主にフリードマンが提唱したらしい、フィリップス曲線からの類推から、インフレにより失業率が減らせるという主張があり、それに対する反論でもある。 20世紀後半の代表的な経済学者サムエルソンが、自然失業率を正確に測定できた者は いまだに一人もいないと、著作『経済学』で述べている<ref name="nm">根井雅弘『サムエルソン『経済学』の時代 』、中央公論新聞社、中公選書、2012年1月10日初版発行、P68</ref>。 仮に自然失業率なる概念が明確に規定できるなら、我々の社会でその値がある程度明確に時間に応じて存在すると見れるだろう。それを統計調査で測定し、明らかにしたいのだが、この測定はやはり完璧に正確にはいかない。しかしサムエルソンの主張はそれ以前の問題。概念も測定もいまだ相当あいまいだという主張だろう。 サムエルソンは2009年に死亡した。彼は自然失業率は、長期的には安定した数値ではなく、そのため、ある程度の幅を持っていたり、あるいは複数の幅を持っている<ref name="nm" />、と云う。 冷戦崩壊や日本の1990年前後の不動産バブルについてはサムエルソンの著作は言及できたものの、しかし2008年前後のリーマンショック・サブプライム危機については言及が乏しいと考えられる(※ wiki著者がまだ未確認)。 余談だが、サムエルソンの経済学教科書『経済学』は、日本では『サムエルソン経済学』などと言われるが、実際は1985年以降の版は経済学者ノードハウスとの共著である(和訳本『サムエルソン経済学』の表紙を良く見ると、原著者ノードハウスの名前も入っている)。 =====自然失業率の算出===== 景気の変動などで実際の失業率はやや周期的に波上に上限に変動するだろう。 実際の失業率を、一定期間の平均的な高さの曲線でならしたものが自然失業率である、という見方がある。 この平均曲線の失業率と、実際の失業率とのずれの分を、循環的失業(cyclical unemployment)、とも云う。 フィリップス曲線の理論と関連づけるなら、インフレが進行したときの失業率の減少は、この循環的失業の部分だとされている(とスティグリッツは言う)。また、政府の経済対策などの成功によって減少できる失業率も、この循環失業率の部分だけである(と、スティグリッツは言っている)。 しかしマンキューは、スティグリッツのような意見には反対していて、自然失業率は経済政策の影響を受けないとは限らない、と主張している。 このスティグリッツとマンキューの差異のように、自然失業率の細かい定義はあまりはっきりしていない。 ==実質という指標== 貨幣は絶対の固定された価値を持つものではない。経済の様々な指標は貨幣値で示すものだろうが、時期により貨幣の価値は変動している。だから様々な指標に貨幣の額面ではなく、物価の変動を考慮した補正を加える。 これが、実質〇〇(real 〇〇)だろう。具体的には、実質GDPや実質利子率などがある。 たとえば、実質利子率は、次のように引き算で定義される。 :実質利子率=名目の利子率-未来のインフレ率の予想値 例えば、まあ金額が少なすぎるが、例え話で銀行に100円預けたとしよう。これで、1か月後に利子が10円つくとする。これで名目利子率は、10% 。そして一か月後に10%のインフレになると予想されていると、実質利子率は0%だよね。これはどういうことだろう? 仮に予想通り、一か月後に10%のインフレ、物価高になったら、100円で買えたものには110円払わなければいけなくなる。名目利子率が10%なら、戻ってくるお金は110円だろう。つまり実質の利子は0%、預けたお金と同じ価値の貨幣が、銀行から返ってくる。 そして、もしこのインフレ状態で銀行に預けず、その資金を投資にも回さなければ、持っている100円の価値は100/110に下がっているだろう。 だからもし実質利子率がマイナスになっても、インフレで貨幣の価値は下がるが、事実上利子はつくのだから、やはり銀行に預けた方が得という事になる。 しかし予想値はあくまで予想値、この辺なんらかの欺瞞も、現実には多くあるような気もする。 ===物価の指数、インフレ率をどうやって導くか?=== 物価高とか、物価が低いと言ったところで、商品やサービスごとに価格の変動は異なるだろう。 インフレ傾向だと言っても、価格が下落している商品もあるだろう。 そこで総合的なインフレ率、物価動向を示す指数は、様々な算出法が考えられることになる。 「物価指数」とは、市場にある数種の商品の価格を実際に行政が調べて、基準年から何倍になったかを表している。 たとえば、リンゴでもハンバーガーでも何でもいいのだが、たとえばリンゴが基準年から20% 価格上昇したら、リンゴの物価指数は1.2(=1+0.2)ですね。 そして物価指数というのは、社会の物価を総合的に示す指数であるので、いくつもの商品の価格の変動を考慮して算出する。 そして消費者にとって重要な商品と、生産者にとって重要な商品は違う。 だから、「消費者物価指数」(CPI, consumer price index)と「生産者物価指数」(PPI, producer price index)という、それぞれ別の物価指数が算出されている(少なくともアメリカでは)。 さらに、GDPの計算のときに使う物価指数は「GDPデフレーター」といい、消費者物価指数とも生産者物価指数とも異なる。 GDPデフレーターは、名目GDP から実質GDP を求めるときに算出する物価指数で、これも、物価が高ければ1 ( 100分率の場合は100 )を超える。 :実質GDP = 名目GDP / (GDPデフレーター[100分率]/100) ですね。GDPデフレーターは実際は100分率で示す場合が多い。 事実上、物価指数の計算方法は、種々多様になるだろう。 GDPデフレーターの算出方法は、「消費者物価指数」(CPI)の方法に近いが、ある程度は異なる。実質GDPは国内総生産(GDP)であり、国内生産に関する商品の価格変化を重視し、いっぽう消費者物価指数(CPI)では、輸入品の価格も比較的に強めに考慮する。 事実上、「GDPデフレーター」とは、実質GDPの算出に用いる物価指数であり、『スティグリッツ入門経済学 第4版』もその文脈で解説している。 消費者物価指数とGDPデフレーターの関係、アメリカでは、1970年代の(2度の)石油危機のときに、2度、値が乖離した。 いっぽう同じ1970年代の日本では、CPIとGDPデフレーターはあまり、乖離しなかった。 ==金持ちはけち?いやー金持ちだろうが貧乏だろうが、けちな奴はけちだし、太っ腹(放蕩?^^;;;)なやつは太っ腹じゃあない^^?== ===先ず…=== GDPが高い国家は、消費も多くなるだろう。 消費額をCとして、所得をYとし、比例係数 k を用いて式 :C≒kY が、成り立つと考えてみよう。 所得以上に消費することは普通無いので、 :k<1 と、してみる。 また、ミクロ経済では、需要Dを、 :D = j×Y + 定数 の式で示す試みもある<ref>小室直樹『小室直樹の経済原論』、東洋経済新報社、2015年6月11日発行、P509</ref>。このような立式で、需要、消費、所得などを、数理的に議論する事が可能になる。 === 限界消費性向 === さて、誰がけちで誰が太っ腹かの話は、はっきり言ってどうでもいい事だろう。 先ずここで「平均消費性向」という言葉を提示する。これは、可処分所得に対する消費支出の割合の事だ。 ある人がある所得を得て生活している時、その可処分所得の中から、平均消費性向の分だけ消費として使っている訳だ。 そしてこの人の所得が増加した時、増加分のうち、消費に回す割合を、限界消費性向(MPC、marginal propensity to consume)、と、いう。 一般に経済学では、何か(金額など)の投入を1単位ぶん増やしたときに、増える出力の割合のことを「限界〇〇」という。 アメリカでの調査では、所得の大小に関わらず限界消費性向は0.8~0.9である、と、言われている。 クズネッツは1869~1938年の統計を見ると、限界消費性向は0.9である、と記述する。 ここで、仮に平均消費性向も0.8~0.9であるとすると、縦軸に消費額をとり、横軸に所得(可処分所得)をとると、このグラフは傾き0.8~0.9の直線になる。(『スティグリッツ入門経済学 第4版』、薮下史郎ほか訳、東洋経済、2012念4月5日 発行、)(クルーグマン『マクロ経済学』、大山道弘ほか訳、東洋経済、2009年4月2日発行、315ページ) だから、平均消費性向と限界消費性向の値が一致するなら、所得と消費は比例式だから、単に所得の内のある割合が消費になるし、そうでないなら、所得が増える程、財布の紐を締める、或いはその逆、という議論が可能になるだろう。 ===消費関数=== クズネッツ型の消費関数(consumption function)とは、前述した :C≒kY 、である。 日本などいくつかの国では、所得が増えるほど消費の割合が低くなる、という現象が、統計として見られる。 これはケインズ型の消費関数↓を使うと、うまく表現する事が出来る。 :c = a + MPC × Yd :c: 消費 :a: 独立消費水準 :MPC: 限界消費性向 :Yd : 可処分所得 MPC<1 でないと、一般的には意味を持たないだろう。 式中のaの部分、所得によらずにする消費のことを独立消費(antonomous consumption)というが、日本では基礎消費ともいう(※: 『基礎消費』の参考文献: 福田慎一・照山博司『マクロ経済学・入門 第5版』、有斐閣、2016年3月30日 第5版 第1刷 発行,32ページ) 独立消費水準が0 なら、これはクズネッツ型の消費関数だが、一般的には、クズネッツ型は比例式、ケインズ型は、所得に応じて消費の傾向が変わる状況を示す関数とみる。a>0 なら、所得が上がるごとに平均消費性向は下がっていくだろう。 中谷巌『マクロ経済学入門 <第2版>』(日本経済新聞社、2007年1月15日、2版1刷、32ページ)は、1992年から1997年の日本の消費関数を :C=76+0.61Y としている。<!-- すじにくさん、これ単位は何なの?千円? --> 有斐閣アルマ『マクロ経済学入門』(福田慎一・照山博司,38ページ)によると、2004年、2009年、2014年の日本では、低所得者の平均消費性向は0.9に近く、年収1250万円ていどの所得者の平均消費性向は0.6~0.7程度と低い。 ケインズ型の関数はより一般化されているから、所得に応じた平均消費性向の変化を表現する事が出来る。 現編集者としては、このクズネット型とケインズ型の消費関数の違いについてああだこうだ議論することに大きな意味があるとは思えないが、長期スケールではクズネッツ型の短期スケールではケインズ型の消費関数が当てはまるという指摘もある。 しかしこれは本当だろうか? 短期の所得と消費の関係、長期にわたる所得と消費の関係、この兼ね合いは、まず数理的な扱いの検討が必要になるだろう。短期スケールと長期スケールが独立してあるわけではなく、短期スケールの積み重ねが長期スケールになる。しかし、この問題をそんなに徹底的に考える意義はあるだろうか? また前編集者はさらに、この問題には、「ライフサイクル仮説」という学説、も関連話題としてあり、多くの大学生向けのマクロ経済学の教科書で解説されているという。 *クズネッツ型とケインズ型 [[File:Consumption function of Kuznets and Keynes type compatible japaneseB.svg|thumb|500px|※ これは架空のグラフです。]] 数学的には、クズネッツ型の比例式を一次関数に一般化したのがケインズ型の消費関数だろう。 さて、今具体的なある年を考えて、この年に日本国籍を持っていた人物、というのは具体的に上げて、数え上げることができるだろう。そしてその具体的な人物の年収も、その年収のうちその年にいくら消費したのかも、具体的な数値、金額として示すことができるだろう。 例えばその数値を、1950年から、1999年まで、すべての日本人について、右のような所得→消費のグラフにプロットしたとする。 これを比例式で回帰したら、クズネッツ型の消費関数になるだろうし、普通に回帰直線を描いたら、ケインズ型になるだろう。 また、全てのデータを使わずに、1950年代、1970年代、1990年代、と、データを分けて回帰すると、おそらくケインズ型の回帰が見られるだろうし、あるいはまた、特定の傾向を持つ少数の人物の、長い時間にわたるプロット、例えばその間にインフレが進行するとか、あるいは所得も上がっているかもしれません、を回帰すると、クズネッツ型の関係が見いだされるかもしれません。 右上のグラフはそういう統計手段についてのイメージ図ですが、参考文献: 福田慎一・照山博司『マクロ経済学・入門』37ページ図、2-3 にある第二次大戦後の昭和の日本の家計消費のグラフを、参照して作っています。 {{-}} *ピケティの言 クズネッツ型の、所得と消費の比例式は、主に所得格差の小さい時期に見られる様だ。 フランスの経済学者ピケティは、クズネッツ型の消費の比例関係は、アメリカで大戦後一時所得格差が小さかった時代、或いは社会経済の動乱期のデータで<ref>トマ・ピケティ『21世紀の資本』、訳 山形浩生・森岡桜・森本正史、東洋経済、みすず書房、2015年1月15日、13ページ・15ページ</ref>、格差自体は、どんどん広がっているので、消費は、ケインズ型の一次関数になっていくだろう、と、指摘する。 * 乗数効果 さて、あなたが消費したお金は、誰かが受け取り収入になる。その誰かもまたそのお金を消費すると、また別の誰かの収入になる。 お金や人々の手から手へ廻っているのですね。 では今、ある人、 Aさんの年収を 1000万円としましょう。そして、現実にはあり得ないことですが、 Aさんが消費したお金はすべて Bさんの収入になるとしましょう。そして同じような関係が、 Bさん、 Cさん、 Dさん、…と、続いていくとしましょう。そして今平均消費傾向が限界消費傾向 MPCと等しいとすると… :Aさんは 1000万円 の収入を手にしたので MPC × 1000万円 の消費をすることになる。 :Bさんは MPC ×1000万円 の収入を手にしたので MPC<sup>2</sup> × 1000万円 の消費をすることになる。 :Cさんは MPC<sup>2</sup> ×1000万円 の収入を手にしたので MPC<sup>3</sup> × 1000万円 の消費をすることになる。 :Dさんは MPC<sup>3</sup> ×1000万円 の収入を手にしたので MPC<sup>4</sup> × 1000万円 の消費をすることになる。 つまり、一人の消費が、別の消費を数珠つなぎに引き出していることを示したいのです。 ここで、このつながりが n人に及べば、Aさんの消費が最終的に :<math>MPC+MPC^2+MPC^3+MPC^4+\cdots+MPC^n</math> 倍の消費を生み出したことになる。 収入の和を考えれば、 Aさんは 1倍の収入があるから、 :<math>1+MPC+MPC^2+MPC^3+MPC^4+\cdots+MPC^n</math> これは等比数列の和ですね。 ここで無限に足し合わせた級数を考えると、0<=MPC<1 に注意して、 <math>1+MPC+MPC^2+MPC^3+MPC^4+\cdots+MPC^n+\cdots= \frac{1}{1-MPC}</math> と、なります。 実際には人口は無限でありませんが、十分に大きい数をとると、この値にほぼ近くなるとみていいでしょう。 そこで消費傾向が0.9 なら、<math>\frac{1}{1-MPC}</math>は 10になる。 このように、何らかの消費や投資の効果は増加、増殖する、と、考えられています。 さて、 :1-MPC は貯蓄性向(正確には限界貯蓄性向 MPS)。 そこで、 :<math>\frac{1}{1-MPC}=\frac{1}{MPS}</math> になります。 ここでは、0<MPS<=1 ですね。 つまりこの発想で考えると、貯蓄の割合を多くすると世に出回るお金の量が少なくなり、社会経済、景気が停滞し、発展が閉ざされ、生活が貧困になる、つまり合成の誤謬が成立するわけです<ref>[http://park.saitama-u.ac.jp/~yanagisawa/het10/44-61.pdf 『第5章 ケインズの経済学』P51]</ref>。 *預金は銀行が借入しているのだろう {|class="wikitable" style="float:right" |+ 信用創造 ! 銀行・借入者 !! 預金・借入金 !! 支払い準備金・内部留保や消費 !! 貸し付け金・預金 |- ! A銀行 |  100万円 ||  20万円 || 80万円  |- ! B企業 |  80万円 ||  16万円   || 64万円 |- ! C銀行 |  64 ||  12.8   || 51.2 |- ! D企業 |  51.2 ||  10.24   || 40.96 |- ! 以下省略 |   ||     || |- ! 合計 |  500万円 ||  100万円   || 400万円 |- |} 家計が銀行に預金をすると、銀行にとって貸出資金が増加し、それが金融市場に流れ、企業や他の銀行も資金増加になり,社会全体で多くのお金が動くとみなせる、このような考え方を信用創造という。これは高校政治経済でも言及されている。 右の表では、例えば誰かが A銀行に 100万円預金する。 A銀行は預金のうち 80%の 80万円を B企業に貸す。 B企業は、まああまりリアリティのない仮定だが、 20%を運転資金として消費し、 80%を C銀行にいったん預ける。つまり、銀行も企業も 20%を留保または消費して、 80% を他者に貸す。 そうすると預金を債権とみなすとして、 :信用創造された債権総額=元の預金/0.2 と考えることができる。 これは前述した等比級数の考え方だ。 :信用創造された債権総額= 元の預金× (1 + 0.8 + 0.8<sup>2</sup> + 0.8<sup>3</sup> + ・・・) ::= 元の預金×(1/(1-0.8)) 預金だけを考えれば、 :信用創造された預金総額=元の預金/(1-0.8<sup>2</sup>) に、なるだろう。 信用創造を考えるとき、元の預金のことを「本源的預金」ということもある。 ===ハンセン=サミュエルソンの乗数・加速度モデル=== さて、ケインズ型の消費関数は以前、 :c = a + MPC × Yd :c:消費 :a:独立消費水準 :MPC:限界消費性向 :Yd :可処分所得 と、記述した。 ここで消費c ではなく、所得Y に注目する。そしてむしろ国全体の所得、生産に着目し、つまり GDPを見るのだが、似たような形式の数理議論がある。 [[w:乗数・加速度モデル]]。 :<math>Y_t=C_t+I_t</math> :<math>C_t = C + cY_{t-1}</math> :<math>I_t = I + v (Y_{t-1}-Y_{t-2}) </math> ただし、 * <math>Y</math>: GDP * <math>C</math>: <math>C_t</math>はt期の消費。<math>C</math>は基礎消費。 * <math>I</math>: <math>I_t</math>はt期の投資。<math>I</math>は独立投資。 * <math>c</math>: 消費性向 * <math>t</math>: t期(時間) * <math>v</math>: 加速度係数 この連立式から、 <math>Y_t=(c+v) Y_{t-1}-vY_{t-2}+(C+I)</math> を導き、時間に対応する数列としての GDPを議論できる。 ==貨幣数量説== まず名目GDP の一番基本的な定義から考えてみよう。ある期間の、ある国に所属する経済主体の、売り上げから原材料費を引いた金額の総和がこれであろう。 そして売り上げそのもの、つまり原材料を引かない金額の総和も考えることが出来るし、そしてこれは大雑把に言えば,GDP に比例しているとみなすこともできる。 そしてまず、このような式を提示しよう。 :貨幣の流通速度 V = 名目GDP / 貨幣量M 速度というのは単位時間ごとの値だが、ここでは例えば、名目GDP が 3か月の値なら、3か月の量を示しているわけだ。 さて、名目GDPは、販売された商品の価格に含まれる製品一個当たりの付加価値 P(販売価格から原価をひいたもの)とその個数の合計 Yとの積 ΣPY に等しい。 :<math>\sum_{k=1}P_k Y_k=P_1 Y_1+P_2 Y_2+P_3 Y_3+\cdots</math> つまり、こうですか。 :MV=名目GDP=<math>\sum_{k=1}P_k Y_k</math> さて、先ほど売り上げそのもの、つまり原材料を引かない金額の総和について書いたが、これは荒くとらえて名目GDP に比例するとみてみようと言及したが、製品一個の付加価値ではなく価格をP' とすると、 :bMV=b*名目GDP=<math>\sum_{k=1}P'_k Y_k</math> そこで、貨幣の流通速度の別解釈を提示しよう。 :貨幣の流通速度(別) V' = b*名目GDP / 貨幣量M これはこうなるでしょう。 :MV'=<math>\sum_{k=1}P'_k Y_k</math> さて、ここでですねー、こういう値を考えたい。 <math>Y=\sum_{k=1}Y_k</math> こうなると、この値、P' を求めることが出来るでしょう。 P'=<math>\frac{\sum_{k=1}P'_k Y_k}{Y}</math> 結局 MV'=P'Y :菅原晃『使えるマクロ経済学』、中経出版、2014年10月14日 第1刷発行,178ページ、 :では、『貨幣数量説』の公式として、 ::「貨幣量×世の中を回った回数=物価×取引量」 とある。 :菅原晃『使えるマクロ経済学』、中経出版、2014年10月14日 第1刷発行,203ページ、 :では、『貨幣数量説』の公式として、 ::「供給:貨幣量×世の中を回った回数=需要:物価×取引量」 とある。 この形の公式を「数量方程式」(quantity equation) と呼んでみましょう。また、この公式であらわされる学説を「貨幣数量説」という場合もある。 右辺に価格が入っているので、物価のインフレまたはデフレの解析に、この貨幣の流通速度の理論が使えそうだと経済学では思われている。 アメリカ経済学の教科書のスタイルではP×Y は 名目GDP に等しいと説明されるが、P' と同様に一般的な付加価値、P を求めることが出来るから、正しい主張でしょう。 PをGDPデフレーターとして、Yを実質GDPとして :MV = PY という書き方が、各種教科書でなされることも多い。どちらにしろP*Y は名目GDPになるわけです。 前編集者は :MV'=物価×取引量 ∝ 名目GDP :MV'=物価×取引量 ∝ 実質GDP × インフレ率 という関係式を得て、それを経済モデルに合うように連立させることが重要、と記述していたが、現編集者はこの手の数理議論にはあまり大きな意味はないと思っている。 ===マーシャルのk=== さて、前項で、 :MV=名目GDP=PY :MV'=P'Y :M:貨幣量 :V:貨幣の流通速度α :V':貨幣の流通速度β :P:一般化された付加価値 :P':一般化された価格 :Y:財、サービスの取引数 ここで前回の議論にもあったように、 P'Y=b*PY としてみると、 M=(b/V')*P*Y そして、 M=k*P*Y このk が、マーシャルのkであるかは定かではないが、彼の議論の片りんを見るものとみていいだろう。 統計的には k は定数ではない。(※参考文献:中谷巌『入門マクロ経済学 第5版』、日本評論社、2007年3月30日第5版第1刷発行、192ページ) たとえば中谷は参考文献『入門マクロ経済学第5版』で、日本では1970年代はマーシャルのkが 0.7 程度だったが、しだいに増加していき、2004年には k は 1.4 程度であるとグラフで図示している。 :※福田慎一・照山博司『マクロ経済学・入門』(有斐閣、2016年3月30日第5版第1刷発行、141ページ)では、文中に「右辺の定数k」とある。しかし、中谷の文献で紹介されるように、統計的にはkは定数ではない。数学的にはkは、「右辺の'''係数'''」である。 k=b/V'でもし bが定数なら、貨幣の交換が少なくなるほどk が大きくなる。 だから、いわゆる「デフレ経済」と言われる日本の1990年以降の時代(平成初期の不動産バブル崩壊の以降の時代)でマーシャルのkが増加するのは常識と一致するのだが、しかし中谷の文献のグラフを見ると、1970年代も1980年代でもマーシャルのkは増加傾向であるのが、グラフから読み取れる。(しかし中谷は、不動産バブル崩壊以前のマーシャルのkの増大には注意を払ってない。) そしてこの式は、こう読める。 :M=k*名目GDP (参考文献:菅原晃『使えるマクロ経済学』、中経出版、2014年10月14日第1刷発行,203ページ。この文献では「貨幣量=GDP」という図とともに「k%ルールが有効!」という文言が図中にある。 ) このkを、経済政策の目安にするのが良いだろうという学説があるらしく、フリードマンがそのような学説を提唱したらしい(菅原の文献を読んだ限り、そういう印象を受けた。By E.Suj.)。 ==インフレは好ましいか?== 経験的に、経済政策として、インフレ率2~4%程度の緩やかなインフレを目指すことが、多くの国で行われている。 クルーグマンが『マクロ経済学』(2009年版、472ページ)で報告するには、アメリカのFRBは方針こそ断言してないが、その実行結果から、2~3%ていどのインフレ率を好んでいる、と、云う。また、イングランド銀行はインフレ率を2.5%とすると明示的に公表している、と同ページに記述されている。 なお、この2%のインフレ率のように、比較的に低率でのインフレのことをクリーピング・インフレ(creeping inflation)という。クリーピングとは「しのびよる」という意味の英語である。1~3%程度のインフレ率が、クリーピング・インフレだと言われている。 また、スティグリッツは、もし政府がインフレを嫌ってデフレを誘導すると、一時的には失業率が増加する、と述べている(『スティグリッツ入門経済学 第4版』東洋経済、432ページ)。 しかし、この低率のインフレが好ましいという議論は、論理的に明快に因果関係が説明されているわけではない。少なくとも、『クルーグマン マクロ経済学』や『スティグリッツ入門経済学』を読んでも、そのインフレ率2~3%程度が好ましいという論の明確な説明は全く見当たらない。 スティグリッツは、循環的失業の増加は低インフレをもたらし、循環的失業の減少は高インフレをもたらす、と述べているが、しかし彼以外のクルーグマンもマンキューも、スティグリッツのような主張は(調べたかぎりでは)していないようである。 ==ケインズ政策== アメリカの1940年代のニューディール政策は、1930年代のケインズの経済理論が根拠になっている、とよく言われる。しかしそれ以外にも参考にした具体例があったようだ。 例えば、1930年代の日本の高橋是清・蔵相の不況対策で、似たような積極的財政政策がとられている<ref>福田慎一・照山博司『マクロ経済学・入門』、有斐閣、2016年3月30日第5版第1刷、194ページ</ref>。 1930年代のドイツでの独裁者ヒトラー政権下でも、ドイツ人経済学者シャハト博士の助言のもとに、公共事業(高速道路アウトバーン建設など)や軍備増強など、積極的にドイツ政府は財政拡大をして投資した<ref>たとえば 犬走文彦『反経済学講座』、新潮社、2009年8月20日、P142</ref>。もっともこのころのドイツの軍備増強は、誰もが知るところだろう。だからこそ、第二次世界大戦の大騒ぎが実現したわけだ。 まあ軍備増強を公共投資と言っていいのかは疑問だが、当時のヒトラーの経済政策の果敢さは、彼の国内での、あるいは国外でも、人気拡大に一役買っただろう。 詳しい文脈は不明だが、森嶋道夫『思想としての近代経済学』(岩波新書、1994年)に、経済学者ヒックスが森嶋に「戦前はヒトラーの時代であった。戦後はケインズの時代になろう」と述べたことが記されている<ref>小室直樹『小室直樹の経済原論』、東洋経済新報社、2015年6月11日発行、P541</ref>。小畑二郎『経済学の歴史』にも似たような話が書かれている。 1940年代アメリカのニューディール政策はケインズの理論だけではなく、当時の様々な前例も参考に行われたのだろう。 さて近年、2008~2009年ごろのリーマンショックやサブプライムショックなどの対策としても、銀行の救済や公共事業などによる積極財政や金融政策がとられている。 ケインズ政策、ケインズ主義とは、不況対策や経済発展などのために政府が積極的に公共事業や融資や民間への資金援助などを行う政策をいうのだろう。ケインズ自身は、大恐慌に対する処方箋として、利子率の切り下げ(金融政策)と社会基盤への政府投資(財政政策)を示していた。 リーマンショック対策でケインズ政策はひとます成功したし、今でもこの政策が不況対策として有効だと、一般に認知されている。 ケインズの議論はケインズ経済学というマクロ経済学の主要な学派になっている。ケインジアン、という言葉もある。 一方でケインズ政策を実行すると、その国は多くの場合財政が悪化する。具体的には、国債を増発するようになる。第二次大戦後のアメリカ合衆国はそうなった。 この借金による国家運営の問題点をなくすために、ケインズ主義に代わる新しい経済思想がアメリカやイギリスで必要になり、1980年代にはレーガン大統領のレーガノミクスやサッチャー首相のサッチャリズムのような「新自由主義」が政治の表舞台に現れてきた。 *ハーヴェイロードの前提 ケインズ自身は、恐慌の時期には政府は借金をして投資しても、恐慌を脱したら財政規律を高めて赤字財政を回収して均衡財政に戻すべきと考えていた<ref>http://park.saitama-u.ac.jp/~yanagisawa/het10/44-61.pdf P58、2022年4月6日に確認.</ref>。 しかし、実際の多くの戦後先進国では、そのような政策はとられず、20世紀後半に赤字財政に陥った国も少なからず存在する。 WW2戦後のインフレには、このような赤字財政という背景もあったと、経済学者ブキャナンなどの新自由主義者は述べている<ref>http://park.saitama-u.ac.jp/~yanagisawa/het10/44-61.pdf P58、2022年4月6日に確認.</ref>。 ケインズの議論には、政府の経済政策には賢人としての高度な判断があるという、「ハーヴェイロードの前提」がある。ハーヴェイロードというのはケインズが生まれ育ったイギリスケンブリッジの土地で、知識人が集まっている場であった。 戦後の経済がケインズの当初の予想通りの均衡財政にならなかったのは、政治家の堕落(だらく)であり、為政者としての責任感の欠如だ、という指摘もある。つまり「ハーヴェイ・ロードの前提」が政治家に欠けている、という事だろう。 一方ケインズ経済理論を批判するブキャナンたち新自由主義の経済学者は、むしろ「ハーヴェイ・ロードの前提」が非現実的だろう、とも語る。 そして前編集者は、堕落しているのは政治家ではなく、むしろ民衆だろうと記述している。正しい政治家に投票できない民衆がおごりの中で政治家を批判しているだけだろうと指摘する。 しかし仮に民衆が堕落しているのなら、政治家も等しく堕落しているだろう。 全ての人間が公平に堕落しているのが現代社会だろう^^;;;。 赤信号、みんなで渡れば怖くない^^;;; *貨幣錯覚 ケインズの一般理論でも、「貨幣錯覚」については言及されている。本来貨幣は定まった価値を持つものではなく、一般的絶対的な価値に対して、必要な額面が大きくなったり小さくなったりする。つまり財やサービスに必要な貨幣の額面、物価が高くなったり低くなったりするのだ。 だから本来貨幣は名目、額面としての数字ではなく実質の価値が問題になるのだが、実際には人々は貨幣の額面の数字に捉われる。 多くの労働者も、実質賃金ではなく貨幣賃金を見て行動する、という<ref>滝川好夫『図解雑学 ケインズ経済学』、ナツメ社、2010年11月21日初版発行、P60</ref>。 ケインズは緩やかなインフレを肯定した。また、インフレ誘導的な政策が、恐慌の脱出措置としてよく用いられる。 物価が高くなると、実質賃金は下がるが、それに合わせて名目の賃金を上げると、労働者は収入が上昇しているように感じるだろう(か?)。 *利子理論と物価 一般に、インフレなら名目金利を高くすることが可能だという{{要出典}}。 前編集者は物価に関する数理を欲していたが、ケインズの利子理論やそこから導出された、LS-IM分析は,その目的にはかなわないものだという。 ケインズは「一般理論」の著書で,2%という数字を利子率の基準として示した。<ref>[https://ynu.repo.nii.ac.jp/?action=pages_view_main&active_action=repository_view_main_item_detail&item_id=3118&item_no=1&page_id=59&block_id=74 石井力『先物市場の「流動性の罠」』,P82]2022年4月6日に確認.</ref>。一方、21世紀、主要な先進国が採用する物価インフレ目標も多くは2%である。 前編集者は物価と金利を結び付けた数理議論を求めているようだが、そういう論説はあまり世にない様だ。ケインズは金利の理論を展開したが、それと物価を結び付ける議論も、特にあまり見当たらないという。 しかし実際には全くそれがないわけではないだろう。一般的な議論として、政策金利を低くすると借金がしやすくなり、銀行のストックが減り世の中に貨幣が出回る。その結果貨幣量が増え、インフレ傾向、物価上昇傾向になると見れるだろう。 ロイター日本語版の2021の記事は物価目標2%と金利を関連づけて語っている<ref> [https://jp.reuters.com/article/column-suzuki-akihiko-idJPKBN2F60HR 鈴木明彦『コラム:所得増えぬまま物価目標2%達成なら、消費者から悲鳴か=鈴木明彦氏』]2022年4月6日に確認.</ref>。しかしケインズの議論には言及がなく、その視点での分析も特に書いていない。 一般的に金利が高いと貨幣量が減り、デフレ傾向だが、不況に関してはどうなるだろう? 一般に金利と言えば貸金、預金の利率、貨幣を貸すときの手数料、利益と見ていいだろう。物価は生産物と貨幣の交換率、この二つの値の比較と重要性を語りたいのが前編集者の議論だが、例えば学問的な考察や議論で、詳細に拘らず、あるものを別の或るもので単純に置き換えると、面白い展開を迎えるというのは、往々にしてある。例えばケインズの利率を物価で置き換えたらどうだ? と、言うのが前編集者のアイディアではあろう。 日本の平成、「デフレ不況」と言われている状況では、金利も低く物価も低くなっている。1990年前後のバブル崩壊よりも前のころは金利は高かったろうし、物価も高かっただろう。 昔の主婦は金利の高い金融機関を探して選んで預金していたものだが、最近は預金に関してはあきれるほど利率が低い。 21世紀の日本の低金利は、日本の不動産バブル崩壊後、何らかの理由で金利を下げる必要があったのだろうと前編集者は考えているようだ、特に物価の下落を重要ファクターと見ている。日本の過去の不動産バブルは、不動産資産のインフレによる騒動と見ることが出来るだろうか。 長期的にはインフレ率と金利が近づいていくという指摘もある{{要出典}}。 '''クラウディング・アウト'''とは何か? 現編集者はむしろ、より詳しい方がここに記述してくれることを望むが、前編集者の説明では、国債や郵便貯金などの利率が高いとその商品が魅力的になるので、株式や投資、民間の債権などにお金が流れなくなる現象だと書く。 では国債や郵便貯金の利率は低いほうが良いのか?もちろんそうなれば財政も圧迫しなくなるし、が一方で公共にお金を貸す意思自体が減ると見られるかもしれない。 政策金利と呼ばれるものはまた別の利率だろうが、これが低すぎると'''流動性の罠(わな)'''と呼ばれ、景気浮揚や投資を増やす効果を持たなくなるという。 現編集者は実際は経済学も大した知らないが、前編集者の不適切な悪意に満ちた文章を何とかしたい一心で、いろいろ調べながらこの文章を書いているだけなので、いずれはより詳しく人間性も良好な人にこのページを書き足し修正してほしいのだが、とりあえず流動性の罠の原因については、「ゼロ金利の近くになると、これ以上は金利は下がりようがないのだから、つまり今後は国債などの金利が上がる可能性が高い。そこで、人々は値上がりを期待して、民間に投資をしなくなる」、という言説もあるようです。 つまりこの主張は、今金利が低いと、人々は将来上がると予想してそれを待つという事? そこで結局流動性の罠とは何かそれほど理解していないまま、文章を先に進めるが、経済評論家の三橋貴明氏は、平成のデフレ不況とは、『デフレ化において単純に「儲からないから投資しない」』現象だと著書で語っている。そのうえでとりあえず政策金利を下げればよいという、バブル崩壊後の日本政府の金融政策を批判している<ref>三橋孝明『黄金の拘束衣を着た首相』、飛鳥新社、2015年2月6日第1刷発行、P129</ref>。 そもそも新たな投資が頻繁になされることが絶対的にいい事なのか? 今現在の生産インフラが潤沢に回っていることで、いい経済状況だとはみなせないのか? 経済が貨幣でお金のことだと見てしまうのは、本質を見失わせるだろう。経済とは我々の日々の生産活動だし、貨幣はそれに従い、それを動かすためのツールに過ぎない。 さて、評論家犬走文彦氏は「金融危機があるレベルまで達すると、信用リスクを回避するためいくら金利が低くなっても金融機関が貸し出しを止めてしまう」と書いている<ref>犬走文彦『反経済学講座』、新潮社、2009年8月20日、P134</ref>。そもそも金利が低くなると貸し出す方に旨味はない。借りる方が得になるから、貨幣需要が増えるという事だろう。しかし金融機関は敢えて貸さない? しかし金融機関とは、貨幣を貸し出して利益を得ている法人だったはずだ。 兎に角細かい事や全体を見ないままとりあえず投資が増えればいいというのなら、そして、「儲からないから投資しない」というのなら、「投資しないと損をするぞ」といった内容の経済構造すればよいのでは? 、と、前編集者は指摘する。 つまり投資という仕事をさせたいから、鼻先にぶら下げる人参はもうないから、では鞭で打とう、と、そういう訳だろう。 インフレ誘導にはそういう意味があるのだろうね。現状がデフレやディスインフレならなおさらこの方法に行きやすい。しかしインフレ誘導が制御できなくなって、高インフレになると、多くの人々が困ることになるだろう。今現在(2023/2)、その傾向があると言えなくもない。 一方経済学者クルーグマンは『中央銀行が将来のインフレ率を公約する「インフレ目標」が、流動性の罠のもとでも有効であると主張した。』、という<ref>福山慎一「マクロ経済学入門 第5版」、有斐閣、P223(『』内は書籍の解説文の引用)</ref>。 「バランスシート不況」という考え方では、恐慌時などには投資家がリスク回避志向になり、不況時は銀行の行動パターンが投資から債権回収などに移るので、この時期に政府が金融政策しても、あまり効果がない、という<ref>犬走文彦『反経済学講座』、新潮社、2009年8月20日、P134</ref>。貸し渋りという事? お金を持っている人たちが貸したくなくなる? しかしファイナンス、貸金とはそんなに経済、景気の進展に重要な事なのか? 借りたお金が世の中を潤沢に回ることが本当に健全な事態なのか? 投資と融資は異なるだろう。投資とは生産インフラの資本、資産を買い、所有することだし、融資はお金を貸しているという事。債権は利子を付けていずれ回収したいが、投資は所有している場合は配当などの利益が期待できるが、株式などの形で売って貨幣を回収することもできる。 1990年前後の不動産バブル崩壊後、日本は2000年代初頭に、非伝統的な金融政策である日銀のバランスシートの拡大、およびそれらの量的緩和をインフレ率が安定的に0.数%になるまで続けるという政策を実施しました。<ref>福山慎一『マクロ経済学入門 第5版』、P224</ref> さて、もちろんケインズは我々の歴史の中で最重要の経済学者ですが、全知全能の神様ではない。その指摘や理論が徹底的に現実を示しているものではないでしょう。 前編集者によると、「ケインズ理論も新自由主義も両方とも間違っている」、という主張も結構多いという。「反経済学講座」(犬走文彦、新潮社、2009年8月20日)がそういうスタンスだという事だが…。 また基本的には、特にその会社の経営者、関係者は自分の会社が倒産することは望まないだろう。しかし世の中には自然淘汰を称賛し、弱者が滅びることが正しい事だと見做す考えも多いし、そこまで極論ではなくても、妥当な経営を出来ない会社はペナルティとして倒産やむなし、という判断は多くなされるだろう。前編集者は経済思想家ハイエクなどはそう考えていると指摘する。 基本的に弱者企業を補助金などで救済すること自体が、経済全体にとって悪い事だという主張は多い。ハイエクは、不況の救済のために必要以上の補助金を投入する事こそが、次のバブルおよびその破裂による恐慌をまねく、と、指摘したという。[https://bizgate.nikkei.co.jp/article/DGXMZO3466714028082018000000 『世界恐慌を予言した人たち~金融緩和がはらむ反動リスク 』 2018/9/18]。 ハイエクなどオーストリア学派は、不況を避けるという考え自体が不適切だろう、と主張したという。ある程度の不況の緩和を目指すことは認められるが、景気は循環するもので、無理やりそれを動かして不況を避けて矯正しようとすると、経済はかえって悪化する、と指摘する<ref>犬走文彦『反経済学講座』、新潮社、2009年8月20日、P154</ref>。 歴史的には大した恐慌対策を取らないまま、状況が改善した例もあるようです。1930の世界恐慌より前、1920年の恐慌は、自然に終息、回復を迎えたとオーストリア学派は主張しています<ref>犬走文彦『反経済学講座』、新潮社、2009年8月20日、P159</ref>。当時のアメリカは金本位制。第一次大戦の放漫財政で金の保有量が減っていたことから、対策をとろうとしてもアメリカ政府のハーディング大統領は対策をとれなかった、と、いう。 さて、一般的に、 Aならば Bでも、 Bならば Aであるとは限らない。 消費の低迷 → 消費依存型産業の物価デフレ この流れはどうですかね。需要が減れば、値は下がるでしょう。 消費依存型産業の物価デフレ → 消費の低迷 これは? まず単純に考えて、値が下がれば需要は増えるのでは? では… 消費の活況 → 消費依存型産業の物価インフレ これはありますよね。需要が増えれば値は上がる。 消費依存型産業の物価インフレ → 消費の活況 これはどうですかね。一般に値が上がれば需要は減る、売りたい人は増えますがね。 高度成長も終わった昭和末期の1980年代、日本はディスインフレでした。しかし消費は活況。1980年代後半には、バブル直前の黄金期を迎えたといいます<ref>藤巻健史『マネーはこう動く』、光文社、2007年7月30日初版発行、P59</ref>。 だからデフレと不況の結びつきはそれほど強固ではない。 ただ需要が低下すると、値は下がる、これが徹底的に続いているのがデフレ不況なのだろう。経済評論家・加谷珪一は「デフレが不景気を引き起こしたわけではない。不景気でモノが売れず、企業は安値販売を余儀なくされ、これがさらに物価と賃金を引き下げている。高く売ることができる商品をわざわざ安く売っていたわけではない点に注意する必要がある。」と語る<ref>[https://www.newsweekjapan.jp/kaya/2022/04/post-180_2.php 『日本だけ給料が上がらない謎...「内部留保」でも「デフレ」でもない本当の元凶』2022年04月01日(金)17時30分]2022年4月9日に確認.</ref>。 つまり需要がない。日本は物に溢れている、なんてよく言うが、それに類する事態だろう。 しかし需要がないという事は必要ないという事。物が十分にあるという事はそんなに働かなくてもいいという事? そんなに作らなくてもいいという事かね? しかし結局この国の経済状況の中で、失業したり貧困に陥る人はかなりの数存在する。 ==完全競争== 高校の政治経済では、「不完全競争市場」の例として、寡占や独占などの事例を習う。不完全の反対が完全だろうが、寡占(かせん、oligopoly)や独占(monopoly)などの、競争をゆがめるような制限のない市場の状態のことをよく、完全競争(pure competition)という この言葉をより詳しく規定するとどうなるか? 次の五つの条件を満たすのが完全競争だという。(前編集者の定義) # 生産者(売り手)と消費者が十分に数が多いという条件。 # また、生産者どうしが談合などせず、競争するという条件。 # また、生産者どうしも独立していて、他の売り手に大きな影響を与えないという、生産者どうしの独立の条件。買い手もまた、他の買い手に大きな影響を与えないという、消費者どうしの独立の条件。 # 消費者はよく商品の情報(特に価格についての情報)を知っているという条件。 # その市場への参入と退出が容易だとする条件。 寡占や独占のもとでの市場競争は、この「完全競争」の条件が満たされてない。と、云うか一般的には完全競争の状態は現実には無いと見なされている。議論のための仮想的な市場状態だろう。 そして完全競争の定義は、論者や学派によって微妙に異なるようだ。ここでは5つの定義を上げたが、これが3つぐらいの規則から導かれる完全競争の性質に過ぎない、という議論もある。 ==不況と好況== [[File:Economic cycle.svg|thumb|450px|景気循環の図。グラフの波型の山の部分が好景気を表し、谷の部分が不景気を表している。<br> Expansion :景気拡大<br> Boom  :好景気の頂点<br> Recession :景気の後退<br> Depression:景気の消沈<br>]] 景気には波があるという。景気を統計的、数量的に示す方法があるかどうか、現編集者は知らないが、実質GDP を基準に考える道はあるだろう。 一般的にある程度安定した国家社会では、実質GDP は微増するものだと見るといいのではないだろうか。社会集団として、生産集団として、文化や技術が発達し生産に慣れて社会として習熟した表れとして、生産を示す実質GDP はわずかに増えていく。あくまでも仮定ですがね。 そうなると、好況というのはその時点での実質GDP成長率がある程度高いことを示すだろうし、不況というのは実質GDP成長率が横ばい、ゼロ、あるいはマイナス成長の時、だということは出来るだろう。 前編集者は、経済や生産の事を語る時に、「不況」「好況」の言葉を使うよりも、「高成長」や「低成長」や「マイナス成長」という言葉を使った方が妥当だし、適切だろうと書いているが、「不況」「好況」という言葉は現実の経済、商業生活でのそれぞれの職業人の精神的な満足度を示しているものではあるので、GDP だけがそれを示すものにはならないだろう。そもそも実質GDP とは常に大きく上昇し、上がっていくのが自然で望ましいのか? そうすれば人々は十分な満足が得られるのか? それさえも怪しいし、定かではないだろう。 ==労働価値説と限界革命== ===労働価値説=== さて、財とサービスに価値があるのは自明でしょう。そしてそれと交換される貨幣にももちろん価値がある。 そしてまあ常識的に払う貨幣が高いほど、その財には価値があると見做されている。 払う貨幣とは価格ですよね。そしてこのページで議論してきたように、価格は需要と供給で決まると考えるのが、現代的な経済理解です。 しかし一方でもっと哲学的、観念的議論として、商品、財が持つ価値の根拠、いったい何によって価値が生まれるか、それを知りたい訳です。 そこでまず議論されたのが、アダムスミスやマルクスが言及した労働価値説ですね。 つまり財やサービスの価値の源泉は、我々の労働だと。 財の価値の根拠が労働にあることは否定できないでしょう。ただその議論を価格と結びつけるのはなんだかんだでかなり困難がある。労力を多く費やしても価格が安くなることはあるし、労力少なくして高い価格がつくことも現実にはある。 しかし数理的に労働量と価格の議論が出来なくても、労働が物事の、財の価値を生み出していることまで否定するのは詭弁でしょう。 大体労働に価値がないのなら、世の人はもう明日から仕事に行かなくなるよ^^;;;。 しかし一方「効用革命」という議論があり、労働価値説とは別の視点として、財を消費する側の満足、欲望の充実に価値の根拠を見出す視点がある<ref>https://diamond.jp/articles/-/75341</ref>。 この議論は数理とも馴染みがよく、ミクロ経済学の重要な分析の一つになっている。 価格は需要と供給によって決まり、財の生産者は市場で売れる価格にあわせて利益が出るように労働および経費などの投入量を調節する<ref>小畑二郎『経済学の歴史』、慶應義塾大学出版会、2014年11月28日 初版 第1刷 発行、P236</ref> ===限界効用理論=== 効用とは財を消費したときの満足度である。ここで効用関数なる値が実数の関数を考える。 一般に消費者は、いくつもある消費計画のうち、みずからの効用関数を最大化させるような消費計画を選ぶ、と考えられる。これを「効用最大化仮説」と言います。 たとえば、ある消費計画Aと、別の消費計画Bについて、それぞれ効用をU(A)およびU(B)とします。つまり消費計画Aの効用がU(A)です。同様に消費計画Bの効用がU(B)です。 そして、たとえば、もし :U(A)>U(B) なら、消費者は消費計画Aを選ぶ。 同様、もし :U(A)<U(B) なら、消費者は消費計画Bを選ぶ。 ただし、効用の大きさそのものを数値化することは一般にはできず、その大小関係・順序にのみ意味があると考えています。数学で言うと、代数システムのうちの順序関係・大小関係のことを「序数」と言うので、効用関数の上述のような性質のことを「効用の序数性」と言います<ref>塩沢修平『経済学・入門』、有斐閣、P60</ref>。書籍によっては便宜的に効用が数値で表される場合もありますが、しかしその数値はあくまで便宜的なものに過ぎず、数値の絶対的な大きさには意味は無い<ref>塩沢修平『経済学・入門』、有斐閣、P59</ref>、とのことです。 :※英語ではfirst やsecond やthird などの単語を「序数」と言いますが、つまり、集合の要素の順序関係を見るのが序数ですよね。 然し導関数として、ステーキの購入計画C とワインの購入計画D で、ステーキ1単位を購入することがある人にとってワイン何単位ぶんの購入に当たるかの計算は議論される。こうのような購入量1単位ごとの効用の換算値を、限界代替率と言います。 「効用」は、主観的な量です<ref>たとえば 塩沢『経済学入門』、P59 など。</ref>。つまり、効用の大きさは、それぞれの消費者の主観で決まります。 この効用と価格の関係に関する数理議論があるだろうが、現編集者はほとんど知らないので記述できない。一般の経済学入門書を見ても、そういう話題はまったく書かれていない、と、前編集者は書く。 効用自体も、消費量が1単位増えた時の効用の増加、限界効用も、関数の数値自体には大きな意味はないと見る。しかし財によって限界効用を比較したもの、限界代替率は、限界効用の数値を比較し、同じ満足度の消費量を見出す概念だとはいえる。 経済学者ヒックスはこの限界代替率に着目した研究を行ったという<ref>小室直樹『経済学をめぐる巨匠たち 経済思想ゼミナール』、ダイヤモンド社、2004年1月8日、P202およびP203</ref>。 もう一度書くが、限界効用とは,財を一単位追加して消費することによる効用の増加分だ。これは効用関数の微分と見ていいだろう<ref>小畑二郎『経済学の歴史』、慶應義塾大学出版会、2014年11月28日初版第1刷発行、P161</ref>。 さて、この効用関数は、単調増加で上に凸だろうか。ある種類の物があふれると、その物ひとつ当たりの価値は小さくなる(効用逓減(ていげん)の法則)。 水は生命活動に不可欠に限らず、ダイヤモンドより価格が安い<ref>小畑二郎『経済学の歴史』、慶應義塾大学出版会、2014年11月28日 初版 第1刷 発行、P172</ref>。同じ美術品を何度も鑑賞すると、慣れてきて価値を感じなくなる<ref>小畑二郎『経済学の歴史』、慶應義塾大学出版会、2014年11月28日 初版 第1刷 発行、P172</ref>。 財の消費だけではなく、人間の心理的または生理的な傾向としてこのような現象は見られますよね<ref>小畑二郎『経済学の歴史』、慶應義塾大学出版会、2014年11月28日初版第1刷発行、P172</ref>。 兎も角効用とは消費する側の議論だろう、一方で供給する側の視点も必要だ。労働がなければ多くの財は供給不可能だ。 ===サンクトペテルブルクの賭け=== さて、事実上は話題として少しそれるが、効用に関する議論として、18世紀前半、ロシアのサンクトペテルブルクに住んでいたスイスの数学者ダニエル・ベルヌーイが示した「サンクトペテルブルクの賭け」という面白い議論があるので、余談として紹介しておこう。 ここではこういうゲームを考える。一枚のコインを表が出るまで何回も投げ続ける。もらえる賞金は、1回目に表が出たら1ダカット(日本円で500円ぐらいだという)、1回目は裏が出て2回目に表が出たら倍の2ダカット、2回目まで裏が出ていて3回目に初めて表が出たらそのまた倍の4ダカット、3回目まで裏が出ていて4回目に初めて表が出たらそのまた倍の8ダカット、というふうに倍々で賞金は増えていく。 さて、この場合このゲームを売る胴元は、何ダカットでこの賭けを売ればよいだろうか? 普通ギャンブルのこういう議論では期待値を計算する。 期待値の例として、別の簡単なゲームを考えてみよう。 二人の人間がゲームに参加し、参加料として100円ずつ払う。じゃんけんをして勝った方が場に出た200円を総取りする。 この場合片方の参加者がじゃんけんに勝つ確率は 1/2、負ける確率は残り 1/2、200*1/2+0*1/2 で期待値は100円。参加料が100円だから、ゲームとしてはトントンだという事になる。 ここでもしゲームとしての胴元がいて、10円ずつ参加料から場所代を抜いていたら、賞金総額は 180円で、期待値は 90円。世によくある、胴元が確実に儲け、参加者が総体的には結局損をしているギャンブルになる。 さて、先のサンクトペテルブルクの賭けの賭けでは期待値はどうなるか。 まず最初に表が出る確率は 1/2。その時の賞金が 1ダカット。次に裏が出た後表が出る確率は、1/2*1/2=1/4。賞金は2ダカット。つぎは 1/8と 4ダカット。結局期待値は、 1/2+1/2+1/2+… となって∞に発散する。 つまりこれは圧倒的に胴元が不利なゲームのはずだ。いくらで売っても期待値は無限大だからね。 しかし実際このゲームを 16ダカットで売ったとしてみよう。 だとしたら、賞金が 8ダカット以下になる確率は 15/16。まずこれが起こる可能性が高いから、胴元が得するように思える。しかし問題は、 1/16だ。これは底なし沼だ。場合によっては胴元の資産を超えて負けることもある。ここがこのゲームの期待値が無限大で胴元に不利だと言える根拠になるだろう。 ベルヌーイ自身はここに効用の発想を取り入れて、議論を進めた。つまりダカット金貨の額面で判断せずに額面の満足度、効用を金額の対数と決めてみた。賞金の期待値は∞に発散するが、効用の期待値は一定の値になる。最初に表が出た時の額面が1で、効用をlog[2,1]=0とすると、裏→表で効用が log[2,2]=1、裏→裏→表で効用がlog[2,4]=2で期待値は0/2+1/4+2/8+3/16+4/32+… そしてこの無限級数は幾つになるかな? 現編集者は計算できなかった^^;;;。数学の得意な人が答えだしてください。兎に角 2のこの無限級数乗の金額が効用としての期待値での金額。気持ちとしてはゲーマーとしてはこれでトントンだという事か。対数を考えるという事は、金額が大きいほど増えてもそれほどありがたみを感じなくなるという事ですからね。 さらなる分析として、胴元がこの商売を人生で何回やるか、ゲーマーが何回するかがこの話の議論に関わってくるだろう。 == 脚注 == [[Category:経済学|*]] [[Category:書庫|けいさいかく]] [[en:Principles of Economics]] 9arl2ptx8vq2kgkx935dpzo3o6pxvl0 JavaScript 0 1471 263768 262045 2024-11-18T10:04:44Z Ef3 694 /* 目次 */ # [[/改廃された技術|改廃された技術]] 263768 wikitext text/x-wiki {{pathnav|メインページ|工学|情報技術|プログラミング|frame=1}} [[File:JavaScript.svg|thumb|right|200px|[[JavaScript/はじめに#Hello World|Hello, World!]]]] 本書は、JavaScriptの解説書です。JavaScriptは、ウェブページやウェブアプリケーションで広く使われているスクリプト言語であり、最も広く普及しているプログラミング言語の一つです。また、Node.jsなどのランタイム環境を使うことで、サーバーサイドでもJavaScriptを実行することができます。 本書では、初めてプログラミングをする人から、他の言語で経験を積んだ人まで、広く対象としています。基本的なJavaScriptの書き方を解説することで、読者がより深く理解できるように配慮しました。 JavaScriptは、初心者が学ぶのに最適なプログラミング言語であり、ブラウザだけで簡単にプログラムを作ることができます。言語のコア部分は、国際標準化団体であるEcmaインターナショナルによってECMAScriptとして標準化され、仕様が明確になっています。Node.jsなどのランタイム環境を使うことで、JavaScriptをより高度なアプリケーション開発にも利用できます。 == 目次 == {{進捗状況}} # [[JavaScript/はじめに|はじめに]] # [[JavaScript/文法|文法]] ## [[JavaScript/字句構造|字句構造]] ## [[JavaScript/セミコロンの自動挿入|セミコロンの自動挿入]] ## [[JavaScript/予約語|予約語]] # [[JavaScript/変数|変数]] # [[JavaScript/演算子|演算子]] # [[JavaScript/オブジェクト|オブジェクト]] # [[JavaScript/文字列|文字列]] # [[JavaScript/数値|数値]] # [[JavaScript/配列|配列]] # [[JavaScript/制御構造|制御構造]] # [[JavaScript/関数|関数]] # [[JavaScript/クラス|クラス]] # [[JavaScript/strictモード|strictモード]] # [[JavaScript/ビット演算|ビット演算]] # [[JavaScript/例外処理|例外処理]] # [[JavaScript/正規表現|正規表現]] # [[JavaScript/長整数|長整数]] # [[JavaScript/型付き配列|型付き配列]] # [[JavaScript/Polyfill|Polyfill]] # [[JavaScript/ブラウザ|ブラウザ]] # [[JavaScript/コードギャラリー|コードギャラリー]] # Web API {{---}} Web APIは、JavaScriptでWebブラウザを制御する標準的な手段であり、Webページに対して様々な操作(例えば、要素の追加や削除、イベントの処理、非同期通信等)を行うことができます。 ## [[JavaScript/Window|Windowオブジェクト]] ## [[JavaScript/DOM|DOM API]] ## [[JavaScript/Console|Console API]] ## [[JavaScript/Canvas|Canvas API]] ## [[JavaScript/XMLHttpRequest|Fetch API]] ## [[JavaScript/イベント処理|イベント処理]] ## [[JavaScript/クッキー|クッキー]] ## [[JavaScript/Audio API|Audio API]] # [[/改廃された技術|改廃された技術]] # ライブラリ(フレームワーク) ## [[JavaScript/ライブラリ|ライブラリ]] # [[JSON]] # [[JavaScript/XML|XML]] # リファレンス<!-- let ary = [], errors = [] for (x of Object.getOwnPropertyNames(globalThis)) { if (x == "Buffer") continue let prop = globalThis[x] if (1 || typeof prop === "function") { try { if ("prototype" in prop && "constructor" in prop.prototype) { // console.log("XXX ",x) ary.push(x) let obj = new prop() if (obj instanceof Error) errors.push(x) } } catch (err) { // console.log("Err: ", err) } } } ary.filter(x=>!errors.includes(x)).sort().forEach(x => console.log(`## [[JavaScript/${x}|${x}]]`)) errors.sort().forEach(x => console.log(`### [[JavaScript/${x}|${x}]]`)) ## [[JavaScript/Array|Array]] ## [[JavaScript/ArrayBuffer|ArrayBuffer]] ## [[JavaScript/BigInt|BigInt]] ## [[JavaScript/BigInt64Array|BigInt64Array]] ## [[JavaScript/BigUint64Array|BigUint64Array]] ## [[JavaScript/Boolean|Boolean]] ## [[JavaScript/DataView|DataView]] ## [[JavaScript/Date|Date]] ## [[JavaScript/FinalizationRegistry|FinalizationRegistry]] ## [[JavaScript/Float32Array|Float32Array]] ## [[JavaScript/Float64Array|Float64Array]] ## [[JavaScript/Function|Function]] ## [[JavaScript/Int16Array|Int16Array]] ## [[JavaScript/Int32Array|Int32Array]] ## [[JavaScript/Int8Array|Int8Array]] ## [[JavaScript/Map|Map]] ## [[JavaScript/Number|Number]] ## [[JavaScript/Object|Object]] ## [[JavaScript/Promise|Promise]] ## [[JavaScript/RegExp|RegExp]] ## [[JavaScript/Set|Set]] ## [[JavaScript/SharedArrayBuffer|SharedArrayBuffer]] ## [[JavaScript/String|String]] ## [[JavaScript/Symbol|Symbol]] ## [[JavaScript/TextDecoder|TextDecoder]] ## [[JavaScript/TextEncoder|TextEncoder]] ## [[JavaScript/URL|URL]] ## [[JavaScript/URLSearchParams|URLSearchParams]] ## [[JavaScript/Uint16Array|Uint16Array]] ## [[JavaScript/Uint32Array|Uint32Array]] ## [[JavaScript/Uint8Array|Uint8Array]] ## [[JavaScript/Uint8ClampedArray|Uint8ClampedArray]] ## [[JavaScript/WeakMap|WeakMap]] ## [[JavaScript/WeakRef|WeakRef]] ## [[JavaScript/WeakSet|WeakSet]] ## [[JavaScript/clearImmediate|clearImmediate]] ## [[JavaScript/clearInterval|clearInterval]] ## [[JavaScript/clearTimeout|clearTimeout]] ## [[JavaScript/queueMicrotask|queueMicrotask]] ## [[JavaScript/setImmediate|setImmediate]] ## [[JavaScript/setInterval|setInterval]] ## [[JavaScript/setTimeout|setTimeout]] ### [[JavaScript/Error|Error]] ### [[JavaScript/EvalError|EvalError]] ### [[JavaScript/RangeError|RangeError]] ### [[JavaScript/ReferenceError|ReferenceError]] ### [[JavaScript/SyntaxError|SyntaxError]] ### [[JavaScript/TypeError|TypeError]] ### [[JavaScript/URIError|URIError]] --> ## [[JavaScript/Global|Global]] ## [[JavaScript/Array|Array]] ## [[JavaScript/BigInt|BigInt]] ## [[JavaScript/Boolean|Boolean]] ## [[JavaScript/Date|Date]] ## [[JavaScript/FinalizationRegistry|FinalizationRegistry]] ## [[JavaScript/Function|Function]] ## [[JavaScript/Map|Map]] ## [[JavaScript/WeakMap|WeakMap]] ## [[JavaScript/Math|Math]] ## [[JavaScript/Number|Number]] ## [[JavaScript/Object|Object]] ## [[JavaScript/Promise|Promise]] ## [[JavaScript/RegExp|RegExp]] ## [[JavaScript/Set|Set]] ## [[JavaScript/WeakSet|WeakSet]] ## [[JavaScript/String|String]] ## [[JavaScript/Symbol|Symbol]] ## [[JavaScript/WeakRef|WeakRef]] ## [[JavaScript/Error|Error]] ### [[JavaScript/EvalError|EvalError]] ### [[JavaScript/RangeError|RangeError]] ### [[JavaScript/ReferenceError|ReferenceError]] ### [[JavaScript/SyntaxError|SyntaxError]] ### [[JavaScript/TypeError|TypeError]] ### [[JavaScript/URIError|URIError]] ## [[JavaScript/Intl|Intl]] == Javaとの関連性 == JavaScriptとJavaは名前が似ていますが、実際にはかなり異なるプログラミング言語です。それぞれの特徴と関連性について簡潔に説明します。 # '''起源と命名''' #: JavaScriptは当初、Java言語の人気にあやかって名付けられました。 #: しかし、両言語の開発元は異なります(JavaScriptはNetscape、JavaはSun Microsystems)。 # '''言語の特徴''' #: JavaScript: 主にWeb開発用の動的型付け言語。 #: Java: 汎用的な静的型付け言語。 # '''実行環境''' #: JavaScript: 主にブラウザ上で動作(Node.jsなどサーバーサイドも可能)。 #: Java: 主にサーバーサイドやデスクトップアプリケーションで使用。 # '''構文''' #: 一部の構文(ループ、条件文、演算子など)に類似点がありますが、全体的な言語設計は大きく異なります。 # '''オブジェクト指向''' #: 両言語ともオブジェクト指向をサポートしていますが、実装方法が異なります。 #: JavaScript: プロトタイプベースのオブジェクト指向言語。 #: Java: クラスベースのオブジェクト指向言語。 # '''相互運用性''' #: 完全に別々の言語であり、直接的な互換性はありません。 # '''用途''' #: JavaScriptはWeb開発、特にフロントエンド開発で主に使用されます。 #: Javaは大規模なエンタープライズアプリケーション、Androidアプリ開発などに使用されます。 結論として、JavaScriptとJavaは名前の類似性以外に深い関連性はありません。それぞれが異なる目的と設計思想を持つ独立した言語です。 == JavaScriptの応用範囲 == JavaScriptは、Web開発において最も広く使用される言語の一つであり、以下のような応用範囲があります。 * クライアントサイドWeb開発:JavaScriptは、Webブラウザで動作するクライアントサイドのWebアプリケーション開発に使用されます。JavaScriptを使用することで、ユーザーがWebページやWebアプリケーションを対話的に操作することができます。 * サーバーサイドWeb開発:Node.jsを使用することで、JavaScriptはサーバーサイドのWebアプリケーション開発にも使用されます。Node.jsは、JavaScriptを実行するためのランタイム環境であり、サーバーサイドでのWebアプリケーションの実行や、データベースやファイルシステムなどのI/O操作を実行することができます。 * モバイルアプリケーション開発:React Nativeを使用することで、JavaScriptはモバイルアプリケーション開発にも使用されます。React Nativeは、JavaScriptを使用してiOSやAndroidのネイティブモバイルアプリケーションを開発するためのフレームワークです。 * デスクトップアプリケーション開発:Electronを使用することで、JavaScriptはデスクトップアプリケーション開発にも使用されます。Electronは、JavaScriptを使用して、Windows、Mac、Linuxなどのデスクトップアプリケーションを開発するためのフレームワークです。 * ゲーム開発:JavaScriptは、Webブラウザ上で動作するゲーム開発にも使用されます。HTML5 CanvasやWebGLなどのWeb技術を使用することで、高品質のWebゲームを開発することができます。 JavaScriptは、Web技術を中心に広く使用される言語であり、多くの場面で使用されています。これらの応用範囲は、今後も拡大することが予想されます。 == 派生言語 == JavaScriptの派生言語には、以下のようなものがあります。 === TypeScript === {{main|TypeScript}} Microsoftが開発したJavaScriptのスーパーセットであり、静的型付けやクラス、インターフェースなどの機能を追加しています。 ;TypeScriptのコード例:<syntaxhighlight lang=ts> function greet(name: string) { console.log(`Hello, ${name}!`); } greet("John"); </syntaxhighlight> === JavaScript XML === JavaScript XML(JSX)は、JavaScriptの拡張構文であり、Reactフレームワークで一般的に使用されます。JSXは、HTMLライクな構文をJavaScriptコードに埋め込むことができ、Reactコンポーネントの宣言的な記述やUIの構築を簡素化します。 JSXでは、<code><nowiki><div></nowiki></code>や<code><nowiki><span></nowiki></code>などのHTML要素をJavaScriptコード内で直接記述できます。これにより、コンポーネント階層構造を視覚的に表現し、リーダブルで保守しやすいコードを記述できます。また、JavaScriptの変数や式を<code>{}</code>で囲んで埋め込むことができ、動的な値をレンダリングすることができます。 例えば、以下はJSXを使用してReactコンポーネントを宣言的に記述する例です: ;JavaScript XMLのコード例:<syntaxhighlight lang=jsx> import React from 'react'; const Greeting = ({ name }) => { return ( <div> <h1>Hello, {name}!</h1> <p>Welcome to JSX.</p> </div> ); }; export default Greeting; </syntaxhighlight> この例では、<code>Greeting</code>コンポーネントが<code>name</code>プロパティを受け取り、JSX内でその値を表示しています。JSXはReactにおいて、UIを構築するためのシンタックスシュガーとして広く採用され、Reactの開発者がより効果的かつ可読性の高いコードを書くのに役立ちます。 === TypeScript XML === TypeScript XML(TSX)は、Reactアプリケーションのためのファイル拡張子で、[[#TypeScript|TypeScript]]を使用してReactコンポーネントを記述するための構文です。TSXファイルは、JSX(JavaScript XML)とTypeScriptの機能を組み合わせたもので、静的型チェックとReactコンポーネントの記述を同時に行うことができます。 TSXでは、Reactコンポーネントを定義するために、JSXの構文を使用します。この構文は、HTMLライクな要素構造をJavaScriptやTypeScriptのコード内に埋め込むためのもので、UIを宣言的かつコンパクトに記述できます。また、TypeScriptの型システムを活用して、コンポーネントのプロパティやステートに関する型情報を提供できます。 例えば、以下は簡単なReactコンポーネントを含むTSXファイルの例です: ;TypeScript XMLのコード例:<syntaxhighlight lang=react> import React, { useState } from 'react'; interface CounterProps { initialValue: number; } const Counter: React.FC<CounterProps> = ({ initialValue }) => { const [count, setCount] = useState(initialValue); const increment = () => setCount(count + 1); const decrement = () => setCount(count - 1); return ( <div> <p>Count: {count}</p> <button onClick={increment}>Increment</button> <button onClick={decrement}>Decrement</button> </div> ); }; export default Counter; </syntaxhighlight> この例では、<code>Counter</code>コンポーネントが<code>CounterProps</code>型のプロパティを受け取り、ステートとして<code>count</code>を持っています。JSX内で<code>{}</code>を使用してJavaScriptやTypeScriptのコードを埋め込むことができ、動的なUIを構築できます。 === CoffeeScript === JavaScriptの文法をより簡潔にした言語で、コードを読みやすくするための構文糖衣を提供します。 ;CoffeeScriptのコード例:<syntaxhighlight lang=coffeescript> greet = (name) -> console.log "Hello, #{name}!" greet "John" </syntaxhighlight> == 参考文献 == * [https://262.ecma-international.org/5.1/ Standard ECMA-262 5.1 Edition / June 2011 ECMAScript® Language Specification]([https://es5.github.io 注釈版]) * [https://262.ecma-international.org/6.0/ Standard ECMA-262 6th Edition / June 2015 ECMAScript® 2015 Language Specification] * [https://tc39.es/ecma262/ Draft ECMA-262 ECMAScript® Language Specification] * [https://402.ecma-international.org/ ECMA-402 7th Edition / June 2020 ECMAScript® 2020 Internationalization API Specification] === 標準API === * [https://html.spec.whatwg.org/ HTML Living Standard] * [https://dom.spec.whatwg.org/ DOM Living Standard] * [https://console.spec.whatwg.org/ Console Living Standard] * [https://xhr.spec.whatwg.org/ XMLHttpRequest Living Standard] Ajax * [https://fetch.spec.whatwg.org/ Fetch Living Standard] * [https://fullscreen.spec.whatwg.org/ Fullscreen API Living Standard] * [https://infra.spec.whatwg.org/ Infra Living Standard] * [https://compat.spec.whatwg.org/ Compatibility Living Standard] * [https://storage.spec.whatwg.org/ Storage Living Standard] * [https://streams.spec.whatwg.org/ Streams Living Standard] * [https://encoding.spec.whatwg.org/ Encoding Living Standard] * [https://mimesniff.spec.whatwg.org/ MIME Sniffing Living Standard] * [https://notifications.spec.whatwg.org/ Notifications API Living Standard] * [https://url.spec.whatwg.org/ URL Living Standard] * [https://w3c.github.io/mediasession/ Media Session Standard] == 関連項目 == * [[JSDoc]] == 下位階層のページ == {{特別:前方一致ページ一覧/JavaScript}} == 外部リンク == {{wikipedia}} {{wikiversity|Topic:Javascript|JavaScript}} * [//developer.mozilla.org/ja/docs/Web/JavaScript JavaScript - MDN] [[Category:JavaScript|*]] [[Category:プログラミング言語]] [[Category:World Wide Web]] {{NDC|007.64}} jjc3qani29d2nymdn3zwy98saoh3wu1 Perl 0 1611 263772 261282 2024-11-18T10:10:24Z Ef3 694 # [[/改廃された技術|改廃された技術]] 263772 wikitext text/x-wiki {{Pathnav|メインページ|工学|情報技術|プログラミング|frame=1}} {{Wikipedia|Perl}} Perlは、広く使用されているプログラミング言語の1つです。その名前は、"Practical Extraction and Reporting Language"の頭字語から来ています。Perlは、UNIXシステムで最初に開発されたため、テキスト処理に適しています。Perlは、Web開発、システム管理、自動化、データ処理、バイオインフォマティクスなどのさまざまな用途で使用されています。 このPerlの教科書では、Perlの基本的な構文や制御構造、ファイル入出力、テキスト処理、正規表現、モジュールの作成などについて学ぶことができます。また、Webアプリケーションの開発に必要なCGIプログラミングや、データベースとの連携についても学ぶことができます。 Perlは、豊富な機能と柔軟性を備えたプログラミング言語であり、簡潔なコードで多くの作業を行うことができます。この教科書を通じて、Perlを効果的に活用するための基礎知識を身につけることができます。 # [[/はじめに|はじめに]] ## [[/はじめに#前提条件|前提条件]] ## [[/はじめに#実行環境|実行環境]] ## [[/はじめに#作成、実行の流れ|作成、実行の流れ]] ## [[/はじめに#Perlの基本機能の紹介|Perlの基本機能の紹介]] # [[/制御構造|制御構造]] ## [[/制御構造#条件分岐|条件分岐]] ## [[/制御構造#ループ構造|ループ構造]] ## [[/制御構造#ループ制御|ループ制御]] # [[/変数、データ構造|変数、データ構造]] ## [[/変数、データ構造#変数とは|変数とは]] ## [[/変数、データ構造#記法|記法]] ## [[/変数、データ構造#利用法|利用法]] ## [[/変数、データ構造#特殊変数|特殊変数]] ## [[/変数、データ構造#コンテキスト|コンテキスト]] # [[/演算子|演算子]] ## [[/演算子#代入演算子|代入演算子 <nowiki>=</nowiki>]] ## [[/演算子#算術演算子|算術演算子 + - / * % ** ++ --]] ## [[/演算子#文字列演算子|文字列演算子 . x]] ## [[/演算子#クオート演算子|クオート演算子 <nowiki>q qq ' " qw qr qx</nowiki>]] ## [[/演算子#ビット演算子|ビット演算子 <nowiki>| & ~ >> << </nowiki>]] ## [[/演算子#論理演算子|論理演算子 or and || &&]] ## [[/演算子#数値比較演算子|数値比較演算子 <nowiki>< > <= >= == != <=> </nowiki>]] ## [[/演算子#文字列比較演算子|文字列比較演算子 eq ne le ge lt gt cmp]] ## [[/演算子#範囲演算子|範囲演算子 ..]] ## [[/演算子#置換演算子|置換演算子 s/// tr/// y///]] # [[/関数|関数]] ## [[/関数#組み込み関数|組み込み関数]] ## [[/関数#ユーザ定義関数(サブルーチン)|ユーザ定義関数(サブルーチン)]] ## [[/関数#引数・返り値とコンテキスト|引数・返り値とコンテキスト]] # [[/入出力・コマンドラインオプション|入出力・コマンドラインオプション]] ## [[/入出力・コマンドラインオプション#ファイルハンドル|ファイルハンドル]] ## [[/入出力・コマンドラインオプション#コマンドラインオプション|コマンドラインオプション]] ## [[/入出力・コマンドラインオプション#環境変数|環境変数]] # [[/正規表現|正規表現]] ## [[/正規表現#基礎|基礎]] # [[/リファレンス|リファレンス]] ## [[/リファレンス#多次元配列|多次元配列]] ## [[/リファレンス#リファレンス|リファレンス]] ### [[/リファレンス#スカラのリファレンス|スカラのリファレンス]] ### [[/リファレンス#配列のリファレンス|配列のリファレンス]] ### [[/リファレンス#ハッシュのリファレンス|ハッシュのリファレンス]] ### [[/リファレンス#サブルーチンのリファレンス|サブルーチンのリファレンス]] ### [[/リファレンス#正規表現のリファレンス|正規表現のリファレンス]] # [[/改廃された技術|改廃された技術]] # [[/class|クラス構文]] # [[/ライブラリ・モジュールとオブジェクト指向|ライブラリ・モジュールとオブジェクト指向]] ## [[/ライブラリ・モジュールとオブジェクト指向#ライブラリ・モジュール|ライブラリ・モジュール]] ### [[/ライブラリ・モジュールとオブジェクト指向#プラグマ|プラグマ]] ### [[/ライブラリ・モジュールとオブジェクト指向#標準ライブラリ|標準ライブラリ]] ### [[/ライブラリ・モジュールとオブジェクト指向#CPAN|CPAN]] ### [[/ライブラリ・モジュールとオブジェクト指向#ライブラリを作成する|ライブラリを作成する]] ## [[/ライブラリ・モジュールとオブジェクト指向#Perlとオブジェクト指向|Perlとオブジェクト指向]] ### [[/ライブラリ・モジュールとオブジェクト指向#オブジェクト指向Perlの前提知識|オブジェクト指向Perlの前提知識]] ### [[/ライブラリ・モジュールとオブジェクト指向#オブジェクト指向Perlの記述例|オブジェクト指向Perlの記述例]] ### [[/ライブラリ・モジュールとオブジェクト指向#コンストラクタ|コンストラクタ]] ### [[/ライブラリ・モジュールとオブジェクト指向#オブジェクト|オブジェクト]] ### [[/ライブラリ・モジュールとオブジェクト指向#クラス|クラス]] ### [[/ライブラリ・モジュールとオブジェクト指向#メソッド|メソッド]] ### [[/ライブラリ・モジュールとオブジェクト指向#メンバ|メンバ]] ### [[/ライブラリ・モジュールとオブジェクト指向#継承|継承]] # [[/例外処理|例外処理]] # [[/日本語処理|日本語処理]] # [[/ウェブアプリケーション|ウェブアプリケーション]] ## [[CGI]] ## [[Perl/CGI]] # [[/ヘルプ・ドキュメント|ヘルプ・ドキュメント]] # [[/附録|附録]] == 外部リンク == ;CPAN :[1] https://www.cpan.org/ ;日本語perldoc :[2] https://perldoc.jp/ [[Category:プログラミング言語]] [[Category:Perl|*]] {{stub}} {{NDC|007.64}} tdihn7jha1kcg3eaj8svl24vst957e8 東京理科大対策 0 3035 263769 206237 2024-11-18T10:06:17Z Ayhxuknbsijceivzdjhswh 66317 263769 wikitext text/x-wiki {{wikipedia|東京理科大学}} *[[日本の大学受験ガイド]] > [[東京理科大対策]] 本項は、[[w:東京理科大学|東京理科大学]]の入学試験対策に関する事項である。 東京理科大学は、東京都にある理工系総合大学である。文系学部は経営学部だけである。略称は「理科大」。 理科大の入試問題は計算力・思考力を問う良問が多い。理系学部の入試科目は英語、数学、理科(地学以外から一科目選択)である。早慶や旧帝国大、東工大の理・工学部の併願として受験する場合、特別な対策は不要だが、農学部、医療系学部との併願である場合、問題の質が異なるので対策が必要。実質倍率はどの学部も3~4倍程度である。 = 個別入試(B方式) = == 理系学部 == === 英語 === (60分)数学や理科に比べると英語の問題は総じて平易だが、下記の特徴を持つ。 * 他大学と比べて長文が長く、整序英作文も難易度が高いため、それらへの対策が必要である。なお整序英作文は、配点が全体の3割を占める年(2008年)もある。 * 年によって文法問題が見受けられないこともあるが、多くは長文問題に隠れて重複している。 * 整序英作文以外は概ね平易なので、まずは基本文法、語彙をマスターすることが重要。 * 長文は大抵、受験する学科に関連した英文が出るため、志望学科の専門領域に関連した語彙を覚えること。文学部向けの小説読解や社会問題読解などに時間を費やす必要はない。 ===理系数学 === (100分)良問が多いが、解法パターンを暗記しただけの勉強法では解けない。マーク式+記述の併用試験である。解法の理解を前提として、それらを応用する力が問われる。数IIIの出題が多く、微分積分、数列、三角関数がよく出題される。この領域に関してはかなりの習熟度が必要である。学部学科での難易度の差が激しい。先進工学部の問題は易~標準程度の為満点争いになる。工学部や数学科専用の問題の難易度は極めて高い。 繁雑な計算を長々とさせられた挙句に出る答えが,ルートの中に t の4次式が入るなど汚いものであることが多いが,それに惑わされずに解き進めてゆく必要があろう。 === 理科 === (80分)物理・化学・生物の中から1科目選択して受験する。学部学科によっては、指定された科目を受験する。 ====物理==== 力学、熱力学、波動、電磁気の分野からよく出題される。洗練された良問が多く、難易度の高い問題も出るが、悪問や奇問は出題されない。知識よりも思考力を試す問題である。 ====化学==== 化学に対する基本的な理解、および素早い計算力が問われることが多い。計算量は多い。 ; 【理学部】 : 計算力重視の問題が多い。知識問題での失点を最小限にとどめ、計算問題でどれだけ粘れるかが大切である。特に化学科受験生は計算練習をしっかりとしておくことが大切である。最近は無機化学の出題頻度は少ないが、対策しないで受験することは望ましくない。 ; 【薬学部】 : 化学の配点が大きいので化学の出来が合否に大きく影響する。有機化学の分量がやや多い。知識問題が多いが有機の知識問題では高度なものが出題されることがある。過去問に類似していることが多いので過去問対策は重要である。 ; 【工学部】 : 理学部に比べると知識問題の割合は多いが、計算量の多い問題もあるので素早く正確に解くことが重要である。 ; 【理工学部】 : 他の学部に比べると知識問題の分量が多い。高得点が取りやすいので7割以上は確実に取りたい。 ====生物==== 分子生物学領域の問題が多い。応用生物科学科では遺伝の計算問題が出題されることもあり、思考力と計算力が問われる。知識問題は少ない。限られた時間で問題文を適切に判断、計算していく能力が問われる。生物工学科は応用生物科学科よりシンプルな問題が多い。現象に対する理解を確認するだけではなく、それらを応用する力が求められるため、暗記型の学習では対応できない。 ==経営学部== 経営学部は学科によって入試方式が微妙に異なっている。 ・経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)。 3教科のうち、高得点の2科目を1.5倍にして、合否判定する。 ・国際デザイン経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(200)。 ・ビジネスエコノミクス学科は2~3教科(300点満点)である。 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)を必須科目とし、最後の1科目は 《国語》国語総合・現代文B(古文・漢文を除く)(100)、と 《数学》数I・数A・数II・数B(数列・ベクトル)・数III(100)の中から1科目を選択する。 東京理科大学経営学部は都内キャンパスへの全面移転により競争率が近年上昇している。 ===英語=== 必須科目。理系学部の「英語」を参照。 ===選択科目1=== 国語か理系数学(3Cまで)から1科目選択する。 '''国語'''<br /> 全国の国語の入試問題の中でも、驚くほどの長い文章を課す。その分量は大問1つにつき、本文は10ページにも及ぶものである。大問構成は大問2つでどちらも前述した量の文章量である。記述式の設問が多いので、思考力が試される。今までは試験時間が100分であったが2016年度の入試から試験時間が80分になってしまった。その2016年の入試では大問1つにつき8ページから9ページ程に文章量は減ったが、設問数は変わらず時間内に終わらせるには相当至難な問題となっていた。2017年度以降に注目である。受験生は読解速度の向上と記述式の設問に慣れ、解答速度を上げておく必要がある。本文本文の諺や国文法に関する知識も問われ、単独での古文、漢文の出題は例年見受けられないものの、現古融合文は年によって課されるため、古文と漢文の学習は必須である。 '''理系数学'''<br /> 理系学部の「理系数学」を参照。 ===選択科目2=== 数学(2B) '''文系数学'''<br /> 理系数学に比べると平易。 = センター試験利用入試(A方式) = センター試験の成績のみで合否を決める入試である。 *'''理系学部''' 国語、数学ⅠA・ⅡB、英語(リスニングあり)、理科1科目のセンター試験5科目の成績が求められる。合格するには、薬学部で85%、その他の学部学科で75%~82%必要である。 *'''経営学部''' 英語+3科目選択のセンター試験4科目の成績が求められる。合格するには80%必要である。 = センター試験+個別入試(C方式) = センター試験の成績と個別入試の成績の合計で合否を決める入試である。 *'''理系学部''' 国語、英語(リスニングあり)のセンター試験2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。 *'''経営学部''' 国語、英語(リスニングあり)のセンター試験2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。ただし、個別入試では理科を受験せず、数学の1科目だけの受験も可能である。その場合は、数学の得点が2倍される。 = 外部サイト = *[http://www.tus.ac.jp/ 理科大公式サイト] [[Category:大学入試|とうきようりかたいたいさく]] 10i6vzuhera1znevom2zcg15lcaac5p 263770 263769 2024-11-18T10:07:12Z Ayhxuknbsijceivzdjhswh 66317 /* 化学 */ 263770 wikitext text/x-wiki {{wikipedia|東京理科大学}} *[[日本の大学受験ガイド]] > [[東京理科大対策]] 本項は、[[w:東京理科大学|東京理科大学]]の入学試験対策に関する事項である。 東京理科大学は、東京都にある理工系総合大学である。文系学部は経営学部だけである。略称は「理科大」。 理科大の入試問題は計算力・思考力を問う良問が多い。理系学部の入試科目は英語、数学、理科(地学以外から一科目選択)である。早慶や旧帝国大、東工大の理・工学部の併願として受験する場合、特別な対策は不要だが、農学部、医療系学部との併願である場合、問題の質が異なるので対策が必要。実質倍率はどの学部も3~4倍程度である。 = 個別入試(B方式) = == 理系学部 == === 英語 === (60分)数学や理科に比べると英語の問題は総じて平易だが、下記の特徴を持つ。 * 他大学と比べて長文が長く、整序英作文も難易度が高いため、それらへの対策が必要である。なお整序英作文は、配点が全体の3割を占める年(2008年)もある。 * 年によって文法問題が見受けられないこともあるが、多くは長文問題に隠れて重複している。 * 整序英作文以外は概ね平易なので、まずは基本文法、語彙をマスターすることが重要。 * 長文は大抵、受験する学科に関連した英文が出るため、志望学科の専門領域に関連した語彙を覚えること。文学部向けの小説読解や社会問題読解などに時間を費やす必要はない。 ===理系数学 === (100分)良問が多いが、解法パターンを暗記しただけの勉強法では解けない。マーク式+記述の併用試験である。解法の理解を前提として、それらを応用する力が問われる。数IIIの出題が多く、微分積分、数列、三角関数がよく出題される。この領域に関してはかなりの習熟度が必要である。学部学科での難易度の差が激しい。先進工学部の問題は易~標準程度の為満点争いになる。工学部や数学科専用の問題の難易度は極めて高い。 繁雑な計算を長々とさせられた挙句に出る答えが,ルートの中に t の4次式が入るなど汚いものであることが多いが,それに惑わされずに解き進めてゆく必要があろう。 === 理科 === (80分)物理・化学・生物の中から1科目選択して受験する。学部学科によっては、指定された科目を受験する。 ====物理==== 力学、熱力学、波動、電磁気の分野からよく出題される。洗練された良問が多く、難易度の高い問題も出るが、悪問や奇問は出題されない。知識よりも思考力を試す問題である。 ====化学==== 化学に対する基本的な理解、および素早い計算力が問われることが多い。計算量は多い。 ; 【理学部】 : 計算力重視の問題が多い。知識問題での失点を最小限にとどめ、計算問題でどれだけ粘れるかが大切である。特に化学科受験生は計算練習をしっかりとしておくことが大切である。最近は無機化学の出題頻度は少ないが、対策しないで受験することは望ましくない。 ; 【薬学部】 : 化学の配点が大きいので化学の出来が合否に大きく影響する。有機化学の分量がやや多い。知識問題が多いが有機の知識問題では高度なものが出題されることがある。過去問に類似していることが多いので過去問対策は重要である。 ; 【工学部】 : 理学部に比べると知識問題の割合は多いが、計算量の多い問題もあるので素早く正確に解くことが重要である。 ; 【創域理工学部】 : 他の学部に比べると知識問題の分量が多い。高得点が取りやすいので7割以上は確実に取りたい。 ====生物==== 分子生物学領域の問題が多い。応用生物科学科では遺伝の計算問題が出題されることもあり、思考力と計算力が問われる。知識問題は少ない。限られた時間で問題文を適切に判断、計算していく能力が問われる。生物工学科は応用生物科学科よりシンプルな問題が多い。現象に対する理解を確認するだけではなく、それらを応用する力が求められるため、暗記型の学習では対応できない。 ==経営学部== 経営学部は学科によって入試方式が微妙に異なっている。 ・経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)。 3教科のうち、高得点の2科目を1.5倍にして、合否判定する。 ・国際デザイン経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(200)。 ・ビジネスエコノミクス学科は2~3教科(300点満点)である。 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)を必須科目とし、最後の1科目は 《国語》国語総合・現代文B(古文・漢文を除く)(100)、と 《数学》数I・数A・数II・数B(数列・ベクトル)・数III(100)の中から1科目を選択する。 東京理科大学経営学部は都内キャンパスへの全面移転により競争率が近年上昇している。 ===英語=== 必須科目。理系学部の「英語」を参照。 ===選択科目1=== 国語か理系数学(3Cまで)から1科目選択する。 '''国語'''<br /> 全国の国語の入試問題の中でも、驚くほどの長い文章を課す。その分量は大問1つにつき、本文は10ページにも及ぶものである。大問構成は大問2つでどちらも前述した量の文章量である。記述式の設問が多いので、思考力が試される。今までは試験時間が100分であったが2016年度の入試から試験時間が80分になってしまった。その2016年の入試では大問1つにつき8ページから9ページ程に文章量は減ったが、設問数は変わらず時間内に終わらせるには相当至難な問題となっていた。2017年度以降に注目である。受験生は読解速度の向上と記述式の設問に慣れ、解答速度を上げておく必要がある。本文本文の諺や国文法に関する知識も問われ、単独での古文、漢文の出題は例年見受けられないものの、現古融合文は年によって課されるため、古文と漢文の学習は必須である。 '''理系数学'''<br /> 理系学部の「理系数学」を参照。 ===選択科目2=== 数学(2B) '''文系数学'''<br /> 理系数学に比べると平易。 = センター試験利用入試(A方式) = センター試験の成績のみで合否を決める入試である。 *'''理系学部''' 国語、数学ⅠA・ⅡB、英語(リスニングあり)、理科1科目のセンター試験5科目の成績が求められる。合格するには、薬学部で85%、その他の学部学科で75%~82%必要である。 *'''経営学部''' 英語+3科目選択のセンター試験4科目の成績が求められる。合格するには80%必要である。 = センター試験+個別入試(C方式) = センター試験の成績と個別入試の成績の合計で合否を決める入試である。 *'''理系学部''' 国語、英語(リスニングあり)のセンター試験2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。 *'''経営学部''' 国語、英語(リスニングあり)のセンター試験2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。ただし、個別入試では理科を受験せず、数学の1科目だけの受験も可能である。その場合は、数学の得点が2倍される。 = 外部サイト = *[http://www.tus.ac.jp/ 理科大公式サイト] [[Category:大学入試|とうきようりかたいたいさく]] 98d6swjkfwicr7k2dr0d27wg47pqbtn 263773 263770 2024-11-18T10:10:49Z Ayhxuknbsijceivzdjhswh 66317 263773 wikitext text/x-wiki {{wikipedia|東京理科大学}} *[[日本の大学受験ガイド]] > [[東京理科大対策]] 本項は、[[w:東京理科大学|東京理科大学]]の入学試験対策に関する事項である。 東京理科大学は、東京都にある理工系総合大学である。文系学部は経営学部だけである。略称は「理科大」。 理科大の入試問題は計算力・思考力を問う良問が多い。理系学部の入試科目は英語、数学、理科(地学以外から一科目選択)である。早慶や旧帝国大、東工大の理・工学部の併願として受験する場合、特別な対策は不要だが、農学部、医療系学部との併願である場合、問題の質が異なるので対策が必要。実質倍率はどの学部も3~4倍程度である。 = 個別入試(B方式) = == 理系学部 == === 英語 === (60分)数学や理科に比べると英語の問題は総じて平易だが、下記の特徴を持つ。 * 他大学と比べて長文が長く、整序英作文も難易度が高いため、それらへの対策が必要である。なお整序英作文は、配点が全体の3割を占める年(2008年)もある。 * 年によって文法問題が見受けられないこともあるが、多くは長文問題に隠れて重複している。 * 整序英作文以外は概ね平易なので、まずは基本文法、語彙をマスターすることが重要。 * 長文は大抵、受験する学科に関連した英文が出るため、志望学科の専門領域に関連した語彙を覚えること。文学部向けの小説読解や社会問題読解などに時間を費やす必要はない。 ===理系数学 === (100分)良問が多いが、解法パターンを暗記しただけの勉強法では解けない。マーク式+記述の併用試験である。解法の理解を前提として、それらを応用する力が問われる。数IIIの出題が多く、微分積分、数列、三角関数がよく出題される。この領域に関してはかなりの習熟度が必要である。学部学科での難易度の差が激しい。先進工学部の問題は易~標準程度の為満点争いになる。工学部や数学科専用の問題の難易度は極めて高い。 繁雑な計算を長々とさせられた挙句に出る答えが,ルートの中に t の4次式が入るなど汚いものであることが多いが,それに惑わされずに解き進めてゆく必要があろう。 === 理科 === (80分)物理・化学・生物の中から1科目選択して受験する。学部学科によっては、指定された科目を受験する。 ====物理==== 力学、熱力学、波動、電磁気の分野からよく出題される。洗練された良問が多く、難易度の高い問題も出るが、悪問や奇問は出題されない。知識よりも思考力を試す問題である。 ====化学==== 化学に対する基本的な理解、および素早い計算力が問われることが多い。計算量は多い。 ; 【理学部】 : 計算力重視の問題が多い。知識問題での失点を最小限にとどめ、計算問題でどれだけ粘れるかが大切である。特に化学科受験生は計算練習をしっかりとしておくことが大切である。最近は無機化学の出題頻度は少ないが、対策しないで受験することは望ましくない。 ; 【薬学部】 : 化学の配点が大きいので化学の出来が合否に大きく影響する。有機化学の分量がやや多い。知識問題が多いが有機の知識問題では高度なものが出題されることがある。過去問に類似していることが多いので過去問対策は重要である。 ; 【工学部】 : 理学部に比べると知識問題の割合は多いが、計算量の多い問題もあるので素早く正確に解くことが重要である。 ; 【創域理工学部】 : 他の学部に比べると知識問題の分量が多い。高得点が取りやすいので7割以上は確実に取りたい。 ====生物==== 分子生物学領域の問題が多い。応用生物科学科では遺伝の計算問題が出題されることもあり、思考力と計算力が問われる。知識問題は少ない。限られた時間で問題文を適切に判断、計算していく能力が問われる。生物工学科は応用生物科学科よりシンプルな問題が多い。現象に対する理解を確認するだけではなく、それらを応用する力が求められるため、暗記型の学習では対応できない。 ==経営学部== 経営学部は学科によって入試方式が微妙に異なっている。 ・経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)。 3教科のうち、高得点の2科目を1.5倍にして、合否判定する。 ・国際デザイン経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(200)。 ・ビジネスエコノミクス学科は2~3教科(300点満点)である。 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)を必須科目とし、最後の1科目は 《国語》国語総合・現代文B(古文・漢文を除く)(100)、と 《数学》数I・数A・数II・数B(数列・ベクトル)・数III(100)の中から1科目を選択する。 東京理科大学経営学部は都内キャンパスへの全面移転により競争率が近年上昇している。 ===英語=== 必須科目。理系学部の「英語」を参照。 ===選択科目1=== 国語か理系数学(3Cまで)から1科目選択する。 '''国語'''<br /> 全国の国語の入試問題の中でも、驚くほどの長い文章を課す。その分量は大問1つにつき、本文は10ページにも及ぶものである。大問構成は大問2つでどちらも前述した量の文章量である。記述式の設問が多いので、思考力が試される。今までは試験時間が100分であったが2016年度の入試から試験時間が80分になってしまった。その2016年の入試では大問1つにつき8ページから9ページ程に文章量は減ったが、設問数は変わらず時間内に終わらせるには相当至難な問題となっていた。2017年度以降に注目である。受験生は読解速度の向上と記述式の設問に慣れ、解答速度を上げておく必要がある。本文本文の諺や国文法に関する知識も問われ、単独での古文、漢文の出題は例年見受けられないものの、現古融合文は年によって課されるため、古文と漢文の学習は必須である。 '''理系数学'''<br /> 理系学部の「理系数学」を参照。 ===選択科目2=== 数学(2B) '''文系数学'''<br /> 理系数学に比べると平易。 = 共通テスト利用入試(A方式) = 共通テストの成績のみで合否を決める入試である。 *'''理系学部''' 数学ⅠA・ⅡB、英語、理科1科目+国語or情報の共通テスト科目の成績が求められる。合格するには、薬学部で85%、その他の学部学科で75%~82%必要である。 *'''経営学部''' 英数国+選択1科目(理科、社会、情報)の共通テストの成績が求められる。合格するには80%必要である。 = センター試験+個別入試(C方式) = センター試験の成績と個別入試の成績の合計で合否を決める入試である。 *'''理系学部''' 国語、英語(リスニングあり)のセンター試験2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。 *'''経営学部''' 国語、英語(リスニングあり)のセンター試験2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。ただし、個別入試では理科を受験せず、数学の1科目だけの受験も可能である。その場合は、数学の得点が2倍される。 = 外部サイト = *[http://www.tus.ac.jp/ 理科大公式サイト] [[Category:大学入試|とうきようりかたいたいさく]] 74s4gicz4lwya82smy5o65eemg2mnq8 263774 263773 2024-11-18T10:12:05Z Ayhxuknbsijceivzdjhswh 66317 /* 共通テスト+個別入試(C方式) */ 263774 wikitext text/x-wiki {{wikipedia|東京理科大学}} *[[日本の大学受験ガイド]] > [[東京理科大対策]] 本項は、[[w:東京理科大学|東京理科大学]]の入学試験対策に関する事項である。 東京理科大学は、東京都にある理工系総合大学である。文系学部は経営学部だけである。略称は「理科大」。 理科大の入試問題は計算力・思考力を問う良問が多い。理系学部の入試科目は英語、数学、理科(地学以外から一科目選択)である。早慶や旧帝国大、東工大の理・工学部の併願として受験する場合、特別な対策は不要だが、農学部、医療系学部との併願である場合、問題の質が異なるので対策が必要。実質倍率はどの学部も3~4倍程度である。 = 個別入試(B方式) = == 理系学部 == === 英語 === (60分)数学や理科に比べると英語の問題は総じて平易だが、下記の特徴を持つ。 * 他大学と比べて長文が長く、整序英作文も難易度が高いため、それらへの対策が必要である。なお整序英作文は、配点が全体の3割を占める年(2008年)もある。 * 年によって文法問題が見受けられないこともあるが、多くは長文問題に隠れて重複している。 * 整序英作文以外は概ね平易なので、まずは基本文法、語彙をマスターすることが重要。 * 長文は大抵、受験する学科に関連した英文が出るため、志望学科の専門領域に関連した語彙を覚えること。文学部向けの小説読解や社会問題読解などに時間を費やす必要はない。 ===理系数学 === (100分)良問が多いが、解法パターンを暗記しただけの勉強法では解けない。マーク式+記述の併用試験である。解法の理解を前提として、それらを応用する力が問われる。数IIIの出題が多く、微分積分、数列、三角関数がよく出題される。この領域に関してはかなりの習熟度が必要である。学部学科での難易度の差が激しい。先進工学部の問題は易~標準程度の為満点争いになる。工学部や数学科専用の問題の難易度は極めて高い。 繁雑な計算を長々とさせられた挙句に出る答えが,ルートの中に t の4次式が入るなど汚いものであることが多いが,それに惑わされずに解き進めてゆく必要があろう。 === 理科 === (80分)物理・化学・生物の中から1科目選択して受験する。学部学科によっては、指定された科目を受験する。 ====物理==== 力学、熱力学、波動、電磁気の分野からよく出題される。洗練された良問が多く、難易度の高い問題も出るが、悪問や奇問は出題されない。知識よりも思考力を試す問題である。 ====化学==== 化学に対する基本的な理解、および素早い計算力が問われることが多い。計算量は多い。 ; 【理学部】 : 計算力重視の問題が多い。知識問題での失点を最小限にとどめ、計算問題でどれだけ粘れるかが大切である。特に化学科受験生は計算練習をしっかりとしておくことが大切である。最近は無機化学の出題頻度は少ないが、対策しないで受験することは望ましくない。 ; 【薬学部】 : 化学の配点が大きいので化学の出来が合否に大きく影響する。有機化学の分量がやや多い。知識問題が多いが有機の知識問題では高度なものが出題されることがある。過去問に類似していることが多いので過去問対策は重要である。 ; 【工学部】 : 理学部に比べると知識問題の割合は多いが、計算量の多い問題もあるので素早く正確に解くことが重要である。 ; 【創域理工学部】 : 他の学部に比べると知識問題の分量が多い。高得点が取りやすいので7割以上は確実に取りたい。 ====生物==== 分子生物学領域の問題が多い。応用生物科学科では遺伝の計算問題が出題されることもあり、思考力と計算力が問われる。知識問題は少ない。限られた時間で問題文を適切に判断、計算していく能力が問われる。生物工学科は応用生物科学科よりシンプルな問題が多い。現象に対する理解を確認するだけではなく、それらを応用する力が求められるため、暗記型の学習では対応できない。 ==経営学部== 経営学部は学科によって入試方式が微妙に異なっている。 ・経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)。 3教科のうち、高得点の2科目を1.5倍にして、合否判定する。 ・国際デザイン経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(200)。 ・ビジネスエコノミクス学科は2~3教科(300点満点)である。 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)を必須科目とし、最後の1科目は 《国語》国語総合・現代文B(古文・漢文を除く)(100)、と 《数学》数I・数A・数II・数B(数列・ベクトル)・数III(100)の中から1科目を選択する。 東京理科大学経営学部は都内キャンパスへの全面移転により競争率が近年上昇している。 ===英語=== 必須科目。理系学部の「英語」を参照。 ===選択科目1=== 国語か理系数学(3Cまで)から1科目選択する。 '''国語'''<br /> 全国の国語の入試問題の中でも、驚くほどの長い文章を課す。その分量は大問1つにつき、本文は10ページにも及ぶものである。大問構成は大問2つでどちらも前述した量の文章量である。記述式の設問が多いので、思考力が試される。今までは試験時間が100分であったが2016年度の入試から試験時間が80分になってしまった。その2016年の入試では大問1つにつき8ページから9ページ程に文章量は減ったが、設問数は変わらず時間内に終わらせるには相当至難な問題となっていた。2017年度以降に注目である。受験生は読解速度の向上と記述式の設問に慣れ、解答速度を上げておく必要がある。本文本文の諺や国文法に関する知識も問われ、単独での古文、漢文の出題は例年見受けられないものの、現古融合文は年によって課されるため、古文と漢文の学習は必須である。 '''理系数学'''<br /> 理系学部の「理系数学」を参照。 ===選択科目2=== 数学(2B) '''文系数学'''<br /> 理系数学に比べると平易。 = 共通テスト利用入試(A方式) = 共通テストの成績のみで合否を決める入試である。 *'''理系学部''' 数学ⅠA・ⅡB、英語、理科1科目+国語or情報の共通テスト科目の成績が求められる。合格するには、薬学部で85%、その他の学部学科で75%~82%必要である。 *'''経営学部''' 英数国+選択1科目(理科、社会、情報)の共通テストの成績が求められる。合格するには80%必要である。 = 共通テスト+個別入試(C方式) = 共通テストの成績と個別入試の成績の合計で合否を決める入試である。 *'''理系学部''' 国語、英語の共通テスト2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。 *'''経営学部''' 国語、英語の共通テストと数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。ただし、個別入試では理科を受験せず、数学の1科目だけの受験も可能である。その場合は、数学の得点が2倍される。 = 外部サイト = *[http://www.tus.ac.jp/ 理科大公式サイト] [[Category:大学入試|とうきようりかたいたいさく]] 39jeq2r2rclt4o5lk9xkdnbfvvbto68 263775 263774 2024-11-18T10:15:46Z Ayhxuknbsijceivzdjhswh 66317 /* 物理 */ 263775 wikitext text/x-wiki {{wikipedia|東京理科大学}} *[[日本の大学受験ガイド]] > [[東京理科大対策]] 本項は、[[w:東京理科大学|東京理科大学]]の入学試験対策に関する事項である。 東京理科大学は、東京都にある理工系総合大学である。文系学部は経営学部だけである。略称は「理科大」。 理科大の入試問題は計算力・思考力を問う良問が多い。理系学部の入試科目は英語、数学、理科(地学以外から一科目選択)である。早慶や旧帝国大、東工大の理・工学部の併願として受験する場合、特別な対策は不要だが、農学部、医療系学部との併願である場合、問題の質が異なるので対策が必要。実質倍率はどの学部も3~4倍程度である。 = 個別入試(B方式) = == 理系学部 == === 英語 === (60分)数学や理科に比べると英語の問題は総じて平易だが、下記の特徴を持つ。 * 他大学と比べて長文が長く、整序英作文も難易度が高いため、それらへの対策が必要である。なお整序英作文は、配点が全体の3割を占める年(2008年)もある。 * 年によって文法問題が見受けられないこともあるが、多くは長文問題に隠れて重複している。 * 整序英作文以外は概ね平易なので、まずは基本文法、語彙をマスターすることが重要。 * 長文は大抵、受験する学科に関連した英文が出るため、志望学科の専門領域に関連した語彙を覚えること。文学部向けの小説読解や社会問題読解などに時間を費やす必要はない。 ===理系数学 === (100分)良問が多いが、解法パターンを暗記しただけの勉強法では解けない。マーク式+記述の併用試験である。解法の理解を前提として、それらを応用する力が問われる。数IIIの出題が多く、微分積分、数列、三角関数がよく出題される。この領域に関してはかなりの習熟度が必要である。学部学科での難易度の差が激しい。先進工学部の問題は易~標準程度の為満点争いになる。工学部や数学科専用の問題の難易度は極めて高い。 繁雑な計算を長々とさせられた挙句に出る答えが,ルートの中に t の4次式が入るなど汚いものであることが多いが,それに惑わされずに解き進めてゆく必要があろう。 === 理科 === (80分)物理・化学・生物の中から1科目選択して受験する。学部学科によっては、指定された科目を受験する。 ====物理==== 力学、熱力学、波動、電磁気の分野からよく出題される。洗練された良問が多く、難易度の高い問題も出るが、悪問や奇問は出題されない。知識よりも思考力を試す問題である。 工学部では数値計算の大問がある上に他学科より難易度が高い。10⁰として答える問題もある。計算ミスをしてないか慎重に進めること。 ====化学==== 化学に対する基本的な理解、および素早い計算力が問われることが多い。計算量は多い。 ; 【理学部】 : 計算力重視の問題が多い。知識問題での失点を最小限にとどめ、計算問題でどれだけ粘れるかが大切である。特に化学科受験生は計算練習をしっかりとしておくことが大切である。最近は無機化学の出題頻度は少ないが、対策しないで受験することは望ましくない。 ; 【薬学部】 : 化学の配点が大きいので化学の出来が合否に大きく影響する。有機化学の分量がやや多い。知識問題が多いが有機の知識問題では高度なものが出題されることがある。過去問に類似していることが多いので過去問対策は重要である。 ; 【工学部】 : 理学部に比べると知識問題の割合は多いが、計算量の多い問題もあるので素早く正確に解くことが重要である。 ; 【創域理工学部】 : 他の学部に比べると知識問題の分量が多い。高得点が取りやすいので7割以上は確実に取りたい。 ====生物==== 分子生物学領域の問題が多い。応用生物科学科では遺伝の計算問題が出題されることもあり、思考力と計算力が問われる。知識問題は少ない。限られた時間で問題文を適切に判断、計算していく能力が問われる。生物工学科は応用生物科学科よりシンプルな問題が多い。現象に対する理解を確認するだけではなく、それらを応用する力が求められるため、暗記型の学習では対応できない。 ==経営学部== 経営学部は学科によって入試方式が微妙に異なっている。 ・経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)。 3教科のうち、高得点の2科目を1.5倍にして、合否判定する。 ・国際デザイン経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(200)。 ・ビジネスエコノミクス学科は2~3教科(300点満点)である。 【数学】数I・数A・数II・数B(数列・ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)を必須科目とし、最後の1科目は 《国語》国語総合・現代文B(古文・漢文を除く)(100)、と 《数学》数I・数A・数II・数B(数列・ベクトル)・数III(100)の中から1科目を選択する。 東京理科大学経営学部は都内キャンパスへの全面移転により競争率が近年上昇している。 ===英語=== 必須科目。理系学部の「英語」を参照。 ===選択科目1=== 国語か理系数学(3Cまで)から1科目選択する。 '''国語'''<br /> 全国の国語の入試問題の中でも、驚くほどの長い文章を課す。その分量は大問1つにつき、本文は10ページにも及ぶものである。大問構成は大問2つでどちらも前述した量の文章量である。記述式の設問が多いので、思考力が試される。今までは試験時間が100分であったが2016年度の入試から試験時間が80分になってしまった。その2016年の入試では大問1つにつき8ページから9ページ程に文章量は減ったが、設問数は変わらず時間内に終わらせるには相当至難な問題となっていた。2017年度以降に注目である。受験生は読解速度の向上と記述式の設問に慣れ、解答速度を上げておく必要がある。本文本文の諺や国文法に関する知識も問われ、単独での古文、漢文の出題は例年見受けられないものの、現古融合文は年によって課されるため、古文と漢文の学習は必須である。 '''理系数学'''<br /> 理系学部の「理系数学」を参照。 ===選択科目2=== 数学(2B) '''文系数学'''<br /> 理系数学に比べると平易。 = 共通テスト利用入試(A方式) = 共通テストの成績のみで合否を決める入試である。 *'''理系学部''' 数学ⅠA・ⅡB、英語、理科1科目+国語or情報の共通テスト科目の成績が求められる。合格するには、薬学部で85%、その他の学部学科で75%~82%必要である。 *'''経営学部''' 英数国+選択1科目(理科、社会、情報)の共通テストの成績が求められる。合格するには80%必要である。 = 共通テスト+個別入試(C方式) = 共通テストの成績と個別入試の成績の合計で合否を決める入試である。 *'''理系学部''' 国語、英語の共通テスト2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。 *'''経営学部''' 国語、英語の共通テストと数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。ただし、個別入試では理科を受験せず、数学の1科目だけの受験も可能である。その場合は、数学の得点が2倍される。 = 外部サイト = *[http://www.tus.ac.jp/ 理科大公式サイト] [[Category:大学入試|とうきようりかたいたいさく]] 9984d3a28vgz4f381i2z9f8n2vrmcwi 263785 263775 2024-11-18T11:11:44Z Ayhxuknbsijceivzdjhswh 66317 263785 wikitext text/x-wiki {{wikipedia|東京理科大学}} *[[日本の大学受験ガイド]] > [[東京理科大対策]] 本項は、[[w:東京理科大学|東京理科大学]]の入学試験対策に関する事項である。 東京理科大学は、東京都にある理工系総合大学である。文系学部は経営学部だけである。略称は「理科大」。 理科大の入試問題は計算力・思考力を問う良問が多い。理系学部の入試科目は英語、数学、理科(地学以外から一科目選択)である。早慶や旧帝国大、東工大の理・工学部の併願として受験する場合、特別な対策は不要だが、農学部、医療系学部との併願である場合、問題の質が異なるので対策が必要。実質倍率はどの学部も3~4倍程度である。 = 個別入試(B方式) = == 理系学部 == === 英語 === (60分)数学や理科に比べると英語の問題は総じて平易だが、下記の特徴を持つ。 * 他大学と比べて長文が長く、整序英作文も難易度が高いため、それらへの対策が必要である。なお整序英作文は、配点が全体の3割を占める年(2008年)もある。 * 年によって文法問題が見受けられないこともあるが、多くは長文問題に隠れて重複している。 * 整序英作文以外は概ね平易なので、まずは基本文法、語彙をマスターすることが重要。 * 長文は大抵、受験する学科に関連した英文が出るため、志望学科の専門領域に関連した語彙を覚えること。文学部向けの小説読解や社会問題読解などに時間を費やす必要はない。 ===理系数学 === 出題範囲は数I・数A (図形の性質・場合の数と確率)・数II・数B(数列・統計的な推測)・数III・数C(ベクトル・平面上の曲線と複素数平面) 制限時間は100分。良問が多いが、解法パターンを暗記しただけの勉強法では解けない。マーク式+記述の併用試験である。解法の理解を前提として、それらを応用する力が問われる。数IIIの出題が多く、微分積分、数列、三角関数がよく出題される。この領域に関してはかなりの習熟度が必要である。学部学科での難易度の差が激しい。先進工学部の問題は易~標準程度の為満点争いになる。工学部や数学科専用の問題の難易度は極めて高い。 繁雑な計算を長々とさせられた挙句に出る答えが,ルートの中に t の4次式が入るなど汚いものであることが多いが,それに惑わされずに解き進めてゆく必要があろう。 === 理科 === (80分)物理・化学・生物の中から1科目選択して受験する。学部学科によっては、指定された科目を受験する。 ====物理==== 力学、熱力学、波動、電磁気の分野からよく出題される。洗練された良問が多く、難易度の高い問題も出るが、悪問や奇問は出題されない。知識よりも思考力を試す問題である。 工学部では数値計算の大問がある上に他学科より難易度が高い。10⁰として答える問題もある。計算ミスをしてないか慎重に進めること。 ====化学==== 化学に対する基本的な理解、および素早い計算力が問われることが多い。計算量は多い。 ; 【理学部】 : 計算力重視の問題が多い。知識問題での失点を最小限にとどめ、計算問題でどれだけ粘れるかが大切である。特に化学科受験生は計算練習をしっかりとしておくことが大切である。最近は無機化学の出題頻度は少ないが、対策しないで受験することは望ましくない。 ; 【薬学部】 : 化学の配点が大きいので化学の出来が合否に大きく影響する。有機化学の分量がやや多い。知識問題が多いが有機の知識問題では高度なものが出題されることがある。過去問に類似していることが多いので過去問対策は重要である。 ; 【工学部】 : 理学部に比べると知識問題の割合は多いが、計算量の多い問題もあるので素早く正確に解くことが重要である。 ; 【創域理工学部】 : 他の学部に比べると知識問題の分量が多い。高得点が取りやすいので7割以上は確実に取りたい。 ====生物==== 分子生物学領域の問題が多い。応用生物科学科では遺伝の計算問題が出題されることもあり、思考力と計算力が問われる。知識問題は少ない。限られた時間で問題文を適切に判断、計算していく能力が問われる。生物工学科は応用生物科学科よりシンプルな問題が多い。現象に対する理解を確認するだけではなく、それらを応用する力が求められるため、暗記型の学習では対応できない。 ==経営学部== 経営学部は学科によって入試方式が微妙に異なっている。 ・経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A (図形の性質・場合の数と確率)・数II・数B(数列・統計的な推測)・数C(ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)。 3教科のうち、高得点の2科目を1.5倍にして、合否判定する。 ・国際デザイン経営学科は3教科(400点満点)である。 【国語】国語総合・現代文B(古文・漢文を除く)(100)、 【数学】数I・数A (図形の性質・場合の数と確率)・数II・数B(数列・統計的な推測)・数C(ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(200)。 ・ビジネスエコノミクス学科は2~3教科(300点満点)である。 【数学】数I・数A(図形の性質・場合の数と確率)・数II・数B(数列・統計的な推測)・数C(ベクトル)(100)、 【外国語】コミュ英I・コミュ英II・コミュ英III・英語表現I・英語表現II(100)を必須科目とし、最後の1科目は 《国語》国語総合・現代文B(古文・漢文を除く)(100)、と 《数学》数I・数A(図形の性質・場合の数と確率)・数II・数B(数列・統計的な推測)・数III・数C(ベクトル・平面上の曲線と複素数平面)(100)の中から1科目を選択する。 東京理科大学経営学部は都内キャンパスへの全面移転により競争率が近年上昇している。 ===英語=== 必須科目。理系学部の「英語」を参照。 ===選択科目1=== 国語か理系数学(3Cまで)から1科目選択する。 '''国語'''<br /> 全国の国語の入試問題の中でも、驚くほどの長い文章を課す。その分量は大問1つにつき、本文は10ページにも及ぶものである。大問構成は大問2つでどちらも前述した量の文章量である。記述式の設問が多いので、思考力が試される。今までは試験時間が100分であったが2016年度の入試から試験時間が80分になってしまった。その2016年の入試では大問1つにつき8ページから9ページ程に文章量は減ったが、設問数は変わらず時間内に終わらせるには相当至難な問題となっていた。2017年度以降に注目である。受験生は読解速度の向上と記述式の設問に慣れ、解答速度を上げておく必要がある。本文本文の諺や国文法に関する知識も問われ、単独での古文、漢文の出題は例年見受けられないものの、現古融合文は年によって課されるため、古文と漢文の学習は必須である。 '''理系数学'''<br /> 理系学部の「理系数学」を参照。 ===選択科目2=== 数学(2B) '''文系数学'''<br /> 理系数学に比べると平易。 = 共通テスト利用入試(A方式) = 共通テストの成績のみで合否を決める入試である。 *'''理系学部''' 数学ⅠA・ⅡB、英語、理科1科目+国語or情報の共通テスト科目の成績が求められる。合格するには、薬学部で85%、その他の学部学科で75%~82%必要である。 *'''経営学部''' 英数国+選択1科目(理科、社会、情報)の共通テストの成績が求められる。合格するには80%必要である。 = グローバル方式/共通テスト+個別入試(C方式) = グローバル方式は英語資格の提出が必須となる試験。英検やTEAPで一定以上の点数を取ると加算される(最大25点) C方式は共通テストの成績と個別入試の成績の合計で合否を決める入試である。 なおどちらも問題は同じ。但し併願は不可。 *'''理系学部''' 国語、英語の共通テスト2科目と数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。 *'''経営学部''' 国語、英語の共通テストと数学(ⅢCまで)、理科1科目の個別入試2科目を合わせた4科目の成績で合否を決める。ただし、個別入試では理科を受験せず、数学の1科目だけの受験も可能である。その場合は、数学の得点が2倍される。 = 個別入試(S方式) = 創域理工学部の数理学科と電気電子工学科のみで行われる。400点満点で問題はB方式と同じだが、違いは数理学科は数学の配点が3倍、電気電子工学科は物理の配点が2倍となる。さらに数理学科では理科の試験は実施されない。数学や物理がかなり得意ならばこちらを受験するのもありだろう。同一試験日でなければB方式とS方式の併願も可能。 = 外部サイト = *[http://www.tus.ac.jp/ 理科大公式サイト] [[Category:大学入試|とうきようりかたいたいさく]] g25jiwq2d1trtjnmtwbggv2au3g3gl3 PHP 0 3037 263764 263213 2024-11-18T09:46:25Z Ef3 694 /* 目次 */ # [[/改廃された技術|改廃された技術]] 263764 wikitext text/x-wiki __NOTOC__ {{pathnav|メインページ|工学|情報技術|プログラミング}} PHPはWeb開発において非常に人気のあるサーバーサイドプログラミング言語です。その理由として、PHPはシンプルで学びやすい構文を持ち、特にWebアプリケーションの開発に最適化されている点が挙げられます。また、豊富なオープンソースのフレームワークやライブラリが利用可能であり、個人開発者から大規模なプロジェクトに至るまで、広範なユーザー層に支持されています。 本書では、プログラミング初心者を対象に、PHPの基本的な概念、構文、関数の作成方法、オブジェクト指向プログラミングにおけるクラスの活用方法などを丁寧に解説しています。読者が実際に手を動かしながらコードを記述し、動作確認を行うことで、実践的なスキルを身に付けられるよう構成されています。 2024年11月現在、PHPの唯一の公式サポートバージョンはPHP 8であり、最新の機能とセキュリティ対策が導入されています<ref>{{Cite web|url=https://www.php.net/supported-versions.php|title=PHP: Supported Versions|accessdate=2024-11-08}}</ref>。本書では、PHP 8をベースに、基礎的な知識からWebアプリケーション開発に必要なスキルを順を追って学べるように設計されています。特にPHP初心者が無理なく理解できるよう、豊富なサンプルコードとわかりやすい説明を通じて、ステップバイステップで学習を進めていきます。 なお、PHP 7.4は2022年11月28日に公式サポートが終了しており、セキュリティアップデートなどの提供は行われていません<ref>{{Cite web|url=https://www.php.net/eol.php|title=PHP: Unsupported Branches|accessdate=2024-11-08}}</ref>。そのため、最新バージョンであるPHP 8の使用が推奨されます。 == 目次 == # [[/開発環境|開発環境]] # [[/コマンドラインでの活用|コマンドライン]] # [[/入門/テキスト表示とコメント|テキスト表示とコメント]] # [[/入門/変数と値|変数と値]] # [[/入門/変数の種類|データ型]] # [[/配列|配列]] # [[/制御構造|制御構造]] # [[/関数|関数]] # [[/クラス|PHPのオブジェクト指向]] # [[/Webアプリケーション向けの機能|Webアプリケーション向けの機能]] # [[/ファイル入出力|ファイル入出力]] # [[/データベースとの連動|データベースとの連携]] # [[/Null安全性|Null安全性]] # [[/ジェネリックプログラミング|ジェネリックプログラミング]] # [[/新機能|バージョンごとの新機能]] # [[/改廃された技術|改廃された技術]] == 脚註 == {{Wikipedia|PHP (プログラミング言語)}} <references /> [[Category:PHP|*]] [[Category:プログラミング言語]] {{NDC|007.64}} og43r3sujwfe8uj0th3hryddhj42zt9 ガリア戦記 0 3514 263722 263676 2024-11-17T12:00:56Z Linguae 449 /* 各巻対訳 */ 263722 wikitext text/x-wiki __notoc__ <!--【2006年4月23日起稿】--> *[[古典ラテン語]]>'''ガリア戦記''' *[[ラテン文学]]>'''ガリア戦記''' {{NDC|992|かりあせんき}} <div style="font-family:Arial Black;font-style:normal;font-size:17pt;color:#990033;text-align:center;background-color:#fee;">C &middot; IVLII &middot; CAESARIS &middot; COMMENTARII &middot; DE &middot; BELLO &middot; GALLICO</div> [[画像:Commentarii_de_Bello_Gallico.jpg|thumb|right|240px|1783年刊行の『ガリア戦記』と『内乱記』]] [[画像:Siege-alesia-vercingetorix-jules-cesar.jpg|thumb|right|280px|カエサル(右)と対面するウェルキンゲトリクス(左)<br>(リオネル=ノエル・ロワイエ [[w:fr:Lionel Royer|(fr)]] 画、1899年)]] [[w:古代ローマ|古代ローマ]]の政治家・武将・著述家である[[w:ガイウス・ユリウス・カエサル|ガイウス・ユリウス・カエサル4世]]([[w:la:Gaius_Iulius_Caesar|Gaius Iulius Caesar IV]])が[[w:ガリア戦争|ガリア戦争]]([[w:la:Bellum_Gallicum|Bellum Gallicum]])の経過を[[w:古典ラテン語|古典ラテン語]]で著述した[[w:ラテン文学|ラテン文学]]の古典的名著『ガリア戦記』([[wikt:la:Commentarii_de_bello_Gallico|Commentarii de bello Gallico]])の[[ラテン語]]・[[日本語]]対訳。第8巻のみ[[w:アウルス・ヒルティウス|アウルス・ヒルティウス]]([[w:la:Aulus_Hirtius|Aulus Hirtius]])による著作。  刊行当時の書名は、『ガイウス・ユリウス・カエサルの業績(戦績)に関する覚え書』(C. Iulii Caesaris Commentarii Rerum Gestarum)であったと推定され、『'''[[内乱記]]'''』と併せたものであった。 ルネサンス期以降は『ガイウス・ユリウス・カエサルのガリア戦争および内戦に関する覚え書』(C. Iulii Caesaris Commentarii de Bello Gallico et Civili)と題して刊行されていた(右の画像)。 <div style="background-color:#dfd;"> 『ガリア戦記』は、ガリア戦争の当事者であるカエサルが、簡潔明晰かつ客観的に描写することにより自らの戦争の正当性を示し<ref name="ガリア戦記">[https://kotobank.jp/word/%E3%82%AC%E3%83%AA%E3%82%A2%E6%88%A6%E8%A8%98-47339 ガリア戦記(がりあせんき)とは? 意味や使い方 - コトバンク]</ref>、自らに対する種々の非難に対する弁明を意図したものである<ref name="ガリア戦記"/>。簡潔雄渾な名文として名高く<ref name="ガリア戦記"/>、第一級の歴史書であるとともにラテン文学の傑作とされている<ref name="ガリア戦記"/>。</div> <br><br> <div style="border:solid #999 1px;background:#F8F8F8;max-width:60%;padding:0.25em 1em;margin:0.5em auto;align:left;overflow:auto;text-align:justify;"> 『ガリア戦記』冒頭部分の英語圏の人による朗読を聴いてみよう。 Gallia est omnis<!--omnes--> dīvīsa in partēs trēs; quārum ūnam incolunt Belgae, aliam Aquītānī, tertiam quī<!--qui--> ipsōrum linguā Celtae, nostrā Gallī appellantur. Hī omnēs linguā, īnstitūtīs, lēgibus inter sē differunt. Gallōs ab Aquītānīs Garumna flūmen, ā Belgīs Mātrona et Sēquana dīvidit. ::::: [[File:La-cls-de-bello-gallico.ogg]] ::::::([[w:Vorbis|Ogg Vorbis]] 音声ファイル、<strong>長さ 54秒</strong>、155 kbps) </div> <br> == 各巻対訳 == *[[ガリア戦記 第1巻]](54節){{進捗|25%|2009-07-28}}<u>(作成途上)</u>:[[w:ヘルウェティイ族|ヘルウェティイー族]]との戦役。[[w:アリオウィストゥス|アリオウィストゥス]]との戦役。 *[[ガリア戦記 第2巻]](35節){{進捗|75%|2022-04-25}}:[[w:ベルガエ人|ベルガエ人]]同盟軍との戦役、大西洋岸の征服。     *[[ガリア戦記 第3巻]](29節){{進捗|75%|2022-10-31}}:アルプスの戦い、[[w:アレモリカ|大西洋岸]]および[[w:アクィタニア|アクィータニア]]の平定。 <!--【2007年4月30日から】--> *[[ガリア戦記 第4巻]](38節){{進捗|75%|2023-07-24}}:[[w:ゲルマニア|ゲルマーニア]]人との戦役。[[w:ブリタンニア|ブリタンニア]]への初めての遠征。 *[[ガリア戦記 第5巻]](58節){{進捗|75%|2024-09-23}}:ブリタンニアへの再遠征。[[w:エブロネス族|エブローネース族]]ら諸部族の蜂起。 *[[ガリア戦記 第6巻]](44節){{進捗|50%|2024-11-17}}:ガッリアと[[w:ゲルマニア|ゲルマーニア]]の社会と風習。エブローネース族らの平定。 *[[ガリア戦記 第7巻]](90節){{進捗|50%|2011-04-16}}:[[w:ウェルキンゲトリクス|ウェルキンゲトリクス]]らが率いるガッリア同盟軍との戦役。 *ガリア戦記 第8巻(55節):<u>(掲載未定)</u> == 注解編と用例集 == ;注解編 *<span style="background-color:#ffd;">[[/注解編]] {{進捗|25%|2024-09-23}}</span>   <small>(2020年3月27日から)</small> **<span style="background-color:#ffd;">[[/注解編/写本と校訂版|/写本と校訂版]] {{進捗|25%|2024-11-13}}</span><!-- 2020-04-17 -->   <small>(2020年4月17日から)</small> *各巻の注解 **<span style="background-color:#ffd;">[[ガリア戦記 第1巻/注解|/第1巻注解]] {{進捗|25%|2020-06-01}}</span>   <small>(2020年3月27日から)</small> **<span style="background-color:#ffd;">[[ガリア戦記 第2巻/注解|/第2巻注解]] {{進捗|25%|2022-05-05}}</span>   <small>(2021年8月26日から)</small> **<span style="background-color:#ffd;">[[ガリア戦記 第3巻/注解|/第3巻注解]] {{進捗|25%|2022-10-27}}</span>   <small>(2022年3月27日から)</small> **<span style="background-color:#ffd;">[[ガリア戦記 第4巻/注解|/第4巻注解]] {{進捗|25%|2023-07-10}}</span>   <small>(2022年10月20日から)</small> **<span style="background-color:#ffd;">[[ガリア戦記 第5巻/注解|/第5巻注解]] {{進捗|25%|2024-09-23}}</span>   <small>(2023年07月20日から)</small> **<span style="background-color:#ffd;">[[ガリア戦記 第6巻/注解|/第6巻注解]] {{進捗|00%|2024-11-14}}</span>   <small>(2024年09月09日から)</small> ;用例集 *<span style="background-colo:#ffd;">[[/用例集]] {{進捗|00%|2020-03-29}}</span><!-- 2020-03-29 --> ;ガリア語 *<span style="background-colo:#ffd;">[[/ガリア語の名前]] {{進捗|00%|2021-12-11}}</span><!-- 2021-09-25 --> == 付録1 == {{Wikipedia|ガリア戦記|ガリア戦記}} {{Wiktionary|la:Commentarii_de_bello_Gallico|ガリア戦記}} {{Commons|Category:Gallic_War|ガリア戦争}} <!-- *[[/あらすじ]]:各巻のあらすじ --> *[[/内容目次]]:巻・章・節の内容を記した目次 {{進捗|75%|2011-04-02}} *[[/参照画像一覧]]:本文で参照した画像一覧  {{進捗|75%|2023-11-05}} *[[/ガリアの河川]]:本書で言及される河川  {{進捗|00%|2023-01-07}}<!--【2021年11月22日より】--> *[[/関連年表]] *[[/対訳語彙集 (羅和)]] - [[/対訳語彙集 (羅英)]] **[[/人物一覧 (羅和)]] **[[/部族一覧 (羅和)]] **[[/地名一覧 (羅和)]] {{進捗|25%|2010-04-07}} == 付録2 == *<span style="background-color:#ffa;">'''[[古代ローマの不定時法]]'''   {{進捗|50%|2020-08-24}}</span> <!-- 2016-12-31 --> *<span style="background-color:#ffb;">[[ガイウス・ユリウス・カエサルの著作/ラテン語の紀年法|/ラテン語の紀年法]]   {{進捗|75%|2009-01-12}}</span> *<span style="background-color:#ffb;">[[ガイウス・ユリウス・カエサルの著作/古代ローマの攻城兵器|/古代ローマの攻城兵器]] {{進捗|00%|2019-08-06}}</span> *<span style="background-color:#ffffcc;">[[ガイウス・ユリウス・カエサルの著作/古代ローマの軍旗類|/古代ローマの軍旗類]]  {{進捗|00%|2022-01-22}}</span><!--【2022年1月22日より】--> *[[ガイウス・ユリウス・カエサルの著作/通貨・計量単位|/通貨・計量単位]]    {{進捗|25%|2020-12-27}}</span> == 原文出典 == {{Wikisource|la:Commentarii de bello Gallico|ガリア戦記}} {{進捗状況}} *ラテン語版ウィキソース:[[s:la:Commentarii_de_bello_Gallico|Commentarii de bello Gallico]](ただし、校訂本の出典記載なし! しかも誤植が多いので注意! α系写本の影響が強いと思われる。) :以下の校訂本を参照しながら、できるだけα系写本の影響を尊重しつつ、原文を修整した。 *トイプナー古典叢書(<small>[[w:la:Bibliotheca_scriptorum_Graecorum_et_Romanorum_Teubneriana|Bibliotheca scriptorum Graecorum et Romanorum Teubneriana]]</small>) **C. Iulii Caesaris Commentarii Rerum Gestarum, edidit [[w:de:Otto_Seel|Otto Seel]], vol.I. Bellum Gallicum, [[w:la:Lipsia|Lipsiae]], Teubner, 1961. *:(オットー・ゼール(1907-1975)編。現代の代表的な校訂本。β系写本の影響がやや強い。絶版。) **C. Iulii Caesaris Commentarii Rerum Gestarum, edidit [[w:de:Wolfgang_Hering|Wolfgang Hering]], vol.I. Bellum Gallicum, Lipsiae, Teubner, 1987. *: ISBN 978-3-322-00351-5 (ISBN 3-322-00351-5) *:(ヴォルフガング・ヘーリンク編。最近の校訂本。写本の異同などの情報量、文の完成度はゼール版より劣ると思われる。) == 参考文献 == *ラテン語・英語対訳 **CAESAR: The Gallic War (with an English translation), by H. J. Edwards, [[w:en:Loeb_Classical_Library|Loeb Classical Library]](#72), [[w:en:Harvard_University_Press|Harvard University Press]], ISBN 979-0-674-99080-7 **:(1917年の初版以来、[[w:ローブ・クラシカルライブラリー|ローブ古典叢書]]の一冊として刊行され続けている読み物としての普及版) *ラテン語・日本語対訳 **『カエサル『ガリア戦記』第I巻』遠山一郎 訳注、大学書林、2009年、ISBN 978-4-475-02446-4 *日本語訳 **『ガリア戦記』 カエサル著、近山金次訳、岩波文庫(岩波書店)、1964年、ISBN 978-4-00-334071-4 **『ガリア戦記』 カエサル著、國原吉之助訳、講談社学術文庫、1994年、ISBN 978-4-06-159127-1 *英語訳 **CAESAR: The Gallic War (A new English translation) by Carolyn Hammond, [[w:en:Oxford World's Classics|Oxford World's Classics(OWC)]], [[w:en:Oxford University Press|Oxford University Press]], First published 1996 ; Reissued 2008、ISBN 978-0-19-954026-6(近年の新訳) *注釈書 **Gould, H.E. & J.L. Whiteley. C. Iuli Caesaris Commentariorum De Bello Gallico. Liber Quartus. (London: Macmillan & Co Ltd., 1968).;初級者向けの英文注釈がある。 **Caesar: De Bello Gallico V, Edited by R.C.Carrington (再版Bristol Classical Press, 1984), ISBN 0-86292-136-8 etc. == 関連項目 == *<span style="background-color:#ffea;">[[古典ラテン語]] {{進捗|00%|2018-04-18}} </span><!-- 2018-04-18 -->   <small>(2018年4月18日から)</small> *<span style="background-color:#ffe;">[[羅馬史略]]   {{進捗|00%|2022-08-18}}</span><!-- 2022-08-18 -->   <small>(2022年8月18日から)</small> == 関連記事 == *英語版ウィキソース:[[s:en:Commentaries_on_the_Gallic_War|Commentaries on the Gallic War]](英語訳) *フランス語版ウィキソース:[[s:fr:La_Guerre_des_Gaules|La Guerre des Gaules]](仏語訳) :  *ラテン語版ウィクショナリー:[[wikt:la:Commentarii_de_bello_Gallico|wikt:la:Commentarii de bello Gallico]] == 脚注 == <references /> == 外部リンク == *[http://www.forumromanum.org/literature/caesar/gallic.html Commentaries on the Gallic War]("corpus scriptorum latinorum" ラテン文学のデジタルライブラリー;英仏訳と地図付) *[http://www.debellogallico.org/index.cgi/bgtext Commentarii de Bello Gallico](ガリア戦記の日本語対訳サイト) *[http://itunes.apple.com/jp/podcast/classics-texts-caesar-de-bello/id183722640 Classics Texts :: Caesar, De Bello Gallico 2 (Study Speed)](『[[ガリア戦記 第2巻]]』の各節を[[w:ITunes|iTunes]]向けに読み上げた音声ファイルのダウンロードサイト) === Latein.me === *[https://www.latein.me/ Latein-Wörterbuch - Latein.me] (ラテン語-ドイツ語オンラインリソース) **[https://www.latein.me/text/3/Caesar Caesar - Übersetzungen] (カエサルの著作) ***[https://www.latein.me/text/3/Caesar/33/De+Bello+Gallico+%28I%29/p/0 De Bello Gallico (I)] (第1巻) ***[https://www.latein.me/text/3/Caesar/34/De+Bello+Gallico+%28II%29/p/0 De Bello Gallico (II)] (第2巻) ***[https://www.latein.me/text/3/Caesar/35/De+Bello+Gallico+%28III%29/p/0 De Bello Gallico (III)] (第3巻) ***[https://www.latein.me/text/3/Caesar/36/De+Bello+Gallico+%28IV%29/p/0 De Bello Gallico (IV)] (第4巻) ***[https://www.latein.me/text/3/Caesar/37/De+Bello+Gallico+%28V%29/p/0 De Bello Gallico (V)] (第5巻) ***[https://www.latein.me/text/3/Caesar/38/De+Bello+Gallico+%28VI%29/p/0 De Bello Gallico (VI)] (第6巻) ***[https://www.latein.me/text/3/Caesar/39/De+Bello+Gallico+%28VII%29/p/0 De Bello Gallico (VII)] (第7巻) ***[https://www.latein.me/text/3/Caesar/40/De+Bello+Gallico+%28VIII%29/p/0 De Bello Gallico (VIII)] (第8巻) [[Category:ガリア戦記|*]] [[Category:ラテン語|かりあせんき]] [[Category:古典ラテン文学|かりあせんき]] [[Category:ガイウス・ユリウス・カエサルの著作|かりあせんき]] 8f39qhw77krar6qgpvctjs4k47nqbgl Java/プログラミングのための準備 0 4241 263727 242031 2024-11-17T23:38:35Z Ef3 694 校閲と推敲 263727 wikitext text/x-wiki {{Nav}} = プログラミングのための準備 = == JDK == {{Wikipedia|Java Development Kit|Java Development Kit}} JDK(Java Development Kit)は、Javaプログラムを開発するためのソフトウェア開発キットです。JDKには、Javaプログラムを作成、コンパイル、実行するために必要なツールやファイルが含まれています。具体的には以下のような要素が含まれます。 # '''Javaコンパイラ(javac):''' Javaソースコードをバイトコードに変換するためのコンパイラです。Javaコンパイラは、Javaプログラムをコンパイルして実行可能な形式に変換します。 # '''Javaランタイム環境(JRE):''' Javaプログラムを実行するための実行時環境です。JREには、Java仮想マシン(JVM)やJavaクラスライブラリが含まれています。 # '''デバッグツール:''' デバッグやトラブルシューティングのためのツールが含まれています。例えば、デバッガやプロファイラなどがあります。 # '''APIドキュメント:''' JavaプログラミングのためのAPIドキュメントが含まれています。これにより、Javaの標準ライブラリやクラスの使用方法を確認することができます。 # '''開発ツール:''' jshell(Java REPL)、jlink(モジュールリンカー)、jdeps(依存関係分析)などの開発支援ツールが含まれています。 === javac === {{Wikipedia|javac}} javacは、Javaコンパイラのコマンドラインツールです。このツールは、Javaソースコードファイル(.java拡張子)をJava仮想マシン(JVM)が理解できるバイトコードファイル(.class拡張子)に変換します。 具体的には、以下のような役割があります: # '''Javaソースコードのコンパイル:''' javacは、Javaプログラムをコンパイルしてバイトコードに変換します。このバイトコードはJVM上で実行されるため、プラットフォームやオペレーティングシステムに依存しません。 # '''エラーチェックとデバッグ:''' javacは、ソースコードに文法エラーや論理エラーがないかをチェックし、必要に応じてエラーメッセージを生成します。これにより、開発者はコードの品質を向上させることができます。 # '''バイトコードの生成:''' javacは、コンパイルされたJavaソースコードからバイトコードファイルを生成します。このバイトコードは、JVM上で実行されるJavaアプリケーションやアプレットの基盤となります。 # '''モジュール対応:''' Java 9以降、javacはモジュールシステム(Project Jigsaw)に対応し、モジュール化されたアプリケーションのコンパイルをサポートしています。 === JRE === {{Wikipedia|Java Runtime Environment}} JRE(Java Runtime Environment)は、Javaプログラムを実行するための環境を提供するソフトウェアパッケージです。主な役割は以下の通りです: # '''Javaアプリケーションの実行:''' JREにはJava仮想マシン(JVM)が含まれており、Javaプログラムを実行可能な形式に変換します。これにより、Javaアプリケーションは異なるプラットフォームやオペレーティングシステム上で動作します。 # '''Javaクラスライブラリの提供:''' JREには、Java標準ライブラリが含まれています。これにより、Javaアプリケーションは基本的なデータ構造や機能を利用できます。例えば、文字列処理、ネットワーク通信、ファイル操作などが含まれます。 # '''セキュリティ機能の提供:''' JREは、Javaアプリケーションの実行中にセキュリティを確保し、悪意ある操作やリソースの不正使用を防ぎます。これには、セキュリティマネージャーなどが含まれます。 # '''パフォーマンス最適化:''' JITコンパイラによるコードの最適化やガベージコレクションの実行など、実行時のパフォーマンスを向上させる機能を提供します。 === Java仮想マシン === {{Wikipedia|Java仮想マシン}} Java仮想マシン(Java Virtual Machine、JVM)は、Javaプログラムを実行するための仮想的なコンピュータ環境です。JVMは、Javaバイトコード(.classファイル)をホストプラットフォームのネイティブマシンコードに変換し、実行します。 以下はJVMの主な役割です: # '''プログラムの実行:''' JVMはJavaバイトコードを解釈し、ネイティブマシンコードに変換して実行します。これにより、Javaプログラムはホストプラットフォームやオペレーティングシステムに依存せずに実行できます。 # '''メモリ管理:''' JVMはメモリの割り当てや解放を管理し、ガベージコレクションと呼ばれるメカニズムを使用して不要なオブジェクトを自動的に解放します。これにより、メモリリークや無効なメモリアクセスなどの問題を回避できます。 # '''セキュリティ:''' JVMは、セキュリティ管理を強化するための機能を提供します。例えば、セキュリティマネージャーを使用して、Javaアプリケーションのアクセス権を制御することができます。 # '''例外処理:''' JVMは、Javaプログラム内で発生する例外をキャッチし、適切な例外処理を行います。これにより、プログラムの安定性が向上し、予期せぬエラーに対処できます。 # '''JITコンパイル:''' Just-In-Time(JIT)コンパイラを使用して、頻繁に実行されるコードをネイティブコードに変換し、実行性能を向上させます。 # '''プロファイリング:''' アプリケーションの実行状況を監視し、パフォーマンスデータを収集する機能を提供します。 == Oracle JDKとOpen JDK == === Oracle JDK === Oracle JDKは、Javaプログラミング言語の開発および実行環境を提供するOracle Corporationによる製品です。Oracle JDK 17以降はNFTC(No-Fee Terms and Conditions)ライセンスの下で提供され、開発、テスト、プロトタイピング、デモンストレーション目的での使用に加えて、商用環境での使用も無料で許可されています。 主な特徴: # '''商用サポート:''' 有償のサポートサービスが利用可能です。 # '''パフォーマンス最適化:''' 商用環境向けの最適化が施されています。 # '''セキュリティアップデート:''' 定期的なセキュリティアップデートが提供されます。 # '''追加ツール:''' Java Flight Recorderなどの商用機能が含まれています。 === Open JDK === OpenJDKは、Javaプログラミング言語のオープンソースのリファレンス実装です。GNU General Public License (GPL) version 2 with Classpath Exceptionの下で提供され、商用利用も含めて無料で利用できます。 主な特徴: # '''オープンソース:''' ソースコードが公開され、コミュニティによる開発が行われています。 # '''プラットフォーム互換性:''' 様々なプラットフォームやアーキテクチャに対応しています。 # '''コミュニティサポート:''' 活発なコミュニティによるサポートが提供されます。 # '''最新機能:''' 新機能の実装が早期に行われます。 === その他の JDK === その他の主要なJDK実装には以下のようなものがあります: ; Amazon Corretto : Amazonが提供する無償のOpenJDK配布版です。AWS環境での最適化が施されており、長期サポート(LTS)が提供されます。特徴: :* AWS環境での最適化 :* 自動パッチ適用 :* 無償の長期サポート :* マルチプラットフォーム対応 ; Eclipse Temurin (旧AdoptOpenJDK) : Eclipse Foundationが管理するOpenJDKの配布版です。特徴: :* 厳格な品質管理 :* 豊富なプラットフォームサポート :* コミュニティドリブンな開発 :* 定期的なアップデート提供 ; Azul Zulu : Azul Systemsが提供するOpenJDKの実装です。特徴: :* エンタープライズグレードのサポート :* プラットフォーム最適化 :* セキュリティ強化 :* ARM版を含む幅広いアーキテクチャ対応 === Java SE LTS === Java SE LTS(Java Standard Edition Long-Term Support)は、Java SEプラットフォームの長期サポートを提供するプログラムです。2024年2月現在、最新のJava SE LTSはJava 21です。 以下は、最新のJava SE LTSバージョンの一覧です: :{| class=wikitable |+ Java SE LTSのバージョン一覧 !Java バージョン !リリース日 !LTS サポート終了日 !主な特徴 |- | Java SE 8 LTS | 2014年3月18日 | 2030年12月 | * Lambdaサポート * Stream API * JavaFX 8 |- | Java SE 11 LTS | 2018年9月25日 | 2026年9月 | * HTTPクライアントAPI * 新しいガベージコレクタ * モジュールシステム |- | Java SE 17 LTS | 2021年9月14日 | 2029年9月 | * シールドクラス * パターンマッチング * 新しいランダム生成器 |- | Java SE 21 LTS | 2023年9月19日 | 2031年9月 | * 仮想スレッド * レコードパターン * シーケンシャルコレクション |} == プログラミングに必要なもの == === 統合開発環境(IDE) === 現代のJava開発では、以下のような統合開発環境(IDE)が広く使用されています: ; IntelliJ IDEA : JetBrainsが開発する高機能IDE。Community Edition(無料)とUltimate Edition(有料)があります。 : 主な特徴: :* インテリジェントなコード補完 :* 高度なリファクタリング機能 :* フレームワークサポート :* デバッグ機能の充実 :* Git統合 ; Eclipse : オープンソースの統合開発環境。無料で利用可能です。 : 主な特徴: :* プラグインによる拡張性 :* マルチ言語サポート :* 豊富なプロジェクトテンプレート :* デバッグツールの充実 :* チーム開発支援機能 ; Visual Studio Code : Microsoftが開発する軽量なコードエディタ。Java拡張機能により、IDEとしても利用可能です。 : 主な特徴: :* 軽量で高速 :* 豊富な拡張機能 :* Git統合 :* デバッグ機能 :* Live Share機能 === ビルドツール === 現代のJavaプロジェクトでは、以下のビルドツールが主流です: ; Apache Maven : XMLベースの構成管理とビルド自動化ツール。 : 主な特徴: :* 宣言的な依存関係管理 :* 標準化されたプロジェクト構造 :* 豊富なプラグイン :* センターリポジトリ :* ライフサイクル管理 ; Gradle : GroovyまたはKotlinベースのビルド自動化ツール。 : 主な特徴: :* 柔軟なビルドスクリプト :* インクリメンタルビルド :* ビルドキャッシュ :* 依存関係の最適化 :* Android公式ビルドツール == 開発環境のセットアップ == === JDKのインストール === {{Main|[https://docs.oracle.com/javase/jp/21/install/overview-jdk-installation.html JDKインストレーション・ガイド]}} # '''JDKのダウンロード:''' #: Oracle公式サイト([https://www.oracle.com/jp/java/technologies/downloads/ Java SE Downloads])からJDKをダウンロードします。 #: 以下の点に注意してダウンロードを行います: #:* 使用するOSに合ったバージョンを選択 #:* LTSバージョンの選択を推奨 #:* プロセッサアーキテクチャ(x64/ARM)の確認 === SDKMANを使う方法 === SDKMANはJavaの開発環境を簡単に管理できるコマンドラインツールです。複数のJDKバージョンを切り替えて使用できる便利な機能を提供します。 # '''SDKMANのインストール:''' #: Unix系OS(Linux/macOS)で以下のコマンドを実行: #: <code>curl -s "https://get.sdkman.io" | bash</code> #: インストール後、次のコマンドでSDKMANを有効化: #: <code>source "$HOME/.sdkman/bin/sdkman-init.sh"</code> # '''SDKMANでのJDK管理:''' #:* 利用可能なJDKの一覧表示: #: <code>sdk list java</code> #:* 特定バージョンのJDKインストール: #: <code>sdk install java 21.0.2-tem</code> #:* デフォルトJDKの設定: #: <code>sdk default java 21.0.2-tem</code> #:* インストール済みJDKの切り替え: #: <code>sdk use java 21.0.2-tem</code> === ビルドツールの設定 === Javaプロジェクトの依存関係管理とビルド自動化のため、以下のツールの導入を推奨します: # '''Maven:''' #:* 最も広く使われているビルドツール #:* インストール方法: #:* SDKMANを使用:<code>sdk install maven</code> #:* 手動インストール:[https://maven.apache.org/download.cgi Apache Maven公式サイト]からダウンロード #:* 基本的な設定はsettings.xmlで管理 # '''Gradle:''' #:* 柔軟性の高いビルドツール #:* インストール方法: #:* SDKMANを使用:<code>sdk install gradle</code> #:* 手動インストール:[https://gradle.org/install/ Gradle公式サイト]からダウンロード #:* build.gradleファイルでビルド設定を管理 これらの環境設定が完了したら、実際の開発作業を開始できます。 {{Nav}} {{DEFAULTSORT:ふろくらみんくのためのしゆんひ}} [[Category:Java]] 4of568krz5btv59edvhvrnpul9lta0n 民法第413条 0 4848 263724 263696 2024-11-17T12:51:05Z Tomzo 248 /* 要件 */ 263724 wikitext text/x-wiki [[法学]]>[[民事法]]>[[民法]]>[[コンメンタール民法]]>[[第3編 債権 (コンメンタール民法)|第3編 債権]] ==条文== ([[受領遅滞]]) ;第413条 #[[債権者]]が[[債務]]の[[弁済|履行]]を受けることを拒み、又は受けることができない場合において、その債務の目的が特定物の引渡しであるときは、債務者は、履行の提供をした時からその引渡しをするまで、自己の財産に対するのと同一の注意をもって、その物を保存すれば足りる。 #債権者が債務の履行を受けることを拒み、又は受けることができないことによって、その履行の費用が増加したときは、その増加額は、債権者の負担とする。 ===改正経緯=== 2017年改正前は以下のとおり。 :債権者が債務の履行を受けることを拒み、又は受けることができないときは、その債権者は、履行の提供があった時から遅滞の責任を負う。 ==解説== {{wikipedia|受領遅滞}} 本条は、債権者の[[受領遅滞]]について規定している。 :受領遅滞の法的性質について、債権者の義務をめぐり、債権者は権利者であり義務を持たないとし、法が特に債権者の義務を定めたものとする'''法定責任説'''と、債権者にも給付の実現に協力すべき義務があり、義務違反の債務不履行責任を定めたものとする'''債務不履行説'''がある。 :法定責任説が、判例・通説の立場である。 ===構成=== ====要件==== :*履行の提供 :*:債務者から履行が提供されていること :*::いかなる行為をもって「履行の提供」とするか。→[[民法第493条|第493条]](弁済の提供の方法) :*受領拒絶・受領不能 :**受領拒絶とは :**受領不能とは ====効果==== :*債務が特定物の引渡しであるときの保管責任の軽減(本条第1項) :*:自己の財産に対するのと同一の注意。故意の毀損ないし通常施される程度に至らない管理でなければ良い。 :*履行費用の増加 :*:債権者の負担となる(本条第1項)。 :*:例えば、債権者が引き取らないことにより生ずる倉庫料、保管のために他の用途に用いられないことにより被る機会損失などの費用は債権者が負担する。 :*危険負担 :*:債権者の負担となる([[民法第413条の2|第413条の2]]第2項)。 :※受領遅滞は、債権者による債務不履行の類ではないので、債務者からの解除は認められない。 ==参照条文== *履行の提供(弁済の提供) :[[民法第492条]](弁済の提供の効果) :[[民法第493条]](弁済の提供の方法) *履行遅滞 :[[民法第412条]](履行期と履行遅滞) :[[民法第415条]](債務不履行による損害賠償) *[[民法第567条]] *:売買契約において、売主が引渡しの債務の履行を提供したにもかかわらず、買主の受領遅滞により、当事者双方の責めに帰することができない事由によって目的物の滅失等が生じた場合、買主はその目的物に関して、売主に'''契約不適合の責任'''を追及することはできない([[危険負担]]が移転する)。 ==判例== #[http://www.courts.go.jp/search/jhsp0030?hanreiid=53971&hanreiKbn=02 損害賠償請求](最高裁判決 昭和40年12月03日)[[民法第493条]] #;建物の賃貸人が現実に提供された賃料の受領を拒絶した場合とその後における賃料不払を理由とする契約の解除 #:建物の賃貸人が現実に提供された賃料の受領を拒絶したときは、特段の事情がないかぎり、その後において提供されるべき賃料についても、受領拒絶の意思を明確にしたものと解すべきであり、右賃貸人が賃借人の賃料の不払を理由として契約を解除するためには、単に賃料の支払を催告するだけでは足りず、その前提として、受領拒絶の態度を改め、以後賃料を提供されれば確実にこれを受領すべき旨を表示する等、自己の受領遅滞を解消させるための措置を講じなければならない。 #[https://www.courts.go.jp/app/hanrei_jp/detail2?id=54097 家屋明渡等請求](最高裁判決 昭和45年8月20日)[[民法第541条]] #;債務者は債権者の受領遅滞を理由として契約を解除できるか。 #:債務者が債権者の受領遅滞を理由として契約を解除することは、特段の事由のないかぎり、許されない。 #:*債務者の債務不履行と債権者の受領遅滞とは、その性質が異なるのであるから、一般に後者に前者と全く同一の効果を認めることは民法の予想していない。 #:*受領遅滞に対し債務者のとりうる措置としては、供託・自動売却等の規定を設けている。されば、特段の事由の認められないとき、債権者の受領遅滞を理由として債務者は契約を解除することができない。 #[https://www.courts.go.jp/app/hanrei_jp/detail2?id=51875 損害賠償等請求](最高裁判決 昭和46年12月16日)[[民法第1条]]、[[民法第555条]] #;硫黄鉱石売買契約の買主に引取義務が認められた事例 #:硫黄鉱区の採掘権を有する甲が鉱石を採掘して乙に売り渡す硫黄鉱石売買契約において、甲は、乙に対し、右契約の存続期間を通じて採掘する鉱石の全量を売り渡す約定があつたなど判示の事情がある場合には、信義則上、乙には、甲が右期間内に採掘した鉱石を引き取る義務があると解すべきである。 #:*<u>鉱石売買契約においては、「売主」が右契約期間を通じて採掘する鉱石の全量が売買されるべきものと定められており、「売主」は「買主」に対し右鉱石を継続的に供給すべきもの</u>なのであるから、信義則に照らして考察するときは、「売主」は、右約旨に基づいて、その採掘した鉱石全部を順次「買主」に出荷すべく、「買主」はこれを引き取り、かつ、その代金を支払うべき法律関係が存在していたものと解するのが相当である。したがつて、「買主」には、「売主」が採掘し、提供した鉱石を引き取るべき義務があつたものというべきであり、「買主」の前示引取の拒絶は、債務不履行の効果を生ずるものといわなければならない。 #[https://www.courts.go.jp/app/hanrei_jp/detail2?id=56336 建物収去土地明渡](最高裁判決 昭和56年3月20日)[[民法第266条]]、[[民法第276条]] #;土地所有者が地代の受領を拒絶し又はこれを受領しない意思が明確であるため地上権者において提供をするまでもなく債務不履行の責を免れる事情にある場合と民法266条1項、276条に基づく地上権消滅請求 #:土地所有者が地代の受領を拒絶し又は地上権の存在を否定する等弁済を受領しない意思が明確であるため地上権者が言語上の提供をするまでもなく地代債務の不履行の責を免れるという事情がある場合には、土地所有者は、みずから受領拒絶の態度を改め、以後地代を提供されればこれを確実に受領すべき旨を明らかにしたのち相当期間を経過したか、又は相当期間を定めて催告をしたにもかかわらず地上権者が右期間を徒過した等、自己の受領遅滞又はこれに準ずる事態を解消させる措置を講じたのちでなければ、民法266条1項、276条に基づく地上権消滅請求の意思表示をすることができない。 ---- {{前後 |[[コンメンタール民法|民法]] |[[第3編 債権 (コンメンタール民法)|第3編 債権]]<br> [[第3編 債権 (コンメンタール民法)#1|第1章 総則]]<br> [[第3編 債権 (コンメンタール民法)#1-2|第2節 債権の効力]] |[[民法第412条]]<br>(履行期と履行遅滞) |[[民法第413条の2]]<br>(履行遅滞中又は受領遅滞中の履行不能と帰責事由) }} {{stub|law}} [[category:民法|413]] [[category:民法 2017年改正|413]] 0wefgs017v6s49wk8oxm9alfb6c8h2y 263726 263724 2024-11-17T22:16:12Z Tomzo 248 /* 効果 */ 263726 wikitext text/x-wiki [[法学]]>[[民事法]]>[[民法]]>[[コンメンタール民法]]>[[第3編 債権 (コンメンタール民法)|第3編 債権]] ==条文== ([[受領遅滞]]) ;第413条 #[[債権者]]が[[債務]]の[[弁済|履行]]を受けることを拒み、又は受けることができない場合において、その債務の目的が特定物の引渡しであるときは、債務者は、履行の提供をした時からその引渡しをするまで、自己の財産に対するのと同一の注意をもって、その物を保存すれば足りる。 #債権者が債務の履行を受けることを拒み、又は受けることができないことによって、その履行の費用が増加したときは、その増加額は、債権者の負担とする。 ===改正経緯=== 2017年改正前は以下のとおり。 :債権者が債務の履行を受けることを拒み、又は受けることができないときは、その債権者は、履行の提供があった時から遅滞の責任を負う。 ==解説== {{wikipedia|受領遅滞}} 本条は、債権者の[[受領遅滞]]について規定している。 :受領遅滞の法的性質について、債権者の義務をめぐり、債権者は権利者であり義務を持たないとし、法が特に債権者の義務を定めたものとする'''法定責任説'''と、債権者にも給付の実現に協力すべき義務があり、義務違反の債務不履行責任を定めたものとする'''債務不履行説'''がある。 :法定責任説が、判例・通説の立場である。 ===構成=== ====要件==== :*履行の提供 :*:債務者から履行が提供されていること :*::いかなる行為をもって「履行の提供」とするか。→[[民法第493条|第493条]](弁済の提供の方法) :*受領拒絶・受領不能 :**受領拒絶とは :**受領不能とは ====効果==== :*債務が特定物の引渡しであるときの保管責任の軽減(本条第1項) :*:自己の財産に対するのと同一の注意。故意の毀損ないし通常施される程度に至らない管理でなければ良い。 :*履行費用の増加 :*:債権者の負担となる(本条第2項)。 :*:例えば、債権者が引き取らないことにより生ずる倉庫料、保管のために他の用途に用いられないことにより被る機会損失などの費用は債権者が負担する。 :*危険負担 :*:債権者の負担となる([[民法第413条の2|第413条の2]]第2項)。 :※受領遅滞は、債権者による債務不履行の類ではないので、債務者からの解除は認められない。 ==参照条文== *履行の提供(弁済の提供) :[[民法第492条]](弁済の提供の効果) :[[民法第493条]](弁済の提供の方法) *履行遅滞 :[[民法第412条]](履行期と履行遅滞) :[[民法第415条]](債務不履行による損害賠償) *[[民法第567条]] *:売買契約において、売主が引渡しの債務の履行を提供したにもかかわらず、買主の受領遅滞により、当事者双方の責めに帰することができない事由によって目的物の滅失等が生じた場合、買主はその目的物に関して、売主に'''契約不適合の責任'''を追及することはできない([[危険負担]]が移転する)。 ==判例== #[http://www.courts.go.jp/search/jhsp0030?hanreiid=53971&hanreiKbn=02 損害賠償請求](最高裁判決 昭和40年12月03日)[[民法第493条]] #;建物の賃貸人が現実に提供された賃料の受領を拒絶した場合とその後における賃料不払を理由とする契約の解除 #:建物の賃貸人が現実に提供された賃料の受領を拒絶したときは、特段の事情がないかぎり、その後において提供されるべき賃料についても、受領拒絶の意思を明確にしたものと解すべきであり、右賃貸人が賃借人の賃料の不払を理由として契約を解除するためには、単に賃料の支払を催告するだけでは足りず、その前提として、受領拒絶の態度を改め、以後賃料を提供されれば確実にこれを受領すべき旨を表示する等、自己の受領遅滞を解消させるための措置を講じなければならない。 #[https://www.courts.go.jp/app/hanrei_jp/detail2?id=54097 家屋明渡等請求](最高裁判決 昭和45年8月20日)[[民法第541条]] #;債務者は債権者の受領遅滞を理由として契約を解除できるか。 #:債務者が債権者の受領遅滞を理由として契約を解除することは、特段の事由のないかぎり、許されない。 #:*債務者の債務不履行と債権者の受領遅滞とは、その性質が異なるのであるから、一般に後者に前者と全く同一の効果を認めることは民法の予想していない。 #:*受領遅滞に対し債務者のとりうる措置としては、供託・自動売却等の規定を設けている。されば、特段の事由の認められないとき、債権者の受領遅滞を理由として債務者は契約を解除することができない。 #[https://www.courts.go.jp/app/hanrei_jp/detail2?id=51875 損害賠償等請求](最高裁判決 昭和46年12月16日)[[民法第1条]]、[[民法第555条]] #;硫黄鉱石売買契約の買主に引取義務が認められた事例 #:硫黄鉱区の採掘権を有する甲が鉱石を採掘して乙に売り渡す硫黄鉱石売買契約において、甲は、乙に対し、右契約の存続期間を通じて採掘する鉱石の全量を売り渡す約定があつたなど判示の事情がある場合には、信義則上、乙には、甲が右期間内に採掘した鉱石を引き取る義務があると解すべきである。 #:*<u>鉱石売買契約においては、「売主」が右契約期間を通じて採掘する鉱石の全量が売買されるべきものと定められており、「売主」は「買主」に対し右鉱石を継続的に供給すべきもの</u>なのであるから、信義則に照らして考察するときは、「売主」は、右約旨に基づいて、その採掘した鉱石全部を順次「買主」に出荷すべく、「買主」はこれを引き取り、かつ、その代金を支払うべき法律関係が存在していたものと解するのが相当である。したがつて、「買主」には、「売主」が採掘し、提供した鉱石を引き取るべき義務があつたものというべきであり、「買主」の前示引取の拒絶は、債務不履行の効果を生ずるものといわなければならない。 #[https://www.courts.go.jp/app/hanrei_jp/detail2?id=56336 建物収去土地明渡](最高裁判決 昭和56年3月20日)[[民法第266条]]、[[民法第276条]] #;土地所有者が地代の受領を拒絶し又はこれを受領しない意思が明確であるため地上権者において提供をするまでもなく債務不履行の責を免れる事情にある場合と民法266条1項、276条に基づく地上権消滅請求 #:土地所有者が地代の受領を拒絶し又は地上権の存在を否定する等弁済を受領しない意思が明確であるため地上権者が言語上の提供をするまでもなく地代債務の不履行の責を免れるという事情がある場合には、土地所有者は、みずから受領拒絶の態度を改め、以後地代を提供されればこれを確実に受領すべき旨を明らかにしたのち相当期間を経過したか、又は相当期間を定めて催告をしたにもかかわらず地上権者が右期間を徒過した等、自己の受領遅滞又はこれに準ずる事態を解消させる措置を講じたのちでなければ、民法266条1項、276条に基づく地上権消滅請求の意思表示をすることができない。 ---- {{前後 |[[コンメンタール民法|民法]] |[[第3編 債権 (コンメンタール民法)|第3編 債権]]<br> [[第3編 債権 (コンメンタール民法)#1|第1章 総則]]<br> [[第3編 債権 (コンメンタール民法)#1-2|第2節 債権の効力]] |[[民法第412条]]<br>(履行期と履行遅滞) |[[民法第413条の2]]<br>(履行遅滞中又は受領遅滞中の履行不能と帰責事由) }} {{stub|law}} [[category:民法|413]] [[category:民法 2017年改正|413]] 5m20eteohe75uio9gn9b6ze1ll36heq Ruby 0 6662 263782 244845 2024-11-18T11:00:29Z Ef3 694 /*改廃された技術*/ Rubyの改廃された技術や利用が推奨されない技術は、言語の進化、パフォーマンスの向上、シンプルさの追求、新しいプログラミングパラダイムへの対応により置き換えられます。以下に、代表的な技術を示します。 263782 wikitext text/x-wiki {{Pathnav|メインページ|工学|情報技術|プログラミング|frame=1}} {{Wikipedia}} 本書は、[[w:Ruby|Ruby]]のチュートリアルです。 Rubyは、比較的習得が容易なオブジェクト指向スクリプティング言語です。 [[w:まつもとゆきひろ|まつもとゆきひろ]]によって開発されました。 [[Ruby on Rails]]の記述言語として選ばれたことで有名になりましたが、ウェブアプリケーション以外にもシステム管理やネットワークアプリケーションなどさまざまな用途に用いられます。 __TOC__ == Rubyとは == === Rubyの特徴 === Rubyには、強力で多用途な言語とするための多くの特徴があります。その特徴とは以下の通りです: ;オブジェクト指向のプログラミング :Rubyは完全なオブジェクト指向言語であり、Rubyのすべてがオブジェクトであることを意味します。このため、複雑なプログラムを簡単に作成することができ、メンテナンスも容易です。 ;動的な型付け :Rubyは動的型付け言語であり、コンパイル時に変数の型がチェックされることはありません。このため、プログラムを再コンパイルすることなく、変数の型を簡単に変更することができます。 ;インタプリタ型言語 :Rubyはインタープリタ型言語であり、機械語にコンパイルされるのではなく、コードが1行ずつ実行されます。そのため、Rubyのプログラムの開発やデバッグが容易に行えます。 ;簡潔な構文 :Rubyには簡潔な構文があり、コードを書くのが簡単です。そのため、初心者から経験豊富なプログラマーまで、幅広く利用することができます。 ;大規模なコミュニティ :Rubyには、言語やライブラリに貢献する開発者たちの大規模で活発なコミュニティがあります。そのため、Rubyプログラミングのヘルプやサポートを簡単に見つけることができます。 Rubyは強力で汎用性の高い言語であり、さまざまなタスクに適しています。Rubyの学習と使用は簡単で、開発者の大規模で活発なコミュニティがあります。強力で汎用性が高く、習得が容易な言語をお探しなら、Rubyは良い選択です。 == 初級編 == === Rubyのインストール方法 === Rubyを利用するためには、公式ウェブサイトからインストーラーをダウンロードしてインストールします。 以下は、主要なプラットフォームへのインストール手順の概要です: ;Windows: :RubyInstaller( https://rubyinstaller.org/ ) のページからインストーラーをダウンロードします。 :ダウンロードしたインストーラーを実行し、指示に従ってインストールを進めます。 ;macOS: :macOSにはデフォルトでRubyがインストールされていますが、最新バージョンを利用する場合はRVM(Ruby Version Manager https://rvm.io/ ) や [https://github.com/rbenv/rbenv rbenv]を使用することをお勧めします。 ;Linux: :パッケージマネージャーを使用してインストールします。例えば、UbuntuやDebianでは次のコマンドでインストールできます: :<syntaxhighlight lang=shell> sudo apt-get update sudo apt-get install ruby </syntaxhighlight> {{Main|[https://www.ruby-lang.org/ja/documentation/installation/ Rubyのインストール]}} === Hello Worldプログラムの作成 === RubyでのHello Worldプログラムは非常に簡単です。以下は、コンソールに"Hello, World!"と出力するプログラムです: ;hello.rb:<syntaxhighlight lang=ruby> puts "Hello, World!" </syntaxhighlight> これを<code>hello.rb</code>という名前で保存し、ターミナルで<code>ruby hello.rb</code>と実行すると、"Hello, World!"が表示されます。 :<syntaxhighlight lang=shell> $ ruby hello.rb Hello, World! $ </syntaxhighlight> === データ型と変数 === Rubyでは、様々なデータ型が利用できます。文字列、数値、配列、ハッシュなどがその代表的なものです。動的型付け言語であるRubyでは、変数の型宣言が不要です。以下に、主要なデータ型と変数の宣言と代入について詳細を示します。 ; 数値 (Numeric) : 数値には、整数 (Integer) や浮動小数点数 (Float) が含まれます。整数は例えば<code>42</code>のように表され、浮動小数点数は例えば<code>3.14</code>のように表されます。 ; 文字列 (String) : 文字列は、ダブルクォーテーション (") またはシングルクォーテーション (') で囲まれた文字の並びです。例えば、<code>"Hello"</code>や<code>'Ruby'</code>などが文字列です。 ; 配列 (Array) : 配列は、複数の要素を順序付けして格納するデータ構造です。要素は角かっこ <code>[ ]</code> で囲まれ、コンマで区切ります。例えば、<code>[1, 2, 3]</code>や<code>['a', 'b', 'c']</code>などが配列です。 ; ハッシュ (Hash) : ハッシュは、キーと値のペアを格納するデータ構造です。波かっこ <code>{ }</code> で囲まれ、キーと値はコロン <code>:</code> で区切ります。例えば、<code>{'name' => 'Alice', 'age' => 30}</code>などがハッシュです。 ==== 変数の宣言と代入 ==== 変数は代入演算子 <code>=</code> を使用して宣言および初期化されます。変数名はアルファベットまたはアンダースコア <code>_</code> で始まり、その後にはアルファベット、数字、アンダースコアを組み合わせることができます。型宣言は不要であり、変数は動的に型が決まります。 以下は、変数の宣言と代入の例です。 :<syntaxhighlight lang=ruby> name = "Alice" # 文字列型の変数 age = 30 # 整数型の変数 scores = [85, 90, 75, 100] # 配列型の変数 person = {'name' => 'Bob', 'age' => 25} # ハッシュ型の変数 </syntaxhighlight> これらの例では、それぞれの変数に適切なデータ型の値が代入されています。 === 制御構造 === Rubyには様々な制御構造が用意されており、以下のようなものがあります。 ; 条件分岐 :; <code>if</code>/<code>elsif</code>/<code>else</code> :: 最も基本的な条件分岐構文 :; <code>unless</code>/<code>else</code> :: <code>if not</code>と同等の意味 :; <code>case</code>/<code>when</code>/<code>else</code> :: 値の一致で分岐 :; <code>case</code>/<code>in</code>/<code>else</code> :: パターンマッチ ; ループ :; <code>while</code> :: 条件が真の間ループを実行 :; <code>until</code> :: 条件が偽の間ループを実行(whileの逆) :; <code>for</code>/<code>in</code> :: 反復可能オブジェクトの要素に対してループ :; <code>loop</code> :: 無限ループ :; <code>break</code>/<code>next</code> :: ループから抜ける/次の反復へ進む ; 例外処理 :; <code>begin</code>/<code>rescue</code>/<code>else</code>/<code>ensure</code> :: 例外の捕捉と処理 :; <code>raise</code> :: 例外を発生させる ; その他 :; <code>times</code>/<code>upto</code>/<code>downto</code> :: ブロックを繰り返し実行 :; <code>tap</code> :: 参照渡しでブロックを実行 :; <code>yield</code> :: ブロックを呼び出す Rubyの制御構造はPerlやBashなどとよく似ていますが、独自の構文も存在します。 また、Rubyはブロックの概念があり、それを活用した制御構造があるのが特徴です。 ;制御構造の一例:<syntaxhighlight lang=ruby> # 条件分岐 name = 'Alice' if name == 'Alice' puts 'こんにちは、Aliceさん' elsif name == 'Bob' puts 'こんにちは、Bobさん' else puts "あなたの名前は#{name}ですね" end # ifは式 puts if name == 'Alice' 'こんにちは、Aliceさん' elsif name == 'Bob' 'こんにちは、Bobさん' else "あなたの名前は#{name}ですね" end # unless file_exists = false puts 'ファイルが存在しません' unless file_exists # case/when age = 25 case age when 0...18 puts '未成年者です' when 18...65 puts '働き盛りの年齢ですね' else puts 'シニア世代かもしれません' end # パターンマッチング puts case [2, 3, 5] in 0, 1, 2 '最初の整数' in 0, 2, 4 '最初の偶数' in 1, 3, 5 '最初の奇数' in 2, 3, 5 => n "最初の素数、三番目は#{n}" else 'どの数列でもない' end # 出力: "最初の素数、三番目は5" # 繰り返し # while i = 0 while i < 5 puts "i = #{i}" i += 1 end # until j = 0 until j > 5 puts "j = #{j}" j += 1 end # for/in array = [10, 20, 30, 40] for item in array puts "要素は#{item}" end # loop count = 1 loop do puts "回数は#{count}" count += 1 break if count > 5 end # 繰り返し制御 # break/next numbers = [1, 2, 3, 4, 5] numbers.each do |n| next if n.even? puts "奇数は#{n}" break if n == 5 end # 例外処理 # begin/rescue/else/ensure begin result = 10 / 0 rescue ZeroDivisionError => e puts "0で割ろうとしました: #{e.message}" else puts "結果は#{result}" ensure puts '計算処理が完了しました' end # each [2, 3, 5, 7, 11].each { |i| puts i } # times/upto/downto 5.times { puts 'Hello' } 1.upto(5) { |i| puts "uptoの値は#{i}" } 5.downto(1) { |i| puts "downtoの値は#{i}" } # tap string = 'Hello' result = string.tap { |s| puts "tap内: #{s}" } puts "tapの結果: #{result}" # yield def greet yield('Morning') yield('Evening') end greet { |time| puts "Good #{time}!" } </syntaxhighlight> ==== 条件実行のイディオム ==== Rubyには条件実行を簡潔に記述するためのいくつかのイディオムがあります。 # '''三項演算子''' #:<syntaxhighlight lang=ruby> 条件式 ? 真の場合の値 : 偽の場合の値 </syntaxhighlight> #: 三項演算子を使うと、if...elseを1行で記述できます。 #:<syntaxhighlight lang=ruby> allowed = user.admin? ? "Full access" : "Read only" </syntaxhighlight> # '''||= (OR代入演算子)''' #: 値が nil または false の場合のみ右辺の値が代入されます。 #:<syntaxhighlight lang=ruby> name = params[:name] || "Guest" # nameがnilまたは空文字列の場合、"Guest"が代入される </syntaxhighlight> # '''&&= (AND代入演算子)''' #: 値が真の場合のみ右辺の値が評価され、代入されます。 #:<syntaxhighlight lang=ruby> obj &&= obj.method # objがnilやfalseでない場合のみ、obj.methodが評価される </syntaxhighlight> # '''safe navigation 演算子 (&.)''' #: レシーバがnilの場合にメソッドが呼ばれず、nilを返します。 #:<syntaxhighlight lang=ruby> name = params.dig(:user, :name)&.strip # params[:user]または params[:user][:name]がnilの場合にnilを返す </syntaxhighlight> これらのイディオムを適切に使うことで、条件実行を簡潔で読みやすく記述できます。 ==== 反復実行のイディオム ==== Rubyには反復実行を簡潔に記述するためのいくつかのイディオムがあります。 # ''' each と do...end''' #:<syntaxhighlight lang=ruby> [1, 2, 3].each do |n| puts n end </syntaxhighlight> # ''' ブロック付きイテレータ''' #:<syntaxhighlight lang=ruby> (1..5).map { |n| n**2 } # => [1, 4, 9, 16, 25] [1, 2, 3].select(&:even?) # => [2] </syntaxhighlight> # '''times''' #:<syntaxhighlight lang=ruby> 5.times { puts "Ruby!" } # "Ruby!"が5回出力される </syntaxhighlight> # ''' loop do...end''' #:<syntaxhighlight lang=ruby> loop do cmd = gets.chomp break if cmd == "exit" # 処理 end </syntaxhighlight> # '''each''' と相当する '''for-in-end''' #:<syntaxhighlight lang=ruby> [1, 2, 3].each { |n| puts n } for n in [1, 2, 3] do puts n end </syntaxhighlight> #: Rubyでは forよりは each の方が #:* each はループ変数がメソッドに閉じている。 #:* eachは通常 self を返し、breakされると nil を返す #:* eachはメソッドチェインを構成しやすい #: などの理由で好まれます。 # ''' while/until''' #:<syntaxhighlight lang=ruby> ary = [1, 2, 3] i = 0 while i < ary.length puts ary[i] i += 1 end </syntaxhighlight> # ''' Enumerable#each_with_index''' #:<syntaxhighlight lang=ruby> ["a", "b", "c"].each_with_index { |item, index| puts "#{index}: #{item}"} </syntaxhighlight> # ''' Enumerable#with_index''' #:<syntaxhighlight lang=ruby> ["a", "b", "c"].with_index { |item, index| puts "#{index}: #{item}"} </syntaxhighlight> Rubyの反復構文はループだけでなく、ブロックやイテレータによる関数型のスタイルの記述も可能です。状況に応じて適切な方法を選ぶことで、簡潔でわかりやすいコードを書くことができます。 === (中級編あるいはリファレンス編に移動予定) === ==== 条件分岐 ==== 条件分岐は、プログラムの中で特定の条件が満たされた場合に異なる処理を実行するための制御構造です。 Rubyには、if-elsif-else-end 構文、case-when-else-end 構文があります。 ===== if-elsif-else-end ===== <code>if</code>、<code>elsif</code>、<code>else</code>キーワードを使用して条件分岐を記述します。以下はその基本的な構文です: :<syntaxhighlight lang=ruby> if 条件式 # 条件が真の場合の処理 elsif 別の条件式 # 条件が真の場合の処理 else # どの条件も満たされない場合の処理 end </syntaxhighlight> 例えば、次のように使用します: :<syntaxhighlight lang=ruby> age = 20 if age >= 20 puts "You are an adult." else puts "You are not an adult yet." end </syntaxhighlight> この場合、<code>age</code>が20以上の場合は"You are an adult."が出力され、それ以外の場合は"You are not an adult yet."が出力されます。 ===== case-when-else-end ===== Rubyの<code>case-when-else-end</code>文は、条件に応じて異なる処理を行うための制御構造です。 以下に、基本的な構文と使い方を解説します。 :<syntaxhighlight lang=ruby> case 式 when 条件1 # 式が条件1に合致したときに実行されるコード when 条件2, 条件3 # 式が条件2または条件3に合致したときに実行されるコード else # どの条件にも合致しない場合に実行されるコード end </syntaxhighlight> <code>case</code>の後に評価したい式を置きます。その式の評価結果と、<code>when</code>節の各条件を比較し、合致する場合に対応するブロックが実行されます。<code>else</code>節は、どの条件にも合致しない場合のデフォルトの処理を提供します。 例えば、以下は<code>case-when-else-end</code>文の使用例です。 :<syntaxhighlight lang=ruby> grade = 'B' puts case grade when 'A' then 'Excellent!' when 'B' then 'Good job!' when 'C' then 'You passed, but you could do better.' else 'Sorry, you failed.' end #=> Good job! </syntaxhighlight> この例では、変数<code>grade</code>の値に応じて異なるメッセージが出力されます。<code>grade</code>が'A'の場合は"Excellent!"が出力され、'B'の場合は"Good job!"が出力されます。<code>grade</code>が'C'の場合は"You passed, but you could do better."が出力され、どの条件にも一致しない場合は"Sorry, you failed."が出力されます。 <code>case-when-else-end</code>文は、複数の条件をテストする必要がある場合や、条件に基づいてさまざまな処理を行う必要がある場合に便利です。 ==== パターンマッチング ==== パターンマッチングは、プログラムの中で特定のパターンに処理を実行するための制御構造です。 Rubyには、case-in-else-end 構文と<code>=></code>演算子と<code>in</code>演算子があります。 ===== case-in-else-end ===== Rubyのパターンマッチング(Pattern Matching)は、構造化された値の深いマッチングを可能にする機能です。これにより、構造をチェックし、一致した部分をローカル変数にバインドすることができます。 Rubyのパターンマッチングは、<code>case/in</code>式を使用して実装されています。 以下に、その基本的な構文と使い方を示します。 :<syntaxhighlight lang=ruby> case 式 in パターン1 # 式がパターン1に合致したときに実行されるコード in パターン2 # 式がパターン2に合致したときに実行されるコード else # どのパターンにも合致しない場合に実行されるコード end </syntaxhighlight> <code>case</code>式の中の<code>in</code>ブロックは、パターンと一致するかどうかをチェックし、マッチした場合に対応するコードを実行します。<code>else</code>節は、どのパターンにも一致しない場合のデフォルトの処理を提供します。 以下は、パターンマッチングの使用例です。 :<syntaxhighlight lang=ruby> puts case [2, 3, 5] in 0, 1, 2 '最初の整数' in 0, 2, 4 '最初の偶数' in 1, 3, 5 '最初の奇数' in 2, 3, 5 => n "最初の素数、三番目は#{n}" else 'どの数列でもない' end # 出力: "最初の素数、三番目は5" </syntaxhighlight> このコードは、パターンマッチングを利用して、与えられた配列の最初の要素に応じて異なる処理を行います。与えられた配列 <code>[2, 3, 5]</code> の最初の要素が特定のパターンに一致するかどうかをテストし、一致する場合に対応するメッセージを出力します。 具体的には、与えられた配列 <code>[2, 3, 5]</code> の最初の要素が各条件に一致するかどうかをテストします。 * <code>[2, 3, 5]</code> は <code>0, 1, 2</code> に一致せず、次の条件へ進みます。 * <code>[2, 3, 5]</code> は <code>0, 2, 4</code> に一致せず、次の条件へ進みます。 * <code>[2, 3, 5]</code> は <code>1, 3, 5</code> に一致せず、次の条件へ進みます。 * <code>[2, 3, 5]</code> は <code>2, 3, 5 => n</code> に一致し、<code>n</code> に <code>7</code> が割り当てられます。 最終的に <code>"最初の素数、三番目は7"</code> というメッセージが出力されます。 <code>else</code> 節は、どの条件にも一致しない場合に実行されますが、この場合、どの数列でもないことを示すメッセージが出力されることになります。 ===== =>演算子とin演算子 ===== =>演算子とin演算子 は、パターンマッチングを簡潔に行う方法の1つです。通常、パターンマッチングは複数の行にわたるケース式や条件分岐を使用しますが、=>演算子とin演算子 は1行の式でパターンをマッチングする手法です。 具体的には、次のような形式で表現されます: :<syntaxhighlight lang=ruby> 式 => パターン </syntaxhighlight> あるいは :<syntaxhighlight lang=ruby> 式 in パターン </syntaxhighlight> この形式では、<code>式</code> の値が <code>パターン</code> にマッチするかどうかを評価します。 =>演算子とin演算子 でパターンマッチングに失敗すると、NoMatchingPatternKeyError例外が raise されます。 :<syntaxhighlight lang=ruby> {a: 1, b: 2, c: 3} => { b: n } puts n # 2 {a: 1, b: 2, c: 3} => { x: n } # {:a=>1, :b=>2, :c=>3}: key not found: :x (NoMatchingPatternKeyError) </syntaxhighlight> ===== さまざまなパターン ===== パターンマッチングにはさまざまなパターンがあります: * 値パターン(Value pattern) * 配列パターン(Array pattern) * ハッシュパターン(Hash pattern) * バインディングパターン(Variable pattern) * その他のパターン(Alternative pattern) これらのパターンを組み合わせて、複雑なデータ構造をマッチングできます。また、パターンマッチングではマッチした部分をローカル変数にバインドすることもできます。 ==== 反復 ==== Rubyにおける反復(ループ)は、いくつかの方法で行うことができます。主な方法は以下の通りです。 ===== eachメソッド ===== 配列やハッシュなどのコレクションに対して使われる最も一般的な反復方法です。以下はその例です。 :<syntaxhighlight lang=ruby> array = [1, 2, 3, 4, 5] array.each do |item| puts item end </syntaxhighlight> ===== for文 ===== for文も使用できますが、Rubyではあまり一般的ではありません。 :<syntaxhighlight lang=ruby> for i in 1..5 puts i end </syntaxhighlight> ===== while文 ===== while文を使って条件が満たされている間、ブロック内のコードを実行します。 :<syntaxhighlight lang=ruby> x = 0 while x < 5 do puts x x += 1 end </syntaxhighlight> ===== until文 ===== until文は条件が満たされるまでループします。 :<syntaxhighlight lang=ruby> x = 0 until x == 5 do puts x x += 1 end </syntaxhighlight> ===== timesメソッド ===== 固定回数のループを行う場合に便利です。 :<syntaxhighlight lang=ruby> 5.times do |i| puts i end </syntaxhighlight> これらの方法を組み合わせて、さまざまな反復のニーズに対応できます。 ただし、Rubyではeachメソッドが最も一般的で、他の方法よりも好まれることが多いです。 === メソッド === メソッドは、Rubyプログラムで特定の処理を実行するための手段を提供します。メソッドは、関数や手続きと同様の機能を持ち、再利用可能なコードブロックを定義します。Rubyでは、メソッドはオブジェクト指向プログラミングの基本的な概念であり、ほとんどの処理がメソッドとして定義されます。 ==== メソッドの定義 ==== メソッドは以下のような形式で定義されます: :<syntaxhighlight lang=ruby> def メソッド名(引数1, 引数2, ...) # メソッドの処理 end </syntaxhighlight> ここで、<code>def</code>キーワードを使ってメソッドを定義し、メソッド名を指定します。メソッドが引数を取る場合は、引数のリストを指定します。メソッドの本体は、<code>end</code>キーワードで終了します。 以下は、簡単なメソッドの例です: :<syntaxhighlight lang=ruby> def greet(name) puts "Hello, #{name}!" end greet("Alice") </syntaxhighlight> この例では、<code>greet</code>という名前のメソッドが定義されています。このメソッドは<code>name</code>という引数を取り、それを使用して挨拶を表示します。<code>greet("Alice")</code>という呼び出しでは、"Hello, Alice!"というメッセージが表示されます。 ==== Endlessなメソッドの定義 ==== <code>end</code>キーワードを伴わず、代入に似た形式でも定義できます: :<syntaxhighlight lang=ruby> def メソッド名(引数1, 引数2, ...) = 式 </syntaxhighlight> ここで、<code>def</code>キーワードと<code>=</code>を使ってメソッドを定義し、メソッド名を指定します。メソッドが引数を取る場合は、引数のリストを指定します。 以下は、簡単なメソッドの例です: :<syntaxhighlight lang=ruby> def greet(name) = puts "Hello, #{name}!" greet("Alice") </syntaxhighlight> ==== 戻り値 ==== また、Rubyではメソッド内で最後に評価された式が自動的にメソッドの戻り値となります。明示的な<code>return</code>文は省略することができますが、必要に応じて使用することもできます。 ==== ブロックを伴うメソッド ==== さらに、メソッドはオプションのブロックを受け取ることができます。ブロックを受け取るメソッドは、<code>yield</code>キーワードを使ってブロックを実行します。 :<syntaxhighlight lang=ruby> def greet(name) puts "Hello, #{name}!" yield if block_given? end </syntaxhighlight> このメソッドでは、引数として受け取った<code>name</code>に対して挨拶を出力し、その後に<code>yield</code>を使ってブロックを実行しています。<code>block_given?</code>メソッドは、メソッドがブロックを受け取ったかどうかを判定します。 メソッドを呼び出す際には、通常の引数と一緒にブロックを渡すことができます。 :<syntaxhighlight lang=ruby> greet("Alice") do puts "Nice to meet you!" end </syntaxhighlight> このコードは、以下を出力します。 :<syntaxhighlight lang=text> Hello, Alice! Nice to meet you! </syntaxhighlight> === 配列とハッシュ === ==== 配列の操作 ==== 配列は複数の要素を格納するためのデータ構造であり、それぞれの要素は順序付けされています。Rubyでは、配列は角かっこ <code>[ ]</code> で囲まれ、コンマで区切られた要素のリストとして表現されます。 ===== 要素の追加、削除、取得 ===== * 要素の追加: <code><<</code>演算子や<code>push</code>メソッドを使用して要素を配列に追加することができます。 *:<syntaxhighlight lang=ruby> fruits = ['apple', 'banana', 'orange'] fruits << 'grape' fruits.push('kiwi') </syntaxhighlight> * 要素の削除: <code>delete_at</code>メソッドや<code>pop</code>メソッドを使用して配列から要素を削除することができます。 *:<syntaxhighlight lang=ruby> fruits.delete_at(0) # インデックス0の要素を削除 fruits.pop # 末尾の要素を削除 </syntaxhighlight> * 要素の取得: インデックスを指定して配列から要素を取得することができます。 *:<syntaxhighlight lang=ruby> puts fruits[0] # => "banana" </syntaxhighlight> ==== ハッシュの操作 ==== ハッシュは、キーと値のペアを格納するデータ構造であり、各要素はキーを使用して参照されます。Rubyでは、波かっこ <code>{ }</code> を使用してハッシュを定義します。 ===== キーと値の追加、削除、取得 ===== * キーと値の追加: ハッシュに新しいキーと値のペアを追加するには、単純に代入演算子 <code>=</code> を使用します。 *:<syntaxhighlight lang=ruby> person = {'name' => 'Alice', 'age' => 30} person['gender'] = 'female' </syntaxhighlight> * キーと値の削除: <code>delete</code>メソッドを使用して、指定したキーとそれに対応する値を削除することができます。 *:<syntaxhighlight lang=ruby> person.delete('age') </syntaxhighlight> * キーと値の取得: ハッシュから特定のキーに関連付けられた値を取得するには、そのキーを指定します。 *:<syntaxhighlight lang=ruby> puts person['name'] # => "Alice" </syntaxhighlight> === クラスとオブジェクト指向プログラミング === ==== クラスの定義とインスタンス化 ==== クラスは、オブジェクトの設計図として機能し、それぞれのオブジェクトはそのクラスのインスタンスです。Rubyでは、<code>class</code>キーワードを使用してクラスを定義します。 ===== クラスの定義 ===== :<syntaxhighlight lang=ruby> class Person def initialize(name, age) @name = name @age = age end def introduce puts "My name is #{@name} and I'm #{@age} years old." end end </syntaxhighlight> この例では、<code>Person</code>という名前のクラスが定義されています。<code>initialize</code>メソッドは、新しいインスタンスが作成されるときに呼び出され、インスタンス変数 <code>@name</code> と <code>@age</code> に値を設定します。<code>introduce</code>メソッドは、そのインスタンスの情報を出力します。 ===== インスタンス化 ===== :<syntaxhighlight lang=ruby> alice = Person.new("Alice", 30) bob = Person.new("Bob", 25) </syntaxhighlight> これにより、<code>Person</code>クラスの新しいインスタンス <code>alice</code> と <code>bob</code> が作成されます。それぞれのインスタンスは、<code>initialize</code>メソッドによって設定された名前と年齢を持ちます。 :<syntaxhighlight lang=ruby> alice.introduce # => "My name is Alice and I'm 30 years old." bob.introduce # => "My name is Bob and I'm 25 years old." </syntaxhighlight> 各インスタンスは、クラス内で定義されたメソッドを呼び出すことができます。 ==== オブジェクト指向プログラミングの基礎 ==== オブジェクト指向プログラミング(OOP)は、プログラムをオブジェクトとそれらの相互作用に基づいて構造化する方法です。OOPには、次のような重要な概念があります: * カプセル化: データとそれに関連するメソッドを1つのユニットにまとめ、外部からのアクセスを制限します。 * 継承: 既存のクラスから新しいクラスを作成し、既存の機能を再利用します。 * ポリモーフィズム: 同じ名前のメソッドが異なるクラスで異なる振る舞いをすることを許容します。 これらの概念を使用することで、コードをより柔軟で保守しやすくすることができます。 == 中級編 == === 例外処理 === ==== begin-rescue-end文を使った例外処理の実装 ==== 例外処理は、予期しないエラーが発生した場合にプログラムの実行を中断せずに制御を継続するための仕組みです。Rubyでは、<code>begin</code>、<code>rescue</code>、<code>end</code>キーワードを使用して例外処理を実装します。 :<syntaxhighlight lang=ruby> begin # 例外が発生する可能性のあるコード result = 10 / 0 rescue ZeroDivisionError => e # 例外が発生した場合の処理 puts "Error occurred: #{e.message}" end </syntaxhighlight> 上記の例では、<code>begin</code>ブロック内でゼロ除算エラーが発生する可能性があります。<code>rescue</code>ブロックでは、特定の例外(ここでは<code>ZeroDivisionError</code>)が発生した場合の処理を指定します。例外が発生した場合、その例外オブジェクトが<code>rescue</code>ブロックの変数<code>e</code>に割り当てられ、<code>message</code>メソッドを使ってエラーメッセージを取得します。 ==== ファイル操作 ==== ==== ファイルの読み書き ==== ファイルの読み書きは、プログラムでよく行われる操作の1つです。Rubyでは、<code>File</code>クラスを使用してファイルの読み書きを行います。 :<syntaxhighlight lang=ruby> # ファイルの書き込み File.open("example.txt", "w") do |file| file.write("Hello, World!") end # ファイルの読み込み File.open("example.txt", "r") do |file| content = file.read puts content # => "Hello, World!" end </syntaxhighlight> ==== ファイルポインタの移動 ==== ファイルポインタを移動して、ファイル内の特定の位置から読み書きを行うこともできます。 :<syntaxhighlight lang=ruby> # ファイルのオープン File.open("example.txt", "r") do |file| # ファイルポインタの移動 file.seek(7) # 指定位置からの読み込み content = file.read puts content # => "World!" } </syntaxhighlight> === モジュールとMix-in === ==== モジュールの作成と利用 ==== モジュールは、関連するメソッドや定数をまとめるための仕組みであり、クラスにインクルードすることでその機能を利用することができます。 :<syntaxhighlight lang=ruby> module Greeting def say_hello puts "Hello!" end end class MyClass include Greeting end obj = MyClass.new obj.say_hello # => "Hello!" </syntaxhighlight> 上記の例では、<code>Greeting</code>モジュールを定義し、<code>MyClass</code>クラスにインクルードしています。その結果、<code>MyClass</code>のインスタンスである<code>obj</code>から<code>say_hello</code>メソッドが利用できるようになります。 ==== Mix-inパターンの活用 ==== Mix-inは、複数のクラスに同じメソッドや振る舞いを提供するためのデザインパターンです。モジュールを使ってMix-inを実現することができます。 :<syntaxhighlight lang=ruby> module Debug def debug_info puts "#{self.class} - #{self.inspect}" end end class MyClass include Debug end obj = MyClass.new obj.debug_info # => "MyClass - #<MyClass:0x00007fb35a20b3b8>" </syntaxhighlight> <code>Debug</code>モジュールは、<code>debug_info</code>メソッドを提供し、このメソッドを含むクラスにMix-inします。これにより、クラスのインスタンスがデバッグ情報を表示するメソッドを利用できるようになります。 === テスト === ==== Mintest ==== Minitestは、Rubyプログラミング言語用の軽量なテストフレームワークです。Minitestは、Rubyの標準ライブラリに含まれており、Rubyのバージョン1.9以降で利用可能です。Minitestは、テスト駆動開発(Test-Driven Development、TDD)や振る舞い駆動開発(Behavior-Driven Development、BDD)などのソフトウェア開発手法を支援するために使用されます。 {{Main|Ruby/Minitest}} Minitestは、単体テストや統合テストなど、さまざまな種類のテストをサポートしています。また、アサーションを用いて期待される振る舞いを確認するための豊富な機能も提供しています。Minitestの特徴は、シンプルで使いやすいインターフェース、高速な実行速度、そしてRubyの標準ライブラリに含まれているため、追加の依存関係を導入せずに利用できることです。 開発者がMinitestを使用することで、安定性や品質を向上させることができます。また、テストコードの記述や実行が容易であるため、素早く効果的なテストを作成することができます。 ---- 実際のコードを観てみましょう。 下記は、逆ポーランド記法の式を評価する機能を配列を継承して実装した例で、コメントを合わせても30行のコードですが、各演算子の実装の確認など基礎的なテストケースを書くだけで、数倍のコード量になります。 ;[https://paiza.io/projects/VltRK6tlhKoiWqIxn2dOaw?language=ruby Minitestの例] :<syntaxhighlight lang=ruby line> # frozen_string_literal: true # RPNクラスは逆ポーランド記法(Reverse Polish Notation)の式を評価するためのクラスです。 # スタック構造を使用して式を解析し、結果を計算します。 # Rubyでは、Arrayクラスがpop,pushなどのスタックとしてのメソッドが完備されているので継承しました。 class RPN < Array # 与えられた逆ポーランド記法の式を評価し、結果を返します。 # @param expression [String] 評価する式 # @return [Numeric] 式の評価結果 def eval(expression) expression.split.each do |token| case token when /\A-?\d+\z/, # 十進数 /\A[+-]?0[Bb][01]+\z/, # 2進数 /\A[+-]?0[Oo][0-7]+\z/, # 8進数 /\A[+-]?0[Xx][0-9A-Fa-f]+\z/ # 10進数 push Integer(token) when /\A-?\d+(\.\d+)?([eE][-+]?\d+)?\z/ # 浮動小数点数 push(token.to_f) when *%w[+ - * / % ** & | ^ << >>] # 二項演算子 left, right = pop(2) push left.send(token.to_sym, right) else raise RuntimeError, "Invalid operator: #{token}" end end # 最終的な結果はスタックの一番上に残る peek end # スタックの一番上の値を返しますが、スタックから削除しません。 # @return [Numeric, nil] スタックの一番上の値。スタックが空の場合はnilを返します。 alias peek last end require 'minitest/autorun' class TestRPN < Minitest::Test def setup @rpn = RPN.new end def test_eval_with_single_operand assert_equal 5, @rpn.eval('5') assert_equal 5, @rpn.eval('0b101') assert_equal -5, @rpn.eval('-0b101') assert_equal 5, @rpn.eval('+0b101') assert_equal 127, @rpn.eval('0o177') assert_equal -127, @rpn.eval('-0o177') assert_equal 127, @rpn.eval('+0O177') assert_equal 195935983, @rpn.eval('0xbadbeef') assert_equal -195935983, @rpn.eval('-0xbadbeef') assert_equal 1.5, @rpn.eval('1.5') assert_equal 1e234, @rpn.eval('1e+234') end def test_eval_with_addition assert_equal 8, @rpn.eval('3 5 +') assert_equal 10, @rpn.eval('2 +') end def test_eval_with_subtraction assert_equal 7, @rpn.eval('10 3 -') end def test_eval_with_multiplication assert_equal 24, @rpn.eval('4 6 *') end def test_eval_with_division assert_equal 5, @rpn.eval('15 3 /') end def test_eval_with_remain assert_equal 2, @rpn.eval('11 3 %') end def test_eval_with_exponentiation assert_equal 8, @rpn.eval('2 3 **') assert_equal 1.4142135623730951, @rpn.eval('2 0.5 **') assert_equal 633825300114114700748351602688, @rpn.eval('2 99 **') end def test_eval_with_bitwidth_and assert_equal 8, @rpn.eval('12 10 &') assert_raises(NoMethodError) { @rpn.eval('12.0 10 &') } assert_raises(TypeError) { @rpn.eval('12 10.0 &') } end def test_eval_with_bitwidth_or assert_equal 14, @rpn.eval('12 10 |') assert_raises(NoMethodError) { @rpn.eval('12.0 10 |') } assert_raises(TypeError) { @rpn.eval('12 10.0 |') } end def test_eval_with_bitwidth_exclusive_or assert_equal 6, @rpn.eval('12 10 ^') assert_raises(NoMethodError) { @rpn.eval('12.0 10 ^') } assert_raises(TypeError) { @rpn.eval('12 10.0 ^') } end def test_eval_with_shift_left assert_equal 12288, @rpn.eval('12 10 <<') assert_raises(NoMethodError) { @rpn.eval('12.0 10 <<') } assert_equal 12288, @rpn.eval('12 10.1 <<') end def test_eval_with_shift_right assert_equal 15, @rpn.eval('123 3 >>') assert_raises(NoMethodError) { @rpn.eval('123.0 3 >>') } assert_equal 15, @rpn.eval('123 3.9 >>') end def test_eval_with_invalid_expression assert_raises(TypeError) { @rpn.eval('2 +') } end def test_peek_returns_top_element @rpn.eval('1 2 3 + +') assert_equal 6, @rpn.peek end def test_nan_or_zero_division @rpn.eval('0.0 0 /') assert @rpn.peek.nan? @rpn.eval('0 0.0 /') assert @rpn.peek.nan? @rpn.eval('-0.0 0 /') assert @rpn.peek.nan? assert_raises(ZeroDivisionError) { @rpn.eval('0 0 /') } end def test_inf_or_zero_division @rpn.eval('1.0 0 /') assert_equal Float::INFINITY, @rpn.peek @rpn.eval('-1 0.0 /') assert_equal -Float::INFINITY, @rpn.peek @rpn.eval('1 -0.0 /') assert_equal -Float::INFINITY, @rpn.peek @rpn.eval('-1 -0.0 /') assert_equal Float::INFINITY, @rpn.peek assert_raises(ZeroDivisionError) { @rpn.eval('110 0 /') } end def test_peek_returns_nil_for_empty_stack assert_nil @rpn.peek end end </syntaxhighlight> このコードは、逆ポーランド記法(Reverse Polish Notation)の式を評価するためのRPN(Reverse Polish Notation)クラスを定義しています。このクラスは、与えられた式をスタックを使用して解析し、計算します。以下に、このコードの機能と構造についての解説を行います。 ; RPNクラス * <code># frozen_string_literal: true</code>: この行は、ファイル内の文字列リテラルが変更されないことを確認するためのリテラルです。 * <code>RPN</code>クラスは<code>Array</code>クラスを継承しており、スタックとしての機能を使用します。 * <code>eval</code>メソッドは与えられた逆ポーランド記法の式を評価し、結果を返します。 * <code>peek</code>メソッドは、スタックの一番上の値を返しますが、スタックから削除しません。 ; テストケース * <code>TestRPN</code>クラスは<code>Minitest::Test</code>を継承しており、RPNクラスのテストを定義します。 * <code>setup</code>メソッドは各テストメソッドの前に実行され、テストで使用するRPNオブジェクトをセットアップします。 ; テストメソッド * <code>test_eval_with_single_operand</code>から<code>test_eval_with_invalid_expression</code>までのメソッドは、<code>eval</code>メソッドが正しく動作することを確認するためのテストです。 * <code>test_peek_returns_top_element</code>は<code>peek</code>メソッドがスタックの一番上の値を返すことを確認するテストです。 * <code>test_nan_or_zero_division</code>と<code>test_inf_or_zero_division</code>は、NaNやInfinityの扱い、ゼロ除算の例外処理をテストします。 * これらのテストは、RPNクラスの各機能が正しく動作することを保証します。 このコードは、逆ポーランド記法の式の評価に関する機能を提供し、テストによってその正確性が検証されています。 ==== RSpec ==== RSpecは、Rubyでのテストを行うためのフレームワークの1つです。RSpecを使用すると、テストをより明確に記述し、テスト結果を見やすく出力することができます。 ;Gemfile:<syntaxhighlight lang=ruby> # Gemfile source 'https://rubygems.org' gem 'rspec' </syntaxhighlight> ;導入:<syntaxhighlight lang=shell> # コマンドライン bundle install </syntaxhighlight> ==== ユニットテストと統合テストの書き方 ==== ユニットテストは、個々のコンポーネント(クラスやメソッドなど)が正しく機能するかをテストするものです。一方、統合テストは複数のコンポーネントが互いに連携して正しく動作するかをテストします。 ;spec/my_class_spec.rb:<syntaxhighlight lang=ruby> # spec/my_class_spec.rb (ユニットテスト) require 'my_class' RSpec.describe MyClass do describe '#method_name' do it 'returns something' do obj = MyClass.new expect(obj.method_name).to eq(something) end end end </syntaxhighlight> ;spec/integration_spec.rb:<syntaxhighlight lang=ruby> # spec/integration_spec.rb (統合テスト) require 'app' RSpec.describe 'Integration Test' do it 'checks something' do # 統合テストの実装 end end </syntaxhighlight> RSpecを使ってユニットテストと統合テストを書くことで、コードの品質を向上させ、予期せぬバグを見つけるのに役立ちます。 == 上級編 == === 高度なオブジェクト指向プログラミング === ==== 継承、ポリモーフィズム、カプセル化の活用 ==== 継承は、既存のクラスから新しいクラスを作成し、そのクラスが親クラスのすべての特性を引き継ぐことができる機能です。ポリモーフィズムは、同じ名前のメソッドが異なるクラスで異なる振る舞いをすることを指します。カプセル化は、データやメソッドをオブジェクト内部に隠蔽し、外部からのアクセスを制限することです。これらの概念を活用することで、より柔軟で効率的なコードを書くことができます。 :<syntaxhighlight lang=ruby> class Animal def speak raise NotImplementedError, "Subclasses must implement the 'speak' method." end end class Dog < Animal def speak "Woof!" end end class Cat < Animal def speak "Meow!" end end dog = Dog.new puts dog.speak # => "Woof!" cat = Cat.new puts cat.speak # => "Meow!" </syntaxhighlight> 上記の例では、<code>Animal</code>クラスが親クラスとして定義され、<code>speak</code>メソッドが定義されています。<code>Dog</code>クラスと<code>Cat</code>クラスはそれぞれ<code>Animal</code>クラスを継承し、<code>speak</code>メソッドをオーバーライドしています。これにより、<code>Dog</code>クラスと<code>Cat</code>クラスは同じ名前のメソッドを持ちつつも、それぞれ異なる振る舞いをします。 ==== オブジェクト指向デザインパターンの理解と実装 ==== オブジェクト指向デザインパターンは、再利用可能なソフトウェア設計のガイドラインです。これらのパターンは、特定の問題に対する解決策を提供し、コードの再利用性、拡張性、保守性を向上させます。代表的なデザインパターンには、Singleton、Factory、Observer、Decoratorなどがあります。 {{See|デザインパターン}} :<syntaxhighlight lang=ruby> # Singleton パターンの例 require 'singleton' class SingletonClass include Singleton def initialize @counter = 0 end def increment_counter @counter += 1 end def get_counter @counter end end instance1 = SingletonClass.instance instance1.increment_counter puts instance1.get_counter # => 1 instance2 = SingletonClass.instance puts instance2.get_counter # => 1 </syntaxhighlight> 上記の例では、Singletonパターンを使用して、特定のクラスのインスタンスが常に1つしか存在しないことを保証しています。<code>Singleton</code>モジュールをインクルードすることで、インスタンスが複数作成されることを防ぎます。 === 並行プログラミング === ==== スレッド、プロセスの管理 ==== Rubyにおける並行プログラミングは、スレッドとプロセスを使用して実現されます。スレッドはプロセス内で動作し、複数のスレッドが同時に実行されることで並行処理が可能になります。一方、プロセスは独立した実行単位であり、それぞれが独自のメモリ空間を持ちます。 以下では、Rubyにおけるスレッドとプロセスの管理について解説し、コード例を示します。 ===== スレッド ===== Rubyでは<code>Thread</code>クラスを使用してスレッドを作成し、<code>Thread.new</code>メソッドを使って新しいスレッドを生成します。生成されたスレッドは並行して実行され、メインスレッドと同時に動作します。スレッドの制御には<code>join</code>メソッドを使用して、メインスレッドがスレッドの終了を待機することができます。 :<syntaxhighlight lang=ruby> threads = [] # スレッドを生成して配列に格納 threads << Thread.new do 3.times do sleep 1 puts "Thread 1 executing" end end threads << Thread.new do 3.times do sleep 2 puts "Thread 2 executing" end end # 全てのスレッドが終了するのを待機 threads.each(&:join) puts "All threads finished" </syntaxhighlight> 上記の例では、2つのスレッドを生成し、それぞれが一定間隔でメッセージを出力しています。<code>join</code>メソッドにより、メインスレッドが全てのスレッドの終了を待機します。 ===== プロセス ===== Rubyでは、<code>fork</code>メソッドを使用して新しいプロセスをフォークし、子プロセス内で処理を実行することができます。プロセスの終了を待機するには<code>Process.wait</code>メソッドを使用します。 :<syntaxhighlight lang=ruby> child_pid = fork do puts "Child process executing" sleep 3 puts "Child process finished" end puts "Parent process waiting for child to finish" Process.wait(child_pid) puts "Parent process finished waiting" </syntaxhighlight> 上記の例では、親プロセスが子プロセスをフォークし、子プロセスが一定時間待機した後に終了します。親プロセスは<code>Process.wait</code>メソッドで子プロセスの終了を待機します。 Rubyのスレッドとプロセスを使った並行プログラミングには、他にも多くの機能や制御方法がありますが、基本的な部分はこのようになります。 ==== スレッド、プロセス以外の並行プログラミング ==== Rubyには、スレッドとプロセス以外にも並行プログラミングを行うためのさまざまな手段があります。以下にいくつかの方法を紹介します。 ===== Fiber ===== Fiberは、イテレータと似たコンテキストを持つ軽量なスレッドのようなものです。複数のFiberを作成し、それらを切り替えながら処理を行うことで、非同期の並行処理を実現することができます。 :<syntaxhighlight lang=ruby> fiber1 = Fiber.new do puts "Fiber 1 executing" Fiber.yield puts "Fiber 1 resumed" end fiber2 = Fiber.new do puts "Fiber 2 executing" Fiber.yield puts "Fiber 2 resumed" end fiber1.resume fiber2.resume fiber1.resume fiber2.resume </syntaxhighlight> ===== Concurrent Ruby gem ===== Concurrent Ruby gemは、並行プログラミングを行うための機能を提供するGemです。ThreadPoolやFuture、Promise、Actorなどの機能を使って、複雑な並行処理を実現することができます。 :<syntaxhighlight lang=ruby> require 'concurrent' pool = Concurrent::FixedThreadPool.new(5) future = Concurrent::Future.execute(executor: pool) do # 並行処理を実行するコード sleep 1 "Future result" end puts "Waiting for future to complete..." puts future.value </syntaxhighlight> ===== Celluloid gem ===== Celluloid gemは、アクターモデルをベースにした並行プログラミングを行うためのGemです。アクターモデルでは、個々のアクターがメッセージを送受信しながら処理を実行します。 :<syntaxhighlight lang=ruby> require 'celluloid' class MyActor include Celluloid def initialize puts "Actor initialized" end def process_message(message) puts "Received message: #{message}" end end actor = MyActor.new actor.async.process_message("Hello from main thread!") </syntaxhighlight> これらの手法を使うことで、Rubyでより効果的な並行プログラミングを実現することができます。選択肢はプロジェクトの要件や好みに応じて異なりますが、Rubyの並行処理に関する柔軟性と機能性は広範囲にわたっています。 ==== 並行処理の問題点と解決策 ==== 並行プログラミングでは、競合状態やデッドロックなどの問題が発生する可能性があります。競合状態は、複数のスレッドが同時に共有されたリソースにアクセスしようとすることで起こります。デッドロックは、複数のスレッドがお互いにリソースを解放するのを待ち合わせることで発生します。 これらの問題を回避するための解決策として、適切なロックの使用、スレッドセーフなデータ構造の選択、並行処理の慎重な設計などがあります。 並行処理の問題点と解決策について、コード例を示して説明します。 ===== 問題点: 競合状態 ===== 競合状態は、複数のスレッドが同時に共有されたリソースにアクセスしようとすることで発生します。 以下は、競合状態が発生する可能性のあるコード例です。 :<syntaxhighlight lang=ruby> counter = 0 threads = 10.times.map do Thread.new do 1000.times { counter += 1 } end end threads.each(&:join) puts "Counter: #{counter}" </syntaxhighlight> このコードでは、複数のスレッドが<code>counter</code>変数にアクセスしています。しかし、<code>counter += 1</code>の操作は複数のスレッドで同時に実行される可能性があり、結果として期待通りにカウンターが増加しない可能性があります。 ===== 解決策: ロックの使用 ===== 競合状態を回避するために、ロックを使用して複数のスレッドが同時に共有されたリソースにアクセスできないようにします。Rubyでは、<code>Mutex</code>クラスを使用してスレッドセーフなロックを実装できます。 :<syntaxhighlight lang=ruby> counter = 0 mutex = Mutex.new threads = 10.times.map do Thread.new do 1000.times do mutex.synchronize { counter += 1 } end end end threads.each(&:join) puts "Counter: #{counter}" </syntaxhighlight> このコードでは、<code>Mutex</code>を使用して<code>counter</code>変数へのアクセスを同期化しています。 これにより、複数のスレッドが同時に<code>counter</code>変数にアクセスすることができず、競合状態が回避されます。 ===== 問題点: デッドロック ===== デッドロックは、複数のスレッドがお互いにリソースを解放するのを待ち合わせることで発生します。 以下は、デッドロックが発生する可能性のあるコード例です。 :<syntaxhighlight lang=ruby> mutex1 = Mutex.new mutex2 = Mutex.new thread1 = Thread.new do mutex1.lock sleep 1 mutex2.lock mutex1.unlock mutex2.unlock end thread2 = Thread.new do mutex2.lock sleep 1 mutex1.lock mutex2.unlock mutex1.unlock end thread1.join thread2.join </syntaxhighlight> このコードでは、<code>thread1</code>が<code>mutex1</code>をロックし、同時に<code>thread2</code>が<code>mutex2</code>をロックする可能性があります。その後、各スレッドは相手のロックを解放するのを待ち合わせることになり、デッドロックが発生します。 ===== 解決策: ロックの順序付け ===== デッドロックを回避するために、ロックを取得する順序を一貫させることが重要です。 この方法により、複数のスレッドが同じ順序でロックを取得しようとしても、デッドロックを引き起こすことがありません。 :<syntaxhighlight lang=ruby highlight=13> mutex1 = Mutex.new mutex2 = Mutex.new thread1 = Thread.new do mutex1.lock sleep 1 mutex2.lock mutex1.unlock mutex2.unlock end thread2 = Thread.new do mutex1.lock # ロックの順序を変更 sleep 1 mutex2.lock mutex1.unlock mutex2.unlock end thread1.join thread2.join </syntaxhighlight> この修正では、<code>thread2</code>が<code>mutex1</code>を先にロックするように変更されており、ロックの順序が一致しています。これにより、デッドロックが発生する可能性が低くなります。 以上が、並行処理の問題点とその解決策をコード例を交えて説明したものです。競合状態やデッドロックは並行プログラミングにおける一般的な問題であり、適切な対処が必要です。 === Webアプリケーション開発 === ==== Ruby on Railsなどのフレームワークを使用したWebアプリケーションの開発 ==== Ruby on Railsは、RubyでのWebアプリケーション開発を支援する人気のあるフレームワークです。Railsを使用することで、MVC(Model-View-Controller)アーキテクチャをベースにした効率的なWebアプリケーションを開発することができます。 :<syntaxhighlight lang=shell> # Railsアプリケーションの作成 rails new myapp # モデルの作成 rails generate model User name:string email:string # データベースマイグレーションの実行 rails db:migrate # コントローラの作成 rails generate controller UsersController </syntaxhighlight> ;config/routes.rb:<syntaxhighlight lang=ruby> # ルーティングの設定 Rails.application.routes.draw do resources :users end </syntaxhighlight> Railsでは、コマンドラインツールを使用してモデルやコントローラを簡単に生成し、ルーティングを設定することができます。これにより、短期間で効率的なWebアプリケーションを構築することができます。 {{Main|Ruby on Rails}} ==== MVCアーキテクチャの理解 ==== MVC(Model-View-Controller)アーキテクチャは、アプリケーションの設計を3つの主要なコンポーネントに分割するアーキテクチャパターンです。 ;モデル (Model): :*データやビジネスロジックを担当します。 :*アプリケーションの状態やデータを管理し、ビューに表示されるデータを提供します。 :*モデルは通常、データベースや外部サービスとのやり取りも担当します。 ;ビュー (View): :*ユーザーインターフェース(UI)の表示を担当します。 :*ユーザーにデータを視覚的に提示し、ユーザーからの入力を受け付けます。 :*ビューは通常、モデルからデータを受け取り、それをユーザーに見やすい形で表示します。 ;コントローラ (Controller): :*ユーザーからの入力を受け付け、それに基づいてモデルやビューの操作を制御します。 :*ユーザーの操作に応じてモデルの状態を変更し、ビューの更新をトリガーします。 :*コントローラはユーザーとアプリケーションの主要な仲介者であり、ビジネスロジックを含む場合があります。 ;相互関係: :*ユーザーがビューで何かしらの操作を行うと、それに対するイベントがコントローラに送信されます。 :*コントローラはそのイベントを受け取り、必要に応じてモデルを更新したり、新しいデータをビューに送ったりします。 :*モデルが変更されると、モデルはその変更をビューに通知します。 :*ビューは通知を受け取り、表示を更新します。 このように、MVCアーキテクチャは各コンポーネントが疎結合であり、変更が発生した際に一部のコンポーネントを変更しても他のコンポーネントに影響を与えにくい特徴があります。これにより、柔軟性が向上し、保守性が高まります。 ===== RoRにおけるMVC ===== RoR(Ruby on Rails)は、MVC(Model-View-Controller)アーキテクチャの理念に基づいて設計されたWebアプリケーションフレームワークです。RoRにおけるMVCの役割と機能を説明します。 ; モデル (Model) * RoRのモデルは、アプリケーションのデータベースとのやり取りを担当します。 * モデルはActive Recordとして実装されており、データベースのテーブルと対応するオブジェクトを表現します。 * モデルはビジネスロジックを含み、データの検証や処理を行います。 :<syntaxhighlight lang=ruby> class User < ApplicationRecord validates :name, presence: true end </syntaxhighlight> ; ビュー (View) * RoRのビューは、ユーザーにデータを表示するためのテンプレートを提供します。 * HTMLやERB(Embedded Ruby)などのテンプレートエンジンを使用して、動的なコンテンツを生成します。 * ビューは主にユーザーインターフェースの生成に使用されます。 :<syntaxhighlight lang=ruby> <% @users.each do |user| %> <p><%= user.name %></p> <% end %> </syntaxhighlight> ; コントローラ (Controller) * RoRのコントローラは、ユーザーからのリクエストを受け取り、それに応じて適切な処理を行います。 * リクエストの解析やデータの操作など、ビジネスロジックの一部もコントローラで処理されます。 * ビューの表示を制御し、モデルへのデータの渡し方もコントローラで決定されます。 :<syntaxhighlight lang=ruby> class UsersController < ApplicationController def index @users = User.all end end </syntaxhighlight> ; ルーティング (Routing) * RoRでは、URLとコントローラアクションの対応をルーティングで定義します。 * ルーティングは<code>config/routes.rb</code>ファイルに記述され、特定のURLパスへのリクエストを特定のコントローラアクションにマップします。 :<syntaxhighlight lang=ruby> Rails.application.routes.draw do resources :users, only: [:index] end </syntaxhighlight> ; MVCの相互関係 * ユーザーからのリクエストはルーティングで適切なコントローラアクションに送信されます。 * コントローラは必要に応じてモデルからデータを取得し、適切なビューをレンダリングしてユーザーに表示します。 * ビューはユーザーにデータを表示し、必要に応じてユーザーの入力を受け付けます。 * ユーザーの入力やアクションによっては、再びコントローラへリクエストが送信され、その処理が繰り返されます。 Ruby on RailsはMVCアーキテクチャにより、アプリケーションの各コンポーネントが明確に分離され、保守性が向上し、柔軟性が高まります。 === データベース連携 === ==== SQLデータベースとの接続 ==== Railsでは、アクティブレコードと呼ばれるオブジェクト関係マッピング(ORM)ツールを使用して、データベースとのやり取りを簡単に行うことができます。アクティブレコードを使用することで、SQLクエリを直接記述せずに、Rubyオブジェクトとしてデータベースのテーブルを操作することができます。 :<syntaxhighlight lang=ruby> # ユーザーデータの取得 users = User.all # 新しいユーザーの作成 user = User.new(name: "Alice", email: "alice@example.com") user.save </syntaxhighlight> Railsでは、データベースへの接続設定を行うことで、アプリケーション内でアクティブレコードを使用してデータベースとやり取りすることができます。 ==== ORM(Object-Relational Mapping)の活用 ==== ORMは、オブジェクトとリレーショナルデータベースとの間のマッピングを行うためのツールです。ORMを使用することで、データベースのテーブルをオブジェクトとして操作することができ、SQLクエリの記述を最小限に抑えることができます。これにより、コードの可読性や保守性が向上します。 ===パフォーマンスチューニング=== ====メモリ管理、コードの最適化==== メモリ管理とコードの最適化は、Rubyプログラミングにおいて重要な要素です。効率的なメモリ管理を行うことで、アプリケーションのメモリ使用量を最小限に抑え、パフォーマンスを向上させることができます。また、コードの最適化により、処理速度を高速化し、リソースの効率的な利用を実現することができます。 ;メモリ管理のベストプラクティス: *不要なオブジェクトの解放: 不要なオブジェクトを定期的に解放することで、メモリリークを防止しましょう。 *大量のデータの処理: 大規模なデータ処理が必要な場合は、メモリを過剰に消費することがあります。代わりに、イテレータやジェネレータを使用してデータを効率的に処理しましょう。 *メモリフラグメンテーション: メモリフラグメンテーションが発生すると、メモリが不連続に配置されるため、効率的なメモリ使用が妨げられます。適切なメモリ管理を行い、フラグメンテーションを最小限に抑えましょう。 ;コードの最適化のベストプラクティス: *効率的なアルゴリズムの選択: 適切なアルゴリズムを選択することで、処理速度を向上させることができます。時間計算量や空間計算量を考慮して、最適なアルゴリズムを選択しましょう。 *不要なループの削減: 不要なループや再帰呼び出しを削減することで、処理速度を向上させることができます。ループのネストを最小限に抑え、効率的なコードを作成しましょう。 *遅延読み込み: 大きなデータセットを扱う場合は、遅延読み込みを活用して、必要な時点でデータを取得するようにしましょう。これにより、不要なデータの読み込みを回避し、メモリ使用量を最小限に抑えることができます。 =====プロファイリングツールの使用===== プロファイリングツールは、アプリケーションのパフォーマンスを詳細に分析し、ボトルネックを特定するための有用なツールです。プロファイリングツールを使用することで、どの部分が最もリソースを消費しているかや、どの部分が最も遅いかなどを把握することができます。 ;代表的なプロファイリングツール: *RubyProf: Rubyのプロファイリングツールの1つであり、メソッドごとの実行時間や呼び出し回数などを詳細に分析することができます。 *StackProf: スレッドごとのスタックトレースを収集し、アプリケーションのホットスポットを特定することができるプロファイリングツールです。 *DTrace: オペレーティングシステムレベルでのパフォーマンス分析を行うための強力なツールであり、Rubyアプリケーションのボトルネックを特定するのに役立ちます。 これらのプロファイリングツールを使用して、アプリケーションのパフォーマンスを詳細に分析し、効率的な最適化を行いましょう。 ;プロファイリング手法と注意点: *アプリケーション全体のプロファイリング: アプリケーション全体のプロファイリングを行うことで、全体のパフォーマンスを把握し、最も時間がかかる部分を特定します。この情報をもとに、重点的に最適化を行いましょう。 *繰り返し実行による平均化: プロファイリングを行う際には、複数回の実行を行い、結果を平均化することが重要です。これにより、ランダムな外部要因の影響を排除し、より正確なプロファイリング結果を得ることができます。 *プロファイリングの結果の解釈: プロファイリング結果を解釈する際には、アプリケーションのコードや処理の特性を理解することが重要です。高負荷がかかっている部分やボトルネックを正確に特定し、効果的な最適化を行いましょう。 *プロファイリングの定期的な実施: アプリケーションのコードや処理が変更されるたびに、プロファイリングを定期的に実施することで、パフォーマンスの変化や問題点を早期に検出し、適切な対策を講じることができます。 *セキュリティとプライバシー: プロファイリングツールを使用する際には、セキュリティとプライバシーに配慮しましょう。機密情報や個人情報が含まれる可能性がある場合は、適切な対策を講じて情報漏洩を防止しましょう。 ;総括 :メモリ管理、コードの最適化、およびプロファイリングツールの使用は、Rubyプログラミングにおいてアプリケーションのパフォーマンスを向上させるために重要なスキルです。効率的なメモリ管理とコードの最適化により、リソースの効率的な利用を実現し、プロファイリングツールを使用してボトルネックを特定し、効果的な最適化を行うことで、より高速で効率的なアプリケーションを開発することができます。 === さらなるトピック === ====オブジェクト指向デザインパターンの活用==== 上級レベルでは、オブジェクト指向デザインパターンの理解と実装に焦点を当てましたが、実際のアプリケーション開発では、これらのパターンを活用して柔軟で効率的なコードを書くことが重要です。より実践的な例や、実際の問題に対する解決策を学ぶことで、より高度な開発スキルを身につけることができます。 ====セキュリティとエラーハンドリング==== プロの開発者になるためには、セキュリティとエラーハンドリングの重要性を理解し、適切な対策を講じることが不可欠です。セキュリティホールや悪意のある攻撃からアプリケーションを保護し、エラーが発生した際にユーザーやシステムに影響を与えないようにするための方法を学びましょう。 ====テスト駆動開発(TDD)==== テスト駆動開発(Test-Driven Development, TDD)は、コードを書く前にテストを書き、そのテストをパスするようなコードを実装する開発手法です。TDDを実践することで、より品質の高いコードを生産し、バグの早期発見やリファクタリングの容易化が可能となります。 ====コード品質とリファクタリング==== コード品質は、プロの開発者にとって非常に重要な要素です。コードを読みやすく、保守しやすく、拡張しやすくするためのリファクタリングのテクニックやベストプラクティスを学び、コードベースを常に改善していきましょう。 これらのトピックを網羅的に学ぶことで、より高度なRubyプログラミングスキルを身につけることができます。プロの開発者としてのキャリアを築くために、着実にスキルを向上させていきましょう。 == リファレンス編 == === 変数 === Rubyの変数は、オブジェクトに名前をつけるために使われます。 Rubyでは、変数は宣言する必要はありません。 オブジェクトを変数に代入するには :<syntaxhighlight lang=ruby> 変数名 = オブジェクト </syntaxhighlight> の様に代入演算子 <code>=</code> を使います。 ;[https://paiza.io/projects/x1_UlCeb1PtW8pG8Xi-i-g?language=ruby 変数へのオブジェクトの代入と参照]:<syntaxhighlight lang=ruby> a = 1 p a # => 1 a = "abc" p a # => "abc" a = [1, 2, 3] p a # => [1, 2, 3] b = a p b # => [1, 2, 3] b[1] = 999 p a # => [1, 999, 3] # bはaと同じ配列を参照しているため、bの変更がaにも反映されます。 </syntaxhighlight> {{コラム|puts メソッドと p メソッド|2= putsメソッドはオブジェクトにto_sメソッドで適用した結果を表示します。 これに対し、pメソッドはオブジェクトにinspectメソッドで適用した結果を表示します。 ;[https://paiza.io/projects/uZV53RJGbr3FKbscJc8tiw?language=ruby putsとp]:<syntaxhighlight lang=ruby> puts "Hello, world!" # => Hello, world! p "Hello, world!" # => "Hello, world!" </syntaxhighlight> }} === 定数 === Rubyにおける定数は、変更できない値のことです。定数は大文字で始まり、一度値を代入するとその後変更することができません。定数を宣言するには、変数名の先頭に大文字のアルファベットを付けます。 定数は、クラスやモジュールの定義内で宣言される場合、そのクラスやモジュールのスコープにのみ存在します。クラスやモジュール外で宣言された定数は、グローバルスコープに属します。 定数にアクセスするには、定数名を参照します。定数が未定義の場合、RubyはNameError例外を発生させます。 以下は、定数を宣言して参照する例です。 :<syntaxhighlight lang=ruby line> # クラス内で定数を宣言する class MyClass MY_CONSTANT = 100 end # クラス外で定数を参照する puts MyClass::MY_CONSTANT #=> 100 </syntaxhighlight> また、Rubyでは組み込み定数もいくつか存在します。例えば、<code>Math::PI</code>は円周率を表す定数です。 === グローバル変数 === グローバル変数は、プログラム中のどこからでもアクセス可能な変数です。グローバル変数は、<code>$</code>記号で始まる変数名を持ちます。一般的に、グローバル変数は、複数のメソッドで共有するデータを格納するために使用されます。ただし、グローバル変数は多用すべきではなく、できるだけ避けるべきです。 :<syntaxhighlight lang=ruby line> $global_variable = 10 def print_global puts "Global variable is #$global_variable" end print_global </syntaxhighlight> このコードでは、<code>$global_variable</code>というグローバル変数が定義されています。そして、<code>print_global</code>メソッド内でその値が参照されて表示されます。グローバル変数はプログラム中のどこからでも参照可能であるため、異なるメソッド間でデータを共有する場合に使用されます。しかし、グローバル変数の使用は避けるべきであり、できるだけローカル変数やインスタンス変数を使用することが推奨されます。 === 特殊変数 === 特殊変数は、Rubyがあらかじめ定義している変数で、プログラム中で直接代入することができません。これらの変数は、プログラムの実行中に自動的に設定され、Rubyの様々な機能で使用されます。 * <code>$0</code>: 現在のプログラムファイル名 * <code>$~</code>: 最後にマッチした正規表現 * <code>$&</code>: 最後にマッチした文字列 * <code>$'</code>: 最後にマッチした文字列より後ろの文字列 * <code>$'</code>: 最後にマッチした文字列より後ろの文字列 * <code>$1</code>, <code>$2</code>, <code>$3</code>...: 最後にマッチした正規表現の1番目、2番目、3番目...のキャプチャグループにマッチした文字列 * <code>$stdin</code>: 標準入力 * <code>$stdout</code>: 標準出力 * <code>$stderr</code>: 標準エラー出力 * <code>$LOAD_PATH</code>: ライブラリの検索パス * <code>$:</code>: ライブラリの検索パス(<code>$LOAD_PATH</code>の別名) :<syntaxhighlight lang=ruby line> puts "This program's name is #{$0}" puts "The Ruby version is #{RUBY_VERSION}" puts "The current line number is #{$.}" </syntaxhighlight> === オブジェクト === Rubyは完全なオブジェクト指向言語であり、すべてがオブジェクトです。オブジェクトは、データとそれに対する操作をカプセル化したものであり、オブジェクトを操作するためにメソッドを使用します。 以下は、オブジェクトについての基本的な説明です。 * オブジェクトは、Rubyの世界で唯一の存在であり、それぞれが固有の状態と振る舞いを持っています。 * オブジェクトは、何らかのデータ(文字列、数値、配列、ハッシュ、ファイルなど)を表します。例えば、整数、浮動小数点数、有理数や複素数などの数値を表すオブジェクトがあり、文字列オブジェクトはテキストを表します。 * オブジェクトは、そのデータを操作するためのメソッドを提供します。メソッドは、オブジェクトの状態を変更することができます。例えば、数値オブジェクトには、加算や減算などの算術演算を行うためのメソッドがあります(演算子もメソッドです)。文字列オブジェクトには、文字列の結合や部分文字列の取得などのメソッドがあります。 * オブジェクトは、クラスと呼ばれるテンプレートから作成されます。クラスは、オブジェクトのデータやメソッドを定義するための設計図です。オブジェクトは、クラスのインスタンスとして作成されます。 * オブジェクトは、他のオブジェクトとやり取りすることができます。オブジェクトは、別のオブジェクトをメソッドの引数として受け取ることができ、戻り値としても返すことができます。 これらのオブジェクトのクラスを知ることは、そのオブジェクトがどのような振る舞いをするかを理解するために非常に重要です。 ==== Objectクラス ==== Rubyにおけるすべてのオブジェクトは、<code>Object</code>から継承されています。<code>Object</code>には、すべてのオブジェクトに共通するメソッドが定義されています。 以下は、<code>Object</code>に関する基本的な説明です。 * Rubyのすべてのオブジェクトは、<code>Object</code>のサブクラスであるため、<code>Object</code>に定義されているメソッドはすべてのオブジェクトで利用できます。 * <code>Object</code>には、例外を発生させる<code>raise</code>メソッドや、オブジェクトのクラスを取得する<code>class</code>メソッド、オブジェクトが同一かどうかを判定する<code>equal?</code>メソッドなど、多くの便利なメソッドが定義されています。 * <code>Object</code>には、<code>to_s</code>メソッドも定義されており、すべてのオブジェクトは<code>to_s</code>メソッドを呼び出すことができます。<code>to_s</code>メソッドは、オブジェクトを文字列に変換します。このメソッドは、デバッグやログ出力などに活用されます。 * <code>Object</code>には、同一性比較に使用される<code>==</code>メソッドも定義されています。<code>==</code>メソッドは、2つのオブジェクトが同じかどうかを比較します。オブジェクトの同一性を比較する場合は、<code>equal?</code>メソッドを使用します。 * <code>Object</code>には、<code>.initialize</code>メソッドも定義されており、新しいオブジェクトを作成する際に呼び出されます。<code>.initialize</code>メソッドをオーバーライドすることで、新しいオブジェクトが初期化される際の処理をカスタマイズすることができます。 ==== オブジェクトのクラスを調べる ==== オブジェクトのクラスを調べるには、Objectクラスの<code>class</code>メソッドを使います。 :<syntaxhighlight lang=ruby> puts "Hello, world!".class # ==> String puts 10.class # ==> Integer puts 3.14.class # ==> Float puts [2, 3, 5, 7, 11].class # ==> Array puts ({"key1" => "value1", "key2" => "value2"}).class # ==> Hash puts /hello/.class # ==> Regexp puts (1..10).class # ==> Range puts :abc.class # ==> Symbol puts false.class # ==> FalseClass puts true.class # ==> TrueClass puts nil.class # ==> NilClass puts (lambda {|x, y| x + y }).class # ==> Proc puts Complex(3, 4).class # ==> Complex puts Rational(22, 7).class # ==> Rational puts Time.now.class # ==> Time puts Struct.new("Cat", :sex, :age).class # ==> Class </syntaxhighlight> :{| class="sortable wikitable" |+ <code>Object</code>クラスの代表的なメソッド !メソッド名 !引数の数 !説明 |- |<code>!=</code> |1 |オブジェクトと引数が等しくない場合に<code>true</code>、等しい場合に<code>false</code>を返す |- |<code>!</code> |0 |オブジェクトが<code>false</code>または<code>nil</code>の場合に<code>true</code>を返す |- |<code>==</code> |1 |オブジェクトと引数が等しい場合に<code>true</code>、等しくない場合に<code>false</code>を返す |- |<code>===</code> |1 |引数がオブジェクトと等しい場合に<code>true</code>、そうでない場合に<code>false</code>を返す |- |<code>__id__</code> |0 |オブジェクトの<code>object_id</code>を返す |- |<code>__send__</code> |1以上 |メソッドを動的に呼び出す |- |<code>class</code> |0 |オブジェクトのクラスを返す |- |<code>clone</code> |0 |オブジェクトを複製して返す |- |<code>dup</code> |0 |オブジェクトを浅く複製して返す |- |<code>equal?</code> |1 |オブジェクトと引数が同じオブジェクトである場合に<code>true</code>、そうでない場合に<code>false</code>を返す |- |<code>instance_eval</code> |0または1 |レシーバーオブジェクトに対してブロックを評価する |- |<code>instance_of?</code> |1 |オブジェクトが指定したクラスのインスタンスである場合に<code>true</code>、そうでない場合に<code>false</code>を返す |- |<code>instance_variable_defined?</code> |1 |指定されたインスタンス変数が定義されている場合に<code>true</code>、そうでない場合に<code>false</code>を返す |- |<code>instance_variable_get</code> |1 |指定されたインスタンス変数の値を取得する |- |<code>instance_variable_set</code> |2 |指定されたインスタンス変数に値を設定する |- |<code>kind_of?</code> |1 |オブジェクトが指定したクラスのインスタンスである場合に<code>true</code>、そうでない場合に<code>false</code>を返す |- |<code>method</code> |1 |指定されたメソッドオブジェクトを返す |- |<code>nil?</code> |0 |オブジェクトが<code>nil</code> |} === 式と演算子 === Rubyにおける式と演算子について説明します。 ==== 式 ==== Rubyにおける式とは、ある値を評価するためのコードのことを指します。例えば、以下のような式があります。 :<syntaxhighlight lang=ruby> 1 + 2 </syntaxhighlight> この式は、<code>1</code>と<code>2</code>を足した結果を評価するための式です。この式を実行すると、<code>3</code>という値が返されます。 ==== 演算子 ==== 演算子は、式を組み合わせたり、値を変更するために使用されます。Rubyにはさまざまな種類の演算子があります。以下はいくつかの例です。 ===== 数値演算子 ===== 数値演算子には、加算、減算、乗算、除算、剰余演算子などがあります。 以下はいくつかの例です。 ;[https://paiza.io/projects/z2HDB6CbEbLClzWILhmpmA?language=python3 operators.rb]:<syntaxhighlight lang=ruby style="width:fit-content"> # 整数 p 10 + 3 # 13: 加算 p 10 - 3 # 7: 減算 p 10 * 3 # 30: 乗算 p 10 / 3 # 3: 除算 p 10 % 3 # 1: 剰余演算 # 文字列 p "abc" + "xyz" # abcxyz: 連結 p "abc" * 3 # abcabcabc: 反復 p "%x" % 77 # 4d: 書式化 # 配列 p [1, 2, 3] + [7, 8, 9] # [1, 2, 3, 7, 8, 9]: 連結 # 有理数 p Rational(2, 3) + 3 # (11/3) p Rational(2, 3) - 3 # (-7/3) p Rational(2, 3) * 3 # (2/1) p Rational(2, 3) / 3 # (2/9) # 複素数 p (-2)**0.5 # (0.0+1.4142135623730951i) p Complex(2, 3) + 3 # (5+3i) p Complex(2, 3) - 3 # (-1+3i) p Complex(2, 3) * 3 # (6+9i) p Complex(2, 3) / 3 # ((2/3)+1i) </syntaxhighlight> Rubyの四則演算子と剰余演算子は、通常の数値演算に使用されることが一般的ですが、オブジェクト指向プログラミング言語であるRubyでは、これらの演算子がオーバーロードされることがあります。 数値演算子の使用は、さまざまなデータ型に対して行われます。整数、文字列、配列、有理数、複素数など、Rubyは様々なデータ型をサポートしており、それぞれのデータ型に対して適切な演算が行われます。 例えば、文字列の場合、加算演算子は文字列の連結を行います。同様に、整数や有理数の場合は数値演算が行われますが、複素数の場合は複素数の演算が行われます。 また、Rubyでは四則演算子や剰余演算子などの演算子がオーバーロードされることがあります。これにより、ユーザー定義のクラスやオブジェクトに対して独自の演算を定義することができます。オブジェクト指向の特性を活かした柔軟な演算の定義が可能です。 数値演算子の適切な使用は、プログラムの正確性や効率性に直結します。Rubyの数値演算子を適切に理解し、適切に活用することで、より効率的で読みやすいコードを書くことができます。 ===== 比較演算子 ===== 比較演算子とComparableモジュールは、Rubyにおいてオブジェクトの比較を可能にする重要な機能です。 比較演算子には以下のようなものがあります: * <code>==</code>: 等しい * <code>!=</code>: 等しくない * <code>></code>: より大きい * <code><</code>: より小さい * <code>>=</code>: 以上 * <code><=</code>: 以下 以下はいくつかの例です。 :<syntaxhighlight lang=ruby> a = 1 b = 2 puts a == b # 等しい puts a != b # 等しくない puts a > b # より大きい puts a < b # より小さい puts a >= b # 以上 puts a <= b # 以下 </syntaxhighlight> これらの演算子を使って、オブジェクト同士を比較することができます。例えば、整数同士や文字列同士の比較などが挙げられます。 ====== Comparableモジュール ====== Comparableモジュールは、比較可能なオブジェクトを定義するためのモジュールです。このモジュールをクラスにincludeすることで、そのクラスのインスタンス同士を比較可能にすることができます。 Comparableモジュールでは、<code><=></code>演算子(スペース船演算子)を実装する必要があります。この演算子は、二つのオブジェクトを比較して以下のような値を返します: * 自身が他のオブジェクトより小さい場合は負の整数 * 自身が他のオブジェクトと等しい場合はゼロ * 自身が他のオブジェクトより大きい場合は正の整数 Comparableモジュールを使用することで、クラス内で<code><=></code>演算子を定義するだけで、そのクラスのインスタンス同士を比較することができます。これにより、コードの可読性を高め、一貫した比較処理を実現することができます。 例えば、数値や文字列など、大小関係を持つオブジェクトを扱う場合に便利です。また、<code>min</code>や<code>max</code>などのメソッドを利用して、比較可能なオブジェクトの最小値や最大値を簡単に取得することもできます。 :<syntaxhighlight lang=ruby> class Person include Comparable attr_accessor :name, :age def initialize(name, age) @name = name @age = age end def <=>(other) @age <=> other.age end end p1 = Person.new("Alice", 25) p2 = Person.new("Bob", 30) puts p1 < p2 # true puts p1 == p2 # false puts p1 > p2 # false </syntaxhighlight> <code>Person</code>クラスでは、<code><=></code>演算子を定義して、<code>age</code>インスタンス変数を比較しています。そのため、<code>Person</code>クラスのインスタンスは、<code><</code>, <code><=</code>, <code>==</code>, <code>></code>, <code>>=</code>, <code>between?</code>演算子によって比較可能になります。 ===== 論理演算子 ===== 論理演算子には、AND、OR、NOT演算子があります。以下はいくつかの例です。 :<syntaxhighlight lang=ruby> a = true b = false puts a && b # false: AND puts a and b # true: AND(低い優先度なのでputsと先に結合) puts a || b # true: OR puts a or b # true: OR(低い優先度) puts !a # false: NOT </syntaxhighlight> *<code>&&</code> の優先度は <code>||</code> より強いです(論理'''積'''と論理'''和'''なので)。 *<code>||</code> の優先度は <code>and</code> より強いです(単語版の方が弱いとおぼえてください)。 *<code>and</code> の優先度は <code>or</code> より強いです(論理積と論理和なので)。 以下に、論理積 (<code>AND</code>)、論理和 (<code>OR</code>)、論理否定 (<code>NOT</code>) を表現するための真理値表を示します。 {| class="wikitable" style="float:left" |+ 論理積 (<code>AND</code>) !A !B !A AND B |- |0 |0 |0 |- |0 |1 |0 |- |1 |0 |0 |- |1 |1 |1 |} {| class="wikitable" style="float:left" |+ 論理和 (<code>OR</code>) !A !B !A OR B |- |0 |0 |0 |- |0 |1 |1 |- |1 |0 |1 |- |1 |1 |1 |} {| class="wikitable" style="float:left" |+ 論理否定 (<code>NOT</code>) !A !NOT A |- |0 |1 |- |1 |0 |} <br style="clear:both"> 上記の表で、A と B はそれぞれ真 (1) または偽 (0) の値を表し、AND や OR などの論理演算子によって表された結果は、真 (1) または偽 (0) のいずれかです。 また、論理否定では、NOT A は A の真偽を反転させた値となります。 ====== 短絡評価 ====== Rubyの短絡評価とは、論理式の評価において、最初の式で結果が確定した場合に、その後の式を評価しないことを指します。つまり、式が最初の部分で真偽値が確定した場合、後続の式を評価せずに即座に結果を返します。 例えば、以下のようなコードがあったとします。 :<syntaxhighlight lang=ruby> def check_name(name = nil) if name && name.length > 0 puts "名前は#{name}です" else puts "名前が未入力です" end end check_name() # => "名前が未入力です" check_name("") # => "名前が未入力です" check_name("John") # => "名前はJohnです" </syntaxhighlight> このコードでは、<code>name</code> が <code>nil</code> でないかつ文字列の長さが0より大きいかを同時にチェックしています。 具体的には、条件式 <code>name && name.length > 0</code> によってチェックしています。 この条件式では、短絡評価 (short-circuit evaluation) が利用されています。短絡評価とは、条件式の全ての部分を評価せずに、最初に結果が確定した部分で評価を終了するという評価方法です。 具体的には、この場合は<code>name</code>が<code>nil</code>である場合、<code>name.length > 0</code> の評価は行われず、条件式全体が<code>false</code>と判定されます。 このような短絡評価の利用により、コードのパフォーマンスを向上させることができます。また、<code>name</code> が <code>nil</code> の場合に <code>name.length</code> を呼び出すことがなくなるため、エラーを避けることができます。 しかし、短絡評価を乱用すると、プログラムの可読性が低下したり、バグを引き起こしたりすることがあります。適切な場面でのみ利用するようにしましょう。 : 論理演算子(AND, OR)は演算子の姿をしていますが、内実は制御構造です。そのため論理演算子は演算子オーバーロード出来ません。 ==== Rubyでは演算子もメソッド ==== 「Rubyでは演算子もメソッド」とは、Rubyにおいて演算子 (たとえば <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> など) が単なる記号ではなく、それぞれが対応するメソッドとして定義されているということを指します。 例えば、<code>+</code> 演算子は、2つの数値を足し合わせるために使われますが、実際には <code>+</code> メソッドとして定義されています。以下のように <code>+</code> メソッドを使って足し算を行うことができます。 :<syntaxhighlight lang=ruby> a = 1 b = 2 c = a.+(b) # a + b と同じ puts c # => 3 </syntaxhighlight> また、<code>*</code> 演算子も同様に <code>*</code> メソッドとして定義されています。以下のように、文字列に対して <code>*</code> メソッドを使って、指定した回数だけ繰り返した新しい文字列を作ることができます。 :<syntaxhighlight lang=ruby> str = "hello" new_str = str.*(3) # str * 3 と同じ puts new_str # => "hellohellohello" </syntaxhighlight> このように、Rubyでは演算子も単なる記号ではなく、それぞれが対応するメソッドとして定義されているため、オブジェクト指向の考え方に基づいた柔軟なプログラミングが可能になっています。 ==== Rubyで演算子メソッドをオーバーロード ==== Rubyでは、クラスやモジュールで演算子に対応するメソッドを定義することができます。このようにして定義された演算子メソッドをオーバーロードと呼びます。 以下は、<code>Vector2</code> クラスで <code>+</code> 演算子に対応するメソッドを定義する例です。このメソッドでは、<code>Vector2</code> クラスのインスタンス同士を足し合わせることができます。 :<syntaxhighlight lang=ruby> class Vector2 attr_accessor :x, :y def initialize(x, y) @x = x @y = y end def +(other) Vector2.new(@x + other.x, @y + other.y) end def to_s() "[#{@x}, #{@y}]" end end v1 = Vector2.new(1, 2) v2 = Vector2.new(3, 4) v3 = v1 + v2 # => Vector2オブジェクト puts v3 # => [4, 6] </syntaxhighlight> このコードは、2次元ベクトルを表す <code>Vector2</code> クラスを定義し、2つのベクトルを足し合わせるメソッドを実装しています。 まず、<code>attr_accessor</code> によって、<code>x</code> と <code>y</code> のインスタンス変数に対する getter/setter メソッドが定義されています。これによって、外部から <code>v1.x</code> のようにしてインスタンス変数にアクセスしたり、<code>v1.x = 10</code> のようにしてインスタンス変数に値を代入したりできます。 次に、<code>initialize</code> メソッドが定義されています。これは、<code>new</code> メソッドが呼ばれた時に、引数として渡された <code>x</code> と <code>y</code> をインスタンス変数 <code>@x</code> と <code>@y</code> に代入するためのコンストラクタです。 <code>+</code> メソッドは、引数として与えられた <code>other</code> という別の <code>Vector2</code> オブジェクトを足し合わせ、新しい <code>Vector2</code> オブジェクトを作成して返します。これによって、<code>v1 + v2</code> のようにして2つのベクトルを足し合わせることができます。 最後に、<code>to_s</code> メソッドが定義されています。これは、オブジェクトを文字列に変換するためのメソッドで、ベクトルの座標を <code>[x, y]</code> のような形式の文字列に変換して返します。 実際に、<code>v1</code> と <code>v2</code> を足し合わせた結果を <code>v3</code> に代入し、<code>puts v3</code> で <code>v3</code> を表示しています。<code>v3</code> の値は <code>[4, 6]</code> となります。 このように演算子メソッドをオーバーロードすることで、プログラムの読みやすさや柔軟性を高めることができます。ただし、意図しない挙動を招くこともあるため、注意して使いましょう。 ==== 演算子オーバーロード ==== Rubyでは、演算子をオーバーロードすることが出来ます。 オーバーロード可能な演算子には、組み込みクラスの演算子も含まれます。 :<syntaxhighlight lang=ruby highlight=2> class String def /(s) = split(s) end ary = "The quick brown fox jumps over the lazy dog" / " " p ary # => ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"] str = ary * " ! " p str # => "The ! quick ! brown ! fox ! jumps ! over ! the ! lazy ! dog" </syntaxhighlight> このコードは、Rubyの <code>String</code> クラスに、新しいメソッド <code>/</code> を追加しています。 <code>/</code> メソッドは、文字列を引数 <code>s</code> で分割するためのメソッドです。 実装は <code>split</code> メソッドを呼び出すだけで、文字列オブジェクト自身を <code>self</code> で表しています。 まず、<code>/</code> メソッドによって、文字列 <code>"The quick brown fox jumps over the lazy dog"</code> がスペース <code>" "</code> で分割され、配列 <code>ary</code> に格納されます。 ここで <code>ary</code> は、<code>["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]</code> という値を持ちます。 次に、<code>*</code> メソッドによって、配列 <code>ary</code> が感嘆符 <code>"!"</code> で連結され、文字列 <code>str</code> が作成されます。 ここで <code>str</code> は、<code>"The ! quick ! brown ! fox ! jumps ! over ! the ! lazy ! dog"</code> という値を持ちます。 このように、<code>/</code> と <code>*</code> メソッドを利用することで、簡単に文字列の分割や連結を行うことができます。 ただし、他の開発者がこのようなメソッドを利用しているコードを読む場合、このような振る舞いを予想できない可能性があるため、注意が必要です。 <code>/</code> と <code>*</code> を、それぞれ文字列の分割と結合に割り当てる例は、[[Pike]]に見ることが出来ます。 ==== 演算子の優先順位と結合方向 ==== ;演算子の優先順位 演算子には優先順位があります。 例えば、以下のようなコードがあった場合、演算子の優先順位に従って評価されます。 :<syntaxhighlight lang=ruby> a = 2 + 3 * 4 ** 2 / 2 </syntaxhighlight> ここで、**は先に評価されます。次に、*と/が同じ優先順位なので、左から右に評価されます。最後に+が-よりも優先度が高いので、+が評価されます。 :<syntaxhighlight lang=ruby> a = 2 + ( ( 3 * ( 4 ** 2 ) ) / 2 ) </syntaxhighlight> つまり、aの値は50になります。 ;演算子の結合方向 同じ優先順位の演算子が続いた場合、演算子の結合方向により実行順序が決まります。 例えば、以下のコードがある場合、 :<syntaxhighlight lang=ruby> a = 2 ** 3 ** 2 </syntaxhighlight> <code>**</code>は'''右結合'''なので、<code>3 ** 2</code>が先に評価されます。そして、<code>2 ** 9</code>が評価されて、aは512になります。 :<syntaxhighlight lang=ruby> a = 2 ** ( 3 ** 2 ) </syntaxhighlight> 以下は、Rubyの演算子の優先順位と結合方向の表です。 :{| class=wikitable |+ Rubyの演算子の優先順位と結合方向 !演算子 !説明 !優先順位 !結合方向 |- !:: |クラスやオブジェクトのネスト | style="text-align:center;" | 1 | style="text-align:center;" |左結合 |- <!-- ruby のソースを読むと、ここに . 属性参照が入るはず --> ![] |配列やハッシュから要素を取得する | style="text-align:center;" | 2 | style="text-align:center;" |左結合 |- !+ |単項演算子(正) | rowspan=3 style="text-align:center;" | 3 | rowspan=3 style="text-align:center;" |'''右結合''' |- !<nowiki>!</nowiki> |論理否定 |- !~ |ビット否定 |- !** |べき乗 | style="text-align:center;" | 4 | style="text-align:center;" |'''右結合''' |- !- |単項演算子(負) | style="text-align:center;" | 5 | style="text-align:center;" |'''右結合''' |- !* |乗算 | rowspan=3 style="text-align:center;" | 6 | rowspan=3 style="text-align:center;" |左結合 |- !/ |除算 |- !% |剰余算 |- !+ |加算 | rowspan=2 style="text-align:center;" | 7 | rowspan=2 style="text-align:center;" |左結合 |- !- |減算 |- !<< |ビットシフト(左) | rowspan=2 style="text-align:center;" | 8 | rowspan=2 style="text-align:center;" |左結合 |- !>> |ビットシフト(右) |- !& |ビット積 | style="text-align:center;" | 9 | style="text-align:center;" |左結合 |- ! <nowiki>|</nowiki> |ビット和 | rowspan=2 style="text-align:center;" | 10 | rowspan=2 style="text-align:center;" |左結合 |- !^ |ビット排他的論理和 |- ! > |大なり | rowspan=4 style="text-align:center;" | 11 | rowspan=4 style="text-align:center;" |左結合 |- ! >= |以上 |- ! < |未満 |- ! <= |以下 |- ! <=> |比較 | rowspan=6 style="text-align:center;" | 12 | rowspan=6 style="text-align:center;" |左結合 |- ! == |一致 |- ! === |厳密に一致 |- ! <nowiki>!=</nowiki> |不一致 |- ! =~ |パターンマッチング |- ! <nowiki>!~</nowiki> | アンマッチ |- !&& |論理積 | style="text-align:center;" | 13 | style="text-align:center;" |左結合 |- !<nowiki>||</nowiki> |論理和 | style="text-align:center;" | 14 | style="text-align:center;" |左結合 |- !.. |範囲を生成する(終端を含む) | rowspan=2 style="text-align:center;" | 15 | rowspan=2 style="text-align:center;" |左結合 |- !... |範囲を生成する(終端を含まない) |- !? : |条件演算子 | style="text-align:center;" | 16 | style="text-align:center;" |'''右結合''' |- != |代入 | rowspan=2 style="text-align:center;" | 17 | rowspan=2 style="text-align:center;" |'''右結合''' |- !op= |代入演算子 |- !not |論理否定 | style="text-align:center;" | 18 | style="text-align:center;" |'''右結合''' |- !and |論理積 | rowspan=2 style="text-align:center;" | 19 | rowspan=2 style="text-align:center;" |左結合 |- !or |論理和 |} :優先順位が高い演算子から順に、結合方向の左右を記載しています。 :表中の "op= " は、代入演算子の一般形を表しています。具体的な代入演算子には、"+= "、"-= "、"*= "、"/= "、"%= "、"||= "、"&&= "、"||= "、"|= "、"&= "、"^= "などがあります。 ;コード例:<syntaxhighlight lang=ruby> a = 5 b = 10 puts "a = #{a}" puts "b = #{b}" puts "-" * 20 # 算術演算子 puts "算術演算子:" puts "a + b = #{a + b}" puts "a - b = #{a - b}" puts "a * b = #{a * b}" puts "b / a = #{b / a}" puts "b % a = #{b % a}" puts "a ** 2 = #{a ** 2}" puts "-" * 20 # 比較演算子 puts "比較演算子:" puts "a == b : #{a == b}" puts "a != b : #{a != b}" puts "a > b : #{a > b}" puts "a < b : #{a < b}" puts "b >= a : #{b >= a}" puts "a <= b : #{a <= b}" puts "-" * 20 # 論理演算子 puts "論理演算子:" puts "a == 5 && b == 10 : #{a == 5 && b == 10}" puts "a == 5 || b == 5 : #{a == 5 || b == 5}" puts "! (a == 5) : #{!(a == 5)}" puts "-" * 20 # 代入演算子 puts "代入演算子:" puts "a += b : #{a += b}" puts "a -= b : #{a -= b}" puts "a *= b : #{a *= b}" puts "a /= b : #{a /= b}" puts "a %= b : #{a %= b}" puts "a **= 2 : #{a **= 2}" puts "-" * 20 # 三項演算子 puts "三項演算子:" puts "a > b ? 'a is greater than b' : 'a is less than or equal to b'" puts "-" * 20 # ビット演算子 puts "ビット演算子:" puts "a & b : #{a & b}" puts "a | b : #{a | b}" puts "a ^ b : #{a ^ b}" puts "~a : #{~a}" puts "a << 1 : #{a << 1}" puts "a >> 1 : #{a >> 1}" puts "-" * 20 # 演算子メソッド puts "演算子メソッド:" puts "a == b : #{a.==(b)}" puts "a != b : #{a.!=(b)}" puts "a > b : #{a.>(b)}" puts "a < b : #{a.<(b)}" puts "b >= a : #{b.>=(a)}" puts "a <= b : #{a.<=(b)}" puts "a <=> b : #{a.<=>(b)}" puts "a === b : #{a.===(b)}" puts "a =~ b : #{a.=~(b)}" puts "-" * 20 # その他の演算子 puts "その他の演算子:" puts "defined? a : #{defined?(a)}" puts "(1..10).each do |i| puts i end" puts ":symbol.to_s : #{:symbol.to_s}" puts "%w(one two three) : #{%w(one two three)}" puts "-" * 20 </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> a = 5 b = 10 -------------------- 算術演算子: a + b = 15 a - b = -5 a * b = 50 b / a = 2 b % a = 0 a ** 2 = 25 -------------------- 比較演算子: a == b : false a != b : true a > b : false a < b : true b >= a : true a <= b : true -------------------- 論理演算子: a == 5 && b == 10 : true a == 5 || b == 5 : true ! (a == 5) : false -------------------- 代入演算子: a += b : 15 a -= b : 5 a *= b : 50 a /= b : 5 a %= b : 5 a **= 2 : 25 -------------------- 三項演算子: a > b ? 'a is greater than b' : 'a is less than or equal to b' -------------------- ビット演算子: a & b : 8 a | b : 27 a ^ b : 19 ~a : -26 a << 1 : 50 a >> 1 : 12 -------------------- 演算子メソッド: a == b : false a != b : true a > b : true a < b : false b >= a : false a <= b : false a <=> b : 1 a === b : false a =~ b : -------------------- その他の演算子: defined? a : local-variable (1..10).each do |i| puts i end :symbol.to_s : symbol %w(one two three) : ["one", "two", "three"] -------------------- </syntaxhighlight> === 制御構造 === Rubyには、if-else-elsif-end、unless-else-end、case-when-else-end、case-in-else-end、while文、until文、for文、そしてbegin-rescue-else-ensure-endのような例外処理構文など、様々な制御構造があります。 これらの制御構造を使うことで、プログラムの実行を条件に応じたループや分岐によって制御することができます。 制御構造を正しく理解し、適切に使用することで、効率的で洗練されたプログラムを書くことができます。 また広義の制御構造にはブロックを伴う each や loop などのメソッドも含まれ、ここではそれらについても解説します。 ;書式概観:<syntaxhighlight lang=ruby> # if-elsif-else-end if 条件式1 then 処理1 elsif 条件式2 then 処理2 else 処理3 end # if修飾子 式 if 条件式 # unless-else-end unless 条件式 then 処理1 else 処理2 end # unless修飾子 式 unless 条件式 # case-when-else-end case 対象のオブジェクト when 条件式1 then 処理1 when 条件式2 then 処理2 when 条件式3 then 処理3 else 処理4 end # while文 while 条件式 do 処理 end # while修飾子 式 while 条件式 # until文 until 条件式 do 処理 end # until修飾子 式 until 条件式 # for文 for 変数 in 範囲 do 処理 end # loopメソッド loop do 処理 end # eachメソッド コレクション.each do |変数| 処理 end # timesメソッド 回数.times do |変数| 処理 end </syntaxhighlight> ==== 条件分岐 ==== Rubyの条件分岐には、if-elsif-else-end、unless-else-end、そしてcase-when-else-endがあります。 また、if, unless には修飾子構文もあります。 ===== if-elsif-else-end ===== if-elsif-else-endは、条件に応じて処理を分岐するためのもっとも基本的な構文です。 :<syntaxhighlight lang=ruby> if 条件式1 処理1 elsif 条件式2 処理2 else 処理3 end </syntaxhighlight> 例えば、ある数値変数numが0未満なら「negative」、0なら「zero」、0より大きいなら「positive」と表示するプログラムは以下のように書けます。 :<syntaxhighlight lang=ruby> num = -3 if num < 0 puts "negative" elsif num == 0 puts "zero" else puts "positive" end </syntaxhighlight> ===== if修飾子 ===== if修飾子は、条件式が肯定されたとき式を評価する構文です。 :<syntaxhighlight lang=ruby> 式 if 条件式 </syntaxhighlight> 例えば、ある数値変数numが0未満なら「negative」と表示するプログラムは以下のように書けます。 :<syntaxhighlight lang=ruby> num = -3 puts "negative" if num < 0 </syntaxhighlight> ===== unless-else-end ===== unless-else-endは、if-elsif-else-endと似たような構文ですが、条件式が否定されたときに処理が実行されます。 :<syntaxhighlight lang=ruby> unless 条件式 処理1 else 処理2 end </syntaxhighlight> 例えば、ある数値変数numが0以上なら「non-negative」、0未満なら「negative」と表示するプログラムは以下のように書けます。 :<syntaxhighlight lang=ruby> num = -3 unless num >= 0 puts "negative" else puts "non-negative" end </syntaxhighlight> ===== unless修飾子 ===== unless修飾子は、if修飾子に似ていますが、条件式が否定されたときに式を評価する構文です。 :<syntaxhighlight lang=ruby> 式 unless 条件式 </syntaxhighlight> 例えば、ある数値変数numが0以上でなければ「negative」と表示するプログラムは以下のように書けます。 :<syntaxhighlight lang=ruby> num = -3 puts "negative" unless num >= 0 </syntaxhighlight> ===== case-when-else-end ===== case-when-else-endは、複数の値に応じて処理を分岐するための構文です。if-elsif-else-endと比較して、1つのオブジェクトに対して複数の条件式を一度に評価できるという利点があります。 :<syntaxhighlight lang=ruby> case オブジェクト when 条件式1 処理1 when 条件式2 処理2 else 処理3 end </syntaxhighlight> 例えば、ある文字変数cに対して、それが母音なら「vowel」、子音なら「consonant」、数字なら「number」、それ以外なら「other」と表示するプログラムは以下のように書けます。 :<syntaxhighlight lang=ruby> c = 'a' case c when 'a', 'e', 'i', 'o', 'u' puts "vowel" when '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' puts "number" when 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z' puts "consonant" else puts "other" end </syntaxhighlight> ====== when へのオブジェクト ====== Rubyの <code>case</code> 文では、比較に用いるオブジェクトの型に応じて条件分岐することができます。具体的には、<code>case</code> 文の式の型が以下のいずれかである場合に、対応する条件分岐が行われます。 * 整数型 (<code>Integer</code>) の場合 * 文字列型 (<code>String</code>) の場合 * 正規表現型 (<code>Regexp</code>) の場合 * クラスオブジェクト (<code>Class</code>) の場合 以下に、それぞれの場合の例を示します。 ;整数型の場合 :<syntaxhighlight lang=ruby> case num when 0 puts "num is zero" when 1 puts "num is one" when 2 puts "num is two" else puts "num is something else" end </syntaxhighlight> ;文字列型の場合 :<syntaxhighlight lang=ruby> case str when "foo" puts "str is foo" when "bar" puts "str is bar" when /baz/ puts "str includes baz" else puts "str is something else" end </syntaxhighlight> ;正規表現型の場合 :<syntaxhighlight lang=ruby> case str when /foo/ puts "str includes foo" when /bar/ puts "str includes bar" when Regexp.new("baz") puts "str includes baz" else puts "str is something else" end </syntaxhighlight> ;クラスオブジェクトの場合 :<syntaxhighlight lang=ruby> case obj when Integer puts "obj is an instance of Integer" when String puts "obj is an instance of String" when Array puts "obj is an instance of Array" else puts "obj is an instance of something else" end </syntaxhighlight> これらの例では、<code>case</code> 文の式の型によって、比較に用いるオブジェクトの型や正規表現パターンが異なることに注意してください。また、どの条件にも一致しない場合に実行される <code>else</code> 節は省略可能です。 {{コラム|Rubyのif,unless,caseは式|2=Rubyの <code>if</code>、<code>unless</code>、<code>case</code> は、制御フロー構文としての使い方に加えて、式としても使うことができます。 例えば、<code>if</code> 式を使ってみましょう。通常の <code>if</code> は、条件が <code>true</code> ならば処理を実行します。 :<syntaxhighlight lang=ruby> if x > 10 puts "x is greater than 10" end </syntaxhighlight> この <code>if</code> 文を式として使うこともできます。具体的には、以下のように <code>if</code> の後ろに式を書き、式の値が <code>true</code> であれば、<code>if</code> の条件式の評価値が式の値となります。 :<syntaxhighlight lang=ruby> a = if x > 10 "x is greater than 10" else "x is less than or equal to 10" end puts a </syntaxhighlight> 同様に、<code>unless</code> も式として使うことができます。 :<syntaxhighlight lang=ruby> a = unless x > 10 "x is less than or equal to 10" else "x is greater than 10" end puts a </syntaxhighlight> また、<code>case</code> 式もあります。<code>case</code> 式は、複数の条件に対する分岐処理を行う場合に使われます。以下は、<code>case</code> 式の例です。 :<syntaxhighlight lang=ruby> a = case x when 1 "one" when 2 "two" else "other" end puts a </syntaxhighlight> <code>case</code> 式では、<code>when</code> 句を使って、複数の条件式を書くことができます。<code>case</code> 式の評価値は、<code>when</code> 句の条件式と一致する最初のものの右辺の式の値となります。 }} ==== パターンマッチング ==== Rubyのパターンマッチングは、バージョン2.7で導入された新機能であり、構造化された値に対してパターンをマッチングすることができます。これにより、より複雑なデータ構造を柔軟に操作できるようになります。 以下に、Rubyのパターンマッチングの基本的な構文と機能について説明します。 ===== 基本的な構文 ===== :<syntaxhighlight lang=ruby> case 式 in パターン1 # パターン1にマッチする場合の処理 in パターン2 # パターン2にマッチする場合の処理 else # どのパターンにもマッチしない場合の処理 end </syntaxhighlight> ===== パターン ===== パターンは以下のようなものがあります: * 値パターン(Value pattern) * 配列パターン(Array pattern) * ハッシュパターン(Hash pattern) * 検索パターン(Find pattern) * 変数キャプチャ(Variable capture) * その他のパターン(Alternative pattern) ===== 変数バインディング ===== パターンマッチングによって、マッチした部分をローカル変数にバインドすることができます。 :<syntaxhighlight lang=ruby> case [1, 2] in Integer => a, Integer puts "マッチしました: #{a}" else puts "マッチしませんでした" end </syntaxhighlight> ===== ガード節 ===== <code>if</code>を使用して、パターンがマッチした場合に追加の条件を指定することができます。 :<syntaxhighlight lang=ruby> case [1, 2] in a, b if b == a * 2 puts "マッチしました" else puts "マッチしませんでした" end </syntaxhighlight> ===== パターンの合成 ===== 複数のパターンを組み合わせてマッチングを行うこともできます。 :<syntaxhighlight lang=ruby> case [1, 2] in [1, Integer] puts "マッチしました" else puts "マッチしませんでした" end </syntaxhighlight> ===== 例外の扱い ===== パターンマッチングが失敗した場合には、例外が発生します。これは、<code>NoMatchingPatternError</code>として知られています。 ===== メソッドの利用 ===== カスタムクラスに対してパターンマッチングを行う場合、<code>deconstruct</code>や<code>deconstruct_keys</code>メソッドを実装することでマッチングを行うことができます。 ===== パターンマッチングの利点 ===== * より読みやすいコードを書くことができます。 * より安全なコードを書くことができます。 * より柔軟なデータ操作が可能になります。 以上が、Rubyのパターンマッチングについての基本的な説明です。この機能は、プログラミングのパラダイムをより関数型プログラミング寄りのスタイルに変えることができます。 ==== 反復 ==== Rubyの反復構文は、特定の条件が満たされるまでコードのブロックを繰り返すことができる文のセットです。最も一般的な反復文は、while、until、for、loop です。 * while文は、ある条件が真である限り、コードのブロックを実行します。 * until文は、ある条件が偽である限り、コードのブロックを実行します。 * for文は、要素のコレクションを繰り返し処理し、各要素に対してコードのブロックを実行します。 また、while, until には修飾子構文もあります。 これらの基本的な反復処理文に加えて、Ruby には break、next、redo、lazy などの反復処理文があります。これらの文により、コードの実行の流れを制御することができます。 ===== while文 ===== ;例:<syntaxhighlight lang=ruby> # このコードでは、1から10までの数字を表示します。 while i <= 10 do puts i i += 1 end </syntaxhighlight> while文の構文は以下の通り: ;構文:<syntaxhighlight lang=ruby> while 条件 do # 処理 end </syntaxhighlight> 条件とは、ループの実行を継続するためにtrueと評価されなければならないブール値の式です。 処理の部分は、条件が真である限って実行されるコードのブロックです。 まえの例では、条件は「i <= 10」です。これは、iの値が10以下である限り、ループが実行され続けることを意味します。 処理の部分は、puts i行です。この行はiの値をコンソールに出力します。 while文は、特定の条件が満たされる限り、コードのブロックを繰り返すことができる強力なツールです。 ===== while修飾子 ===== while修飾子は、if修飾子に似ていますが、条件式が肯定されている間は式を評価し続ける構文です。 :<syntaxhighlight lang=ruby> 式 while 条件式 </syntaxhighlight> 例えば、ある数値変数numが0未満の間、num に 2 を足し続けるプログラムは以下のように書けます。 :<syntaxhighlight lang=ruby> num = -3 num += 2 while num < 0 </syntaxhighlight> ===== until文 ===== ;例:<syntaxhighlight lang=ruby> # このコードでは、10から1までの数字を表示します。 i = 10 until i <= 1 do puts i i -= 1 end </syntaxhighlight> until文の構文は以下の通り: ;構文:<syntaxhighlight lang=ruby> until 条件 do # 処理 end </syntaxhighlight> 条件とは、ループの実行を継続するためにfalseと評価されなければならないブール値の式です。 処理の部分は、条件が偽である限って実行されるコードのブロックです。 まえの例では、条件はi <= 1である。これは、iの値が1以上である限り、ループが実行され続けることを意味します。 処理の部分は、puts i行です。この行はiの値をコンソールに出力します。 until文は、特定の条件が満たされない限り、コードのブロックを繰り返すために使用できる強力なツールです。 ===== until修飾子 ===== until修飾子は、while修飾子に似ていますが、条件式が否定されている間は式を評価し続ける構文です。 :<syntaxhighlight lang=ruby> 式 until 条件式 </syntaxhighlight> 例えば、ある数値変数numが0以上でない間、num に 2 を足し続けるプログラムは以下のように書けます。 :<syntaxhighlight lang=ruby> num = -3 num += 2 until num >= 0 </syntaxhighlight> ===== for文 ===== ;例:<syntaxhighlight lang=ruby> # このコードでは、配列の要素を順に表示します。 array = [2, 3, 5, 7, 11] for element in array puts element end puts element #=> 11 ## forループを抜けてもスコープは終わらない </syntaxhighlight> for文の構文は以下の通り: ;構文:<syntaxhighlight lang=ruby> for ループ変数 in コレクション # ループ変数にまつわる処理 end </syntaxhighlight> ループ変数は、コレクション内の現在の要素のプレースホルダーです。 コレクションは、配列、範囲、その他の反復可能なオブジェクトのいずれでもかまいません。 ループ変数にまつわる処理の部分は、コレクション内の各要素に対して実行されるコードのブロックです。 この例では、コレクションは配列[2, 3, 5, 7, 11]です。ループ変数はelementです。 ループ変数にまつわる処理の部分は、puts element行です。この行は、elementの値をコンソールに表示します。 for文は、要素のコレクションを繰り返し処理するために使用できる強力なツールです。 ==== 反復制御文 ==== Rubyには、反復制御を行う文が5つあります。 * break : break文は、現在のループを終了させる。 * next : 現在のループの繰り返しをスキップする。 * redo : 現在のループの繰り返しを再び実行する。 * retry: 例外処理をリトライする。 * return : メソッドを終了します。現在のループの繰り返しも終了します。 反復制御文は、Rubyのコードをより効率的に、より読みやすくするために使用できる強力なツールです。 ====== break ====== break文は、現在のループを終了させます。 ;例:<syntaxhighlight lang=ruby> (1..).step(12) do |i| break if i >= 50 puts i end #=> 1 # 13 # 25 # 37 # 49 </syntaxhighlight> このコードは、<code>1</code>から始まり、<code>12</code>ずつ増加する無限の数列を生成し、その数列の各要素を<code>do..end</code>ブロック内で処理しています。各要素は変数<code>i</code>に割り当てられ、<code>puts</code>文を使って出力されます。 しかし、<code>break if i >= 50</code>の部分によって、<code>i</code>が<code>50</code>以上になった場合、ループが終了します。つまり、ループは<code>50</code>未満の値のときだけ実行されます。 このコードは、<code>1, 13, 25, 37, 49</code>といった<code>50</code>未満の数列を出力します。そして、<code>i</code>が<code>50</code>以上の値になった時点でループが終了します。 ====== next ====== next文は、ループの現在の反復をスキップさせます。 ;例:<syntaxhighlight lang=ruby> 1.upto(10) do |i| next if i == 5 puts i end #=> 1 # 2 # 3 # 4 # 6 # 7 # 8 # 9 # 10 </syntaxhighlight> このコードは、<code>1</code>から<code>10</code>までの数列を生成し、その数列の各要素を<code>do..end</code>ブロック内で処理しています。各要素は変数<code>i</code>に割り当てられ、<code>puts</code>文を使って出力されます。 <code>next if i == 5</code>の部分によって、<code>i</code>が<code>5</code>の場合、それ以降の処理をスキップして次の要素の処理に進みます。つまり、<code>5</code>は出力されません。 したがって、このコードは<code>1, 2, 3, 4, 6, 7, 8, 9, 10</code>という数列を出力します。<code>5</code>がスキップされ、それ以外の値が出力されます。 ====== redo ====== redo文は、現在のループの繰り返しを再度実行します。 ;例:<syntaxhighlight lang=ruby> count = 0 (1..10).each do |i| count += 1 redo if i == 5 and count < 20 puts "#{count}: #{i}" end #=> 1: 1 # 2: 2 # 3: 3 # 4: 4 # 20: 5 # 21: 6 # 22: 7 # 23: 8 # 24: 9 # 25: 10 </syntaxhighlight> ===== retry ===== 例外が発生した場合に、その処理をやり直します。 :<syntaxhighlight lang=ruby> begin # 何らかの処理 rescue SomeException retry end </syntaxhighlight> ===== return ===== メソッド内でループを含む場合、<code>return</code>を使ってループからも抜けることができます。以下はその例です。 :<syntaxhighlight lang=ruby> def example_method (1..10).each do |i| return if i == 5 puts i end end example_method </syntaxhighlight> この場合、<code>return</code>が呼び出されると、<code>example_method</code>自体が終了し、その場でループも終了します。 これらのキーワードやメソッドを使うことで、ループの挙動を制御することができます。 ==== 反復メソッド ==== Rubyでは、反復処理を用いて演算を行うメソッドを反復処理メソッドと呼びます。 反復処理とは、コードのブロックを指定された回数だけ、あるいは特定の条件が満たされるまで繰り返す処理のことです。 ==== コレクションのイテレーションメソッド ==== Rubyには、ArrayやHashなどのコレクションオブジェクトを簡単にイテレーションできる多数のメソッドがあります。以下はいくつかの例です: ;例:<syntaxhighlight lang=ruby> # eachメソッド array = [1, 2, 3] array.each { |x| puts x } # mapメソッド array = [1, 2, 3] new_array = array.map { |x| x * 2 } # selectメソッド array = [1, 2, 3] new_array = array.select { |x| x.even? } # reduceメソッド array = [1, 2, 3] sum = array.reduce(0) { |total, x| total + x } # each_with_indexメソッド array = [1, 2, 3] array.each_with_index { |value, index| puts "#{index}: #{value}" } </syntaxhighlight> 上記の例では、以下のように動作しています。 ;eachメソッド:配列の各要素に対して、ブロック内の処理を1回ずつ実行します。この例では、配列の各要素を出力しています。 ;mapメソッド:配列の各要素に対して、ブロック内の処理を1回ずつ実行し、その結果を新しい配列に格納します。この例では、配列の各要素を2倍にして新しい配列を作成しています。 ;selectメソッド:配列の各要素に対して、ブロック内の条件がtrueになる要素だけを抽出して、新しい配列に格納します。この例では、配列の偶数要素だけを抽出して新しい配列を作成しています。 ;reduceメソッド:配列の各要素に対して、ブロック内の演算を順番に適用して、最終的な結果を返します。この例では、配列の各要素を加算して合計を求めています。 ;each_with_indexメソッド:配列の各要素とそのインデックスに対して、ブロック内の処理を1回ずつ実行します。この例では、配列の各要素とそのインデックスを出力しています。 これらのメソッドを使用することで、コレクションの要素に簡単にアクセスできます。また、each_with_indexを使用することで、要素のインデックスにも簡単にアクセスできます。 ==== 暗黙のブロック引数 ==== Rubyには、様々なメソッドやイテレータで使用される暗黙のブロック引数があります。これらは <code>_1</code>, <code>_2</code> などの形式で表され、ブロック内で引数を明示的に書く必要がなくなります。代表的なものを以下に示します。暗黙のブロック引数はRuby 2.7からサポートされました。 # <code>each</code> メソッドなどのイテレータでの使用: #:<syntaxhighlight lang=ruby> numbers = [1, 2, 3, 4, 5] numbers.each { |num| puts num } # 通常の引数を使用する場合 numbers.each { puts _1 } # `_1` を使用することで、暗黙の引数として要素を取得 hash = { a: 1, b: 2, c: 3 } hash.each { |key, value| puts "#{key}: #{vale}" } hash.each { puts "#{_1}: #{_2}" } </syntaxhighlight> # <code>map</code> メソッドでの使用: #:<syntaxhighlight lang=ruby> doubled = numbers.map { |num| num * 2 } # 通常の引数を使用する場合 doubled = numbers.map { _1 * 2 } # `_1` を使用することで、暗黙の引数として要素を取得して計算 </syntaxhighlight> このように、暗黙のブロック引数は通常の引数の代替として使われ、ブロック内でのコードをより簡潔にすることができます。ただし、可読性の観点から、コードが複雑になりすぎないよう注意が必要です。 ==== 整数のイテレーションメソッド ==== Rubyには、数値を連続して扱うための便利なメソッドがあります。その中でもupto、downto、stepはよく使われるものです。これらのメソッドについて解説します。 ;例:<syntaxhighlight lang=ruby> # uptoの例 1.upto(5) do |i| puts i end # 実行結果: 1 2 3 4 5 # downtoの例 5.downto(1) do |i| puts i end # 実行結果: 5 4 3 2 1 # stepの例 1.step(10, 2) do |i| puts i end # 実行結果: 1 3 5 7 9 </syntaxhighlight> 上記の例では、以下のように動作しています。 ;uptoメソッド:整数オブジェクトから別の整数オブジェクトまで、1ずつ増加させながら、ブロック内の処理を繰り返します。この例では、1から5までの整数を順に出力しています。 ;downtoメソッド:整数オブジェクトから別の整数オブジェクトまで、1ずつ減少させながら、ブロック内の処理を繰り返します。この例では、5から1までの整数を順に出力しています。 ;stepメソッド:開始値から終了値まで、指定されたステップで数値を増加させながら、ブロック内の処理を繰り返します。この例では、1から10までの奇数を順に出力しています。stepメソッドで は、第2引数に指定した数値が増加量として使用されます。この例では、2ずつ増加しているため、1, 3, 5, 7, 9という結果になっています。 ==== loopメソッド ==== 過去の編集で、loopをloop文と紹介されていましたが、loopはKernelオブジェクトのメソッドで構文ではありません。 loopメソッドの使い方は以下の通り: :<syntaxhighlight lang=ruby> loop do # 処理 end </syntaxhighlight> 処理の部分は、無限に実行されるコードのブロックです。 ;例:<syntaxhighlight lang=ruby> # このコードは、永久に "This will print forever!" を表示します。 loop do puts "This will print forever!" end </syntaxhighlight> この例では、処理パートは <code>puts "This will print forever!"</code>です。 この行は、"This will print forever!"というメッセージをコンソールに無限に出力します。 ;loopとEnumrator:<syntaxhighlight lang=ruby> enum = [1, 2, 3].each puts enum.class #=> Enumerator loop do puts enum.next end #=> 1 # 2 # 3 </syntaxhighlight> <code>enum</code>は<code>[1, 2, 3].each</code>から生成された<code>[[#列挙(Enumerator)|Enumerator]]</code>です。<code>Enumerator</code>は、<code>each</code>メソッドをブロックなしで呼び出すことで生成され、配列内の各要素を反復処理することができます。 その後、<code>loop</code>構文が使われています。<code>loop</code>構文は、無限ループを作成するためのもので、ループ内のコードを繰り返し実行します。 ループ内では、<code>enum.next</code>が呼び出されています。これにより、<code>Enumerator</code>から次の要素が取得され、その要素が<code>puts</code>メソッドを使って出力されます。最初は1が出力され、次に2、そして3が出力されます。 しかし、3を出力した後、<code>Enumerator</code>からはもう要素がないため、<code>StopIteration</code>例外が発生します。この例外が<code>loop</code>構文によって自動的に捕捉され、ループが終了します。 ==== 反復メソッドと反復制御文 ==== break、next、redo文もこれらのメソッドと一緒に使うことができます。 たとえば、次のようなものです: *break : break 文は、ループの現在の繰り返しを終了させます。 ;例:<syntaxhighlight lang=ruby> array = [1, 2, 3] array.each do |element| puts element break if element == 2 end </syntaxhighlight> このコードでは、配列の要素のうち、要素2までを表示します。 *next : next文は、ループの現在の繰り返しをスキップする。 ;例:<syntaxhighlight lang=ruby> array = [1, 2, 3] array.each do |element| puts element next if element == 2 end </syntaxhighlight> このコードでは、配列の要素を、要素2をスキップして表示します。 *redo : redo文は、ループの現在の繰り返しを再度実行します。 ;例:<syntaxhighlight lang=ruby> array = [1, 2, 3] array.each do |element| puts element redo if element == 2 end </syntaxhighlight> このコードは、配列の要素を表示しますが、要素2を無限に表示します。 ==== イテレーションとブロック ==== Rubyのイテレーションメソッドは、繰り返し処理を行うためのメソッドで、通常はブロックを引数に取ります。ブロックは、繰り返し処理を行うためのコードブロックで、メソッドに渡されたオブジェクトの要素に対して、一つずつ実行されます。 イテレーションメソッドに渡されるブロックには、引数を指定することができます。引数は、ブロック内で処理する要素を表します。引数を指定する方法には、以下の2つがあります。 ;パイプ(| |)で囲んだ引数を指定する方法 :<syntaxhighlight lang=ruby> array = [1, 2, 3] array.each do |x| puts x end # 出力結果: 1, 2, 3 </syntaxhighlight> ;ブロック引数を指定する方法 :<syntaxhighlight lang=ruby> array = [1, 2, 3] array.each { puts _1 } # 出力結果: 1, 2, 3 </syntaxhighlight> このように、イテレーションメソッドは、ブロックを引数に取り、ブロック内で要素に対する処理を実行するため、とても柔軟性が高く、コードの再利用性を高めることができます。 {{コラム|eachメソッドを使ったハック|2= 普段あまり使うことはありませんが、配列のeachメソッドは戻値を返します。 通常は配列自身ですが、breakでループを中断すると nil を返します。 この特徴を利用すると、ZigやPythonのループと結合したelseの様に「ループを完走したときだけ実行する処理」を記述できます。 ;[https://paiza.io/projects/Je9yc_1sAi0h-jMfCSln4g?language=ruby 100以下の素数を求めるコード]:<syntaxhighlight lang=ruby highlight="3,4"> primes = [] (2..100).each do |i| primes.push(i) if primes.each do |prime| break if i % prime == 0 end end p primes </syntaxhighlight> :実行結果:<syntaxhighlight lang=text> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] </syntaxhighlight> : 素数集合(primes)から1つ素数(prime)を取出し、候補(i)をそれで割り、割切れたら break します。 : break すると each は nil を返し、素数集合への候補の追加は行われません。 }} ==== 例外処理 ==== Rubyにおける例外処理は、プログラムが想定外のエラーに遭遇した場合に、プログラムの強制終了を防ぐために使用されます。例外処理を使用すると、プログラムはエラーが発生しても継続して実行されるため、エラーに含まれる情報をログファイルに記録したり、エラーメッセージを表示したりすることができます。 以下は、Rubyで例外処理を行うための基本的な書式です。 :<syntaxhighlight lang=ruby> begin # 例外が発生する可能性のある処理 rescue [エラークラス => 変数] # エラークラスが発生した場合に実行する処理 else # 例外が発生しなかった場合に実行する処理 ensure # 必ず実行される処理 end </syntaxhighlight> 例外処理の流れは、まずbeginブロック内で例外が発生する可能性のある処理を書きます。そして、rescueブロックで発生しうる例外の種類を指定し、例外が発生した場合に行う処理を書きます。elseブロックは、例外が発生しなかった場合に実行する処理を書く部分です。ensureブロックには、必ず実行される処理を書きます。 以下は、例外処理を用いたコードの例です。 :<syntaxhighlight lang=ruby> def divide(a, b) begin result = a / b rescue ZeroDivisionError => e puts "Error: #{e.message}" result = nil else puts "Result is #{result}" ensure puts "Process finished" end return result end puts divide(10, 0) puts divide(10, 2) </syntaxhighlight> この例では、divideメソッド内で引数bが0である場合にZeroDivisionErrorが発生する可能性があるため、beginブロック内で計算を行っています。また、rescueブロックではZeroDivisionErrorを補足して、エラーメッセージを表示しています。elseブロックでは、計算結果を表示しています。ensureブロックでは、処理が必ず実行されるように設定しています。 このコードを実行すると、以下のような結果が得られます。 :<syntaxhighlight lang=text> Error: divided by 0 Process finished nil Result is 5 Process finished 5 </syntaxhighlight> ==== 修飾子 ==== Rubyでは、制御構造の修飾子版も提供されています。これは一行で短く書くことができ、可読性を向上させる場合があります。 制御構造の修飾子版には、以下のものがあります: ===== if修飾子 ===== :<syntaxhighlight lang=ruby> puts "Hello" if flag </syntaxhighlight> この場合、"Hello"はflagが真の場合にのみ出力されます。 ===== unless修飾子 ===== :<syntaxhighlight lang=ruby> puts "Hello" unless cond </syntaxhighlight> この場合、"Hello"はcondが偽の場合にのみ出力されます。 ===== while修飾子 ===== :<syntaxhighlight lang=ruby> x = 0 puts x += 1 while x < 5 </syntaxhighlight> この場合、ループが続行される条件が満たされている間、xの値がインクリメントされ、その値が出力されます。 ===== until修飾子 ===== :<syntaxhighlight lang=ruby> x = 0 puts x += 1 until x == 5 </syntaxhighlight> この場合、ループが続行される条件が満たされるまで、xの値がインクリメントされ、その値が出力されます。 ===== rescue修飾子 ===== Rubyの<code>rescue</code>修飾子は、単一行の式での例外処理を行うために使用されます。通常の<code>begin..rescue..end</code>ブロックと異なり、修飾子版はコードを短く保ち、よりコンパクトに書くことができます。 <code>rescue</code>修飾子の構文は以下の通りです: :<syntaxhighlight lang=ruby> 式1 rescue 式2 </syntaxhighlight> 式1が例外を発生させた場合、<code>rescue</code>修飾子はその例外をキャッチし、代わりに式2を評価します。 以下は<code>rescue</code>修飾子を使用した例です: :<syntaxhighlight lang=ruby> result = risky_operation() rescue default_value </syntaxhighlight> この例では、<code>risky_operation</code>というメソッドを呼び出しますが、もし例外が発生した場合には、デフォルト値を代入することでエラーハンドリングを行っています。 <code>rescue</code>修飾子は、例外が発生する可能性のある単一の式を簡潔に記述する場合に便利ですが、複雑な例外処理を行う場合や、複数の式に対する例外処理を行う場合には、通常の<code>begin..rescue..end</code>ブロックを使用する方が適しています。 これらの修飾子版は、単純な条件の場合や短いコードブロックの場合に便利です。 ただし、複雑な制御構造や複数の条件がある場合は、通常の制御構造を使用した方が可読性が高くなります。 === メソッド === Rubyのメソッドとは、ある一定の処理をまとめて名前をつけたもので、複数の場所で同じような処理を書く必要がある場合に便利です。 以下は、Rubyでメソッドを定義する方法の例です。 :<syntaxhighlight lang=ruby> def メソッド名(仮引数) 処理 end </syntaxhighlight> 上記のコードでは、<code>def</code>キーワードを使ってメソッドを定義します。メソッド名は自分で決定し、仮引数は必要に応じて任意の数を指定できます。また、<code>end</code>キーワードでメソッドの終わりを示します。 : このように、トップレベルで定義されたメソッドは、スクリプト中どこならでも呼び出すことができ、関数と呼ばれことがあります。 以下は Ruby における関数定義における引数に関する機能の例です。 :<syntaxhighlight lang=ruby> # 固定順位引数 def greet(name) puts "Hello, #{name}!" end greet("Alice") # => "Hello, Alice!" greet("Bob") # => "Hello, Bob!" # 固定順位引数のデフォルト値 def greet_with_default(name="world") puts "Hello, #{name}!" end greet_with_default # => "Hello, world!" greet_with_default("Alice") # => "Hello, Alice!" # キーワード引数 def greet_with_keyword(name:) puts "Hello, #{name}!" end greet_with_keyword(name: "Alice") # => "Hello, Alice!" greet_with_keyword(name: "Bob") # => "Hello, Bob!" # キーワード引数のデフォルト値 def greet_with_keyword_default(name: "world") puts "Hello, #{name}!" end greet_with_keyword_default # => "Hello, world!" greet_with_keyword_default(name: "Alice") # => "Hello, Alice!" # ブロック引数 def greet_with_block(name) puts "Hello, #{name}!" yield end greet_with_block("Alice") { puts "Glad to see you!" } # => "Hello, Alice!" # => "Glad to see you!" # 残余引数 def greet_with_remainder(*names) names.each { |name| puts "Hello, #{name}!" } end greet_with_remainder("Alice", "Bob", "Charlie") # => "Hello, Alice!" # => "Hello, Bob!" # => "Hello, Charlie!" </syntaxhighlight> greet 関数は固定順位引数を使用しています。greet_with_default 関数では、name のデフォルト引数が指定されています。greet_with_keyword 関数では、キーワード引数を使用しています。greet_with_keyword_default 関数では、キーワード引数のデフォルト引数が指定されています。greet_with_block 関数では、ブロック引数を使用しています。最後に、greet_with_remainder 関数は残余引数を使用しています。 これらの機能を駆使することで、より柔軟かつ読みやすいコードを作成することができます。 ==== 固定順位引数 ==== 例えば、以下のようなメソッドを定義してみましょう。 :<syntaxhighlight lang=ruby> def say_hello(name) puts "Hello, #{name}!" end </syntaxhighlight> このメソッドは、引数に渡した名前に対して「Hello, 〇〇!」というメッセージを出力します。引数の「name」には、任意の名前を指定することができます。 このメソッドを呼び出すためには、以下のように書きます。 :<syntaxhighlight lang=ruby> say_hello("John") #=> Hello, John! </syntaxhighlight> 引数に指定した名前が、「name」の部分に代入され、<code>puts</code>メソッドによってメッセージが出力されます。 ==== 固定順位引数のディフォルト値 ==== また、Rubyには引数を指定しないデフォルト値を設定する方法もあります。以下は、デフォルト値を設定したメソッドの例です。 :<syntaxhighlight lang=ruby> def say_hello(name = "World") puts "Hello, #{name}!" end </syntaxhighlight> この場合、引数を指定しなかった場合は「World」という名前が、引数を指定した場合は指定した名前が代入されます。例えば、以下のように呼び出します。 :<syntaxhighlight lang=ruby> say_hello #=> Hello, World! say_hello("Mary") #=> Hello, Mary! </syntaxhighlight> ==== キーワード引数 ==== キーワード引数では、引数名を指定することができます。これにより、引数の並び順を気にすることなく、任意の引数を指定することができます。 :<syntaxhighlight lang=ruby> def person(name:, age:) puts "名前は#{name}、年齢は#{age}才です。" end person(name: "山田太郎", age: 30) #=> 名前は山田太郎、年齢は30才です。 </syntaxhighlight> キワード引数の実引数でに順序は任意です。 ==== キーワード引数のディフォルト値 ==== キーワード引数もディフォルト値を設定することができます。引数を指定しなかった場合は、初期値が使われるようになります。 :<syntaxhighlight lang=ruby> def person(name: "名無し", age: 0) puts "名前は#{name}、年齢は#{age}才です。" end person(name: "山田太郎") #=> 名前は山田太郎、年齢は0才です。 </syntaxhighlight> ==== ブロック引数 ==== ブロック引数とは、メソッドの引数としてブロックを受け取るための仕組みです。 ブロックを受け取るメソッドの引数リストの最後に、"&ブロック名"という形式の引数を指定することで、ブロックをメソッド内で扱うことができます。 以下に例を示します。 :<syntaxhighlight lang=ruby> def my_method(&block) block.call end my_method do puts "Hello, World!" end # => "Hello, World!" </syntaxhighlight> 上記の例では、<code>my_method</code>メソッドにブロックを渡しています。<code>my_method</code>メソッド内では、ブロックを扱うための引数として<code>"&block"</code>を指定しており、ブロックを呼び出すために"block.call"を用いています。 ===== yield ===== <code>yield</code>は、メソッドに渡されたブロックを実行するためのキーワードです。<code>yield</code>を使用することで、メソッド内でブロックを実行することができます。 以下に例を示します。 :<syntaxhighlight lang=ruby> def my_method yield end my_method do puts "Hello, World!" end # => "Hello, World!" </syntaxhighlight> 上記の例では、<code>my_method</code>メソッド内で<code>yield</code>を用いてブロックを実行しています。<code>my_method</code>メソッドが呼び出されると、引数として渡されたブロックが実行されます。 ===== ブロック呼び出しへの引数 ===== ブロック引数の呼び出しや<code>yield</code>は引数を渡すこともできます。 ====== ブロック引数の呼び出しへの引数 ====== :<syntaxhighlight lang=ruby> def my_method(name, &block) block.call(name) end my_method("John") do |name| puts "Hello, #{name}!" end # => "Hello, John!" </syntaxhighlight> 上記の例では、<code>my_method</code>メソッドにブロックを渡し、ブロック引数に<code>"name"</code>を指定しています。 ブロック内で引数を使用するために、block.callで<code>"name"</code>を渡しています。 ブロック内では、引数として渡された<code>"name"</code>を使用して文字列を出力しています。 Procクラスは<code>[]</code>をオーバーロードしており。 :<syntaxhighlight lang=ruby highlight=2> def my_method(name, &block) block[name] end </syntaxhighlight> と書くことも出来ます。 ====== yield への引数 ====== :<syntaxhighlight lang=ruby> def my_method(name) yield(name) end my_method("John") do |name| puts "Hello, #{name}!" end # => "Hello, John!" </syntaxhighlight> 上記の例では、<code>my_method</code>メソッドに引数として<code>"name"</code>を渡し、<code>yield</code>に<code>"name"</code>を引数として渡しています。 ブロック内では、引数として渡された<code>"name"</code>を使用して文字列を出力しています。 ===== ブロック引数と yield どちらを使うべきか? ===== 再帰を行う場合、通常はブロック引数を使用する方が適切です。再帰的な関数では、ブロック引数を使用することで、再帰呼び出しのたびに異なるブロックを渡すことができます。これにより、再帰呼び出しのたびに異なる処理を行うことが可能になります。 例えば、再帰的なメソッドを定義する際には、ブロック引数を使用して次の再帰呼び出し時に実行される処理を指定します。 :<syntaxhighlight lang=ruby> def recursive_method(n, &block) if n > 0 # ブロックを実行 block[n] # 再帰呼び出し recursive_method(n - 1, &block) end end recursive_method(5) { |num| puts num } </syntaxhighlight> このように、ブロック引数を使うことで、再帰呼び出し時に実行される処理を柔軟に指定することができます。これにより、再帰メソッドがより汎用的で柔軟なものになります。 ===== ブロック引数の有無 ===== Rubyでは、メソッド内でブロックが渡されたかどうかを判定する方法があります。これを行うには、<code>block_given?</code>メソッドを使用します。このメソッドは、メソッド内でブロックが渡された場合に<code>true</code>を返し、それ以外の場合に<code>false</code>を返します。 以下は、<code>block_given?</code>メソッドを使用してブロックが渡されたかどうかを判定する例です。 :<syntaxhighlight lang=ruby> def method_with_block if block_given? puts "ブロックが渡されました" # yield が使えます else puts "ブロックが渡されていません" # yield は使えません end end method_with_block { puts "Hello, block!" } # => ブロックが渡されました method_with_block # => ブロックが渡されていません </syntaxhighlight> このように、<code>block_given?</code>メソッドを使うことで、メソッド内でブロックが渡されたかどうかを簡単に判定することができます。 ===== ブロック引数を省略した時の戻り値 ===== ブロック引数を受け取るメソッドの呼び出しで、ブロック引数を省略した場合の戻り値は、<code>Enumerator</code>オブジェクトとする慣習があります。 例えば、配列を<code>each</code>メソッドで呼び出した場合、ブロックが省略されると<code>Enumerator</code>オブジェクトが返ります。 :<syntaxhighlight lang=ruby> array = [2, 3, 5, 7] enum = array.each puts enum.class # => Enumerator begin puts enum.next while true rescue StopIteration => e puts e.inspect end # => 2 # 3 # 5 # 7 # #<StopIteration: iteration reached an end> enum2 = 10.upto(15) loop do puts enum2.next end # => 10 # 11 # 12 # 13 # 14 # 15 # 一見無限ループになりそうですが # loop は StopIteration をキャッチすると静かに繰り返しを終了します。 </syntaxhighlight> このように、<code>each</code>メソッドがブロック引数を省略された場合、戻り値はイテレータとして機能する<code>Enumerator</code>オブジェクトとなります。このオブジェクトは、コレクションの各要素を順番に処理するために使用されます。 ; 典型的なブロック引数処理 :<syntaxhighlight lang=ruby highlight=2> def inorder_traversal(node = @root, &block) return to_enum(__method__, node) unless block def core(node, &block) return if node.nil? core(node.left, &block) yield node.value core(node.right, &block) end core(node, &block) self end </syntaxhighlight> ==== 残余引数 ==== Rubyにおける「残余引数(rest argument)」とは、メソッド定義の中で最後の引数として指定され、そのメソッドに渡された全ての追加の引数を1つの配列として受け取る機能です。残余引数は、メソッドが可変長の引数を受け取ることを可能にします。 残余引数は、メソッド定義の引数の前にアスタリスク * を付けて指定されます。これにより、メソッドが受け取る引数の数を動的に決定することができます。 以下は、残余引数を使用する例です。 ;[https://paiza.io/projects/ieLAdVArMpdUwbnQ5z_oKQ?language=ruby rest-args.rb:]<syntaxhighlight lang=ruby> def greet(greeting, *names) names.each { |name| puts "#{greeting}, #{name}!" } end greet("Hello", "Alice", "Bob", "Charlie") # 出力: # Hello, Alice! # Hello, Bob! # Hello, Charlie! </syntaxhighlight> この例では、greet メソッドは greeting という通常の引数と、*names という残余引数を持っています。greet メソッドは最初の引数を挨拶の文字列として受け取り、残りの引数を配列 names として受け取ります。その後、names 配列内の各要素に対して、挨拶と名前を組み合わせたメッセージを出力します。 残余引数を使用することで、メソッドが任意の数の引数を受け取る柔軟性が向上し、可読性の高いコードを記述することができます。 ==== 戻り値 ==== メソッド内で最後に評価される値が、そのメソッドの戻り値になります。例えば、次のようなメソッドを考えてみましょう。 :<syntaxhighlight lang=ruby> def add(a, b) return a + b end </syntaxhighlight> このメソッドは2つの引数を受け取り、それらの和を返します。<code>return</code> キーワードを使用して、明示的に戻り値を指定しています。このように <code>return</code> を使わずに値を返すと、メソッドの最後に評価された値が自動的に戻り値として返されます。 :<syntaxhighlight lang=ruby> def add(a, b) a + b end </syntaxhighlight> このように、明示的に <code>return</code> を書かなくても、メソッド内で最後に評価された値が自動的に戻り値となります。 さらに、1つの式からなる関数は <code>=</code> を使い <code>end</code> を伴わない構文で定義できます。 :<syntaxhighlight lang=ruby> def add(a, b) = a + b </syntaxhighlight> メソッドを呼び出す際には、その戻り値を変数に代入したり、別のメソッドの引数として渡したりすることができます。 戻り値が必要な場合や、逆に必要ではない場合など、メソッドの設計時にはしっかりと考慮して実装する必要があります。 ==== スコープ ==== Rubyには4つのスコープがあります。以下にそれぞれのスコープとコード例を示します。 ; ローカルスコープ : 変数が定義されたブロック内でしか使用できません。 :<syntaxhighlight lang=ruby> def local_scope x = 10 puts x # output: 10 end puts x # undefined local variable or method `x' for main:Object (NameError) </syntaxhighlight> ; インスタンススコープ : インスタンス変数は同じインスタンスの中であればどこでも使用できます。 :<syntaxhighlight lang=ruby> class Person def initialize(name) @name = name end def greet puts "Hello, #{@name}!" end end person = Person.new("Alice") person.greet # Hello, Alice! puts @name # undefined method `name' for main:Object (NameError) </syntaxhighlight> ; クラススコープ : クラス変数はそのクラス及びサブクラスのどこからでも使用できます。 :<syntaxhighlight lang=ruby> class Counter @@count = 0 def initialize @@count += 1 end def self.count @@count end end counter1 = Counter.new counter2 = Counter.new puts Counter.count # 2 </syntaxhighlight> ; グローバルスコープ : グローバル変数はどこからでも使用できます。ただし、他のスコープで同じ名前の変数が定義されている場合はその変数が使用されます。 :<syntaxhighlight lang=ruby> $global_var = "I'm global" def check_global_var puts $global_var end check_global_var # I'm global def set_global_var $global_var = "I'm changed globally" end set_global_var check_global_var # I'm changed globally </syntaxhighlight> 以上がRubyの4つのスコープです。 {{コラム|メソッドの引数リストを囲む括弧の省略|2= メソッドの引数リストを囲む括弧 <code>p(</code> と <code>)</code> は、曖昧さのない場合は省略可能です。 上の例は、<code>puts(s)</code>と書く代わりに、<code>put s</code> と書く事ができます。 ;コード:<syntaxhighlight lang=ruby> s = 'Hello World!' puts s </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello World! </syntaxhighlight> }} ==== 再帰的呼び出し ==== Rubyでは、メソッド内で再帰を行うことができます。以下は、再帰を行うシンプルな例です。 :<syntaxhighlight lang=ruby> def countdown(num) if num > 0 puts num countdown(num - 1) else puts "Blast off!" end end countdown(5) </syntaxhighlight> このコードでは、<code>countdown</code>メソッドが自分自身を呼び出して、カウントダウンを実行しています。呼び出し結果は以下の通りです。 :<syntaxhighlight lang=text> 5 4 3 2 1 Blast off! </syntaxhighlight> このように、再帰を使うと、同じ処理を繰り返し実行することができます。 ==== クロージャー ==== Rubyにはクロージャーという概念があります。クロージャーとは、変数とブロックを組み合わせたもので、後からブロック内で変数が参照された場合でも、当時の変数の値を保持している特殊なオブジェクトです。 以下は、クロージャーを使った例です。 :<syntaxhighlight lang=ruby> def greeting_proc(name) Proc.new { puts "Hello, #{name}!" } end hello = greeting_proc("Alice") hello.call # => "Hello, Alice!" changing_name = "Bob" hello.call # => "Hello, Alice!" (value of name is retained) </syntaxhighlight> 上記の例では、<code>greeting_proc</code>メソッドがブロックを返し、そのブロックが<code>hello</code>変数に代入されます。このブロック内で参照される変数<code>name</code>の値が保持され、<code>hello.call</code>を複数回実行しても、最初に指定した名前が表示されます。 また、<code>changing_name</code>という変数を新しく定義しても、クロージャー内で参照される<code>name</code>の値には影響がなく、<code>hello.call</code>を実行すると、<code>"Hello, Alice!"</code>が表示されます。 === クラス === Rubyにおけるクラスは、オブジェクト指向プログラミングにおいて重要な役割を持ちます。クラスは、同じ構造や属性を持つオブジェクトの集合を定義するもので、それぞれのオブジェクトはクラスのインスタンスであると考えることができます。 ==== クラス定義とインスタンスの生成とメソッドの呼び出し ==== :<syntaxhighlight lang=ruby> # クラス定義 class MyClass # クラス変数 @@class_variable = "Class Variable" # インスタンス変数 attr_accessor :instance_variable # コンストラクター def initialize(arg) @instance_variable = arg end # クラスメソッド def self.class_method puts @@class_variable end # インスタンスメソッド def instance_method puts @instance_variable end end # クラスの利用 my_object = MyClass.new("Instance Variable") MyClass.class_method #=> "Class Variable" my_object.instance_method #=> "Instance Variable" my_object.instance_variable = "New Instance Variable" my_object.instance_method #=> "New Instance Variable" </syntaxhighlight> クラス定義は<code>class</code>キーワードを使い、インスタンス変数を作成するために<code>attr_accessor</code>を使っています。コンストラクターは<code>initialize</code>メソッドを使い、引数を受け取ってインスタンス変数を初期化します。 クラスメソッド、インスタンスメソッドはそれぞれ<code>def self.method_name</code>、<code>def method_name</code>の形式で定義されます。また、クラス変数は<code>@@</code>で始められ、インスタンス変数は<code>@</code>で始められます。 このように、Rubyのクラスを使用することで、簡単にオブジェクト指向プログラミングを実現することができます。 ==== アクセス修飾子 ==== Rubyには3種類のアクセス修飾子があります。 ;public :どこからでもアクセス可能なメソッドや変数を定義するときに使用します。 :クラスの外部からもアクセス可能です。 ;protected :自クラスまたはそのサブクラスであればアクセス可能なメソッドや変数を定義するときに使用します。 :クラスの外部からはアクセスできません。 ;private :同じオブジェクト内でしかアクセスできないメソッドや変数を定義するときに使用します。 :クラスの外部からはアクセスできません。 以下は、それぞれのアクセス修飾子を使用した例です。 :<syntaxhighlight lang=ruby> class Animal def swim # public puts "I can swim!" end protected def run # protected puts "I can run!" end private def fly # private puts "I can fly!" end end class Cat < Animal def can_run run # protectedなのでAnimalクラスのサブクラス内から呼び出し可能 end def can_fly fly # privateなので呼び出し不可能 end end cat = Cat.new cat.swim # publicなので呼び出し可能 cat.can_run # protectedなので呼び出し可能 cat.can_fly # privateなので呼び出し不可能 </syntaxhighlight> 上記の例では、<code>Animal</code>クラスに <code>swim</code>、<code>run</code>、<code>fly</code> メソッドを定義しています。 <code>swim</code>メソッドは <code>public</code>、<code>run</code> メソッドは <code>protected</code>、<code>fly</code> メソッドは <code>private</code> となっています。 また、<code>Cat</code> クラスを <code>Animal</code> クラスのサブクラスとして定義し、<code>can_run</code>メソッドで、<code>Animal</code>クラスで <code>protected</code> として定義した <code>run</code> メソッドを呼び出しています。一方で、<code>can_fly</code> メソッドで <code>private</code> として定義した <code>fly</code> メソッドを呼び出しているため、エラーが発生しています。 ==== クラスの継承 ==== :<syntaxhighlight lang=ruby> # 親クラス class Animal def speak puts "動物が鳴いています" end end # 子クラス class Dog < Animal def speak puts "わんわん" end end # 子クラス class Cat < Animal def speak puts "にゃーにゃー" end end # 子クラスのインスタンス化 dog = Dog.new cat = Cat.new # 子クラスのメソッドを呼び出し dog.speak #=> わんわん cat.speak #=> にゃーにゃー # 親クラスのメソッドも呼び出し可能 dog.superclass #=> Animal dog.superclass.superclass #=> Object(親クラスの親クラス) </syntaxhighlight> この例では、<code>Animal</code> という親クラスを作成し、 <code>Dog</code> と <code>Cat</code> という子クラスを作成しています。 <code>Dog</code> と <code>Cat</code> はそれぞれ <code>speak</code> メソッドを持っており、それぞれ異なる出力をします。 <code>Dog</code> と <code>Cat</code> は <code>Animal</code> クラスを継承しています。このため、 <code>Dog</code> と <code>Cat</code> も <code>Animal</code> クラスの <code>speak</code> メソッドを呼び出すことができます。 ==== 演算子オーバーロード ==== 以下はRubyにおける演算子オーバーロードの例です。 :<syntaxhighlight lang=ruby> class Person attr_accessor :name, :age def initialize(name, age) @name = name @age = age end def +(other) Person.new("#{self.name} #{other.name}", self.age + other.age) end def ==(other) self.name == other.name && self.age == other.age end end person1 = Person.new("John", 30) person2 = Person.new("Doe", 40) # カスタム演算子 '+' の利用 person3 = person1 + person2 puts person3.name #=> John Doe puts person3.age #=> 70 # カスタム演算子 '==' の利用 puts person1 == person3 #=> false person4 = Person.new("John Doe", 70) puts person3 == person4 #=> true </syntaxhighlight> *この例では、Personクラスで+演算子と==演算子をオーバーロードしています。 *+演算子は2つのPersonオブジェクトを受け取り、新しいPersonオブジェクトを返します。 *==演算子は2つのPersonオブジェクトを比較し、nameプロパティとageプロパティが両方とも同じ場合にtrueを返します。 ==== クラスへの動的なメソッドの追加 ==== :<syntaxhighlight lang=ruby> class MyClass def initialize(name) @name = name end end my_object = MyClass.new("Bob") class MyClass def greet() puts "Hello, #{@name}!" end end my_object.greet #=> "Hello, Bob!" </syntaxhighlight> *最初に、「MyClass」というクラスを定義します。 *次に、MyClassのインスタンスを生成し変数my_objectに代入しています。 *その後、件のMyClassに新しいメソッドgreet()を定義しています。 * 最後の行で、「my_object.greet」というコードが実行され、オブジェクトの「greet」メソッドが呼び出されます。これにより、「Hello, Bob!」という文字列が出力されます。 注目すべきは: * クラス定義の後でもメソッドの追加はできる * インスタンス化とメソッドの追加定義が前後しても、メソッド呼び出しは可能である の2点です。 ==== 特異メソッド ==== Rubyでは、オブジェクトに固有のメソッドを定義することができます。これを特異メソッドと呼びます。通常、メソッドはクラス定義内で定義されますが、特異メソッドは特定のオブジェクトに対して定義されます。 ===== 特異メソッドの定義 ===== 特異メソッドを定義するには、以下のように書きます。 :<syntaxhighlight lang=ruby> オブジェクト名.define_singleton_method(シンボル) do |引数| # メソッドの中身 end </syntaxhighlight> 例えば、以下のように書くことで、特定のオブジェクトにhelloメソッドを定義することができます。 :<syntaxhighlight lang=ruby> str = "Hello, world!" str.define_singleton_method(:hello) do puts "Hello!" end </syntaxhighlight> これで、strオブジェクトにhelloメソッドが定義されました。呼び出すには以下のようにします。 :<syntaxhighlight lang=ruby> str.hello #=> "Hello!" </syntaxhighlight> ===== 特異クラスと特異メソッド ===== Rubyでは、オブジェクトに対して特異クラスというものが存在します。これは、そのオブジェクトだけが持つクラスのことです。この特異クラスに対して特異メソッドを定義することで、そのオブジェクトだけにメソッドを追加できます。 特異クラスは、以下のように記述します。 :<syntaxhighlight lang=ruby> class << オブジェクト名 # メソッドの定義 end </syntaxhighlight> 例えば、以下のように記述することで、上記のstrオブジェクトに対してメソッドを定義することができます。 :<syntaxhighlight lang=ruby> class << str def goodbye puts "Goodbye!" end end </syntaxhighlight> これで、strオブジェクトにgoodbyeメソッドが定義されました。呼び出すには以下のようにします。 :<syntaxhighlight lang=ruby> str.goodbye #=> "Goodbye!" </syntaxhighlight> ===== まとめ ===== 以上が、Rubyの特異メソッドについてのチュートリアルです。オブジェクトに対して固有のメソッドを定義することで、便利なプログラミングをすることができます。 ==== クラス定義の例 ==== ===== 都市間の大圏距離 ===== [[Go/メソッドとインターフェース]]の都市間の大圏距離を求めるメソッドを追加した例を、Rubyに移植しました。 ;[https://paiza.io/projects/Pr8BO96TMXQCuTybsTm3mg?language=ruby 都市間の大圏距離]:<syntaxhighlight lang=ruby line> class GeoCoord attr_accessor :longitude, :latitude def initialize(longitude, latitude) @longitude, @latitude = longitude, latitude end def to_s() ew, ns = "東経", "北緯" long, lat = @longitude, @latitude ew, long = "西経", -long if long < 0.0 ns, lat = "南緯", -lat if lat < 0.0 "(#{ew}: #{long}, #{ns}: #{lat})" end def distance(other) i, r = Math::PI / 180, 6371.008 Math.acos(Math.sin(@latitude * i) * Math.sin(other.latitude * i) + Math.cos(@latitude * i) * Math.cos(other.latitude * i) * Math.cos(@longitude * i - other.longitude * i)) * r end end def GeoCoord(longitude, latitude) GeoCoord.new(longitude, latitude) end Sites = { "東京駅": GeoCoord(139.7673068, 35.6809591), "シドニー・オペラハウス": GeoCoord(151.215278, -33.856778), "グリニッジ天文台": GeoCoord(-0.0014, 51.4778), } Sites.each{|name, gc| puts "#{name}: #{gc}" } keys, len = Sites.keys, Sites.size keys.each_with_index{|x, i| y = keys[(i + 1) % len] puts "#{x} - #{y}: #{Sites[x].distance(Sites[y])} [km]" } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 東京駅: (東経: 139.7673068, 北緯: 35.6809591) シドニー・オペラハウス: (東経: 151.215278, 南緯: 33.856778) グリニッジ天文台: (西経: 0.0014, 北緯: 51.4778) 東京駅 - シドニー・オペラハウス: 7823.269299386704 [km] シドニー・オペラハウス - グリニッジ天文台: 16987.2708377249 [km] グリニッジ天文台 - 東京駅: 9560.546566490015 [km] </syntaxhighlight> このコードは、<code>GeoCoord</code>というクラスを定義し、そこに緯度と経度を持つ「地球上の位置」を表現しています。それを利用して、<code>Sites</code>というディクショナリに都市名と位置を紐付けています。 このコードのメインの処理は、各都市に対して、その距離を計算して出力しています。すなわち、都市の位置情報から、地球上での距離を求めることができます。 この「地球上の距離を求める」処理は、<code>distance</code>メソッドで定義されており、球面三角法を使って計算されています。具体的には、2点の緯度経度から、その2点間の地表面上の距離を求める数式を用いています。 また、都市名と位置情報を紐付けた<code>Sites</code>に対しては、各都市の位置を出力しています。それぞれの都市の位置は、東経か西経か、北緯か南緯かで表され、丸括弧でくくられ、「東京駅」の場合は <code>(東経: 139.7673068, 北緯: 35.6809591)</code>という文字列が出力されます。 ===== 包含と継承 ===== [[JavaScript/クラス#包含と継承]]を、Rubyに移植しました。 ;[https://paiza.io/projects/Zv6cp4tlI3JoV36uEQFetQ?language=ruby 包含と継承]:<syntaxhighlight lang=ruby line> class Point def initialize(x = 0, y = 0) @x, @y = x, y end def inspect() = "x:#{@x}, y:#{@y}" def move(dx = 0, dy = 0) @x, @y = @x + dx, @y + dy self end end class Shape def initialize(x = 0, y = 0) @location = Point.new(x, y) end def inspect() = @location.inspect() def move(x, y) @location.move(x, y) self end end class Rectangle < Shape def initialize(x = 0, y = 0, width = 0, height = 0) super(x, y) @width, @height = width, height end def inspect() = "#{super()}, width:#{@width}, height:#{@height}" end rct = Rectangle.new(12, 32, 100, 50) p ["rct=", rct] p ['rct.instance_of?( Rectangle ) => ', rct.instance_of?(Rectangle)] p ['rct.instance_of?( Shape ) => ', rct.instance_of?(Shape)] p ['rct.instance_of?( Point ) => ', rct.instance_of?(Point)] rct.move(11, 21) p ["rct=", rct] </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ["rct=", x:12, y:32, width:100, height:50] ["rct.instance_of?( Rectangle ) => ", true] ["rct.instance_of?( Shape ) => ", false] ["rct.instance_of?( Point ) => ", false] ["rct=", x:23, y:53, width:100, height:50] </syntaxhighlight> このコードは、Rubyでオブジェクト指向プログラミングを用いた簡単な図形クラスの例です。 <code>Point</code>クラスは、座標を表現するためのクラスであり、<code>x</code>と<code>y</code>の2つのインスタンス変数を持っています。 コンストラクタで、<code>x</code>と<code>y</code>の初期値が設定できます。<code>inspect</code>メソッドは、オブジェクトを文字列に変換するために使用されます。<code>move</code>メソッドにより、(dx, dy)だけ点を移動することができます。 <code>Shape</code>クラスは、点の座標を持つ図形を表すためのクラスであり、<code>initialize</code>メソッド内で、<code>Point</code>クラスのオブジェクトを作成して、点の座標を設定します。<code>inspect</code>メソッドは、点の座標を返します。 <code>move</code>メソッドによって、図形を(dx, dy)だけ移動することができます。 <code>Rectangle</code>クラスは、<code>Shape</code>クラスを継承しています。コンストラクタで、左上の点の座標と幅と高さを設定できます。<code>inspect</code>メソッドは、左上の点の座標と、幅と高さを表現する文字列を返します。 最後の行では、<code>Rectangle</code>クラスのインスタンス<code>rct</code>を作成し、その後、<code>rct</code>が<code>Rectangle</code>クラス、<code>Shape</code>クラス、<code>Point</code>クラスのどれに対してインスタンスかを調べるようにしています。また、<code>rct</code>の位置を(11, 21)だけ移動させます。 === 高階関数 === Rubyの高階関数とは、関数を引数や戻り値として扱うことができる関数のことを指します。これにより、コードの再利用性が向上し、より柔軟なプログラミングが可能になります。 例えば、以下のような高階関数があります。 :<syntaxhighlight lang=ruby> def manipulate_array(arr, func) arr.map(&func) end </syntaxhighlight> この関数は、配列と関数を受け取り、配列の各要素に対してその関数を適用した新しい配列を返します。このように、関数自体を引数として渡せることで、どのような処理でも適用することができます。 また、RubyのProcオブジェクトを使うことで、無名関数を定義して高階関数に渡すこともできます。例えば、以下のようなコードです。 :<syntaxhighlight lang=ruby> add_num = Proc.new {|x| x + 1 } puts manipulate_array([1, 2, 3], add_num) # => [2, 3, 4] </syntaxhighlight> このように、Procオブジェクトを定義して関数に渡すことで、より柔軟なプログラミングが可能になります。 ==== lambda ==== Rubyのlambdaとは、無名関数(関数を名前を付けずに定義すること)の一種であり、関数をオブジェクトとして扱うことができます。 以下は、lambda式の基本構文です。 :<syntaxhighlight lang=ruby> lambda { |引数| 処理 } </syntaxhighlight> <code>lambda</code>には引数を渡すことができ、渡された引数を処理に渡すことができます。また、処理の中で <code>return</code> を使うことができ、<code>lambda</code>の戻り値として処理結果を返すことができます。以下が、<code>lambda</code>を利用した簡単な例です。 :<syntaxhighlight lang=ruby> # lambda式を変数に代入する add = lambda { |x, y| x + y } # lambda式の引数の数 puts add.arity #=> 2 # lambda式を直接呼び出す puts lambda { |x, y| x + y }.call(2, 3) #=> 5 # lambda式を変数に代入したものを呼び出す puts add.call(2, 3) #=> 5 # ブラケット記法による呼び出し puts add[2, 3] #=> 5 </syntaxhighlight> Ruby 1.9 からは :<syntaxhighlight lang=ruby> -> (引数) { 処理 } </syntaxhighlight> のような構文が追加され :<syntaxhighlight lang=ruby> # lambda式を変数に代入する add = -> (x, y) { x + y } # lambda式の引数の数 puts add.arity #=> 2 # lambda式を直接呼び出す puts -> (x, y) { x + y }[2, 3] #=> 5 </syntaxhighlight> とも書けるようになりました。 以上が、Rubyの<code>lambda</code>の基本的な使い方です。 ==== Procとlambdaの違い ==== RubyのProcとlambdaは、両方とも無名関数を定義するための方法ですが、いくつかの違いがあります。 引数の扱い方 Procの場合、渡された引数の数が関係なく、無視されます。一方、lambdaの場合は、正確な数の引数が期待されます。引数が足りない場合はエラーが発生します。 return文の扱い方 Procの場合、return文は元の呼び出し元に戻りますが、そのブロック内の後続のコードも実行されます。lambdaの場合、return文はただちにブロックから返され、コードの後続部分は実行されません。 以下は、Procとlambdaの振る舞いの違いを示す例です。 :<syntaxhighlight lang=ruby> def proc_test p = Proc.new { return "Proc" } p.call return "proc_test method" end def lambda_test l = lambda { return "Lambda" } l.call return "lambda_test method" end puts proc_test # 出力結果: Proc puts lambda_test # 出力結果: lambda_test method </syntaxhighlight> この例では、Procはブロック内でreturn文を呼び出していますが、lambdaは呼び出していません。そのため、Procはreturn文で元の呼び出し元に戻って、その後のコードも実行されなくなっています。一方、lambdaはreturn文を呼び出すことがないので、lambda_testメソッドが正常に終了します。 === 並行処理 === Rubyには以下のような並行処理の仕組みが提供されています。 ;Threadクラス:Threadクラスを使用することで、Rubyでのマルチスレッドプログラミングが可能になります。Thread.newメソッドを呼び出すことで新しいスレッドを作成し、その中で並列に実行したい処理をブロックとして渡します。スレッド間でのデータ共有については、QueueやMutexといった同期プリミティブを使用することができます。 ;Fiberクラス:Fiberクラスを使用することで、Rubyでのコルーチンを実現できます。コルーチンは一般的なスレッドとは異なり、スケジューラを持っておらず、明示的に切り替える必要があります。Fiber.yieldメソッドを呼び出すことで一旦コルーチンの実行を中断し、Fiber.resumeメソッドを呼び出すことで再開します。 ;Processクラス:Processクラスを使用することで、Rubyでのプロセス間通信が可能になります。プロセス同士はメモリを共有せず、別々のプロセスとして実行されます。プロセス間で通信を行うには、パイプや共有メモリなどの仕組みを使用する必要があります。 なお、Rubyには以上の他にも、ThreadクラスやFiberクラスと同様に、GVL(Global VM Lock)によってスレッドセーフに実行されるイベントマシンであるEventMachineや、並行処理のためのツールキットであるCelluloidなどが存在します。 ==== スレッド(Thread) ==== Rubyにおけるスレッドは、軽量な並列処理を実現するための機能であり、プログラム内で独立して動作する変数やメソッドの集合を表します。スレッドは、複数のタスクを同時に処理することで、CPUを最大限活用することができます。 スレッドは、Threadクラスを使用して作成することができます。Thread.newメソッドを使用して、新しいスレッドを作成した後、startメソッドを呼び出すことでスレッドを開始します。また、Thread.currentメソッドを使用することで、現在のスレッドを取得することができます。 以下は、スレッドを使用した簡単な例です。 :<syntaxhighlight lang=ruby> t1 = Thread.new { # スレッド1の処理 puts "Thread 1 started" sleep(2) puts "Thread 1 ended" } t2 = Thread.new { # スレッド2の処理 puts "Thread 2 started" sleep(1) puts "Thread 2 ended" } t1.join t2.join </syntaxhighlight> この例では、スレッド1とスレッド2が開始されます。それぞれのスレッドは、sleepメソッドを使用して一定時間待機した後、メッセージを出力します。joinメソッドを呼び出すことで、スレッドが完了するまでプログラムの実行をブロックします。 Rubyにおけるスレッドには、マルチスレッドに関する問題がいくつか存在します。例えば、同一のリソースにアクセスする複数のスレッドによる競合状態や、デッドロックに陥ってしまう可能性があります。これらの問題を回避するため、適切なロック処理や排他制御が必要な場合があります。 ==== ファイバー(Fiber) ==== Rubyのファイバー(Fiber)は、擬似並行処理を実現するための仕組みです。標準的なスレッドと異なり、Rubyのファイバーはコルーチン的な動作をし、明示的に制御を渡す必要があります。 ファイバーは、Ruby 1.9以降から標準機能として組み込まれています。ファイバーを利用することで、特定の処理を中断したあと再開したり、独自のスケジューリングに基づいた処理を実現したりすることができます。 ファイバーは以下のように作成できます。 :<syntaxhighlight lang=ruby> fiber = Fiber.new do puts "start" Fiber.yield puts "end" end </syntaxhighlight> このコードでは、Fiber.newメソッドにブロックを渡してファイバーを作成します。puts "start"を実行した後、Fiber.yieldで処理を中断しています。この時点でプログラムは停止しており、puts "end"はまだ実行されていません。 ファイバーを再開するには、Fiber#resumeメソッドを呼び出します。 :<syntaxhighlight lang=ruby> fiber.resume </syntaxhighlight> このコードを実行すると、puts "start"が表示された後にプログラムが停止します。その後、再びfiber.resumeを実行すると、puts "end"が表示されます。 このように、ファイバーを利用することで、特定の処理を中断してから再開することができます。また、ファイバーを複数作成し、独自のスケジューリングに基づいた処理を行うことができます。 以下は、複数のファイバーを作成し、それぞれの処理を交互に実行する例です。 :<syntaxhighlight lang=ruby> f1 = Fiber.new do loop do puts "1" Fiber.yield end end f2 = Fiber.new do loop do puts "2" Fiber.yield end end f1.resume f2.resume f1.resume f2.resume # ... </syntaxhighlight> このように、ファイバーを利用することで、擬似的な並行処理を実現することができます。しかし、ファイバーはスレッドと異なり、OSレベルでのスケジューリングを行わないため、適切な制御を行わないとデッドロックや競合状態などの問題が生じることがあります。注意して使用する必要があります。 ==== プロセス(Process) ==== Rubyには、プロセスを管理するための Process モジュールが用意されています。このモジュールを使用することで、現在のプロセスや子プロセスを管理することができます。以下に、Processモジュールの主な機能をコードを交えて解説します。 ===== 現在のプロセス情報の取得 ===== Process モジュールに用意されている、 Process.pid メソッドを使用することで、現在のプロセスのIDを取得することができます。以下は、 Process.pid を使用して現在のプロセスIDを取得し、表示する例です。 :<syntaxhighlight lang=ruby> puts "現在のプロセスID: #{Process.pid}" </syntaxhighlight> ===== プロセスの生成 ===== Process モジュールには、新しいプロセスを生成するためのメソッドが複数用意されています。ここでは、代表的な2つのメソッドを紹介します。 ====== Process.spawn メソッド ====== Process.spawn メソッドを使用することで、外部プログラムを実行する新しいプロセスを生成することができます。以下は、 ls コマンドを実行する新しいプロセスを生成する例です。 :<syntaxhighlight lang=ruby> pid = Process.spawn("ls") </syntaxhighlight> ====== fork メソッド ====== fork メソッドを使用することで、現在のプロセスの子プロセスを生成することができます。 fork メソッドは、呼び出し元のプロセスからコピーされた新しいプロセスを生成します。以下は、 fork メソッドを使用して子プロセスを生成し、子プロセス内で puts メソッドを呼び出す例です。 :<syntaxhighlight lang=ruby> pid = fork if pid.nil? puts "子プロセスのID: #{Process.pid}" else puts "親プロセスのID: #{Process.pid}, 子プロセスのID: #{pid}" end </syntaxhighlight> ===== プロセスの終了 ===== 生成したプロセスを適切に終了することも重要です。以下は、プロセスを終了するためのメソッドを紹介します。 ====== Process.kill メソッド ====== Process.kill メソッドを使用することで、指定したシグナルを送信してプロセスを終了することができます。以下は、 kill メソッドを使用して、先程生成した ls コマンドを実行しているプロセスを終了する例です。 :<syntaxhighlight lang=ruby> pid = Process.spawn("ls") puts "新しいプロセスのID: #{pid}" sleep 1 Process.kill("TERM", pid) puts "プロセスを終了しました" </syntaxhighlight> ===== まとめ ===== このように、Rubyの Process モジュールを使用することで、プロセスの生成や管理を容易に行うことができます。プロセスを扱う場合は、適切な終了処理も行うようにしましょう。 ==ライブラリ編== プログラミング言語Rubyの大きな魅力の1つは、豊富なライブラリが用意されていることです。Rubyには標準添付ライブラリとgemと呼ばれるパッケージ管理システムを通じて配布されるライブラリがあり、開発者はこれらのライブラリを活用することで、効率的で堅牢なプログラミングが可能になります。 ライブラリ編では、Rubyにおけるライブラリの概念と、主要なライブラリの機能およびユースケースを解説します。ライブラリのインストール方法から、具体的なコード例に至るまでカバーし、Rubyでのライブラリ活用の第一歩を支援します。 === リテラル表記 === Rubyでは、数値、文字列、正規表現、シンボル、配列、ハッシュ、範囲などのオブジェクトを直接記述する方法としてリテラル表記が用意されています。 # '''[[#数値(Numeric)|数値(Numeric)]]''' #:整数と浮動小数点数のリテラルは通常の数値表記で記述します。有理数は接尾辞<code>r</code>を補い、複素数は虚数単位<code>i</code>を伴い表記します。 #:<syntaxhighlight lang=ruby> 42 0o177 0xbad 3.14 123e45 55/7r 3+4i </syntaxhighlight> # '''[[#文字列(String)|文字列(String)]]''' #: 文字列リテラルは<code>"</code>や<code>'</code>で囲んで記述します。 #:<syntaxhighlight lang=ruby> "Hello, World!" 'Ruby is fun' </syntaxhighlight> # '''[[#正規表現(Regexp)|正規表現(Regexp)]]''' #:正規表現リテラルは<code>/</code>で開始し<code>/</code>で終了する形式で記述します。 #:<syntaxhighlight lang=ruby> /ruby/ /^start/ </syntaxhighlight> # '''[[#シンボル(Symbol)|シンボル(Symbol)]]''' #:シンボルリテラルはコロン<code>:</code>から始まる名前で表します。 #:<syntaxhighlight lang=ruby> :symbol :name </syntaxhighlight> # '''[[#配列(Array)|配列(Array)]]''' #: 配列リテラルは<code>[]</code>の中に要素をカンマ区切りで記述します。 #:<syntaxhighlight lang=ruby> [1, 2, 3, 4, 5] ["apple", "banana", "orange"] </syntaxhighlight> # '''[[#ハッシュ(Hash)|ハッシュ(Hash)]]''' #:ハッシュリテラルは<code>{}</code>の中にキーと値をハッシュロケット<code>=></code>で対応付けて記述します。 #:<syntaxhighlight lang=ruby> {"name" => "Jane", "age" => 25} {:name => "John", :age => 30} </syntaxhighlight> #:キーがシンボルの場合は、短縮表記があります。 #:<syntaxhighlight lang=ruby> {name: "John", age: 30} </syntaxhighlight> # '''[[#範囲(Range)|範囲(Range)]]''' #:範囲リテラルは開始値と終了値を<code>..</code>または<code>...</code>で囲んで記述します。 #:<syntaxhighlight lang=ruby> (1..5) # 1から5まで ("a"..."d") # "a"から"c"まで </syntaxhighlight> これらのリテラル表記は、対応するクラスのオブジェクトを直接生成するための簡潔な記法となっています。また、配列やハッシュの中でもリテラルを入れ子にすることができます。オブジェクトの初期化を手軽に記述できるため、Rubyのコードの可読性が高まります。 === 数値(Numeric) === RubyのNumericは、数値を表す抽象クラスです。具体的な数値の型、例えば整数(Integer)や浮動小数点数(Float)などは、このNumericクラスのサブクラスとして実装されています。 Numericクラスは、数値演算や比較などの基本的な操作を提供します。例えば、加算、減算、乗算、除算、比較演算子(<、<=、==、>、>=)などがこのクラスで定義されています(ただし複素数に大小関係は定義できないので大小比較演算子も定義されません)。 また、単項の加算と減算を表す+@や-@といったメソッドも定義されています。 このクラスは、Rubyの数値型の共通の振る舞いを定義するための基盤となっています。そのため、IntegerやFloatなどの具体的な数値型が共通のメソッドや振る舞いを持てるように、Numericクラスでこれらのメソッドが定義されています。 数値演算や比較などの一般的な操作に加えて、Numericクラスは他の数値型間での演算を可能にするためのメソッドも提供しています。例えば、coerceメソッドを使うことで、異なる数値型同士での演算が可能になります。 {{Main|[https://ruby-doc.com/3.3.0/Numeric.html class Numeric - RDoc Documentation]}} ==== 整数(Integer) ==== Rubyには整数を扱うためのIntegerクラスがあります。 {{Main|[https://ruby-doc.com/3.3.0/Integer.html class Integer - RDoc Documentation]}} Integerクラスは、以下のような数値リテラルで整数値を表現することができます。 :<syntaxhighlight lang=ruby> 123 #=> 123 0b1111 #=> 15 0o777 #=> 511 0xFF #=> 255 </syntaxhighlight> また、整数の四則演算や比較演算子なども、Integerクラスで定義されています。 :<syntaxhighlight lang=ruby> 1 + 2 #=> 3 3 - 4 #=> -1 5 * 6 #=> 30 7 / 8 #=> 0 9 % 4 #=> 1 1 == 1 #=> true 2 < 3 #=> true 4 > 5 #=> false </syntaxhighlight> ==== 浮動小数点数(Float) ==== Rubyには浮動小数点数を扱うためのFloatクラスがあります。 Floatクラスは、IEEE 754のbinary64をRubyのクラス化したものです。 {{Main|[https://ruby-doc.com/3.3.0/Float.html class Float - RDoc Documentation]}} 以下のような数値リテラルで浮動小数点数を表現することができます。 :<syntaxhighlight lang=ruby> 1.23 #=> 1.23 1.2e3 #=> 1200.0 -4.56 #=> -4.56 4E10 #=> 40000000000.0 </syntaxhighlight> また、浮動小数点数の四則演算や比較演算子なども、Floatクラスで定義されています。 :<syntaxhighlight lang=ruby> 1.2 + 3.4 #=> 4.6 5.6 - 7.8 # -2.1999999999999997 9.0 * 1.2 # 10.8 3.4 / 5.6 # 0.6071428571428571 1.2 == 1.2 #=> true 2.3 < 4.5 # true 6.7 > 8.9 # false 1.0 / 0.0 #=> Infinity 1.0 / -0.0 # -Infinity 0.0 / 0.0 # NaN </syntaxhighlight> ===== coerceメソッドによる型強制 ===== Rubyの<code>coerce</code>メソッドは、数値演算の際に異なる型のオブジェクトを同じ型に変換するために使用されます。一般的には、<code>coerce</code>メソッドは二項演算子(たとえば<code>+</code>、<code>-</code>、<code>*</code>、<code>/</code>など)が呼び出されたときに使用されます。 例えば、<code>1 + 2.0</code>の場合、整数型の<code>1</code>と浮動小数点数型の<code>2.0</code>が加算されます。このとき、Rubyは<code>1</code>を<code>Float</code>型に変換してから加算を行います。この変換は<code>coerce</code>メソッドによって行われます。 具体的には、<code>1 + 2.0</code>の場合、Rubyは以下のように処理を行います: # 整数型の<code>1</code>が<code>Float</code>型の<code>2.0</code>に合わせるために、<code>1.coerce(2.0)</code>を呼び出します。 # <code>coerce</code>メソッドは、<code>[1.0, 2.0]</code>という配列を返します。これは<code>1</code>が<code>Float</code>型に変換された結果です。 # Rubyは、<code>1.0 + 2.0</code>(<code>1.coerce(2.0).reduce(&:+)</code>)を計算し、結果の<code>3.0</code>を返します。 このように、<code>coerce</code>メソッドは異なる型のオブジェクトを同じ型に変換して演算を行う際に使用されます。 ==== 有理数(Rational) ==== Rubyの<code>Rational</code>クラスは、有理数を表現するためのクラスです。 有理数は、整数のペアとして表現されます:a/b(b>0)、ここでaは分子であり、bは分母です。 数学的には、整数aは有理数a/1と等価です。 {{Main|[https://ruby-doc.com/3.3.0/Rational.html class Rational - RDoc Documentation]}} 以下は、<code>Rational</code>クラスのインスタンスを作成する方法の例です。 :<syntaxhighlight lang=ruby> p 1r #=> (1/1) p 3/4r # (3/4) p Rational(1) # (1/1) p Rational(3, 4) # (3/4) p Rational(0.3) # (5404319552844595/18014398509481984) p Rational('0.3') # (3/10) p Rational(3)/10 # (3/10) p 3.to_r/10 # (3/10)) </syntaxhighlight> <code>Rational</code>クラスのインスタンスは、有理数の四則演算や比較演算を行うことができます。 :<syntaxhighlight lang=ruby> a = 2/3r b = 4/5r p a + b #=> (22/15) p a - b # (-2/15) p a * b # (8/15) p a / b # (10/9) p a == b #=> false p a != b # true p a > b # false p a >= b # false p a <=> 0.0/0.0 #=> nil </syntaxhighlight> ==== 複素数(Complex) ==== Rubyの<code>Complex</code>クラスは、複素数を表現するためのクラスです。 このクラスを使用すると、複素数を直交座標形式または極座標形式で作成し、演算を行うことができます。 {{Main|[https://ruby-doc.com/3.3.0/Complex.html class Complex - RDoc Documentation]}} 直交座標形式の複素数は、実数部と虚数部のペアで表されます。以下は、複素数を直交座標形式で作成する方法の例です。 :<syntaxhighlight lang=ruby> c1 = 3 + 4i C2 = Complex.rect(3, 4) c3 = Complex(3, 4) c4 = '3 + 4i'.to_c c5 = 3 + 4 * Complex::I </syntaxhighlight> # <code>c1 = 3 + 4i</code>: この行では、虚数単位 <code>i</code> を使って直接複素数を表現しています。<code>3</code> は実部であり、<code>4</code> は虚部です。 # <code>c2 = Complex.rect(3, 4)</code>: ここでは、<code>Complex</code> クラスの <code>rect</code> メソッドを使用して複素数を作成しています。これは、実部と虚部を指定する方法です。 # <code>c3 = Complex(3, 4)</code>: この行では、<code>Complex</code> クラスのコンストラクタを使用して複素数を作成しています。引数として実部と虚部を指定します。 # <code>c4 = '3 + 4i'.to_c</code>: ここでは、文字列 <code>'3 + 4i'</code> を複素数に変換しています。<code>to_c</code> メソッドは、文字列が複素数の形式である場合に使用できます。 # <code>c5 = 3 + 4 * Complex::I</code>: 最後の行では、<code>Complex::I</code> 定数を使って複素数を作成しています。<code>Complex::I</code> は虚数単位を表します。 極座標形式の複素数は、絶対値(大きさ)と偏角で表されます。以下は、複素数を極座標形式で作成する方法の例です。 :<syntaxhighlight lang=ruby> Complex.polar(5, Math::PI / 4) # 絶対値が5、偏角がπ/4の複素数を作成 </syntaxhighlight> これらの方法を使って、異なる形式の入力を扱い、複素数を生成することができます。 直交座標形式と極座標形式の相互変換 :<syntaxhighlight lang=ruby> c = Complex(3, 4) p c.real # 3 p c.imaginary # 4 p c.rect # [3, 4] p c.polar # [5.0, 0.9272952180016122] z = p Complex.polar(10, Math::PI / 4) p z.real # 7.0710678118654755 p z.imag # 7.071067811865475 </syntaxhighlight> <code>Complex</code> クラスでは、複素数の演算もサポートされています。例えば、加算や乗算、除算などが可能です。 :<syntaxhighlight lang=ruby> a = Complex(2, 3) b = Complex(4, 5) c = a + b # 6 + 8i d = a - b # -2 - 2i e = a * b # -7 + 22i f = a / b # 0.5609756097560976 + 0.0487804878048781i </syntaxhighlight> また、複素数同士の比較も可能です。 <code>==</code> 演算子を用いることで、2つの複素数が等しいかを比較することができ、 <code>!=</code> 演算子を用いることで、2つの複素数が等しくないを比較することができます。 :<syntaxhighlight lang=ruby> a = Complex(2, 3) b = Complex(2, 3) puts a == b # true puts a != b # false </syntaxhighlight> 複素数の一致・不一致は定義されますが、大小関係はないので <code><</code>, <code>></code>, <code><=</code>, <code>>=</code> や <code><=></code> は定義されていません 複素数の演算や比較において、実数と複素数の演算や比較も可能です。 この場合、実数は複素数の虚数部が0のものとして扱われます。例えば、以下のような計算が可能です。 :<syntaxhighlight lang=ruby> a = Complex(2, 3) b = 4 c = a + b # 6 + 3i d = a * b # 8 + 12i e = a > b # true </syntaxhighlight> ==== Numericと、そのサブクラスのメソッド ==== Numericと、そのサブクラスのメソッドはの実装は均質ではなく、整数だけがビット演算が可能であったり、複素数だけが大小の比較が出来なかったりします。 このため実装状況を調べたいのですが、手でテストケースを書くのも手数がかかるので、自動的に表にまとめるプログラムを書いてみました。 ;[https://paiza.io/projects/5r9t7OejxrGB4s0z19vvSA?language=ruby メソッドの実装状況表を書く] :<syntaxhighlight lang=ruby> def build_table(types) headers = types.map(&:to_s) objects = types.map do |t| eval("#{t}.new") rescue StandardError eval("#{t}(0)") end # メソッドの和集合を求める all_methods = objects.map(&:methods).flatten.sort.uniq all_methods -= Object.methods all_methods += Comparable.methods all_methods.sort! all_methods.uniq! method_str_width = all_methods.map(&:to_s).map(&:length).max # ヘッダー head = ['Method'.rjust(method_str_width), *headers.map { _1.center 8 }].join(' ') # 各オブジェクトについて、メソッドが存在するかどうかを確認し表を構築する table = '' index = 0 all_methods.each do |method| next unless objects.any? { |obj| obj.methods.include? method } table << "#{head}\n#{'-' * head.length}\n" if (index % 10).zero? table << method.to_s.rjust(26) << ' ' table << objects.map do |obj| (obj.methods.include?(method) ? 'o' : '-').center(8) end.join(' ') table << "\n" index += 1 end puts table end build_table([Numeric, Integer, Float, Rational, Complex])</syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- ! o o o o o != o o o o o !~ o o o o o % o o o o - & - o - - - * - o o o o ** - o o o o + - o o o o +@ o o o o o - - o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- -@ o o o o o / - o o o o < o o o o - << - o - - - <= o o o o - <=> o o o o o == o o o o o === o o o o o =~ o o o o o > o o o o - Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- >= o o o o - >> - o - - - [] - o - - - ^ - o - - - __id__ o o o o o __send__ o o o o o abs o o o o o abs2 o o o o o allbits? - o - - - angle o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- anybits? - o - - - arg o o o o o between? o o o o - bit_length - o - - - ceil o o o o - chr - o - - - clamp o o o o - class o o o o o clone o o o o o coerce o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- conj o o o o o conjugate o o o o o define_singleton_method o o o o o denominator o o o o o digits - o - - - display o o o o o div o o o o - divmod o o o o - downto - o - - - dup o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- enum_for o o o o o eql? o o o o o equal? o o o o o even? - o - - - extend o o o o o fdiv o o o o o finite? o o o o o floor o o o o - freeze o o o o o frozen? o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- gcd - o - - - gcdlcm - o - - - hash o o o o o i o o o o - imag o o o o o imaginary o o o o o infinite? o o o o o inspect o o o o o instance_eval o o o o o instance_exec o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- instance_of? o o o o o instance_variable_defined? o o o o o instance_variable_get o o o o o instance_variable_set o o o o o instance_variables o o o o o integer? o o o o o is_a? o o o o o itself o o o o o kind_of? o o o o o lcm - o - - - Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- magnitude o o o o o method o o o o o methods o o o o o modulo o o o o - nan? - - o - - negative? o o o o - next - o - - - next_float - - o - - nil? o o o o o nobits? - o - - - Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- nonzero? o o o o o numerator o o o o o object_id o o o o o odd? - o - - - ord - o - - - phase o o o o o polar o o o o o positive? o o o o - pow - o - - - pred - o - - - Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- prev_float - - o - - private_methods o o o o o protected_methods o o o o o public_method o o o o o public_methods o o o o o public_send o o o o o quo o o o o o rationalize - o o o o real o o o o o real? o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- rect o o o o o rectangular o o o o o remainder o o o o - remove_instance_variable o o o o o respond_to? o o o o o round o o o o - send o o o o o singleton_class o o o o o singleton_method o o o o o singleton_method_added o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- singleton_methods o o o o o size - o - - - step o o o o - succ - o - - - taint o o o o o tainted? o o o o o tap o o o o o then o o o o o times - o - - - to_c o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- to_enum o o o o o to_f - o o o o to_i - o o o o to_int o o o o o to_r - o o o o to_s o o o o o truncate o o o o - trust o o o o o untaint o o o o o untrust o o o o o Method Numeric Integer Float Rational Complex ----------------------------------------------------------------------- untrusted? o o o o o upto - o - - - yield_self o o o o o zero? o o o o o | - o - - - ~ - o - - - </syntaxhighlight> === 文字列(String) === Rubyでは、文字列(String)はダブルクォート(")で囲まれた文字列リテラルで表します。シングルクォート(')で囲まれた文字列リテラルは、単なる文字列であり、式の展開やエスケープシーケンスの展開が行われません。 :<syntaxhighlight lang=ruby> name = "Alice" puts "Hello, #{name}!" #=> "Hello, Alice!" puts 'Hello, #{name}!' #=> "Hello, \#{name}!" </syntaxhighlight> ==== 文字列中の式の展開 ==== Rubyでは、ダブルクォートで囲まれた文字列リテラルの中で式を展開することができます。式を展開する場合は、#{}を使います。式を#{}で囲んで文字列中に埋め込むことができます。 :<syntaxhighlight lang=ruby> x = 10 puts "xの値は#{x}です" #=> "xの値は10です" puts "xの二乗は#{x ** 2}です" #=> "xの二乗は100です" </syntaxhighlight> また、式を展開する場合は、式が評価されてから文字列中に埋め込まれます。そのため、式の中で定義された変数などの値も展開されます。 :<syntaxhighlight lang=ruby> x = 10 puts "xの値は#{x}です" #=> "xの値は10です" x = 20 puts "xの値は#{x}です" #=> "xの値は20です" </syntaxhighlight> なお、シングルクォートで囲まれた文字列リテラルでは、式の展開は行われず、文字列中にそのまま#{...}が表示されます。 :<syntaxhighlight lang=ruby> x = 10 puts 'xの値は#{x}です' #=> "xの値は\#{x}です" </syntaxhighlight> ==== エスケープシーケンス ==== 以下がRubyで使用できる主なエスケープシーケンスです。 :{| class=wikitable |+ エスケープシーケンス !エスケープシーケンス !意味 |- ! \\ |バックスラッシュ |- ! \' |シングルクォート |- ! \" |ダブルクォート |- ! \a | ベル音(BEL) |- ! \b |バックスペース |- ! \f |改ページ(FF) |- ! \n |改行 |- ! \r |キャリッジリターン(CR) |- ! \t | 水平タブ |- ! \v | 垂直タブ |- ! \e | エスケープ文字(ESC) |- ! \s | 空白 |- ! \nnn | 8進数表記の文字コード(nは0〜7の数字) |- ! \xnn | 16進数表記の文字コード(nは0〜9またはA〜F) |- ! \unnnn | Unicode文字コード(nは0〜9またはA〜F) |- ! \Unnnnnnnn | Unicode文字コード(nは0〜9またはA〜F) |} なお、Rubyではダブルクォートで囲まれた文字列リテラル内でエスケープシーケンスが展開されますが、シングルクォートで囲まれた文字列リテラル内では展開されません。 ==== 文字リテラル ==== Rubyにおける「文字リテラル」は、<code>?</code>を前置した1文字で表します。 :<syntaxhighlight lang=ruby> p ?a #==> "a" p ?字 #==> "字" p ?😈 #==> "😈" p ?😈.class #==> String </syntaxhighlight> Rubyに文字型はなく、文字リテラルは長さ1文字の文字列です。 ==== エンコーディング ==== Ruby では、文字列のエンコーディングを指定することができます。通常、UTF-8 エンコーディングが使われますが、別のエンコーディングを指定することもできます。 文字列のエンコーディングを指定するには、文字列の前に encoding: を付けて指定します。例えば、UTF-8 エンコーディングの文字列を扱う場合は以下のように書きます。 :<syntaxhighlight lang=ruby> str = "こんにちは".encoding("UTF-8") </syntaxhighlight> 別のエンコーディングを指定する場合は、指定したいエンコーディング名を文字列で渡します。 :<syntaxhighlight lang=ruby> str = "こんにちは".encoding("Shift_JIS") </syntaxhighlight> 上記のコードでは、文字列 "こんにちは" が Shift_JIS エンコーディングの文字列として扱われます。 文字列のエンコーディングを指定することで、文字列の変換時にエラーが発生することを防ぐことができます。 === 正規表現(Regexp) === Rubyにおける「正規表現クラス」と「正規表現リテラル」は、文字列をパターンとして表現するための機能です。 まず、「正規表現クラス」は <code>Regexp</code> クラスを使用して表現されます。以下のように、<code>Regexp.new</code> メソッドを使用して正規表現を作成することができます。 :<syntaxhighlight lang=ruby> pattern = Regexp.new("Hello, world!") </syntaxhighlight> また、正規表現オプションを指定する場合は、第2引数にオプションを渡すことができます。 :<syntaxhighlight lang=ruby> pattern = Regexp.new("hello, world!", Regexp::IGNORECASE) </syntaxhighlight> 次に、「正規表現リテラル」はスラッシュ <code>/</code> で囲まれた文字列で表現されます。以下のように、スラッシュで正規表現を作成することができます。 :<syntaxhighlight lang=ruby> pattern = /Hello, world!/ </syntaxhighlight> また、正規表現オプションを指定する場合は、スラッシュの後ろにオプションを付けることができます。 :<syntaxhighlight lang=ruby> pattern = /hello, world!/i </syntaxhighlight> 正規表現クラスと正規表現リテラルはどちらも同じ機能を持っており、どちらを使用しても正規表現を表現することができます。 ただし、リテラル表現の方が簡潔に表現することができ、可読性が高くなります。 :{| class="wikitable" |+ Rubyで使用できる正規表現 !正規表現 !ユースケース |- |<code>/pattern/</code> |文字列に一致するパターンを検索します。 |- |<code>/./</code> |任意の一文字に一致します。 |- |<code>/^pattern/</code> |文字列の先頭に一致するパターンを検索します。 |- |<code>/pattern$/</code> |文字列の末尾に一致するパターンを検索します。 |- |<code>/[abc]/</code> |a、b、cのいずれかに一致するものを検索します。 |- |<code>/[^abc]/</code> |a、b、c以外のものに一致するものを検索します。 |- |<code>/pattern*/</code> |0回以上の繰り返しに一致するパターンを検索します。 |- |<code>/pattern+/</code> |1回以上の繰り返しに一致するパターンを検索します。 |- |<code>/pattern?/</code> |0回または1回の繰り返しに一致するパターンを検索します。 |- |<code>/pattern{n}/</code> |n回の繰り返しに一致するパターンを検索します。 |- |<code>/pattern{n,}/</code> |n回以上の繰り返しに一致するパターンを検索します。 |- |<code>/pattern{n,m}/</code> |n回以上、m回以下の繰り返しに一致するパターンを検索します。 |- |<code>/(pattern)/</code> |一致する部分をグループ化します。 |- |<code>/(?<name>pattern)/</code> |一致する部分を名前でグループ化します。 |- |<code>/(?#comment)/</code> |正規表現内のコメントを書くことができます。 |- |<code>/\Apattern/</code> |文字列の先頭に一致するパターンを検索します。 |- |<code>/pattern\z/</code> |文字列の末尾に一致するパターンを検索します。 |- |<code>/\bpattern/</code> |単語の先頭に一致するパターンを検索します。 |- |<code>/pattern\b/</code> |単語の末尾 |- |<code>/pattern/i</code> |大文字小文字を区別せずに文字列に一致するパターンを検索します。 |- |<code>/pattern/m</code> |複数行の文字列に一致するパターンを検索します。 |- |<code>/pattern/x</code> |正規表現内で空白を無視します。 |- |<code>/pattern/o</code> |正規表現を一度だけコンパイルします。 |} === シンボル(Symbol) === Rubyの「シンボル(Symbol)」は、一度定義されたら変更できないイミュータブルなオブジェクトで、文字列に似たデータ型です。シンボルは、コロン(<code>:</code>)の後ろに名前を付けて表します。例えば、<code>:apple</code>や<code>:banana</code>などがシンボルの例です。 シンボルは、主にキーとして使われることが多く、文字列と比較して以下のようなメリットがあります。 * シンボルは一度生成されたら変更できないため、ハッシュのキーとして使うときに、キーの値が変更される心配がありません。 * 同じ名前のシンボルは必ず同じオブジェクトIDを持つため、検索が高速になります。 * 文字列よりもメモリ消費量が少ないため、大量のデータを扱う場合や、ハッシュのキーとして多用する場合に有効です。 シンボルを使う場合、通常はコロン(<code>:</code>)をつけて定義しますが、<code>:"apple"</code>のようにダブルクォーテーション(<code>"</code>)で囲って文字列から生成することもできます。また、文字列からシンボルを生成するには、<code>to_sym</code>メソッドまたは<code>intern</code>メソッドを使います。 例えば、以下のようにハッシュのキーとしてシンボルを使うことができます。 :<syntaxhighlight lang=ruby> fruits = { apple: 100, banana: 200, orange: 300 } puts fruits[:banana] # => 200 </syntaxhighlight> === 配列(Array) === Rubyの配列(Array)は、複数の要素を順序付けて格納するためのデータ構造です。配列は、異なるデータ型の要素を混在させることができます。例えば、整数、文字列、オブジェクトなどを含めることができます。 Rubyの配列は、角かっこ <code>[ ]</code> で囲まれた要素のコンマ区切りのリストで表されます。以下は、Rubyの配列の例です。 :<syntaxhighlight lang=ruby> numbers = [1, 2, 3, 4, 5] fruits = ["apple", "banana", "orange"] mixed_array = [1, "hello", true, 3.14] </syntaxhighlight> 配列内の要素は、0から始まるインデックスを使用してアクセスできます。例えば、<code>numbers</code>配列の最初の要素にアクセスするには、<code>numbers[0]</code>とします。 Rubyの配列は動的で、サイズを事前に宣言する必要はありません。要素を追加、削除、置換することができます。また、Rubyには多くの配列関連のメソッドが組み込まれており、配列を操作するための便利な機能が提供されています。 Rubyの配列には、さまざまな操作が可能です。以下にいくつかの一般的な操作を示します。 # '''要素の追加と削除:''' <code><<</code>演算子や<code>push</code>メソッドを使用して要素を配列の末尾に追加できます。また、<code>pop</code>メソッドを使用して末尾の要素を削除できます。他にも、<code>unshift</code>メソッドを使って先頭に要素を追加したり、<code>shift</code>メソッドを使って先頭の要素を削除したりすることもできます。 #:<syntaxhighlight lang=ruby> numbers << 6 # numbersは[1, 2, 3, 4, 5, 6] fruits.push("grape") # fruitsは["apple", "banana", "orange", "grape"] numbers.pop # numbersは[1, 2, 3, 4, 5] fruits.unshift("kiwi") # fruitsは["kiwi", "apple", "banana", "orange", "grape"] fruits.shift # fruitsは["apple", "banana", "orange", "grape"] </syntaxhighlight> # '''要素の取得と変更:''' インデックスを使用して特定の要素にアクセスし、値を取得したり変更したりできます。 #:<syntaxhighlight lang=ruby> puts numbers[2] # 3を出力 fruits[1] = "pear" # fruitsは["apple", "pear", "orange", "grape"] </syntaxhighlight> # '''配列の結合と分割:''' <code>+</code>演算子を使用して配列を結合したり、<code>concat</code>メソッドを使用したりして配列を結合できます。また、<code>slice</code>メソッドを使用して配列を部分的に分割することもできます。 #:<syntaxhighlight lang=ruby> combined_array = numbers + fruits # combined_arrayは[1, 2, 3, 4, 5, "apple", "pear", "orange", "grape"] part_of_fruits = fruits.slice(1, 2) # part_of_fruitsは["pear", "orange"] </syntaxhighlight> # '''配列と繰り返し:''' #:Rubyの配列は、繰り返し処理とともにしばしば使われるデータ構造です。配列の要素を1つずつ処理する場合には、以下のような繰り返し処理がよく用いられます。 #:<syntaxhighlight lang=ruby> fruits = ["apple", "banana", "orange"] fruits.each do |fruit| puts fruit end </syntaxhighlight> #:このコードでは、<code>each</code>メソッドを用いて、<code>fruits</code>配列の要素を順番に取り出しています。そして、ブロック引数<code>fruit</code>に格納された各要素を<code>puts</code>メソッドで出力しています。 #:また、配列の要素をインデックスで処理する場合には、以下のような繰り返し処理がよく用いられます。 #:<syntaxhighlight lang=ruby> fruits = ["apple", "banana", "orange"] fruits.each_with_index do |fruit, i| puts "#{i+1}: #{fruit}" end </syntaxhighlight> #:このコードでは、<code>each_with_index</code>メソッドを用いて、<code>fruits</code>配列の要素とインデックスを順番に取り出しています。そして、ブロック引数<code>fruit</code>に格納された各要素とブロック引数<code>i</code>に格納された各インデックスを使って、<code>puts</code>メソッドで出力しています。 # '''要素の検索とフィルタリング:''' <code>include?</code>メソッドを使用して特定の要素が配列に含まれているかどうかを確認したり、<code>select</code>メソッドを使用して条件に一致する要素のみを抽出したりすることができます。 #:<syntaxhighlight lang=ruby> puts numbers.include?(3) # trueを出力 even_numbers = numbers.select { |num| num.even? } # even_numbersは[2, 4] </syntaxhighlight> # '''配列操作メソッド:''' Rubyには、配列を操作するための便利なメソッドが豊富に用意されています。その中でも、<code>map</code>、<code>filter</code>、<code>reduce</code>は特によく使われるメソッドです。 #:<syntaxhighlight lang=ruby> numbers = [1, 2, 3, 4, 5] doubled_numbers = numbers.map do |n| n * 2 end p doubled_numbers #=> [2, 4, 6, 8, 10] even_numbers = numbers.filter do |n| n.even? end p even_numbers #=> [2, 4] sum = numbers.reduce do |result, n| result + n end puts sum #=> 15 # ブロックの代わりにシンボルを使って、次のように書くこともできます。 puts numbers.reduce(&:+) #=> 15 </syntaxhighlight> これらはRubyの配列を操作するための基本的な操作の一部です。Rubyの配列にはさらに多くの機能がありますが、これらの基本操作から始めることができます。 ==== メソッドチェイン ==== Rubyには、複数のメソッドを連鎖して呼び出す「メソッドチェイン」という機能があります。メソッドチェインを使うことで、1つのオブジェクトに対して複数のメソッドを簡潔につなげて処理することができます。 例えば、以下のような配列があるとします。 :<syntaxhighlight lang=ruby> fruits = ["apple", "banana", "orange"] </syntaxhighlight> この配列に対して、<code>map</code>メソッドで各要素を大文字にし、さらに<code>join</code>メソッドでカンマ区切りの文字列に変換する場合、通常の記法では以下のように書くことができます。 :<syntaxhighlight lang=ruby> fruits = ["apple", "banana", "orange"] upcase_fruits = fruits.map do |fruit| fruit.upcase end result = upcase_fruits.join(",") puts result #=> "APPLE,BANANA,ORANGE" </syntaxhighlight> しかし、メソッドチェインを使うと以下のように簡潔に書くことができます。 :<syntaxhighlight lang=ruby> fruits = ["apple", "banana", "orange"] result = fruits.map {|fruit| fruit.upcase}.join(",") puts result #=> "APPLE,BANANA,ORANGE" </syntaxhighlight> さらにブロックにシンボルを使うと以下のように簡潔に書くことができます。 :<syntaxhighlight lang=ruby> fruits = ["apple", "banana", "orange"] result = fruits.map(&:upcase).join(",") puts result #=> "APPLE,BANANA,ORANGE" </syntaxhighlight> このように、複数のメソッドを簡潔につなげて処理することができます。ただし、メソッドチェインは読みやすさを損なうことがあるため、適切に使うようにしましょう。 ;tapメソッド: <code>tap</code>メソッドは、オブジェクト自体を受け取り、ブロックをそのオブジェクトのコンテキストで実行し、最終的にそのオブジェクトを返すメソッドです。主な目的は、オブジェクトの特定の状態をデバッグやログ出力などで調査することです。例えば、以下のように使用できます。 :<syntaxhighlight lang=ruby> some_object.tap{|obj|p obj}.method1.method2.method3 </syntaxhighlight> このコードでは、<code>some_object</code> に対して <code>method1</code> から <code>method3</code> までのメソッドを呼び出す前に、<code>tap</code>ブロック内でその状態を出力しています。<code>tap</code>メソッドは常にそのオブジェクトを返すため、メソッドチェインを中断することなく、そのまま次のメソッド呼び出しを行うことができます。 これらの機能を組み合わせることで、効果的にコードを記述し、デバッグやログ出力などの目的に役立てることができます。 === ハッシュ(Hash) === Rubyの「ハッシュ(Hash)」は、キー(key)と値(value)のペアを保持するデータ構造であり、連想配列やマップとも呼ばれます。 ハッシュは波括弧(<code>{}</code>)で囲まれたキーと値のペアのリストで表され、キーと値の間には<code>=></code>を使って対応付けます。例えば、以下のように定義することができます。 :<syntaxhighlight lang=ruby> my_hash = { "key1" => "value1", "key2" => "value2" } </syntaxhighlight> この場合、<code>my_hash</code>は、<code>"key1"</code>というキーに対応する<code>"value1"</code>、<code>"key2"</code>というキーに対応する<code>"value2"</code>という値を持ちます。 ハッシュは、キーを使って値を取得することができます。例えば、上記の<code>my_hash</code>から値を取得するには、以下のように書きます。 :<syntaxhighlight lang=ruby> my_hash["key1"] # => "value1" </syntaxhighlight> また、<code>Hash</code>クラスの<code>each</code>メソッドを使うことで、ハッシュ内の全てのキーと値に対して繰り返し処理を行うことができます。以下は、<code>my_hash</code>の全てのキーと値を出力する例です。 :<syntaxhighlight lang=ruby> my_hash.each do |key, value| puts "#{key}: #{value}" end </syntaxhighlight> 出力結果は以下のようになります。 :<syntaxhighlight lang=text> key1: value1 key2: value2 </syntaxhighlight> このように、ハッシュはRubyで非常に重要なデータ構造の一つであり、プログラムで様々な用途に利用されます。 ==== シンボルをキーとした特別なハッシュリテラル ==== 例えば、以下のようなハッシュを考えます。 :<syntaxhighlight lang=ruby> my_hash = { :key1 => "value1", :key2 => "value2" } </syntaxhighlight> このハッシュでは、キーとしてシンボルを使っています。ただし、この記法は少し冗長であり、Rubyでは以下のように短縮して書くことができます。 :<syntaxhighlight lang=ruby> my_hash = { key1: "value1", key2: "value2" } </syntaxhighlight> このように、キーをシンボルで表す場合は、コロン(<code>:</code>)をキー名の前に付けることで簡潔に表現できます。これにより、より見やすく、読みやすいコードを書くことができます。 また、シンボルを使うことで、文字列を使う場合に比べて、ハッシュの検索速度が速くなることがあります。これは、シンボルはRuby内部で一度だけ生成され、それ以降は同じオブジェクトを使い回すため、検索時にオブジェクトの比較を高速に行えるためです。 なお、シンボルは、文字列と異なりイミュータブルなオブジェクトであり、文字列と同様に、<code>to_sym</code>メソッドを使って文字列からシンボルを生成することもできます。 === 範囲(Range) === Rubyの「範囲(Range)」は、ある値から別の値までの連続する要素を表すオブジェクトです。Rubyでは、範囲は<code>..</code>または<code>...</code>の範囲演算子を使って作成することができます。以下に例を示します。 :<syntaxhighlight lang=ruby> range1 = 1..5 # 1から5までの範囲を表すRangeオブジェクトを作成 range2 = 1...5 # 1から5未満までの範囲を表すRangeオブジェクトを作成 </syntaxhighlight> <code>..</code>を使うと、範囲に終端の値が含まれますが、<code>...</code>を使うと、範囲に終端の値は含まれません。 範囲は主に繰り返し処理に使われ、以下のように使うことができます。 :<syntaxhighlight lang=ruby> range = 1..5 range.each { |i| puts i } # 1から5までの値を1つずつ表示する </syntaxhighlight> このコードでは、<code>each</code>メソッドを使って、範囲内の値を1つずつ取り出し、ブロック内で処理しています。 また、範囲を使うことで、配列の一部を切り出すこともできます。例えば、以下のように範囲を使って、配列から一部の要素を取り出すことができます。 :<syntaxhighlight lang=ruby> array = [1, 2, 3, 4, 5] sub_array = array[1..3] # 2番目から4番目までの要素を取り出す puts sub_array # => [2, 3, 4] </syntaxhighlight> このように、範囲はRubyで様々な場面で使われ、プログラミングをより効率的に行うための重要な要素の1つです。 === ファイル (File) === Rubyにはファイル操作を行う標準ライブラリ <code>File</code> があります。これを使用することで、ファイルの読み込み・書き込み、存在確認・削除、ディレクトリの作成・削除などが簡単に行えます。 以下は、ファイル操作の基本的な使い方の例です。 :<syntaxhighlight lang=ruby> # ファイルの読み込み File.open('sample.txt', 'r') do |file| puts file.read end # ファイルの書き込み File.open('output.txt', 'w') do |file| file.write('Hello, world!') end # ファイルの存在確認 puts File.exist?('sample.txt') #=> true # ファイルの削除 File.delete('output.txt') # ディレクトリの作成 Dir.mkdir('mydir') # ディレクトリの削除 Dir.delete('mydir') </syntaxhighlight> === 数学(Math) === RubyのMathモジュールは、数学関数を提供するライブラリです。このモジュールに含まれる関数を使用することで、三角関数、指数関数、対数関数などの計算を簡単に行うことができます。 例えば、sin関数を使用する場合は、以下のように記述します。 :<syntaxhighlight lang=ruby> Math.sin(30 * Math::PI / 180) #=> 0.5 </syntaxhighlight> この例では、30度の正弦(sin)を計算しています。Math::PIは円周率を表しており、角度をラジアンに変換しています。 他にも、cos関数、tan関数、exp関数、log関数などがあります。詳細は公式ドキュメントを参照してください。 === Rubyの標準ライブラリとMix-in === Rubyの標準ライブラリには、多数のクラスやモジュールが含まれています。これらのクラスやモジュールは、Rubyプログラムで頻繁に使用される共通機能を提供しています。例えば、文字列(String)クラス、配列(Array)クラス、ファイル操作(File)クラスなどがあります。 また、RubyではMix-inという概念もあります。Mix-inとは、あるクラスに他のモジュールを取り込んで機能を追加することです。これにより、クラスを継承することなく、複数のモジュールから機能を組み合わせて利用することができます。 例えば、Enumerableモジュールは、Rubyの多くのクラスにEnumerableという機能を提供するためのモジュールです。Enumerableモジュールには、eachメソッドやmapメソッド、selectメソッドなどが含まれており、これらのメソッドを利用することで、配列やハッシュなどのオブジェクトに対して繰り返し処理を簡単に行うことができます。 以下に、標準ライブラリからいくつかの代表的なクラスやMix-inを挙げます。 * Stringクラス:文字列を扱うためのクラス * Arrayクラス:配列を扱うためのクラス * Hashクラス:ハッシュを扱うためのクラス * Fileクラス:ファイルを扱うためのクラス * Enumerableモジュール:繰り返し処理を行うためのモジュール * Comparableモジュール:比較演算を行うためのモジュール * Kernelモジュール:基本的なメソッドを提供するためのモジュール これらのクラスやMix-inは、Rubyプログラムの中で頻繁に使用されるため、覚えておくと便利です。詳細は公式ドキュメントを参照してください。 === 列挙(Enumerator) === RubyのEnumeratorクラスは、反復処理を行うためのクラスです。配列やハッシュなどのオブジェクトに対して繰り返し処理を行うことができます。 例えば、以下のようなコードを考えてみましょう。 :<syntaxhighlight lang=ruby> array = [1, 2, 3, 4, 5] array.each do |num| puts num end </syntaxhighlight> この場合、eachメソッドを使用して、配列の要素を順番に取り出していることがわかります。しかし、この方法では要素の途中で処理を中断したり、要素を複数回利用することができません。 ここでEnumeratorクラスを使用すると、以下のように書くことができます。 :<syntaxhighlight lang=ruby> array = [1, 2, 3, 4, 5] enum = array.to_enum loop do num = enum.next puts num end </syntaxhighlight> この場合、to_enumメソッドを使用して、Enumeratorオブジェクトを生成しています。そして、nextメソッドを使用して、順番に要素を取り出しています。この方法を使用することで、要素の途中で処理を中断することができますし、要素を複数回利用することもできます。 ==== Enumeratorを使ったジェネレータ ==== :<syntaxhighlight lang=ruby> def primegen n = 2 sieve = [] Enumerator.new do |y| loop do if sieve[n].nil? || sieve[n] == 0 y << n sieve[n * n] = n else factor = sieve[n] sieve[n + factor] = factor sieve[n] = 0 end n += 1 end end.lazy end p primegen.first(10) #=> [2, 3, 5, 7, 11, 13, 15, 17, 19, 21] primegen.each_with_index do |prime, index| break if index > 5 puts "#{index}: #{prime}" end # => 0: 2 # 1: 3 # 2: 5 # 3: 7 # 4: 11 # 5: 13 </syntaxhighlight> === %記法 === Rubyの%記法は、文字列や正規表現、配列、シンボルなどを作成するための簡潔な書き方のことを指します。%記法を使うことで、コードの可読性を高めることができます。 以下に、Rubyの%記法の使い方を表にまとめました。 :{| class="wikitable" |+ %記法 !記号 !役割 !例 |- |%q |シングルクォートで囲んだ文字列を作成する |<code>%q(Hello, world!)</code> => <code>"Hello, world!"</code> |- |%Q |ダブルクォートで囲んだ文字列を作成する |<code>%Q(Hello, #{name}!)</code> => <code>"Hello, Alice!"</code> |- |%r |正規表現リテラルを作成する |<code>%r(\d+-\d+-\d+)</code> => <code>/\\d+-\\d+-\\d+/</code> |- |%w |単語の配列を作成する |<code>%w(apple banana orange)</code> => <code>["apple", "banana", "orange"]</code> |- |%W |ダブルクォートで展開される単語の配列を作成する |<code>%W(#{fruit1} #{fruit2} #{fruit3})</code> => <code>["apple", "banana", "orange"]</code> |- |%s |シンボルを作成する |<code>%s(hello)</code> => <code>:hello</code> |- |%i |シンボルの配列を作成する |<code>%i(apple banana orange)</code> => <code>[:apple, :banana, :orange]</code> |} 上の例ではパッターンを丸括弧<code>()</code>で囲みましたが、波括弧<code>{}</code>・角括弧<code>[]</code>で囲むことも出来、括弧でない文字(例えば<code>!</code>)で始めたら、同じ文字(この場合は<code>!</code>)で閉じることが出来ます。 :<syntaxhighlight lang=ruby> # {} を使う例 puts %q{Hello, #{name}!} # => Hello, Ruby! # [] を使う例 puts %w[apple banana orange] # => ["apple", "banana", "orange"] puts %i[foo bar baz] # => [:foo, :bar, :baz] # ! を使う例 puts %Q!It's raining outside! # => It's raining outside puts %w!apple banana orange! # => ["apple", "banana", "orange"] # | を使う例 puts %Q|Hello, #{name}!| # => Hello, Ruby! puts %i|foo bar baz| # => [:foo, :bar, :baz] </syntaxhighlight> これらの例では、%記法の丸括弧 <code>()</code>の部分を、波括弧 <code>{}</code>、角括弧 <code>[]</code>、感嘆符 <code>!</code>、縦棒 <code>|</code> に置き換えています。%記法では、括弧以外にも様々な文字を使うことができますが、適切な文字を選んで使用することが重要です。 === 標準クラス階層の一覧化 === :<syntaxhighlight lang=ruby> def print_subclasses(klass, indent = 0) subclasses = klass.subclasses return if subclasses.empty? subclasses.to_a.sort{|a,b| a.to_s <=> b.to_s}.each do |subclass| puts "#{"\t" * indent}#{subclass}" print_subclasses(subclass, indent + 1) end end # <code>Object</code>から再帰的にサブクラスを表示 print_subclasses(Object.superclass) </syntaxhighlight> :このRubyのコードは、与えられたクラスのサブクラスを再帰的に表示するものです。以下はコードの解説です: :# <code>print_subclasses</code>メソッドは、与えられたクラス(<code>klass</code>)のサブクラスを再帰的に表示します。<code>indent</code>はインデントレベルを表し、デフォルト値は0です。 :# <code>subclasses</code>メソッドは、指定されたクラスの直接のサブクラスを返します。 :# <code>sort</code>メソッドは、サブクラスをアルファベット順に並べ替えます。 :# <code>each</code>メソッドは、サブクラスを1つずつ処理し、その名前を表示します。 :# <code>print_subclasses</code>メソッドを再帰的に呼び出すことで、サブクラスのサブクラスも同様に処理されます。 :# <code>Object.superclass</code>は、すべてのクラスの祖先である<code>Object</code>クラスから始まります。 :# 最後に、<code>print_subclasses(Object.superclass)</code>を呼び出すことで、すべてのクラスの階層構造を表示します。 次は、Rubyの標準クラス階層を再帰的に表示するものです。各クラスはその直接のサブクラスとしてインデントされて表示されます。以下に各部分の解説を示します: * <code>Object</code>クラスはRubyのほとんどのクラスの祖先となる基本クラスです。 ** <code>ARGF.class</code>: コマンドライン引数やファイルからの入力を扱うクラスです。 ** <code>Array</code>: 配列を表すクラスです。 ** <code>Binding</code>: メソッド呼び出しのコンテキストを保持するオブジェクトを表すクラスです。 ** <code>Complex::compatible</code>: 複素数を表すクラスです。 ** <code>DidYouMean</code>以下のクラス群: ユーザーの入力ミスに対する修正候補を提案する機能を提供するモジュールです。 ** <code>Dir</code>: ディレクトリを扱うクラスです。 ** <code>Encoding</code>以下のクラス群: 文字エンコーディングを扱うクラスです。 ** <code>Enumerator</code>以下のクラス群: 列挙可能なオブジェクトを生成するためのクラスです。 ** <code>ErrorHighlight</code>以下のクラス群: エラーメッセージをハイライトする機能を提供するモジュールです。 ** <code>Exception</code>以下のクラス群: 例外を扱うためのクラスです。 ** <code>FalseClass</code>: 真でない値を表すクラスです。 ** <code>Fiber</code>: コルーチンを表すクラスです。 ** <code>File::Stat</code>: ファイルの状態を表すクラスです。 ** <code>Gem</code>以下のクラス群: RubyGemsを扱うためのクラスです。 ** <code>Hash</code>: ハッシュを表すクラスです。 ** <code>IO</code>以下のクラス群: 入出力を扱うクラスです。 ** <code>MatchData</code>: 正規表現のマッチング結果を表すクラスです。 ** <code>Method</code>: メソッドオブジェクトを表すクラスです。 ** <code>Module</code>以下のクラス群: モジュールを表すクラスです。 ** <code>Monitor</code>以下のクラス群: スレッドセーフな処理を実現するためのクラスです。 ** <code>NameError::message</code>: 名前エラーのメッセージを表すクラスです。 ** <code>NilClass</code>: <code>nil</code>を表すクラスです。 ** <code>Numeric</code>以下のクラス群: 数値を表すクラスです。 *** <code>Integer</code>整数を表すクラスです。 *** <code>Complex</code>複素数を表すクラスです。 *** <code>Rational</code>有理数を表すクラスです。 ** <code>ObjectSpace::WeakMap</code>: 弱参照を使ったハッシュマップを表すクラスです。 ** <code>Proc</code>: プロシージャやラムダを表すクラスです。 ** <code>Process::Status</code>: プロセスのステータスを表すクラスです。 ** <code>Ractor</code>以下のクラス群: Rubyの並行処理を実現するためのクラスです。 ** <code>Random::Base</code>以下のクラス群: 乱数生成を行うためのクラスです。 ** <code>Range</code>: 範囲を表すクラスです。 ** <code>Regexp</code>: 正規表現を表すクラスです。 ** <code>RubyVM</code>以下のクラス群: Rubyの仮想マシンを扱うクラスです。 ** <code>String</code>: 文字列を表すクラスです。 ** <code>Struct</code>: 構造体を表すクラスです。 ** <code>Symbol</code>: シンボルを表すクラスです。 ** <code>Thread</code>以下のクラス群: スレッドを扱うクラスです。 ** <code>ThreadGroup</code>: スレッドグループを表すクラスです。 ** <code>Time</code>以下のクラス群: 時刻を表すクラスです。 ** <code>TracePoint</code>: トレースポイントを表すクラスです。 ** <code>TrueClass</code>: 真の値を表すクラスです。 ** <code>UnboundMethod</code>: バインドされていないメソッドを表すクラスです。 ** <code>Ractor::MovedObject</code>: 移動されたオブジェクトを表すクラスです。 これはRubyの標準ライブラリで定義されたクラス階層を表しており、各クラスがどのような階層構造にあるかを示しています。 ;結果:<syntaxhighlight lang=text> Object ARGF.class Array Binding Complex::compatible DidYouMean::ClassNameChecker DidYouMean::DeprecatedMapping DidYouMean::Formatter DidYouMean::KeyErrorChecker DidYouMean::MethodNameChecker DidYouMean::NullChecker DidYouMean::PatternKeyNameChecker DidYouMean::RequirePathChecker DidYouMean::SpellChecker DidYouMean::TreeSpellChecker DidYouMean::VariableNameChecker Dir Encoding Encoding::Converter Enumerator Enumerator::ArithmeticSequence Enumerator::Chain Enumerator::Lazy Enumerator::Generator Enumerator::Producer Enumerator::Yielder ErrorHighlight::DefaultFormatter ErrorHighlight::Spotter Exception ErrorHighlight::Spotter::NonAscii NoMemoryError ScriptError LoadError Gem::LoadError Gem::ConflictError Gem::MissingSpecError Gem::MissingSpecVersionError NotImplementedError SyntaxError SecurityError SignalException Interrupt StandardError ArgumentError Gem::Requirement::BadRequirementError UncaughtThrowError EncodingError Encoding::CompatibilityError Encoding::ConverterNotFoundError Encoding::InvalidByteSequenceError Encoding::UndefinedConversionError FiberError IOError EOFError IndexError KeyError StopIteration ClosedQueueError Ractor::ClosedError LocalJumpError Math::DomainError NameError NoMethodError NoMatchingPatternError NoMatchingPatternKeyError RangeError FloatDomainError RegexpError RuntimeError FrozenError Gem::Exception Gem::CommandLineError Gem::DependencyError Gem::DependencyResolutionError Gem::UnsatisfiableDependencyError Gem::DependencyRemovalException Gem::DocumentError Gem::EndOfYAMLException Gem::FilePermissionError Gem::FormatException Gem::GemNotFoundException Gem::SpecificGemNotFoundException Gem::GemNotInHomeException Gem::ImpossibleDependenciesError Gem::InstallError Gem::RuntimeRequirementNotMetError Gem::InvalidSpecificationException Gem::OperationNotSupportedError Gem::RemoteError Gem::RemoteInstallationCancelled Gem::RemoteInstallationSkipped Gem::RemoteSourceException Gem::RubyVersionMismatch Gem::UninstallError Gem::UnknownCommandError Gem::VerificationError Gem::WebauthnVerificationError IO::Buffer::AccessError IO::Buffer::AllocationError IO::Buffer::InvalidatedError IO::Buffer::LockedError Ractor::Error Ractor::IsolationError Ractor::MovedError Ractor::RemoteError Ractor::UnsafeError SystemCallError Errno::E2BIG Errno::EACCES Errno::EADDRINUSE Errno::EADDRNOTAVAIL Errno::EADV Errno::EAFNOSUPPORT Errno::EAGAIN IO::EAGAINWaitReadable IO::EAGAINWaitWritable Errno::EALREADY Errno::EBADE Errno::EBADF Errno::EBADFD Errno::EBADMSG Errno::EBADR Errno::EBADRQC Errno::EBADSLT Errno::EBFONT Errno::EBUSY Errno::ECANCELED Errno::ECHILD Errno::ECHRNG Errno::ECOMM Errno::ECONNABORTED Errno::ECONNREFUSED Errno::ECONNRESET Errno::EDEADLK Errno::EDESTADDRREQ Errno::EDOM Errno::EDOTDOT Errno::EDQUOT Errno::EEXIST Errno::EFAULT Errno::EFBIG Errno::EHOSTDOWN Errno::EHOSTUNREACH Errno::EHWPOISON Errno::EIDRM Errno::EILSEQ Errno::EINPROGRESS IO::EINPROGRESSWaitReadable IO::EINPROGRESSWaitWritable Errno::EINTR Errno::EINVAL Errno::EIO Errno::EISCONN Errno::EISDIR Errno::EISNAM Errno::EKEYEXPIRED Errno::EKEYREJECTED Errno::EKEYREVOKED Errno::EL2HLT Errno::EL2NSYNC Errno::EL3HLT Errno::EL3RST Errno::ELIBACC Errno::ELIBBAD Errno::ELIBEXEC Errno::ELIBMAX Errno::ELIBSCN Errno::ELNRNG Errno::ELOOP Errno::EMEDIUMTYPE Errno::EMFILE Errno::EMLINK Errno::EMSGSIZE Errno::EMULTIHOP Errno::ENAMETOOLONG Errno::ENAVAIL Errno::ENETDOWN Errno::ENETRESET Errno::ENETUNREACH Errno::ENFILE Errno::ENOANO Errno::ENOBUFS Errno::ENOCSI Errno::ENODATA Errno::ENODEV Errno::ENOENT Errno::ENOEXEC Errno::ENOKEY Errno::ENOLCK Errno::ENOLINK Errno::ENOMEDIUM Errno::ENOMEM Errno::ENOMSG Errno::ENONET Errno::ENOPKG Errno::ENOPROTOOPT Errno::ENOSPC Errno::ENOSR Errno::ENOSTR Errno::ENOSYS Errno::ENOTBLK Errno::ENOTCONN Errno::ENOTDIR Errno::ENOTEMPTY Errno::ENOTNAM Errno::ENOTRECOVERABLE Errno::ENOTSOCK Errno::ENOTSUP Errno::ENOTTY Errno::ENOTUNIQ Errno::ENXIO Errno::EOVERFLOW Errno::EOWNERDEAD Errno::EPERM Errno::EPFNOSUPPORT Errno::EPIPE Errno::EPROTO Errno::EPROTONOSUPPORT Errno::EPROTOTYPE Errno::ERANGE Errno::EREMCHG Errno::EREMOTE Errno::EREMOTEIO Errno::ERESTART Errno::ERFKILL Errno::EROFS Errno::ESHUTDOWN Errno::ESOCKTNOSUPPORT Errno::ESPIPE Errno::ESRCH Errno::ESRMNT Errno::ESTALE Errno::ESTRPIPE Errno::ETIME Errno::ETIMEDOUT Errno::ETOOMANYREFS Errno::ETXTBSY Errno::EUCLEAN Errno::EUNATCH Errno::EUSERS Errno::EXDEV Errno::EXFULL Errno::NOERROR ThreadError TypeError ZeroDivisionError SystemExit Gem::SystemExitException SystemStackError fatal FalseClass Fiber File::Stat Gem::BasicSpecification Gem::Specification Gem::StubSpecification Gem::Dependency Gem::ErrorReason Gem::PlatformMismatch Gem::SourceFetchProblem Gem::List Gem::PathSupport Gem::Platform Gem::Requirement Gem::StubSpecification::StubLine Gem::UnknownCommandSpellChecker Gem::Version Hash IO File IO::Buffer MatchData Method Module Class Refinement Monitor MonitorMixin::ConditionVariable NameError::message NilClass Numeric Complex Float Integer Rational ObjectSpace::WeakMap Proc Process::Status Ractor Random::Base Random Range Rational::compatible Regexp RubyVM RubyVM::AbstractSyntaxTree::Node RubyVM::InstructionSequence String DidYouMean::ClassNameChecker::ClassName Warning::buffer Struct #<Class:0x0000798f28922be8> #<Class:0x0000798f2902c5b0> Process::Tms Symbol Thread Process::Waiter Thread::Backtrace Thread::Backtrace::Location Thread::ConditionVariable Thread::Mutex Thread::Queue Thread::SizedQueue ThreadGroup Time Time::tm TracePoint TrueClass UnboundMethod Ractor::MovedObject </syntaxhighlight> == RDoc == RDocとは、Rubyドキュメンテーションの生成ツールであり、Rubyのプログラムに対する文書化を支援するためのツールです。RDocを使用すると、Rubyのプログラムに関する情報をドキュメントとして出力することができます。これにより、ユーザーは作成されたコードを理解するための情報が提供され、開発者は自分たちのコードを文書化することができます。RDocは、Rubyの標準ライブラリに含まれています。 === 構文 === RDocは、Rubyのための文書作成システムで、コード内で注釈コメントを書くことで、自動的にドキュメントを生成します。以下はRDocの構文についての解説です。 RDocの注釈コメントは、通常のRubyコメントとして記述されますが、一つ上に「#」の代わりに「=begin」と「=end」を使ってマークアップを開始し、終了します。 以下は、RDocのマークアップの例です。 :<syntaxhighlight lang=ruby> =begin This class does some cool things. == Example An example of how to use this class: MyClass.new.do_cool_thing == Copyright Copyright (c) 2022 John Doe. All rights reserved. =end</syntaxhighlight> RDocは、以下の形式のマークアップタグをサポートしています。 * <code>#</code>: コメント * <code>=begin</code>/<code>=end</code>: ドキュメントの開始/終了 * <code>==</code>: セクションの開始 * <code>*</code>: 箇条書きの開始 * <code>+</code>: リストの開始 * <code>-</code>: リストの終了 * <code>!></code>: コードブロックの開始 * <code><nowiki><pre></nowiki></code>/<code><nowiki></pre></nowiki></code>: コードブロックの開始/終了 * <code>+methodName+(args)+</code>: メソッドの定義 * <code>(arg)</code>, <code>(arg=default)</code>: 引数の指定 * <code>returns (type)</code>: 戻り値の指定 * <code>\</code>: ラインコンティニュー === RDocの実行 === RDocの実行には、次のコマンドを使用します。 :<syntaxhighlight lang=bash> $ rdoc [options] [names...] </syntaxhighlight> オプションには、ドキュメンテーションを生成するFormattersや、ドキュメント化するファイルの指定などが含まれます。<code>names</code>には、ドキュメンテーションを生成するファイルまたはディレクトリを指定します。 以上が、RDocの構文解説です。 == 附録 == {{先頭に戻る}} === Rubyの変更の概要 === {{先頭に戻る|title=附録に戻る|label=附録|style=border-top:1px solid gray;}} :<syntaxhighlight lang=ruby highlight=18> </syntaxhighlight> :<syntaxhighlight lang=text> </syntaxhighlight> ==== Ruby-3.3.0 ==== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} Ruby 3.3.0では、多くの重要な変更が導入されました。その中には、言語機能の改善、コアクラスの更新、標準ライブラリの更新、C APIの更新、実装の改善などが含まれます。 ;言語機能の変更: :# 匿名の可変長引数とキーワード可変長引数が引数として渡せるようになりました。 :# Procオブジェクトのdupとcloneメソッドが#initialize_dupおよび#initialize_cloneフックを呼び出すようになりました。 :# "Find pattern" が実験的ではなくなりました。 :# ブロック内での匿名パラメータの転送が制限されました。 :<syntaxhighlight lang=ruby> # Ruby 3.3.0での変更点の例 # 匿名の可変長引数とキーワード可変長引数が引数として渡せるようになりました。 def example(*args, **kwargs) p args p kwargs end example(1, 2, 3, key1: 'value1', key2: 'value2') # Procオブジェクトのdupとcloneメソッドが#initialize_dupおよび#initialize_cloneフックを呼び出すようになりました。 proc_object = proc { |x| x * 2 } cloned_proc = proc_object.clone p cloned_proc.call(5) # => 10 # Range#overlap?メソッドが追加されました。 range1 = 1..5 range2 = 4..8 p range1.overlap?(range2) # => true </syntaxhighlight> ;Core classesの更新: :# Array#packとString#unpackが未知のディレクティブに対してArgumentErrorを発生させるようになりました。 :# メソッドRange#overlap?が追加され、2つの範囲が重なっているかどうかを確認できるようになりました。 ;標準ライブラリの更新: :# RubyGemsとBundlerが、必要なgemをGemfileやgemspecに追加せずにrequireした場合に警告を発生させるようになりました。 :# 多くの標準ライブラリのバージョンが更新されました。 ;C APIの更新: :# 新しいAPIが導入されいくつかのAPUが廃止されました。 :# Postponed job APIが変更され、新しいAPIが追加されました。 ; 実装の改善: :# パーサーがBisonからLrama LALRパーサージェネレーターに置き換えられました。 :# GCとメモリ管理のパフォーマンスが大幅に向上しました。 :# YJITのパフォーマンスとメモリ使用量が改善されました。 :# MJITが削除され、代わりにRJITが導入されました。 これらの変更により、Ruby 3.3.0はより高速で効率的なバージョンになりました。 ==== Ruby-3.2.0 ==== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} Ruby 3.2.0では、いくつかの重要な変更と新機能が導入されています。以下に概要を示します: # 言語の変更: #* 匿名の可変長引数とキーワード可変長引数が引数として渡せるようになりました。 #* 単一の位置引数とキーワードを受け入れるProcは、自動的にスプラットしなくなりました。 #* 明示的なオブジェクトに対する定数の割り当て評価順序が一貫性を持つようになりました。 #* "Find pattern" が実験的ではなくなりました。 #* restパラメータを持つメソッドが<code>*args</code>を通じてキーワード引数を委譲する場合、<code>ruby2_keywords</code>でマークする必要があります。 #:<syntaxhighlight lang=ruby> # Ruby 3.2.0の言語の変更 # 匿名の可変長引数とキーワード可変長引数が引数として渡せるようになりました。 # 例: def example(*args) p args end example(1, 2, 3) # => [1, 2, 3] # 単一の位置引数とキーワードを受け入れるProcは、自動的にスプラットしなくなりました。 # 例: proc_example = proc { |a, **kw| [a, kw] } p proc_example.call(1, x: 2, y: 3) # => [1, {:x=>2, :y=>3}] # 明示的なオブジェクトに対する定数の割り当て評価順序が一貫性を持つようになりました。 # 例: class Foo; end BAR = :baz Foo::BAR = BAR p Foo::BAR # => :baz # "Find pattern" が実験的ではなくなりました。 # restパラメータを持つメソッドが*argsを通じてキーワード引数を委譲する場合、ruby2_keywordsでマークする必要があります。 # 例: def target(**kw) p kw end ruby2_keywords def delegate(*args) target(*args) end delegate(a: 1, b: 2) # => {:a=>1, :b=>2} </syntaxhighlight> # コアクラスの更新: #* 継承可能なファイバーストレージのための<code>Fiber.[]</code>と<code>Fiber.[]=</code>が導入されました。 #* Thread、IO、Class、Data、Encoding、Enumerator、Exception、Hash、Integer、Kernel、MatchData、Module、Proc、Process、Regexp、Refinement、RubyVM::AbstractSyntaxTree、Set、String、Struct、Timeなどの新しいメソッドや機能が追加されました。 # 標準ライブラリの更新: #* Bundler、CGI、Coverage、Date、ERB、FileUtils、IRB、Net::Protocol、Pathname、Socket、URIなどの更新と機能強化が行われました。 # C APIの更新: #* 更新されたAPIや非推奨APIの除去、PRNGやスレッドの計装などのための新しいAPIが導入されました。 # 実装の改善: #* <code>Kernel#autoload</code>における競合状態が解消されました。 #* Regexpマッチングのキャッシュベースの最適化が導入されました。 #* 変数幅割り当てがデフォルトで有効化されました。 #* オブジェクトの形状を考慮した新しいインスタンス変数のキャッシングメカニズムが導入され、JITコードの生成が改善されました。 #* 命令シーケンスのマーキングやメジャーコレクションの高速化が実装されました。 # JITの改善: #* YJITが実験的な段階を抜け、複数のプラットフォーム(x86-64やarm64/aarch64など)をサポートするようになりました。 #* YJITはオブジェクトの形状を最適化するように改善され、物理メモリの遅延割り当てが導入されました。 #* MJITコンパイラがRubyで再実装され、フォークされたRubyプロセスで実行されるようになりました。 これらの変更と改善により、Rubyプログラミングのさまざまな側面でパフォーマンス、安定性、機能性が向上しました。ユーザーは、より良いエクスペリエンスと改善されたパフォーマンスのために、Ruby 3.2.0へのアップグレードを検討することが推奨されます。 ==== Ruby-3.1.0 ==== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} Ruby 3.1.0の変更点は以下の通りです: 言語の変更点: # ブロック引数が、ブロックが別のメソッドに渡される場合は匿名であってもよくなりました。 # ピン演算子は、式を受け取れるようになりました。 # ピン演算子は、インスタンス、クラス、グローバル変数をサポートするようになりました。 # 1行のパターンマッチングが実験的ではなくなりました。 # 複数の代入の評価順序が単一の代入の評価順序と一貫性が持たされるようになりました。 # ハッシュリテラルとキーワード引数では値を省略できるようになりました。 # main-Ractor以外のRactorも、共有可能なオブジェクトを参照する場合はクラス/モジュールのインスタンス変数を取得できるようになりました。 # 無限メソッド定義でもコマンド構文が許可されるようになりました。 :<syntaxhighlight lang=ruby> # ブロック引数が、ブロックが別のメソッドに渡される場合は匿名であってもよくなりました。 def foo(&) bar(&) end # ピン演算子は、式を受け取れるようになりました。 result = Prime.each_cons(2).lazy.find_all{_1 in [n, ^(n + 2)]}.take(3).to_a #=> [[3, 5], [5, 7], [11, 13]] # ピン演算子は、インスタンス、クラス、グローバル変数をサポートするようになりました。 @n = 5 result = Prime.each_cons(2).lazy.find{_1 in [n, ^@n]} #=> [3, 5] # 1行のパターンマッチングが実験的ではなくなりました。 # Parenthesesを省略できるようになりました。 [0, 1] => _, x {y: 2} => y: x #=> 1 y #=> 2 # 複数の代入の評価順序が単一の代入の評価順序と一貫性が持たされるようになりました。 # Ruby 3.1.0以前 foo[0], bar.baz = a, b # 評価順序: a, b, foo, []= on foo, bar, []= on bar, baz= on bar # Ruby 3.1.0以降 # 評価順序: foo, bar, a, b, []= on foo, baz= on bar foo[0], bar.baz = a, b # ハッシュリテラルとキーワード引数では値を省略できるようになりました。 # 例: {x: x, y: y} を {x:, y:} と書けます。 </syntaxhighlight> ;コアクラスの更新: : Array、Class、Enumerable、Enumerator::Lazy、File、GC、Integer、Kernel、Marshal、MatchData、Method / UnboundMethod、Module、Process、Struct、String、Thread、Thread::Backtrace、Thread::Queue、Time、TracePointなどのクラスに変更が加えられました。 ; 標準ライブラリの更新: : RubyGems、base64、benchmark、bigdecimal、bundler、cgi、csv、date、did_you_mean、digest、drb、erb、error_highlight、etc、fcntl、fiddle、fileutils、find、io-console、io-wait、ipaddr、irb、json、logger、net-http、net-protocol、nkf、open-uri、openssl、optparse、ostruct、pathname、pp、prettyprint、psych、racc、rdoc、readline、readline-ext、reline、resolv、rinda、ruby2_keywords、securerandom、set、stringio、strscan、tempfile、time、timeout、tmpdir、un、uri、yaml、zlibなどの更新があります。 C APIの更新、実装の改善、JIT(MJIT、YJIT)、静的解析、デバッガ、エラーハイライト、IRBの自動補完、その他の変更が含まれます。 ==== Ruby-3.0.0 ==== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} Ruby 3.0.0には、多くの言語の変更点が含まれています。主な変更点を以下に示します: # '''キーワード引数と位置引数の分離:''' キーワード引数は位置引数と区別されるようになりました。これにより、Ruby 2.7で警告が発生していたコードは、ArgumentErrorが発生するか、異なる動作をするようになります。 # '''Procの動作変更:''' 単一のrest引数とキーワードを受け入れるProcは、autosplattingの対象外となりました。これにより、単一のrest引数とキーワードを受け入れるProcの動作が統一されました。 # '''Arguments forwardingの改善:''' Arguments forwarding(...)が前方の引数をサポートするようになりました。 # '''パターンマッチングの改善:''' パターンマッチング(case/in)が実験的な段階から正式な機能に移行しました。また、一行のパターンマッチングも改良され、=>演算子が導入されました。 # '''Endless method definitionの導入:''' Endless method definitionが導入され、メソッドをより簡潔に定義することができるようになりました。 # '''文字列補間リテラルの変更:''' # frozen-string-literal: trueを使用している場合、文字列補間リテラルが凍結されなくなりました。 # '''静的解析の導入:''' 静的解析の基盤が導入され、RBSというRubyプログラムのための型定義言語が導入されました。また、TypeProfというRubyプログラムのための型解析ツールも実験的な形で提供されます。 # '''非推奨の警告の変更:''' 非推奨の警告はデフォルトで表示されなくなりました。 # '''$SAFEと$KCODEの変更:''' $SAFEと$KCODEは通常のグローバル変数として振る舞い、関連するC-APIメソッドが削除されました。 # '''yieldの変更:''' メソッド内のシングルトンクラス定義でのyieldは、警告ではなくSyntaxErrorとなりました。 # '''クラス変数のアクセスの変更:''' 同じ定義でクラス変数が上書きされた場合、RuntimeErrorが発生するようになりました。 # '''番号付きパラメータへの代入の変更:''' 番号付きパラメータへの代入は、警告ではなくSyntaxErrorとなりました。 :<syntaxhighlight lang=ruby> # キーワード引数と位置引数の分離 def example(arg, kwarg:) puts arg puts kwarg end # ArgumentErrorが発生します # example(123, kwarg: 456) # Procの動作変更 # autosplattingの対象外となりました proc = ->(*rest, **kwargs) { [rest, kwargs] } # [rest, kwargs]がそのまま返されます p proc.call(1, 2, a: 3, b: 4) # Arguments forwardingの改善 def forwarder(*args, **kwargs) receiver(*args, **kwargs) end def receiver(a, b:, c: nil) puts "a: #{a}, b: #{b}, c: #{c}" end forwarder(1, b: 2, c: 3) # => a: 1, b: 2, c: 3 # パターンマッチングの改善 case [1, 2] in [1, x] puts x end # => 2 # Endless method definitionの導入 def foo = puts "Hello" foo # => Hello # 文字列補間リテラルの変更 # # frozen-string-literal: trueを使用している場合、文字列補間リテラルが凍結されなくなりました foo = "foo #{Time.now}" # 静的解析の導入 # 型定義言語RBSが導入され、型解析ツールTypeProfが提供されます # 非推奨の警告の変更 # デフォルトで表示されなくなりました # $SAFEと$KCODEの変更 # 通常のグローバル変数として振る舞い、関連するC-APIメソッドが削除されました # yieldの変更 # メソッド内のシングルトンクラス定義でのyieldは、警告ではなくSyntaxErrorとなりました # クラス変数のアクセスの変更 class MyClass @@var = 1 end # RuntimeErrorが発生します # MyClass.class_eval { @@var = 2 } # 番号付きパラメータへの代入の変更 # SyntaxErrorが発生します # _1 = 10 </syntaxhighlight> これらの変更点は、Ruby 3.0.0で導入された主な機能です。これにより、より安全で効率的なコーディングが可能になり、言語の進化が促進されました。 === 改廃された技術 === {{先頭に戻る|title=附録に戻る|label=附録|style=border-top:1px solid gray;}} Rubyの改廃された技術や利用が推奨されない技術は、言語の進化、パフォーマンスの向上、シンプルさの追求、新しいプログラミングパラダイムへの対応により置き換えられます。以下に、代表的な技術を示します。 ==== <code>taint</code> メソッド ==== * '''サポート開始年:''' 1997年(Ruby 1.0) * '''サポート終了年:''' 2020年(Ruby 3.0で削除) ; 廃止または衰退の理由 : 信頼性を向上させるため、<code>taint</code>と<code>trust</code>メカニズムは非推奨となり削除されました。セキュリティモデルが変更されたことに伴います。 ; 代替技術 : 特定のセキュリティ要件に応じて、コードレビューや他の安全な実装方法を採用してください。 ==== <code>$==</code> グローバル変数 === * '''サポート開始年:''' 1997年(Ruby 1.0) * '''サポート終了年:''' 2007年(Ruby 1.9で削除) ; 廃止または衰退の理由 : 可読性の向上と、グローバル変数の乱用を避けるため削除されました。 ; 代替技術 : 特定の機能に応じて、<code>Thread</code>または<code>Fiber</code>ローカル変数を使用してください。 ==== <code>Object#==~</code> メソッド === * '''サポート開始年:''' 1997年(Ruby 1.0) * '''サポート終了年:''' 2018年(Ruby 2.5で削除) ; 廃止または衰退の理由 : 不要とされ、特定の意味を持たない<code>Object#=~</code>は削除されました。 ; 代替技術 : カスタムクラスでマッチングを実装する場合は、<code>#===</code>や明示的なメソッドを実装してください。 ==== <code>Fixnum</code> と <code>Bignum</code> クラス ==== * '''サポート開始年:''' 1997年(Ruby 1.0) * '''サポート終了年:''' 2017年(Ruby 2.4で削除) ; 廃止または衰退の理由 : 一貫性を持たせるために、整数型が<code>Integer</code>に統一されました。 ; 代替技術 : <code>Integer</code>クラスを使用してください。 ==== <code>Flip-flop</code> 演算子 ==== * '''サポート開始年:''' 1997年(Ruby 1.0) * '''サポート終了年:''' 2020年(Ruby 3.0で削除) ; 廃止または衰退の理由 : コードの可読性が低く、多くのケースで誤解を招くため非推奨化されました。 ; 代替技術 : 明示的な条件分岐や状態管理を用いて実装してください。 ==== <code>DL</code> ライブラリ ==== * '''サポート開始年:''' 2000年(Ruby 1.6) * '''サポート終了年:''' 2014年(Ruby 2.2で削除) ; 廃止または衰退の理由 : より安全で使いやすい<code>Fiddle</code>ライブラリに置き換えられました。 ; 代替技術 : <code>Fiddle</code>ライブラリを使用してください。 ==== <code>sprintf</code> における <code>%</code> フォーマット指定子 ==== * '''サポート開始年:''' 1997年(Ruby 1.0) * '''サポート終了年:''' 2018年(Ruby 2.5で非推奨、3.0で削除) ; 廃止または衰退の理由 : <code>%</code>の意味があいまいで、誤用される可能性があるため削除されました。 ; 代替技術 : 明示的なフォーマット指定子(例: <code>%d</code>や<code>%s</code>)を使用してください。 ==== <code>String#byteslice</code> の旧引数形式 ==== * '''サポート開始年:''' 2001年(Ruby 1.6) * '''サポート終了年:''' 2017年(Ruby 2.4で非推奨、2.6で削除) ; 廃止または衰退の理由 : 一貫性を保つため引数形式が変更されました。 ; 代替技術 : 新しい引数形式(<code>String#byteslice(start, length)</code>)を使用してください。 ==== 旧式のプロック引数 ==== * '''サポート開始年:''' 1997年(Ruby 1.0) * '''サポート終了年:''' 2011年(Ruby 1.9で削除) ; 廃止または衰退の理由 : 一貫した引数形式を推進し、動作を明確化するため削除されました。 ; 代替技術 : ブロック引数の新しい形式を使用してください(例: <code>proc { |x| ... }</code>)。 ==== YAML における Symbol のデフォルトロード ==== * '''サポート開始年:''' 2005年(Ruby 1.8) * '''サポート終了年:''' 2019年(Ruby 2.6で非推奨、3.0で削除) ; 廃止または衰退の理由 : セキュリティリスクを軽減するため、Symbolのデフォルトロードが廃止されました。 ; 代替技術 : <code>safe_load</code>メソッドを使用し、Symbolのロードを手動で有効化してください。 === コードギャラリー === {{先頭に戻る|title=附録に戻る|label=附録|style=border-top:1px solid gray;}} :<syntaxhighlight lang=ruby highlight=18> </syntaxhighlight> :<syntaxhighlight lang=text> </syntaxhighlight> ==== エラトステネスの篩 ==== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} エラトステネスの篩を、若干 Ruby らしく書いてみました。 ;エラトステネスの篩:<syntaxhighlight lang=ruby line> def eratosthenes(n) is_prime = [true] * (n + 1) is_prime[0] = false is_prime[1] = false (2..Math.sqrt(n)).each do |i| if is_prime[i] (i*i..n).step(i) do |j| is_prime[j] = false end end end primes = (2..n).select { |i| is_prime[i] } return primes end p eratosthenes(100) </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] </syntaxhighlight> ==== 最大公約数と最小公倍数 ==== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} 最大公約数と最小公倍数を、若干 Ruby らしく書いてみました。 ;最大公約数と最小公倍数:<syntaxhighlight lang=ruby line> def gcd2(m, n) = n == 0 ? m : gcd2(n, m % n) def gcd(*ints) = ints.reduce(&method(:gcd2)) def lcm2(m, n) = m * n / gcd2(m, n) def lcm(*ints) = ints.reduce(&method(:lcm2)) puts "gcd2(30, 45) => #{gcd2(30, 45)}" puts "gcd(30, 72, 12) => #{gcd(30, 72, 12)}" puts "lcm2(30, 72) => #{lcm2(30, 72)}" puts "lcm(30, 42, 72) => #{lcm(30, 42, 72)}" </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> gcd2(30, 45) => 15 gcd(30, 72, 12) => 6 lcm2(30, 72) => 360 lcm(30, 42, 72) => 2520 </syntaxhighlight> ==== 二分法 ==== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} [[W:二分法|二分法]]を、若干 Ruby らしく書いてみました。 ;[https://paiza.io/projects/9R72T8PZ3vDlXJXq08FgeA?language=ruby 二分法]:<syntaxhighlight lang=ruby line> def bisection(low, high, &f) x = (low + high) / 2.0 fx = f[x] return x if fx.abs < 1.0e-10 case fx <=> 0 when -1 then low = x when 1 then high = x end return bisection(low, high, &f) end puts bisection(0, 3) { |x| x - 1 } puts bisection(0, 3) { |x| x * x - 1 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 0.9999999999417923 1.0000000000291038 </syntaxhighlight> : [[旧課程(-2012年度)高等学校数学B/数値計算とコンピューター#2分法]]の例を Ruby に移植しました。 == 関連項目 == * [[Ruby on Rails]] == 脚註 == <references /> [[Category:Ruby|*]] [[Category:プログラミング言語]] {{NDC|007.64}} sq8cig7zcmed9fwu8plcjfgwqzc2zmx 立教大対策 0 7906 263755 224569 2024-11-18T09:27:22Z Ayhxuknbsijceivzdjhswh 66317 /* 共通テスト利用入試 */ 263755 wikitext text/x-wiki {{wikipedia|立教大学}} *[[日本の大学受験ガイド]] > [[立教大対策]] 本項は、[[w:立教大学|立教大学]]の入学試験対策に関する事項である。 立教大学は、豊島区池袋に本部を置く私立大学。それほど規模は大きくない大学だが、知名度は高く、競争率も激しい。問題の難易度はそれほど高くないが、'''合格最低点はかなり高くなっており'''、しっかりとした実力がなければ合格は難しい。 私大の入試の特徴として、定員以上の人数の受験者に合格が与えられることが挙げられるが、立教大学もその例に洩れず、どの学部も定員よりも多い人数が合格になっている。よって、表面的な倍率(志願者数÷定員数)よりも実質倍率(受験者数÷合格数)の方が必ず低くなる。しかし、実質倍率4〜15倍(学部により異なる)は大学入試としては高い方なので、優秀な受験生でも注意が必要である。 == 個別学部日程 == 公式に合格最低点は示されていないが、池袋キャンパス就学の学部は75%前後(社会・経営・異文化コミュニケーション学部は80%弱)、新座キャンパス就学の学部は70%前後がボーダーと予測される。 === 英語 === 長文2題、文法(正誤なども含める)・会話問題(出題無しの場合も有)合わせて2題、文章中の空所に適切な単語を入れる問題1題の5問構成。年によっては6題になることもある。長文はミッション系の学校だけあって「高度」と思われがちであるが、実際はそれほど難しいものではない(センター試験の問題よりやや難易度が高い程度である)。むしろ、「長い」というのが特徴である。1000語超えの長文2つということも多いため、試験時間75分の中でどう捌けるかが問題になる。本文を読む前に、先に設問に目を通しておき、あらかじめヒントを拾っておくと良い。設問は大きく分けて文章の内容を問う内容一致問題、文章中の語彙に下線部を引き意味を選ばせる問題、長文のタイトルを選ぶ問題がある。どのタイプの問題も標準的な難易度なので落ち着いて取り組もう。ただし、長文には十分に慣れ、ある程度の速読技術も習得する必要があるだろう。また、時間配分にも注意しよう。 次に文法・会話問題であるが、これもまた標準的難易度であり、市販の文法書などで十分に対応できる。最後の記述問題と言うのは、短い文章がありその中の空欄に自分で単語を書いていくというものである。おそらく、ここで一番差がつくと思われる。問われている単語自体は難しくないものの、「どの単語がどのような場合に使われるのか」というような実践的知識がないと難しくなってしまうかもしれない。単語を覚える際は、例文と一緒に覚えるということを習慣づけておきたい。総じて標準的問題が多いものの、受験生のレベルはかなり高い。受験生の層からすると、本番では一問も落とせないような熾烈な戦いが展開されるだろう。 文学部は和文英訳か英文和訳を課すことがあるので、対策をしておくべきである。 === 国語 === 現代文2題、古文1題の構成(文学部は現代文1題、古文1題、漢文1題)。試験時間は75分。現代文、古文ともに記述問題がある。 * 現代文は分かりやすい文章から抽象度の高い文章まで様々である。全体の難易度としてはやや高め。出題は傍線部の説明問題、記述問題、内容真偽がある。説明問題は最初に自分で本文を根拠に答えを考え出してから、選択肢を吟味していくと良い。また解答の根拠が傍線部から離れている場合もあるので即答は危険である。記述問題は抜き出し問題が多い。解答の根拠を部分で見つけるのではなく、文章を一読し作者の言いたいことを加味しつつ考えること。最後の内容一致問題は本文を読みながら解くことをお勧めしたい。なお、文学部の場合は他学部よりも難易度がやや高めなので注意したい。 * 古文は単語の意味を直接聞くものや客観問題、文法問題がある。基盤がしっかりしていれば、それほど怖ろしくはないレベルだが、時代背景や平安貴族の文化などを多少勉強しておくと差をつけられるだろう。源氏物語からの出題が頻出。 * 漢文は文学部のみ出題される。難易度はセンター試験よりも低い。高得点が狙えるだろう。 === 選択科目 === 文系は日本史・世界史、数学、地理のいずれかを選択する。(学部により選択できる科目が違う。日本史と世界史は全学部で選択可。各自で大学ホームページ等で確認してもらいたい。) 理系は物理・化学・生物から1科目を選択。 '''日本史'''</br> 大問が2個あり、内容はどちらも空欄を埋める問題と下線部についての設問である。問題数が多く、難しい用語を書かせる問題や20字程度の記述問題も出題される。また、マイナーな事項のテーマ史が頻出なので、資料集にも目を通しておきたい(社会経済史では「土地制度」や「近代以降の女性運動」、文化史では「思想・宗教」「江戸時代の大衆文化」が頻出)。記述式の解答が約半数を占めるため語句を正確に覚えることが必要である。 '''世界史'''</br> 幅広い地域・時代・分野から出題される。大部分は教科書を中心とした基本的な問題だが、中には細かな知識を含む問題も見られるので、用語集・資料集も使ってより幅広い知識の形成を目指そう。年によっては、20~30字程度の記述問題も出題される。 '''数学'''</br> 大問数3問であるが、小問に分かれており、得点しやすくなっている。全体的にはやや易〜標準的な問題である。 '''地理'''</br> 観光学部のみ受験可能。基本的な問題が多いが、論述問題や描図問題が多いため日本史、世界史と同様に正確な知識が必要である。 == 共通テスト利用入試 == 共通テストの結果のみによって合否が決まる試験方式である。全学部全学科で3教科型と6教科型(ドイツ文学科のみ3科目と4科目)で実施されている。合格するためには、学部学科、科目数にもよるが、80%〜90%は必要である。3教科型は私大専願の受験生でも受験可能である。 経営・コミュニティ福祉学部は古典の試験を課さないなど、学部により入試科目が微妙に異なる。 == 全学部日程 == 立教大学では、個別学部日程のほかに全学部日程も行っている。合格難易度は学部別日程よりも若干高くなることもある。入試問題自体は個別学部日程とあまり変わらない。 === 3教科方式 === 一般的な入試方式。学部学科の併願はできない。 2017年度入試より、文・異文化コミュニケーション学部以外の文系学部は政治経済での受験が可能となった。 === グローバル方式 === 以下の出願資格を持つ者のみ出願可能。 ;出願資格 * GTEC CBT…1000点以上 * TEAP(Reading/Listening+Writing+Speaking)…226点以上 * IELTS…4.0以上 * TOEIC & TOEIC SW…790点以上 * TOEFL iBT…42点以上 * 実用英語技能検定(英検)…準1級以上 (2016年4月以降〜 2級以上) == 外部サイト == *[http://www.rikkyo.ac.jp/invitation/admissions/undergraduate/ 立教大公式サイト] [[Category:大学入試|りつきよう]] 9d1c8zyxbt0agclins60dfqqmbt6abv 263759 263755 2024-11-18T09:37:01Z Ayhxuknbsijceivzdjhswh 66317 263759 wikitext text/x-wiki {{wikipedia|立教大学}} *[[日本の大学受験ガイド]] > [[立教大対策]] 本項は、[[w:立教大学|立教大学]]の入学試験対策に関する事項である。 立教大学は、豊島区池袋に本部を置く私立大学。それほど規模は大きくない大学だが、知名度は高く、競争率も激しい。問題の難易度はそれほど高くないが、'''合格最低点はかなり高くなっており'''、しっかりとした実力がなければ合格は難しい。 私大の入試の特徴として、定員以上の人数の受験者に合格が与えられることが挙げられるが、立教大学もその例に洩れず、どの学部も定員よりも多い人数が合格になっている。よって、表面的な倍率(志願者数÷定員数)よりも実質倍率(受験者数÷合格数)の方が必ず低くなる。しかし、実質倍率4〜15倍(学部により異なる)は大学入試としては高い方なので、優秀な受験生でも注意が必要である。 == 個別学部日程 == 公式に合格最低点は示されていないが、池袋キャンパス就学の学部は75%前後(社会・経営・異文化コミュニケーション学部は80%弱)、新座キャンパス就学の学部は70%前後がボーダーと予測される。 === 英語 === 2024年現在では英検または共通テストの英語の成績を利用する。共通テストの成績を使う場合、リーディングとリスニングの配点比率が1:1のためリスニングの対策もしっかりすること。個別試験の英語は文学部の一部入試方式のみ課される。 ※以下のはかつての入試対策である。 長文2題、文法(正誤なども含める)・会話問題(出題無しの場合も有)合わせて2題、文章中の空所に適切な単語を入れる問題1題の5問構成。年によっては6題になることもある。長文はミッション系の学校だけあって「高度」と思われがちであるが、実際はそれほど難しいものではない(センター試験の問題よりやや難易度が高い程度である)。むしろ、「長い」というのが特徴である。1000語超えの長文2つということも多いため、試験時間75分の中でどう捌けるかが問題になる。本文を読む前に、先に設問に目を通しておき、あらかじめヒントを拾っておくと良い。設問は大きく分けて文章の内容を問う内容一致問題、文章中の語彙に下線部を引き意味を選ばせる問題、長文のタイトルを選ぶ問題がある。どのタイプの問題も標準的な難易度なので落ち着いて取り組もう。ただし、長文には十分に慣れ、ある程度の速読技術も習得する必要があるだろう。また、時間配分にも注意しよう。 次に文法・会話問題であるが、これもまた標準的難易度であり、市販の文法書などで十分に対応できる。最後の記述問題と言うのは、短い文章がありその中の空欄に自分で単語を書いていくというものである。おそらく、ここで一番差がつくと思われる。問われている単語自体は難しくないものの、「どの単語がどのような場合に使われるのか」というような実践的知識がないと難しくなってしまうかもしれない。単語を覚える際は、例文と一緒に覚えるということを習慣づけておきたい。総じて標準的問題が多いものの、受験生のレベルはかなり高い。受験生の層からすると、本番では一問も落とせないような熾烈な戦いが展開されるだろう。 文学部は和文英訳か英文和訳を課すことがあるので、対策をしておくべきである。 === 国語 === 現代文2題、古文1題の構成(文学部は現代文1題、古文1題、漢文1題)。試験時間は75分。現代文、古文ともに記述問題がある。 * 現代文は分かりやすい文章から抽象度の高い文章まで様々である。全体の難易度としてはやや高め。出題は傍線部の説明問題、記述問題、内容真偽がある。説明問題は最初に自分で本文を根拠に答えを考え出してから、選択肢を吟味していくと良い。また解答の根拠が傍線部から離れている場合もあるので即答は危険である。記述問題は抜き出し問題が多い。解答の根拠を部分で見つけるのではなく、文章を一読し作者の言いたいことを加味しつつ考えること。最後の内容一致問題は本文を読みながら解くことをお勧めしたい。なお、文学部の場合は他学部よりも難易度がやや高めなので注意したい。 * 古文は単語の意味を直接聞くものや客観問題、文法問題がある。基盤がしっかりしていれば、それほど怖ろしくはないレベルだが、時代背景や平安貴族の文化などを多少勉強しておくと差をつけられるだろう。源氏物語からの出題が頻出。 * 漢文は文学部のみ出題される。難易度はセンター試験よりも低い。高得点が狙えるだろう。 === 選択科目 === 文系は日本史・世界史、数学、地理のいずれかを選択する。(学部により選択できる科目が違う。日本史と世界史は全学部で選択可。各自で大学ホームページ等で確認してもらいたい。) 理系は物理・化学・生物から1科目を選択。 '''日本史'''</br> 大問が2個あり、内容はどちらも空欄を埋める問題と下線部についての設問である。問題数が多く、難しい用語を書かせる問題や20字程度の記述問題も出題される。また、マイナーな事項のテーマ史が頻出なので、資料集にも目を通しておきたい(社会経済史では「土地制度」や「近代以降の女性運動」、文化史では「思想・宗教」「江戸時代の大衆文化」が頻出)。記述式の解答が約半数を占めるため語句を正確に覚えることが必要である。 '''世界史'''</br> 幅広い地域・時代・分野から出題される。大部分は教科書を中心とした基本的な問題だが、中には細かな知識を含む問題も見られるので、用語集・資料集も使ってより幅広い知識の形成を目指そう。年によっては、20~30字程度の記述問題も出題される。 '''数学'''</br> 大問数3問であるが、小問に分かれており、得点しやすくなっている。全体的にはやや易〜標準的な問題である。 '''地理'''</br> 観光学部のみ受験可能。基本的な問題が多いが、論述問題や描図問題が多いため日本史、世界史と同様に正確な知識が必要である。 == 共通テスト利用入試 == 共通テストの結果のみによって合否が決まる試験方式である。全学部全学科で3教科型と6教科型(ドイツ文学科のみ3科目と4科目)で実施されている。合格するためには、学部学科、科目数にもよるが、80%〜90%は必要である。3教科型は私大専願の受験生でも受験可能である。 経営・コミュニティ福祉学部は古典の試験を課さないなど、学部により入試科目が微妙に異なる。 == 全学部日程 == 立教大学では、個別学部日程のほかに全学部日程も行っている。合格難易度は学部別日程よりも若干高くなることもある。入試問題自体は個別学部日程とあまり変わらない。 === 3教科方式 === 一般的な入試方式。学部学科の併願はできない。 2017年度入試より、文・異文化コミュニケーション学部以外の文系学部は政治経済での受験が可能となった。 === グローバル方式 === 以下の出願資格を持つ者のみ出願可能。 ;出願資格 * GTEC CBT…1000点以上 * TEAP(Reading/Listening+Writing+Speaking)…226点以上 * IELTS…4.0以上 * TOEIC & TOEIC SW…790点以上 * TOEFL iBT…42点以上 * 実用英語技能検定(英検)…準1級以上 (2016年4月以降〜 2級以上) == 外部サイト == *[http://www.rikkyo.ac.jp/invitation/admissions/undergraduate/ 立教大公式サイト] [[Category:大学入試|りつきよう]] 0z3y5y8tpapufqlrf18vvq89qncsuso 263760 263759 2024-11-18T09:37:07Z Ayhxuknbsijceivzdjhswh 66317 263760 wikitext text/x-wiki {{wikipedia|立教大学}} *[[日本の大学受験ガイド]] > [[立教大対策]] 本項は、[[w:立教大学|立教大学]]の入学試験対策に関する事項である。 立教大学は、豊島区池袋に本部を置く私立大学。それほど規模は大きくない大学だが、知名度は高く、競争率も激しい。問題の難易度はそれほど高くないが、'''合格最低点はかなり高くなっており'''、しっかりとした実力がなければ合格は難しい。 私大の入試の特徴として、定員以上の人数の受験者に合格が与えられることが挙げられるが、立教大学もその例に洩れず、どの学部も定員よりも多い人数が合格になっている。よって、表面的な倍率(志願者数÷定員数)よりも実質倍率(受験者数÷合格数)の方が必ず低くなる。しかし、実質倍率4〜15倍(学部により異なる)は大学入試としては高い方なので、優秀な受験生でも注意が必要である。 == 個別学部日程 == 公式に合格最低点は示されていないが、池袋キャンパス就学の学部は75%前後(社会・経営・異文化コミュニケーション学部は80%弱)、新座キャンパス就学の学部は70%前後がボーダーと予測される。 === 英語 === 2024年現在では英検または共通テストの英語の成績を利用する。共通テストの成績を使う場合、リーディングとリスニングの配点比率が1:1のためリスニングの対策もしっかりすること。個別試験の英語は文学部の一部入試方式のみ課される。 ※以下のはかつての入試対策である。 長文2題、文法(正誤なども含める)・会話問題(出題無しの場合も有)合わせて2題、文章中の空所に適切な単語を入れる問題1題の5問構成。年によっては6題になることもある。長文はミッション系の学校だけあって「高度」と思われがちであるが、実際はそれほど難しいものではない(センター試験の問題よりやや難易度が高い程度である)。むしろ、「長い」というのが特徴である。1000語超えの長文2つということも多いため、試験時間75分の中でどう捌けるかが問題になる。本文を読む前に、先に設問に目を通しておき、あらかじめヒントを拾っておくと良い。設問は大きく分けて文章の内容を問う内容一致問題、文章中の語彙に下線部を引き意味を選ばせる問題、長文のタイトルを選ぶ問題がある。どのタイプの問題も標準的な難易度なので落ち着いて取り組もう。ただし、長文には十分に慣れ、ある程度の速読技術も習得する必要があるだろう。また、時間配分にも注意しよう。 次に文法・会話問題であるが、これもまた標準的難易度であり、市販の文法書などで十分に対応できる。最後の記述問題と言うのは、短い文章がありその中の空欄に自分で単語を書いていくというものである。おそらく、ここで一番差がつくと思われる。問われている単語自体は難しくないものの、「どの単語がどのような場合に使われるのか」というような実践的知識がないと難しくなってしまうかもしれない。単語を覚える際は、例文と一緒に覚えるということを習慣づけておきたい。総じて標準的問題が多いものの、受験生のレベルはかなり高い。受験生の層からすると、本番では一問も落とせないような熾烈な戦いが展開されるだろう。 文学部は和文英訳か英文和訳を課すことがあるので、対策をしておくべきである。 === 国語 === 現代文2題、古文1題の構成(文学部は現代文1題、古文1題、漢文1題)。試験時間は75分。現代文、古文ともに記述問題がある。 * 現代文は分かりやすい文章から抽象度の高い文章まで様々である。全体の難易度としてはやや高め。出題は傍線部の説明問題、記述問題、内容真偽がある。説明問題は最初に自分で本文を根拠に答えを考え出してから、選択肢を吟味していくと良い。また解答の根拠が傍線部から離れている場合もあるので即答は危険である。記述問題は抜き出し問題が多い。解答の根拠を部分で見つけるのではなく、文章を一読し作者の言いたいことを加味しつつ考えること。最後の内容一致問題は本文を読みながら解くことをお勧めしたい。なお、文学部の場合は他学部よりも難易度がやや高めなので注意したい。 * 古文は単語の意味を直接聞くものや客観問題、文法問題がある。基盤がしっかりしていれば、それほど怖ろしくはないレベルだが、時代背景や平安貴族の文化などを多少勉強しておくと差をつけられるだろう。源氏物語からの出題が頻出。 * 漢文は文学部のみ出題される。難易度はセンター試験よりも低い。高得点が狙えるだろう。 === 選択科目 === 文系は日本史・世界史、数学、地理のいずれかを選択する。(学部により選択できる科目が違う。日本史と世界史は全学部で選択可。各自で大学ホームページ等で確認してもらいたい。) 理系は物理・化学・生物から1科目を選択。 '''日本史'''</br> 大問が2個あり、内容はどちらも空欄を埋める問題と下線部についての設問である。問題数が多く、難しい用語を書かせる問題や20字程度の記述問題も出題される。また、マイナーな事項のテーマ史が頻出なので、資料集にも目を通しておきたい(社会経済史では「土地制度」や「近代以降の女性運動」、文化史では「思想・宗教」「江戸時代の大衆文化」が頻出)。記述式の解答が約半数を占めるため語句を正確に覚えることが必要である。 '''世界史'''</br> 幅広い地域・時代・分野から出題される。大部分は教科書を中心とした基本的な問題だが、中には細かな知識を含む問題も見られるので、用語集・資料集も使ってより幅広い知識の形成を目指そう。年によっては、20~30字程度の記述問題も出題される。 '''数学'''</br> 大問数3問であるが、小問に分かれており、得点しやすくなっている。全体的にはやや易〜標準的な問題である。 '''地理'''</br> 観光学部のみ受験可能。基本的な問題が多いが、論述問題や描図問題が多いため日本史、世界史と同様に正確な知識が必要である。 == 共通テスト利用入試 == 共通テストの結果のみによって合否が決まる試験方式である。全学部全学科で3教科型と6教科型(ドイツ文学科のみ3科目と4科目)で実施されている。合格するためには、学部学科、科目数にもよるが、80%〜90%は必要である。3教科型は私大専願の受験生でも受験可能である。 経営・コミュニティ福祉学部は古典の試験を課さないなど、学部により入試科目が微妙に異なる。 == 全学部日程 == 立教大学では、個別学部日程のほかに全学部日程も行っている。合格難易度は学部別日程よりも若干高くなることもある。入試問題自体は個別学部日程とあまり変わらない。 === 3教科方式 === 一般的な入試方式。学部学科の併願はできない。 2017年度入試より、文・異文化コミュニケーション学部以外の文系学部は政治経済での受験が可能となった。 === グローバル方式 === 以下の出願資格を持つ者のみ出願可能。 ;出願資格 * GTEC CBT…1000点以上 * TEAP(Reading/Listening+Writing+Speaking)…226点以上 * IELTS…4.0以上 * TOEIC & TOEIC SW…790点以上 * TOEFL iBT…42点以上 * 実用英語技能検定(英検)…準1級以上 (2016年4月以降〜 2級以上) == 外部サイト == *[http://www.rikkyo.ac.jp/invitation/admissions/undergraduate/ 立教大公式サイト] [[Category:大学入試|りつきよう]] 5cqifxurvoh6a716zacv8mos18r1jri 263766 263760 2024-11-18T09:58:19Z Ayhxuknbsijceivzdjhswh 66317 263766 wikitext text/x-wiki {{wikipedia|立教大学}} *[[日本の大学受験ガイド]] > [[立教大対策]] 本項は、[[w:立教大学|立教大学]]の入学試験対策に関する事項である。 立教大学は、豊島区池袋に本部を置く私立大学。それほど規模は大きくない大学だが、知名度は高く、競争率も激しい。問題の難易度はそれほど高くないが、'''合格最低点はかなり高くなっており'''、しっかりとした実力がなければ合格は難しい。 私大の入試の特徴として、定員以上の人数の受験者に合格が与えられることが挙げられるが、立教大学もその例に洩れず、どの学部も定員よりも多い人数が合格になっている。よって、表面的な倍率(志願者数÷定員数)よりも実質倍率(受験者数÷合格数)の方が必ず低くなる。しかし、実質倍率4〜15倍(学部により異なる)は大学入試としては高い方なので、優秀な受験生でも注意が必要である。 == 個別学部日程 == 公式に合格最低点は示されていないが、池袋キャンパス就学の学部は75%前後(社会・経営・異文化コミュニケーション学部は80%弱)、新座キャンパス就学の学部は70%前後がボーダーと予測される。 === 英語 === 2024年現在では英検または共通テストの英語の成績を利用する。共通テストの成績を使う場合、リーディングとリスニングの配点比率が1:1のためリスニングの対策もしっかりすること。個別試験の英語は文学部の一部入試方式のみ課される。 ※以下のはかつての入試対策である。 長文2題、文法(正誤なども含める)・会話問題(出題無しの場合も有)合わせて2題、文章中の空所に適切な単語を入れる問題1題の5問構成。年によっては6題になることもある。長文はミッション系の学校だけあって「高度」と思われがちであるが、実際はそれほど難しいものではない(センター試験の問題よりやや難易度が高い程度である)。むしろ、「長い」というのが特徴である。1000語超えの長文2つということも多いため、試験時間75分の中でどう捌けるかが問題になる。本文を読む前に、先に設問に目を通しておき、あらかじめヒントを拾っておくと良い。設問は大きく分けて文章の内容を問う内容一致問題、文章中の語彙に下線部を引き意味を選ばせる問題、長文のタイトルを選ぶ問題がある。どのタイプの問題も標準的な難易度なので落ち着いて取り組もう。ただし、長文には十分に慣れ、ある程度の速読技術も習得する必要があるだろう。また、時間配分にも注意しよう。 次に文法・会話問題であるが、これもまた標準的難易度であり、市販の文法書などで十分に対応できる。最後の記述問題と言うのは、短い文章がありその中の空欄に自分で単語を書いていくというものである。おそらく、ここで一番差がつくと思われる。問われている単語自体は難しくないものの、「どの単語がどのような場合に使われるのか」というような実践的知識がないと難しくなってしまうかもしれない。単語を覚える際は、例文と一緒に覚えるということを習慣づけておきたい。総じて標準的問題が多いものの、受験生のレベルはかなり高い。受験生の層からすると、本番では一問も落とせないような熾烈な戦いが展開されるだろう。 文学部は和文英訳か英文和訳を課すことがあるので、対策をしておくべきである。 === 国語 === 現代文2題、古文1題の構成(文学部は現代文1題、古文1題、漢文1題)。試験時間は75分。現代文、古文ともに記述問題がある。 * 現代文は分かりやすい文章から抽象度の高い文章まで様々である。全体の難易度としてはやや高め。出題は傍線部の説明問題、記述問題、内容真偽がある。説明問題は最初に自分で本文を根拠に答えを考え出してから、選択肢を吟味していくと良い。また解答の根拠が傍線部から離れている場合もあるので即答は危険である。記述問題は抜き出し問題が多い。解答の根拠を部分で見つけるのではなく、文章を一読し作者の言いたいことを加味しつつ考えること。最後の内容一致問題は本文を読みながら解くことをお勧めしたい。なお、文学部の場合は他学部よりも難易度がやや高めなので注意したい。 * 古文は単語の意味を直接聞くものや客観問題、文法問題がある。基盤がしっかりしていれば、それほど怖ろしくはないレベルだが、時代背景や平安貴族の文化などを多少勉強しておくと差をつけられるだろう。源氏物語からの出題が頻出。 * 漢文は文学部のみ出題される。難易度はセンター試験よりも低い。高得点が狙えるだろう。 === 数学(理系) === 大問数は3問(数学科は4問)。大問1は小問集合(答えのみ記入)、大問2~4は誘導付きの問題が出題される。近年は確率は出題されてなかったが、2024年度に久々に出題された。 全体的に見て難問と言えるものは少ないものの、少しのミスが命取りとなる。 === 選択科目 === 文系は日本史・世界史、数学、地理のいずれかを選択する。(学部により選択できる科目が違う。日本史と世界史は全学部で選択可。各自で大学ホームページ等で確認してもらいたい。) 理系は物理・化学・生物から1科目選択。ただし物理学科は物理、化学科は化学必須である。 '''日本史'''</br> 大問が2個あり、内容はどちらも空欄を埋める問題と下線部についての設問である。問題数が多く、難しい用語を書かせる問題や20字程度の記述問題も出題される。また、マイナーな事項のテーマ史が頻出なので、資料集にも目を通しておきたい(社会経済史では「土地制度」や「近代以降の女性運動」、文化史では「思想・宗教」「江戸時代の大衆文化」が頻出)。記述式の解答が約半数を占めるため語句を正確に覚えることが必要である。 '''世界史'''</br> 幅広い地域・時代・分野から出題される。大部分は教科書を中心とした基本的な問題だが、中には細かな知識を含む問題も見られるので、用語集・資料集も使ってより幅広い知識の形成を目指そう。年によっては、20~30字程度の記述問題も出題される。 '''数学'''</br> 大問数3問であるが、小問に分かれており、得点しやすくなっている。全体的にはやや易〜標準的な問題である。 '''地理'''</br> 観光学部のみ受験可能。基本的な問題が多いが、論述問題や描図問題が多いため日本史、世界史と同様に正確な知識が必要である。 '''物理'''</br> 大問数は6問程度で全問解答のみを記入する。またマーク式の問題もある。基本的な問題が多いが一部独特な問題も見られるため注意。満遍なく出題され、現役生が疎かにしやすい原子も毎年のように出題されている。 == 共通テスト利用入試 == 共通テストの結果のみによって合否が決まる試験方式である。全学部全学科で3教科型と6教科型(ドイツ文学科のみ3科目と4科目)で実施されている。合格するためには、学部学科、科目数にもよるが、80%〜90%は必要である。3教科型は私大専願の受験生でも受験可能である。 経営・コミュニティ福祉学部は古典の試験を課さないなど、学部により入試科目が微妙に異なる。 == 全学部日程 == 立教大学では、個別学部日程のほかに全学部日程も行っている。合格難易度は学部別日程よりも若干高くなることもある。入試問題自体は個別学部日程とあまり変わらない。 === 3教科方式 === 一般的な入試方式。学部学科の併願はできない。 2017年度入試より、文・異文化コミュニケーション学部以外の文系学部は政治経済での受験が可能となった。 === グローバル方式 === 以下の出願資格を持つ者のみ出願可能。 ;出願資格 * GTEC CBT…1000点以上 * TEAP(Reading/Listening+Writing+Speaking)…226点以上 * IELTS…4.0以上 * TOEIC & TOEIC SW…790点以上 * TOEFL iBT…42点以上 * 実用英語技能検定(英検)…準1級以上 (2016年4月以降〜 2級以上) == 外部サイト == *[http://www.rikkyo.ac.jp/invitation/admissions/undergraduate/ 立教大公式サイト] [[Category:大学入試|りつきよう]] gthfrz86yhiwublowwpxhs12tm29l7i 高校化学 アルミニウム 0 10721 263732 263591 2024-11-18T02:28:43Z Nermer314 62933 263732 wikitext text/x-wiki {{pathnav|高等学校の学習|高等学校理科|高等学校 化学|pagename=アルミニウム|frame=1|small=1}} '''アルミニウム Al''' は13族の金属元素で、価電子を3個もち、3価の陽イオンになりやすい。 銀白色の軽い金属である。展性や延性が大きく、薄く伸ばしたものはアルミニウム箔(いわゆるアルミホイル)として一般家庭でも用いられている。また、電気伝導性も良く、熱伝導性も良い。熱伝導性が良いことから、鍋などにも用いられる。 アルミニウムの単体を空気中に放置すると、表面に緻密な酸化膜(酸化アルミニウム Al{{sub|2}}O{{sub|3}} )の被膜ができ、内部を保護する。 アルミニウムやマグネシウムを主成分とする合金である'''ジュラルミン'''は軽量かつ強度が高く、航空機に用いられている。アルミニウム自体も、アルミ缶や1円硬貨に用いられている。 == 製法 == [[File:Mineraly.sk - bauxit.jpg|200px|ボーキサイト|代替文=ボーキサイト|サムネイル]] アルミニウムの製法は、工業的には、鉱石の'''ボーキサイト'''(bauxite、主成分: 酸化アルミニウム <chem>Al2O3</chem>)を処理して酸化アルミニウム(<chem>Al2O3</chem>)にかえたあと、氷晶石(<chem>Na3AlF6</chem>、ヘキサフルオロアルミン酸ナトリウム)とともに熔融塩電解して製造される。('''エルー・ホール法''') : <chem>Al^3+ + 3e^- -> Al v</chem> アルミニウムの電解には、大量の電力が必要となる。 [[File:Cut Ruby.jpg|150px|ルビー|代替文=ルビー|サムネイル]][[File:SaphirSynthetique.jpg|150px|サファイア|代替文=サファイア|サムネイル]] 製造の過程で得られる酸化アルミニウム(Al{{sub|2}}O{{sub|3}})は水に溶けにくい白色の固体である。酸化アルミニウムは'''アルミナ'''とも呼ばれ、融点が非常に高い(アルミナの融点は2054℃)ことから耐熱材の原材料としても用いられるほどである。氷晶石は、このアルミナの融点を降下させるために加えられる。 アルミニウムの粉末は、空気中または酸素中で熱すると、激しく燃える。 * ボーキサイトから酸化アルミニウムを得る方法 (※ 教科書の範囲外。資料集(実教出版など)の範囲内。文献により、方法が若干、違う。) 濃い水酸化ナトリウム水溶液でボーキサイト中の酸化アルミニウムが溶け、ほかの不純物はあまり溶けない。まず、この水酸化ナトリウム水溶液で酸化アルミニウムを溶かして アルミン酸ナトリウム <chem>Na[Al(OH)4]</chem> を得る。 : <chem>Al2O3 + 2NaOH + 3H2O -> 2 Na[Al(OH)4]</chem> (ここまでは、どの文献でも、ほぼ同じ。) まず、ろ過をして、溶液から、不溶性の <chem>Fe2O3</chem> などの余計な不純物を取り除く。 あとは、このアルミン酸ナトリウム水溶液をうまく処理し、アルミナに変えていく方法が必要なのである。 まず、アルミン酸ナトリウム <chem>Na[Al(OH)4]</chem> 水溶液から、なんらかの方法で、加水分解を起こし、水酸化アルミニウム <chem>Al(OH)3</chem> を沈殿させる。 : <chem>Na[Al(OH)4] -> Al(OH)3 + NaOH</chem> あとは、この水酸化アルミニウムを高温で焼成すると、純度の高い酸化アルミニウムが得られる。 * テルミット法 また、アルミニウム単体の粉末と、酸化鉄 <chem>Fe2O3</chem> など他の金属酸化物の粉末を混合して、加熱すると、アルミニウムが激しく酸化され、ほかの金属酸化物が還元され、金属単体が得られる。たとえば酸化鉄(Ⅲ)とアルミニウムを混合して加熱すると、鉄が得られる。 : <chem>2Al + Fe2O3 -> Al2O3 + 2Fe v</chem> これを'''テルミット法'''といい、レールの熔接などに用いられる。 両性元素 アルミニウムは両性元素であり、酸とも塩基とも反応して水素を生じる。たとえば、塩酸と反応して水素を発生しながら塩化アルミニウムを生じる。 : <chem>2Al + 6HCl -> 2AlCl3 + 3H2 ^</chem> また、水酸化ナトリウム水溶液と反応して、水素を発生しながらテトラヒドロキソアルミン酸イオンを生じる。 : <chem>2Al + 2NaOH + 6H2O -> 2Na+ + 2[Al(OH)4]^- + 3H2 ^</chem> しかし、アルミニウムは濃硝酸に溶けない。これは、反応開始直後に金属表面に緻密な酸化被膜を形成し、反応が金属内部まで進行しなくなるためである。このように、緻密な酸化皮膜により保護されて、それ以上は反応が進行しない状態を'''不動態'''(ふどうたい)という。 '''アルマイト'''という材料は、アルミニウムの表面を人工的に酸化させることで厚い不動態の膜で保護させ、そのアルミニウムの耐久性を上げた材料であり、日本で開発された。 イオン アルミニウムイオン(<chem>Al3+</chem>)の水溶液は無色透明である。これに水酸化ナトリウム水溶液を少量加えると、水酸化アルミニウムの白色ゼリー状沈殿を生じる。 : <chem>Al3+ + 3NaOH -> 3 Na+ + Al(OH)3 v</chem> しかし、水酸化ナトリウム水溶液を過剰に加えると、沈殿は溶解して無色の水溶液となり、テトラヒドロキソアルミン酸イオンを生じる。 : <chem>Al(OH)3 + NaOH -> Na+ + [Al(OH)4]^-</chem> テトラヒドロキソアルミン酸イオン水溶液に塩酸を加えると、逆に水酸化アルミニウムの白色沈殿を生じ、過剰に加えれば塩化アルミニウムを生じる。塩化アルミニウムは潮解性のある白色の固体であるが、水に溶けやすく、電離してアルミニウムイオンを生じる。 == 水酸化アルミニウム == アルミニウムイオンを含んだ水溶液に、塩基を加えると、水酸化アルミニウム <chem>Al(OH)3</chem> の白色ゲル状の沈殿が生じる。 水酸化アルミニウムを熱すると、酸化アルミニウム <chem>Al2O3</chem> が生じる。 水酸化アルミニウム <chem>Al(OH)3</chem> は酸とも塩基とも反応して溶けることのできる、両性水酸化物である。 : <chem>Al(OH)3 + 3HCl -> AlCl3 + 3H2O</chem> : <chem>Al(OH)3 + NaOH -> Na[Al(OH)4]</chem> == 酸化アルミニウム == 酸化アルミニウム <chem>Al2O3</chem> は、'''アルミナ'''(alumina)とも呼ばれ、白色の粉末で、水に溶けない。また、融点が高い(融点:2054℃)。 酸化アルミニウム <chem>Al2O3</chem> は、酸にも強塩基にも溶ける両性酸化物であるが、アンモニア水には溶けない。 : <chem>Al2O3 + 6HCl -> 2AlCl3 + 3H2O</chem> : <chem>Al2O3 + 2NaOH + 3 H2O -> 2Na[Al(OH)4]</chem> また、たとえば宝石のルビーやサファイアは、酸化アルミニウムが主成分の結晶である。酸化アルミニウムの結晶のうち、ごく微量のクロムやチタンなどの金属が混入したものが、赤いルビーや青いサファイアであり、ともに、かなり硬い。また、酸にも塩基にも、ルビーやサファイアは溶けない。 なお、ルビーにはクロム Cr が、サファイアには鉄 Fe やチタン Ti が含まれている。 {{コラム|人工宝石| :※ 『科学と人間生活』(啓林館など)に記述がある。 ルビーやサファイアなどは組成がわかっているので、人工的に作ることもできる。 材料であるアルミナやクロムまたは鉄などに高温や高圧などを加えて熱することで、人工的にルビーやサファイアなどを作ることができる。 このように、人工的につくった宝石のことを人工宝石といい、さまざまな分野に応用されている。 また、アルミナ化合物ではないが、ダイヤモンドや水晶などアルミナ以外の宝石でも、人工的につくることができる。 人工ダイヤや人工水晶も、人工宝石に含める。 なお、人工ダイヤモンドは、その硬さを活用して、工場などの大型の回転カッターなどの切れ味を増すための材料などとして、刃先に人工ダイヤのある刃物が応用されている(いわゆるダイヤモンドカッター)。 }} == ミョウバン == [[File:Alun.jpg|200px|ミョウバンの結晶|代替文=ミョウバンの結晶|サムネイル]] 硫酸カリウム水溶液と硫酸アルミニウム水溶液とを混合して濃縮して得られる結晶は、硫酸カリウムアルミニウム十二水和物 AlK(SO{{sub|4}}){{sub|2}}・12H{{sub|2}}O の結晶であり、この硫酸カリウムアルミニウム十二水和物を'''ミョウバン'''(明礬)という。 ミョウバンの結晶は無色透明で正八面体形をしている。 ミョウバンを水に溶かすと、<chem>Al^3+</chem> 、<chem>K^+</chem> 、<chem>SO4^2-</chem> の各イオンに電離する。 <chem>AlK(SO4)2*12H2O -> {Al^3+} + {K^+} + 2 {SO4^{2-}} + 12 H2O</chem> ミョウバンのように、2種類以上の塩が結合して物質を'''複塩'''(ふくえん、double salt)という。 ミョウバンを焼くと、無水物である焼きミョウバンが得られる。ミョウバンは温度による溶解度の変化が激しく、低温の水には少量しか溶けないが、温度を上げるとよく溶けるようになる。 == 補:両性金属の反応モデル == [[高校化学 アルカリ金属#金属と水の反応モデル]]において、水酸化物皮膜を用いて金属と水の反応を説明した。 ここでは、同様にして両性金属元素の反応モデルを考える。 水中にある金属Mは水と反応して表面に水酸化物M(OH){{sub|x}}の皮膜を作る。 ここで、酸HXを加えると水酸化物皮膜と反応して塩が生成される。塩は完全に電離するので金属の表面が露出し、水酸化物皮膜が生成される。また水酸化物が酸と反応して金属の表面が露出し・・・と反応が進行し、最終的に全て塩となって水に溶ける。 また、塩基YOHを加えると、水酸化物イオンと水酸化物が反応して錯イオンを形成する。錯イオンは水に可溶なので金属の表面が露出し(以下略)と反応が進行し、最終的に全て錯イオンとなって水に溶ける。 [[カテゴリ:高等学校化学|あるみにうむ]] 6usq3o1jpiiex2z1om9n1uu7lp620yx ガリア戦記 第6巻 0 10983 263721 263718 2024-11-17T11:59:54Z Linguae 449 /* 10節 */ 修整 263721 wikitext text/x-wiki [[Category:ガリア戦記|6]] [[ガリア戦記]]>&nbsp;'''第6巻'''&nbsp;>[[ガリア戦記 第6巻/注解|注解]] <div style="text-align:center"> <span style="font-size:20px; font-weight:bold; font-variant-caps: petite-caps; color:white; background: rgb(47,94,255);background: linear-gradient(180deg, rgba(47,94,255,1) 0%, rgba(24,56,255,1) 50%, rgba(0,8,255,1) 100%);">&nbsp;C&nbsp;IVLII&nbsp;CAESARIS&nbsp;COMMENTARIORVM&nbsp;BELLI&nbsp;GALLICI&nbsp;</span> <span style="font-size:40px; font-weight:bold; color:white; background: rgb(47,94,255);background: linear-gradient(180deg, rgba(47,94,255,1) 0%, rgba(24,56,255,1) 50%, rgba(0,8,255,1) 100%);">&nbsp;LIBER SEXTVS&nbsp;</span> </div> [[画像:Gaule_-53.png|thumb|right|150px|ガリア戦記 第6巻の情勢図(BC53年)。<br>黄色の領域がローマ領。桃色が同盟部族領。]] {| id="toc" style="align:left;clear:all;" align="left" cellpadding="5" ! style="background:#ccccff; text-align:left;" colspan="2" | ガリア戦記 第6巻 目次 |- | style="text-align:right; font-size: 0.86em;"| '''[[#ガッリア北部の平定|ガッリア北部の平定]]''':<br /> '''[[#第二次ゲルマーニア遠征|第二次ゲルマーニア遠征]]''':<br /> '''[[#ガッリア人の社会と風習について|ガッリア人の社会と風習について]]''':<br /> '''[[#ゲルマーニアの風習と自然について|ゲルマーニアの風習と自然について]]''':<br /> '''[[#対エブロネス族追討戦(1)|対エブロネス族追討戦(1)]]''':<br /> '''[[#スガンブリー族のアドゥアトゥカ攻略戦|スガンブリー族のアドゥアトゥカ攻略戦]]''':<br /> '''[[#対エブロネス族追討戦(2)|対エブロネス族追討戦(2)]]''':<br /> <br /> <br /> <br /> <br /> <br /> | style="text-align:left; font-size: 0.86em;"| [[#1節|01節]] | [[#2節|02節]] | [[#3節|03節]] | [[#4節|04節]] | [[#5節|05節]] | [[#6節|06節]] | [[#7節|07節]] | [[#8節|08節]] <br /> [[#9節|09節]] | [[#10節|10節]] <br /> [[#11節|11節]] | [[#12節|12節]] | [[#13節|13節]] | [[#14節|14節]] | [[#15節|15節]] | [[#16節|16節]] | [[#17節|17節]] | [[#18節|18節]] | [[#19節|19節]] | [[#20節|20節]] <br /> [[#21節|21節]] | [[#22節|22節]] | [[#23節|23節]] | [[#24節|24節]] | [[#25節|25節]] | [[#26節|26節]] | [[#27節|27節]] | [[#28節|28節]] <br /> [[#29節|29節]] | [[#30節|30節]] | [[#31節|31節]] | [[#32節|32節]] | [[#33節|33節]] | [[#34節|34節]] <br /> [[#35節|35節]] | [[#36節|36節]] | [[#37節|37節]] | [[#38節|38節]] | [[#39節|39節]] | [[#40節|40節]] | [[#41節|41節]] | [[#42節|42節]] <br/> [[#43節|43節]] | [[#44節|44節]] <br/> &nbsp;&nbsp;1節 [[#コラム「カエサルの軍団」|コラム「カエサルの軍団」]]<br> 10節 [[#コラム「スエービー族とカッティー族・ケールスキー族・ウビイー族について」|コラム「スエービー族とカッティー族・ケールスキー族・ウビイー族について」]]<br>10節 [[#コラム「ガッリア・ゲルマーニアの地誌・民族誌について」|コラム「ガッリア・ゲルマーニアの地誌・民族誌について」]]<br /> [[#脚注|脚注]]<br /> [[#参考リンク|参考リンク]]<br /> |} <br style="clear:both;" /> __notoc__ <div style="background-color:#dfffdf;"> ==<span style="color:#009900;">はじめに</span>== :<div style="color:#009900;width:85%;">カエサルは、第1巻の年([[w:紀元前58年|紀元前58年]])から<ruby><rb>[[w:プロコンスル|前執政官]]</rb><rp>(</rp><rt>プロコンスル</rt><rp>)</rp></ruby>として属州総督に赴任した。が、これは[[w:ガリア・キサルピナ|ガッリア・キサルピーナ]]、[[w:イリュリクム|イッリュリクム]]および[[w:ガリア・ナルボネンシス|ガッリア・トラーンサルピーナ]]の三属州の統治、および4個軍団を5年間にもわたって任されるというローマ史上前代未聞のものであった。これはカエサルが[[w:マルクス・リキニウス・クラッスス|クラッスス]]、[[w:グナエウス・ポンペイウス|ポンペイウス]]と非公式な盟約を結んだ[[w:三頭政治#第一回三頭政治|三頭政治]]の成果であった。カエサルには属州の行政に従事する気持ちははじめからなく、任期のほとんどを夏季は[[w:ガリア戦争|ガッリア侵攻]]に、冬季は首都ローマへの政界工作に費やした。[[ガリア戦記_第3巻#はじめに|第3巻]]の年([[w:紀元前56年|紀元前56年]])に3人は[[w:ルッカ|ルカ]]([[w:la:Luca|Luca]])の会談を行い、カエサルはクラッススとポンペイウスが翌年に執政官になること、カエサルの総督の任期をさらに5年間延長されることを求めた。会談の結果、任期が大幅に延長されることになったカエサルは、もはや軍事的征服の野望を隠そうとせず、ガッリアに止まらず、[[w:ゲルマニア|ゲルマーニア]]や[[w:ブリタンニア|ブリタンニア]]の征服へと向かっていく。一方、第4巻の年([[w:紀元前55年|前55年]])に再び執政官になった二人は、[[w:パルティア|パルティア]]を攻略するためにクラッススが[[w:シリア属州|シュリア]]総督になること、ポンペイウスがカエサルと同様に[[w:ヒスパニア|両ヒスパーニア]]と[[w:アフリカ属州|アフリカ]]の三属州の総督になって4個軍団を任されることを決める。</div> <div style="text-align:center"> {| |- |[[画像:First Triumvirate of Caesar, Crassius and Pompey.jpg|thumb|right|500px|後に[[w:三頭政治#第一回三頭政治|三頭政治]](<span style="font-family:Times New Roman;">[[w:la:Triumviratus|Triumviratus]]</span>)と呼ばれることになる非公式な盟約を結んでいた、左から[[w:ガイウス・ユリウス・カエサル|カエサル]]、[[w:マルクス・リキニウス・クラッスス|クラッスス]]、[[w:グナエウス・ポンペイウス|ポンペイウス]]。<br>3人の同盟はついに破綻の時を迎える。]] |} </div> :<div style="color:#009900;width:85%;">[[w:ガリア戦記 第5巻|第5巻]]の年([[w:紀元前54年|前54年]])、カエサルは満を持して二回目の[[w:ローマによるブリタンニア侵攻 (紀元前55年-紀元前54年)|ブリタンニア侵攻]]を敢行するが、大した戦果は得られず、背後のガッリア情勢を気にしながら帰還する。ついに[[w:アンビオリクス|アンビオリークス]]率いる[[w:エブロネス族|エブローネース族]]、ついで[[w:ネルウィイ族|ネルウィイー族]]が反乱を起こし、カエサルは何とか動乱を鎮めるが、ガッリア諸部族の動きは不穏であり、カエサルは諸軍団とともに越冬することを決める。</div> :<div style="color:#009900;width:85%;">カエサルがブリタンニア遠征で不在の間に、ポンペイウスに嫁していたカエサルの一人娘[[w:ユリア (ガイウス・ユリウス・カエサルの娘)|ユーリア]]が[[w:産褥|産褥]]で命を落とす。一方、クラッススは属州[[w:シリア属州|シュリア]]に向かうが、これはクラッススの命運とともに三頭政治の瓦解、カエサルとポンペイウスの関係悪化を招来することになる。</div> :<div style="color:#009900;width:85%;">本巻の年([[w:紀元前53年|前53年]])、カエサルは[[w:エブロネス族|エブローネース族]]追討戦に向かうが、これは大きな嵐の前の出来事に過ぎない。</div> </div> <!-- **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ==ガッリア北部の平定== ===1節=== *<span style="background-color:#ffd;">[[/注解/1節]] {{進捗|00%|2024-09-18}}</span> ;カエサルがポンペイウスの助けにより新兵を徴募する *<!--❶-->Multis de causis Caesar maiorem Galliae [[wikt:en:motus#Noun_2|motum]] [[wikt:en:exspectans|exspectans]] **多くの理由から、カエサルは、ガッリアのより大きな動乱を予期しており、 *per [[wikt:en:Marcus#Latin|Marcum]] [[wikt:en:Silanus#Latin|Silanum]], [[wikt:en:Gaius#Latin|Gaium]] [[wikt:en:Antistius#Latin|Antistium]] Reginum, [[wikt:en:Titus#Latin|Titum]] [[wikt:en:Sextius#Latin|Sextium]], legatos, **<ruby><rb>[[w:レガトゥス|総督副官]]</rb><rp>(</rp><rt>レガトゥス</rt><rp>)</rp></ruby>の[[w:マルクス・ユニウス・シラヌス (紀元前25年の執政官)|マールクス・スィーラーヌス]]、ガーイウス・アンティスティウス・レーギーヌス、ティトゥス・セクスティウスを介して **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[w:en:Marcus Junius Silanus (consul 25 BC)|Mārcus Iūnius Sīlānus]] はこの年([[w:紀元前53年|前53年]])からカエサルの副官、[[w:紀元前25年|前25年]]に執政官。<br>    ''[[w:fr:Caius Antistius Reginus|Gaius Antistius Reginus]]'' は副官として[[ガリア戦記_第7巻#83節|第7巻83節]]と[[ガリア戦記_第7巻#90節|90節]]でも後出。<br>    [[w:en:Titus Sextius|Titus Sextius]] はこの年からカエサルの副官、[[ガリア戦記_第7巻#83節|第7巻83節]]でも後出、<br>     [[w:三頭政治#第二回三頭政治|第二回三頭政治]]では[[w:アフリカ属州|アフリカ属州]]の総督を務め、[[w:マルクス・アエミリウス・レピドゥス|レピドゥス]]に引き継ぐ。)</span> *[[wikt:en:dilectus#Noun|dilectum]] habere [[wikt:en:instituo#Latin|instituit]]; **<small>(兵士の)</small>徴募を行なうことを決める。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[wikt:en:dilectus#Noun|dīlēctus]] = [[wikt:en:delectus#Noun_2|dēlēctus]]「選択、徴募」)</span> :  *<!--❷-->simul ab [[wikt:en:Gnaeus#Latin|Gnaeo]] [[wikt:en:Pompeius#Proper_noun|Pompeio]] [[wikt:en:proconsul#Latin|proconsule]] [[wikt:en:peto#Latin|petit]], **同時に、<ruby><rb>[[w:プロコンスル|前執政官]]</rb><rp>(</rp><rt>プロコンスル</rt><rp>)</rp></ruby>の[[w:グナエウス・ポンペイウス|グナエウス・ポンペイウス]]に<small>(以下のことを)</small>求める。 *[[wikt:en:quoniam#Latin|quoniam]] ipse ad <u>urbem</u> cum imperio rei publicae causa [[wikt:en:remaneo#Latin|remaneret]], **<small>(ポンペイウス)</small>自身は<u>首都</u><small>〔[[w:ローマ|ローマ市]]〕</small>の辺りに、<ruby><rb>[[w:インペリウム|軍隊司令権]]</rb><rp>(</rp><rt>インペリウム</rt><rp>)</rp></ruby>を伴って、国務のために留まっていたので、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[wikt:en:urbs#Latin|urbs (urbem)]] は普通名詞として「都市・街」を意味するが、特に首都'''[[w:ローマ|ローマ市]]'''を指す。)</span> **:<span style="color:#009900;">(訳注:ポンペイウスは、第4巻の年([[w:紀元前55年|前55年]])に[[w:マルクス・リキニウス・クラッスス|クラッスス]]とともに[[w:執政官|執政官]]を務め、<br>    第5巻の年(昨年=[[w:紀元前54年|前54年]])には[[w:ヒスパニア|両ヒスパーニア]]と[[w:アフリカ属州|アフリカ]]の属州総督となったが、<br>    首都ローマの政局が気がかりであったため、任地には副官を派遣して、<br>    自らはローマ郊外に滞在していた。ただ彼は属州総督であったため、<br>    [[w:ポメリウム|ポメリウム]]と呼ばれるローマ市中心部に立ち入ることは禁じられていた。)</span> *quos ex [[wikt:en:cisalpinus#Latin|Cisalpina]] Gallia <u>consulis</u> [[wikt:en:sacramentum#Latin|sacramento]] [[wikt:en:rogo#Latin|rogavisset]], **[[w:ガリア・キサルピナ|ガッリア・キサルピーナ]]の内から、<ruby><rb>[[w:執政官|執政官]]</rb><rp>(</rp><rt>コンスル</rt><rp>)</rp></ruby>のための宣誓を求めていた者たちに、 **:<span style="color:#009900;">(訳注:ポンペイウスは執政官のときに元老院の許可を得て、<br>    カエサルの属州で、自らの属州に派遣するための4個軍団の徴募を行った。<br>    徴集された新兵たちは執政官に宣誓したようである。)</span> **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、主要写本&omega; では [[wikt:en:consulis#Noun|consulis]]「執政官の」だが、<br>         [[ガリア戦記/注解編/写本と校訂版#Ciacconius|Ciacconius]]は [[wikt:en:consul#Latin|consul]]「執政官が」と修正提案している。)</span> *ad signa [[wikt:en:convenio#Latin|convenire]] et ad se [[wikt:en:proficiscor#Latin|proficisci]] [[wikt:en:iubeo#Latin|iuberet]], **軍旗のもとに集まって、自分<small>〔カエサル〕</small>のもとへ進発することを命じるようにと。 **:<span style="color:#009900;">(訳注:カエサルは、ポンペイウスに軍団兵の融通を求めたわけだ。<br>    ポンペイウスが執政官のときに徴募していたうちの1個軍団がカエサルに貸し出された。<br>    ところがその後、<u>第8巻54節の記述</u>によれば <ref>ラテン語文は、[[s:la:Commentarii_de_bello_Gallico/Liber_VIII#54]] などを参照。</ref><ref>英訳は、[[s:en:Commentaries_on_the_Gallic_War/Book_8#54]] などを参照。</ref>、[[w:マルクス・リキニウス・クラッスス|クラッスス]]の死後に、[[w:元老院|元老院]]は、<br>    対[[w:パルティア|パルティア]]戦争のために、カエサルとポンペイウスがそれぞれ1個軍団を供出することを可決したが、<br>    ポンペイウスはカエサルに1個軍団の返還を求めたので、<br>    カエサルは計2個軍団の引き渡しを求められることになる。<br>    このことは、[[内乱記_第1巻#2節|『内乱記』第1巻2節]]以降でも言及される。)</span> :  *<!--❸-->magni [[wikt:en:intersum#Latin|interesse]] etiam in reliquum tempus ad [[wikt:en:opinio#Latin|opinionem]] Galliae [[wikt:en:existimans#Latin|existimans]] **ガッリアの世論に対して、これから後の時期にさえも、(カエサルが)大いに重要であると考えていたのは、 *tantas videri Italiae [[wikt:en:facultas#Latin|facultates]] **(以下の程度に)イタリアの(動員)能力が豊富であると見えることである。 **:<span style="color:#009900;">(訳注:Italiaという語は多義的でさまざまに解釈できるが、<br>    本書ではガッリア・キサルピーナを指すことが多い。)</span> *ut, si [[wikt:en:aliquid#Etymology_2|quid]] esset in bello [[wikt:en:detrimentum#Latin|detrimenti]] acceptum, **もし、戦争において何がしかの(兵員の)損害を蒙ったとしても、 *non modo id [[wikt:en:brevis#Latin|brevi]] tempore [[wikt:en:sarcio#Latin|sarciri]], **それが短期間で修復(できる)だけでなく、 *sed etiam [[wikt:en:maior#Adjective_2|maioribus]] [[wikt:en:augeo#Latin|augeri]] copiis posset. **より多く軍勢で増されることが可能だ<br>(とガッリアの世論に思われることが重要であるとカエサルは考えたのである)。 :  *<!--❹-->Quod cum [[wikt:en:Pompeius#Proper_noun|Pompeius]] et rei publicae et amicitiae [[wikt:en:tribuo#Latin|tribuisset]], **そのことを、ポンペイウスは公儀<small>〔ローマ国家〕</small>のためにも(三頭政治の)盟約のためにも認めたので、 *celeriter [[wikt:en:confectus#Latin|confecto]] per suos [[wikt:en:dilectus#Noun|dilectu]] **(カエサルの)配下の者たちを介して速やかに徴募が成し遂げられて *tribus ante [[wikt:en:exactus#Latin|exactam]] [[wikt:en:hiems#Latin|hiemem]] et [[wikt:en:constitutus#Participle|constitutis]] et [[wikt:en:adductus#Latin|adductis]] legionibus **冬が過ぎ去る前に、3個[[w:ローマ軍団|軍団]]が組織されて<small>(カエサルのもとへ)</small>もたらされ、 *[[wikt:en:duplicatus#Latin|duplicato]]<nowiki>que</nowiki> earum [[wikt:en:cohors#Latin|cohortium]] numero, quas cum [[wikt:en:Quintus#Latin|Quinto]] [[wikt:en:Titurius#Latin|Titurio]] [[wikt:en:amitto#Latin|amiserat]], **それらの<ruby><rb>[[w:コホルス|歩兵大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby>の数は、[[w:クィントゥス・ティトゥリウス・サビヌス|クィーントゥス・ティトゥーリウス(・サビーヌス)]]とともに失っていたものの倍にされた。 **:<span style="color:#009900;">(訳注:前巻でサビーヌスとコッタは1個軍団と5個[[w:コホルス|歩兵大隊]](=15個歩兵大隊)を失ったが、<br>    代わりに3個軍団(=30個歩兵大隊)を得たということ。)</span> *et [[wikt:en:celeritas#Latin|celeritate]] et copiis [[wikt:en:doceo#Latin|docuit]], **<small>(徴兵の)</small>迅速さと軍勢<small>(の多さ)</small>において<small>(ガッリア人たちに)</small>示したのは、 *quid populi Romani [[wikt:en:disciplina#Latin|disciplina]] atque [[wikt:en:ops#Noun_4|opes]] possent. **ローマ国民の規律と能力がいかに有力であるかということである。 {| class="wikitable" |- | style="vertical-align:top; text-align:left;" |[[画像:Hw-pompey.jpg|thumb|right|250px|[[w:グナエウス・ポンペイウス|グナエウス・ポンペイウス]]の胸像。カエサルおよび[[w:マルクス・リキニウス・クラッスス|マルクス・クラッスス]]とともに[[w:三頭政治|三頭政治]]を行ない、[[w:共和政ローマ|共和政末期のローマ]]を支配した。この巻の年にクラッススが戦死し、ポンペイウスに嫁いでいたカエサルの娘[[w:ユリア (ガイウス・ユリウス・カエサルの娘)|ユーリア]]が前年に病没、三頭政治は瓦解して、やがて[[w:ローマ内戦 (紀元前49年-紀元前45年)|内戦]]へ向かう。]] | style="vertical-align:top; text-align:left;" |[[画像:Theatre of Pompey 3D cut out.png|thumb|left|400px|'''[[w:ポンペイウス劇場|ポンペイウス劇場]]'''の復元図。[[w:グナエウス・ポンペイウス|ポンペイウス]]の名を冠したこの劇場は、彼が執政官であった[[w:紀元前55年|紀元前55年]]頃に竣工し、当時最大の劇場であった。<br> 伝記作家[[w:プルタルコス|プルータルコス]]は以下のように伝えている<ref>[[s:en:Plutarch%27s_Lives_(Clough)/Life_of_Pompey]] より</ref>:「クラッススは執政官の任期が切れるとすぐに属州へと出発したが、ポンペイウスはローマで劇場の開館式や奉献式に出席し、その式にはあらゆる競技・ショー・運動・体操・音楽などで人々を楽しませた。野獣の狩猟や餌付け、野獣との闘いもあり、500頭のライオンが殺された。しかし何よりも、象の闘いは、恐怖と驚きに満ちた見世物であった」と。<br><br> カエサルの最期の場所でもあり、血みどろのカエサルはポンペイウスの胸像の前で絶命したとされている。]] |} <!-- <span style="color:#009900;"></span> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> <div style="background-color:#dfffdf;"> ===<span style="color:#009900;">コラム「カエサルの軍団」</span>=== :<div style="color:#009900;width:75%;">カエサルは第1巻の年([[w:紀元前58年|紀元前58年]])に三属州の総督に任官するとともに4個軍団(VI・VII・[[w:en:Legio VIII Augusta|VIII]]・[[w:en:Legio IX Hispana|IX]])を任された。[[w:ヘルウェティイ族|ヘルウェーティイー族]]([[w:la:Helvetii|Helvetii]])と対峙するうちに、元老院に諮らずに独断で2個軍団([[w:en:Legio X Equestris|X]]・[[w:en:Legio XI Claudia|XI]])を徴募する(1巻10節)。<br> 第2巻の年([[w:紀元前57年|紀元前57年]])に3個軍団([[w:en:Legio XII Fulminata|XII]]・[[w:en:Legio XIII Gemina|XIII]]・[[w:en:Legio XIV Gemina|XIV]])を徴募して、計9個軍団。<br><br> [[ガリア戦記_第5巻#24節|『第5巻』24節]]の時点で、カエサルは8個軍団と5個[[w:コホルス|歩兵大隊]]を保持していると記されている。最古参の第6軍団が半減していると考えると、[[w:アドゥアトゥカの戦い|アドゥアトゥカの戦い]]で[[w:アンビオリクス|アンビオリークス]]によって、[[w:クィントゥス・ティトゥリウス・サビヌス|サビーヌス]]やコッタらとともに滅ぼされたのは、第14軍団([[w:en:Legio XIV Gemina|XIV]])と古い第6軍団(VI)の生き残りの5個[[w:コホルス|歩兵大隊]]と考えることができる。<br><br> 本巻の年([[w:紀元前53年|紀元前53年]])では、ポンペイウスの第1軍団がカエサルに譲られ、後にカエサルの軍団の番号系列に合わせて第6軍団(VI)と改称されたようだ。「第14軍団」は全滅させられたので通常は欠番にするところだが、カエサルはあえて再建して第14軍団と第15軍団が徴募され、これら3個軍団を加えると、カエサルが保持するのは計10個軍団となる。<br> もっとも本巻ではカエサルは明瞭な記述をしておらず、上述のように後に2個軍団を引き渡すことになるためか、伝記作家[[w:プルタルコス|プルータルコス]]は、ポンペイウスがカエサルに2個軍団を貸し出した、と説明している。 </div> </div> ===2節=== *<span style="background-color:#ffd;">[[/注解/2節]] {{進捗|00%|2024-09-29}}</span> ;ガッリア北部の不穏な情勢、トレーウェリー族がライン川東岸のゲルマーニア人を勧誘 *<!--❶-->[[wikt:en:interfectus#Latin|Interfecto]] [[wikt:en:Indutiomarus#Latin|Indutiomaro]], ut [[wikt:en:doceo#Latin|docuimus]], **<small>([[ガリア戦記 第5巻#58節|第5巻58節]]で)</small>述べたように、インドゥーティオマールスが殺害されると、 *ad eius propinquos a [[wikt:en:Treveri#Latin|Treveris]] imperium [[wikt:en:defero#Latin|defertur]]. **トレーウェリー族の者たちにより彼の縁者たちへ支配権がもたらされる。 *Illi finitimos [[wikt:en:Germanus#Noun|Germanos]] [[wikt:en:sollicito#Latin|sollicitare]] et [[wikt:en:pecunia#Latin|pecuniam]] [[wikt:en:polliceor#Latin|polliceri]] non [[wikt:en:desisto#Latin|desistunt]]. **彼らは隣接する[[w:ゲルマニア|ゲルマーニア]]人たちをそそのかすこと、および金銭を約束することをやめない。 *Cum ab proximis [[wikt:en:impetro#Latin|impetrare]] non possent, [[wikt:en:ulterior#Latin|ulteriores]] [[wikt:en:tempto#Latin|temptant]]. **たとえ隣人たちによって(盟約を)成し遂げることができなくても、より向こう側の者たちに試みる。 :  *<!--❷-->[[wikt:en:inventus#Latin|Inventis]] [[wikt:en:nonnullus#Latin|non nullis]] civitatibus **少なからぬ部族国家を見出して *[[wikt:en:ius_iurandum#Latin|iure iurando]] inter se [[wikt:en:confirmo#Latin|confirmant]] **互いに誓約し合って(支持を)固め、 *obsidibusque de pecunia [[wikt:en:caveo#Latin|cavent]]; **金銭(の保証)のために人質たちを提供する。 *[[wikt:en:Ambiorix#Latin|Ambiorigem]] sibi [[wikt:en:societas#Latin|societate]] et [[wikt:en:foedus#Latin|foedere]] [[wikt:en:adiungo#Latin|adiungunt]]. **[[w:アンビオリクス|アンビオリークス]]を自分たちにとっての連合や同盟に加盟させる。 :  *<!--❸-->Quibus rebus [[wikt:en:cognitus#Participle|cognitis]] Caesar, **それらの事情を知るや、カエサルは、 *cum undique bellum [[wikt:en:paro#Latin|parari]] videret, **至る所で戦争が準備されていることを見ていたので、 *[[wikt:en:Nervii#Latin|Nervios]], [[wikt:en:Aduatuci#Latin|Atuatucos]] ac [[wikt:en:Menapii#Latin|Menapios]] [[wikt:en:adiunctus#Participle|adiunctis]] **(すなわち)[[w:ネルウィイ族|ネルウィイー族]]、アトゥアトゥキー族とメナピイー族を加盟させたうえに *<u>Cisrhenanis</u> omnibus <u>[[wikt:en:Germanus#Noun|Germanis]]</u> esse in armis, **レーヌス<small>〔[[w:ライン川|ライン川]]〕</small>のこちら側のすべてのゲルマーニア人たちが武装していて、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:''[[w:en:Germani cisrhenani|Germani Cisrhenani]]''「レーヌスのこちら側のゲルマーニア人」(西岸の諸部族) は西岸部族の総称。<br>    ''Germani Transrhenani'' 「レーヌスの向こう側のゲルマーニア人」(東岸の諸部族) の対義語で、<br>     西岸の諸部族が東岸の諸部族を招き寄せているというのが『ガリア戦記』の主張である。)</span> *[[wikt:en:Senones#Latin|Senones]] ad [[wikt:en:imperatum#Latin|imperatum]] non venire **セノネース族は<small>(カエサルから)</small>命令されたことに従わずに *et cum [[wikt:en:Carnutes#Latin|Carnutibus]] finitimisque civitatibus consilia [[wikt:en:communico#Latin|communicare]], **カルヌーテース族および隣接する諸部族とともに謀計を共有しており、 *a [[wikt:en:Treveri#Latin|Treveris]] [[wikt:en:Germanus#Noun|Germanos]] crebris [[wikt:en:legatio#Latin|legationibus]] [[wikt:en:sollicito#Latin|sollicitari]], **ゲルマーニア人たちがたびたびトレーウェリー族の使節団によってそそのかされていたので、 *[[wikt:en:mature#Adverb|maturius]] sibi de bello [[wikt:en:cogitandus#Latin|cogitandum]] [[wikt:en:puto#Latin|putavit]]. **<small>(カエサルは)</small>自分にとって<small>(例年)</small>より早めに戦争を計画するべきだと見なした。 <!-- <span style="color:#009900;"></span> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ===3節=== *<span style="background-color:#ffd;">[[/注解/3節]] {{進捗|00%|2024-10-06}}</span> ;カエサルがネルウィイー族を降し、ガッリアの領袖たちの会合を召集する *<!--❶-->Itaque [[wikt:en:nondum#Latin|nondum]] [[wikt:en:hiems#Latin|hieme]] [[wikt:en:confectus#Latin|confecta]] **<small>(カエサルは)</small>こうして、まだ冬が終わらないうちに、 *proximis quattuor [[wikt:en:coactus#Latin|coactis]] legionibus **近隣の4個[[w:ローマ軍団|軍団]]を集めて、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[ガリア戦記_第5巻#52節|第5巻52節]]で言及されたように、カエサルは、本営を置いていた<br>    サマロブリーウァ(現在の[[w:アミアン|アミアン]])周辺の冬営に3個軍団、<br>    およびファビウスの軍団を配置していたと思われる。)</span> *[[wikt:en:de_improviso#Latin|de improviso]] in fines [[wikt:en:Nervii#Latin|Nerviorum]] [[wikt:en:contendo#Latin|contendit]] **不意に[[w:ネルウィイ族|ネルウィイー族]]の領土に急いだ。 :  *<!--❷-->et, [[wikt:en:priusquam#Latin|prius quam]] illi aut [[wikt:en:convenio#Latin|convenire]] aut [[wikt:en:profugio#Latin|profugere]] possent, **そして、彼ら<small>(の軍勢)</small>は、集結したり、あるいは逃亡したりできるより前に、 *magno [[wikt:en:pecus#Latin|pecoris]] atque hominum numero [[wikt:en:captus#Latin|capto]] **家畜たちおよび人間たちの多数を捕らえて、 *atque ea [[wikt:en:praeda#Latin|praeda]] militibus [[wikt:en:concessus#Participle|concessa]] **それらの戦利品を兵士たちに譲り、 *[[wikt:en:vastatus#Latin|vastatis]]<nowiki>que</nowiki> agris **耕地を荒らして、 *in [[wikt:en:deditio#Latin|deditionem]] venire atque obsides sibi dare [[wikt:en:cogo#Latin|coegit]]. **<small>(ネルウィイー族に、ローマ勢へ)</small>降伏すること、人質たちを自分<small>〔カエサル〕</small>に供出することを強いた。 :  *<!--❸-->Eo celeriter [[wikt:en:confectus#Latin|confecto]] [[wikt:en:negotium#Latin|negotio]] **その戦役は速やかに成し遂げられたので、 *rursus in [[wikt:en:hibernum#Latin|hiberna]] legiones [[wikt:en:reduco#Latin|reduxit]]. **再び諸軍団を冬営に連れ戻した。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:本営を置いていたサマロブリーウァ周辺の冬営。)</span> :  *'''ガッリアの領袖たちの会合''' *<!--❹-->[[wikt:en:concilium#Latin|Concilio]] Galliae primo [[wikt:en:ver#Latin|vere]], ut [[wikt:en:instituo#Latin|instituerat]], [[wikt:en:indictus#Participle|indicto]], **ガッリアの<small>(領袖たちの)</small>会合を、定めていたように、春の初めに通告すると、 **:<span style="color:#009900;">(訳注:会合の集合場所は、当初は本営のあるサマロブリーウァだったであろう。)</span> *cum reliqui praeter [[wikt:en:Senones#Latin|Senones]], [[wikt:en:Carnutes#Latin|Carnutes]] [[wikt:en:Treveri#Latin|Treveros]]<nowiki>que</nowiki> venissent, **[[w:セノネス族|セノネース族]]、カルヌーテース族とトレーウェリー族を除いて、ほかの者たちは(会合に)現われていたので、 **:<span style="color:#009900;">(訳注:ガッリア北部では、このほかエブローネース族とメナピイー族が参加していないはずである。)</span> *initium belli ac [[wikt:en:defectio#Latin|defectionis]] hoc esse [[wikt:en:arbitratus#Latin|arbitratus]], **このこと<span style="color:#009900;">〔3部族の不参加〕</span>は戦争と背反の始まりであると思われて、 *ut omnia [[wikt:en:postpono#Latin|postponere]] videretur, **<small>(他の)</small>すべて<small>(の事柄)</small>を後回しにすることと見なされるように、 *[[wikt:en:concilium#Latin|concilium]] [[wikt:en:Lutetia#Latin|Lutetiam]] [[wikt:en:Parisii#Latin|Parisiorum]] [[wikt:en:transfero#Latin|transfert]]. **会合を[[w:パリシイ族|パリースィイー族]]の(城塞都市である)[[w:ルテティア|ルーテーティア]]に移す。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:ルーテーティア Lutetia は、写本によってはルーテーキア Lutecia とも表記されている。<br>    ラテン語では Lutetia Parisiorum「パリースィイー族の泥土」と呼ばれ、現在の[[w:パリ|パリ市]]である。<br>    [[w:ストラボン|ストラボーン]]などによれば[[w:ケルト語|ケルト語]]でルコテキア Lukotekia と呼ばれていたらしい。)</span> :  ;   セノネース族について [[画像:Plan_de_Paris_Lutece2_BNF07710745.png|thumb|right|200px|ルテティア周辺の地図(18世紀頃)]] *<!--❺-->[[wikt:en:confinis#Latin|Confines]] erant hi [[wikt:en:Senones#Latin|Senonibus]] **彼ら<small>〔パリースィイー族〕</small>はセノネース族に隣接していて、 *civitatemque patrum memoria [[wikt:en:coniungo#Latin|coniunxerant]], **父祖の伝承では<small>(セノネース族と一つの)</small>部族として結びついていた。 *sed ab hoc consilio [[wikt:en:absum#Latin|afuisse]] [[wikt:en:existimo#Latin|existimabantur]]. **しかし<small>(パリースィイー族は)</small>これらの謀計には関与していなかったと考えられていた。 :  *<!--❻-->Hac re pro [[wikt:en:suggestus#Latin|suggestu]] [[wikt:en:pronuntiatus#Latin|pronuntiata]] **<small>(カエサルは)</small>この事を演壇の前で宣言すると、 *eodem die cum legionibus in [[wikt:en:Senones#Latin|Senones]] [[wikt:en:proficiscor#Latin|proficiscitur]] **同日に諸軍団とともにセノネース族のところに出発して、 *magnisque itineribus eo [[wikt:en:pervenio#Latin|pervenit]]. **強行軍でもってそこに到着した。 <!-- <span style="color:#009900;"></span> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ===4節=== *<span style="background-color:#ffd;">[[/注解/4節]] {{進捗|00%|2024-10-09}}</span> ;セノネース族のアッコーが造反するが、カエサルはセノネース族とカルヌーテース族を降伏させる *<!--❶-->[[wikt:en:cognitus#Participle|Cognito]] eius [[wikt:en:adventus#Latin|adventu]], **彼<small>〔カエサル〕</small>の到来を知ると、 *[[wikt:en:Acco#Latin|Acco]], qui princeps eius consilii fuerat, **その画策の首謀者であった<small>(セノネース族の)</small>'''アッコー''' は、 *[[wikt:en:iubeo#Latin|iubet]] in oppida multitudinem [[wikt:en:convenio#Latin|convenire]]. **群衆に諸[[w:オッピドゥム|城塞都市]]に集結することを命じる。 :  *[[wikt:en:conans#Latin|Conantibus]], [[wikt:en:priusquam|prius quam]] id [[wikt:en:effici|effici]] posset, [[wikt:en:adsum#Latin|adesse]] Romanos [[wikt:en:nuntio#Verb|nuntiatur]]. **そのことが遂行され得るより前に、ローマ人が接近していることが、企てている者たちに報告される。 :  *<!--❷-->Necessario [[wikt:en:sententia#Latin|sententia]] [[wikt:en:desisto#Latin|desistunt]] **<small>(セノネース族は)</small>やむなく<small>(カエサルへの謀反の)</small>意図を思いとどまって、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[wikt:en:necessario#Adverb|necessāriō]] = [[wikt:en:necessarie#Adverb|necessāriē]]「やむを得ず」)</span> *legatosque [[wikt:en:deprecor#Latin|deprecandi]] causa ad Caesarem mittunt; **<small>(恩赦を)</small>嘆願するために、使節たちをカエサルのもとへ遣わして、 *<u>adeunt</u> per [[wikt:en:Aedui#Latin|Haeduos]], quorum [[wikt:en:antiquitus|antiquitus]] erat in fide civitas. **部族国家が昔から<small>(ローマ人に対して)</small>忠実であった[[w:ハエドゥイ族|ハエドゥイー族]]を介して、頼み込む。 **:<span style="color:#009900;">(訳注:この部分は、セノネース族がハエドゥイー族の庇護下にあったように訳されることも多いが、<br>    [[ガリア戦記 第5巻#54節|第5巻54節]]における両部族とローマ人の関係の記述を考慮して、上のように訳した<ref>[[s:en:Commentaries_on_the_Gallic_War/Book_6#4|英語版ウィキソース]]では「they make advances to him through the Aedui, whose state was from ancient times under the protection of Rome.」と英訳されている。</ref>。)</span> **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[wikt:de:adire|adeō]]「(誰かに)アプローチする」「(誰かに)頼る、頼む、懇願する」<ref>[https://www.frag-caesar.de/lateinwoerterbuch/adeo-uebersetzung-1.html adeo-Übersetzung im Latein Wörterbuch]</ref>)</span> :  *<!--❸-->Libenter Caesar [[wikt:en:petens#Latin|petentibus]] [[wikt:en:Aedui#Latin|Haeduis]] dat [[wikt:en:venia#Latin|veniam]] **カエサルは、懇願するハエドゥイー族に対して、喜んで<small>(セノネース族への)</small>恩赦を与え、 *[[wikt:en:excusatio#Latin|excusationem]]<nowiki>que</nowiki> accipit, **<small>(セノネース族の)</small>弁解を受け入れる。 *quod [[wikt:en:aestivus#Latin|aestivum]] tempus [[wikt:en:instans#Latin|instantis]] belli, **というのは、夏の時季は差し迫っている<small>(エブローネース族らとの)</small>戦争のためのものであり、 *non [[wikt:en:quaestio#Latin|quaestionis]] esse [[wikt:en:arbitror#Latin|arbitrabatur]]. **<small>(謀反人に対する)</small>尋問のためのものではないと<small>(カエサルが)</small>判断していたからである。 **:<span style="color:#009900;">(訳注:エブローネース族との戦争が終わった後に、謀反人への尋問が行なわれることになる。[[#44節|44節]]参照。)</span> :  *<!--❹-->Obsidibus [[wikt:en:imperatus#Latin|imperatis]] centum, **<small>(カエサルは)</small>100人の人質<small>(の供出)</small>を命令すると、 *hos Haeduis [[wikt:en:custodiendus#Latin|custodiendos]] [[wikt:en:trado#Latin|tradit]]. **彼ら<small>〔人質たち〕</small>を監視するべく[[w:ハエドゥイ族|ハエドゥイー族]]に引き渡す。 :  *<!--❺-->[[wikt:en:eodem#Adverb|Eodem]] [[wikt:en:Carnutes#Latin|Carnutes]] legatos obsidesque [[wikt:en:mitto#Latin|mittunt]], **ちょうどそこに、カルヌーテース族が使節たちと人質たちを遣わして、 *[[wikt:en:usus#Participle|usi]] [[wikt:en:deprecator#Latin|deprecatoribus]] [[wikt:en:Remi#Proper_noun_3|Remis]], quorum erant in [[wikt:en:clientela#Latin|clientela]]; **<small>(カルヌーテース族が)</small><ruby><rb>[[w:クリエンテス|庇護]]</rb><rp>(</rp><rt>クリエンテーラ</rt><rp>)</rp></ruby>を受ける関係にあったレーミー族を<ruby><rb>助命仲介者</rb><rp>(</rp><rt>デープレカートル</rt><rp>)</rp></ruby>として利用して、 *eadem ferunt [[wikt:en:responsum#Latin|responsa]]. **<small>(セノネース族のときと)</small>同じ返答を獲得する。 :  *<!--❻-->[[wikt:en:perago#Latin|Peragit]] [[wikt:en:concilium#Noun|concilium]] Caesar **カエサルは<small>(ガッリア諸部族の領袖たちの)</small>会合を完了して、 *equitesque [[wikt:en:impero#Latin|imperat]] civitatibus. **[[w:騎兵|騎兵]]たち<small>(の供出)</small>を諸部族に命令する。 <!-- <span style="color:#009900;"></span> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ===5節=== *<span style="background-color:#ffd;">[[/注解/5節]] {{進捗|00%|2024-10-10}}</span> ;アンビオリークスへの策を練り、メナピイー族へ向かう *<!--❶-->Hac parte Galliae [[wikt:en:pacatus#Latin|pacata]], **ガッリアのこの方面が平定されたので、 **:<span style="color:#009900;">(訳注:[[#3節|3節]]~[[#4節|4節]]でネルウィイー族、セノネース族とカルヌーテース族がカエサルに降伏したことを指す。)</span> *totus et mente et animo in bellum [[wikt:en:Treveri#Latin|Treverorum]] et [[wikt:en:Ambiorix#Latin|Ambiorigis]] [[wikt:en:insisto#Latin|insistit]]. **<small>(カエサルは)</small>全身全霊をかけて、トレーウェリー族と[[w:アンビオリクス|アンビオリークス]]との戦争に着手する。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:totus et [[wikt:en:mens#Latin|mente]] et [[wikt:en:animus#Latin|animo]] 「全身全霊をかけて」''with all his heart and soul'' )</span> :  *<!--❷-->[[wikt:en:Cavarinus#Latin|Cavarinum]] cum equitatu [[wikt:en:Senones#Latin|Senonum]] [[wikt:en:secum#Latin|secum]] [[wikt:en:proficiscor#Latin|proficisci]] [[wikt:en:iubeo#Latin|iubet]], **カウァリーヌスに、セノネース族の[[w:騎兵|騎兵]]隊を伴って、自分<small>〔カエサル〕</small>とともに出発することを命じる。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:''[[w:de:Cavarinus|Cavarinus]]'' は、[[ガリア戦記 第5巻#54節|第5巻54節]]で前述のように、<br>    カエサルにより王位に据えられていたが、独立主義勢力により追放された。)</span> *ne [[wikt:en:aliquis#Latin|quis]] <u>aut</u> ex huius [[wikt:en:iracundia#Latin|iracundia]] <u>aut</u> ex eo, quod [[wikt:en:mereo#Latin|meruerat]], [[wikt:en:odium#Latin|odio]] civitatis [[wikt:en:motus#Noun_2|motus]] [[wikt:en:exsistat|exsistat]]. **彼の激しやすさから、<u>あるいは</u>彼が招来していた反感から、部族国家の何らかの動乱が起こらないようにである。 **:<span style="color:#009900;">(訳注:前節でアッコーら独立主義者たちがカエサルに降伏して、<br>    カウァリーヌスが王位に戻されたために、<br>    部族内で反感をかっていたのであろう。)</span> :  *<!--❸-->His rebus [[wikt:en:constitutus#Participle|constitutis]], **これらの事柄が取り決められると、 *quod pro explorato habebat, [[wikt:en:Ambiorix#Latin|Ambiorigem]] [[wikt:en:proelium#Latin|proelio]] non esse <u>concertaturum</u>, **<small>(カエサルは)</small>[[w:アンビオリクス|アンビオリークス]]が戦闘で激しく争うつもりではないことを、確実と見なしていたので、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[wikt:en:pro#Latin|pro]] [[wikt:en:exploratus#Latin|explorato]] = [[wikt:en:exploratus#Latin|exploratum]]「確かなものとして(''as certain'')」)</span> **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&chi;系(A・Q)およびL・N写本では non esse <u>[[wikt:en:concertaturum|concertaturum]]</u>「激しくつもりではないこと」だが、<br>         &beta;系写本では non esse <u>[[wikt:en:contenturum|contenturum]]</u><br>         B・M・S写本では non esse <u>concertaturum [[wikt:en:tenturum|tenturum]]</u> となっている。)</span> *reliqua eius [[wikt:en:consilium#Latin|consilia]] animo [[wikt:en:circumspicio#Latin|circumspiciebat]]. **彼<small>〔アンビオリークス〕</small>のほかの計略に思いをめぐらせていた。 :  ;   カエサルがメナピイー族の攻略を決意 *<!--❹-->Erant [[wikt:en:Menapii#Latin|Menapii]] propinqui [[wikt:en:Eburones#Latin|Eburonum]] finibus, **メナピイー族は[[w:エブロネス族|エブローネース族]]の領土に隣り合っていて、 *[[wikt:en:perpetuus#Latin|perpetuis]] [[wikt:en:palus#Latin|paludibus]] [[wikt:en:silva#Latin|silvis]]<nowiki>que</nowiki> [[wikt:en:munitus#Latin|muniti]], **絶え間ない沼地と森林によって守られており、 *qui uni ex Gallia de pace ad Caesarem legatos [[wikt:en:numquam#Latin|numquam]] [[wikt:en:mitto#Latin|miserant]]. **彼らは[[w:ガリア|ガッリア]]のうちでカエサルのもとへ講和の使節たちを決して遣わさなかった唯一の者たちであった。 :  *Cum his esse [[wikt:en:hospitium#Latin|hospitium]] [[wikt:en:Ambiorix#Latin|Ambiorigi]] [[wikt:en:scio#Latin|sciebat]]; **<small>(カエサルは)</small>[[w:アンビオリクス|アンビオリークス]]が彼らのもとで歓待されていることを知っていたし、 *item per [[wikt:en:Treveri#Latin|Treveros]] venisse Germanis in [[wikt:en:amicitia#Latin|amicitiam]] [[wikt:en:cognosco#Latin|cognoverat]]. **同様にトレーウェリー族を通じて[[w:ゲルマニア|ゲルマーニア]]人と盟約を結んだことも探知していた。 :  *<!--❺-->Haec <u>prius</u> illi [[wikt:en:detrahendus#Latin|detrahenda]] auxilia [[wikt:en:existimo#Latin|existimabat]] <u>quam</u> ipsum bello [[wikt:en:lacesso#Latin|lacesseret]], **<ruby><rb>彼奴</rb><rp>(</rp><rt>あやつ</rt><rp>)</rp></ruby><small>〔アンビオリークス〕</small>へのこれらの支援は、彼奴自身に戦争で挑みかかる<u>より前に</u>引き離されるべきだと考えていた。 *ne [[wikt:en:desperatus#Latin|desperata]] [[wikt:en:salus#Latin|salute]] **<small>(アンビオリークスが)</small>身の安全に絶望して、 *<u>aut</u> se in [[wikt:en:Menapii#Latin|Menapios]] [[wikt:en:abdo#Latin|abderet]], **<u>あるいは</u>メナピイー族のところに身を隠したりしないように、 *<u>aut</u> cum [[wikt:en:Transrhenanus#Latin|Transrhenanis]] [[wikt:en:congredior#Latin|congredi]] [[wikt:en:cogo#Latin|cogeretur]]. **<u>あるいは</u>レーヌス<small>〔[[w:ライン川|ライン川]]〕</small>の向こう側の者たちと合同することを強いられないように、である。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:''Germani Transrhenani'' 「レーヌスの向こう側のゲルマーニア人」(東岸の諸部族)を<br>    ''[[w:en:Germani cisrhenani|Germani Cisrhenani]]''「レーヌスのこちら側のゲルマーニア人」(西岸の諸部族) が<br>    招き寄せているというのが『ガリア戦記』の主張である。)</span> :  *<!--❻-->Hoc [[wikt:en:initus#Participle|inito]] consilio, **この計略を決断すると、 *[[wikt:en:totus#Etymology_1|totius]] exercitus [[wikt:en:impedimentum#Latin|impedimenta]] ad [[wikt:en:Labienus#Latin|Labienum]] in [[wikt:en:Treveri#Latin|Treveros]] [[wikt:en:mitto#Latin|mittit]] **<small>(カエサルは)</small>全軍の[[w:輜重|輜重]]を、トレーウェリー族のところにいる[[w:ティトゥス・ラビエヌス|ラビエーヌス]]のもとへ送り、 *duasque ad eum legiones [[wikt:en:proficiscor#Latin|proficisci]] [[wikt:en:iubeo#Latin|iubet]]; **2個[[w:ローマ軍団|軍団]]に彼<small>〔ラビエーヌス〕</small>のもとへ出発することを命じる。 :  *ipse cum legionibus [[wikt:en:expeditus#Participle|expeditis]] quinque in [[wikt:en:Menapii#Latin|Menapios]] [[wikt:en:proficiscor#Latin|proficiscitur]]. **<small>(カエサル)</small>自身は軽装の5個軍団とともにメナピイー族のところに出発する。 :  *<!--❼-->Illi, [[wikt:en:nullus#Adjective|nulla]] [[wikt:en:coactus#Latin|coacta]] [[wikt:en:manus#Latin|manu]], **あの者らは、何ら手勢を集めず、 *loci [[wikt:en:praesidium#Latin|praesidio]] [[wikt:en:fretus#Adjective|freti]], **地勢の要害を信頼して、 *in [[wikt:en:silva#Latin|silvas]] [[wikt:en:palus#Latin|paludes]]<nowiki>que</nowiki> [[wikt:en:confugio#Latin|confugiunt]] **森林や沼地に避難して、 *[[wikt:en:suus#Latin|sua]]<nowiki>que</nowiki> [[wikt:en:eodem#Adverb|eodem]] [[wikt:en:confero#Latin|conferunt]]. **自分たちの家財を同じところに運び集める。 <!-- <span style="color:#009900;"></span> <small></small> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ===6節=== *<span style="background-color:#ffd;">[[/注解/6節]] {{進捗|00%|2024-10-20}}</span> ;メナピイー族がついにカエサルの軍門に降る *<!--❶-->Caesar, **カエサルは、 *[[wikt:en:partitus#Latin|partitis]] copiis cum [[wikt:en:Gaius#Latin|Gaio]] [[wikt:en:Fabius#Latin|Fabio]] legato et [[wikt:en:Marcus#Latin|Marco]] [[wikt:en:Crassus#Latin|Crasso]] [[wikt:en:quaestor#Latin|quaestore]] **[[w:レガトゥス|副官]]である[[w:ガイウス・ファビウス|ガーイウス・ファビウス]]と[[w:クァエストル|財務官]]である[[w:マルクス・リキニウス・クラッスス (財務官)|マールクス・クラッスス]]とともに軍勢を分配して、 *celeriterque [[wikt:en:effectus#Participle|effectis]] [[wikt:en:pons#Latin|pontibus]] **速やかに橋梁を造って、 **:<span style="color:#009900;">(訳注:橋梁は軽装の軍団兵が沼地を渡るためのものなので、丸太道のようなものであろうか。)</span> *[[wikt:en:adeo#Verb|adit]] [[wikt:en:tripertito|tripertito]], **三方面から<small>(メナピイー族の領土に)</small>接近して、 [[画像:GallischeHoeve.jpg|thumb|right|200px|復元されたメナピイー族の住居(再掲)]] *[[wikt:en:aedificium#Latin|aedificia]] [[wikt:en:vicus#Latin|vicos]]<nowiki>que</nowiki> [[wikt:en:incendo#Latin|incendit]], **建物や村々を焼き討ちして、 *magno [[wikt:en:pecus#Latin|pecoris]] atque hominum numero [[wikt:en:potior#Latin|potitur]]. **家畜や人間の多数を<small>(戦利品として)</small>獲得する。 :  *<!--❷-->Quibus rebus [[wikt:en:coactus#Participle|coacti]] **そのような事態に強いられて、 *[[wikt:en:Menapii#Latin|Menapii]] legatos ad eum [[wikt:en:pax#Latin|pacis]] [[wikt:en:petendus#Latin|petendae]] causa [[wikt:en:mitto#Latin|mittunt]]. **メナピイー族は和平を求めるための使節たちを彼<small>〔カエサル〕</small>のもとへ遣わす。 :  *<!--❸-->Ille [[wikt:en:obses#Latin|obsidibus]] [[wikt:en:acceptus#Latin|acceptis]], **彼<small>〔カエサル〕</small>は人質たちを受け取ると、 *hostium se [[wikt:en:habiturus#Latin|habiturum]] numero [[wikt:en:confirmo#Latin|confirmat]], si aut [[wikt:en:Ambiorix#Latin|Ambiorigem]] aut eius legatos finibus suis [[wikt:en:recipio#Latin|recepissent]]. **もし[[w:アンビオリクス|アンビオリークス]]か彼の使節を自領に迎え入れたら、自分は<small>(メナピイー族を)</small>敵として見なすだろうと断言する。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:属格の名詞 + numero「〜として」) :  *<!--❹-->His [[wikt:en:confirmatus#Latin|confirmatis]] rebus, **これらの事柄を確立すると、 *[[wikt:en:Commius#Latin|Commium]] [[wikt:en:Atrebas#Latin|Atrebatem]] cum [[wikt:en:equitatus#Latin|equitatu]] [[wikt:en:custos#Latin|custodis]] loco in [[wikt:en:Menapii#Latin|Menapiis]] [[wikt:en:relinquo#Latin|relinquit]]; **アトレバーテース族である[[w:コンミウス|コンミウス]]を[[w:騎兵|騎兵]]隊とともに、目付け役として、メナピイー族のところに残す。 **:<span style="color:#009900;">(訳注:コンミウスは、カエサルがアトレバテース族の王にすえて、ブリタンニア遠征の先導役として遣わし、<br>    カッスィウェッラウヌスの降伏の仲介を</span>果たしていた。[[ガリア戦記 第4巻#21節|第4巻21節]]・27節や[[ガリア戦記 第5巻#22節|第5巻22節]]などを参照。) *ipse in [[wikt:en:Treveri#Latin|Treveros]] [[wikt:en:proficiscor#Latin|proficiscitur]]. **<small>(カエサル)</small>自身はトレーウェリー族のところに出発する。 <!-- <span style="color:#009900;"></span> <small></small> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ===7節=== *<span style="background-color:#ffd;">[[/注解/7節]] {{進捗|00%|2024-10-27}}</span> [[画像:Titelberg_01.jpg|thumb|right|200px|トレーウェリー族の城砦跡(再掲)]] ;トレーウェリー族の開戦準備、ラビエーヌスの計略 *<!--❶-->Dum haec a Caesare [[wikt:en:gero#Latin|geruntur]], **これらのことがカエサルによって遂行されている間に、 *[[wikt:en:Treveri#Latin|Treveri]] magnis [[wikt:en:coactus#Participle|coactis]] [[wikt:en:peditatus#Latin|peditatus]] [[wikt:en:equitatus#Etymology_1|equitatus]]<nowiki>que</nowiki> copiis **トレーウェリー族は、[[w:歩兵|歩兵]]隊と[[w:騎兵|騎兵]]隊の大軍勢を徴集して、 *[[wikt:en:Labienus#Latin|Labienum]] cum una legione, quae in eorum finibus <u>[[wikt:en:hiemo#Latin|hiemaverat]]</u>, **彼らの領土において越冬していた1個[[w:ローマ軍団|軍団]]とともに[[w:ティトゥス・ラビエヌス|ラビエーヌス]]を、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&alpha;系写本では [[wikt:en:hiemaverat|hiemaverat]] <small>(過去完了形)</small> だが、<br>         &beta;系写本では [[wikt:en:hiemabat|hiemabat]] <small>(未完了過去形)</small> などとなっている。)</span> *[[wikt:en:adorior#Latin|adoriri]] [[wikt:en:paro#Latin|parabant]], **襲撃することを準備していた。 :  *<!--❷-->iamque ab eo non longius [[wikt:en:biduum#Latin|bidui]] via [[wikt:en:absum#Verb|aberant]], **すでに、そこ<small>〔ラビエーヌスの冬営〕</small>から2日間の道のりより遠く離れていなかったが、 *cum duas venisse legiones [[wikt:en:missus#Noun_2|missu]] Caesaris [[wikt:en:cognosco#Latin|cognoscunt]]. **そのときに、カエサルが派遣した2個軍団が到着したことを知る。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[#5節|5節]]で既述のように、カエサルはラビエーヌスのところへ全軍の輜重と2個軍団を派遣していた。<br>    こうして、ラビエーヌスはローマ全軍の輜重と3個軍団を任されることになった。) :  *<!--❸-->[[wikt:en:positus#Latin|Positis]] <u>castris</u> a milibus passuum [[wikt:en:quindecim#Latin|quindecim]](XV) **<small>(トレーウェリー勢は、ラビエーヌスの冬営から)</small>15ローママイルのところに<u>野営地</u>を設置して、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:1[[ガイウス・ユリウス・カエサルの著作/通貨・計量単位#ミーッレ・パッスーム、ミーリア(ローママイル)|ローママイル]]は約1.48 kmで、15マイルは約22 km)</span> **:<span style="color:#009900;font-family:Times New Roman;">(訳注:[[w:カストラ|カストラ]] [[wikt:en:castra#Latin|castra]] という語はローマ勢の行軍中の野営地や常設の宿営地に用いられ、<br>    非ローマ系部族の野営地に用いられることは稀である。)</span> *auxilia [[wikt:en:Germani#Latin|Germanorum]] [[wikt:en:exspecto#Latin|exspectare]] [[wikt:en:constituo#Latin|constituunt]]. **[[w:ゲルマニア|ゲルマーニア]]人の援軍を待つことを決める。 :  *<!--❹-->[[wikt:en:Labienus#Latin|Labienus]] hostium [[wikt:en:cognitus#Participle|cognito]] consilio **ラビエーヌスは、敵勢<small>〔トレーウェリー族〕</small>の計略を知ると、 *[[wikt:en:sperans#Latin|sperans]] [[wikt:en:temeritas#Latin|temeritate]] eorum [[wikt:en:fore#Etymology_2_2|fore]] [[wikt:en:aliqui#Latin|aliquam]] [[wikt:en:dimico#Latin|dimicandi]] facultatem, **彼らの無謀さにより何らかの争闘する機会が生ずるであろうと期待して、 *[[wikt:en:praesidium#Latin|praesidio]] quinque(V) cohortium [[wikt:en:impedimentum#Latin|impedimentis]] [[wikt:en:relictus#Latin|relicto]] **5個<ruby><rb>[[w:コホルス|歩兵大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby>の守備隊を[[w:輜重|輜重]]のために残し、 *cum XXV(viginti quinque) cohortibus magnoque [[wikt:en:equitatus#Etymology_1|equitatu]] contra hostem [[wikt:en:proficiscor#Latin|proficiscitur]] **25個<ruby><rb>[[w:コホルス|歩兵大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby>および多勢の騎兵隊とともに、敵に抗して進発する。 *et mille passuum [[wikt:en:intermissus#Latin|intermisso]] spatio castra [[wikt:en:communio#Latin|communit]]. **<small>(トレーウェリー勢から)</small>1ローママイルの間隔を置いて、[[w:カストラ|陣営]]<small>〔野営地〕</small>を固める。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:1[[ガイウス・ユリウス・カエサルの著作/通貨・計量単位#ミーッレ・パッスーム、ミーリア(ローママイル)|ローママイル]]は約1.48 km)</span> :  *<!--❺-->Erat inter [[wikt:en:Labienus#Latin|Labienum]] atque hostem [[wikt:en:difficilis#Latin|difficili]] [[wikt:en:transitus#Latin|transitu]] flumen [[wikt:en:ripa#Latin|ripis]]<nowiki>que</nowiki> [[wikt:en:praeruptus#Adjective|praeruptis]]. **ラビエーヌスと敵の間には、渡ることが困難な川が、急峻な岸とともにあった。 *Hoc <u>neque</u> ipse [[wikt:en:transeo#Latin|transire]] habebat in animo **これを<small>(ラビエーヌス)</small>自身は渡河するつもりではなかったし、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:~ habeo in animo「~するつもりである」)</span> **:<span style="color:#009900;font-family:Times New Roman;">(訳注:neque ~, neque …「~でもないし、…でもない」)</span> *<u>neque</u> hostes [[wikt:en:transiturus#Latin|transituros]] [[wikt:en:existimo#Latin|existimabat]]. **敵勢も渡河して来ないであろうと<small>(ラビエーヌスは)</small>考えていた。 :  *<!--❻-->[[wikt:en:augeo#Latin|Augebatur]] auxiliorum [[wikt:en:cotidie#Latin|cotidie]] spes. **<small>(トレーウェリー勢にとって、ゲルマーニア人の)</small>援軍への期待は日ごとに増されるばかりであった。 *[[wikt:en:loquor#Latin|Loquitur]] <u>in consilio</u> [[wikt:en:palam#Adverb|palam]]: **<small>(ラビエーヌスは)</small>会議において公然と<small>(以下のように)</small>述べる。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、主要写本&omega;では in [[wikt:en:consilio|consilio]] だが、<br>         [[ガリア戦記/注解編/写本と校訂版#Aldus|Aldus]] は in [[wikt:en:concilium#Latin|concilio]] と修正提案し、<br>         Hecker は [[wikt:en:consulto#Adverb|consulto]] と修正提案している。)</span> *[[wikt:en:quoniam#Latin|quoniam]] [[wikt:en:Germani#Latin|Germani]] [[wikt:en:adpropinquo#Latin|adpropinquare]] [[wikt:en:dico#Latin|dicantur]], **ゲルマーニア人<small>(の軍勢)</small>が近づいていることが言われているので、 *sese suas exercitusque fortunas in [[wikt:en:dubium#Noun|dubium]] non [[wikt:en:devocaturus#Latin|devocaturum]] **自分は自らと軍隊の命運を不確実さの中に引きずり込むことはないであろうし、 *et postero die prima luce castra [[wikt:en:moturus#Latin|moturum]]. **翌日の夜明けには陣営を引き払うであろう。 :  *<!--❼-->Celeriter haec ad hostes [[wikt:en:defero#Latin|deferuntur]], **これら<small>(のラビエーヌスの発言)</small>は速やかに敵勢<small>〔トレーウェリー族〕</small>のもとへ報じられたので、 *ut ex magno Gallorum equitum numero [[wikt:en:nonnullus#Latin|non nullos]] <u>Gallos</u> [[wikt:en:gallicus#Latin|Gallicis]] rebus [[wikt:en:faveo#Latin|favere]] natura [[wikt:en:cogo#Latin|cogebat]]. **ガッリア人の境遇を想う気質が、<small>(ローマ側)</small>ガッリア人騎兵の多数のうちの若干名を励ましていたほどである。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部の [[wikt:en:Gallus#Noun|Gallos]] は &alpha;系写本の記述で、&beta;系写本では欠く。)</span> :  *<!--❽-->[[wikt:en:Labienus#Latin|Labienus]], noctu tribunis militum primisque ordinibus <u>convocatis</u>, **ラビエーヌスは、夜間に<ruby><rb>[[w:トリブヌス・ミリトゥム|兵士長官]]</rb><rp>(</rp><rt>トリブヌス・ミリトゥム</rt><rp>)</rp></ruby>たちと第一序列(の[[w:ケントゥリオ|百人隊長]])たちを召集すると、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:1個軍団当たりの<ruby><rb>[[w:トリブヌス・ミリトゥム|兵士長官]]</rb><rp>(</rp><rt>トリブヌス・ミリトゥム</rt><rp>)</rp></ruby> の定員は計6名。<br>    第一序列の<ruby><rb>[[w:ケントゥリオ|百人隊長]]</rb><rp>(</rp><rt>ケントゥリオー</rt><rp>)</rp></ruby>たち primorum ordinum centuriones は、軍団内における[[w:下士官|下士官]]のトップであり、<br>     第一<ruby><rb>[[w:コホルス|歩兵大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby> においては定員5名だが、<br>     ほかの歩兵大隊においては定員6名であった。)</span> **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&alpha;系写本では [[wikt:en:convocatus#Latin|convocatis]] だが、<br>         &beta;系写本では [[wikt:en:coactus#Participle|coactis]] などとなっている。)</span> *quid sui sit consilii, [[wikt:en:propono#Latin|proponit]] **自分の計略がいかなるものであるかを呈示して、 *et, quo facilius hostibus [[wikt:en:timor#Latin|timoris]] [[wikt:en:det#Latin|det]] [[wikt:en:suspicio#Noun|suspicionem]], **それ<small>〔計略〕</small>によって、よりたやすく敵勢に<small>(ローマ勢の)</small>恐怖心という推測を起こすべく、 *maiore [[wikt:en:strepitus#Latin|strepitu]] et [[wikt:en:tumultus#Latin|tumultu]], quam populi Romani fert [[wikt:en:consuetudo#Latin|consuetudo]] **ローマ国民の習慣が引き起こすよりもより大きな騒音や喧騒をもって *castra [[wikt:en:moveo#Latin|moveri]] [[wikt:en:iubeo#Latin|iubet]]. **陣営を引き払うことを命じる。 *His rebus fugae [[wikt:en:similis#Latin|similem]] [[wikt:en:profectio#Latin|profectionem]] [[wikt:en:efficio#Latin|effecit]]. **<small>(ラビエーヌスは)</small>これらの事によって、逃亡に似た進発を実現した。 :  *<!--❾-->Haec quoque per [[wikt:en:explorator#Latin|exploratores]] **これらのこともまた、<small>(トレーウェリー勢の)</small>斥候たちを通じて、 *ante [[wikt:en:lux#Latin|lucem]] in tanta [[wikt:en:propinquitas#Latin|propinquitate]] castrorum ad hostes [[wikt:en:defero#Latin|deferuntur]]. **夜明け前には、陣営のこれほどの近さにより、敵勢へ報じられる。 <!-- <span style="color:#009900;"></span> <small></small> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ===8節=== *<span style="background-color:#ffd;">[[/注解/8節]] {{進捗|00%|2024-10-28}}</span> ;ラビエーヌスがトレーウェリー族を降す :  ;   トレーウェリー勢が、渡河してラビエーヌスの軍勢に攻めかかろうとする *<!--❶-->[[wikt:en:vix#Latin|Vix]] [[wikt:en:agmen#Latin|agmen]] [[wikt:en:novissimus#Latin|novissimum]] extra [[wikt:en:munitio#Latin|munitiones]] [[wikt:en:procedo#Latin|processerat]], **<small>(ローマ勢の)</small>行軍隊列の最後尾が防塁の外側にほぼ進み出ようとしていた、 *cum Galli [[wikt:en:cohortatus#Latin|cohortati]] inter se, ne [[wikt:en:speratus#Latin|speratam]] [[wikt:en:praeda#Latin|praedam]] ex manibus [[wikt:en:dimitto#Latin|dimitterent]] **そのときにガッリア人たちは、期待していた戦利品を<small>(彼らの)</small>手から逸しないように、互いに鼓舞し合って、 *── longum esse, [[wikt:en:perterritus#Latin|perterritis]] Romanis [[wikt:en:Germani#Proper_noun|Germanorum]] auxilium [[wikt:en:exspecto#Latin|exspectare]]; **── ローマ人が<ruby><rb>怖気</rb><rp>(</rp><rt>おじけ</rt><rp>)</rp></ruby>ているのに、[[w:ゲルマニア|ゲルマーニア]]人の支援を待つことは悠長なものである。 *neque suam [[wikt:en:patior#Latin|pati]] [[wikt:en:dignitas#Latin|dignitatem]], **<small>(以下のことは)</small>自分たちの尊厳が耐えられない。 *ut [[wikt:en:tantus#Latin|tantis]] copiis [[wikt:en:tam#Latin|tam]] [[wikt:en:exiguus#Latin|exiguam]] manum, praesertim [[wikt:en:fugiens#Latin|fugientem]] atque [[wikt:en:impeditus#Latin|impeditam]], **これほどの大軍勢で<small>(ローマの)</small>それほどの貧弱な手勢を、特に逃げ出して<small>(荷物で)</small>妨げられている者たちを *[[wikt:en:adorior#Latin|adoriri]] non [[wikt:en:audeo#Latin|audeant]] ── **あえて襲撃しないとは──<small>(と鼓舞し合って)</small> *flumen [[wikt:en:transeo#Latin|transire]] et iniquo loco [[wikt:en:committo#Latin|committere]] proelium non [[wikt:en:dubito#Latin|dubitant]]. **川を渡って<small>(切り立った岸を登りながら)</small>不利な場所で交戦することをためらわない。 :  ;   ラビエーヌス勢が怖気を装いながら、そろりそろりと進む *<!--❷-->Quae fore [[wikt:en:suspicatus#Latin|suspicatus]] [[wikt:en:Labienus#Latin|Labienus]], **こうしたことが生じるであろうと想像していた[[w:ティトゥス・ラビエヌス|ラビエーヌス]]は、 *ut omnes citra flumen [[wikt:en:elicio#Latin|eliceret]], **<small>(敵の)</small>総勢を川のこちら側に誘い出すように、 *[[wikt:en:idem#Latin|eadem]] [[wikt:en:usus#Participle|usus]] [[wikt:en:simulatio#Latin|simulatione]] itineris **行軍の同じ見せかけを用いて、 **:<span style="color:#009900;">(訳注:前節で語られたように、<ruby><rb>怖気</rb><rp>(</rp><rt>おじけ</rt><rp>)</rp></ruby>て今にも逃げ出しそうな風に装いながらの行軍。)</span> *[[wikt:en:placide#Adverb|placide]] [[wikt:en:progredior#Latin|progrediebatur]]. **穏やかに前進していた。 :  ;   ラビエーヌスが全軍の兵を叱咤激励する *<!--❸-->Tum [[wikt:en:praemissus#Latin|praemissis]] paulum impedimentis **それから、[[w:輜重|輜重]]<small>(の隊列)</small>を少し先に遣わして、 *atque in [[wikt:en:tumulus#Latin|tumulo]] [[wikt:en:quidam#Adjective|quodam]] [[wikt:en:collocatus#Latin|conlocatis]], **とある高台に配置すると、 *<!--▲直接話法--><span style="background-color:#e8e8ff;"><span style="color:#009900;">«</span>&nbsp;[[wikt:en:habetis|Habetis]],<span style="color:#009900;">»</span></span> [[wikt:en:inquam#Latin|inquit]], <!--▲直接話法--><span style="background-color:#e8e8ff;"><span style="color:#009900;">«</span>milites, quam [[wikt:en:petistis|petistis]], [[wikt:en:facultas#Latin|facultatem]]; </span> **<small>(ラビエーヌスは)</small>「兵士らよ、<small>(諸君は)</small>求めていた機会を得たぞ」と言った。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:以下、<!--▲直接話法--><span style="background-color:#e8e8ff;">&nbsp;<span style="color:#009900;">«</span> ~ <span style="color:#009900;">»</span>&nbsp;</span> の箇所は、直接話法で記されている。)</span> *<!--▲直接話法--><span style="background-color:#e8e8ff;">hostem [[wikt:en:impeditus#Latin|impedito]] atque [[wikt:en:iniquus#Latin|iniquo]] loco [[wikt:en:tenetis|tenetis]]: </span> **「<small>(諸君は)</small>敵を<small>(川岸で)</small>妨げられた不利な場所に追いやった。」 *<!--❹--><!--▲直接話法--><span style="background-color:#e8e8ff;">[[wikt:en:praestate|praestate]] eandem nobis [[wikt:en:dux#Latin|ducibus]] [[wikt:en:virtus#Latin|virtutem]], quam saepe numero [[wikt:en:imperator#Latin|imperatori]] [[wikt:en:praestitistis|praestitistis]], </span> **「我々<ruby><rb>将帥</rb><rp>(</rp><rt>ドゥクス</rt><rp>)</rp></ruby>らに、<small>(諸君が)</small>しばしば<ruby><rb>将軍</rb><rp>(</rp><rt>インペラートル</rt><rp>)</rp></ruby><small>〔カエサル〕</small>に見せて来たのと同じ武勇を見せてくれ。」 *<!--▲直接話法--><span style="background-color:#e8e8ff;">atque illum adesse et haec [[wikt:en:coram#Adverb|coram]] [[wikt:en:cerno#Latin|cernere]] [[wikt:en:existimate|existimate]].<span style="color:#009900;">»</span></span> **「彼<small>〔カエサル〕</small>が訪れて、これ<small>〔武勇〕</small>を目の前で見ていると思ってくれ。」 :  ;   ラビエーヌスが軍を反転させて攻撃態勢を整える *<!--❺-->Simul signa ad hostem [[wikt:en:converto#Latin|converti]] aciemque [[wikt:en:dirigo#Latin|dirigi]] [[wikt:en:iubeo#Latin|iubet]], **同時に、軍旗が敵の方へ向きを変えられることと、戦列が整えられること、を命じる。 **:<span style="color:#009900;">(訳注:軍勢が敵側へ向けて反転して、戦列を整えること、を命じた。)</span> [[画像:Pilensalve.jpg|thumb|right|250px|[[w:ピルム|ピールム]](投槍)を投げるローマ軍兵士(帝政期)の再演]] *et paucis [[wikt:en:turma#Latin|turmis]] praesidio ad impedimenta [[wikt:en:dimissus#Latin|dimissis]], **かつ若干の<ruby><rb>[[w:トゥルマ|騎兵小隊]]</rb><rp>(</rp><rt>トゥルマ</rt><rp>)</rp></ruby>を輜重のための守備隊として送り出して、 **:<span style="color:#009900;">(訳注:騎兵小隊 turma はローマ軍の<br>    [[w:アウクシリア|支援軍]]における中規模の編成単位で、<br>    各30騎ほどと考えられている。)</span> *reliquos equites ad latera [[wikt:en:dispono#Latin|disponit]]. **残りの[[w:騎兵|騎兵]]たちを<small>(軍勢の)</small>両側面へ分置する。 :  ;   ラビエーヌス勢が喊声を上げて、投げ槍を投げ始める *<!--❻-->Celeriter nostri, clamore [[wikt:en:sublatus#Latin|sublato]], [[wikt:en:pilum#Latin|pila]] in hostes [[wikt:en:inmitto#Latin|inmittunt]]. **我が方<small>〔ローマ勢〕</small>は、雄叫びを上げると、速やかに<ruby><rb>[[w:ピルム|投げ槍]]</rb><rp>(</rp><rt>ピールム</rt><rp>)</rp></ruby>を敵勢へ放り入れる。 :  ;   不意を突かれたトレーウェリー勢が、一目散に逃げ出して、最寄りの森林を目指す *Illi, ubi [[wikt:en:praeter#Latin|praeter]] spem, quos <span style="color:#009900;">&lt;modo&gt;</span> [[wikt:en:fugio#Latin|fugere]] [[wikt:en:credo#Latin|credebant]], [[wikt:en:infestus#Latin|infestis]] signis ad se ire viderunt, **<span style="font-size:11pt;">彼らは、期待に反して、<span style="color:#009900;">&lt;ただ&gt;</span>逃げていると信じていた者たちが、軍旗を攻勢にして自分らの方へ来るのを見るや否や、</span> *[[wikt:en:impetus#Latin|impetum]] <u>modo</u> ferre non potuerunt **<small>(ローマ勢の)</small>突撃を持ちこたえることができずに、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部 modo は主要写本&omega;ではこの位置にあるが、<br>    上記の &lt;modo&gt; に移す修正提案がある。)</span> *ac primo [[wikt:en:concursus#Noun|concursu]] in fugam [[wikt:en:coniectus#Participle|coniecti]] **最初の猛攻で敗走に追い込まれて、 *proximas silvas [[wikt:en:peto#Latin|petierunt]]. **近隣の森を目指した。 :  ;   ラビエーヌス勢が、トレーウェリー勢の多数を死傷させ、部族国家を奪回する *<!--❼-->Quos [[wikt:en:Labienus#Latin|Labienus]] equitatu [[wikt:en:consectatus#Latin|consectatus]], **<small>(敗走した)</small>その者たちを、ラビエーヌスは騎兵隊で追撃して、 *magno numero [[wikt:en:interfectus#Latin|interfecto]], **多数の者を<ruby><rb>殺戮</rb><rp>(</rp><rt>さつりく</rt><rp>)</rp></ruby>して、 *compluribus [[wikt:en:captus#Latin|captis]], **かなりの者たちを捕らえて、 *paucis post diebus civitatem recepit. **数日後に<small>(トレーウェリーの)</small>部族国家を<small>(蜂起の前の状態に)</small>戻した。 :  [[画像:Bund-ro-altburg.jpg|thumb|right|180px|トレーウェリー族の再現された住居(再掲)]] [[画像:Trier_Kaiserthermen_BW_1.JPG|thumb|right|180px|トレーウェリー族(Treveri)の名を現代に伝えるドイツの[[w:トリーア|トリーア市]](Trier)に残るローマ時代の浴場跡]] ;   ゲルマーニア人の援軍が故国へ引き返す *Nam [[wikt:en:Germani#Latin|Germani]], qui auxilio veniebant, **なぜなら、援軍として来ようとしていたゲルマーニア人たちは、 *[[wikt:en:perceptus#Latin|percepta]] [[wikt:en:Treveri#Latin|Treverorum]] fuga **トレーウェリー族の敗走を把握したので、 *sese [[wikt:en:domus#Latin|domum]] <u>receperunt</u>. **故国に撤退していった。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&alpha;系写本では [[wikt:en:receperunt|receperunt]] だが、<br>         &beta;系写本では [[wikt:en:contulerunt|contulerunt]] となっている。)</span> :  ;   インドゥーティオマールスの残党がゲルマーニアへ出奔する *<!--❽-->Cum his [[wikt:en:propinquus#Latin|propinqui]] [[wikt:en:Indutiomarus#Latin|Indutiomari]], **彼ら<small>〔ゲルマーニア人〕</small>とともに、インドゥーティオマールスの縁者たちは、 *qui [[wikt:en:defectio#Latin|defectionis]] [[wikt:en:auctor#Latin|auctores]] fuerant, **その者らは<small>(トレーウェリー族におけるカエサルへの)</small>謀反の張本人であったが、 *[[wikt:en:comitatus#Participle|comitati]] eos ex civitate [[wikt:en:excedo#Latin|excesserunt]]. **彼ら<small>〔ゲルマーニア人〕</small>を伴って、部族国家から出て行った。 :  ;   カエサルとローマに忠節なキンゲトリークスに、部族の統治権が託される *<!--❾-->[[wikt:en:Cingetorix#Latin|Cingetorigi]], **キンゲトリークスに対しては、 *quem ab initio [[wikt:en:permaneo#Latin|permansisse]] in [[wikt:en:officium#Latin|officio]] [[wikt:en:demonstravimus|demonstravimus]], **──その者が当初から<small>(ローマへの)</small>忠義に留まり続けたことは前述したが── **:<span style="color:#009900;">(訳注:キンゲトリークスについては、[[ガリア戦記 第5巻#3節|第5巻3節]]~4節・[[ガリア戦記 第5巻#56節|56節]]~57節で述べられている。)</span> *[[wikt:en:principatus#Latin|principatus]] atque [[wikt:en:imperium#Latin|imperium]] est traditum. **首長の地位と支配権が託された。 <!-- <span style="color:#009900;"></span> <span style="font-size:11pt;"></span> <small></small> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ==第二次ゲルマーニア遠征== ===9節=== *<span style="background-color:#ffd;">[[/注解/9節]] {{進捗|00%|2024-11-06}}</span> ;再びレーヌスを渡河、ウビイー族を調べる *<!--❶-->Caesar, [[wikt:en:postquam#Latin|postquam]] ex [[wikt:en:Menapii#Latin|Menapiis]] in [[wikt:en:Treveri#Latin|Treveros]] venit, **カエサルは、メナピイー族のところからトレーウェリー族のところに来た後で、 *duabus de causis [[wikt:en:Rhenus#Latin|Rhenum]] [[wikt:en:transeo#Latin|transire]] [[wikt:en:constituo#Latin|constituit]]; **二つの理由からレーヌス<small>〔[[w:ライン川|ライン川]]〕</small>を渡ることを決めた。 :  *<!--❷-->quarum una erat, quod <span style="color:#009900;">&lt;Germani&gt;</span> auxilia contra se [[wikt:en:Treveri#Latin|Treveris]] [[wikt:en:mitto#Latin|miserant]]; **その<small>(理由の)</small>一つは、<span style="color:#009900;">&lt;ゲルマーニア人が&gt;</span>自分<small>〔カエサル〕</small>に対抗して、トレーウェリー族に援軍を派遣していたことであった。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:&lt;[[wikt:en:Germani#Latin|Germani]]&gt; は、主要写本&omega;にはなく、[[ガリア戦記/注解編/写本と校訂版#Hotomanus|Hotomanus]] による挿入提案。)</span> *<span style="color:#009900;">(quarum)</span> altera <span style="color:#009900;">(erat)</span>, ne ad eos [[wikt:en:|Ambiorix]] [[wikt:en:receptus#Noun|receptum]] haberet. **もう一つ<small>(の理由)</small>は、彼らのもとへ[[w:アンビオリクス|アンビオリークス]]が避難所を持たないように、ということであった。 :  [[画像:Caesar's Rhine Crossing.jpg|thumb|right|250px|カエサルがライン川に橋を架けたとされる有力な地点の図示。ライン川と[[w:モーゼル川|モーゼル川]]の合流点にある[[w:コブレンツ|コブレンツ]]([[w:en:Koblenz|Koblenz]])と下流の[[w:アンダーナッハ|アンダーナッハ]]([[w:en:Andernach|Andernach]])との間の[[w:ノイヴィート|ノイヴィート]]([[w:en:Neuwied|Neuwied]])辺りが有力な地点の一つとされる。'''([[ガリア戦記_第4巻#17節|第4巻17節]]の図を再掲)''']] *<!--❸-->His [[wikt:en:constitutus#Participle|constitutis]] rebus, **これらの事柄を決定すると、 *[[wikt:en:paulum#Adverb|paulum]] supra eum locum, [[wikt:en:quo#Adverb|quo]] ante exercitum [[wikt:en:traduco#Latin|traduxerat]], **<u>以前に軍隊を渡らせていた場所</u>の少し上流に、 *facere [[wikt:en:pons#Latin|pontem]] [[wikt:en:instituo#Latin|instituit]]. **橋を造ることを決意する。 **:<span style="color:#009900;">(訳注:[[ガリア戦記_第4巻#17節|第4巻17節]] でカエサルが[[w:ライン川|ライン川]]に架橋した場所のこと。<br>    第4巻の'''[[ガリア戦記_第4巻#コラム「ゲルマーニア両部族が虐殺された場所はどこか?」|コラム]]''' や [[ガリア戦記_第4巻#17節|第4巻17節]]の図で説明したように、<br>    カエサルの最初の架橋地点には異論もあるが、<br>    今回の架橋地点がトレーウェリー族領であった<br>    [[w:モーゼル川|モーゼル川]]渓谷から近かったであろうことから有力視される。)</span> :  *<!--❹-->[[wikt:en:notus#Latin|Nota]] atque [[wikt:en:institutus#Latin|instituta]] ratione, **経験しかつ建造していた方法で、 *magno militum [[wikt:en:studium#Latin|studio]] **兵士たちの大きな熱意により *paucis diebus [[wikt:en:opus#Latin|opus]] [[wikt:en:efficio#Latin|efficitur]]. **わずかな日数で作業が完遂される。 :  *<!--❺-->[[wikt:en:firmus#Latin|Firmo]] in [[wikt:en:Treveri#Latin|Treveris]] ad pontem praesidio [[wikt:en:relictus#Latin|relicto]], **トレーウェリー族領内の橋のたもとへ強力な守備隊を残して、 *ne [[wikt:en:aliquis#Latin|quis]] ab his subito [[wikt:en:motus#Noun_2|motus]] <u>oreretur</u>, **──彼ら<small>〔トレーウェリー族〕</small>による何らかの動乱が不意に起こされないためであるが、── **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&chi;系・B・&rho;系写本では [[wikt:en:oreretur|oreretur]]、<br>         &phi;系・&pi;系写本では [[wikt:en:oriretur|oriretur]] だが、語形の相異。)</span> *reliquas copias [[wikt:en:equitatus#Noun|equitatum]]<nowiki>que</nowiki> [[wikt:en:traduco#Latin|traducit]]. **残りの軍勢と騎兵隊を<small>(レーヌス川の東岸へ)</small>渡らせる。 :  *<!--❻-->[[wikt:en:Ubii#Latin|Ubii]], qui ante obsides [[wikt:en:dederant|dederant]] atque in [[wikt:en:deditio#Latin|deditionem]] venerant, **ウビイー族は、以前に<small>(カエサルに対して)</small>人質たちを供出していて、降伏していたが、 **:<span style="color:#009900;">(訳注:この事はすでに[[ガリア戦記 第4巻#16節|第4巻16節]]で述べられている。)</span> *<u>[[wikt:en:purgandus#Latin|purgandi]] sui</u> causa ad eum legatos mittunt, **自分たちの申し開きをすることのために、彼<small>〔カエサル〕</small>のもとへ使節たちを遣わして、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&alpha;系写本では [[wikt:en:purgandi|purgandi]] [[wikt:en:sui#Pronoun|sui]] だが、<br>         &beta;系写本では purgandi のみ。)</span> *qui [[wikt:en:doceant|doceant]], **<small>(以下のように)</small>説かせた。 *neque <u>auxilia ex sua civitate</u> in [[wikt:en:Treveri#Latin|Treveros]] [[wikt:en:missus#Participle|missa]] **自分たちの部族から援軍をトレーウェリー族のところに派遣してもいないし、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&chi;系・B・M・S写本では [[wikt:en:auxilia#Latin|auxilia]] ex sua [[wikt:en:civitate|civitate]]、<br>         L・N・&beta;系写本では ex sua civitate auxilia の語順になっている。)</span> *neque ab se [[wikt:en:fides#Latin|fidem]] [[wikt:en:laesus#Latin|laesam]]: **自分らにより<small>(ローマへの)</small>信義を傷つけてもいない、と。 :  *<!--❼-->[[wikt:en:peto#Latin|petunt]] atque [[wikt:en:oro#Latin|orant]], **<small>(ウビイー族の使節たちは、以下のように)</small>求め、かつ願った。 *ut sibi [[wikt:en:parco#Latin|parcat]], **自分たちを容赦し、 *ne [[wikt:en:communis#Latin|communi]] [[wikt:en:odium#Latin|odio]] [[wikt:en:Germani#Latin|Germanorum]] [[wikt:en:innocens#Latin|innocentes]] pro [[wikt:en:nocens#Latin|nocentibus]] poenas [[wikt:en:pendo#Latin|pendant]]; **[[w:ゲルマニア|ゲルマーニア]]人一般への憎しみから、潔白な者たちが加害者たちのために罰を償うことがないように、と。 *si [[wikt:en:amplius|amplius]] obsidum <u>vellet, dare</u> [[wikt:en:polliceor#Latin|pollicentur]]. **もし、より多くの人質を欲するのなら、供出することを約束する、と。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、&alpha;系写本では [[wikt:en:vellet#Latin|vellet]] <small>(未完了過去・接続法)</small> [[wikt:en:dare#Latin|dare]] <small>(現在・能動・不定)</small> だが、<br>         &beta;系写本では [[wikt:en:velit#Latin|velit]] <small>(現在・接続法)</small> [[wikt:en:dari#Latin|dari]] <small>(現在・受動・不定法)</small> となっている。)</span> :  *<!--❽-->Cognita Caesar causa **カエサルは事情を調査して、 *<u>repperit</u> ab [[wikt:en:Suebi#Latin|Suebis]] auxilia [[wikt:en:missus#Participle|missa]] esse; **スエービー族により<small>(トレーウェリー族に)</small>援軍が派遣されていたことを見出した。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、主要写本 &omega; では [[wikt:en:repperit|repperit]] <small>(完了形)</small> だが、<br>         近世以降の印刷本 [[ガリア戦記/注解編/写本と校訂版#クリティカル・アパラトゥスとその略号|edd.]] では [[wikt:en:reperit|reperit]] <small>(現在形)</small> となっている。)</span> :  *[[wikt:en:Ubii#Latin|Ubiorum]] [[wikt:en:satisfactio#Latin|satisfactionem]] <u>accepit</u>, **ウビイー族の弁解を受け入れて、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:下線部は、主要写本 &omega; では [[wikt:en:accepit|accepit]] <small>(完了形)</small> だが、<br>         [[ガリア戦記/注解編/写本と校訂版#Davisius|Davisius]] の修正提案では [[wikt:en:accipit|accipit]] <small>(現在形)</small> となっている。)</span> *[[wikt:en:aditus#Noun_2|aditus]] viasque in [[wikt:en:Suebi#Latin|Suebos]] [[wikt:en:perquiro#Latin|perquirit]]. **スエービー族のところに出入りする道筋を問い質す。 <!-- <span style="color:#009900;"></span> <small></small> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> ===10節=== *<span style="background-color:#ffd;">[[/注解/10節]] {{進捗|00%|2024-11-16}}</span> ;ウビイー族を通じてスエービー族の動静を探る *<!--❶-->Interim paucis post diebus fit ab [[wikt:en:Ubii#Latin|Ubiis]] certior, **数日後の間に、ウビイー族によって報告されたことには、 *[[wikt:en:Suebi#Latin|Suebos]] omnes in unum locum copias [[wikt:en:cogo#Latin|cogere]] **スエービー族は、すべての軍勢を一か所に集めて、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:後述するように、これはカッティー族 [[w:en:Chatti|Chatti]] のことであろう。)</span> *atque iis [[wikt:en:natio#Latin|nationibus]], quae sub eorum sint imperio, **彼らの支配下にある種族たちに *[[wikt:en:denuntio#Latin|denuntiare]], ut auxilia [[wikt:en:peditatus#Latin|peditatus]] [[wikt:en:equitatus#Noun|equitatus]]<nowiki>que</nowiki> mittant. **[[w:歩兵|歩兵]]隊と[[w:騎兵|騎兵]]隊の援軍を派遣するように布告する。 :  *<!--❷-->His [[wikt:en:cognitus#Participle|cognitis]] rebus, **<small>(カエサルは)</small>これらの事情を知ると、 *rem [[wikt:en:frumentarius#Latin|frumentariam]] [[wikt:en:provideo#Latin|providet]], **糧食調達を手配して、 *castris idoneum locum [[wikt:en:deligo#Latin|deligit]]; **[[w:カストラ|陣営]]<small>(を設置するために)</small>に適切な場所を選ぶ。 :  *[[wikt:en:Ubii#Latin|Ubiis]] [[wikt:en:impero#Latin|imperat]], ut [[wikt:en:pecus#Latin|pecora]] [[wikt:en:deduco#Latin|deducant]] suaque omnia ex agris in oppida [[wikt:en:confero#Latin|conferant]], **ウビイー族には、家畜を連れ去り、自分らの一切合財を農村地帯から<ruby><rb>[[w:オッピドゥム|城塞都市]]</rb><rp>(</rp><rt>オッピドゥム</rt><rp>)</rp></ruby>に運び集めるように命令する。 *[[wikt:en:sperans#Latin|sperans]] [[wikt:en:barbarus#Adjective|barbaros]] atque [[wikt:en:imperitus#Latin|imperitos]] homines **<small>(カエサルが)</small>期待したのは、野蛮で未熟な連中が *[[wikt:en:inopia#Noun_2|inopia]] [[wikt:en:cibaria#Latin|cibariorum]] [[wikt:en:adductus#Latin|adductos]] **食糧の欠乏に動かされて、 *ad [[wikt:en:iniquus#Latin|iniquam]] [[wikt:en:pugno#Latin|pugnandi]] [[wikt:en:condicio#Latin|condicionem]] posse [[wikt:en:dēdūcō|deduci]]; **不利な条件のもとで戦うことにミスリードされ得ることであった。 :  *<!--❸-->[[wikt:en:mando#Latin|mandat]], ut [[wikt:en:creber#Latin|crebros]] [[wikt:en:explorator#Latin|exploratores]] in [[wikt:en:Suebi#Latin|Suebos]] [[wikt:en:mitto#Latin|mittant]] [[wikt:en:quis#Pronoun|quae]]<nowiki>que</nowiki> apud eos [[wikt:en:gero#Latin|gerantur]] [[wikt:en:cognosco#Latin|cognoscant]]. **多数の斥候をスエービー族領に遣わして、彼らのもとで遂行されていることを探知するように<small>(ウビイー族に)</small>委ねる。 :  *<!--❹-->Illi imperata faciunt et paucis diebus intermissis referunt: **彼ら<small>〔ウビイー族〕</small>は、命令されたことを実行して、わずかな日々を間に置いて(以下のことを)報告する。 *[[wikt:en:Suebi#Latin|Suebos]] omnes, posteaquam certiores nuntii de exercitu Romanorum venerint, **スエービー族は皆、ローマ人の軍隊についてより確実な報告がもたらされた後で、 *cum omnibus suis sociorumque copiis, quas coegissent, **自分たちの軍勢と集結していた同盟者たちの軍勢とともに、 *penitus ad extremos fines se recepisse; **領土の最も遠い奥深くまで撤退していた。 :  *<!--❺-->silvam esse ibi infinita magnitudine, quae appellatur <u>Bacenis</u>; **そこには、'''バケーニス'''と呼ばれている限りない大きさの森林がある。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:バケーニス [[wikt:en:Bacenis#Latin|Băcēnis]] は、ギリシア語で Βακέννη とも表記されるが、どこなのかは諸説ある。<br>     ①ドイツ西部[[w:ヘッセン州|ヘッセン州]]にあったブコニアの森 ''[[w:de:Buchonia|Buchonia]]; [[w:fr:Forêt de Buconia|Buconia]]'' は有力。<br>     ②ドイツの奥地・中東部の[[w:テューリンゲン州|テューリンゲン州]]にある[[w:テューリンゲンの森|テューリンゲンの森]]という説<ref>[[s:de:RE:Bacenis silva]], [[wikt:de:Bacenis]] 等を参照。</ref><br>     ③ドイツ西部[[w:ラインラント=プファルツ州|ラインラント=プファルツ州]]ライン川沿岸のニールシュタイン [[w:en:Nierstein|Nierstein]] 説、<br>    などがある。史実としてスエービーという部族連合が居住していたのはテューリンゲンであろうが、<br>    ライン川からはあまりにも遠すぎる。)</span> *hanc longe introrsus pertinere et pro nativo muro obiectam **これは、はるか内陸に及んでいて、天然の防壁として横たわっており、 *[[wikt:en:Cheruscos|Cheruscos]] ab Suebis Suebosque ab [[wikt:en:Cheruscis|Cheruscis]] iniuriis incursionibusque prohibere: **ケールスキー族をスエービー族から、スエービー族をケールスキー族から、無法行為や襲撃から防いでいる。 *ad eius initium silvae Suebos adventum Romanorum exspectare constituisse. **その森の始まりのところで、スエービー族はローマ人の到来を待ち構えることを決定した。 <!-- <span style="color:#009900;"></span> <small></small> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> <div style="border:solid #999 1px;background:#feedff;max-width:80%;padding:0.25em 1em;margin:0.5em auto;align:left;overflow:auto;text-align:justify;"> ===コラム「スエービー族とカッティー族・ケールスキー族・ウビイー族について」=== [[画像:Hermann (Arminius) at the battle of the Teutoburg Forest in 9 CE by Peter Jannsen, 1873, with painting creases and damage removed.jpg|thumb|right|250px|ウァルスの戦い([[w:de:Varusschlacht|Varusschlacht]])こと[[w:トイトブルク森の戦い|トイトブルク森の戦い]](AD9年)で戦う、ゲルマーニア軍とローマ軍(Johann Peter Theodor Janssen画、1870~1873年頃)。中央上の人物はケールスキー族の名将[[w:アルミニウス (ゲルマン人)|アルミニウス]]。<br>アルミニウスが率いるケールスキー族・カッティー族らゲルマーニア諸部族同盟軍は、P.クィン(ク)ティリウス・ウァルス麾下ローマ3個軍団を壊滅させ、アウグストゥスに「ウァルスよ諸軍団を返せ([[w:la:Publius_Quinctilius_Varus|Quintili Vare]], legiones redde!)」と嘆かせた。]] <br> <div style="background:#ecf;">  '''スエービー族とカッティー族'''</div> :『ガリア戦記』では、第1巻・第4巻および第6巻でたびたび[[w:スエビ族|スエービー族]]の名が言及される。タキトゥス<ref>『ゲルマーニア』タキトゥス著、泉井久之助訳注、岩波文庫の38章「スエービー」などを参照。</ref>など多くの史家が伝えるようにスエービー族 [[wikt:en:Suebi#Latin|Suēbī]] またはスエウィ族 Suēvī とは、単一の部族名ではなく、多くの独立した部族国家から構成される連合体の総称とされる。 :19世紀のローマ史家[[w:テオドール・モムゼン|テオドール・モムゼン]]によれば<ref>『モムゼン ローマの歴史Ⅳ』長谷川博隆訳、名古屋大学出版会、のp.201, p.224, p.232などを参照。</ref>、カエサルの時代のローマ人には 「スエービー」とは遊牧民を指す一般的な呼称で、カエサルがスエービーと呼ぶのはカッティー族だという。 :カッティー族とスエービー系諸部族の異同は明確ではないが、多くの史家は両者を区別して伝えている。 : 第1巻37節・51節・53節~54節、第4巻1節~4節・7節などで言及され、「百の郷を持つ」と されている「スエービー族」は、スエービー系諸部族の総称、あるいは遊牧系の部族を指すのであろう。 : 他方、第4巻16節・19節・第6巻9節~10節・29節で、ウビイー族を圧迫する存在として言及される :「スエービー族」はモムゼンの指摘のように、カッティー族 [[w:en:Chatti|Chatti]] であることが考えられる。 :タキトゥス著『ゲルマーニア』<ref>『ゲルマーニア』タキトゥス著、泉井久之助訳注、岩波文庫の36章「ケルスキー」などを参照。</ref>でも、カッティー族はケールスキー族と隣接する宿敵として描写され、本節の説明に合致する。 <div style="background:#ecf;">  '''ケールスキー族'''</div> :ケールスキー族は、『ガリア戦記』では[[#10節|本節]]でカッティー族と隣接する部族として名を挙げられる :のみである。しかしながら、本巻の年(BC53年)から61年後(AD9年)には、帝政ローマの :[[w:アウグストゥス|アウグストゥス帝]]がゲルマーニアに派遣していたプブリウス・クィンクティリウス・ウァルス :([[w:la:Publius_Quinctilius_Varus|Publius Quinctilius Varus]])が率いるローマ軍3個軍団に対して、名将[[w:アルミニウス (ゲルマン人)|アルミニウス]]を :指導者とするケールスキー族は、カッティー族ら諸部族の同盟軍を組織して、ウァルスの3個軍団を :[[w:トイトブルク森の戦い|トイトブルク森の戦い]]において壊滅させ、老帝アウグストゥスを嘆かせたという。 <div style="background:#ecf;">  '''ウビイー族'''</div> :ウビイー族は『ガリア戦記』の第4巻・第6巻でも説明されているように、ローマ人への忠節を :認められていた。そのため、タキトゥスによれば<ref>『ゲルマーニア』タキトゥス著、泉井久之助訳注、岩波文庫の28章などを参照。</ref>、ゲルマニアへのローマ人の守りとして :BC38年頃にレヌス(ライン川)左岸のコロニア([[w:la:Colonia_Agrippina|Colonia]];植民市)すなわち現在の[[w:ケルン|ケルン市]]に移された。) </div> ==ガッリア人の社会と風習について== <div style="border:solid #999 1px;background:#feedff;max-width:80%;padding:0.25em 1em;margin:0.5em auto;align:left;overflow:auto;text-align:justify;"> ===コラム「ガッリア・ゲルマーニアの地誌・民族誌について」=== [[画像:Testa di saggio o principe, forse il filosofo poseidonio, 50 ac. ca 01.JPG|thumb|right|200px|アパメアの[[w:ポセイドニオス|ポセイドニオス]]の胸像。地中海世界やガッリアなどを広く訪れて、膨大な著作を残した。<br>『ガリア戦記』の地誌・民族誌的な説明も、その多くを彼の著作に依拠していると考えられている。]] :これ以降、11節~20節の10節にわたってガッリアの地誌・民族誌的な説明が展開され、さらには、ゲルマーニアの地誌・民族誌的な説明などが21節~28節の8節にわたって続く。ガッリア戦争の背景説明となるこのような地誌・民族誌は、本来ならば第1巻の冒頭に置かれてもおかしくはない。しかしながら、この第6巻の年(BC53年)は、カエサル指揮下のローマ勢にとってはよほど書かれるべき戦果が上がらなかったためか、ガッリア北部の平定とエブロネス族の追討戦だけでは非常に短い巻となってしまうため、このような位置に置いたとも考えられる。ゲルマーニアの森にどんな獣が住んでいるかなど、本筋にほとんど影響のないと思われる記述も見られる。 :『ガリア戦記』におけるガッリアの地誌・民族誌的な説明、特にこの11節以降の部分は、文化史的に重要なものと見なされ、考古学やケルトの伝承などからも裏付けられる。しかし、これらの記述はカエサル自身が見聞したというよりも、むしろ先人の記述、とりわけBC2~1世紀のギリシア哲学ストア派の哲学者・地理学者・歴史学者であった[[w:ポセイドニオス|ポセイドニオス]]([[w:la:Posidonius Apameus|Posidonius Apameus]])の著作に依拠していたと考えられている<ref>『ケルト事典』ベルンハルト・マイヤー著、鶴岡真弓監修、創元社の「ポセイドニオス」「カエサル」の項を参照。</ref> <ref>『ケルト人』ヴァンセスラス・クルータ([[w:fr:Venceslas Kruta|Venceslas Kruta]])著、鶴岡真弓訳、白水社 のp.20-21を参照。</ref>。ポセイドニオスは、ローマが支配する地中海世界やガッリア地域などを広く旅行した。彼の52巻からなる膨大な歴史書は現存しないが、その第23巻にガッリアに関する詳細な記述があったとされ、[[w:シケリアのディオドロス|ディオドロス]]、[[w:ストラボン|ストラボン]]、[[w:アテナイオス|アテナイオス]]らによって引用され、同時代および近代のケルト人観に多大な影響を与えたと考えられている。 :現存するガッリアの地誌・民族誌は、ストラボン<ref>『ギリシア・ローマ世界地誌Ⅰ』ストラボン著、飯尾都人訳、龍溪書舎を参照。</ref>、ディオドロス<ref>『神代地誌』ディオドロス著、飯尾都人訳、龍溪書舎を参照。</ref>、ポンポニウス・メラ<ref>『世界地理』ポンポニウス・メラ著、飯尾都人訳(上掲『神代地誌』に所収)</ref>のものなどがある。現存するゲルマーニアの地誌・民族誌は、ストラボン、タキトゥス<ref>『ゲルマーニア』タキトゥス著、泉井久之助訳注、岩波文庫などを参照。</ref>、ポンポニウス・メラなどのものがある。 </div> ===11節=== '''ガッリア人の派閥性''' *① Quoniam ad hunc locum perventum est, **この地(ゲルマーニア)にまで到達したので、 *non alienum esse videtur de Galliae Germaniaeque moribus et, quo differant hae nationes inter sese proponere. **[[w:ガリア|ガッリア]]と[[w:ゲルマニア|ゲルマーニア]]の風習について、これらの種族が互いにどのように異なるか述べることは不適切でないと思われる。 *② In Gallia non solum in omnibus civitatibus atque in omnibus <u>[[wikt:en:pagus#Latin|pagis]]</u> partibusque, **ガッリアにおいては、すべての部族において、さらにすべての<u>郷</u>や地方においてのみならず、 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:''pagus'' (郷) はここでは、部族の領土の農村区画を指す行政用語<ref name="pagus">''[[w:en:Pagus]]'' 等を参照。</ref>。)</span> *sed paene etiam in singulis domibus factiones sunt, **ほとんどの個々の氏族においてさえも、派閥があり、 *earumque factionum principes sunt, **それらの派閥には、領袖がいる。 *③ qui summam auctoritatem eorum iudicio habere existimantur, **その者(領袖)らは、彼ら(派閥)の判断に対して、最高の影響力を持っていると考えられている。 *quorum ad arbitrium iudiciumque summa omnium rerum consiliorumque redeat. **すべての事柄と協議は結局のところ、その者(領袖)らの裁量や判断へ帰する。 *④ Idque eius rei causa antiquitus institutum videtur, **それは、それらの事柄のために昔から取り決められたものと見られ、 *ne quis ex plebe contra potentiorem auxilii egeret: **平民のある者が、より権力のある者に対して、援助を欠くことがないように、ということである。 *suos enim quisque opprimi et circumveniri non patitur, **すなわち(領袖たちの)誰も、身内の者たちが抑圧されたり欺かれたりすることを容認しない。 *neque, aliter si faciat, ullam inter suos habet auctoritatem. **もし(領袖が)そうでなくふるまったならば、身内の者たちの間で何ら影響力を持てない。 *⑤ Haec eadem ratio est in summa totius Galliae; **これと同じ理屈が、ガッリア全体の究極において存在する。 *namque omnes civitates in partes divisae sunt duas. **すなわち、すべての部族が二つの党派に分けられているのである。 ===12節=== '''ハエドゥイ族、セクァニ族、レミ族の覇権争い''' *① Cum Caesar in Galliam venit, **カエサルがガッリアに来たときに、 *alterius factionis principes erant Haedui, alterius Sequani. **(二つの)派閥の一方の盟主は[[w:ハエドゥイ族|ハエドゥイ族]]であり、他方は[[w:セクァニ族|セクァニ族]]であった。 **:(訳注:第1巻31節の記述によれば、ハエドゥイ族と[[w:アルウェルニ族|アルウェルニ族]]がそれぞれの盟主であった。 **:カエサルが本節でアルウェルニ族の名を伏せている理由は不明である。 **:また、[[w:ストラボン|ストラボン]]によれば<ref>ストラボン『ギリシア・ローマ世界地誌Ⅰ』(前掲、p.330)</ref>、ハエドゥイ族とセクァニ族の敵対関係においては、 **:両部族を隔てるアラル川の水利権(川舟の通行税)をめぐる争いが敵意を助長していたという。) *② Hi cum per se minus valerent, **後者(セクァニ族)は自力ではあまり優勢ではなかったので、 *quod summa auctoritas antiquitus erat in Haeduis **というのは、昔から最大の影響力はハエドゥイ族にあって、 *magnaeque eorum erant clientelae, **彼ら(ハエドゥイ族)には多くの庇護民があったからであるが、 *Germanos atque Ariovistum sibi adiunxerant **[[w:ゲルマニア|ゲルマニア]]人と[[w:アリオウィストゥス|アリオウィストゥス]]を自分たちに会盟させ、 *eosque ad se magnis iacturis pollicitationibusque perduxerant. **多くの負担と約束で 彼らを自分たちのところに引き入れた。 *③ Proeliis vero compluribus factis secundis **実にいくつもの戦闘を順調に行なって、 *atque omni nobilitate Haeduorum interfecta **ハエドゥイ族のすべての高貴な者たちを殺害して、 *tantum potentia antecesserant, **かなりの勢力で抜きん出たので、 *④ ut magnam partem clientium ab Haeduis ad se traducerent **結果として、ハエドゥイ族から庇護民の大部分を自分たちへ味方に付けて、 *obsidesque ab iis principum filios acciperent **彼らから領袖の息子たちを人質として受け取り、 *et publice iurare cogerent nihil se contra Sequanos consilii inituros, **自分たち(ハエドゥイ族)がセクァニ族に対して何ら謀計を始めるつもりではない、と公に誓うことを強いて、 *et partem finitimi agri per vim occupatam possiderent **近隣の土地の一部を力ずくで占領して所有地とした。 *Galliaeque totius principatum obtinerent. **ガッリア全体の指導権を手に入れた。 *⑤ Qua necessitate adductus **それにより、やむを得ずに動かされて、 *Diviciacus auxilii petendi causa Romam ad senatum profectus infecta re redierat. **[[w:ディウィキアクス|ディウィキアクス]]は支援を求めるために[[w:ローマ|ローマ市]]に元老院のところへ赴いたが、事を成就せずに帰った。 *⑥ Adventu Caesaris facta commutatione rerum, **カエサルの到来で事態の変化がなされて、 *obsidibus Haeduis redditis, **ハエドゥイ族の人質たちは戻されて、 *veteribus clientelis restitutis, **昔からの庇護民が復帰して、 *novis per Caesarem comparatis, **カエサルを通じて新参者たちを仲間にした。 *quod ii qui se ad eorum amicitiam adgregaverant, **というのは、彼ら(ハエドゥイ族)の友好のもとに仲間となっていた者たちが、 *⑦ meliore condicione atque aequiore imperio se uti videbant, **(セクァニ族)より良い条件とより公平な支配を享受しているように見えて、 *reliquis rebus eorum gratia dignitateque amplificata **ほかの事柄においても彼ら(ハエドゥイ族)の信望と品格がより増されて、 *Sequani principatum dimiserant. **セクァニ族は指導権を放棄したのだ。 *In eorum locum Remi successerant: **彼ら(セクァニ族)の地位において、[[w:レミ族|レミ族]]が取って代わった。 *quos quod adaequare apud Caesarem gratia intellegebatur, **その者ら(レミ族)はカエサルのもとで信望において(ハエドゥイ族と)同等であると認識されたので、 *ii qui propter veteres inimicitias nullo modo cum Haeduis coniungi poterant, **昔からの敵対関係のためにハエドゥイ族とどのようなやり方でも結ぶことができなかった者たちは、 *se Remis in clientelam dicabant. **レミ族との庇護関係に自らを委ねたのだ。 *⑧ Hos illi diligenter tuebantur; **この者ら(レミ族)はあの者ら(庇護民)を誠実に保護して、 *ita et novam et repente collectam auctoritatem tenebant. **このようにして、最近に得られた新しい影響力を保持した。 *⑨ Eo tum statu res erat, ut longe principes haberentur Haedui, **当時、ハエドゥイ族の位置付けは、まったく盟主と見なされるような状態であって、 *secundum locum dignitatis Remi obtinerent. **レミ族の品格は第二の地位を占めたのだ。 ===13節=== '''ガッリア人の社会階級、平民およびドルイドについて(1)''' *① In omni Gallia eorum hominum, qui aliquo sunt numero atque honore, genera sunt duo. **全ガッリアにおいて、何らかの地位や顕職にある人々の階級は二つである。 '''平民について''' *Nam plebes paene servorum habetur loco, **これに対して、平民はほとんど奴隷の地位として扱われており、 *quae nihil audet per se, nullo adhibetur consilio. **自分たちを通じては何らあえてすることはないし、誰も相談をされることもない。 *② Plerique, cum aut aere alieno aut magnitudine tributorum aut iniuria potentiorum premuntur, **多くの者は、あるいは負債、あるいは貢納の多さ、あるいはより権力のある者に抑圧されているので、 *sese in servitutem dicant. **自らを奴隷身分に差し出している。 *Nobilibus in hos eadem omnia sunt iura, quae dominis in servos. **高貴な者たちには彼ら(平民)において、奴隷において主人にあるのと同様なすべての権利がある。 '''ドルイドについて''' *③ Sed de his duobus generibus alterum est druidum, alterum equitum. **ともかく、これら二つの階級について、一方は[[w:ドルイド|ドルイド]](神官)であり、他方は[[w:騎士|騎士]]である。 *④ Illi rebus divinis intersunt, sacrificia publica ac privata procurant, religiones interpretantur: **前者(ドルイド)は神事に介在し、公・私の<ruby><rb>[[w:供犠|供犠]]</rb><rp>(</rp><rt>くぎ</rt><rp>)</rp></ruby>を司り、信仰のことを講釈する。 **:(訳注:供犠とは、人や獣を生け贄として神前に捧げることである。<ruby><rb>[[w:人身御供|人身御供]]</rb><rp>(</rp><rt>ひとみごくう</rt><rp>)</rp></ruby>とも。) [[画像:Two_Druids.PNG|thumb|right|200px|二人のドルイド。フランスの[[w:オータン|オータン]]、すなわちガッリア中部のビブラクテ辺りで発見された[[w:レリーフ|レリーフ]]。]] *ad hos magnus adulescentium numerus disciplinae causa concurrit, **この者ら(ドルイド)のもとへ、若者の多数が教えのために群り集まり、 *magnoque hi sunt apud eos honore. **この者ら(ドルイド)は、彼ら(ガッリア人)のもとで大いなる地位にある。 *⑤ Nam fere de omnibus controversiis publicis privatisque constituunt, **なぜなら(ドルイドは)ほとんどすべての公・私の訴訟ごとに判決をするのである。 *et, si quod est admissum facinus, si caedes facta, **もし何らかの罪悪が犯されれば、もし殺害がなされれば、 *si de hereditate, de finibus controversia est, **もし、遺産について、地所について、訴訟ごとがあれば、 *idem decernunt, praemia poenasque constituunt; **同じ人たち(ドルイド)が裁決し、補償や懲罰を判決するのである。 *⑥ si qui aut privatus aut populus eorum decreto non stetit, sacrificiis interdicunt. **もし何らかの個人あるいは集団が彼ら(ドルイド)の裁決を遵守しなければ、(その者らに)供犠を禁じる。 *Haec poena apud eos est gravissima. **これは、彼ら(ガッリア人)のもとでは、非常に重い懲罰である。 *⑦ Quibus ita est interdictum, **このように(供犠を)禁じられた者たちは、 *hi numero impiorum ac sceleratorum habentur, **彼らは、不信心で不浄な輩と見なされて、 *his omnes decedunt, aditum sermonemque defugiunt, **皆が彼らを忌避して、近づくことや会話を避ける。 *ne quid ex contagione incommodi accipiant, **(彼らとの)接触から、何らかの災厄を負うことがないようにである。 *neque his petentibus ius redditur **彼らが請願しても(元通りの)権利は戻されないし、 *neque honos ullus communicatur. **いかなる地位(に就くこと)も許されない。 *⑧ His autem omnibus druidibus praeest unus, **ところで、これらすべてのドルイドを一人が指導しており、 *qui summam inter eos habet auctoritatem. **その者は彼ら(ドルイドたち)の間に最高の影響力を持っている。 *⑨ Hoc mortuo **この者が死んだならば、 *aut, si qui ex reliquis excellit dignitate, succedit, **あるいは、もし残りの者たちの中から品格に秀でた者がおれば、継承して、 *aut, si sunt plures pares, suffragio druidum {adlegitur}<ref>adlegitur はβ系写本の記述で、α系写本にはない。</ref>; **あるいは、もしより多くの者たちが同等であれば、ドルイドの投票で{選ばれる}。 *nonnumquam etiam armis de principatu contendunt. **ときどきは、武力でさえも首座を争うことがある。 *⑩ Hi certo anni tempore **彼ら(ドルイド)は年間の定められた時期に *in finibus Carnutum, quae regio totius Galliae media habetur, considunt in loco consecrato. **ガッリア全体の中心地方と見なされている[[w:カルヌテス族|カルヌテス族]]の領土において、[[w:聖地|聖地]]に集合する。 **:(訳注:これはカエサルが支配する「ガッリア全体」の話で、他の地方には別の中心地があったようである。) *Huc omnes undique, qui controversias habent, conveniunt **ここへ、至る所から訴訟などを持つあらゆる者たちが集まって、 *eorumque decretis iudiciisque parent. **彼ら(ドルイド)の裁決や判断に服従する。 *⑪ Disciplina in Britannia reperta atque inde in Galliam translata esse existimatur, **(ドルイドの)教えは[[w:ブリタンニア|ブリタンニア]]で見出され、そこからガッリアにもたらされたと考えられている。 **:(訳注:これに対して、[[w:シケリアのディオドロス|ディオドロス]]は、ガッリア人の信仰は[[w:ピュタゴラス教団|ピュタゴラスの教説]]であると伝えている<ref>ディオドロス『神代地誌』(前掲、p.408)</ref>。 **:[[w:ストラボン|ストラボン]]によれば、これは東方のゲタエ人([[w:en:Getae|Getae]];[[w:トラキア|トラキア]]系ないし[[w:ダキア|ダキア]]系)を通じて取り入れたものだという<ref>ストラボン『ギリシア・ローマ世界地誌Ⅰ』(前掲、第7巻 第3章 第5節)</ref>。) *⑫ et nunc, qui diligentius eam rem cognoscere volunt, **今でも、その事柄をより入念に探究することを欲する者たちは、 *plerumque illo discendi causa proficiscuntur. **たいてい、かの地に研究するために旅立つ。 ===14節=== '''ドルイドについて(2)''' *① Druides a bello abesse consuerunt **[[w:ドルイド|ドルイド]]たちは、戦争に関与しない習慣であり、 *neque tributa una cum reliquis pendunt; **ほかの者と一緒に貢納(租税)を支払うこともない。 *militiae vacationem omniumque rerum habent immunitatem. **[[w:徴兵制度|兵役]]の免除や、すべての事柄において免除特権を持っているのである。 [[画像:Druids,_in_the_early_morning_glow_of_the_sun.jpg|thumb|right|200px|現代イギリスのドルイド教復興主義者たち]] *② Tantis excitati praemiis **このような特典に駆り立てられて *et sua sponte multi in disciplinam conveniunt **自らの意思で多くの者が教え(の場)に集まっても来るし、 *et a parentibus propinquisque mittuntur. **親たちや縁者たちによって送られても来る。 *③ Magnum ibi numerum versuum ediscere dicuntur. **(彼らは)そこで詩句の多数を習得すると言われている。 *Itaque annos nonnulli vicenos in disciplina permanent. **こうして、少なからぬ者たちが、20年にもわたって教え(の場)に残留する。 [[画像:Dédicace_de_Segomaros_(inscription gallo-grecque).png|thumb|right|200px|ギリシア文字で刻まれたガッリアの碑文]] *Neque fas esse existimant ea litteris mandare, **それら(の詩句)を文字で刻み込むことは、神意に背くと考えている。 *cum in reliquis fere rebus, publicis privatisque rationibus, Graecis litteris utantur. **もっとも、ほかの事柄においては、公・私の用件に[[w:ギリシア文字|ギリシア文字]]を用いる。 *④ Id mihi duabus de causis instituisse videntur, **それは、私(カエサル)には、二つの理由で(ドルイドが)定めたことと思われる。 **:(訳注:これは、カエサルが自らを一人称で示している珍しい個所である。) *quod neque in vulgum disciplinam efferri velint **というのは、教えが一般大衆にもたらされることは欲していないし、 *neque eos, qui discunt, litteris confisos minus memoriae studere: **(教えを)学ぶ者が、文字を頼りにして、あまり暗記することに努めなくならないようにである。 [[画像:Dying_gaul.jpg|thumb|right|200px|『[[w:瀕死のガリア人|瀕死のガリア人]]』([[w:en:Dying_Gaul|Dying Gaul]])像(ローマ市の[[w:カピトリーノ美術館|カピトリーノ美術館]])]] *quod fere plerisque accidit, ut **というのも、ほとんど多くの場合に起こることには、 *praesidio litterarum diligentiam in perdiscendo ac memoriam remittant. **文字の助けによって、入念に猛勉強することや暗記することを放棄してしまうのである。 *⑤ In primis hoc volunt persuadere, **とりわけ、彼ら(ドルイド)が説くことを欲しているのは、 *non interire animas, sed ab aliis post mortem transire ad alios, **霊魂は滅びることがないのみならず、死後にある者から別のある者へ乗り移るということである。 **:(訳注:ガッリア人の[[w:輪廻転生|転生信仰]]は、[[w:ピュタゴラス教団|ピュタゴラスの教説]]であると、[[w:シケリアのディオドロス|ディオドロス]]が伝えている<ref>ディオドロス『神代地誌』(前掲、p.408)</ref>。) *atque hoc maxime ad virtutem excitari putant metu mortis neglecto. **これによって(ガッリア人は)死の恐怖に無頓着になって最も武勇へ駆り立てられると(ドルイドは)思っている。 [[画像:Universum.jpg|thumb|right|200px|古代以来の伝統的な世界観における天空と平らな大地。カルデアやギリシアを除けば、丸い地球という観念は知られていなかった。]] *Multa praeterea de sideribus atque eorum motu, **さらに多く、星々とその動きについて、 *de mundi ac terrarum magnitudine, de rerum natura, **天空と大地の大きさについて、物事の本質について、 *de deorum immortalium vi ac potestate **不死の神々の力と支配について、 *disputant et iuventuti tradunt. **研究して、青年たちに教示するのである。 <br> <br> *('''訳注:ドルイドについて''' :ケルト社会の神官・祭司・僧などとされるドルイドについては、おそらくは[[w:ポセイドニオス|ポセイドニオス]]、そしてカエサル、 :および[[w:シケリアのディオドロス|ディオドロス]]<ref>ディオドロス『神代地誌』(前掲、p.410-p.411)</ref>、[[w:ストラボン|ストラボン]]<ref>ストラボン『ギリシア・ローマ世界地誌Ⅰ』(前掲、p.341-p.342)</ref>、ポンポニウス・メラ<ref>ポンポニウス・メラ『世界地理』(前掲、p.549)</ref>などのギリシア人・ローマ人の著述家たちがそれぞれ :書き残しているために同時代や現代に知られている。しかし、本節にもあるように、その秘密主義からか、 :古代ギリシア・ローマの著作にあるほかには、その詳細については不明である。) ===15節=== [[画像:BIATEC_pri_NBS_1.jpg|thumb|right|200px|ケルト系の王ビアテック([[w:en:Biatec|Biatec]])の騎馬像([[w:スロバキア国立銀行|スロバキア国立銀行]])。彼はBC1世紀のケルトの硬貨に刻まれた人物で、現代[[w:スロバキア・コルナ|スロバキアの5コルナ]]硬貨にも刻まれている。]] [[画像:Bige_Musée_de_Laon_050208.jpg|thumb|right|200px|二頭立て二輪馬車([[w:チャリオット|戦車]])に乗るガリア人像(仏・ラン博物館)]] '''ガッリア人の騎士階級について''' *① Alterum genus est equitum. **(ドルイドと並ぶ)もう一つの階級は、[[w:騎士|騎士]]である。 *Hi, cum est usus atque aliquod bellum incidit **彼らは、必要とされ、かつ何らかの戦争が勃発したときには、 *─ quod fere ante Caesaris adventum quotannis accidere solebat, **─ それ(戦争)はカエサルの到来以前にはほとんど毎年のように起こるのが常であり、 *uti aut ipsi iniurias inferrent aut inlatas propulsarent ─, **自身が侵犯行為を引き起こすためか、あるいは引き起こされて撃退するためであったが、─ *omnes in bello versantur, **総勢が戦争に従事した。 *② atque eorum ut quisque est genere copiisque amplissimus, **さらに彼らは、高貴な生まれで財産が非常に大きければ大きいほど、 **:(訳注:ut quisque ~ ita;おのおのが~であればあるほどますます) *ita plurimos circum se ambactos clientesque habet. **自らの周囲に非常に多くの臣下や庇護民たちを侍らせる。 *Hanc unam gratiam potentiamque noverunt. **(騎士たちは)これが信望や権勢(を示すこと)の一つであると認識しているのである。 ===16節=== '''ガッリア人の信仰と生け贄、ウィッカーマン''' *① Natio est omnis Gallorum admodum dedita religionibus, **ガッリア人のすべての部族民は、まったく信仰行為に身を捧げている。 *② atque ob eam causam, **その理由のために、 *qui sunt adfecti gravioribus morbis **非常に重い病気を患った者たち *quique in proeliis periculisque versantur, **および戦闘において危険に苦しめられる者たちは、 *aut pro victimis homines immolant **あるいは<ruby><rb>[[w:生贄|生け贄]]</rb><rp>(</rp><rt>いけにえ</rt><rp>)</rp></ruby>の獣(犠牲獣)の代わりに人間を供えたり、 *aut se immolaturos vovent, **あるいは自らを犠牲にするつもりであると誓願し、 *administrisque ad ea sacrificia druidibus utuntur, **その<ruby><rb>[[w:供犠|供犠]]</rb><rp>(</rp><rt>くぎ</rt><rp>)</rp></ruby>を執り行う者として[[w:ドルイド|ドルイド]]を利用するのである。 *③ quod, pro vita hominis nisi hominis vita reddatur, **というのは(一人の)人間の生命のためには、(もう一人の)人間の生命が償われない限り、 *non posse deorum immortalium numen placari arbitrantur, **不死の神々の<ruby><rb>御霊</rb><rp>(</rp><rt>みたま</rt><rp>)</rp></ruby>がなだめられることができないと思われているからである。 *publiceque eiusdem generis habent instituta sacrificia. **同じような類いの供儀が公けに定められているのである。 [[画像:WickerManIllustration.jpg|thumb|right|310px|柳の枝で編んだ巨人[[w:ウィッカーマン|ウィッカーマン]]([[w:en:Wicker_Man|Wicker Man]])の想像画(18世紀)。この特異な風習は、近代になって人々の興味をかき立て、いくつもの想像画が描かれた<ref>例えば『ケルト人─蘇るヨーロッパ<幻の民>』C.エリュエール著、鶴岡真弓監修、創元社、p.130の挿絵などを参照。</ref>。1973年にはイギリスで映画化され<ref>“[[w:en:The Wicker Man (1973 film)|The Wicker Man]]”はウィッカーマンを題材にした1973年のイギリスのカルト映画作品。</ref>、2006年にはアメリカなどでも映画化された<ref>“[[w:en:The Wicker Man (2006 film)|The Wicker Man]]”は上記作品をリメイクした2006年のアメリカ・カナダ・ドイツの映画作品。</ref>。]] [[画像:Burning_wicker_man_by_Bruce_McAdam.jpg|thumb|right|100px|スコットランドの野外博物館で燃やされるウィッカーマン(2008年)]] '''ウィッカーマン''' *④ Alii immani magnitudine simulacra habent, **ある者たちは、恐ろしく大規模な像を持って、 *quorum contexta viminibus membra vivis hominibus complent; **その柳の枝で編み込まれた肢体を人間たちで満杯にして、 *quibus succensis **それらを燃やして、 *circumventi flamma exanimantur homines. **人々は炎に取り巻かれて息絶えさせられるのである。 *⑤ Supplicia eorum qui in furto aut in latrocinio **窃盗あるいは追い剥ぎに関わった者たちを処刑することにより、 *aut aliqua noxia sint comprehensi, **あるいは何らかの罪状により捕らわれた者たち(の処刑)により、 *gratiora dis immortalibus esse arbitrantur; **不死の神々に感謝されると思っている。 *sed, cum eius generis copia defecit, **しかしながら、その類いの量が欠けたときには、 *etiam ad innocentium supplicia descendunt. **潔白な者たちさえも犠牲にすることに頼るのである。 <br><br> :('''訳注''':このような'''[[w:ウィッカーマン|ウィッカーマン]]'''の供犠については[[w:ストラボン|ストラボン]]も伝えており<ref>ストラボン『ギリシア・ローマ世界地誌Ⅰ』(前掲、p.343)</ref>、 :[[w:人身御供|人身御供]]の種類の一つとして、干し草やたきぎで巨像を作り、その中へあらゆる :家畜・野生動物や人間たちを投げ込んで丸焼きにする習慣があったという。 : また、[[w:シケリアのディオドロス|ディオドロス]]<ref>ディオドロス『神代地誌』(前掲、p.410~p.411)</ref>やストラボンによれば、ドルイドはむしろ'''[[w:予言|予言者]]・[[w:占い|占い師]]''' :であるという。ドルイドが重要な問題について占うときには、供犠される人間の :腹または背中を剣などで刺して、犠牲者の倒れ方、肢体のけいれん、出血の様子 :などを観察して、将来の出来事を占うのだという。) ===17節=== '''ガッリアの神々(ローマ風解釈)''' *① Deum maxime [[w:la:Mercurius_(deus)|Mercurium]] colunt. **(ガッリア人は)神々のうちでとりわけ[[w:メルクリウス|メルクリウス]]を崇拝する。 **:(訳注:メルクリウスは[[w:ローマ神話|ローマ神話]]の神名であり、本節の神名はすべてローマ風解釈である。) *Huius sunt plurima simulacra: **彼の偶像が最も多い。 *hunc omnium inventorem artium ferunt, **(ガッリア人は)彼をすべての技芸の発明者であると言い伝えており、 *hunc viarum atque itinerum ducem, **彼を道および旅の案内者として、 *hunc ad quaestus pecuniae mercaturasque habere vim maximam arbitrantur. **彼が金銭の利得や商取引で絶大な力を持つと思われている。 [[画像:Taranis_Jupiter_with_wheel_and_thunderbolt_Le_Chatelet_Gourzon_Haute_Marne.jpg|thumb|right|200px|ガッリアの雷神タラニス([[w:en:Taranis|Taranis]])の神像([[w:en:National_Archaeological_Museum_(France)|フランス国立考古学博物館]])。雷を司ることからローマ神話のユピテルと同一視された。左手に車輪、右手に稲妻を持っている。]] [[画像:God_of_Etang_sur_Arroux_possible_depiction_of_Cernunnos.jpg|thumb|right|200px|ガッリアの神ケルヌンノス([[w:en:Cernunnos|Cernunnos]])の神像(フランス国立考古学博物館)。]] *Post hunc [[w:la:Apollo|Apollinem]] et [[w:la:Minerva|Martem]] et [[w:la:Iuppiter|Iovem]] et [[w:la:Mars_(deus)|Minervam]]. **彼に続いて、[[w:アポローン|アポロ]]と[[w:マルス (ローマ神話)|マルス]]と[[w:ユーピテル|ユピテル]]と[[w:ミネルウァ|ミネルウァ]]を(ガッリア人は崇拝する)。 *② De his eandem fere, quam reliquae gentes, habent opinionem: **これら(の神々)について、ほかの種族とほぼ同じ見解を持っている。 *Apollinem morbos depellere, **アポロは病気を追い払い、 *Minervam operum atque artificiorum initia tradere, **ミネルウァは工芸や技術の初歩を教示し、 *Iovem imperium caelestium tenere, **ユピテルは天界の統治を司り、 *Martem bella regere. **マルスは戦争を支配する。 *③ Huic, cum proelio dimicare constituerunt, **彼(マルス)には、(ガッリア人が)戦闘で干戈を交えることを決心したときに、 *ea quae bello ceperint, plerumque devovent: **戦争で捕獲したものを、たいていは奉納するものである。 *cum superaverunt, animalia capta immolant **(戦闘で)打ち勝ったときには、捕獲された獣を生け贄に供えて、 *reliquasque res in unum locum conferunt. **残りの物を1か所に運び集める。 *④ Multis in civitatibus harum rerum ex(s)tructos tumulos locis consecratis conspicari licet; **多くの部族において、これらの物が積み上げられた塚を、神聖な地で見ることができる。 *⑤ neque saepe accidit, ut neglecta quispiam religione **何らかの者が信仰を軽視するようなことが、しばしば起こることはない。 *aut capta apud se occultare aut posita tollere auderet, **捕獲されたものを自分のもとに隠すこと、あるいは(塚に)置かれたものをあえて運び去ることは。 *gravissimumque ei rei supplicium cum cruciatu constitutum est. **そんな事には、拷問を伴う最も重い刑罰が決められている。 **:(訳注:最も重い刑罰とは、処刑であると思われる。) <br> :(訳注:'''ローマ風解釈について''' :ガッリアなどケルト文化の社会においては、非常に多くの神々が信仰されており、 :ケルト語による多くの神名が知られており、考古学的にも多くの神像が遺されている。 :しかしながら、これらの神々がどのような性格や権能を持っていたのか、詳しくは判っていない。 :ローマ人は、数多くのケルトの神々をローマ神話の神々の型に当てはめて解釈した。 :[[w:タキトゥス|タキトゥス]]はこれを「[[w:ローマ風解釈|ローマ風解釈]]」[[w:en:Interpretatio_Romana#Roman_version|Interpretatio Romana]] <ref>タキトゥス『ゲルマーニア』43章([[s:la:De_origine_et_situ_Germanorum_(Germania)#XLIII|ラテン語原文]])を参照。</ref>と呼んでいる<ref>『ケルト事典』(前掲)「ローマ風解釈」の項を参照。</ref>。) ===18節=== [[画像:Gaul_god_Sucellus.jpg|thumb|right|200px|ガッリアの神スケッルス([[w:en:Sucellus|Sucellus]])の神像。[[w:冥界|冥界]]の神とされ、ディス・パテルと同一視されたと考えられている。]] '''ガッリア人の時間や子供についての観念''' *① Galli se omnes ab Dite patre prognatos praedicant **ガッリア人は、自分たちは皆、ディス・パテルの末裔であると公言しており、 **:(訳注:ディス・パテル [[w:en:Dis_Pater|Dis Pater]] も前節と同様にローマ神話の神名である。) *idque ab druidibus proditum dicunt. **それは[[w:ドルイド|ドルイド]]たちにより伝えられたと言う。 ;時間の観念 *② Ob eam causam spatia omnis temporis non numero dierum, sed noctium finiunt; **その理由のために、すべての[[w:時間|時間]]の間隔を、[[w:昼|昼間]]の数ではなく、[[w:夜|夜間]](の数)で区切る。 *dies natales et mensum et annorum initia sic observant, ut noctem dies subsequatur. **誕生日も、月や年の初めも、夜間に昼間が続くように注意を払っている。 ;子供についての観念 *③ In reliquis vitae institutis hoc fere ab reliquis differunt, **人生のほかの風習において、以下の点でほかの者たち(種族)からほぼ異なっている。 *quod suos liberos, nisi cum adoleverunt, ut munus militiae sustinere possint, **自分の子供たちが、[[w:徴兵制度|兵役の義務]]を果たすことができるように成長したときでない限り、 *palam ad se adire non patiuntur **公然と自分のところへ近づくことは許されないし、 *filiumque puerili aetate in publico in conspectu patris adsistere turpe ducunt. **少年期の息子が公けに父親の見ているところでそばに立つことは恥ずべきと見なしている。 ===19節=== '''ガッリア人の婚姻と財産・葬儀の制度''' *① Viri, quantas pecunias ab uxoribus dotis nomine acceperunt, **夫は、妻から[[w:持参金|持参金]]の名目で受け取った金銭の分だけ、 *tantas ex suis bonis aestimatione facta cum dotibus communicant. **自分の財産のうちから見積もられた分を、持参金とともに一つにする。 *② Huius omnis pecuniae coniunctim ratio habetur fructusque servantur: **これらのすべての金銭は共同に算定が行なわれて、[[w:利子|利子]]が貯蓄される。 *uter eorum vita superarit, **彼ら2人のいずれかが、人生において生き残ったら、 *ad eum pars utriusque cum fructibus superiorum temporum pervenit. **双方の分がかつての期間の利子とともに(生き残った)その者(の所有)に帰する。 [[画像:Hallstatt_culture_ramsauer.jpg|thumb|right|200px|[[w:ハルシュタット文化|ハルシュタット文化]]の[[w:墳丘墓|墳丘墓]]から発掘された遺骸と[[w:副葬品|副葬品]](19世紀の模写)。ガッリアなどではハルシュタット文化後期から[[w:土葬|土葬]]が普及したが、[[w:ラ・テーヌ文化|ラ・テーヌ文化]]中期から再び[[w:火葬|火葬]]が主流になったと考えられている。]] *③ Viri in uxores, sicuti in liberos, vitae necisque habent potestatem; **夫は、妻において、子供におけるのと同様に、生かすも殺すも勝手である。 *et cum pater familiae inllustriore loco natus decessit, eius propinqui conveniunt **上流身分に生まれた家族の父親が死去したとき、彼の近縁の者たちが集まって、 *et de morte, si res in suspicionem venit, de uxoribus in servilem modum quaestionem habent, **死について、もし疑念が出来したならば、妻について、[[w:奴隷|奴隷]]におけるようなやり方で審問して、 *et si compertum est, igni atque omnibus tormentis excruciatas interficiunt. **もし(疑念が)確認されたならば、火やあらゆる責め道具によって[[w:拷問|拷問]]にかけて誅殺する。 *④ Funera sunt pro cultu Gallorum magnifica et sumptuosa; **[[w:葬儀|葬儀]]は、ガッリア人の生活習慣の割には派手でぜいたくなものである。 *omniaque quae vivis cordi fuisse arbitrantur in ignem inferunt, etiam animalia, **生前に大切であったと思われるもの一切合財を、獣でさえも、火の中に投げ入れる。 *ac paulo supra hanc memoriam servi et clientes, quos ab his dilectos esse constabat, **さらに、より以前のこの記憶では、彼ら(亡者)により寵愛されていたことが知られていた奴隷や庇護民をも、 *iustis funeribus confectis una cremabantur. **慣習による葬儀が成し遂げられたら、一緒に火葬されていたのである。 ===20節=== '''ガッリア部族国家の情報統制''' *① Quae civitates commodius suam rem publicam administrare existimantur, **より適切に自分たちの公儀(=国家体制)を治めると考えられているような部族は、 *habent legibus sanctum, **(以下のように)定められた法度を持つ。 *si quis quid de re publica a finitimis rumore aut fama acceperit, **もし、ある者が公儀に関して近隣の者たちから何らかの噂や風聞を受け取ったならば、 *uti ad magistratum deferat neve cum quo alio communicet, **官吏に報告して、他の者と伝え合ってはならないと。 *② quod saepe homines temerarios atque imperitos falsis rumoribus terreri **というのは、無分別で無知な人間たちはしばしば虚偽の噂に恐れて、 *et ad facinus impelli et de summis rebus consilium capere cognitum est. **罪業に駆り立てられ、重大な事態についての考えを企てると認識されているからである。 *③ Magistratus quae visa sunt occultant, **官吏は、(隠すことが)良いと思われることを隠して、 *quaeque esse ex usu iudicaverunt, multitudini produnt. **有益と判断していたことを、民衆に明らかにする。 *De re publica nisi per concilium loqui non conceditur. **公儀について、集会を通じてでない限り、語ることは認められていない。 ==ゲルマーニアの風習と自然について== ===21節=== '''ゲルマーニア人の信仰と性''' *① Germani multum ab hac consuetudine differunt. **[[w:ゲルマニア|ゲルマーニア]]人はこれに対し、風習が大いに異なっている。 *Nam neque druides habent, qui rebus divinis praesint, neque sacrificiis student. **すなわち、神事を司る[[w:ドルイド|ドルイド]]も持たないし、供犠に熱心でもない。 *② Deorum numero **神々に数えるものとして、 *eos solos ducunt, quos cernunt et quorum aperte opibus iuvantur, Solem et Vulcanum et Lunam, **(彼らが)見分けるものや明らかにその力で助けられるもの、[[w:太陽|太陽]]と[[w:ウォルカヌス|ウォルカヌス]](火の神)と[[w:月|月]]だけを信仰して、 *reliquos ne fama quidem acceperunt. **ほかのものは風聞によってさえも受け入れていない。 **:(訳注:これに対して、[[w:タキトゥス|タキトゥス]]は、ゲルマーニア人はメルクリウスやマルスなどを信仰すると伝えている<ref>タキトゥス『ゲルマーニア』2章・9章を参照</ref>。) *③ Vita omnis in venationibus atque in studiis rei militaris consistit: **すべての人生は、[[w:狩猟|狩猟]]に、および[[w:軍事|軍事]]への執心に依拠しており、 *ab parvulis labori ac duritiae student. **幼時より労役や負担に努める。 *④ Qui diutissime impuberes permanserunt, maximam inter suos ferunt laudem: **最も長く純潔に留まった者は、自分たちの間で最大の賞賛を得る。 *hoc ali staturam, ali vires nervosque confirmari putant. **これによって、ある者には背の高さが、ある者には力と筋肉が強化されると、思っている。 *⑤ Intra annum vero vicesimum feminae notitiam habuisse in turpissimis habent rebus; **20歳にならない内に女を知ってしまうことは、とても恥ずべきことであると見なしている。 *cuius rei nulla est occultatio, **その(性の)事を何ら隠すことはない。 *quod et promiscue in fluminibus perluuntur **というのは、川の中で(男女が)混じって入浴しても、 *et pellibus aut parvis renonum tegimentis utuntur, magna corporis parte nuda. **なめし皮や、小さな毛皮の覆いを用いるが、体の大部分は裸なのである。 ===22節=== '''ゲルマーニア人の土地制度''' *① Agri culturae non student, **(ゲルマーニア人は)[[w:農耕|土地を耕すこと]]に熱心ではなく、 *maiorque pars eorum victus in lacte, caseo, carne consistit. **彼らの大部分は、生活の糧が[[w:乳|乳]]、[[w:チーズ|チーズ]]、[[w:肉|肉]]で成り立っている。 *② Neque quisquam agri modum certum aut fines habet proprios; **何者も、土地を確定した境界で、しかも持続的な領地として、持ってはいない。 *sed magistratus ac principes in annos singulos **けれども、官吏や領袖たちは、各年ごとに、 *gentibus cognationibusque hominum, quique una coierunt, **一緒に集住していた種族や血縁の人々に、 *quantum et quo loco visum est agri adtribuunt **適切と思われる土地の規模と場所を割り当てて、 *atque anno post alio transire cogunt. **翌年には他(の土地)へ移ることを強いるのである。 **:(訳注:[[ガリア戦記 第4巻#1節|第4巻1節]]には、スエービー族の説明として同様の記述がある。) *③ Eius rei multas adferunt causas: **(官吏たちは)その事の多くの理由を説明する。 *ne adsidua consuetudine capti studium belli gerendi agricultura commutent; **(部族民が)[[w:居住|定住]]する習慣にとらわれて、戦争遂行の熱意を土地を耕すことに変えてしまわないように。 *ne latos fines parare studeant, potentioresque humiliores possessionibus expellant; **広大な領地を獲得することに熱心になって、有力者たちが弱者たちを地所から追い出さないように。 *ne accuratius ad frigora atque aestus vitandos aedificent; **寒さや暑さを避けるために(住居を)非常な入念さで建築することがないように。 *ne qua oriatur pecuniae cupiditas, qua ex re factiones dissensionesque nascuntur; **金銭への欲望が増して、その事から派閥や不和が生ずることのないように。 *ut animi aequitate plebem contineant, cum suas quisque opes cum potentissimis aequari videat. **おのおのが自分の財産も最有力者のも同列に置かれていると見ることで、心の平静により民衆を抑えるように。 <br> :(訳注:[[w:ストラボン|ストラボン]]<ref>ストラボン『ギリシア・ローマ世界地誌Ⅰ』(前掲、p.510)</ref>や[[w:タキトゥス|タキトゥス]]<ref>タキトゥス『ゲルマーニア』23章・16章などを参照。26章では農耕についても解説されている。</ref>などの著述家たちも、ゲルマーニアの住民が農耕をせず、 :遊牧民のように移動しながら暮らし、小さな住居に住み、食料を家畜に頼っていると記述している。) ===23節=== '''ゲルマーニア諸部族のあり方''' *① Civitatibus maxima laus est **諸部族にとって、最も称賛されることは、 *quam latissime circum se vastatis finibus solitudines habere. **できる限り広く自分たちの周辺で領土を荒らして荒野に保っておくことである。 *② Hoc proprium virtutis existimant, **以下のことを(自分たちの)武勇の特質と考えている。 *expulsos agris finitimos cedere, **近隣の者たちが土地から追い払われて立ち去ること、 *neque quemquam prope {se} audere consistere; **および、何者も自分たちの近くにあえて定住しないこと、である。 *③ simul hoc se fore tutiores arbitrantur, repentinae incursionis timore sublato. **他方、これにより、予期せぬ襲撃の恐れを取り除いて、自分たちはより安全であろうと思われた。 *④ Cum bellum civitas aut inlatum defendit aut infert, **部族に戦争がしかけられて防戦したり、あるいはしかけたりしたときには、 *magistratus, qui ei bello praesint, ut vitae necisque habeant potestatem, deliguntur. **その戦争を指揮して、生かすも殺すも勝手な権力を持つ将官が選び出される。 *⑤ In pace nullus est communis magistratus, **平時においては、(部族に)共通の将官は誰もいないが、 *sed principes regionum atque <u>[[wikt:en:pagus#Latin|pagorum]]</u> inter suos ius dicunt controversiasque minuunt. **地域や<u>郷</u>の領袖たちが、身内の間で判決を下して、訴訟ごとを減らす。 **:<span style="color:#009900;font-family:Times New Roman;">(訳注:''pagus'' (郷) はここでは、部族の領土の農村区画を指す行政用語<ref name="pagus"/>。)</span> *⑥ Latrocinia nullam habent infamiam, quae extra fines cuiusque civitatis fiunt, **それぞれの部族の領土の外で行なう略奪のことは、何ら恥辱とは見なしていない。 *atque ea iuventutis exercendae ac desidiae minuendae causa fieri praedicant. **さらに、それ(略奪)は、青年たちを訓練することや、怠惰を減らすことのために行なわれる、と公言している。 *⑦ Atque ubi quis ex principibus in concilio dixit **そして、領袖たちのうちのある者が(次のように)言うや否や、 *se ducem fore, qui sequi velint, profiteantur, **《自分が(略奪の)引率者となるから、追随したい者は申し出るように》と(言うや否や)、 *consurgunt ii qui et causam et hominem probant, suumque auxilium pollicentur **(略奪の)口実にも(引率する)人物にも賛同する者は立ち上がって、自らの支援を約束して、 *atque ab multitudine conlaudantur: **群衆から大いに誉められる。 *⑧ qui ex his secuti non sunt, **これら(約束した者)のうちで(略奪に)追随しない者は、 *in desertorum ac proditorum numero ducuntur, **逃亡兵や裏切り者と見なされて、 *omniumque his rerum postea fides derogatur. **その後は、彼らにとってあらゆる事の信頼が(皆から)拒まれる。 *⑨ Hospitem violare fas non putant; **客人に暴行することは道理に適うとは思ってはいない。 *qui quacumque de causa ad eos venerunt, **彼ら(ゲルマーニア人)のところへ理由があって来た者(=客人)は誰であれ、 *ab iniuria prohibent, sanctos habent, **無法行為から防ぎ、尊ぶべきであると思っている。 *hisque omnium domus patent victusque communicatur. **彼ら(客人)にとってすべての者の家は開放されており、生活用品は共有される。 **:(訳注:客人への接待ぶりについては、[[w:タキトゥス|タキトゥス]]<ref>タキトゥス『ゲルマーニア』21章を参照。</ref>も伝えている。) ===24節=== [[画像:Celts.svg|thumb|right|200px|ケルト文化の広がり(BC800年~BC400年頃)。ケルト系部族の優越は、[[w:鉄器|鉄器]]文化の発達などによると考えられている。]] [[画像:Mappa_di_Eratostene.jpg|thumb|right|200px|[[w:エラトステネス|エラトステネス]]の地理観を再現した世界地図(19世紀)。左上に「Orcynia Silva(オルキュニアの森)」とある。]] [[画像:Hallstatt_LaTene.png|thumb|right|200px|[[w:ハルシュタット文化|ハルシュタット文化]]期と[[w:ラ・テーヌ文化|ラ・テーヌ文化]]期におけるケルト系部族の分布。右上にウォルカエ族(Volcae)やボイイ族(Boii)の名が見える。ボイイ族が居住していた地域はボイオハエムム(Boihaemum)と呼ばれ、[[w:ボヘミア|ボヘミア]](Bohemia)として現在に残る。]] '''ゲルマーニア人とガッリア人''' *① Ac fuit antea tempus, **かつてある時代があって、 *cum Germanos Galli virtute superarent, **そのとき、[[w:ゲルマニア|ゲルマーニア]]人を[[w:ガリア|ガッリア]]人が武勇で優っており、 *ultro bella inferrent, propter hominum multitudinem agrique inopiam **人間の多さと土地の欠乏のために(ガッリア人は)自発的に戦争をしかけて、 *trans Rhenum colonias mitterent. **レーヌス(=[[w:ライン川|ライン川]])の向こう側へ入植者たちを送り込んでいた。 *② Itaque ea quae fertilissima Germaniae sunt loca circum Hercyniam silvam, **[[w:ヘルキュニア|ヘルキュニア]]の森の周辺のゲルマーニアで最も肥沃な地を、 *quam Eratostheni et quibusdam Graecis fama notam esse video, **それを[[w:エラトステネス|エラトステネス]]や[[w:ギリシア人|ギリシア人]]のある者たちも風聞により知っていたと私は見出して、 *quam illi Orcyniam appellant, **それを彼らはオルキュニアと呼んでいるが、 *Volcae Tectosages occupaverunt atque ibi consederunt; **(その地を)ウォルカエ族系のテクトサゲス族が占領して、そこに定住していた。 *③ quae gens ad hoc tempus his sedibus sese continet **その種族は、この時代までこの居場所に留まっており、 *summamque habet iustitiae et bellicae laudis opinionem. **公正さと戦いの称賛で最高の評判を得ている。 *④ Nunc quod in eadem inopia, egestate, patientia qua Germani permanent, **今も、窮乏や貧困を、ゲルマーニア人が持ちこたえているのと同じ忍耐をもって、 *eodem victu et cultu corporis utuntur; **同じ食物および体の衣服を用いている。 *⑤ Gallis autem provinciarum propinquitas et transmarinarum rerum notitia **これに対して、ガッリア人にとって(ローマの)属州に近接していること、および海外のものを知っていることは、 *multa ad copiam atque usus largitur, **富や用品の多くが供給されている。 *paulatim adsuefacti superari multisque victi proeliis **(ガッリア人は)しだいに圧倒されることや多くの戦闘で打ち負かされることに慣らされて、 *ne se quidem ipsi cum illis virtute comparant. **(ガッリア人)自身でさえも彼ら(ゲルマーニア人)と武勇で肩を並べようとはしないのである。 <br> :('''訳注''':本節の①項については、[[w:タキトゥス|タキトゥス]]が著書『[[w:ゲルマニア (書物)|ゲルマーニア]]』28章([[s:la:De_origine_et_situ_Germanorum_(Germania)#XXVIII|原文]])において、次のように言及している。 :''Validiores olim Gallorum res fuisse summus auctorum divus Iulius tradit; '' :かつてガッリア人の勢力がより強力であったことは、最高の証言者である神君ユリウス(・カエサル)も伝えている。 :''eoque credibile est etiam Gallos in Germaniam transgressos:'' :それゆえに、ガッリア人でさえもゲルマーニアに渡って行ったと信ずるに値するのである。) ===25節=== '''ヘルキュニアの森林地帯''' *① Huius Hercyniae silvae, quae supra demonstrata est, latitudo **前に述べたヘルキュニアの森の幅は、 *novem dierum iter expedito patet: **軽装の旅で9日間(かかるだけ)広がっている。 *non enim aliter finiri potest, **なぜなら(ゲルマーニア人は)他に境界を定めることができないし、 *neque mensuras itinerum noverunt. **道のりの測量というものを知っていないのである。 [[画像:FeldbergPanorama.jpg|thumb|center|1000px|ヘルキュニアの森林地帯(ドイツ南西部、[[w:シュヴァルツヴァルト|シュヴァルツヴァルトの森]]の最高峰フェルドベルク山 [[w:en:Feldberg_(Black Forest)|Feldberg]] の眺望)]] *② Oritur ab Helvetiorum et Nemetum et Rauracorum finibus **(その森は)[[w:ヘルウェティイ族|ヘルウェティイ族]]とネメテス族とラウラキ族の領土から発しており、 **:(訳注:これはライン川東岸に沿って南北に長い現在の[[w:シュヴァルツヴァルト|シュヴァルツヴァルトの森]]のことである。) *rectaque fluminis [[w:la:Danubius|Danubii]] regione **ダヌビウス川に沿って真っ直ぐに(流れ)、 **:(訳注:ダヌビウス Danubius はダヌウィウス Danuvius とも呼ばれ、現在の[[w:ドナウ川|ドナウ川]]である。) *pertinet ad fines Dacorum et Anartium; **[[w:ダキア人|ダキ族]]やアナルテス族の領土へ至る。 **:(訳注:これは[[w:ダキア|ダキア]] [[w:la:Dacia|Dacia]] すなわち現在の[[w:ルーマニア|ルーマニア]]辺りの地域である。) *③ hinc se flectit sinistrorsus diversis ab flumine regionibus **ここ(ダヌビウス川)から(森は)左方へ向きを変えて、川の地域からそれて、 **:(訳注:川が南へ折れるのとは逆に、森は北へそれて[[w:エルツ山地|エルツ山地]]を通って[[w:カルパティア山脈|カルパティア山脈]]に至ると考えられている<ref>タキトゥス『ゲルマーニア』泉井久之助訳注、岩波文庫、p.131-132の注などを参照</ref>。) *multarumque gentium fines propter magnitudinem attingit; **(森の)大きさのために、多くの種族の領土に接しているのである。 *④ neque quisquam est huius Germaniae, qui se aut adisse ad initium eius silvae dicat, **その森の(東の)端緒へ訪れたと言う者は、こちら(西側)の[[w:ゲルマニア|ゲルマーニア]]に属する者では誰もいないし、 *cum dierum iter LX processerit, **60日間の旅で進んでも(いないのであるが)、 *aut, quo ex loco oriatur, acceperit: **あるいは(森が)どの場所から生じているか把握した(者もいないのである)。 *⑤ multaque in ea genera ferarum nasci constat, quae reliquis in locis visa non sint; **それ(=森)の中には、ほかの地では見られない野獣の多くの種類が生息していることが知られている。 *ex quibus quae maxime differant ab ceteris et memoriae prodenda videantur, **それらのうちで、ほかの(地の)ものと大きく異なったものは、記録で伝えるべきものであり、 *haec sunt. **以下のものである。 ===26節=== [[画像:Rentier fws 1.jpg|thumb|right|200px|[[w:トナカイ|トナカイ]]([[w:la:Tarandrus|Rangifer tarandus]])。発達した枝角を持ち、雌雄ともに角があるという特徴は本節の説明に合致している。が、角が一本ということはないし、野生のトナカイは少なくとも現在では極北の地にしか住まない。]] '''ヘルキュニアの野獣①''' *① Est [[w:la:Bos|bos]] [[w:la:Cervus|cervi]] figura, **雄[[w:シカ|鹿]]の姿形をした[[w:ウシ|牛]]がいる。 *cuius a media fronte inter aures unum [[w:la:Cornu|cornu]] existit **それの両耳の間の額の真ん中から一つの角が出ており、 *excelsius magisque derectum his, quae nobis nota sunt, cornibus; **我々(ローマ人)に知られている角よりも非常に高くて真っ直ぐである。 *ab eius summo sicut palmae ramique late diffunduntur. **その先端部から、手のひらや枝のように幅広く広がっている。 *Eadem est feminae marisque natura, **雌と雄の特徴は同じであり、 *eadem forma magnitudoque cornuum. **角の形や大きさも同じである。 <br> :('''訳注''':カエサルによる本節の記述は[[w:ユニコーン|ユニコーン]](一角獣)の伝説に :結び付けられている。しかし本節における発達した枝角の説明は、むしろ :[[w:トナカイ|トナカイ]]や[[w:ヘラジカ|ヘラジカ]]のような獣を想起させる。) ===27節=== [[画像:Bigbullmoose.jpg|thumb|right|250px|[[w:ヘラジカ|ヘラジカ]](Alces alces)。<br>発達した枝角と大きな体を持ち、名称以外は本節の説明とまったく合致しない。<br>しかしながら、[[w:ガイウス・プリニウス・セクンドゥス|大プリニウス]]の『[[w:博物誌|博物誌]]』第8巻(16章・39節)には、[[w:アクリス|アクリス]]([[w:en:Achlis|achlis]])という一見ヘラジカ(alces)のような奇獣が紹介され、その特徴は本節②項以下のカエサルの説明とほぼ同じであることが知られている。]] [[画像:Gressoney-Saint-Jean-Museo-IMG 1824.JPG|thumb|right|250px|[[w:ノロジカ|ノロジカ]](Capreolus capreolus)。<br>ヨーロッパに広く分布する小鹿で、まだら模様で山羊にも似ているので、本節①項の説明と合致する。しかし、関節はあるし、腹ばいにもなる。]] '''ヘルキュニアの野獣②''' *① Sunt item, quae appellantur [[w:la:Alces|alces]]. **アルケスと呼ばれるものもいる。 **:(訳注:アルケス alces とは[[w:ヘラジカ|ヘラジカ]](オオシカ)を指す単語であるが本節の説明と矛盾する。) *Harum est consimilis [[w:la:Capra|capris]] figura et varietas pellium, **これらの姿形や毛皮のまだらは雄[[w:ヤギ|山羊]]に似ている。 *sed magnitudine paulo antecedunt **が、(山羊を)大きさで少し優っており、 *mutilaeque sunt cornibus **角は欠けていて、 *et crura sine nodis articulisque habent. **脚部には関節の類いがない。 **:(訳注:nodus も articulus も関節の類いを意味する) *② Neque quietis causa procumbunt **休息のために横たわらないし、 *neque, si quo adflictae casu conciderunt, **もし何か不幸なことで偶然にも倒れたならば、 *erigere sese aut sublevare possunt. **自らを起こすことも立ち上げることもできない。 *③ His sunt arbores pro cubilibus; **これらにとって木々は寝床の代わりである。 *ad eas se adplicant **それら(の木々)へ自らを寄りかからせて、 *atque ita paulum modo reclinatae quietem capiunt. **こうして少しだけもたれかかって休息を取るのである。 *④ Quarum ex vestigiis **それらの足跡から *cum est animadversum a venatoribus, quo se recipere consuerint, **(鹿が)どこへ戻ることを常としているかを狩人によって気付かれたときには、 *omnes eo loco aut ab radicibus subruunt aut accidunt arbores, **その地のすべての木々を(狩人は)根から倒すか、あるいは傷つけて、 *tantum ut summa species earum stantium relinquatur. **それらの(木々の)いちばん(外側)の見かけが、立っているかのように残して置かれる。 *⑤ Huc cum se consuetudine reclinaverunt, **そこに(鹿が)習性によってもたれかかったとき、 *infirmas arbores pondere adfligunt atque una ipsae concidunt. **弱った木々を重みで倒してしまい、自身も一緒に倒れるのである。 ===28節=== [[画像:Wisent.jpg|thumb|right|250px|[[w:ヨーロッパバイソン|ヨーロッパバイソン]]([[w:la:Bison|Bison bonasus]])。<br>かつてヨーロッパに多数生息していた野牛で、相次ぐ乱獲により野生のものは20世紀初頭にいったん絶滅したが、動物園で繁殖させたものを再び野生に戻す試みが行なわれている。]] [[画像:Muybridge Buffalo galloping.gif|thumb|right|200px|疾走するバイソン]] [[画像:Drinkhoorn_roordahuizum.JPG|thumb|right|200px|酒杯として用いられた野獣の角。銀で縁取りされている。]] '''ヘルキュニアの野獣③''' *③ Tertium est genus eorum, qui uri appellantur. **第3のものは、野牛と呼ばれる種類である。 *Hi sunt magnitudine paulo infra [[w:la:Elephantidae|elephantos]], **これらは、大きさで少し[[w:ゾウ|象]]に劣るが、 *specie et colore et figura [[w:la:Taurus|tauri]]. **見かけと色と姿形は雄[[w:ウシ|牛]]である。 *② Magna vis eorum est et magna velocitas, **それらの力は大きく、(動きも)とても速く、 *neque homini neque ferae, quam conspexerunt, parcunt. **人間でも野獣でも、見かけたものには容赦しない。 *Hos studiose foveis captos interficiunt. **(ゲルマーニア人は)これらを熱心に落とし穴で捕らえたものとして殺す。 *③ Hoc se labore durant adulescentes **この労苦により青年たちを鍛え、 *atque hoc genere venationis exercent, **[[w:狩猟|狩猟]]のこの類いで鍛錬するのであり、 *et qui plurimos ex his interfecerunt, **これら(の野牛)のうちから最も多くを殺した者は、 *relatis in publicum [[w:la:Cornu|cornibus]], quae sint testimonio, **証拠になるための[[w:角|角]]を公の場に持参して、 *magnam ferunt laudem. **大きな賞賛を得るのである。 *④ Sed adsuescere ad homines et mansuefieri ne parvuli quidem excepti possunt. **けれども(野牛は)幼くして捕らえられてさえも、人間に慣れ親しんで飼い慣らされることはできない。 *⑤ Amplitudo cornuum et figura et species multum a nostrorum boum cornibus differt. **角の大きさや形や見かけは、我々(ローマ人)の牛の角とは大いに異なる。 *⑥ Haec studiose conquisita ab labris argento circumcludunt **これらは熱心に探し求められて、縁を[[w:銀|銀]]で囲って、 *atque in amplissimis epulis pro poculis utuntur. **とても贅沢な祝宴において[[w:盃|杯]]として用いられるのである。 ==対エブロネス族追討戦(1)== ===29節=== '''ゲルマーニアから撤兵、対アンビオリクス戦へ出発''' *① Caesar, postquam per Ubios exploratores comperit Suebos sese in silvas recepisse, **カエサルは、ウビイー族の偵察者たちを通じてスエービー族が森に撤退したことを確報を受けた後で、 **:(訳注:[[#10節|10節]]によれば、バケニス Bacenis の森。[[#コラム「スエービー族とカッティー族・ケールスキー族・ウビイー族について|既述]]のように、スエービー族とはカッティー族 [[w:en:Chatti|Chatti]] と考えられる。) *inopiam frumenti veritus, **糧食の欠乏を恐れて、 *quod, ut supra demonstravimus, minime omnes Germani agri culturae student, **というのは、前に説明したように、ゲルマーニア人は皆が土地を耕すことに決して熱心でないので、 **:(訳注:[[#22節|22節]]を参照。耕地がなければ、ローマ軍は穀物の現地調達ができない。) *constituit non progredi longius; **より遠くへ前進しないことを決めた。 *② sed, ne omnino metum reditus sui barbaris tolleret **けれども、自分たち(ローマ軍)が戻って来る恐れを蛮族からまったく取り去ってしまわないように、 *atque ut eorum auxilia tardaret, **かつ、彼ら(ゲルマーニア人)の(ガッリア人への)支援を遅らせるように、 *reducto exercitu partem ultimam pontis, quae ripas Ubiorum contingebat, **ウビイー族側の岸(=レーヌス川東岸)につなげていた橋の最後の部分に軍隊を連れ戻して、 *in longitudinem pedum ducentorum rescindit **(橋を)長さ200[[w:ペース (長さ)|ペース]](=約60m)切り裂いて、 *③ atque in extremo ponte turrim tabulatorum quattuor constituit **橋の先端のところに4層の櫓を建てて、 *praesidiumque cohortium duodecim pontis tuendi causa ponit **12個[[w:コホルス|歩兵大隊]]の守備隊を橋を防護するために配置して、 *magnisque eum locum munitionibus firmat. **その場所を大きな城砦で固めた。 *Ei loco praesidioque C.(Gaium) Volcacium Tullum adulescentem praeficit. **その場所と守備隊を青年ガイウス・ウォルカキウス・トゥッルスに指揮させた。 **:(訳注:元執政官 [[w:en:Lucius_Volcatius_Tullus_(consul_66_BC)|Lucius Volcatius Tullus]] に対して、青年 adulescentem と区別したのであろう。 **:ウォルカキウス Volcacium の綴りは、写本により相異する。) *④ Ipse, cum maturescere frumenta inciperent, **(カエサル)自身は、穀物が熟し始めたので、 *ad bellum [[w:la:Ambiorix|Ambiorigis]] profectus per Arduennam silvam, **[[w:アンビオリクス|アンビオリクス]]との戦争へ、アルドゥエンナの森を通って進発した。 **:(訳注:アルドゥエンナの森については、[[ガリア戦記 第5巻#3節|第5巻3節]]ですでに説明されている。) *quae est totius Galliae maxima **それ(=森)は全ガッリアで最も大きく、 *atque ab ripis Rheni finibusque Treverorum ad Nervios pertinet **レヌス(=[[w:ライン川|ライン川]])の岸およびトレーウェリー族の境界から、[[w:ネルウィイ族|ネルウィイ族]](の領土)へ及んでおり、 *milibusque amplius quingentis in longitudinem patet, **長さは500ローママイル(=約740km)より大きく広がっている。 *L.(Lucium) Minucium Basilum cum omni equitatu praemittit, **ルキウス・ミヌキウス・バスィルスをすべての騎兵隊とともに先遣した。 *si quid celeritate itineris atque opportunitate temporis proficere possit; **行軍の迅速さと時間の有利さによって、何かを得られるかどうかということである。 *⑤ monet, ut ignes in castris fieri prohibeat, ne qua eius adventus procul significatio fiat: **野営において火を生じることを禁じるように、何事かにより遠くから彼の到来の予兆を生じないように、戒めた。 *sese confestim subsequi dicit. **(カエサル)自らは、ただちに後から続くと言った。 ===30節=== '''アンビオリクスがバスィリスのローマ騎兵から逃れる''' *① Basilus, ut imperatum est, facit. **バスィルスは、命令されたように、行なった。 *Celeriter contraque omnium opinionem confecto itinere **速やかに、かつ皆の予想に反して、行軍を成し遂げて、 *multos in agris inopinantes deprehendit: **(城市でない)土地にいた気付かないでいる多くの者を捕らえた。 *eorum indicio ad ipsum Ambiorigem contendit, quo in loco cum paucis equitibus esse dicebatur. **彼らの申し立てにより、[[w:アンビオリクス|アンビオリクス]]その人がわずかな騎兵たちとともにいると言われていた場所に急いだ。 *② Multum cum in omnibus rebus, tum in re militari potest Fortuna. **あらゆる事柄においても、とりわけ軍事においても、運命(の女神)が大いに力がある。 *Nam magno accidit casu, **実際のところ、大きな偶然により生じたのは、 *ut in ipsum incautum etiam atque imparatum incideret, **(アンビオリクス)自身でさえも油断していて不用意なところに(バスィルスが)遭遇したが、 *priusque eius adventus ab omnibus videretur, quam fama ac nuntius adferretur: **彼の到来が(ガッリア勢の)皆により見られたのが、風聞や報告により知らされるよりも早かったのである。 *sic magnae fuit fortunae **同様に(アンビオリクスにとって)大きな幸運に属したのは、 *omni militari instrumento, quod circum se habebat, erepto, **自らの周りに持っていたすべての武具を奪われて、 *raedis equisque comprehensis **四輪馬車や馬を差し押さえられても、 *ipsum effugere mortem. **(アンビオリクス)自身は死を逃れたことである。 *③ Sed hoc quoque factum est, **しかし、以下のこともまた起こった。 *quod aedificio circumdato silva, **(アンビオリクスの)館が森で取り巻かれており、 *─ ut sunt fere domicilia Gallorum, qui vitandi aestus causa **─ ガッリア人の住居はほぼ、暑さを避けることのために、 *plerumque silvarum atque fluminum petunt propinquitates ─, **たいてい森や川の近接したところに求めるのであるが ─ *comites familiaresque eius angusto in loco paulisper equitum nostrorum vim sustinuerunt. **彼の従者や郎党どもが、狭い場所でしばらく、我が方(ローマ勢)の騎兵の力を持ちこたえたのだ。 *④ His pugnantibus illum in equum quidam ex suis intulit: **彼らが戦っているときに、彼(アンビオリクス)を配下のある者が馬に押し上げて、 *fugientem silvae texerunt. **逃げて行く者(アンビオリクス)を森が覆い隠した。 *Sic et ad subeundum periculum et ad vitandum multum Fortuna valuit. **このように(アンビオリクスが)危険に突き進んだことや避けられたことに対して、運命(の女神)が力をもったのである。 ===31節=== '''エブロネス族の退避、カトゥウォルクスの最期''' *① [[w:la:Ambiorix|Ambiorix]] copias suas iudicione non conduxerit, quod proelio dimicandum non existimarit, **[[w:アンビオリクス|アンビオリクス]]は、戦闘で争闘するべきとは考えていなかったので、自らの判断で軍勢を集めなかったのか、 *an tempore exclusus et repentino equitum adventu prohibitus, **あるいは、時間に阻まれ、予期せぬ[[w:騎兵|騎兵]]の到来に妨げられて、 *cum reliquum exercitum subsequi crederet, **(ローマ勢の)残りの軍隊(=軍団兵)が後続して来ることを信じたためなのか、 *dubium est. **不確かなことである。 *② Sed certe dimissis per agros nuntiis sibi quemque consulere iussit. **けれども、確かに領地を通じて伝令を四方に遣わして、おのおのに自らを助けることを命じた。 *Quorum pars in Arduennam silvam, pars in continentes paludes profugit; **それらの者たち(領民)のある一部はアルドゥエンナの森に、一部は絶え間ない沼地に退避した。 *③ qui proximi Oceano fuerunt, **<ruby><rb>大洋<span style="color:#009900;">〔[[w:大西洋|大西洋]]〕</span></rb><rp>(</rp><rt>オーケアヌス</rt><rp>)</rp></ruby>にとても近いところにいた者たちは、 *hi insulis sese occultaverunt, quas aestus efficere consuerunt: **[[w:潮汐|満潮]]が形成するのが常であった島々に身を隠した。 [[画像:Taxus baccata MHNT.jpg|thumb|right|300px|[[w:ヨーロッパイチイ|ヨーロッパイチイ]]([[w:en:Taxus baccata|Taxus baccata]])<br>欧州などに広く自生するイチイ科の[[w:針葉樹|針葉樹]]。赤い果実は食用で甘い味だが、種子には[[w:タキシン|タキシン]](taxine)という[[w:アルカロイド|アルカロイド]]系の毒物が含まれており、種子を多量に摂れば[[w:痙攣|けいれん]]を起こして[[w:呼吸困難|呼吸困難]]で死に至る。<br>他方、[[w:タキサン|タキサン]](taxane)という成分は[[w:抗がん剤|抗がん剤]]などの[[w:医薬品|医薬品]]に用いられる。]] *④ multi ex suis finibus egressi **多くの者たちは、自分たちの領土から出て行って、 *se suaque omnia alienissimis crediderunt. **自分たちとその一切合財をまったく異邦の者たちに委ねた。 *⑤Catuvolcus, rex dimidiae partis Eburonum, **[[w:カトゥウォルクス|カトゥウォルクス]]は、[[w:エブロネス族|エブロネス族]]の半分の地方の王であり、 *qui una cum Ambiorige consilium inierat, **アンビオリクスと一緒に(カエサルに造反する)企てに取りかかった者であるが、 **:(訳注:[[ガリア戦記 第5巻#26節|第5巻26節]]を参照。) *aetate iam confectus, cum laborem aut belli aut fugae ferre non posset, **もはや老衰していたので、戦争の労苦、あるいは逃亡の労苦に耐えることができなかったので、 **:(訳注:aetate confectus 老衰した) *omnibus precibus detestatus Ambiorigem, qui eius consilii auctor fuisset, **その企ての張本人であったアンビオリクスをあらゆる呪詛のことばで呪って、 *taxo, cuius magna in Gallia Germaniaque copia est, se exanimavit. **[[w:ガリア|ガッリア]]や[[w:ゲルマニア|ゲルマーニア]]に大量にあった[[w:イチイ属|イチイ]]によって、息絶えたのであった。 ===32節=== '''ゲルマーニア部族の弁明、アドゥアトゥカに輜重を集める''' *① Segni Condrusique, ex gente et numero Germanorum, **[[w:ゲルマニア|ゲルマーニア]]人の種族や集団のうち、[[w:セグニ族|セグニ族]]と[[w:コンドルスィ族|コンドルスィ族]]は、 *qui sunt inter Eburones Treverosque, **[[w:エブロネス族|エブロネス族]]とトレーウェリー族の間にいたが、 *legatos ad Caesarem miserunt oratum, **カエサルのところへ嘆願するために使節たちを遣わした。 *ne se in hostium numero duceret **自分たちを敵として見なさないように、と。 *neve omnium Germanorum, qui essent citra Rhenum, unam esse causam iudicaret; **しかも、レーヌス(=[[w:ライン川|ライン川]])のこちら側にいるゲルマーニア人すべての事情は1つであると裁断しないように、と。 *nihil se de bello cogitavisse, nulla Ambiorigi auxilia misisse. **自分たちは、戦争についてまったく考えたことはないし、[[w:アンビオリクス|アンビオリクス]]に何ら援軍を派遣したことはない、と。 *② Caesar explorata re quaestione captivorum, **カエサルは捕虜を審問することによってその事を探り出すと、 *si qui ad eos Eburones ex fuga convenissent, **もし彼らのところへ逃亡しているエブロネス族の者たちの誰かが訪れたならば、 *ad se ut reducerentur, imperavit; **自分(カエサル)のところへ連れ戻されるようにと、命令した。 *si ita fecissent, fines eorum se violaturum negavit. **もしそのように行なったならば、彼らの領土を自分(カエサル)が侵害することはないであろうと主張した。 *③ Tum copiis in tres partes distributis **それから、軍勢を3方面に分散して、 *impedimenta omnium legionum Aduatucam contulit. **すべての軍団の[[w:輜重|輜重]]を[[w:アドゥアトゥカ|アドゥアトゥカ]]に運び集めた。 **:(訳注:アドゥアトゥカ Aduatuca の表記は、写本によってはアトゥアトゥカ Atuatuca となっている。現在の[[w:トンゲレン|トンゲレン市]]。) *④ Id castelli nomen est. **それは、城砦の名前である。 *Hoc fere est in mediis Eburonum finibus, **これは、エブロネス族の領土のほぼ真ん中にあり、 *ubi Titurius atque Aurunculeius hiemandi causa consederant. **そこには、[[w:クィントゥス・ティトゥリウス・サビヌス|ティトゥリウス(・サビヌス)]]と[[w:ルキウス・アウルンクレイウス・コッタ|アウルンクレイウス(・コッタ)]]が越冬するために陣取っていた。 *⑤ Hunc cum reliquis rebus locum probabat, **(カエサルは)この場所を、ほかの事柄によっても是認したし、 *tum quod superioris anni munitiones integrae manebant, ut militum laborem sublevaret. **またとりわけ前年の防備が損なわれずに存続していたので、兵士の労苦を軽減するためでもある。 *Praesidio impedimentis legionem quartamdecimam reliquit, **(全軍の)輜重の守備隊として第14軍団を(そこに)残した。 *unam ex his tribus, quas proxime conscriptas ex Italia traduxerat. **(それは)最近にイタリアから徴集されたものとして連れて来られた3個(軍団)のうちの1個である。 **:(訳注:[[#1節|1節]]を参照。イタリア Italia とはカエサルが総督であった[[w:ガリア・キサルピナ|ガッリア・キサルピーナ]]のことであろう。) *Ei legioni castrisque Q.(Quintum) Tullium Ciceronem praeficit ducentosque equites ei attribuit. **その[[w:ローマ軍団|軍団]]と陣営には[[w:クィントゥス・トゥッリウス・キケロ|クィントゥス・トゥッリウス・キケロ]]を指揮者として、200騎の騎兵を彼に割り当てた。 ===33節=== '''軍勢をカエサル、ラビエヌス、トレボニウスの三隊に分散''' *① Partito exercitu **軍隊を分配して、 *T.(Titum) Labienum cum legionibus tribus ad Oceanum versus **[[w:ティトゥス・ラビエヌス|ティトゥス・ラビエヌス]]には、3個[[w:ローマ軍団|軍団]]とともに、<ruby><rb>大洋<span style="color:#009900;">〔[[w:大西洋|大西洋]]〕</span></rb><rp>(</rp><rt>オーケアヌス</rt><rp>)</rp></ruby>の方へ向けて、 *in eas partes, quae Menapios attingunt, proficisci iubet; **[[w:メナピイ族|メナピイ族]]に接する地方に出発することを命じた。 *② C.(Gaium) Trebonium cum pari legionum numero **[[w:ガイウス・トレボニウス|ガイウス・トレボニウス]]には、軍団の同数とともに、 *ad eam regionem, quae Aduatucis adiacet, depopulandam mittit; **[[w:アドゥアトゥキ族|アドゥアトゥキ族]]に隣接する領域へ、荒らすために派遣した。 [[画像:Locatie-Maas-3.png|thumb|right|200px|[[w:ベルギー|ベルギー]]周辺の地図。図の左側を[[w:スヘルデ川|スヘルデ川]]が、右側を[[w:マース川|マース川]]が流れているため、両河川は離れており、カエサルがどの地に言及しているのかはわからない。]] [[画像:Schelde_4.25121E_51.26519N.jpg|thumb|right|200px|ベルギーの[[w:アントウェルペン|アントウェルペン]]周辺を流れる[[w:スヘルデ川|スヘルデ川]]河口付近の[[w:衛星画像|衛星画像]]。ラビエヌスが向かったメナピイ族に接する地方である。]] *③ ipse cum reliquis tribus ad flumen [[w:la:Scaldis|Scaldim]], quod influit in [[w:la:Mosa|Mosam]], **(カエサル)自身は、残りの3個(軍団)とともに、モサ(川)に流れ込むスカルディス川のところへ、 **:(訳注:スカルディス Scaldis は現在の[[w:スヘルデ川|スヘルデ川]] Schelde で、フランス北部からベルギー、オランダへ流れている。 **:モサ川 Mosa すなわち現在の[[w:マース川|マース川]] Maas とは運河でつながるが、当時の関係およびカエサルの目的地は不詳。) *extremasque Arduennae partes ire constituit, **かつ[[w:アルデンヌ|アルドゥエンナ]](の森林)の外縁の地方へ行軍することを決めた。 *quo cum paucis equitibus profectum Ambiorigem audiebat. **そこへは、アンビオリクスがわずかな騎兵たちとともに出発したと聞いていたのだ。 *④ Discedens post diem septimum sese reversurum confirmat; **(カエサルは陣営を)離れるに当たって、7日目の後(=6日後)に自分は引き返して来るであろうと断言した。 *quam ad diem ei legioni, quae in praesidio relinquebatur, deberi frumentum sciebat. **その当日には、守備に残される軍団にとって糧食が必要とされることを(カエサルは)知っていたのだ。 *⑤ Labienum Treboniumque hortatur, **(カエサルは)ラビエヌスとトレボニウスを(以下のように)鼓舞した。 *si rei publicae commodo facere possint, **もし(ローマ軍全体の)公務のために都合良く行動することができるならば、 *ad eum diem revertantur, **その日には戻って、 *ut rursus communicato consilio exploratisque hostium rationibus **再び(互いの)考えを伝達して、敵たちの作戦を探り出し、 *aliud initium belli capere possint. **次なる戦争の端緒を捉えようではないか、と。 <br> :('''訳注:カエサル麾下の軍団配分について''' :[[ガリア戦記 第5巻#8節|第5巻8節]]の記述によれば、ブリタンニアへ2度目の遠征をする前(BC54年)のカエサルは少なくとも8個軍団と騎兵4000騎を :指揮していた。[[ガリア戦記 第5巻#24節|第5巻24節]]によれば、帰還後は8個軍団および軍団から離れた5個[[w:コホルス|歩兵大隊]]を指揮していたが、 :アンビオリクスによる[[w:アドゥアトゥカの戦い|アドゥアトゥカの戦い]]で[[w:クィントゥス・ティトゥリウス・サビヌス|サビヌス]]らとともに1個軍団と5個大隊が壊滅したので、残りは7個軍団となる。 :[[#1節|本巻1節]]によれば、この年(BC53年)には3個軍団を新たに徴集したので、計10個軍団となったはずである。 :[[#29節|29節]]では、このうちから12個大隊をライン川に架かる橋の守備に残し、[[#32節|32節]]では輜重の守備としてアドゥアトゥカに1個軍団を残した。 :本節の記述通りにラビエヌス、トレボニウス、カエサルがそれぞれ3個軍団(計9個)を受け持ったとすると、あわせて10個軍団と12個大隊という勘定になる。 :したがって、この勘定が正しいのであれば、ライン川に残した12個大隊は各軍団から引き抜いたものであり、各軍団は定員を割っていると考えられる。) ===34節=== '''夷を以って夷を制す対エブロネス族包囲網''' *① Erat, ut supra demonstravimus, manus certa nulla, **前に説明したように、(エブロネス族には)決まった手勢がなかったし、 **:(訳注:[[#31節|31節]]を参照。) *non oppidum, non praesidium, quod se armis defenderet, **自分たちが武器で防衛するような[[w:オッピドゥム|城市]]も、防塁もなかった。 *sed in omnes partes dispersa multitudo. **けれども、あらゆる方面に大勢が分散されていた。 *② Ubi cuique aut valles abdita aut locus silvestris aut palus impedita **おのおのが、密かな峡谷、あるいは森に覆われた土地といったところに、 *spem praesidi aut salutis aliquam offerebat, consederat. **守備あるいは身の安全の何らかの希望を提供するところに、陣取っていた。 *③ Haec loca vicinitatibus erant nota, **これらの場所は、近隣の者たちは知っていたので、 **:(訳注:すなわち、近隣のガッリア人には地の利があり、ローマ人には地の利がなかったので) *magnamque res diligentiam requirebat **事態はたいへんな注意深さを必要としていた。 *non in summa exercitus tuenda **(ローマ人の)軍隊全体を守るためではなく、 *─ nullum enim poterat universis &lt;a&gt; perterritis ac dispersis periculum accidere ─, **─なぜなら、脅かされ分散されている者たちにより(ローマ軍)総勢が危険を生じることはありえなかったので─ *sed in singulis militibus conservandis; **けれども、個々の(ローマ人の)兵士たちを守ることのために(注意深さを必要としていた)。 *quae tamen ex parte res ad salutem exercitus pertinebat. **少なくとも、ある面では、そういう事態は軍隊の安全に及んでいた。 *④ Nam et praedae cupiditas multos longius evocabat, **すなわち、略奪品への欲望が多くの者たちをより遠くへ呼び寄せていたし、 *et silvae incertis occultisque itineribus confertos adire prohibebant. **森林の不確かで隠された道のりによって密集した行軍を妨げていた。 *⑤ Si negotium confici stirpemque hominum sceleratorum interfici vellent, **もし、戦役が完遂されること、および非道な連中(=エブロネス族)の血筋が滅ぼされることを欲するならば、 *dimittendae plures manus diducendique erant milites; **いくつもの部隊が分遣され、兵士たちが展開されるべきである。 *⑥ si continere ad signa manipulos vellent, ut instituta ratio et consuetudo exercitus Romani postulabat, **もし、ローマ軍が決められた流儀や慣行を要求するように、[[w:マニプルス|中隊]]が軍旗のもとにとどまることを欲するならば、 *locus ipse erat praesidio barbaris, **その場所が蛮族にとって守りとなるであろう。 *neque ex occulto insidiandi et dispersos circumveniendi **隠れたところから待ち伏せするため、分散した者たち(=ローマ兵)を包囲するために、 *singulis deerat audacia. **(エブロネス族の)おのおのにとって勇敢さには事欠かなかった。 *⑦ Ut in eiusmodi difficultatibus, quantum diligentia provideri poterat providebatur, **そのような困難さにおいては、できるかぎりの注意深さで用心されるほどに、用心されるものであるが、 *ut potius in nocendo aliquid praetermitteretur, **結果として、むしろ(敵勢への)何らかの加害は差し控えられることになった。 *etsi omnium animi ad ulciscendum ardebant, **たとえ、皆の心が(エブロネス族に)報復するために燃え立っていたとしても、 *quam cum aliquo militum detrimento noceretur. **兵士たちの何らかの損失を伴って(敵に)加害がなされるよりも。 **:(訳注:伏兵によって被害をこうむるよりは、ローマ人の安全のために、ローマ兵による攻撃は避けられた。) *⑧ Dimittit ad finitimas civitates nuntios Caesar; **カエサルは、近隣の諸部族のところへ伝令たちを分遣した。 *omnes ad se vocat spe praedae ad diripiendos Eburones, **[[w:エブロネス族|エブロネス族]]に対して戦利品を略奪することの望みを呼びかけた。 *ut potius in silvis Gallorum vita quam legionarius miles periclitetur, **森の中で、軍団の兵士たちよりも、むしろガッリア人たちの生命が危険にさらされるように、 *simul ut magna multitudine circumfusa **同時にまた、たいへんな大勢で取り囲むことによって、 *pro tali facinore stirps ac nomen civitatis tollatur. **(サビヌスらを滅ぼした)あれほどの罪業の報いとして、部族の血筋と名前が抹殺されるように、と。 *Magnus undique numerus celeriter convenit. **至る所から多数の者が速やかに集結した。 ==スガンブリー族のアドゥアトゥカ攻略戦== ===35節=== '''スガンブリー族が略奪に駆り立てられてアドゥアトゥカへ向かう''' *① Haec in omnibus Eburonum partibus gerebantur, **これらのこと(=追討戦)が[[w:エブロネス族|エブロネス族]]のすべての地方で遂行されていたが、 *diesque adpetebat septimus, quem ad diem Caesar ad impedimenta legionemque reverti constituerat. **カエサルがその日に[[w:輜重|輜重]]と(キケロの)[[w:ローマ軍団|軍団]]のところへ引き返すと決めていた7日目が近づいていた。 *② Hic quantum in bello Fortuna possit et quantos adferat casus, cognosci potuit. **ここに、戦争では運命(の女神)がどれほどのことに力を持ち、どれほどの結末を引き起こすかを知ることができた。 **:(訳注:[[#30節|30節]]でもそうだが、カエサルは戦況が芳しくないと運命 Fortuna を持ち出すようである。[[#42節|42節]]も参照。) *③ Dissipatis ac perterritis hostibus, ut demonstravimus, **(前節で)説明したように、追い散らされて、脅かされている敵たちには、 *manus erat nulla quae parvam modo causam timoris adferret. **(ローマ勢に敵を)恐れる理由を少しの程度も引き起こすようないかなる手勢もなかった。 *④ Trans Rhenum ad Germanos **レーヌス(=[[w:ライン川|ライン川]])の向こう側の[[w:ゲルマニア|ゲルマーニア]]人のところへ、 *pervenit fama, diripi Eburones atque ultro omnes ad praedam evocari. **エブロネス族が収奪され、(近隣部族の)皆が略奪品へ向けて自発的に誘惑されているという風評が達した。 *⑤ Cogunt equitum duo milia Sugambri, qui sunt proximi Rheno, **レーヌスの近隣にいたスガンブリ族は、騎兵2000騎を徴集した。 *a quibus receptos ex fuga Tenctheros atque Usipetes supra docuimus. **前に説明したように、彼らによって[[w:テンクテリ族|テンクテリ族]]と[[w:ウスィペテス族|ウスィペテス族]]が逃亡から迎え入れられたのだ。 **:(訳注:[[ガリア戦記 第4巻#16節|第4巻16節]]および[[ガリア戦記 第4巻#18節|18~19節]]を参照。) *⑥ Transeunt Rhenum navibus ratibusque **(スガンブリー族は)レーヌスを船団や筏で渡河した。 *triginta milibus passuum infra eum locum, ubi pons erat perfectus praesidiumque ab Caesare relictum. **カエサルにより橋が造り上げられて守備隊が残された地点よりも下流に30ローママイル(約44km)のところを。 *Primos Eburonum fines adeunt; **手始めとしてエブロネス族の領土に殺到して、 *multos ex fuga dispersos excipiunt, **逃亡からちりぢりにさせられた多くの者たちを追い捕らえて、 *magno pecoris numero, cuius sunt cupidissimi barbari, potiuntur. **蛮族たちが最も熱望している家畜の多数をわがものにした。 *⑦ Invitati praeda longius procedunt. **(スガンブリー族の軍勢は)略奪品に誘われて、より遠くに進み出た。 *Non hos palus ─ in bello latrociniisque natos ─, non silvae morantur. **戦争や追いはぎに生まれついていたので、沼地も森林も彼らを妨げることがなかった。 *Quibus in locis sit Caesar, ex captivis quaerunt; **カエサルがどの場所にいるのか、捕虜から問い質した。 *profectum longius reperiunt omnemque exercitum discessisse cognoscunt. **(彼が)より遠くに旅立って、軍隊の総勢が立ち去ったことを、知った。 *⑧ Atque unus ex captivis "Quid vos," inquit, **なおかつ、捕虜たちのうちの一人が「なぜ、あんたたちは」と言い出した。 *"hanc miseram ac tenuem sectamini praedam, **「この取るに足らない、ちっぽけな略奪品を追い求めるのか。 **:(訳注:sectamini はデポネンティア動詞 sector の直説法・2人称複数・現在形) *quibus licet iam esse fortunatissimos? **(あんたたちは)今や、最も富裕な者に成り得るのに。 *⑨ Tribus horis Aduatucam venire potestis: **(この場所から)3時間で[[w:アドゥアトゥカ|アドゥアトゥカ]]に到達できる。 **:(訳注:古代ローマの時間は、不定時法であり、当地の緯度や季節により長さは異なる。) *huc omnes suas fortunas exercitus Romanorum contulit; **ここへ、ローマ軍がすべての財産を運び集めたのだ。 *praesidii tantum est, ut ne murus quidem cingi possit, **守備隊は、城壁が取り巻かれることさえできないほどの(貧弱な)ものでしかない。 *neque quisquam egredi extra munitiones audeat." **何者も防備の外側へあえて出て行こうとはしないのだ。」 *⑩ Oblata spe Germani, **ゲルマーニア人たちは(ローマ軍の財産という)望みを提示されて、 *quam nacti erant praedam, in occulto relinquunt; **(すでにエブロネス族の者たちから)獲得していた略奪品を秘されたところに残しておいて、 *ipsi Aduatucam contendunt usi eodem duce, cuius haec indicio cognoverant. **自身は、このことを申告により知ったところの同じ(捕虜の)案内人を使役して、アドゥアトゥカに急いだ。 <br> :('''訳注:部族名・地名の表記について''' :スガンブリー族 Sugambri:α系写本では Sugambri、T・U写本では Sygambri、V・R写本では Sigambri :テンクテリ族 Tenctheri:β系写本では Tenctheri、α系写本では Thenctheri :アドゥアトゥカ Aduatuca:α系・T写本では Aduatuca、V・ρ系写本では Atuatuca) ===36節=== '''アドゥアトゥカのキケロが糧秣徴発に派兵する''' *① [[w:la:Quintus_Tullius_Cicero|Cicero]], qui omnes superiores dies **[[w:クィントゥス・トゥッリウス・キケロ|キケロ]]は(期日の7日目)より以前の日々すべてを *praeceptis Caesaris cum summa diligentia milites in castris continuisset **カエサルの指図により、最高の入念さとともに、兵士たちを陣営の中に留めておき、 *ac ne calonem quidem quemquam extra munitionem egredi passus esset, **<ruby><rb>[[w:カロネス|軍属奴隷]]</rb><rp>(</rp><rt>カロネス</rt><rp>)</rp></ruby> でさえも、何者も防備の外側に出て行くことを許されなかった。 *septimo die diffidens de numero dierum Caesarem fidem servaturum, **(期日の)7日目に、カエサルが日数についての約束を守るであろうか、という不信を抱いた。 *quod longius eum<ref>eum はβ系写本の記述で、α系写本にはない。</ref> progressum audiebat, **というのは、彼(カエサル)は、はるか遠くに前進したと聞いていたのだし、 *neque ulla de reditu eius fama adferebatur, **彼の帰還については何ら伝言を届けられていなかったからである。 *② simul eorum permotus vocibus, **同時に(キケロは)以下のような者たちの声に揺り動かされた。 *qui illius patientiam paene obsessionem appellabant, siquidem ex castris egredi non liceret, **もし本当に陣営から出て行くことが許されないならば、彼の忍耐はほぼ攻囲(籠城)であるというのだ。 *nullum eiusmodi casum exspectans, **以下のような事態を予期してもいなかった。 *quo novem oppositis legionibus maximoque equitatu, **9個[[w:ローマ軍団|軍団]]と最大限の[[w:騎兵|騎兵]]隊が(敵と)対峙して、 *dispersis ac paene deletis hostibus **敵たちは散らばらされて、ほとんど抹殺されたのに、 *in milibus passuum tribus offendi posset, **(自陣から)3ローママイルの内で(敵対勢力から)襲撃され得るとは。 [[画像:PraetorianVexillifer_1.jpg|thumb|right|200px|帝政期に用いられた軍旗(ウェクスィッルム)の一種を再現したもの。]] *quinque cohortes frumentatum in proximas segetes mittit, **5個<ruby><rb>[[w:コホルス|歩兵大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby>を糧秣徴発するために、近隣の耕地に派遣した。 *quas inter et castra unus omnino collis intererat. **それら(の耕地)と陣営の間には、ただ一つの丘陵が介在するだけであった。 *③ Complures erant in castris<ref>in castris はβ系写本の記述で、α系写本にはない。</ref> ex legionibus aegri relicti; **陣営の中には、諸軍団のうちから少なからぬ傷病者たちが残留していた。 *ex quibus qui hoc spatio dierum convaluerant, circiter trecenti(CCC), **その者たちのうちから、この日々の間に回復していた約300名が、 *sub vexillo una mittuntur; **<ruby><rb>[[w:ウェクスィッルム|軍旗]]</rb><rp>(</rp><rt>ウェクスィッルム</rt><rp>)</rp></ruby>のもとで一緒に派遣された。 *magna praeterea multitudo calonum, magna vis iumentorum quae in castris subsederant, **そのうえに、軍属奴隷の大多数、陣営の中に残留していた(ロバなどの)役畜の多数が、 *facta potestate sequitur. **機会を与えられて、随行した。 ===37節=== [[画像:Castra1.png|thumb|right|200px|ローマ式[[w:カストラ|陣営]]([[w:la:Castra_Romana|castra Romana]])の概略図(再掲)。'''7'''が第10大隊の門(porta decumana)で、陣営の裏門に当たる。]] '''スガンブリー族がキケロの陣営に襲来''' *① Hoc ipso tempore et casu Germani equites interveniunt **このまさにその時と状況に、[[w:ゲルマニア|ゲルマーニア]]人の[[w:騎兵|騎兵]]たちが出現して、 *protinusque eodem illo, quo venerant, cursu **さらに前方へ(彼らが)やって来たのと同じ突進でもって、 *ab decumana porta in castra inrumpere conantur, **第10大隊の門(=裏門)から陣営の中に突入することを試みた。 **:(訳注:decumana porta は[[ガリア戦記 第2巻#24節|第2巻24節]]で既出、図を参照。) *② nec prius sunt visi obiectis ab ea parte silvis, quam [[wikt:la:castrum|castris]] adpropinquarent, **その方面については森林がじゃま立てしていたので(彼らは)陣営に接近するまでは視認されなかったのだ。 *usque eo ut qui sub [[w:la:Vallum|vallo]] tenderent mercatores, recipiendi sui facultatem non haberent. **そこまで(敵が急に来たので)、防柵の下に宿営していた商人たちが退避する機会を持たなかったほどであった。 *③ Inopinantes nostri re nova perturbantur, **予感していなかった我が方は、新しい事態に混乱させられて、 *ac vix primum impetum cohors in statione sustinet. **やっとのことで[[w:歩哨|歩哨]]に就いていた[[w:コホルス|歩兵大隊]]が(敵の)最初の突撃を持ちこたえた。 *④ Circumfunduntur ex reliquis hostes partibus, si quem aditum reperire possent. **敵たちは、何らかの入口を探り出せないかと、ほかの方面から取り囲んだ。 *⑤ Aegre portas nostri tuentur; **我が方(=ローマ勢)は辛うじて(四方の)諸門を固守して、 *reliquos aditus locus ipse per se munitioque defendit. **ほかの入口を、その位置そのものと防備が(敵の突入から)防護した。 *⑥ Totis trepidatur castris, **陣営の全体が震撼させられて、 *atque alius ex alio causam tumultus quaerit; **各人がほかの者に騒乱の原因を尋ね合った。 **:(訳注:エブロネス族を追討している最中に、スガンブリー族が来襲するとは予想だにしなかったからである。) *neque quo signa ferantur, neque quam in partem quisque conveniat provident. **が、どこへ軍旗が運ばれるのか、どの方面におのおのが集結するのか、判らなかった。 *⑦ Alius iam castra capta pronuntiat, **ある者は、すでに陣営は占拠されたと公言し、 *alius deleto exercitu atque imperatore victores barbaros venisse contendit; **別のある者は、軍隊も将軍(カエサル)も滅びて蛮族が勝利者としてやって来たのだ、と断言した。 *⑧ plerique novas sibi ex loco religiones fingunt **たいていの者たちは、その場所から、新奇な迷信的感情を創り上げ、 *Cottaeque et Tituri calamitatem, qui in eodem occiderint castello, **同じ砦のところで斃れた[[w:ルキウス・アウルンクレイウス・コッタ|コッタ]]と[[w:クィントゥス・ティトゥリウス・サビヌス|ティトゥリウス(・サビヌス)]]の敗亡を *ante oculos ponunt. **眼前に想い描いた。 *⑨ Tali timore omnibus perterritis **このような怖れによって(陣営内部の)皆が脅えており、 *confirmatur opinio barbaris, ut ex captivo audierant, nullum esse intus praesidium. **蛮族にとっては、捕虜から聞いていたように、内部に守備隊が存在していないという見解が強められた。 *⑩ Perrumpere nituntur **(スガンブリー勢は、陣営の防備を)突破することに努め、 *seque ipsi adhortantur, ne tantam fortunam ex manibus dimittant. **これほどの幸運を手から取りこぼさないように、自分たちが自身を鼓舞した。 ===38節=== '''バクルスと百人隊長たちが防戦する''' *① Erat aeger cum<ref>cum はα系写本の記述で、β系写本では in となっている。</ref> praesidio relictus P.(Publius) Sextius Baculus, **(キケロの陣営には)プーブリウス・セクスティウス・バクルスが傷病者として、守備兵とともに残されていた。 **:<span style="color:#009900;">(訳注:[[w:la:Publius Sextius Baculus|Publius Sextius Baculus]] などの記事を参照。)</span> *qui primum pilum ad<ref>ad はα系写本の記述で、β系写本では apud となっている。</ref> Caesarem duxerat, **その者はカエサルのもとで<ruby><rb>[[w:プリムス・ピルス|首位百人隊長]]</rb><rp>(</rp><rt>プリムス・ピルス</rt><rp>)</rp></ruby> の座に就いていたことがあり、 *cuius mentionem superioribus proeliis fecimus, **かつての戦闘で彼に言及したが、 **:<span style="color:#009900;">(訳注:[[ガリア戦記 第2巻#25節|第2巻25節]] および [[ガリア戦記 第3巻#5節|第3巻5節]]を参照。)</span> *ac diem iam quintum cibo caruerat. **(このとき)食物を欠いてすでに5日目であった。 *② Hic diffisus suae atque omnium saluti inermis ex tabernaculo prodit; **彼は、自らと皆の身の安全に疑念を抱いて、非武装のまま天幕小屋から出て来て、 *videt imminere hostes atque in summo esse rem discrimine; **敵たちが迫って来ていること、および事態が重大な危急にあることを目の当たりにして、 *capit arma a proximis atque in porta consistit. **すぐ近くの者から武器を取って、門のところに陣取った。 *③ Consequuntur hunc centuriones eius cohortis quae in statione erat; **歩哨に立っていた(1個)<ruby><rb>[[w:コホルス|歩兵大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby> の<ruby><rb>[[w:ケントゥリオ|百人隊長]]</rb><rp>(</rp><rt>ケントゥリオ</rt><rp>)</rp></ruby> たちが彼に追随して、 **:(訳注:1個歩兵大隊の百人隊長は、定員通りであれば、6名いた。) *paulisper una proelium sustinent. **しばらく一緒に戦闘を持ちこたえた。 *④ Relinquit animus Sextium gravibus acceptis vulneribus; **セクスティウス(・バクルス)は重い傷を受けて、気を失った。 *Deficiens<ref>deficiens はβ系写本の記述で、α系写本にはない。</ref> aegre per manus tractus servatur. **(彼は)衰弱して、(味方の)手から手に運ばれて辛うじて救助された。 *⑤ Hoc spatio interposito reliqui sese confirmant **こうしてしばらくした後で、ほかの者たちは意を強くした。 *tantum, ut in munitionibus consistere audeant speciemque defensorum praebeant. **(それは)防壁にあえて陣取って、防戦者たちの姿を示したほどであった。 ===39節=== '''スガンブリー族が糧秣徴発部隊をも襲う''' *① Interim confecta frumentatione milites nostri clamorem exaudiunt; **その間に、糧秣徴発を成し遂げると、我が方の兵士たち(=ローマ軍団兵)は叫び声を聞きつけて、 *praecurrunt equites; **[[w:騎兵|騎兵]]たちが先駆けして、 *quanto res sit in periculo cognoscunt. **事態がどれほどの危険にあるかを認識した。 *② Hic vero nulla munitio est quae perterritos recipiat; **そこには、まさに、脅え上がった者たちを受け入れるような、いかなる防備もなかったのである。 *modo conscripti atque usus militaris imperiti **やっと徴集されたばかりの者たち、なおかつ兵役の経験に通じていない者たちは、 *ad tribunum militum centurionesque ora convertunt; **<ruby><rb>[[w:トリブヌス・ミリトゥム|兵士長官]]</rb><rp>(</rp><rt>トリブヌス・ミリトゥム</rt><rp>)</rp></ruby>や<ruby><rb>[[w:ケントゥリオ|百人隊長]]</rb><rp>(</rp><rt>ケントゥリオ</rt><rp>)</rp></ruby>たちの方へ顔を向けた。 *quid ab his praecipiatur exspectant. **彼ら(上官たち)によって何を指図されるか、待っていたのである。 *③ Nemo est tam fortis, quin rei novitate perturbetur. **新奇な事態に不安にさせられないほど勇敢な者は、誰もいなかった。 *④ Barbari signa procul conspicati oppugnatione desistunt, **蛮族たちは、(糧秣徴発隊の)軍旗を遠くから視認すると、(陣営への)攻囲を停止した。 *redisse primo legiones credunt, quas longius discessisse ex captivis cognoverant; **(彼らは)当初は、より遠くに立ち去ったことを捕虜から知っていた(ローマの)諸軍団が戻って来たと思ったが、 *postea despecta paucitate ex omnibus partibus impetum faciunt. **後には、(糧秣徴発隊の)寡勢ぶりを侮って、あらゆる方向から突撃して来た。 ===40節=== '''敵中突破して陣営へ戻る糧秣徴発部隊の明暗''' *① Calones in proximum tumulum procurrunt. **[[w:カロネス|軍属奴隷]]たちは、近隣の丘に先駆けした。 *Hinc celeriter deiecti **(彼らは)ここから、(突撃して来る敵の軍勢を眺めて)たちまち当てが外れて、 *se in signa manipulosque coniciunt; **(後方にいた)軍旗と[[w:マニプルス|歩兵中隊]]のところに身を投じた。 *eo magis timidos perterrent milites. **それゆえに、臆病な兵士たちを大いに脅かした。 [[画像:Wedge-diagram.svg|thumb|right|200px|[[w:くさび|楔(くさび)]]の図。本節で述べられているのは、ローマ勢が楔(図の黒い部分)のように突撃することにより、敵を中央突破しようという戦術であろう。]] *② Alii cuneo facto ut celeriter perrumpant, censent **(ローマ兵の)ある者たちは、速やかに(敵中を)突破するように、<ruby><rb>[[w:くさび|楔形]]</rb><rp>(</rp><rt>くさびがた</rt><rp>)</rp></ruby>隊列を形成しようと考慮した。 *─ quoniam tam propinqua sint castra, **─ 陣営がこれほどまで近隣にあるので、 *etsi pars aliqua circumventa ceciderit, at reliquos servari posse confidunt ─, **たとえ、一部の誰かが包囲されて斃れたとしても、残りの者たちは救われることが可能だと確信したのだ ─。 *③ alii ut in iugo consistant atque eundem omnes ferant casum. **別のある者たちは、(丘の)尾根に陣取って、皆が同じ命運に耐え忍ぼうと(考えた)。 *④ Hoc veteres non probant milites, quos sub vexillo una profectos docuimus. **既述したように軍旗のもとで一緒に発って来た古参兵たちは、後者(の案)を承認しなかった。 **:(訳注:[[#36節|36節]]③項で既述のように、回復した傷病兵たちが同行してきていた。) *Itaque inter se cohortati **こうして、(古参の傷病兵たちは)互いに激励し合って、 *duce C.(Gaio) Trebonio equite Romano, qui iis erat praepositus, **彼らの指揮を委ねられていたローマ人[[w:騎士|騎士階級]]のガイウス・トレボニウスを統率者として、 **:(訳注:[[#33節|33節]]で3個軍団を率いて出発した副官の[[w:ガイウス・トレボニウス|ガイウス・トレボニウス]]とは明らかに同名の別人である。) *per medios hostes perrumpunt incolumesque ad unum omnes in castra perveniunt. **敵たちの中央を突破して、一人に至るまで皆が無傷で陣営に到着した。 *⑤ Hos subsecuti calones equitesque eodem impetu militum virtute servantur. **彼らに追随して、軍属奴隷と[[w:騎兵|騎兵]]たちが同様の突撃をして、兵士たちの武勇により救われた。 *⑥ At ii qui in iugo constiterant, **それに対して(丘の)尾根に陣取った者たちは、 *nullo etiam nunc usu rei militaris percepto **今になってさえも、軍事的行動というものを把握しておらず、 *neque in eo quod probaverant consilio permanere, ut se loco superiore defenderent, **より高い場所で身を守るという、彼らが承認していた考えに留まりもせず、 *neque eam quam prodesse aliis vim celeritatemque viderant, imitari potuerunt, **(彼らが)別の者たち(=古参兵)に役立ったのを見ていたところの力と迅速さを真似することもできなかった。 *sed se in castra recipere conati iniquum in locum demiserunt. **けれども、陣営に退却することを試みたが、不利な場所に落ち込んで行った。 *⑦ Centuriones, quorum nonnulli ex inferioribus ordinibus reliquarum legionum **[[w:ケントゥリオ|百人隊長]]たちといえば、彼らの少なからぬ者たちは、ほかの[[w:ローマ軍団|軍団]]のより低い序列から、 *virtutis causa in superiores erant ordines huius legionis traducti, **武勇のおかげで、この軍団のより高い序列に異動させられていたが、 *ne ante partam rei militaris laudem amitterent, fortissime pugnantes conciderunt. **かつて獲得した軍事的な賞賛を失わないように、とても果敢に奮戦して斃れた。 *⑧ Militum pars horum virtute **兵士たちの一部は、これら(討ち死にした百人隊長たち)の武勇により、 *submotis hostibus praeter spem incolumis in castra pervenit, **予想に反して敵たちが撃退されたので、無傷で陣営に到着した。 *pars a barbaris circumventa periit. **別の一部は、蛮族によって包囲されて、討ち死にした。 ===41節=== '''スガンブリー族の撤退、カエサルの帰還''' *① Germani desperata expugnatione castrorum, **[[w:ゲルマニア|ゲルマーニア]]人たちは(キケロの)[[w:カストラ|陣営]]の攻略に絶望して、 *quod nostros iam constitisse in munitionibus videbant, **というのは、我が方(ローマ勢)が防備のところに立っているのを見たからであるが、 *cum ea praeda quam in silvis deposuerant, trans Rhenum sese receperunt. **森の中にしまい込んでいた略奪品とともに、レヌス(=[[w:ライン川|ライン川]])の向こう側に撤退した。 *② Ac tantus fuit etiam post discessum hostium terror, **敵たちの立ち去った後でさえ(ローマ勢の)畏怖はたいへんなものであったので、 *ut ea nocte, cum C.(Gaius) Volusenus missus cum equitatu ad castra venisset, **その夜に、(追討戦に)派遣されていたガーイウス・ウォルセーヌスが騎兵隊とともに陣営へ帰着したときに **:<span style="color:#009900;font-family:Times New Roman;">(訳注:''[[w:en:Gaius Volusenus|Gaius Volusenus]]'' は、[[ガリア戦記_第3巻#5節|第3巻5節]]のアルプス・オクトードゥールスの戦い、<br>    [[ガリア戦記_第4巻#21節|第4巻21節]]・[[ガリア戦記_第4巻#23節|23節]]のブリタンニアへの先遣で既述。<br>    この後、さらに第8巻23節<sub>([[s:la:Commentarii_de_bello_Gallico/Liber_VIII#23|s]])</sub>、48節<sub>([[s:la:Commentarii_de_bello_Gallico/Liber_VIII#48|s]])</sub>でも活躍する。)</span> *fidem non faceret adesse cum incolumi Caesarem exercitu. **カエサルが無傷の軍隊とともに近くに来ていることを(陣営の残留組に)信用させなかったほどである。 *③ Sic omnino animos timor praeoccupaverat, ut paene alienata mente **ほとんど気でも違ったかのように、皆の心を怖れが占めていた。 **:(訳注:sic … ut ~ の構文;「~と同様に…である」) *deletis omnibus copiis equitatum se ex fuga recepisse dicerent **(残留者たちは、カエサルら)全軍勢が滅ぼされて、[[w:騎兵|騎兵隊]]が敗走から退いて来たのだ、と言った。 *neque incolumi exercitu Germanos castra oppugnaturos fuisse contenderent. **(カエサルら)軍隊が無傷であれば、ゲルマーニア人が陣営を襲撃しなかっただろう、と断言した。 **:(訳注:oppugnaturos fuisse ;間接話法では非現実な[[w:条件法|条件文]]の帰結は「未来分詞+fuisse」で表される。) *④ Quem timorem Caesaris adventus sustulit. **その怖れをカエサルの到着が取り除いた。 **:(訳注:sustulit は tollō の完了・能動3人称単数形) ===42節=== '''カエサルがスガンブリー族の襲来と撤退を運命に帰する''' *① Reversus ille, eventus belli non ignorans, **引き返して来た彼(カエサル)は、戦争の成り行きというものを知らないはずがないので、 *unum quod cohortes ex statione et praesidio essent emissae, **ひとつ(だけ)、<ruby><rb>[[w:コホルス|諸大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby> が[[w:歩哨|歩哨]]や守備から(糧秣徴発に)派遣されたことを *questus ─ ne minimo quidem casu locum relinqui debuisse ─ **不慮の事態に対して最小限のいかなる余地も残されるべきではなかった、と嘆いた。 *multum Fortunam in repentino hostium adventu potuisse iudicavit, **不意の敵たちの到来においては運命(の女神)が大いに力を持つ、と断じた。 *② multo etiam amplius, quod paene ab ipso vallo portisque castrorum barbaros avertisset. **さらに、より一層大きかったのは、(運命が)ほとんど蛮族をその陣営の防柵と諸門から追い返してしまったことである。 *③ Quarum omnium rerum maxime admirandum videbatur, **それらのすべての事態でとりわけ驚くべきと思われたのは、 *quod Germani, qui eo consilio Rhenum transierant, ut Ambiorigis fines depopularentur, **その意図で[[w:アンビオリクス|アンビオリクス]]の領土を荒らすようにレヌス(=[[w:ライン川|ライン川]])を渡河していた[[w:ゲルマニア|ゲルマーニア]]人が、 *ad castra Romanorum delati **ローマ人の陣営の方へそらされて、 *optatissimum Ambiorigi beneficium obtulerunt. **アンビオリクスに最も望ましい恩恵を施してしまったことである。 ==対エブロネス族追討戦(2)== ===43節=== '''アンビオリクスが辛うじて追討を逃れる''' *① Caesar rursus ad vexandos hostes profectus **カエサルは再び敵たちを苦しめるために出発して、 *magno coacto &lt;equitum&gt; numero ex finitimis civitatibus in omnes partes dimittit. **[[w:騎兵|騎兵]]の多数を隣接する諸部族から徴集して、あらゆる方面に派遣した。 **:(訳注:&lt;equitum&gt; 「騎兵の」は近代の校訂者による挿入である。) *② Omnes vici atque omnia aedificia quae quisque conspexerat incendebantur, **おのおのが目にしたすべての村々およびすべての建物が焼き打ちされた。 *pecora interficiebantur<ref>pecora interficiebantur はβ系写本の記述で、α系写本にはない。</ref>, praeda ex omnibus locis agebatur; **家畜は屠殺され、あらゆる場所から略奪品が奪い去られた。 *③ frumenta non solum tanta multitudine iumentorum atque hominum consumebantur, **役畜および人間たちのこれほど大勢により穀物が消費され尽くしたのみならず、 *sed etiam anni tempore atque imbribus procubuerant, **季節と豪雨によってさえも(穀物が)倒れた。 *ut si qui etiam in praesentia se occultassent, **その結果、もし(エブロネス族の)何者かが現状では身を隠しているとしても、 *tamen his deducto exercitu rerum omnium inopia pereundum videretur. **それでも彼らは(ローマ人の)軍隊が引き揚げれば、あらゆるものの欠乏により死滅するはずと思われた。 *④ Ac saepe in eum locum ventum est tanto in omnes partes diviso equitatu, **たいへん多くの騎兵隊があらゆる方面に分遣されて、しばしば以下のような状態に出くわした。 *ut non modo visum ab se Ambiorigem in fuga circumspicerent captivi **捕虜たちが、自分たちによって逃亡中の[[w:アンビオリクス|アンビオリクス]]が目撃されたと見回しただけでなく、 *nec plane etiam abisse ex conspectu contenderent, **(アンビオリクスが)視界からまったく消え去ってはいないとさえ主張した。 *⑤ ut spe consequendi inlata atque infinito labore suscepto, **その結果、(アンビオリクスを)追跡する希望がもたらされて、さらに限りない労苦が従事された。 *qui se summam ab Caesare gratiam inituros putarent, **カエサルから最高の恩恵を得ようと思った者たちは、 *paene naturam studio vincerent, **熱意により(身体的な)資質にほとんど打ち克ったが、 *semperque paulum ad summam felicitatem defuisse videretur, **いつも最高の恵みにあと少しで足りなかったと思われる。 *⑥ atque ille latebris aut silvis<ref>aut silvis はβ系写本の記述で、α系写本にはない。</ref> aut saltibus se eriperet **かつ彼(アンビオリクス)は隠れ処、あるいは森林、あるいは峡谷によって自らを救い、 *et noctu occultatus alias regiones partesque peteret **夜に秘されて、別の地方や方面をめざした。 *non maiore equitum praesidio quam quattuor, **4名より多くない騎兵の護衛によって、 *quibus solis vitam suam committere audebat. **自らの生命をその者たちだけにあえて委ねたのだ。 ===44節=== '''カエサルが撤退し、造反者アッコを処刑する''' *① Tali modo vastatis regionibus **このようなやり方で(エブロネス族の)諸地域を荒廃させて、 [[画像:Porte_Mars_01.jpg|thumb|right|200px|ドゥロコルトルム(現在の[[w:ランス (マルヌ県)|ランス]])に建てられた帝政ローマ時代(3世紀)の[[w:凱旋門|凱旋門]]。]] *exercitum Caesar duarum cohortium damno [[w:la:Remi|Durocortorum]] Remorum reducit **カエサルは、2個<ruby><rb>[[w:コホルス|歩兵大隊]]</rb><rp>(</rp><rt>コホルス</rt><rp>)</rp></ruby> の損失(だけ)で、軍隊を[[w:レミ族|レミ族]]の[[w:ドゥロコルトルム|ドゥロコルトルム]]に連れ戻して、 **:(訳注:ドゥロコルトルムはレミ族の首邑で、現在の[[w:ランス (マルヌ県)|ランス]] Reims である。) *concilioque in eum locum Galliae indicto **その地においてガッリアの(領袖たちの)会合を公示して、 *de coniuratione Senonum et Carnutum quaestionem habere instituit **[[w:セノネス族|セノネス族]]と[[w:カルヌテス族|カルヌテス族]]の共謀について詮議することを決定した。 *② et de Accone, qui princeps eius consilii fuerat, **その謀計の首謀者であった[[w:アッコ (セノネス族)|アッコ]]については *graviore sententia pronuntiata more maiorum supplicium sumpsit. **より重い判決が布告され、(ローマ人の)先祖の習慣により極刑に処した。 **:(訳注:ローマ史家[[w:テオドール・モムゼン|モムゼン]]は、アッコはローマの<ruby><rb>[[w:リクトル|先導吏]]</rb><rp>(</rp><rt>リクトル</rt><rp>)</rp></ruby> により[[w:斬首刑|斬首]]されたと言及している<ref>『モムゼン ローマの歴史Ⅳ』長谷川博隆訳、名古屋大学出版会、p.233 を参照。</ref>。 **:外国から来た侵略者カエサルがこのような刑罰を下したことに、ガッリア人たちは憤激した。[[ガリア戦記 第7巻#1節|第7巻1節]]を参照。) *③ Nonnulli iudicium veriti profugerunt. **少なからぬ者たちは、裁判を恐れて逃走した。 *Quibus cum aqua atque igni interdixisset, **その者たちには水と火が禁じられたうえで、 **:(訳注:「水と火を禁じる」とは追放処分のことで、居住権や財産の没収などを指す。) *duas legiones ad fines Treverorum, duas in Lingonibus, **2個[[w:ローマ軍団|軍団]]をトレーウェリー族の領土へ、2個(軍団)を[[w:リンゴネス族|リンゴネス族]](の領土)に、 *sex reliquas in Senonum finibus [[w:la:Agedincum|Agedinci]] in hibernis conlocavit **残りの6個(軍団)を[[w:セノネス族|セノネス族]]の領土の[[w:アゲディンクム|アゲディンクム]]に、冬営地に宿営させた。 **:(訳注:アゲディンクムは、現在の[[w:サン (ヨンヌ県)|サン]] Sens である。) *frumentoque exercitui proviso, **軍隊の糧秣を調達してから、 *ut instituerat, in Italiam ad conventus agendos profectus est. **定めていたように、イタリアに開廷(巡回裁判)を行なうために出発した。 **:(訳注:ここで「イタリア」とはカエサルが総督を務める[[w:ガリア・キサルピナ|ガッリア・キサルピーナ]]のことと思われる。) ---- *<span style="background-color:#99ff99;">「ガリア戦記 第6巻」了。「[[ガリア戦記 第7巻]]」へ続く。</span> ==脚注== <references /> ==参考リンク== *ウィキペディア英語版・日本語版 **[[w:en:Category:Tribes of ancient Gaul|Category:Tribes of ancient Gaul]]([[w:Category:ガリアの部族|Category:ガッリアの部族]]) ***[[w:en:Eburones|Eburones]]([[w:エブロネス族|エブロネス族]]) ***[[w:en:Nervii|Nervii]]([[w:ネルウィイ族|ネルウィイ族]]) ***[[w:en:Senones|Senones]](セノネス族)- [[w:la:Senones|la:Senones]] ***[[w:en:Carnutes|Carnutes]](カルヌテス族) ***[[w:en:Parisii (Gaul)|Parisii (Gaul)]]([[w:パリシイ族|パリスィ族]]) ****[[w:en:Lutetia|Lutetia]]([[w:ルテティア|ルテティア]]) ***[[w:en:Menapii|Menapii]](メナピイ族) ***[[w:en:Treveri|Treveri]](トレーウェリー族) ***[[w:en:Aedui|Aedui]]([[w:ハエドゥイ族|ハエドゥイ族]]) ***[[w:en:Sequani|Sequani]](セクアニ族) ***[[w:en:Remi|Remi]](レーミー族) **[[w:en:Category:Germanic peoples|Category:Germanic peoples]](ゲルマーニア人のカテゴリ) ***[[w:en:Category:Ancient Germanic peoples|Category:Ancient Germanic peoples]](古代ゲルマーニア人) ***[[w:en:Germanic peoples|Germanic peoples]](ゲルマーニア人) ***[[w:en:Ubii|Ubii]](ウビイー族) ***[[w:en:Suebi|Suebi]]([[w:スエビ族|スエービー族]]) ***[[w:en:Chatti|Chatti]](カッティー族) ***[[w:en:Cherusci|Cherusci]](ケールスキー族) ***[[w:en:Sicambri|Sicambri]](スガンブリー族) ***[[w:en:Hercynian Forest|Hercynian Forest]](ヘルキュニアの森) **地理学者・史家 ***[[w:en:Posidonius|Posidonius]]([[w:ポセイドニオス|ポセイドニオス]];BC135-51年頃)- [[w:la:Posidonius Apameus|la:Posidonius Apameus]] ***[[w:en:Diodorus Siculus|Diodorus Siculus]]([[w:シケリアのディオドロス|シケリアのディオドロス]];BC1世紀) - [[w:la:Diodorus Siculus|la:Diodorus Siculus]] ****〔ウィキソース ギリシア語版:[[s:el:Διόδωρος Σικελιώτης|Διόδωρος Σικελιώτης]](シケリアのディオドロス)- [[s:el:Ιστορική Βιβλιοθήκη|Ιστορική Βιβλιοθήκη]](歴史叢書)〕 ***[[w:en:Strabo|Strabo]]([[w:ストラボン|ストラボン]];BC63年頃–AD24年頃)- [[w:la:Strabo|la:Strabo]] ****〔ウィキソース ギリシア語版:[[s:el:Στράβων|Στράβων]](ストラボン) - [[s:el:Γεωγραφία|Γεωγραφία]](世界地誌)〕 ***[[w:en:Tacitus|Tacitus]]([[w:タキトゥス|タキトゥス]];56年頃–117年頃)- [[w:la:Cornelius Tacitus|la:Cornelius Tacitus]] ****[[w:en:Germania (book)|Germania (book)]]([[w:ゲルマニア (書物)|ゲルマーニア (書物)]])- [[w:la:Germania (opus Taciti)|la:Germania (opus Taciti)]] ***[[w:en:Pomponius Mela|Pomponius Mela]](ポンポニウス・メラ;1世紀)- [[w:la:Pomponius Mela|Pomponius Mela]] ***[[w:en:Athenaeus|Athenaeus]]([[w:アテナイオス|アテナイオス]];2世紀頃)- [[w:la:Athenaeus Naucratita|la:Athenaeus Naucratita]] ***[[w:en:Theodor Mommsen|Theodor Mommsen]]([[w:テオドール・モムゼン|テオドール・モムゼン]];19世紀)- [[w:la:Theodorus Mommsen|la:Theodorus Mommsen]] **[[w:en:Category:Celtic culture|Category:Celtic culture]](ケルト文化) **[[w:en:Category:Celtic mythology|Category:Celtic mythology]]([[w:Category:ケルト神話|Category:ケルト神話]]) ***[[w:en:Druid|Druid]]([[w:ドルイド|ドルイド]]) - [[w:la:Druis|la:Druis]] ***[[w:en:Wicker Man|Wicker Man]]([[w:ウィッカーマン|ウィッカーマン]]) **[[w:en:Category::Celtic_gods|Category::Celtic_gods]](ケルトの神々) **[[w:en:Category:Ancient Gaulish and British gods|Category:Ancient Gaulish and British gods]](古代ガッリアとブリタニアの神々) ***[[w:en:Taranis|Taranis]](タラニス) ***[[w:en:Cernunnos|Cernunnos]](ケルヌンノス) ***[[w:en:Dis Pater|Dis Pater]](ディス・パテル) ***[[w:en:Sucellus|Sucellus]](スケッルス) **カエサルの副官たち ***[[w:en:Titus_Labienus|Titus Labienus]]([[w:ティトゥス・ラビエヌス|ティトゥス・ラビエヌス]])- [[w:la:Titus_Labienus|la:Titus Labienus]] ***[[w:en:Trebonius|Gaius Trebonius]]([[w:ガイウス・トレボニウス|ガイウス・トレボニウス]])- [[w:la:Gaius Trebonius|la:Gaius Trebonius]] ***[[w:en:Quintus_Tullius_Cicero|Quintus Tullius Cicero]]([[w:クィントゥス・トゥッリウス・キケロ|クィントゥス・トゥッリウス・キケロ]])- [[w:la:Quintus_Tullius_Cicero|la:Quintus Tullius Cicero]] ***[[w:en:|en:]]([[w:|w:]]) ***[[w:en:|en:]]([[w:|w:]]) *ウィクショナリー フランス語版 **[[wikt:fr:calo]](カーロー、軍属奴隷) g8lqmm7siq5zxmcjjmnpynqhyt5vwri Python 0 14056 263761 241258 2024-11-18T09:37:45Z Ef3 694 /* 応用 */ ; [[/改廃された技術|改廃された技術]] 263761 wikitext text/x-wiki {{Pathnav|メインページ|工学|情報技術|プログラミング|frame=1}} {{Wikipedia|Python}}{{wikiversity|Python}}[[File:Python-logo-notext.svg|thumb|100px|Python]] '''''Python'''''は高水準な汎用プログラミング言語です。 Pythonの設計思想は、コードの読みやすさを重視しています。 たとえばブロックは波括弧 { } ではなくインデントで構造化されているなど、その構造に対するアプローチは独特です。 また、Pythonは、オブジェクト指向・インタープリタ型・動的型付け・クロスプラットフォームなプログラミング言語です。 これらのアプローチは、プログラマーが小規模および大規模なプロジェクトで自己説明的で論理的なコードを書けるようにすることを目的としています。 == 目次 == {{進捗状況}} === 入門 === : [[/基本事項|基本事項]]{{進捗簡易|100%|2022-11-28}}{{---}}[[/基本事項#pythonの実行方法|pythonの実行方法]]、[[/基本事項#「Hello, world!」と表示させよう|Hello, world!]] : [[/変数と代入|変数と代入]]{{進捗簡易|75%|2022-11-28}}{{---}}[[/変数と代入#変数とは|変数とは]]、[[/変数と代入#代入|代入]]、[[/変数と代入#識別子|識別子]] : [[/数値入力と文字入力と出力表示|数値入力と文字入力と出力表示]]{{進捗簡易|50%|2022-11-28}}{{---}}input(), int(), float() : [[/条件分岐と繰り返し|条件分岐と繰り返し]]{{進捗簡易|100%|2022-11-28}}{{---}}if, else, for, while : [[/演算子|演算子]]{{進捗簡易|25%|2022-11-28}}{{---}} : [[/関数|関数]]{{進捗簡易|75%|2022-11-28}}{{---}}def、[[/関数#引数のある関数|引数]]、ローカル変数、id()、戻り値、[[/関数#キーワード引数|キーワード引数]]、[[/関数#デコレータ|デコレーター]] === 基礎 === : [[/コレクション|コレクション]]{{---}}複数の要素をまとめたデータ構造です。 :: [[/シーケンス|シーケンス]]{{進捗簡易|50%|2022-11-28}}{{---}}データの順序付きコレクションです。 ::: [[/リスト|リスト]]{{進捗簡易|100%|2022-11-28}}{{---}}''list'' 順序つきの可変シーケンスで、異なるデータ型の要素を含むことができます。 ::: [[/タプル|タプル]]{{進捗簡易|25%|2022-11-28}}{{---}}''tuple'' 順序つきの不変シーケンスで、異なるデータ型の要素を含むことができます。 ::: [[/文字列|文字列]]{{---}}''string'' 文字の並びで、シングルクォートまたはダブルクォートで囲まれた不変のデータ型です。 :: [[/辞書|辞書]]{{進捗簡易|25%|2022-11-28}}{{---}}''dict'' キーと値の対応付けを持つ可変コレクションで、中括弧{}を使って定義されます。 :: [[/セット|セット]]{{進捗簡易|50%|2022-11-28}}{{---}}''set'' 重複のない要素のコレクションで、中括弧{}を使って定義し、順序は保持されません。 :: [[/レンジ|レンジ]]{{進捗簡易|50%|2022-11-28}}{{---}}''range'' 数値の範囲を生成する不変のシーケンスで、通常、forループなどで使用されます。 : [[/三種の内包表記とジェネレーター式|三種の内包表記とジェネレーター式]] : [[/モジュールのインポート|モジュールのインポート]]{{進捗簡易|100%|2022-11-28}}{{---}}math モジュール、random モジュール、importlib :: [[/array|array]]{{進捗簡易|50%|2022-11-28}}{{---}}効率的な数値計算のために配列を提供する : [[/例外処理|例外処理]]{{進捗簡易|25%|2022-11-28}}{{---}}try、except、finally、複数の例外の場合分け : [[/クラス|クラス]]{{進捗簡易|75%|2022-11-28}}{{---}}クラス定義、__init__()、self : [[/ファイルの書き込みと読み込み|ファイルの書き込みと読み込み]]{{進捗簡易|00%|2022-11-28}}{{---}}open関数, with文を使ったリソース管理、オープンモード、write、readline === 応用 === : [[/型ヒント|型ヒント]]{{進捗簡易|25%|2022-11-28}}{{---}}[[/型ヒント#型アノテーション|型アノテーション]] : [[/イテレータ|イテレータ]] : [[/演算子オーバーロード|演算子オーバーロード]] ; [[/改廃された技術|改廃された技術]] === モジュール === ==== 標準モジュール ==== [[/標準モジュール|標準モジュール]]{{---}}標準モジュールの一覧 : [[/標準モジュール/Tkinter|Tkinter]]{{---}}GUIアプリケーションの作成 : [[/標準モジュール/urllib|urllib]]{{---}}url拡張、識別 : [[SQLite#Pythonからの利用|sqlite3]]{{---}}簡易的なデータベースの利用 : [[/標準モジュール/yaml|yaml]]{{---}}yaml書式の解析 ==== サードパーティモジュール ==== : [[/TheOtherModules|その他のモジュール]]{{---}} : [[/pip|pip]]{{---}}Pythonのパッケージ管理システム : [[/NumPy|NumPy]]{{---}}数値計算を効率的かつ簡単に行うためのライブラリ : [[/Pandas|Pandas]]{{---}}データ分析やデータ処理において高度な機能を提供するライブラリ : [[/transformers|Transformers]]{{---}}ニューラルネットワークなどの機械学習モデルのデプロイなどに使用されるライブラリ。 : [[/TensorFlow|TensorFlow]]{{---}}ニューラルネットワークなどの機械学習アプリケーションの実装に使用される数値計算ライブラリ : [[/サードパーティデータベースモジュール|サードパーティデータベースモジュール]]{{---}}拡張的データベースの利用 :: [[/mysql|mysql]]{{---}}mysql、aiomysql :: [[/sqlarchemy|sqlarchemy]] : [[/matplotlib|matplotlib]]{{---}}グラフの作成 : [[/requests|requests]]{{---}}HTTPリクエストを簡単に送信するためのライブラリ : [[/BeautifulSoup|BeautifulSoup]]{{---}}HTMLやXMLのパースやスクレイピングに使用されるライブラリ : [[/Django|Django]]{{---}}Webアプリケーションの開発に使用されるフルスタックフレームワーク : [[/Flask|Flask]]{{---}}Webアプリケーションの開発に使用されるマイクロフレームワーク : [[/Pygame|Pygame]]{{---}}ゲーム開発に使用されるマルチメディアライブラリ : [[/OpenCV|OpenCV]]{{---}}コンピュータビジョンタスク(画像処理や機械学習)に使用されるライブラリ : [[/gradio|gradio]]{{---}}機械学習モデルのデプロイや対話型UIの作成を行うためのライブラリ : [[/streamlit|streamlit]]{{---}}データの可視化や機械学習アプリケーションの作成を行うためのライブラリ ? : [[/Scikit-learn|Scikit-learn]]{{---}}機械学習のさまざまなタスク(分類、回帰、クラスタリングなど)をサポートするライブラリ : [[/Keras|Keras]]{{---}}深層学習モデルの構築とトレーニングを容易に行うための高水準のニューラルネットワークAPI : [[/NLTK|NLTK]]{{---}}自然言語処理(NLP)タスクのための豊富な言語データと機能を提供するライブラリ : [[/SciPy|SciPy]]{{---}}科学技術計算のための機能を提供するライブラリ(最適化、統計、信号処理など) : [[/Gensim|Gensim]]{{---}}トピックモデリングや自然言語処理のためのベクトル空間モデルを構築するライブラリ : [[/PyTorch|PyTorch]]{{---}}機械学習およびディープラーニングのためのフレームワーク : [[/FastAPI|FastAPI]]{{---}}高速なWeb APIの開発を支援するマイクロフレームワーク : [[/Celery|Celery]]{{---}}分散タスクキューの実装を可能にする非同期タスクキューライブラリ : [[/pytest|pytest]]{{---}}Pythonのテストフレームワークで、効率的で拡張可能なテストの作成をサポートする : [[/Scrapy|Scrapy]]{{---}}Webスクレイピングとクローリングのためのフレームワーク : [[/PySpark|PySpark]]{{---}}Apache SparkのPython APIで、大規模データ処理や分散処理をサポートする : [[/Arrow|Arrow]]{{---}}効率的な日時とタイムゾーンの操作を提供するライブラリ : [[/Plotly|Plotly]]{{---}}インタラクティブなグラフや可視化を作成するためのライブラリ : [[/Cython|Cython]]{{---}}Pythonのための静的型付けをサポートし、高速なC拡張モジュールを作成するためのツール : [[/PyQt|PyQt]]{{---}}QtアプリケーションフレームワークのPythonバインディング : [[/PyPDF2|PyPDF2]]: PDFファイルの操作と処理を行うためのライブラリ : [[/NetworkX|NetworkX]]: 複雑なネットワークやグラフの解析と可視化を行うためのライブラリ : [[/Seaborn|Seaborn]]: 美しいグラフと統計プロットを作成するためのライブラリ : [[/Cryptography|Cryptography]]: 暗号化やデータ保護のためのライブラリ : [[/Panda3D|Panda3D]]{{---}}3Dゲーム開発のためのオープンソースフレームワーク : [[/Godot Engine|Godot Engine]]{{---}}オープンソースの2Dおよび3Dゲームエンジンで、Pythonを含むさまざまなプログラミング言語をサポート : [[/Arcade|Arcade]]{{---}}シンプルで使いやすい2Dゲーム開発ライブラリ : [[/Pygame Zero|Pygame Zero]]{{---}}Pygameをベースにしたシンプルなゲーム開発フレームワーク。初心者向けに適している : [[/Ursina|Ursina]]{{---}}Pythonで記述された3Dゲームを簡単に作成できるライブラ ==== 拡張モジュールの作成 ==== : [[/c言語による拡張|c言語による拡張]] : [[/ctypesによる拡張|ctypesによる拡張]] === リファレンス === : [[/組込み関数|組込み関数]]{{進捗簡易|25%|2022-11-28}} : [[/組込み型|組込み型]]{{進捗簡易|50%|2022-11-28}} {{コラム|PEPについて|2=PEP(Python Enhancement Proposal)は、Pythonプログラミング言語の改善や機能追加に関する提案や文書のことです。PEPはPythonコミュニティによって作成され、議論されます。Pythonの開発者やユーザーが新しいアイデアを提案し、共有するためのフレームワークとして機能しています。 {{See also|[https://peps.python.org/ Python Enhancement Proposals]}} PEPはさまざまなカテゴリーにわたる提案を含みます。例えば: # 新機能の提案: 新しい機能や機能の変更についての提案が含まれます。例えば、新しい文法、標準ライブラリへの追加、言語の機能強化などがあります。 # 改善案: Pythonの改善や修正に関する提案も含まれます。これには、パフォーマンスの向上、既存の機能の改善、コードの可読性の向上などが含まれます。 # プロセスやガイドライン: Pythonコミュニティの運営や開発プロセスに関する提案もあります。例えば、コードスタイルのガイドライン、バージョン管理に関する規則、開発プロセスの改善などが挙げられます。 PEPはPythonの設計や開発プロセスに透明性と一貫性をもたらし、Pythonの成長と発展を支えてきました。PEPが提案されると、Pythonのコミュニティで議論され、採用されることがあります。採用されたPEPは、将来のPythonのバージョンで実装されることがあります。 }} == Python 3.12 の新機能 == Python 3.12 には、いくつかの新機能が追加されています。以下にいくつかの新機能とそれらを使用するためのコード例を示します。 * Parenthesized context managers in with statements Python 3.12 では、with ステートメントのコンテキストマネージャーに括弧を付けることができます。これにより、コンテキストマネージャーが複数の行にまたがっている場合に、より読みやすいコードを書くことができます。 ;コード例:<syntaxhighlight lang=python3> # Before Python 3.12 with open("file.txt", "r") as file1, open("file2.txt", "r") as file2: # do something with file1 and file2 # With Python 3.12 with (open("file.txt", "r"), open("file2.txt", "r")) as (file1, file2): # do something with file1 and file2 </syntaxhighlight> *Pattern matching improvements Python 3.10 で導入されたパターンマッチングには、Python 3.12 で改良が加えられました。例えば、以下のように | を使用して複数のパターンをマッチングすることができます。 ;コード例:<syntaxhighlight lang=python3> # Before Python 3.12 def my_function(x): if isinstance(x, int): # do something elif isinstance(x, str): # do something else elif isinstance(x, list): # do something else else: raise ValueError("Invalid argument type") # With Python 3.12 def my_function(x): match x: case int: # do something case str: # do something else case list | tuple: # do something else case _: raise ValueError("Invalid argument type") </syntaxhighlight> *New zoneinfo module for working with time zones Python 3.9 で導入された zoneinfo モジュールは、Python 3.12 で改良が加えられました。これにより、タイムゾーンを扱うためのさまざまな機能が追加されました。 ;コード例:<syntaxhighlight lang=python3> # Before Python 3.12 import datetime import pytz tz = pytz.timezone("Asia/Tokyo") now = datetime.datetime.now(tz) # With Python 3.12 import datetime import zoneinfo tz = zoneinfo.ZoneInfo("Asia/Tokyo") now = datetime.datetime.now(tz) </syntaxhighlight> {{stub}} == 整理作業中 == [[Python/整理中]] (複素数、正規表現、HTTPクライアント、JSON、pass) [[Category:Python]] [[Category:プログラミング言語]] {{NDC|007.64}} 57oykte613p719cutx1yhfs1kvh0fzn Fortran 0 17049 263753 242740 2024-11-18T09:17:35Z Ef3 694 /* 附録 */ * [[/改廃された技術|改廃された技術]] 263753 wikitext text/x-wiki <small>{{Pathnav|メインページ|工学|情報技術|プログラミング}}</small> ---- {{Wikipedia|FORTRAN|FORTRAN}} Fortran(フォートラン)は[[w:数値解析|数値計算]]用の[[w:コンパイラ|コンパイラ]]言語です。 この教科書では、最新の機能を取り入れたFortran90、Fortran95について勉強します。 <!--from:https://en.wikibooks.org/w/index.php?title=Fortran&oldid=3870367--> == はじめに == * [[/なぜFortranを学ぶのか?|なぜFortranを学ぶのか?]] * [[/歴史|歴史]] == クイックスタート・チュートリアル == * [[/Hello world|Hello world]] <!-- Hello World --> * [[/基本|基本]] <!-- Fundamentals --> * [[/変数|変数]] <!-- Variables --> * [[/テキスト入出力|テキスト入出力]] <!-- Text input and output --> * [[/プログラムのフロー制御|プログラムのフロー制御]] <!-- Program flow control --> * [[/サブルーチンと関数|サブルーチンと関数]] <!-- Subroutines and functions --> ==Fortranの詳細== * [[/データ型|データ型]] * [[/形式と構造|形式と構造]] * [[/入出力文|入出力文]] * [[/文字列操作|文字列操作]] * [[/構造化データ|構造化データ]] * [[/メモリ管理と共通ブロック|メモリ管理と共通ブロック]] * [[/エラーの捕捉|エラーの捕捉]] * [[/並列処理|並列処理]] * [[/オブジェクト指向プログラミング|オブジェクト指向プログラミング]] * [[/言語の拡張とオーバーロード|言語の拡張とオーバーロード]] == その他のFortran関連ソフトウェア・ツール == * [[/言語の混合|言語の混合]] * ドキュメント生成ツール * ソースコード整形ツール == 附録 == * [[/コードギャラリー|コードギャラリー]] * [[/Fortranの活用例|Fortranの活用例]] * [[/よくある質問|よくある質問]] * [[/改廃された技術|改廃された技術]] ==未整理== {{Special:Prefixindex/Fortran}} === 外部リンク === *[https://www.mri-jma.go.jp/Project/mrinpd/coderule.html Fortran 標準コーディングルール]([https://www.mri-jma.go.jp/Project/mrinpd/coderule.html WARPのアーカイブ])(気象庁の数値モデル開発に携わる有志によりとりまとめられたもの) *[[dmoz:Computers/Programming/Languages/Fortran/Tutorials/Fortran 90 and 95|Open Directory - F95/F90 Tutorials]]を参照してください。 *[http://www.eclipse.org/photran/ EclipseベースのIDE fortran]. *[https://github.com/jerryd/gtk-fortran/wiki gtk-fortran, a GTK+ / Fortran 2003 binding project]. ===コンパイラー=== *[http://www.g95.org g95 コンパイラ]. *[http://www.gnu.org/software/fortran/fortran.html GNU g77 (gcc) Fortran 77 コンパイラ]. *[http://gcc.gnu.org/fortran/ GNU gfortran (gcc) Fortran 95 コンパイラ] *[http://gcc.gnu.org/fortran/ GNU gfortran (gcc) Fortran 95 コンパイラ] 。 *[http://www.intel.com/cd/software/products/asmo-na/eng/compilers/flin/ Intel Fortran Compiler for Linux: a free non-commercial Fortran compiler]. *[http://developers.sun.com/sunstudio Free Sun Fortran 95, C, and C++ compilers and tools]. [[Category:Fortran|*]] [[Category:プログラミング言語]] 2puc801gyjxqzn57pcqjcdui4u4g1h5 平家物語 祇園精舎 0 17362 263735 263327 2024-11-18T02:49:20Z ~2024-14548 84961 /* 本文 */ 263735 wikitext text/x-wiki [[文学]]>[[古典文学]]>[[日本の古典]]>[[平家物語]] [[Category:平家物語|きおんしようしや]] ==本文== [[w:祇園精舍|祇園精舍]]の鐘の音、[[w:諸行無常|諸行無常]]の響きあり。[[w:娑羅双樹|娑羅双樹]]の土の色、盛者必衰の理をあらはす。驕れる人も久しからず、ただ春の夜の夢のごとし。猛き者もつひにはほろびぬ、ひとへに風の前の塵に同じ。 遠く[[w:中国の歴史|異朝]]をとぶらへば、[[w:秦|秦]]の[[w:趙高|趙高]]、[[w:漢|漢]]の[[w:王莽|王莽]]、[[w:梁 (南朝)|梁]]の[[w:朱イ|朱异]]、[[w:唐|唐]]の[[w:安禄山|祿山]]、これらは皆[[w:君主|舊主]][[w:皇帝|先皇]]の[[w:政治|政]]にもしたがはず、樂しみをきはめ、諌めをも思ひ入れず、[[w:天下|天下]]の亂れん事を悟らずして、[[w:民間|民間]]の愁ふるところを知らざりしかば、久しからずして、亡じにし者どもなり。 近く[[w:日本の歴史|本朝]]をうかがふに、[[w:承平 (日本)|承平]]の[[w:平将門|將門]]、[[w:天慶|天慶]]の[[w:藤原純友|純友]]、[[w:康和|康和]]の[[w:源義親|義親]]、[[w:平治|平治]]の[[w:藤原信頼|信賴]]、これらはおごれる心もたけき事も、皆とりどりにこそありしかども、まぢかくは[[w:六波羅|六波羅]]の[[w:入道|入道]]、[[w:太政大臣|前太政大臣]][[w:平清盛|平朝臣清盛公]]と申しし人のありさま、傳へ承るこそ心もことばも及ばれね。 その[[w:先祖|先祖]]を尋ぬれば[[w:桓武天皇|桓武天皇]]第五の皇子、[[w:一品|一品]][[w:式部省|式部卿]][[w:葛原親王|葛原親王]]九代の後胤、[[w:讃岐|讃岐守]][[w:平正盛|正盛]]が孫、[[w:刑部省|刑部卿]][[w:平忠盛|忠盛]]朝臣の[[w:嫡男|嫡男]]なり。かの[[w:親王|親王]]の[[w:王 (皇族)|御子]]、[[w:高見王|高見王]]、無官無位にして失せ給ひぬ。その御子、[[w:高望王|高望王]]の時、初めて平の姓を賜はつて、[[w:上総|上総介]]に成り給ひしより、たちまちに王氏を出でて人臣に列なる、その子[[w:鎮守府将軍|鎮守府将軍]][[w:平国香|良望]]、後には[[w:平国香|國香]]と改む。國香より正盛に至る六代は、諸国の[[w:受領|受領]]たりしかども、[[w:昇殿|殿上]]の仙籍をば未だ赦されず。 磯辺揚げも美味しからず。トイレに行けば膀胱あらず。 ---- ==本文の読み方== [[w:祇園精舎|ぎおんしょうじゃ]]のかねのこえ、[[w:諸行無常|しょぎょうむじょう]]のひびきあり。 [[w:沙羅双樹|しゃらそうじゅ]]のはなのいろ、 じょうしゃひっすいのことわりをあらわす。 おごれるひともひさしからず、 ただはるのよのゆめのごとし。 たけきものもついにはほろびぬ、 ひとえにかぜのまえのちりにおなじ。 とおく[[w:異朝|いちょう]]をとぶらえば、 しんのちょうこう、かんのおうもう、りょうのしゅうい、とうのろくさん、 これらはみな、きゅうしゅせんこうのまつりごとにもしたがわず、 たのしみをきわめ、いさめをもおもいいれず、 てんかのみだれんことをさとらずして、 みんかんのうれうるところをしらざつしかば、 ひさしからずしてぼうじにしものどもなり。 ちかくほんちょうをうかがうに、 じょうへいのまさかど、てんぎょうのすみとも、こうわのぎしん、へいじののぶより、 これらはおごれるこころも、たけきこともみなとりどりにこそありしかども、まぢかくは、 ろくはらのにゅうどう、さきのだいじょうだいじん、たいらのあそんきよもりこうともうししひとのありさま、 つたえうけたまわるこそ、こころもことばもおよばれね。 そのせんぞをたずぬればかんむてんのうだいごのおうじ、 いっぽんしきぶきょうかずらはらしんのうくだいのこういん、さぬきのかみまさもりがまご、 ぎょうぶきょうただもりのあそんのちゃくなんなり。 かのしんのうのみこ、たかみのおう、むかんむいにしてうせたまいぬ。 そのみこ、たかもちのおうのとき、はじめてへいのしょうをたまわって、 かずさのすけになりたまいしより、たちまちにおうしをいでてじんしんにつらなる。 そのこちんじゅふのしょうぐんよしもち、のちにはくにかとあらたむ。 くにかよりまさもりにいたるまでろくだいは、しょこくのずりょうたりしかども、 てんじょうのせんせきをばいまだゆるされず。 ==現代語訳== [[w:祇園精舍|祇園精舍]]の鐘の音には、[[w:諸行無常|諸行無常]]すなわちこの世のすべての現象は絶えず変化していくものだという響きがある。[[w:娑羅双樹|娑羅双樹]]の花の色は、どんなに勢いが盛んな者も必ず衰えるものであるという道理をあらわしている。世に栄え得意になっている者も、その栄えはずっとは続かず、春の夜の夢のようである。勢い盛んではげしい者も、結局は滅び去り、まるで風に吹き飛ばされる塵と同じようである。 遠い[[w:中国の歴史|外国]](の例)を見ると、[[w:秦|秦]]の[[w:趙高|趙高]]、[[w:漢|漢]]の[[w:王莽|王莽]]、[[w:梁 (南朝)|梁]]の[[w:朱イ|朱忌]]、[[w:唐|唐]]の[[w:安禄山|安禄山]]、これらはみな元の[[w:君主|君主]]や先代[[w:皇帝|皇帝]]の政治に従わず、(栄華の)楽しみを極め、忠告にも深く考えようとはせず、[[w:天下|天下]]が乱れることもわからずに、人々の苦労するところとなるものも知らなかったので、長続きせずに滅びた者たちである。 身近な[[w:日本の歴史|日本]](の例)を見ると、[[w:承平天慶の乱|承平]]の[[w:平将門|平将門]]、[[w:承平天慶の乱|天慶]]の[[w:藤原純友|藤原純友]]、[[w:康和|康和]]の[[w:源義親|源義親]]、[[w:平治の乱|平治]]の[[w:藤原信頼|藤原信頼]]、(これらの人は)得意になる心も猛々しい心も、みなそれぞれ持っていたが、最近では[[w:六波羅|六波羅]]の[[w:入道|入道]]、[[w:太政大臣|前太政大臣]][[w:平清盛|平朝臣清盛公]]と申した人の様子は伝え聞いても想像することも形容することもできない(ほどである)。 その清盛の[[w:先祖|先祖]]を調べると、[[w:桓武天皇|桓武天皇]]の第五皇子、一品式部卿葛原親王から数えて九代目の子孫、讃岐守正盛の孫で、刑部卿忠盛の嫡男である。葛原親王の御子、高見王は、官職も官位もないままなくなられた。その御子の高望王のとき、初めて平の姓を賜わって、上総介になられてから、ただちに皇籍を離れて臣下の列に連なる。その子・鎮守府将軍良望は、後には国香と名を改めた国香から正盛に至るまでの六代は、諸国の国守ではあったが、殿上人として昇殿することは、まだ許されなかった。 ---- [[File:平家物語・祇園精舎サンプル3.png|thumb|left|祇園精舎 原文]] [[File:平家物語・祇園精舎 現代語訳.png|thumb|none|祇園精舎 現代語訳]] 9yr7m1xrz0nzl76aesq5l9n5hduei9x 263743 263735 2024-11-18T05:15:53Z Tomzo 248 [[Special:Contributions/~2024-14548|~2024-14548]] ([[User talk:~2024-14548|会話]]) による編集を取り消し、なむから による直前の版へ差し戻す 263327 wikitext text/x-wiki [[文学]]>[[古典文学]]>[[日本の古典]]>[[平家物語]] [[Category:平家物語|きおんしようしや]] ==本文== [[w:祇園精舍|祇園精舍]]の鐘の声、[[w:諸行無常|諸行無常]]の響きあり。[[w:娑羅双樹|娑羅双樹]]の花の色、盛者必衰の理をあらはす。驕れる人も久しからず、ただ春の夜の夢のごとし。猛き者もつひにはほろびぬ、ひとへに風の前の塵に同じ。 遠く[[w:中国の歴史|異朝]]をとぶらへば、[[w:秦|秦]]の[[w:趙高|趙高]]、[[w:漢|漢]]の[[w:王莽|王莽]]、[[w:梁 (南朝)|梁]]の[[w:朱イ|朱异]]、[[w:唐|唐]]の[[w:安禄山|祿山]]、これらは皆[[w:君主|舊主]][[w:皇帝|先皇]]の[[w:政治|政]]にもしたがはず、樂しみをきはめ、諌めをも思ひ入れず、[[w:天下|天下]]の亂れん事を悟らずして、[[w:民間|民間]]の愁ふるところを知らざりしかば、久しからずして、亡じにし者どもなり。 近く[[w:日本の歴史|本朝]]をうかがふに、[[w:承平 (日本)|承平]]の[[w:平将門|將門]]、[[w:天慶|天慶]]の[[w:藤原純友|純友]]、[[w:康和|康和]]の[[w:源義親|義親]]、[[w:平治|平治]]の[[w:藤原信頼|信賴]]、これらはおごれる心もたけき事も、皆とりどりにこそありしかども、まぢかくは[[w:六波羅|六波羅]]の[[w:入道|入道]]、[[w:太政大臣|前太政大臣]][[w:平清盛|平朝臣清盛公]]と申しし人のありさま、傳へ承るこそ心もことばも及ばれね。 その[[w:先祖|先祖]]を尋ぬれば[[w:桓武天皇|桓武天皇]]第五の皇子、[[w:一品|一品]][[w:式部省|式部卿]][[w:葛原親王|葛原親王]]九代の後胤、[[w:讃岐|讃岐守]][[w:平正盛|正盛]]が孫、[[w:刑部省|刑部卿]][[w:平忠盛|忠盛]]朝臣の[[w:嫡男|嫡男]]なり。かの[[w:親王|親王]]の[[w:王 (皇族)|御子]]、[[w:高見王|高見王]]、無官無位にして失せ給ひぬ。その御子、[[w:高望王|高望王]]の時、初めて平の姓を賜はつて、[[w:上総|上総介]]に成り給ひしより、たちまちに王氏を出でて人臣に列なる、その子[[w:鎮守府将軍|鎮守府将軍]][[w:平国香|良望]]、後には[[w:平国香|國香]]と改む。國香より正盛に至る六代は、諸国の[[w:受領|受領]]たりしかども、[[w:昇殿|殿上]]の仙籍をば未だ赦されず。 ---- ==本文の読み方== [[w:祇園精舎|ぎおんしょうじゃ]]のかねのこえ、[[w:諸行無常|しょぎょうむじょう]]のひびきあり。 [[w:沙羅双樹|しゃらそうじゅ]]のはなのいろ、 じょうしゃひっすいのことわりをあらわす。 おごれるひともひさしからず、 ただはるのよのゆめのごとし。 たけきものもついにはほろびぬ、 ひとえにかぜのまえのちりにおなじ。 とおく[[w:異朝|いちょう]]をとぶらえば、 しんのちょうこう、かんのおうもう、りょうのしゅうい、とうのろくさん、 これらはみな、きゅうしゅせんこうのまつりごとにもしたがわず、 たのしみをきわめ、いさめをもおもいいれず、 てんかのみだれんことをさとらずして、 みんかんのうれうるところをしらざつしかば、 ひさしからずしてぼうじにしものどもなり。 ちかくほんちょうをうかがうに、 じょうへいのまさかど、てんぎょうのすみとも、こうわのぎしん、へいじののぶより、 これらはおごれるこころも、たけきこともみなとりどりにこそありしかども、まぢかくは、 ろくはらのにゅうどう、さきのだいじょうだいじん、たいらのあそんきよもりこうともうししひとのありさま、 つたえうけたまわるこそ、こころもことばもおよばれね。 そのせんぞをたずぬればかんむてんのうだいごのおうじ、 いっぽんしきぶきょうかずらはらしんのうくだいのこういん、さぬきのかみまさもりがまご、 ぎょうぶきょうただもりのあそんのちゃくなんなり。 かのしんのうのみこ、たかみのおう、むかんむいにしてうせたまいぬ。 そのみこ、たかもちのおうのとき、はじめてへいのしょうをたまわって、 かずさのすけになりたまいしより、たちまちにおうしをいでてじんしんにつらなる。 そのこちんじゅふのしょうぐんよしもち、のちにはくにかとあらたむ。 くにかよりまさもりにいたるまでろくだいは、しょこくのずりょうたりしかども、 てんじょうのせんせきをばいまだゆるされず。 ==現代語訳== [[w:祇園精舍|祇園精舍]]の鐘の音には、[[w:諸行無常|諸行無常]]すなわちこの世のすべての現象は絶えず変化していくものだという響きがある。[[w:娑羅双樹|娑羅双樹]]の花の色は、どんなに勢いが盛んな者も必ず衰えるものであるという道理をあらわしている。世に栄え得意になっている者も、その栄えはずっとは続かず、春の夜の夢のようである。勢い盛んではげしい者も、結局は滅び去り、まるで風に吹き飛ばされる塵と同じようである。 遠い[[w:中国の歴史|外国]](の例)を見ると、[[w:秦|秦]]の[[w:趙高|趙高]]、[[w:漢|漢]]の[[w:王莽|王莽]]、[[w:梁 (南朝)|梁]]の[[w:朱イ|朱忌]]、[[w:唐|唐]]の[[w:安禄山|安禄山]]、これらはみな元の[[w:君主|君主]]や先代[[w:皇帝|皇帝]]の政治に従わず、(栄華の)楽しみを極め、忠告にも深く考えようとはせず、[[w:天下|天下]]が乱れることもわからずに、人々の苦労するところとなるものも知らなかったので、長続きせずに滅びた者たちである。 身近な[[w:日本の歴史|日本]](の例)を見ると、[[w:承平天慶の乱|承平]]の[[w:平将門|平将門]]、[[w:承平天慶の乱|天慶]]の[[w:藤原純友|藤原純友]]、[[w:康和|康和]]の[[w:源義親|源義親]]、[[w:平治の乱|平治]]の[[w:藤原信頼|藤原信頼]]、(これらの人は)得意になる心も猛々しい心も、みなそれぞれ持っていたが、最近では[[w:六波羅|六波羅]]の[[w:入道|入道]]、[[w:太政大臣|前太政大臣]][[w:平清盛|平朝臣清盛公]]と申した人の様子は伝え聞いても想像することも形容することもできない(ほどである)。 その清盛の[[w:先祖|先祖]]を調べると、[[w:桓武天皇|桓武天皇]]の第五皇子、一品式部卿葛原親王から数えて九代目の子孫、讃岐守正盛の孫で、刑部卿忠盛の嫡男である。葛原親王の御子、高見王は、官職も官位もないままなくなられた。その御子の高望王のとき、初めて平の姓を賜わって、上総介になられてから、ただちに皇籍を離れて臣下の列に連なる。その子・鎮守府将軍良望は、後には国香と名を改めた国香から正盛に至るまでの六代は、諸国の国守ではあったが、殿上人として昇殿することは、まだ許されなかった。 ---- [[File:平家物語・祇園精舎サンプル3.png|thumb|left|祇園精舎 原文]] [[File:平家物語・祇園精舎 現代語訳.png|thumb|none|祇園精舎 現代語訳]] mou5k0xi85ssjw5155n63lwqf42q1kj 高校化学 天然高分子化合物 0 18195 263787 260830 2024-11-18T11:37:45Z Nermer314 62933 /* アミノ酸の反応 */ 263787 wikitext text/x-wiki {{pathnav|高等学校の学習|高等学校理科|高等学校 化学|pagename=天然高分子化合物|frame=1|small=1}} == 糖類 == 多数のヒドロキシ基を持つ、分子式 <chem>C_{m}(H2O){}_{n}</chem> で表される化合物を'''糖類'''(saccharides)または'''炭水化物'''(carbohydrate)という。 それ以上加水分解しない最小の糖類を'''単糖'''という。単糖2分子が脱水縮合した糖類を'''二糖(disaccharide)'''、単糖2~10分子程度が脱水縮合した糖類をオリゴ糖、多数の単糖が脱水縮合した糖類を'''多糖(polysaccharide)'''という。 水溶液中で鎖式構造がホルミル基をもつ糖を'''アルドース'''(aldose)、カルボニル基をもつ糖を'''ケトース'''という。 主な単糖として、グルコース、フルクトース、ガラクトース。 主な二糖として、マルトース、スクロース、ラクトース、セロビオース。 主な多糖として、デンプン、セルロースが挙げられる。 === 投影式 === 糖類の立体配置を表すために'''ハース投影式'''と'''フィッシャー投影式'''を用いる。まずはこれについて学ぼう。 [[ファイル:Beta-D-Glucopyranose.svg|中央|サムネイル|βグルコースのハース投影式]] ハース投影式では、上方向に出ている結合は環から上向きに、下方向に出ている結合は環から下向きに出る。 フィッシャー投影式では、十字の中心は不斉炭素原子とし、左右の結合は紙面(画面)の手前に、上下の結合は紙面(画面)の奥に出る。 [[ファイル:Fischer Projection2.svg|中央|サムネイル|フィッシャー投影式]] [[ファイル:DGlucose Fischer.svg|中央|サムネイル|鎖式グルコースのフィッシャー投影式。左右の結合は手前側に出ている。]] === 単糖 === ==== グルコース ==== グルコース glucose(ブドウ糖)<chem>C6H12O6</chem> は、デンプンを加水分解することによって得られる。 :(C<sub>6</sub>H<sub>10</sub>O<sub>5</sub>)<sub>n</sub> + nH<sub>2</sub>O → nC<sub>6</sub>H<sub>12</sub>O<sub>6</sub> グルコースは甘味をもち、また、水によく溶ける。水溶液中のグルコースは、一部のグルコースの環構造が開き鎖式構造に変わる。ホルミル基を持ち、還元性を示す。従って、銀鏡反応やフェーリング反応を示す。 グルコースはアルドースである。 グルコースは水溶液中で'''αグルコース'''と'''鎖式グルコース'''と'''βグルコース'''の3種類の構造がある。 αグルコースを水に溶かすと、上記のように一部が鎖式グルコースになり、さらにその一部が鎖式構造を経てβグルコースになる。最終的に3種類のグルコースのα形、鎖式、β型の混じりあった平衡状態になる。 [[File:Alpha-D-Glucopyranose.svg|thumb|150px|left|αグルコース]] [[File:Beta-D-Glucopyranose.svg|thumb|150px|center|βグルコース]] {{clear}} ==== フルクトース ==== フルクトースfructose(果糖, fruit sugar )<chem>C6H12O6</chem> は水溶液中で、一部が鎖式フルクトースを経て、五員環フルクトース、六員環フルクトースになる。五員環フルクトースと六員環フルクトースにはα型とβ型が存在するため、フルクトースは水溶液中では5種類の構造が存在する。 フルクトースはケトースである。 [[ファイル:Isomeric forms of fructose.svg|フルクトースの平衡。左と中央2個は鎖式フルクトースで書き方を変えただけで同じ構造。右上はα型の五員環フルクトース、右下はα型の六員環フルクトース。右の五員環と六員環のフルクトースの一位のOHが上にあるβ型フルクトースも合わせると水溶液中のフルクトースは5種類が存在する。|代替文=フルクトースの平衡|中央|フレーム]] 鎖状構造のフルクトースにはホルミル基は無いが、一部が異性化し、ホルミル基を持つので還元性を示す。 フルクトースは、天然に存在する糖類の中で最も甘く、果実などに含まれることが多い。 [[ファイル:Beta-D-Fructopyranose.svg|thumb|150px|left|六員環のβフルクトース]] [[ファイル:Beta-D-Fructofuranose.svg|thumb|150px|center|五員環のβフルクトース]] {{clear}}'''アルコール発酵''' グルコースやフルクトースなどの6炭糖は酵素群チマーゼによって'''アルコール発酵'''を起こす。 C<sub>6</sub>H<sub>12</sub>O<sub>6</sub> → 2C<sub>2</sub>H<sub>5</sub>OH + 2CO<sub>2</sub> ==== ガラクトース ==== ガラクトースはグルコースの4位の不斉炭素原子の立体配置が異なる単糖である。寒天の成分であるガラクタンを加水分解すると、ガラクトースが得られる。ヘミアセタール構造が存在するので、水溶液は還元性をしめす。 [[ファイル:Beta-D-Galactopyranose.svg|中央|サムネイル|βガラクトース]] === ニ糖類 === [[ファイル:Sucrose-inkscape.svg|thumb|200px|二糖の一種であるスクロース]] 二糖類を構成する単糖類の縮合したエーテル結合を'''グリコシド結合'''という。 主な二糖類には、スクロース、マルトース、セロビオース、ラクトースがある。 ==== ヘミアセタール構造 ==== 有機化合物中の、ある一つのC原子に対して、そのC原子にヒドロキシル基 -OH とエーテル結合 -O- が隣り合ってる構造を、'''ヘミアセタール構造'''という。グルコースで、ヘミアセタール構造をもつのは、一箇所だけである。水溶液中のグルコースでは、このヘミアセタール構造が変形してアルデヒドを形成している。 このヘミアセタール構造の有無を、糖類の構造式を見て調べることで、糖類の水溶液中の還元性を予測できる。まず、構造式中のエーテル結合-O- を持つ部分を探してそのOに隣り合ったC原子が-OH を持つかどうかでヘミアセタール構造の有無を判別する。 ==== スクロース ==== [[ファイル:Sucrose-inkscape.svg|thumb|250px|スクロース]]スクロース(sucrose)は、αグルコースとβフルクトースがα-1,2-グリコシド結合した構造をもつ。 スクロースの水溶液は還元性を示さない。これは、グルコースとフルクトースの還元性をしめすヘミアセタール構造の部分で縮合が行われていることによる。 砂糖の主成分であり、サトウキビやテンサイに含まれる。 * 加水分解 希酸または酵素インペルターゼでスクロースを加水分解すると、グルコースとフルクトースの等量混合物になる。 C<sub>12</sub>H<sub>22</sub>O<sub>11</sub> (スクロース) + H<sub>2</sub>O → C<sub>6</sub>H<sub>12</sub>O<sub>6</sub>(グルコース) + C<sub>6</sub>H<sub>12</sub>O<sub>6</sub> (フルクトース) グルコースとフルクトースの等量混合物を'''転化糖'''(invert sugar)という。スクロースを加水分解すると転化糖が得られる。 ==== マルトース ==== [[File:Maltose Gleichgewicht.svg|thumb|400px|マルトース(左)と、水溶液中でのアルデヒド基の出現(右)]] (麦芽糖) αグルコース2分子が縮合した構造。 * 特徴 還元性を示す。 * 加水分解 希酸または酵素マルターゼで加水分解される。 デンプンを酵素アミラーゼで加水分解するとマルトースが生じる。 ==== セロビオース ==== [[ファイル:Cellobiose skeletal.svg|サムネイル|セロビオース]] セロビオースはβ-グルコース2分子がβ-1,4-グリコシド結合した二糖である。 セルロースにセルラーゼを作用させると加水分解しセロビオースが生じる。 ==== ラクトース ==== [[File:Lactose(lac).png|thumb|300px|ラクトース]] (乳糖) ラクトース(lactose)は、ガラクトースとαグルコースが縮合した構造。 * 特徴 ラクトースの水溶液は還元性を示す。 * 加水分解 酵素ラクターゼによってラクトースは加水分解され、ガラクトースとグルコースになる。 牛乳など、哺乳類の乳汁にラクトースは含まれる。 ==== トレハロース ==== [[File:Trehalose.png|thumb|トレハロース]] : トレハロースの構造は、αグルコースが2分子からなり、αグルコースの1位の還元基どうしが結合した構造となっている。このことからもわかるように、トレハロースの水溶液は還元性を示さない。 自然界では、昆虫の体液、キノコやカビ、海藻などに含まれる。 {| class="wikitable" |+ !名前 !構成する単糖 !グリコシド結合 !還元性 |- |スクロース |グルコース+フルクトース |α-1,2 |なし |- |マルトース |グルコース+グルコース |α-1,4 |あり |- |セロビオース |グルコース+グルコース |β-1,4 |あり |- |ラクトース |ガラクトース+グルコース |β-1,4 |あり |- |トレハロース |グルコース+グルコース |α-1,1 |なし |} === 多糖類 === ==== デンプン ==== デンプン(starch)は、植物が光合成によって体内につくる多糖類である。二糖類とちがい、デンプンは甘味をしめさない。また、デンプンは、還元性を示さない。 デンプンは、多数のαグルコースが脱水縮合して出来た構造をもつ多糖類の高分子化合物である。 (C<sub>6</sub>H<sub>10</sub>O<sub>5</sub>)<sub>n </sub>の構造を持つ。nは数百から数十万である。 * デンプンの性質 デンプンは冷水には溶けにくいが、約80℃の熱水には溶けてコロイド状のデンプンのりになる。 酵素'''アミラーゼ'''によって、デンプンは加水分解される。このアミラーゼによるデンプンの加水分解の結果、デンプンの重合数が少なくなった'''デキストリン'''(C<sub>6</sub>H<sub>10</sub>O<sub>5</sub>)<sub>n </sub>を生じる。そしてデキストリンは、さらに二糖類の'''マルトース'''に分解される。 マルトースに対しては、酵素'''マルターゼ'''によって、グルコースになる。 デンプンからグルコースまでの順序を化学式にまとめれば、 (C<sub>6</sub>H<sub>10</sub>O<sub>5</sub>)<sub>n </sub>デンプン→ (C<sub>6</sub>H<sub>10</sub>O<sub>5</sub>)<sub>m</sub> デキストリン → C<sub>12</sub>H<sub>22</sub>O<sub>11</sub> マルトース→ C<sub>6</sub>H<sub>12</sub>O<sub>6</sub> グルコース である。(デンプンとデキストリンの重合数について、n>mとした。) デンプンには還元性は無い。したがってデンプンは、フェーリング液を還元しない。 ===== ヨウ素デンプン反応 ===== [[File:ヨウ素デンプン反応の分子構造.svg|thumb|500px|ヨウ素デンプン反応の分子構造]] ヨウ化カリウム水溶液KIにより、デンプンは青紫色に呈色する。加熱すると、無色になる。この反応を'''ヨウ素デンプン反応'''(iodine-starch reaction)という。 デンプンは水溶液中では、分子内の水素結合により、らせん構造をとる。このらせん構造の中にヨウ素が入りこむことで、呈色する。 加熱で無色になっても、冷却すると、再び、もとの青紫色の呈色を示すようになる。 ===== アミロースとアミロペクチン ===== [[File:Amylose2.svg|thumb|right|270px|アミロースの分子構造]] [[File:Amylopektin Sessel.svg|thumb|right|アミロペクチンの分子構造]] デンプンの種類のうち、αグルコースが直鎖状に結合したものを'''アミロース'''(amylose)と言う。αグルコースが、ところどころ枝分かれした構造のデンプンを'''アミロペクチン'''(amylopectin)という。枝分かれの割合はαグルコース数十個につき、一個の枝分かれの程度である。 もち米のデンプンは、アミロペクチンが100%である。ふつうの植物のデンプンには、アミロースが20%程度でアミロペクチンが80%程度ほど含まれている。 * アミロース グルコースの1位と4位が結合して重合した構造になっている。 ヨウ素デンプン反応では、アミロースは青色。多くのヒドロキシル基を持ち、極性を持つ部分が多いため、熱湯には、比較的、溶けやすい。冷水には溶けにくい。 * アミロペクチン グルコースの1位と4位が結合して重合したほかに、1位と6位が結合した重合構造になっている。 1位と6位の結合のため、構造に枝分かれ上の分岐が起こる。 ヨウ素デンプン反応では、アミロペクチンは赤紫色。アミロースとの色の違いは、直鎖状の長さの違いによって、ヨウ素との結合力に違いが生じたからある。ヨウ素と反応することから分かるように、アミロペクチンもらせん構造を取る。枝分かれをするものの、分かれた枝の先がそれぞれらせん構造をとる。 熱湯には、溶けにくい。冷水にも溶けにくい。 ==== グリコーゲン ==== [[File:Glycogen structure.svg|thumb|260px|グリコーゲンの断面図]] '''グリコーゲン'''(glycogen)は、動物の肝臓に多い多糖類で、その構造はアミロペクチンと似ているが、アミロペクチンよりも枝分かれが多い。分岐の頻度は、おおむね8~12基に一回の程度の分岐である。枝分かれが多いため放射したような網目構造をとり、らせん構造をとらない。このため、極性をもった部分が外側に出やすく、水溶性が高い。 ヨウ素デンプン反応では、グリコーゲンは赤褐色を示す。 * グリコーゲンを含む生体には、動物の体内で栄養素として多いことから、'''動物デンプン'''ともよばれる。 * グリコーゲンは肝臓や筋肉に多く含まれる。 ==== セルロース ==== [[Image:Cellulose-2D-skeletal.svg|thumb|240px|セルロースの構造式]] [[File:Alg-frut-6.jpg|left|thumb|200px|綿花から取れる綿は天然のセルロースである。]] '''セルロース'''(cellulose)[C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)<sub>3</sub>]<sub>n </sub>は植物の細胞壁の主成分である。木綿、パルプ、ろ紙は、ほぼ純粋なセルロースである。セルロースの構造は、多数のβグルコースが、直線状に縮合した構造である。セルロースの構造では、各グルコースの向きが交互に表・裏・表・裏を繰り返すので、セルロース全体で見れば直線状になっている。 * セルロースは、還元性を持たず、また、ヨウ素デンプン反応も示さない。 * セルロースは、冷水や熱水には溶けない。セルロースは、エーテルやアルコールなどにも溶けない。 * セルロースは'''シュバイツアー試薬'''に溶ける。 シュバイツアー試薬とは、水酸化銅Cu(OH)2を濃アンモニア水に溶かしたものである。水溶液中でイオンが、'''テトラ アンミン イオン''' [Cu(NH<sub>3</sub>)<sub>4</sub>]<sup>2+</sup> になる。 セルロースの示性式は、[C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)<sub>3</sub>]<sub>n </sub>である。グルコース1単位あたり3個のヒドロキシル基OHを持つ。したがって、酸と反応させるとエステルを作りやすく、酢酸や硝酸とエステルをつくる。 セルロースは、酸をくわえて長時間加熱すると、最終的にグルコースになる。 このほか、酵素セルラーゼによって、セルロースは分解される。 工業上は硝酸とのセルロースのエステルである「ニトロセルロース」(後述する。)が、特に重要である。 {{clear}} ==== セルロースの誘導体 ==== ===== ニトロセルロース ===== セルロース[C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)<sub>3</sub>]<sub>n</sub>に、濃硝酸および濃硫酸の混合溶液(混酸)を作用させると、セルロースのOH基の一部または全部がエステル化される。セルロース中のグルコース1単位あたり、3個のOH基の一部または3個全部が硝酸エステル化されたものをニトロセルロース(nitrocellulose)という。特にセルロース中のグルコース1単位のうち、3個のOH基すべてが硝酸エステル化されたもの [C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(ONO<sub>2</sub>)<sub>3</sub>]<sub>n</sub> を'''トリニトロセルロース'''という。 [C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)<sub>3</sub>]<sub>n</sub> + 3n HONO<sub>2</sub> → [C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(ONO<sub>2</sub>)<sub>3</sub>]<sub>n</sub> + 3n H<sub>2</sub>O このトリニトロセルロースは火薬の原料である。 ===== ジニトロセルロース ===== セルロース中の2個のOH基がエステル化したものはジニトロセルロースという。このジニトロセルロースは、有機溶媒に溶ける。 * コロジオン このジニトロセルロースを、エタノールとエーテルの混合液に溶かしたものを'''コロジオン'''という。混合液には水分などを含まないので「水溶液」では無いことに注意。 コロジオンの溶液を蒸発させると、薄い膜が残る。これは半透膜の材料に使われる。コロジオンから得られた半透膜のことをコロジオン膜ともいう。 * セルロイド ニトロセルロースをエタノールに溶かし、ショウノウを加えて得られる樹脂をセルロイドという。 ===== アセテート類 ===== セルロースを無水酢酸、氷酢酸および少量の濃硫酸との混合物を反応させる。すると、分子中のOH基中のHがCOOH基で置換される'''アセチル化'''が起きて、'''トリアセチルセルロース'''が生成する。 [C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)<sub>3</sub>]<sub>n</sub> + 3n (CH<sub>3</sub>CO)<sub>2</sub> O → [C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OCOCH<sub>3</sub>)<sub>3</sub>]<sub>n</sub> + 3n CH<sub>3</sub>COOH トリアセチルセルロースはヒドロキシル基OHを持たないため、通常の溶媒(メタノール等)には溶解しづらい。しかし、トリアセチルセルロースは常温の水または温水で、エステル結合の一部が加水分解して'''ジアセチルセルロース''' [C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)(OCOCH<sub>3</sub>)<sub>2</sub>]<sub>n</sub> になる。このジアセチルセルロースはヒドロキシル基をもつので、アセトン溶媒に溶解するようになる。このジアセチルセルロースの溶けたアセトン溶液を細孔から押し出してアセトンを蒸発・乾燥させて、紡糸したものを'''アセテート繊維'''という、あるいは単に'''アセテート'''という。 語「アセテート」の意味は、「酢酸エステルの」という意味である。 アセテート繊維のように、天然繊維を化学的に処理してから紡糸した繊維を'''半合成繊維'''(semisynthetic fiber)という。 ===== レーヨン ===== 天然繊維を溶媒に溶かしたのち、再び繊維に戻したものを'''再生繊維'''(regenerate fiber)という。セルロースの再生繊維は'''レーヨン'''(rayon)と呼ばれ、レーヨンにはビスコースレーヨンと銅アンモニアレーヨンがある。 * 銅アンモニアレーヨン 水酸化銅(II)であるCu(OH)<sub>2</sub>を濃アンモニア溶液に溶かした溶液を'''シュバイツアー試薬'''という。このシュバイツアー試薬溶液にセルロース(具体的には脱脂綿など)を溶かすと、粘度のある液体が得られる。この粘い液体を細孔から希硫酸の中にゆっくり押し出すと、セルロースが再生する。こうして得られた繊維を'''銅アンモニアレーヨン'''または'''キュプラ'''といい、光沢があり、滑らかであり、柔らかいので、衣服の裏地に利用される。 * ビスコースレーヨン セルロース(具体的には脱脂綿など)を濃い水酸化ナトリウム溶液に浸す処理をして'''アルカリセルロース'''(化学式は[C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)<sub>2</sub>ONa]nである。)にしてから、紙などで挟んでから絞って水気を切って、つぎに二硫化炭素CS<sub>2</sub>と反応をさせると、セルロースキサントゲン酸ナトリウム(式は[C<sub>6</sub>H<sub>7</sub>O<sub>2</sub>(OH)<sub>2</sub>OCSSNa]<sub>n</sub>である。)という物質になる。これを水酸化ナトリウム水溶液に溶かすと、赤褐色のコロイド溶液が得られる。こうして、セルロースから得られた赤褐色のコロイド溶液を'''ビスコース'''(viscose)という。このビスコースを、細孔から希硫酸の中に押し出して、セルロースを再生させて紡糸したものが、'''ビスコースレーヨン'''(viscose rayon)という繊維である。 そして、ビスコースを細孔からではなく、細長いすきまから膜上に押し出したものを'''セロハン'''(cellophane)といい、テープや包装材に利用される。 * 再生繊維 レーヨンのように、天然繊維を一度化学的に処理して溶液にした後、糸として、元の化学式を再生させた繊維を'''再生繊維'''という。 なお、アセテート繊維は化学式が変わっているので再生繊維でない。アセテート繊維は化学式が元のセルロースから変わっている繊維で、また人工物だけから得られた合成繊維でもないので、アセテート繊維などは半合成繊維という。 == タンパク質とアミノ酸 == === アミノ酸 === [[File:Amino acid strucuture for highscool education.svg|thumb|300px|アミノ酸の一般的な構造。図中のRは、アミノ酸の種類によって、ことなる。]] 分子中にアミノ基( -NH<sub>2</sub> )とカルボキシル基( -COOH )をもつ化合物を'''アミノ酸'''(amino acid)という。アミノ酸のうち、同一の炭素C原子に、-NH<sub>2</sub>と-COOHが結合しているアミノ酸を'''αアミノ酸'''という。 アミノ酸の一般式は :R-CH(NH<sub>2</sub>)-COOH で表される。(Rは炭化水素基あるいは水素など。) なお、R-の部分をアミノ酸の'''側鎖'''(そくさ)という。Rの違いによって、アミノ酸の種類が決まる。 :※ なお、生体のタンパク質は、約20種類のαアミノ酸が成分となって縮合してできる物である。生体に必要なアミノ酸のうち、ヒトの体内で合成されない・合成されにくいアミノ酸を'''必須アミノ酸'''(essential amino acid)という。 ==== 鏡像異性体 ==== [[File:アラニンの光学異性体.svg|thumb|400px|アラニンの鏡像異性体]] グリシン以外のすべてのアミノ酸には'''鏡像異性体'''(enantiomer)が存在する<ref>光学異性体ともいうが、この呼び方は現在推奨されていない。</ref>。 天然のアミノ酸のほとんどは、L型の配置である。D型の配置のアミノ酸は、天然にはほとんどない。 {{-}} ==== アミノ酸の反応 ==== [[File:アミノ酸のアミド化とエステル化(修正版).svg|thumb|800px|center|アミノ酸のアミド化とエステル化]] アミノ酸のカルボキシ基-COOH は、アルコール(CH<sub>3</sub>OH など)と反応しエステル化をしてエステルをつくる。また、アミノ酸のアミノ基-NH<sub>3は</sub>無水酢酸( (CH<sub>3</sub>CO)<sub>2</sub>O )と反応させるとアセチル化してアミドをつくる。 ==== 双性イオン ==== [[File:双性イオン.svg|800px|center|]] 結晶中のアミノ酸分子中では、分子内で( -COOH )が水素Hを( -NH<sub>2</sub> )に渡して、アミノ酸内にイオンの( -COO<sup>-</sup> )と( -NH<sub>3</sub><sup>+</sup> )を生じる。その結果、アミノ酸の構造は、 R-CH(NH<sub>3</sub><sup>+</sup>)-COO<sup>-</sup> の構造になる。このように分子内に酸性と塩基性の両方のイオンを生じるので、'''双性イオン'''(zwitterion)とよばれる。 このようにイオンがあるため、アミノ酸は水に溶けやすく、また、有機溶媒には溶けにくい。双性イオンの陽イオンと陰イオンどうしがクーロン力で引き合うため、アミノ酸はイオン結晶に近い結晶構造を取り、また、ほかの有機化合物と比べるとアミノ酸は比較的に融点や沸点が高い。 アミノ酸の水溶液に外部から酸をくわえると、平衡がかたむき、-COO<sup>-</sup>がH<sup>+</sup>を受け取り -COOHになるので、アミノ酸分子中で-NH<sub>3</sub><sup>+</sup>が余るので、酸性が強い溶液中ではアミノ酸は陽イオンになる。 いっぽう、アミノ酸の水溶液に外部から塩基をくわえると、平衡がかたむき、-NH<sub>3</sub><sup>+</sup>がOH<sup>-</sup>にH<sup>+</sup>を放出することによって-NH<sub>2</sub>と変わることによって、-COO<sup>-</sup>が余るので、アミノ酸は陰イオンになる。 ==== 等電点 ==== 水溶液中でアミノ酸の陽イオンと陰イオンの個数が等しいときのpHを'''等電点'''(isoelectric point)という。 アミノ酸の水溶液を染み込ませた紙に、2本の電極で電圧を加え電気泳動をおこなうと、等電点よりpHが小さい水溶液中では、アミノ酸は陽イオンになっているため、陰極側に移動する。いっぽう、等電点よりpHが大きい水溶液では、アミノ酸は陰イオンとなり、陽極側に移動する。 そして、pHが等電点と同じくらいの水溶液中だと、アミノ酸は陽極にも陰極にも移動しないので、このときの水溶液のpHを測定することにより、等電点を測定できる。 アミノ酸の等電点は、グリシンでは pH6.0 、酸性アミノ酸のグルタミン酸ではpH3.2、塩基性アミノ酸のリシンでは9.7である。 水溶液が中性付近では、ふつうは双対イオン状態のアミノ酸が最も多く、陰イオン状態のアミノ酸や陽イオン状態のアミノ酸は少ししか存在しない。 ==== ニンヒドリン反応 ==== [[File:Ninhydrin.svg|thumb|ニンヒドリン分子]] アミノ酸水溶液に薄いニンヒドリン水溶液を加えて温めると、アミノ基 -NH<sub>2</sub> と反応して、色が青紫~赤紫になる。この反応を'''ニンヒドリン反応'''(ninhydrin reaction)といい、アミノ酸の検出などの目的に用いられる。この反応は、アミノ酸の検出やタンパク質の検出に利用される。なお。タンパク質も、構造の端部などにアミノ酸をふくむため、少しながらニンヒドリン反応をするので、色が青紫〜赤紫になる。 {{-}} ==== アミノ酸の例 ==== {| class="wikitable" style="background-color:#fff" ! 名称 <br /> (カッコ内のは略記号) !! 構造式 !! 所在、特徴など !! 等電点 |- | グリシン <br /> (Gly) || [[Image:Glycine for highschool.svg|150px]] || 最も簡単なアミノ酸。<br />光学異性体が存在しない。 || 6.0 |- | アラニン <br /> (Ala) || [[Image:Alanine for highschool.svg|150px]] || タンパク質の構成成分。<br />絹に多い。 || 6.0 |- | セリン <br /> (Ser) || [[Image:Serine for highschool.svg|150px]] || 絹に多い。<br />-OH基をもつ。 || 5.7 |- | フェニルアラニン <br /> (Phe) || [[Image:Phenylakanine for highschool.svg|190px]] || 牛乳や卵に多い。<br />ベンゼン環をもつ。 || 5.5 |- | システイン <br /> (Cys) || [[Image:Cysteine for highschool.svg|150px]] || 毛や爪、角に多い。<br />-SH(チオ基)をもつ。 || 5.1 |- | メチオニン <br /> (Met) || CH3 ー S ー (CH2)2 ー || 牛乳のタンパク質のガゼインに多い。<br />硫黄をふくむ。 || 5.7 |- | アスパラギン酸 <br /> (Asp) || [[Image:Aspartic-acid for highschool.svg|200px]] || 植物のタンパク質に多い。<br /> || 2.8 |- | グルタミン酸 <br /> (Glu) || [[Image:Glutamic-acid for highschool.svg|200px]] || 小麦に多い。<br />-COOH基を2個もつ塩基性アミノ酸。 || 3.2 |- | リシン <br /> (Lys) || [[Image:Lysine for highschool.svg|280px]] || ほとんどすべてのタンパク質にある。<br />-NH2基を2個もつ塩基性アミノ酸。 || 9.7 |- |} * 必須アミノ酸 フェニルアラニンやリシン、メチオニンは必須アミノ酸の例である。 必須アミノ酸は、ヒトの体内で合成されないバリン、ロイシン、イソロイシン、トレオニン、メチオニン、フェニルアラニン、トリプトファン、リシンの8種類に、合成されにくいヒスチジンを加えた9種類である。幼児では、さらにアルギニンを加える場合もある。 * グルタミン酸 グルタミン酸は、昆布のうま味の成分である。グルタミン酸には光学異性体があり、L型のグルタミン酸のみが うま味 を示す。一方でD型はうま味を示さず、若干の苦味を伴う [[ファイル:ProteinogenicAminoAcids.svg|中央|フレームなし|600x600ピクセル]] === タンパク質 === ==== ペプチド結合 ==== [[File:ペプチド結合.svg|center|800px|ペプチド結合]] 2個のアミノ酸分子が結合し、いっぽうのアミノ酸のカルボキシル基と、もう一方のアミノ酸のアミノ基が縮合して、脱水縮合して結合を'''ペプチド結合'''(peptide bond)という。それぞれのアミノ酸は同一種でなくても良い。また、ペプチド結合によって生成する化合物をペプチド(peptide)という。 ペプチドのうち、2分子のアミノ酸がペプチド結合したものを'''ジペプチド'''(dipeptide)という。3分子のアミノ酸がペプチド結合したものをトリペプチド(tripeptide)という。多数のアミノ酸が縮合重合したものを'''ポリペプチド'''(polypeptide)という。 ジペプチドには、ペプチド結合が1つ存在する。トリペプチドには、ペプチド結合が2つ存在する。 タンパク質は、ポリペプチドである。 ペプチド化合物で縮合に使われなかったアミノ基が末端に残るが、このペプチド化合物の縮合に使われなかった末端のアミノ基を'''N末端'''という。同様に、カルボキシル基も末端に残るが、これを'''C末端'''という。ペプチドの構造式を書くときは、N末端を左側に、C末端を右に配置して書くのが慣行である。 ジペプチドには、構造異性体が存在する。たとえば、グリシン(Gly)とアラニン(Ala)からなるジペプチドについて、グリシンのCOOH基とアラニンのNH2基が結合したものを、グリシルアラニン(Gly-Ala) という。また、グリシンのNH2基とアラニンのCOOH基が結合したものを、アラニルグリシン(Ala-Gly )という。 グリシルアラシンもアラニルグリシンも、原子数は同じであるが、構造は異なる。 なお、ペプチドの名称は、このグリシルアラニンの例のように、N末端を持つグリシンが名称の先に来て、C末端をもつアラニンがあとに来る。 トリペプチドやポリペプチドの表記でも同様に、N末端からC末端のアミノ酸の名称で表記する。 トリペプチドでも、ジペプチドと同様に構造異性体が存在する。 なお、グルタミン酸は、カルボキシル基を2箇所もつので、グルタミン酸を含むペプチドでは、構造異性体の数が2倍に増える。 例として、いくつかのトリペプチドで構造異性体の数を求める。 ;例1: GlyとGlyとAlaが結合したトリペプチドの場合。(Glyが2分子。) 構造順はGly-Gly-Ala と Gly-Ala-GlyとAla-Gly-Glyの3通りがある。光学異性体を考慮した場合は、グリシン以外のアミノ酸は光学異性体をもち、異性体数が2倍になるので、光学異性体を考慮したGlyとGlyとAlaが結合したトリペプチドの異性体は3×2=6で6通りになる。 ;例2: GlyとAlaとAlaが結合したトリペプチドの場合。(Alaが2分子。) 構造順はGly-Ala-Ala とAla-Gly-Alaと Ala-Ala-Gly の3通りがある。光学異性体を考慮した場合は、グリシン以外のアミノ酸は光学異性体をもち、異性体数が2倍になるのであった。そして、光学異性体を持つAlaが2個あるから、2×2=4で4倍になる。最終的に光学異性体を考慮した異性体数は3×4=12で12通りになる。 ==== 一次構造と高次構造 ==== * 一次構造 タンパク質を構成するアミノ酸の配列順序のことを'''一次構造'''(いちじこうぞう、primary structure)という。たとえば表記「Gly-Gly-Ala」などは一次構造の表記である。 * 二次構造 ** αヘリックス [[Image:AlphaHelixProtein fr.jpg|thumb|left|250px|αヘリックス。<br>図中の“Liaison H”が水素結合のこと。<br>(リエゾン エイチと書いてある。)]] [[Image:Helice alpha spire 0.png|thumb|100px|right|αヘリックスはアミノ酸間の水素結合である.]] タンパク質のポリペプチドの多くの構造は、時計回り(右回り、Z撚り「ゼットより」)のらせん構造をもつ。 このポリペプチドのらせん構造を'''αヘリックス'''という。らせん1巻あたり、平均3.6個のアミノ酸が含まれる。 このらせん化は、水素結合による現象であり、 アミノ酸の分子中の-C=Oと-N-Hの間のOとHが水素結合し、 -C=O ・・・ H-N- のように水素結合した結果、ペプチド全体ではらせん構造を取る。 * βシート [[Image:Feuillet beta 2.jpg|300px|thumb|βシート]] 並行にならんだ2本のポリペプチドのあいだに水素結合が保たれ、ヒダ状に折れ曲る構造をとることがあり、これを'''βシート'''という。 これら、αヘリックスやβシートをまとめて、タンパク質の'''二次構造'''(secondary structure)という。 {{clear}} * 三次構造 [[画像:Myoglobin.png|thumb|left|250px|三次構造の例。ミオグロビン立体構造]] αヘリックスをとったポリペプチドや、βシートをとったポリペプチドなど、二次構造をとったポリペプチドが、さらに折りたたまれて'''三次構造'''(tertiary structure)になる。三次構造の形成には、側鎖どうしに働く引力や、システインによる'''ジスルフィド結合'''(disulfide bond) -S-S- によるものが関わっている。 三次構造は'''サブユニット'''と呼ばれる。 三次構造の生体組織の例として、'''ミオグロビン'''がある。ミオグロビンは、1本のポリペプチド鎖からなり、ヘム色素を持っている。ヘム色素は、酸素と化合する性質がある。 * 四次構造 [[画像:hemoglobin.jpg|thumb|240px|四次構造の例。ヘモグロビン]] 三次構造のポリペプチド鎖(サブユニットという)が、複数個あつまって集合体をなした構造を'''四次構造'''(quaternary structure)という。 四次構造の生体組織の例として、'''ヘモグロビン'''がある。ヘモグロビンは、2種類のサブユニットが2個ずつ、合計4個のサブユニットが集まって、できている。ヘモグロビンは、2個のヘム色素をもつ。 ==== タンパク質の分類 ==== ===== 単純タンパク質と複合タンパク質 ===== タンパク質を加水分解したとき、アミノ酸だけでなく色素、核酸、リン、脂質などアミノ酸以外の有機物を生じるものを'''複合タンパク質'''(conjugated protein)という。 たとえば、血液中にふくまれるヘモグロビンは色素をふくむ複合タンパク質であり、牛乳にふくまれるガゼインはリン酸をふくむ複合タンパク質であり、だ液にふくまれるムチンは糖をふくむ複合タンパク質である。 いっぽう、タンパク質を加水分解したとき、アミノ酸のみを生じるものを'''単純タンパク質'''(simple protein)という。 ===== 球状タンパク質と繊維状タンパク質 ===== タンパク質の形状にもとづいて、'''球状タンパク質'''(globular protein)と'''繊維状タンパク質'''(fibrous protein)に分類される。一般に繊維状タンパク質は、水には溶けにくい。一方、球場タンパク質は、水に溶けやすい。球状タンパク質は、親水基を外側に、疎水基を内側にして、まとまっている事が多いため、である。 アルブミン、グロブリン、グルテリンなどが、球状タンパク質である。 ケラチン、コラーゲン、フィブロインなどが、繊維状タンパク質である。 {{clear}} ==== タンパク質の特徴 ==== * タンパク質の変性 タンパク質に熱、酸・塩基、重金属イオン、有機溶媒などを加えると凝固し生理的機能を失う。これをタンパク質の'''変性'''(denaturation)という。加熱によって変性することを熱変性という場合もある。 タンパク質の変性は、二次構造〜4次構造が破壊されることによって、起きている。そのため、変性したタンパク質は、元には戻らないのが普通である。タンパク質の変性では一次構造の配列順序は変わっていないが、二次構造以上の構造が変わっている。 * 溶液 タンパク質は水に溶けると、親水コロイド溶液になる。タンパク質のコロイド溶液は、多量の電解質によって、水和している水分子が取り除かれ、粒子がくっつき合い沈殿する(塩析)。 ==== 検出反応 ==== ===== ビウレット反応 ===== [[File:Biuret Test 2.jpg|thumb|100px|ビウレット反応]] タンパク質水溶液に水酸化ナトリウム溶液NaOHを加え、少量の硫酸銅(II)水溶液CuSO<sub>4</sub>を加えると、赤紫色になる。この反応を'''ビウレット反応'''(biulet reaction)という。これはCuとペプチド結合とが錯イオンを形成することに基づき、トリペプチドやポリペプチドなどのようにペプチド結合を2個以上もつ場合に起こる。よって、ペプチド結合が1個だけであるジペプチドでは、ビウレット反応は起こらない。 ===== キサントプロテイン反応 ===== タンパク質水溶液に濃硝酸をくわえて加熱すると、チロシンやトリプトファンなどのアミノ酸中にベンゼン環をもつ場合に、タンパク質水溶液が黄色になる。これは、ベンゼン環がニトロ化されるためである。この溶液を冷却し、NaOHやアンモニアなどで溶液を塩基性にすると、橙色になる。 これらの反応を'''キサントプロテイン反応'''(Xanthoprotein reaction)という。 橙色になった水溶液は中和すると、タンパク質の色は黄色に戻る。 フェニルアラニンはベンゼン環を持つが、あまり反応しない。 ===== 硫黄の検出反応 ===== システインやメチオニンなどのようにタンパク質がイオウを含む場合は、タンパク質の水溶液に、固体の水酸化ナトリウムを加えて加熱して、それから酢酸などで中和し、さらにそれから酢酸鉛(II)水溶液 (CH<sub>3</sub>COO)<sub>2</sub>Pb を加えると、硫化鉛(II) PbS の沈殿を生じる。硫化鉛の沈殿の色は黒色である。 :Pb<sup>2+</sup> + S<sup>2-</sup> → PbS ==== 毛髪のパーマネントのしくみ ==== 毛髪はケラチンという繊維状タンパク質からなるが、この分子はジスルフィド結合 -S-S- によって、ところどころ結ばれている。このジスルフィド結合のため、毛髪は一定の形を保っている。 毛髪のパーマ処理は、還元剤をもちいて、このジスルフィド結合を還元して -S-H にすることで、ジスルフィド結合を切断している。 つぎに、酸化剤で、ジスルフィド結合 -S-S- を再生させると、もととは違ったつながりかたで、部分的にジスルフィド結合が再生されるので、元の髪型とは違った髪型になる。 パーマの還元剤には、チオグリコール酸アンモニウムが用いられる。パーマの酸化剤には、臭素酸ナトリウム NaBrO<sub>3</sub> や過酸化水素などが用いられる。 == 繊維 == 繊維(fiber)とは、細くて糸状のものを指す。その中で、天然に存在する糸状の繊維を天然繊維(natural fiber)と呼び、石油などから合成した繊維を合成繊維(synthetic fiber)と呼ぶ。 天然繊維の中で、植物から得られるもの(例えば綿や麻など。主成分はセルロース)を植物繊維(plant fiber)と呼び、動物から得られるもの(羊毛や絹など。主成分はタンパク質。絹はカイコから得られる繊維)を動物繊維(animal fiber)と呼ぶ。 '''木綿''' 木綿(cotton)は植物のワタから取れる植物繊維で、主成分はセルロース。木綿の繊維は内部に中空部分があり、吸湿性が高い。 '''絹''' 絹はカイコガのまゆから取り出される繊維。主成分はフィブロインというタンパク質でセリシンというタンパク質に包まれている構造を持つ。 '''羊毛''' 羊毛の主成分はケラチン。羊毛は動物繊維で、表皮が鱗(うろこ)状で、クチクラ(キューティクル)と呼ばれる構造をしている。羊毛は伸縮性が大きく、水をはじく撥水性もあり、保温性があるので、毛布やコートなどに使われる。羊毛や絹はタンパク質なので、キサントプロテイン反応を示す。 === 化学繊維 === 合成繊維や天然繊維を溶媒に溶かしたり、化学反応させたりといった化学的な処理を行って作る繊維は、化学繊維という。天然繊維を溶媒に溶かしてから再び繊維に戻したものを再生繊維(regenerate fiber)と呼ぶ。セルロースの再生繊維はレーヨンと呼ばれ、ビスコースレーヨンと銅アンモニアレーヨンがある。 一方で、天然繊維を化学的に処理してその組成を変化させたものは半合成繊維という。半合成繊維の例としては、アセテート繊維がある。 == 酵素 == ある種のタンパク質には触媒の働きを持つものがある。この触媒として機能するタンパク質を'''酵素'''(enzyme)という。酵素は、無機触媒や金属触媒とは、異なる性質をもつ。酵素は、ある特定の物質にしか作用しない。これを'''基質特異性'''(substrate specificity)という。そして酵素が作用する物質および分子構造を'''基質'''(substrate)という。 酵素には、基質と立体的にむすびつく'''活性部位'''(active site)があるため、このような反応が起こる。活性部位のことを、'''活性中心'''(active center)ともいう。 [[File:酵素基質複合体 模式図.svg|thumb|600px|center|酵素基質複合体の模式図]] たとえば、だ液にふくまれるアミラーぜはデンプンを加水分解するが、タンパク質を加水分解できない。酵素インペルターゼはスクロースの加水分解にしか作用せず、マルトースやラクトースなどの他の二糖類にはインペルターゼは作用しない。また、マルターゼは、マルトースにしか作用しない。 === 失活 === また、酵素はタンパク質であるので、タンパク質が変性する状況では、酵素はその能力を失う。熱変性などで、タンパク質が修復不可能になると、酵素の触媒能力もまた修復不可能となり、酵素を冷却しても、もはや触媒として機能しなくなる。このように酵素が触媒としての能力を失って、もはや酵素ではなくなったことを'''失活'''(deactivation)という。 === 最適温度 === 酵素の触媒作用が最も働く温度を'''最適温度'''という。酵素にもよるが、動物の体温に近い、35℃から40℃といった温度である。 50℃以上など、これらより高温では熱変性で酵素の構造が破壊される。最適温度より低温にした場合は、低温の間は酵素としての作用が弱まるが、適温に戻すと、再び酵素としての触媒能力を取り戻す。 低温で酵素としての能力を失うことは一般には失活とは呼ばない。 === 最適pH === [[File:酵素と最適pH.svg|thumb|300px|酵素と最適pH]] 酵素には、その場所のpHによって、触媒の働きの反応速度が変わる。もっとも酵素が働くpHを'''最適pH'''(optimum pH)という。 最適pHの値の傾向は、酵素の種類にもよるが、おおむねpH6~8といった、中性付近か、弱酸性の付近で、もっともよく働く。たとえばアミラーゼはpH6~7の付近が最適pHである。すい臓の中で働く酵素のトリプシンはpH8の弱い塩基性が最適pHである。 なお、胃酸の中で働く酵素の'''ペプシン'''は最適pHが2の付近で胃液のpHに近い。このように、酵素は、その酵素が働く環境下に近いpHで、よく働く性質になっている場合が多い。 == 核酸 == 細胞には'''核酸'''という高分子化合物が存在し、これは遺伝情報を担っている。 リン酸、ペントース、有機塩基が結合した化合物を'''ヌクレオチド'''という。 [[ファイル:DAMP chemical structure.svg|中央|サムネイル|ヌクレオチド]] また、ペントースと有機塩基が結合した化合物を'''ヌクレオシド'''という。 [[ファイル:Phosphodiester Bond Diagram.svg|サムネイル|ヌクレオチドの結合]] 核酸はヌクレオチドのペントースの3位の -HO とリン酸の -OH の部分が縮合重合したポリヌクレオチドである。 核酸には、リボ核酸 RNA と デオキシリボ核酸 DNA の2種類が存在する。核酸を構成するペントースの部分が、RNAはリボース <chem>C5H10O5</chem>、DNAはデオキシリボース <chem>C5H10O4</chem> である<ref>deoxyribose の de は「〜がない」、oxyは酸素を意味する。つまり、deoxyribose は ribose から酸素が一個無くなった化合物である。</ref>。 [[ファイル:Pentozi nukleotid.svg|中央|サムネイル|リボース(左) デオキシリボース(右)]] RNAを構成する有機塩基はアデニン(A)、グアニン(G)、シトシン(C)、ウラシル(U)の4種類である。DNAはアデニン(A)、グアニン(G)、シトシン(C)、チミン(T)の4種類である。 [[ファイル:Main nucleobases.png|中央|サムネイル|400x400ピクセル]] === DNAの構造 === [[ファイル:DNAの並び方.png|サムネイル|DNAの並び方]] DNAはアデニン(A)とチミン(T)、グアニン(G)とシトシン(C)が水素結合によって、2本のポリヌクレオチドが合わさった'''二重らせん構造'''をとっている。 [[ファイル:Base_pair_GC.svg|左|サムネイル|水素結合。 DNAにおける2つの塩基対の内の1つであるグアニンとシトシン間の水素結合。]] {{-}} [[ファイル:DNA_animation.gif|右|サムネイル|DNAの立体構造]] === DNAの働き === DNAの働きは、主にタンパク質の設計図となることと、遺伝情報を子孫に伝えることである。 DNAの遺伝子の働きかたを決める要因は、塩基の並び方で決定される。この塩基の並び方で、細胞で合成されるタンパク質が異なるため、DNAはタンパク質の設計図となっている。 DNAは、細胞核の中で、RNAをつくる。RNAの情報は、DNAの情報を元にしている。RNAは、核の外に出ていきリボソームと結合し、消化器官で食品のタンパク質から分解・吸収したアミノ酸を材料にして、 RNAの塩基配列に従ってアミノ酸をつなぎかえることで、タンパク質を作っている。 [[カテゴリ:高等学校化学|てんねんこうふんしかこうふつ]] [[Category:高等学校教育]] [[Category:化学]] a785e364hr2ebsdzkxgllq8asmfijne Java/文法/クラス 0 25809 263739 241932 2024-11-18T03:40:36Z Ef3 694 校閲と推敲 263739 wikitext text/x-wiki {{Nav}} = クラス = == 概要 == クラスは、オブジェクト指向プログラミング(OOP)における基本的な構成要素です。データ(フィールド)と振る舞い(メソッド)を組み合わせた抽象データ型を定義する枠組みを提供します。 == クラスの主要な特徴 == === カプセル化(Encapsulation) === * データとメソッドを1つの単位にまとめる * 内部実装の隠蔽 * データの整合性とセキュリティの向上 * アクセス制御の実現 === 継承(Inheritance) === * 既存クラスの機能を再利用 * コードの再利用性向上 * クラス階層の構築 * 「is-a」関係の表現 === ポリモーフィズム(Polymorphism) === * 同じインターフェースで異なる実装を提供 * メソッドのオーバーライド * 型の柔軟な取り扱い * 拡張性の向上 === 抽象化(Abstraction) === * 実世界の概念のモデル化 * 実装詳細の隠蔽 * インターフェースの提供 * 複雑さの管理 == Javaにおけるクラスの構造 == === クラスの基本構文 === :<syntaxhighlight lang=java copy> public class MyClass { // フィールド(状態) private int value; // コンストラクタ public MyClass(int initialValue) { this.value = initialValue; } // メソッド(振る舞い) public void setValue(int newValue) { this.value = newValue; } } </syntaxhighlight> === クラスのメンバー === ==== フィールド ==== * インスタンス変数 ** オブジェクトごとに固有の状態を保持 ** インスタンス生成時にメモリ割り当て * クラス変数(static) ** クラス全体で共有される状態 ** クラスロード時にメモリ割り当て ==== メソッド ==== * インスタンスメソッド ** オブジェクトの振る舞いを定義 ** thisキーワードでインスタンスを参照 * クラスメソッド(static) ** クラス全体で共有される機能 ** インスタンス不要で呼び出し可能 ==== コンストラクタ ==== * オブジェクト生成時の初期化処理 * クラス名と同名 * オーバーロード可能 * 継承時のsuper()呼び出し === アクセス制御 === ==== アクセス修飾子 ==== {| class="wikitable" ! 修飾子 !! クラス内 !! 同一パッケージ !! サブクラス !! 全てのクラス |- | public || ○ || ○ || ○ || ○ |- | protected || ○ || ○ || ○ || × |- | (default) || ○ || ○ || × || × |- | private || ○ || × || × || × |} ==== final修飾子 ==== * 変数:値の変更を禁止 * メソッド:オーバーライドを禁止 * クラス:継承を禁止 == 高度な機能 == === ネストしたクラス === * 静的ネストクラス * 内部クラス * ローカルクラス * 匿名クラス === 初期化ブロック === * インスタンス初期化ブロック * 静的初期化ブロック === Generics対応 === :<syntaxhighlight lang=java copy> public class Container<T> { private T value; public void set(T value) { this.value = value; } public T get() { return value; } } </syntaxhighlight> == ベストプラクティス == === 設計原則 === * 単一責任の原則 * カプセル化の徹底 * 適切な粒度の設定 * インターフェースの活用 === コーディング規約 === * 命名規則の遵守 * アクセス制御の適切な使用 * コメントとドキュメンテーション * コードの整形と可読性==== 型推論 ==== 型推論は、コンパイラが変数の型を自動的に推測する機能です。 Java 10からは、<code>var</code>キーワードを使用してローカル変数の型を推論することができるようになりました。 以下は、型推論を使用したインスタンス化の例です。 :<syntaxhighlight lang=java copy> var obj = new MyClass(10); </syntaxhighlight> この場合、コンパイラは<code>obj</code>の型を<code>MyClass</code>と推論します。 明示的に型を宣言する必要がなくなり、コードの冗長性を減らすことができます。 === 継承 === Javaでは、既存のクラスを拡張して新しいクラスを作成することができます。 これを'''継承'''と呼びます。 継承を使用することで、既存のクラスのフィールドやメソッドを再利用し、新しいクラスで追加や修正を加えることができます。 :<syntaxhighlight lang=java copy> public class ChildClass extends ParentClass { // ChildClass のフィールドとメソッドを定義 } </syntaxhighlight> ==== 多重継承 ==== Javaでは、クラスは単一の直接スーパークラスしか持つことができません(単一継承)。 しかし、インタフェースは複数実装できるため、多重継承の代替手段として使用されます。 ==== シールドクラス (Sealed class) ==== シールドクラス (Sealed class) は、Java 17から導入された新機能の1つです。 シールドクラスは、そのサブクラスがどのクラスになるかを制限するために使用されます。 シールドクラスは以下のように定義されます: :<syntaxhighlight lang=java copy> sealed class Shape permits Circle, Rectangle { // クラスの定義 } </syntaxhighlight> 上記の例では、<code>Shape</code>というシールドクラスを定義し、<code>Circle</code>と<code>Rectangle</code>というサブクラスを許可しています。つまり、<code>Circle</code>と<code>Rectangle</code>以外のクラスは<code>Shape</code>のサブクラスになることができません。 シールドクラスを使用することで、クラスの階層構造を制御し、より安全な設計を実現することができます。 これにより、クラスの派生元や使用方法をより明確に定義することができます。 === ポリモーフィズム === ポリモーフィズム(Polymorphism)とは、オブジェクト指向プログラミングの重要な概念の一つであり、同じメッセージ(操作やメソッド呼び出し)を異なるオブジェクトに送ることができる能力を指します。つまり、同じ名前のメソッドや操作が複数のクラスで異なる動作をすることができるという概念です。 ポリモーフィズムには主に2つのタイプがあります: ; コンパイル時のポリモーフィズム(Compile-time Polymorphism): : コンパイル時のポリモーフィズムは、メソッドのオーバーロードや演算子のオーバーロードなど、コンパイル時に静的に解決されるポリモーフィズムの形態です。 : オーバーロードされたメソッドや演算子は、同じ名前で異なる引数の型や数を受け入れることができます。コンパイラは、呼び出し元のコンテキストから適切なバージョンのメソッドや演算子を解決します。 ; 実行時のポリモーフィズム(Runtime Polymorphism): : 実行時のポリモーフィズムは、継承とメソッドのオーバーライドを利用して、実行時にオブジェクトの型に基づいてメソッドが動的に選択される機能です。 : この形態では、オーバーライドされたメソッドが異なるサブクラスで定義され、同じメソッド名を持ちますが、それぞれのクラスのインスタンスに対して異なる振る舞いを示します。 Javaでは、実行時のポリモーフィズムが主に使用されます。これは、スーパークラスの参照変数がサブクラスのオブジェクトを参照し、その参照変数を通じてメソッドを呼び出すことで実現されます。実際の実行時に、どのクラスのメソッドが呼び出されるかは、オブジェクトの実際の型に基づいて動的に決定されます。 === オーバーライド === オーバーライド(Override)とは、Javaのオブジェクト指向プログラミングにおいて、サブクラスが親クラスのメソッドを再定義することを指します。つまり、親クラスで定義されたメソッドと同じ名前、引数リスト、戻り値の型を持つメソッドをサブクラスで再度定義することです。 オーバーライドには以下の特徴があります: # 同じシグネチャを持つ: #* オーバーライドするメソッドは、親クラスのメソッドと同じ名前、引数リスト、戻り値の型を持たなければなりません。 # 動的ディスパッチ: #* オーバーライドされたメソッドは、実行時にオブジェクトの型に基づいて動的に呼び出されます。つまり、実際に実行されるメソッドは、オブジェクトの実際の型によって決定されます。 # @Overrideアノテーション: #* Javaでは、<code>@Override</code>アノテーションを使用して、明示的にメソッドがオーバーライドされていることを示すことができます。コンパイラは、このアノテーションを使用してオーバーライドの誤りを検出するのに役立ちます。 :<syntaxhighlight lang=java copy> public class SubClass extends SuperClass { @Override public void methodName() { // オーバーライドされたメソッドの実装 } } </syntaxhighlight> === 抽象クラス === 抽象クラスは、インスタンス化できないクラスであり、抽象メソッド(本体を持たないメソッド)を含むことができます。抽象クラスは、他のクラスによって拡張されることを意図しています。 :<syntaxhighlight lang=java copy> public abstract class AbstractClass { // 抽象メソッド public abstract void abstractMethod(); } </syntaxhighlight> === インタフェース === インタフェースは、抽象メソッドのみを含む抽象型です。 クラスは複数のインタフェースを実装でき、これにより複数の振る舞いを持つことができます。 :<syntaxhighlight lang=java copy> public interface InterfaceName { // 抽象メソッド void methodName(); } </syntaxhighlight> === ジェネリックなクラス === ジェネリックなクラスは、異なる型のデータを扱えるように設計されたクラスです。 ジェネリックなクラスは、その定義中に1つ以上の型パラメータを持ち、そのパラメータを使用してフィールドの型やメソッドの引数・戻り値の型を指定します。 これにより、特定の型に依存せず、汎用的なクラスを定義することができます。 {{Main|Java/ジェネリックス}} 以下は、ジェネリックなクラスの例です。 :<syntaxhighlight lang=java copy> public class Box<T> { private T data; public void setData(T data) { this.data = data; } public T getData() { return data; } } </syntaxhighlight> この <code>Box</code> クラスは、<code>T</code> という型パラメータを持っています。 このパラメータは、クラスのインスタンス化時に実際の型に置き換えられます。 例えば、<code>Box<Integer></code> をインスタンス化すると、<code>T</code> は <code>Integer</code> 型になります。 同様に、<code>Box<String></code> をインスタンス化すると、<code>T</code> は <code>String</code> 型になります。ジェネリックなクラスを使用することで、型安全性を向上させ、コードの再利用性を高めることができます。 === アクセサ === アクセサ (Accessor) は、オブジェクトのフィールドにアクセスするためのメソッドのことを指します。一般的に、オブジェクトのフィールドには直接アクセスせず、フィールドの値を取得するための「ゲッター」メソッドと、フィールドの値を設定するための「セッター」メソッドを使用します。 ==== ゲッター (Getter) ==== ゲッターは、フィールドの値を取得するためのメソッドです。 一般的に、フィールドの名前に "get" を接頭辞として付けます。 以下は、ゲッターの例です。 :<syntaxhighlight lang=java copy> public class MyClass { private int number; public int getNumber() { return number; } } </syntaxhighlight> この例では、<code>getNumber</code> メソッドが <code>number</code> フィールドの値を返します。 ==== セッター (Setter) ==== セッターは、フィールドの値を設定するためのメソッドです。 一般的に、フィールドの名前に "set" を接頭辞として付けます。 以下は、セッターの例です。 :<syntaxhighlight lang=java copy> public class MyClass { private int number; public void setNumber(int number) { this.number = number; } } </syntaxhighlight> この例では、<code>setNumber</code> メソッドが <code>number</code> フィールドの値を設定します。 アクセサを使用することで、フィールドにアクセスする際の制御を強化し、フィールドの値の読み取りおよび変更を制御することができます。 また、フィールドのカプセル化を実現し、オブジェクトのデータの整合性を保つのに役立ちます。 これらは、Javaのクラスの基本的な構造と機能の概要です。 クラスは、オブジェクト指向プログラミングの中核であり、プログラムの構造を構築するための重要な要素です。 == ベストプラクティス == クラスの設計に関するベストプラクティスは、ソフトウェアの品質、保守性、拡張性を向上させるために重要です。以下に、クラスの設計に関するいくつかの一般的なベストプラクティスを示します。 # 単一責任の原則を遵守する(Single Responsibility Principle): #* クラスは、1つの責任や役割を持つべきです。複数の異なる責任を持つクラスは、分割して単一の責任に集中させることで、可読性や保守性を向上させることができます。 # カプセル化を強化する: #* クラスのフィールドを<code>private</code>で宣言し、アクセッサメソッド(getterやsetter)を使用して外部からのアクセスを制御します。これにより、クラスの内部状態を隠蔽し、データの整合性を維持することができます。 # 継承を適切に使用する: #* 継承は強力なツールですが、適切に使用することが重要です。親クラスとサブクラスの間に論理的な関係がある場合にのみ継承を使用し、コードの再利用性を向上させることができます。また、インタフェースを使用することで、継承の代替手段として柔軟性を持たせることができます。 # 不変性を推奨する: #* クラスの不変性を維持することは、バグの発生を減らし、並行性の問題を回避するのに役立ちます。可能な限り不変性を推奨し、フィールドを<code>final</code>で宣言することを検討してください。 # 適切な命名規則を使用する: #* クラス、メソッド、フィールドなどの要素に適切な名前を付けることは、コードの可読性を向上させるために重要です。意味のある名前を選択し、一貫した命名規則を使用することが重要です。 # コンストラクタを適切に設計する: #* クラスのコンストラクタは、オブジェクトの初期化を行うための重要な手段です。コンストラクタのパラメータを最小限に保ち、必要な初期化を適切に行うように設計することが重要です。 # ドキュメントとコメントを追加する: #* クラスやメソッドの目的、機能、使用方法についてのドキュメントとコメントを追加することは、コードの理解を助けるのに役立ちます。特に他の開発者がコードを読む場合に重要です。 これらのベストプラクティスを遵守することで、より保守性の高い、柔軟性のある、品質の高いクラスを設計することができます。 {{コラム|SOLID原則|2=SOLID原則は、オブジェクト指向プログラミングにおける設計原則の集合であり、ソフトウェアの保守性、拡張性、再利用性を向上させるためのガイドラインを提供します。 SOLIDは以下の5つの原則からなります。 # 単一責任の原則(Single Responsibility Principle, SRP): #: 1つのクラスは1つの責務(役割)を持つべきであり、変更する理由は1つであるべきです。この原則により、クラスはシンプルで理解しやすくなり、変更に強い設計になります。 # オープン/クローズドの原則(Open/Closed Principle, OCP): #: ソフトウェアのエンティティ(クラス、モジュール、関数など)は、拡張に対して開いており、修正に対して閉じているべきです。すなわち、新しい機能を追加するときは既存のコードを変更せずに拡張できるようにするべきです。 # リスコフの置換原則(Liskov Substitution Principle, LSP): #: サブタイプ(派生クラス、実装クラス)は、その親タイプ(基底クラス、インターフェース)と置換可能でなければなりません。つまり、基底クラス型の変数に対して派生クラスのインスタンスを代入しても動作が変わらないことを保証する必要があります。 # インターフェース分離の原則(Interface Segregation Principle, ISP): #: クライアント(利用者)が利用しないメソッドに依存しないようにするために、クライアントにとって不要なインターフェースを実装しないように分割します。クライアントは必要な機能にのみ依存するべきです。 # 依存性逆転の原則(Dependency Inversion Principle, DIP): #: 上位のモジュールは下位のモジュールに依存すべきではなく、両方が抽象に依存すべきです。また、具象クラスにではなく抽象クラスやインターフェースに依存すべきです。これにより、コードの柔軟性が向上し、依存関係の注入(DI)などのパターンが可能になります。 SOLID原則は、ソフトウェアの品質を向上させるための強力なガイドラインであり、設計のバランスを保ちながら柔軟性と保守性を確保するのに役立ちます。これらの原則を遵守することで、より清潔で拡張可能なコードを作成することができます。 }} == コード例 == === Javaクラスと配列の操作例 === ;[https://paiza.io/projects/vGiAv_xXPraYJ93-dksSGw?language=java 配列]:<syntaxhighlight lang=java copy> /** * Javaクラスと配列の操作例 */ import java.util.*; /** * 人物を表すクラス */ class Person { // フィールド private String name; private int age; /** * コンストラクタ * @param name 名前 * @param age 年齢 */ public Person(String name, int age) { this.name = name; this.age = age; } /** * 名前のゲッター * @return 名前 */ public String getName() { return name; } /** * 名前のセッター * @param name 名前 */ public void setName(String name) { this.name = name; } /** * 年齢のゲッター * @return 年齢 */ public int getAge() { return age; } /** * 年齢のセッター * @param age 年齢 */ public void setAge(int age) { this.age = age; } } /** * メインクラス */ public class Main { /** * メインメソッド * @param args コマンドライン引数 */ public static void main(String[] args) { // ArrayListを使用してPersonオブジェクトのリストを作成 List<Person> peopleList = new ArrayList<>(); // Personオブジェクトをリストに追加 peopleList.add(new Person("Alice", 30)); peopleList.add(new Person("Bob", 25)); peopleList.add(new Person("Charlie", 35)); // 配列の要素を出力 for (Person person : peopleList) { System.out.println("Name: " + person.getName() + ", Age: " + person.getAge()); } } } </syntaxhighlight> === 行列クラスの実装例 === ;[https://paiza.io/projects/9iy_6ZXmiOJxrTrHlha11w?language=java 行列]:<syntaxhighlight lang=java copy> import java.util.*; /** * 行列演算を行うMatrixクラスの定義 */ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.function.BinaryOperator; /** * 行列を表すMatrixクラス */ class Matrix { /** 行数 */ private final int rows; /** 列数 */ private final int cols; /** 行列データ */ private final double[] data; /** * 行列のコンストラクタ * @param rows 行数 * @param cols 列数 */ public Matrix(int rows, int cols) { this.rows = rows; this.cols = cols; this.data = new double[rows * cols]; } /** * 行列のコンストラクタ * @param data 行列データ */ public Matrix(double[][] data) { this.rows = data.length; this.cols = data[0].length; this.data = new double[rows * cols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { this.data[cols * i + j] = data[i][j]; } } } /** * 行数を取得するメソッド * @return 行数 */ public int getRows() { return rows; } /** * 列数を取得するメソッド * @return 列数 */ public int getCols() { return cols; } /** * 指定された位置の要素を取得するメソッド * @param i 行インデックス * @param j 列インデックス * @return 指定された位置の要素 */ public double get(int i, int j) { return data[cols * i + j]; } /** * 指定された位置に要素を設定するメソッド * @param i 行インデックス * @param j 列インデックス * @param value 設定する値 */ public void set(int i, int j, double value) { data[cols * i + j] = value; } /** * 他の行列との加算を行うメソッド * @param other 加算する行列 * @return 加算結果の行列 */ public Matrix add(Matrix other) { return operate(other, Double::sum); } /** * 他の行列との減算を行うメソッド * @param other 減算する行列 * @return 減算結果の行列 */ public Matrix subtract(Matrix other) { return operate(other, (x, y) -> x - y); } /** * 行列とスカラーの乗算を行うメソッド * @param scalar 乗算するスカラー値 * @return 乗算結果の行列 */ public Matrix scalarMultiply(double scalar) { Matrix result = new Matrix(rows, cols); for (int i = 0; i < data.length; i++) { result.data[i] = this.data[i] * scalar; } return result; } /** * 行列の比較を行うメソッド * @param other 比較する行列 * @return 行列が等しい場合はtrue、そうでない場合はfalse */ public boolean equals(Matrix other) { if (this.rows != other.rows || this.cols != other.cols) { return false; } for (int i = 0; i < data.length; i++) { if (this.data[i] != other.data[i]) { return false; } } return true; } /** * 行列の文字列表現を返すメソッド * @return 行列の文字列表現 */ @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < data.length; i++) { sb.append(data[i]); if ((i + 1) % cols == 0) { sb.append("\n"); } else { sb.append(", "); } } return sb.toString(); } /** * 行列演算を行うメソッド * @param other 演算対象の行列 * @param operator 演算子 * @return 演算結果の行列 */ private Matrix operate(Matrix other, BinaryOperator<Double> operator) { if (rows != other.rows || cols != other.cols) { throw new IllegalArgumentException("Matrices must have the same dimensions"); } Matrix result = new Matrix(rows, cols); Iterator<Double> thisIterator = iterator(); Iterator<Double> otherIterator = other.iterator(); for (int i = 0; i < data.length; i++) { result.data[i] = operator.apply(thisIterator.next(), otherIterator.next()); } return result; } /** * 行列の要素にアクセスするイテレータを返すメソッド * @return 行列の要素にアクセスするイテレータ */ private Iterator<Double> iterator() { return new Iterator<Double>() { private int index = 0; @Override public boolean hasNext() { return index < data.length; } @Override public Double next() { if (!hasNext()) { throw new NoSuchElementException(); } return data[index++]; } }; } } /** * メインクラス */ public class Main { /** * メインメソッド * @param args コマンドライン引数 */ public static void main(String[] args) { Matrix a = new Matrix(new double[][]{{1, 2, 3}, {4, 5, 6}}); Matrix b = new Matrix(new double[][]{{7, 8, 9}, {10, 11, 12}}); // 加算 Matrix sum = a.add(b); System.out.println("Sum:"); System.out.println(sum); // 減算 Matrix difference = a.subtract(b); System.out.println("Difference:"); System.out.println(difference); // スカラー倍 Matrix scaled = a.scalarMultiply(2); System.out.println("Scaled:"); System.out.println(scaled); // 比較 System.out.println("Are matrices equal? " + a.equals(b)); } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Sum: 8.0, 10.0, 12.0 14.0, 16.0, 18.0 Difference: -6.0, -6.0, -6.0 -6.0, -6.0, -6.0 Scaled: 2.0, 4.0, 6.0 8.0, 10.0, 12.0 Are matrices equal? false </syntaxhighlight> {{DEFAULTSORT:くらす}} [[Category:Java]] [[Category:クラス|Java]] 31v110rz1acqxf0xm2ukvc5yg7ccleu 263740 263739 2024-11-18T04:01:25Z Ef3 694 校閲と推敲 263740 wikitext text/x-wiki {{Nav}} = クラス = == 概要 == クラスは、オブジェクト指向プログラミング(OOP)における基本的な構成要素です。データ(フィールド)と振る舞い(メソッド)を組み合わせた抽象データ型を定義する枠組みを提供します。 == クラスの主要な特徴 == === カプセル化(Encapsulation) === * データとメソッドを1つの単位にまとめる * 内部実装の隠蔽 * データの整合性とセキュリティの向上 * アクセス制御の実現 === 継承(Inheritance) === * 既存クラスの機能を再利用 * コードの再利用性向上 * クラス階層の構築 * 「is-a」関係の表現 === ポリモーフィズム(Polymorphism) === * 同じインターフェースで異なる実装を提供 * メソッドのオーバーライド * 型の柔軟な取り扱い * 拡張性の向上 === 抽象化(Abstraction) === * 実世界の概念のモデル化 * 実装詳細の隠蔽 * インターフェースの提供 * 複雑さの管理 == Javaにおけるクラスの構造 == === クラスの基本構文 === :<syntaxhighlight lang=java copy> public class MyClass { // フィールド(状態) private int value; // コンストラクタ public MyClass(int initialValue) { this.value = initialValue; } // メソッド(振る舞い) public void setValue(int newValue) { this.value = newValue; } } </syntaxhighlight> === クラスのメンバー === ==== フィールド ==== * インスタンス変数 ** オブジェクトごとに固有の状態を保持 ** インスタンス生成時にメモリ割り当て * クラス変数(static) ** クラス全体で共有される状態 ** クラスロード時にメモリ割り当て ==== メソッド ==== * インスタンスメソッド ** オブジェクトの振る舞いを定義 ** thisキーワードでインスタンスを参照 * クラスメソッド(static) ** クラス全体で共有される機能 ** インスタンス不要で呼び出し可能 ==== コンストラクタ ==== * オブジェクト生成時の初期化処理 * クラス名と同名 * オーバーロード可能 * 継承時のsuper()呼び出し === アクセス制御 === ==== アクセス修飾子 ==== {| class="wikitable" ! 修飾子 !! クラス内 !! 同一パッケージ !! サブクラス !! 全てのクラス |- | public || ○ || ○ || ○ || ○ |- | protected || ○ || ○ || ○ || × |- | (default) || ○ || ○ || × || × |- | private || ○ || × || × || × |} ==== final修飾子 ==== * 変数:値の変更を禁止 * メソッド:オーバーライドを禁止 * クラス:継承を禁止 == 高度な機能 == === ネストしたクラス === * 静的ネストクラス * 内部クラス * ローカルクラス * 匿名クラス === 初期化ブロック === * インスタンス初期化ブロック * 静的初期化ブロック === Generics対応 === :<syntaxhighlight lang=java copy> public class Container<T> { private T value; public void set(T value) { this.value = value; } public T get() { return value; } } </syntaxhighlight> == ベストプラクティス == === 設計原則 === * 単一責任の原則 * カプセル化の徹底 * 適切な粒度の設定 * インターフェースの活用 === コーディング規約 === * 命名規則の遵守 * アクセス制御の適切な使用 * コメントとドキュメンテーション * コードの整形と可読性 ==== 型推論 ==== 型推論は、コンパイラが変数の型を自動的に推測する機能です。 Java 10からは、<code>var</code>キーワードを使用してローカル変数の型を推論することができるようになりました。 以下は、型推論を使用したインスタンス化の例です。 :<syntaxhighlight lang=java copy> var obj = new MyClass(10); </syntaxhighlight> この場合、コンパイラは<code>obj</code>の型を<code>MyClass</code>と推論します。 明示的に型を宣言する必要がなくなり、コードの冗長性を減らすことができます。 === 継承 === Javaでは、既存のクラスを拡張して新しいクラスを作成することができます。 これを'''継承'''と呼びます。 継承を使用することで、既存のクラスのフィールドやメソッドを再利用し、新しいクラスで追加や修正を加えることができます。 :<syntaxhighlight lang=java copy> public class ChildClass extends ParentClass { // ChildClass のフィールドとメソッドを定義 } </syntaxhighlight> ==== 多重継承 ==== Javaでは、クラスは単一の直接スーパークラスしか持つことができません(単一継承)。 しかし、インタフェースは複数実装できるため、多重継承の代替手段として使用されます。 ==== シールドクラス (Sealed class) ==== シールドクラス (Sealed class) は、Java 17から導入された新機能の1つです。 シールドクラスは、そのサブクラスがどのクラスになるかを制限するために使用されます。 シールドクラスは以下のように定義されます: :<syntaxhighlight lang=java copy> sealed class Shape permits Circle, Rectangle { // クラスの定義 } </syntaxhighlight> 上記の例では、<code>Shape</code>というシールドクラスを定義し、<code>Circle</code>と<code>Rectangle</code>というサブクラスを許可しています。つまり、<code>Circle</code>と<code>Rectangle</code>以外のクラスは<code>Shape</code>のサブクラスになることができません。 シールドクラスを使用することで、クラスの階層構造を制御し、より安全な設計を実現することができます。 これにより、クラスの派生元や使用方法をより明確に定義することができます。 === ポリモーフィズム === ==== 概要 ==== ポリモーフィズムは、同一のインターフェースで異なる実装を提供する機能です。「多態性」とも呼ばれ、オブジェクト指向プログラミングの重要な柱の一つです。 ==== 種類 ==== ===== コンパイル時ポリモーフィズム ===== * '''定義''': コンパイル時に解決される静的な多態性 * '''実現方法''': メソッドオーバーロード * '''特徴''': ** 同じメソッド名で異なるパラメータ ** コンパイル時に決定 ** 静的バインディング {| class="wikitable" ! メソッド定義 !! 説明 |- | <code>void print(int x)</code> || 整数を出力 |- | <code>void print(String s)</code> || 文字列を出力 |- | <code>void print(double d)</code> || 小数を出力 |} ===== 実行時ポリモーフィズム ===== * '''定義''': 実行時に解決される動的な多態性 * '''実現方法''': メソッドオーバーライド * '''特徴''': ** 継承関係に基づく ** 実行時に決定 ** 動的バインディング :<syntaxhighlight lang=java copy> class Animal { void makeSound() { System.out.println("Some sound"); } } class Dog extends Animal { @Override void makeSound() { System.out.println("Woof"); } } class Cat extends Animal { @Override void makeSound() { System.out.println("Meow"); } } </syntaxhighlight> === メソッドオーバーライド === ==== 基本ルール ==== * メソッド名が同一 * 引数リストが同一 * 戻り値の型が同一または共変 * アクセス修飾子は同一または緩和 ==== オーバーライドの例 ==== :<syntaxhighlight lang=java copy> public class Parent { protected void display() { System.out.println("Parent's display"); } } public class Child extends Parent { @Override public void display() { // アクセス修飾子を緩和 System.out.println("Child's display"); } } </syntaxhighlight> ==== @Override アノテーション ==== * オーバーライドを明示 * コンパイル時チェック * コード可読性の向上 === 抽象化の仕組み === ==== 抽象クラス ==== * '''特徴''': ** インスタンス化不可 ** 抽象メソッドと具象メソッドの混在 ** 単一継承のみ :<syntaxhighlight lang=java copy> public abstract class Shape { protected String color; // 具象メソッド public void setColor(String color) { this.color = color; } // 抽象メソッド public abstract double calculateArea(); } </syntaxhighlight> === インターフェース === * '''特徴''': ** すべてのメソッドが抽象(Java 8以降はdefaultメソッド可) ** 定数のみ保持可能 ** 多重実装可能 :<syntaxhighlight lang=java copy> public interface Drawable { void draw(); // 抽象メソッド default void print() { // デフォルトメソッド System.out.println("Printing..."); } } </syntaxhighlight> === ジェネリクス === ==== 基本概念 ==== * 型パラメータによる汎用プログラミング * コンパイル時の型安全性確保 * コード再利用性の向上 ==== ジェネリッククラスの例 ==== :<syntaxhighlight lang=java copy> public class Container<T> { private T value; public Container(T value) { this.value = value; } public T getValue() { return value; } public void setValue(T value) { this.value = value; } } </syntaxhighlight> ==== 型パラメータの制約 ==== {| class="wikitable" ! 制約 !! 説明 !! 例 |- | 上限境界 || extends による制約 || <code><T extends Number></code> |- | 下限境界 || super による制約 || <code><T super Integer></code> |- | 複数境界 || & による連結 || <code><T extends Number & Comparable></code> |} ==== 使用例 ==== :<syntaxhighlight lang=java copy> Container<String> stringContainer = new Container<>("Hello"); Container<Integer> intContainer = new Container<>(42); String str = stringContainer.getValue(); // 型安全 Integer num = intContainer.getValue(); // 型安全 </syntaxhighlight> === アクセサ === アクセサ (Accessor) は、オブジェクトのフィールドにアクセスするためのメソッドのことです。フィールドへの直接アクセスを避け、'''ゲッター'''と'''セッター'''を用いることで、データのカプセル化と整合性を保ちます。 ==== ゲッター (Getter) ==== ゲッターはフィールドの値を取得するためのメソッドで、通常「<code>get</code> + フィールド名」の形式を取ります。 :<syntaxhighlight lang=java> public class MyClass { private int number; public int getNumber() { return number; } } </syntaxhighlight> この例では、<code>getNumber</code> メソッドが <code>number</code> フィールドの値を返します。 ==== セッター (Setter) ==== セッターはフィールドの値を設定するためのメソッドで、通常「<code>set</code> + フィールド名」の形式を取ります。 :<syntaxhighlight lang=java> public class MyClass { private int number; public void setNumber(int number) { this.number = number; } } </syntaxhighlight> セッターはフィールドの値を外部から安全に変更できるようにします。 === ベストプラクティス === クラスの設計におけるベストプラクティスを以下に示します。 # '''単一責任の原則を守る''': クラスは一つの責任または役割だけを持つべきです。 # '''カプセル化を徹底する''': フィールドを<code>private</code>で宣言し、アクセサを使用して外部アクセスを制御します。 # '''継承を適切に利用する''': 継承は親子関係が明確な場合にのみ使用し、インターフェースやコンポジションも検討します。 # '''不変性を推奨する''': フィールドを<code>final</code>で宣言するなどして、クラスの不変性を維持します。 # '''適切な命名を心掛ける''': クラスやメソッドに意味のある一貫した名前を付けます。 # '''コンストラクタを適切に設計する''': 必要な初期化を効率的に行い、引数の数を最小限にします。 # '''コメントとドキュメントを追加する''': コードの意図や使い方を明確に記述します。 これらを守ることで、保守性が高く拡張性のあるクラスを構築できます。 {{コラム|SOLID原則|width=100%|2=SOLID原則は、オブジェクト指向プログラミングにおける設計原則の集合であり、ソフトウェアの保守性、拡張性、再利用性を向上させるためのガイドラインを提供します。 SOLIDは以下の5つの原則からなります。 # 単一責任の原則(Single Responsibility Principle, SRP): #: 1つのクラスは1つの責務(役割)を持つべきであり、変更する理由は1つであるべきです。この原則により、クラスはシンプルで理解しやすくなり、変更に強い設計になります。 # オープン/クローズドの原則(Open/Closed Principle, OCP): #: ソフトウェアのエンティティ(クラス、モジュール、関数など)は、拡張に対して開いており、修正に対して閉じているべきです。すなわち、新しい機能を追加するときは既存のコードを変更せずに拡張できるようにするべきです。 # リスコフの置換原則(Liskov Substitution Principle, LSP): #: サブタイプ(派生クラス、実装クラス)は、その親タイプ(基底クラス、インターフェース)と置換可能でなければなりません。つまり、基底クラス型の変数に対して派生クラスのインスタンスを代入しても動作が変わらないことを保証する必要があります。 # インターフェース分離の原則(Interface Segregation Principle, ISP): #: クライアント(利用者)が利用しないメソッドに依存しないようにするために、クライアントにとって不要なインターフェースを実装しないように分割します。クライアントは必要な機能にのみ依存するべきです。 # 依存性逆転の原則(Dependency Inversion Principle, DIP): #: 上位のモジュールは下位のモジュールに依存すべきではなく、両方が抽象に依存すべきです。また、具象クラスにではなく抽象クラスやインターフェースに依存すべきです。これにより、コードの柔軟性が向上し、依存関係の注入(DI)などのパターンが可能になります。 SOLID原則は、ソフトウェアの品質を向上させるための強力なガイドラインであり、設計のバランスを保ちながら柔軟性と保守性を確保するのに役立ちます。これらの原則を遵守することで、より清潔で拡張可能なコードを作成することができます。 }} == コード例 == === Javaクラスと配列の操作例 === ;[https://paiza.io/projects/vGiAv_xXPraYJ93-dksSGw?language=java 配列]:<syntaxhighlight lang=java copy> /** * Javaクラスと配列の操作例 */ import java.util.*; /** * 人物を表すクラス */ class Person { // フィールド private String name; private int age; /** * コンストラクタ * @param name 名前 * @param age 年齢 */ public Person(String name, int age) { this.name = name; this.age = age; } /** * 名前のゲッター * @return 名前 */ public String getName() { return name; } /** * 名前のセッター * @param name 名前 */ public void setName(String name) { this.name = name; } /** * 年齢のゲッター * @return 年齢 */ public int getAge() { return age; } /** * 年齢のセッター * @param age 年齢 */ public void setAge(int age) { this.age = age; } } /** * メインクラス */ public class Main { /** * メインメソッド * @param args コマンドライン引数 */ public static void main(String[] args) { // ArrayListを使用してPersonオブジェクトのリストを作成 List<Person> peopleList = new ArrayList<>(); // Personオブジェクトをリストに追加 peopleList.add(new Person("Alice", 30)); peopleList.add(new Person("Bob", 25)); peopleList.add(new Person("Charlie", 35)); // 配列の要素を出力 for (Person person : peopleList) { System.out.println("Name: " + person.getName() + ", Age: " + person.getAge()); } } } </syntaxhighlight> === 行列クラスの実装例 === ;[https://paiza.io/projects/9iy_6ZXmiOJxrTrHlha11w?language=java 行列]:<syntaxhighlight lang=java copy> import java.util.*; /** * 行列演算を行うMatrixクラスの定義 */ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.function.BinaryOperator; /** * 行列を表すMatrixクラス */ class Matrix { /** 行数 */ private final int rows; /** 列数 */ private final int cols; /** 行列データ */ private final double[] data; /** * 行列のコンストラクタ * @param rows 行数 * @param cols 列数 */ public Matrix(int rows, int cols) { this.rows = rows; this.cols = cols; this.data = new double[rows * cols]; } /** * 行列のコンストラクタ * @param data 行列データ */ public Matrix(double[][] data) { this.rows = data.length; this.cols = data[0].length; this.data = new double[rows * cols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { this.data[cols * i + j] = data[i][j]; } } } /** * 行数を取得するメソッド * @return 行数 */ public int getRows() { return rows; } /** * 列数を取得するメソッド * @return 列数 */ public int getCols() { return cols; } /** * 指定された位置の要素を取得するメソッド * @param i 行インデックス * @param j 列インデックス * @return 指定された位置の要素 */ public double get(int i, int j) { return data[cols * i + j]; } /** * 指定された位置に要素を設定するメソッド * @param i 行インデックス * @param j 列インデックス * @param value 設定する値 */ public void set(int i, int j, double value) { data[cols * i + j] = value; } /** * 他の行列との加算を行うメソッド * @param other 加算する行列 * @return 加算結果の行列 */ public Matrix add(Matrix other) { return operate(other, Double::sum); } /** * 他の行列との減算を行うメソッド * @param other 減算する行列 * @return 減算結果の行列 */ public Matrix subtract(Matrix other) { return operate(other, (x, y) -> x - y); } /** * 行列とスカラーの乗算を行うメソッド * @param scalar 乗算するスカラー値 * @return 乗算結果の行列 */ public Matrix scalarMultiply(double scalar) { Matrix result = new Matrix(rows, cols); for (int i = 0; i < data.length; i++) { result.data[i] = this.data[i] * scalar; } return result; } /** * 行列の比較を行うメソッド * @param other 比較する行列 * @return 行列が等しい場合はtrue、そうでない場合はfalse */ public boolean equals(Matrix other) { if (this.rows != other.rows || this.cols != other.cols) { return false; } for (int i = 0; i < data.length; i++) { if (this.data[i] != other.data[i]) { return false; } } return true; } /** * 行列の文字列表現を返すメソッド * @return 行列の文字列表現 */ @Override public String toString() { StringBuilder sb = new StringBuilder(); for (int i = 0; i < data.length; i++) { sb.append(data[i]); if ((i + 1) % cols == 0) { sb.append("\n"); } else { sb.append(", "); } } return sb.toString(); } /** * 行列演算を行うメソッド * @param other 演算対象の行列 * @param operator 演算子 * @return 演算結果の行列 */ private Matrix operate(Matrix other, BinaryOperator<Double> operator) { if (rows != other.rows || cols != other.cols) { throw new IllegalArgumentException("Matrices must have the same dimensions"); } Matrix result = new Matrix(rows, cols); Iterator<Double> thisIterator = iterator(); Iterator<Double> otherIterator = other.iterator(); for (int i = 0; i < data.length; i++) { result.data[i] = operator.apply(thisIterator.next(), otherIterator.next()); } return result; } /** * 行列の要素にアクセスするイテレータを返すメソッド * @return 行列の要素にアクセスするイテレータ */ private Iterator<Double> iterator() { return new Iterator<Double>() { private int index = 0; @Override public boolean hasNext() { return index < data.length; } @Override public Double next() { if (!hasNext()) { throw new NoSuchElementException(); } return data[index++]; } }; } } /** * メインクラス */ public class Main { /** * メインメソッド * @param args コマンドライン引数 */ public static void main(String[] args) { Matrix a = new Matrix(new double[][]{{1, 2, 3}, {4, 5, 6}}); Matrix b = new Matrix(new double[][]{{7, 8, 9}, {10, 11, 12}}); // 加算 Matrix sum = a.add(b); System.out.println("Sum:"); System.out.println(sum); // 減算 Matrix difference = a.subtract(b); System.out.println("Difference:"); System.out.println(difference); // スカラー倍 Matrix scaled = a.scalarMultiply(2); System.out.println("Scaled:"); System.out.println(scaled); // 比較 System.out.println("Are matrices equal? " + a.equals(b)); } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Sum: 8.0, 10.0, 12.0 14.0, 16.0, 18.0 Difference: -6.0, -6.0, -6.0 -6.0, -6.0, -6.0 Scaled: 2.0, 4.0, 6.0 8.0, 10.0, 12.0 Are matrices equal? false </syntaxhighlight> {{DEFAULTSORT:くらす}} [[Category:Java]] [[Category:クラス|Java]] be04xni8x5f9heiomfruy14j2fedr73 中学校国語/表現技法 0 26097 263790 251404 2024-11-18T11:53:49Z ~2024-15064 84970 /* 体言止め */ 263790 wikitext text/x-wiki == 修辞法 == 文を強調するための技術を修辞法という。あくまで強調のためのものであり、使いすぎると強調点がわからなくなったり、いやみな文のように見えてしまう。また、小説や詩歌、話し言葉ではよく使われるが、説明文・論説文ではあまり使わない。 === 比喩 === 小学校では「たとえ」と習う。あるものを別のものにたとえることである。「~のようだ」という言葉を使う'''直喩'''(ちょくゆ)といい、それを使わない'''隠喩'''(いんゆ)または暗喩(あんゆ)といい、人間以外のものを人間のようにたとえる'''擬人法'''(ぎじんほう)がある。 例 :直喩「民さんはまるで野菊のような人だ。」(『野菊の墓』より)  :隠喩「(星をたとえて)夜空の宝石」 擬人法「(春の山をたとえて)山が笑っている。」 === 体言止め === 日本語の文では体言のみで終わることは少なく、「だ」「である」などをつけくわえる。それをあえて破り、体言のみの文末(述語)とすることを体言止め(たいげんどめ)といい、感動や詠嘆を表すことが多い。話し言葉では断定の助動詞「だ」などを省略することが多いため、結果的に体言止めになることは少なくない。 例:「五月雨をあつめてはやし最上川」(松尾芭蕉) === 倒置法 === 日本語の語順は主語・述語という順序が標準である。(また、修飾語と被修飾語も同様の語順である。)その語順を破ることで強調したいことを示したり、感動や詠嘆を表すことを倒置法(とうちほう)という。話し言葉や詩歌で多く使われる。 例:「きれいだなあ、この海は。」ここでは主語と述語の語順を入れ替えて述語を強調している。 === 反復 === 同じ語をくり返す方法。 例)嬉しい。まじで嬉しい。 === 擬人法 === 人間ではないものを人間に例える方法。 例 星が笑ってる。 === 対句 === 意味の近い言葉どうしやリズムの近い文どうしを合わせてセットにすることにより、組み合わせを強調する手法。詩歌などで情景を豊かに表す手法として用いることが多い。 例:「祇園精舎の鐘の声 諸行無常の響きあり 沙羅双樹の花の色 盛者必衰の理をあらはす」(『平家物語』より)このばあい、「祇園精舎の鐘の声」と「沙羅双樹の花の色」、「諸行無常」と「盛者必衰」が対になっている。 [[カテゴリ:中学校国語]] 8qjxn8t8gcn1jhiwccf7916sme9wwjh Kotlin 0 26659 263776 263477 2024-11-18T10:17:34Z Ef3 694 /*改廃された技術*/ Kotlinの改廃された技術や利用が推奨されない技術は、言語やエコシステムの進化、新しい要求、セキュリティ上の懸念などにより置き換えられます。以下に、代表的な技術を示します。 263776 wikitext text/x-wiki {{Pathnav|メインページ|工学|情報技術|プログラミング}} ---- {{Wikipedia}} <div style="width: fit-content;float:left; margin: 0 2rem 0 0">__TOC__</div> '''Kotlin'''は、[[w:JetBrains|JetBrains]]社によって開発された静的型付けされたオブジェクト指向のプログラミング言語で、[[W:Java仮想マシン|Java仮想マシン]](JVM)上で動作します。[[JavaScript]]や、[[W:LLVM|LLVMフレームワーク]]を介して多くのプラットフォームで実行可能なコードにもコンパイルできます。 また、Kotlin/Wasmは、Kotlinの新しいコンパイルターゲットであり、WebAssemblyをサポートする環境やデバイス上で実行可能なアプリケーションを作成することができます。これにより、Kotlinの強力な機能と柔軟性を活用して、Webアプリケーションやクライアントサイドのプログラミングにも取り組むことができます。 Kotlinは[[Java]]よりも簡潔で型安全性が高く、[[Scala]]よりもシンプルな言語を目指して開発されました。Scalaと比較して、簡略化された結果、コンパイルが高速化され、IDEでの言語サポートも充実しています。また、KotlinはJavaと完全な互換性があり、Java開発者は徐々に導入することができます。特に、KotlinはAndroidにも組み込まれており、既存のAndroidアプリケーションは、アプリケーション全体を書き換えることなくKotlinで新機能を実装することができます。Kotlin FoundationがKotlin™商標を守っています。 == はじめに == === 予備知識 === Kotlinは多様なプラットフォームで利用できるモダンで柔軟なプログラミング言語です。 このチュートリアルに取り組む前に、以下の予備知識が役立ちます。 ;プログラミング基礎: : 変数、制御構造(条件分岐、ループ)、関数など、プログラミングの基本的な概念を理解していることが望ましいです。これらの概念はKotlinを含む多くのプログラミング言語で共通しています。 ;オブジェクト指向プログラミング(OOP): :Kotlinはオブジェクト指向の概念を採用しており、クラス、オブジェクト、継承、ポリモーフィズムなどのOOPの基本的な理解が重要です。 ;Javaの基本知識(Kotlin/JVMの場合): :KotlinはJavaとの高い互換性を有しています。Javaの基本的な概念やJavaの標準ライブラリについての基本的な知識があると、Kotlin/JVMの理解がより深まります。 ;Web開発基礎(Kotlin/JSの場合): :Kotlin/JSはJavaScriptに変換され、Web開発に利用されます。HTMLやCSS、基本的なWeb開発の知識があると、Kotlin/JSを使用したWebアプリケーションの開発がスムーズに進みます。 ;ネイティブ開発基礎(Kotlin/Nativeの場合): :Kotlin/Nativeはネイティブな実行コードを生成し、組み込みシステムやiOSアプリケーションなどで利用されます。ネイティブ開発の基本的な知識があると、Kotlin/Nativeを活用した開発がしやすくなります。 以上の予備知識を持っていると、Kotlinをより効果的に学習し、異なるプラットフォームでの利用に対応することができます。各プラットフォームにおけるKotlinの特徴や最適な利用法を理解することで、幅広い開発環境で柔軟かつ効率的なプログラミングが可能になります。 ==== プログラミング経験者へ ==== Kotlinを学ぶ際に他の言語のプログラミング経験がある場合、以下のアドバイスが役立つかもしれません。 ;Java経験者へのアドバイス: :KotlinはJavaとの互換性が高いため、既存のJavaコードとの統合がスムーズに行えます。JavaのコードをKotlinに変換することも可能です。 :Kotlinの拡張関数やラムダ式など、新しい機能を積極的に試してみましょう。これにより、コードの簡潔性と可読性が向上します。 ;他の静的型付け言語経験者へのアドバイス: :Kotlinも静的型付け言語であり、型推論が強力です。しかし、null安全性や拡張関数など、他の言語にはない独自の機能にも焦点を当てて学習しましょう。 :Kotlinのコルーチンを利用して非同期処理を書くことで、他の言語での非同期コードよりもシンプルで効率的なコードを書けます。 ;関数型プログラミング経験者へのアドバイス: :Kotlinは関数型プログラミングの概念をサポートしています。ラムダ式や高階関数を駆使して、より宣言的で簡潔なコードを書く方法を探求してみてください。 :Kotlinの拡張関数やパターンマッチングを利用することで、関数型プログラミングの手法をさらに発展させることができます。 ;Android開発者へのアドバイス: :KotlinはAndroidの公式開発言語として広く採用されています。既存のJavaベースのAndroidプロジェクトでもKotlinへの移行が可能です。Android Studioとの統合を利用して、Androidアプリケーションの開発にKotlinを組み込んでみましょう。 総じて、Kotlinは他のプログラミング言語において得た経験を活かしやすい言語です。適応期間は短く、生産性を高めるために積極的に新しい機能や手法を試してみることが重要です。また、公式のドキュメントやサンプルコードを利用して、Kotlinの言語仕様やベストプラクティスに精通することもおすすめです。 ==== プログラミング未経験者へ ==== プログラミング未経験者がKotlinやプログラミング全般に取り組む際のアドバイスは以下の通りです: ;基本的なプログラミング概念の理解: :プログラミングの基本概念(変数、条件分岐、ループなど)を理解することから始めましょう。これらの基本的な概念はほぼ全てのプログラミング言語で共通しています。 ;Kotlinの特徴を理解: :KotlinがJavaとの互換性が高く、Androidアプリケーション開発で広く使われていることを知りましょう。Kotlinはコードの簡潔性や可読性を向上させるための多くの機能を提供しています。 ;オンライン教材やチュートリアルを活用: :オンライン上には多くの無料または低コストでプログラミングを学べる教材やチュートリアルがあります。これらのリソースを活用して基礎から学び、実際に手を動かしながら進めてみましょう。 ;実践を重視: :理論だけでなく、実際にコードを書いてみることが非常に重要です。小さなプログラムから始め、段階的に難易度を上げながら進めていくと良いでしょう。 ;エラーを恐れず、デバッグの練習: :プログラムでエラーが発生することはよくあることです。エラーを見つけて修正することはプログラミングの一部であり、そのプロセスを恐れずに経験してみましょう。 ;プロジェクトを通じた学習: :実際のプロジェクトに取り組むことで、プログラミングの実践的な側面を理解しやすくなります。小さなプロジェクトから始め、徐々に複雑性を増していくと良いでしょう。 ;コミュニティへの参加: :Kotlinやプログラミングに関するコミュニティやフォーラムに参加すると、他の学習者や経験者からのアドバイスやサポートを得ることができます。質問をしてコミュニケーションをとることも大切です。 ;継続的な学習と興味を持つ: プログラミングは絶え間ない学習が求められる分野です。新しい技術やツールに興味を持ち、継続的に学び続けることでスキルを向上させることができます。 プログラミングはスキルの向上に時間がかかるものですが、継続的な努力と実践を通じて着実に成長していきます。最初は小さなステップから始め、徐々に進んでいくことが大切です。 === Hello world === {{先頭に戻る|style=border-top:1px solid gray;}} 他の多くのチュートリアルがそうであるように、 私たちもまずはKotlinの世界にあいさつすることから始めましょう。hello.ktというファイルを作り、次のように書いて保存して下さい(Kotlinのソースファイルの拡張子は .kt です)。 ;[https://pl.kotl.in/JCCTJjX4_ hello.kt]:<syntaxhighlight lang=kotlin copy> fun main() = println("Hello, World!") </syntaxhighlight> それでは、ソースプログラムをコンパイルして実行してみましょう。 :<syntaxhighlight lang="console"> % kotlinc hello.kt -include-runtime -d hello.jar % java -jar hello.jar Hello, World! % _ </syntaxhighlight> # <code>fun main()</code> : #* <code>fun</code>は関数(function)を宣言するためのキーワードです。 #* <code>main</code>はプログラムのエントリーポイントとなる特別な関数の名前です。通常、プログラムの実行が始まるところです。 # <code>=</code> : #* このイコール記号は、関数の本体が始まることを示します。Kotlinでは、単一の式の関数を記述する際に、本体とイコールを省略して1行で記述できます。 # <code>println("Hello, World!")</code> : #* <code>println</code>はコンソールに文字列を表示するための関数です。<code>("Hello, World!")</code>は引数として渡される文字列です。 #* この行全体は、関数の呼び出しとして、文字列 "Hello, World!" をコンソールに表示するものです。 これにより、この一行のコードは「<code>main</code>という関数を宣言し、その中で 'Hello, World!' という文字列をコンソールに表示する」という単純なプログラムを実現しています。Kotlinはこのようにシンプルかつ読みやすい構文を持っており、初学者にも優れた学習言語となっています。 <br style="clear:both"> === クイックツアー === Kotlinのクイックツアーでは、基本的な構文や機能に焦点を当て、簡単なコード例を通じて言語の特徴を理解していきます。 # 変数と基本的なデータ型 #:<syntaxhighlight lang=kotlin copy> fun main() { // 変数の宣言 val message: String = "Hello, Kotlin!" // 自動型推論も可能 val number = 42 // 文字列テンプレート println("$message The answer is $number") } </syntaxhighlight> # 条件分岐とループ #:<syntaxhighlight lang=kotlin copy> fun main() { val score = 75 // 条件分岐 if (score >= 80) { println("Great job!") } else if (score >= 60) { println("Good job!") } else { println("You can do better.") } // ループ for (i in 1..5) { println("Count: $i") } } </syntaxhighlight> # 関数の定義と呼び出し #:<syntaxhighlight lang=kotlin copy> fun main() { // 関数の呼び出し greet("Alice") // 関数の定義 fun greet(name: String) { println("Hello, $name!") } } </syntaxhighlight> # クラスとオブジェクト #:<syntaxhighlight lang=kotlin copy> fun main() { // クラスの定義 class Person(val name: String, val age: Int) // オブジェクトの作成 val person = Person("John", 25) // プロパティへのアクセス println("${person.name} is ${person.age} years old.") } </syntaxhighlight> # Null安全性 #:<syntaxhighlight lang=kotlin copy> fun main() { // Null許容型 var name: String? = "Bob" // 安全呼び出し演算子 val length: Int? = name?.length // Elvis演算子 val result = name ?: "Guest" println("Name length: $length") println("Result: $result") } </syntaxhighlight> # 拡張関数 #:<syntaxhighlight lang=kotlin copy> fun main() { // 拡張関数の定義 fun String.addExclamation(): String { return "$this!" } // 拡張関数の呼び出し val greeting = "Hello".addExclamation() println(greeting) } </syntaxhighlight> # コルーチン #:<syntaxhighlight lang=kotlin copy> import kotlinx.coroutines.* fun main() { // コルーチンの起動 GlobalScope.launch { delay(1000) // 1秒待つ println("World!") } println("Hello, ") // プログラムを待機して終了しないようにする Thread.sleep(2000) // 2秒待つ } </syntaxhighlight> # Kotlin DSL #:<syntaxhighlight lang=kotlin copy> data class Person(val name: String, val age: Int) fun buildPerson(block: PersonBuilder.() -> Unit): Person { val builder = PersonBuilder() builder.block() return builder.build() } class PersonBuilder { var name: String = "" var age: Int = 0 fun build(): Person { return Person(name, age) } } fun main() { val person = buildPerson { name = "Alice" age = 30 } println("Built person: $person") // => Built person: Person(name=Alice, age=30) } </syntaxhighlight> #: この例では、Kotlin DSLを使用して、特定のドメイン(ここでは<code>Person</code>オブジェクトの構築)に特化した言語拡張を行っています。 # Smart cast #: Kotlinは型の安全性を高めるためにスマートキャストを提供しています。これにより、条件分岐やインスタンスのチェック後に自動的にキャストが行われ、冗長なキャストを省略できます。 #:<syntaxhighlight lang=kotlin copy> fun processValue(value: Any) { if (value is String) { // valueはString型として扱われる println(value.length) // ここでlengthプロパティにアクセスできる } if (value is Int) { // valueはInt型として扱われる println(value * 2) // ここでvalueをIntとして使用できる } // スマートキャストを利用することで、valueがどの型であるかを明示的にキャストする必要がない } fun main() { processValue("Hello") // 出力: 5 (Stringの長さ) processValue(10) // 出力: 20 (Intを2倍にした値) } </syntaxhighlight> これらの例はKotlinの基本を紹介するものであり、より高度な概念や機能も学ぶことができます。 {{:Kotlin/インストール方法}} {{:Kotlin/実行方法}} == 特徴 == {{先頭に戻る}} ; [[W:コンパイル型言語|コンパイル型言語]] : Kotlinはコンパイラーとして実装されています。REPLやスクリプティングエンジンもあります。 :; Kotlin/JVM: 1つまたは複数のソースコードをコンパイルしてJavaバイトコードを生成し、生成したJavaバイトコードを実行します。 :; Kotlin/JS: 1つまたは複数のソースコードをコンパイルしてJavaScriptを生成し、生成したJavaScriptを実行します。 :; Kotlin/Native: 1つまたは複数のソースコードをコンパイルしてLLVMインフラストラクチャーをバックエンドに実行形式を生成し、生成した実行形式を実行します。 :; Kotlin/Wasm: 1つまたは複数のソースコードをコンパイルしてWebAssembly(Wasm)バイナリを生成し、WebAssembly仮想マシン上で実行します。 ; [[W:静的型付け|静的型付け]] : 値・変数・関数のパラメーター・関数の戻値などの型はコンパイル時に検証され、[[W:型安全性|型安全性]]が担保されます。 ; [[W:例外#コンピュータと例外|例外]] : try-catch-finally 形の例外処理をサポートします。 ; [[W:多重定義#演算子の多重定義|演算子オーバーロード]]: サポートします。<code>a + b</code> は、メソッド形式 <code>a.plus(b)</code> と同義です。 ; [[W:多義定義|関数オーバーロード]] : 同じ名前で引数の数が異なる関数を定義することが可能です。 ; [[#ラムダ式|ラムダ式]]: サポートします。<code>{ a: Int, b: Int -> a + b }</code> ; [[#無名関数|無名関数]]: サポートします。<code>fun(a: Int, b: int) = a + b</code> ; [[#拡張関数|拡張関数]]: 既存のクラスに新しいメソッドを生やすことができます。これは Java のクラスライブラリーのクラスも例外ではありません。 ; 宣言や定義にはキーワードを伴う: 関数定義なら <code>fun</code>、定数宣言なら <code>val</code>、変数宣言なら <code>var</code>、クラス定義なら <code>class</code> など、明示的にキーワードを使い宣言するので grep フレンドリーです。また、列挙型は <code>enum</code> ではなく、<code>enum class</code> で列挙だと知らなくても '''class''' で検索すれば見落としません。C/C++は、<code>int f(int ch){...}, int i = 9;</code>のように、よく読まないと関数定義なのか変数宣言かわからないのとは対照的です。特にC++は、<code>int a(3)</code>が関数定義なのか変数宣言なのかに曖昧さがあり、パースの時点では確定せずコンパイラーもプログラマーも悩まされます。 ; [[W:型推論|型推論]] : サポートします。 ; [[W:ガベージコレクション|ガベージコレクション]] : サポートします。 ; [[W:クラス (コンピュータ)|クラス]] : クラスベースのオブジェクト指向言語です。 :; 全てがオブジェクト : Javaで言うプリミティブもオブジェクトで、メソッドを持ちます。 :; 祖先クラス : Any :; [[#コンストラクタ|コンストラクター]] : [[#プライマリーコンストラクター|プライマリーコンストラクター]]・[[#セカンダリコンストラクター|セカンダリコンストラクター]]・[[#init|init]] の3つのメソッドがインスタンス化の機能が割振られます。 :; [[#デストラクタ|デストラクター]] : ありません。 :; [[W:継承 (プログラミング)|継承]] : 単一継承をサポートします。 :; 抽象クラス : [[Java]] や [[Go]] の interface や [[Swift]] の protocol はありませんが、abstract class があります。 ; Mix-in : サポートします。 ; [[#名前空間|名前空間]] : [[#パッケージ|パッケージ]]が名前空間を持ちます。 ; defer : ありません。 ; 分岐構造は式 : [[#if|if]], [[#when|when]]は式です。 ; 文末の<code>;</code>(セミコロン): 必要ありません。 == コード・ギャラリー == {{先頭に戻る}} === エラトステネスの篩 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} エラトステネスの篩を、若干 Kotlin らしく書いてみました。 ;[https://pl.kotl.in/YOo5wiNi3 エラトステネスの篩]:<syntaxhighlight lang=kotlin line copy> fun eratosthenes(n: Int) { var sieve = BooleanArray(n + 1){ it >= 2 } for (i in 2..<sieve.size) { if (!sieve[i]) continue; for (j in i * i until sieve.size step i) sieve[j] = false if (i * i >= sieve.size) break; } for (i in 2..<sieve.size) { if (!sieve[i]) continue; print("$i ") } } fun main() { eratosthenes(100); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 </syntaxhighlight> : 使用頻度の高い sieve は、実行効率の良いプリミティブ型配列の BooleanArray として、初期化式を it >= 2 として宣言と同時に素数候補をマークしました。 : <var>i</var> のループはオーソドックスな IntRange をコレクションにした for ですが、<var>j</var> のループは少し変則的で until は制御構造に見えますが、メソッド <code>infix Int.until(to: Int) : IntProgression</code> で、infix 修飾による中置構文です。 === 最大公約数と最小公倍数 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} 最大公約数と最小公倍数を、若干 Kotlin らしく書いてみました。 ;[https://pl.kotl.in/eumYGumM7 最大公約数と最小公倍数]:<syntaxhighlight lang=kotlin line copy> tailrec fun gcd2(a: Int, b: Int): Int = if (b == 0) a else gcd2(b, a % b) fun gcd(vararg numbers: Int): Int = numbers.reduce(::gcd2) fun lcm2(a: Int, b: Int): Int = a * b / gcd2(a, b) fun lcm(vararg numbers: Int): Int = numbers.reduce(::lcm2) fun main() { println("gcd2(30, 45) => ${gcd2(30, 45)}") println("gcd(30, 72, 12) => ${gcd(30, 72, 12)}") println("lcm2(30, 72) => ${lcm2(30, 72)}") println("lcm(30,42,72) => ${lcm(30,42,72)}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> gcd2(30, 45) => 15 gcd(30, 72, 12) => 6 lcm2(30, 72) => 360 lcm(30,42,72) => 2520 </syntaxhighlight> : 関数 gcd2() は、2つの整数の最大公約数を[[W:ユークリッドの互除法|ユークリッドの互除法]]で求めています。 :: gcd2() の修飾子 <code>tailrec</code> は、コンパイラーに末尾再帰が行なわれていることを教え、再帰をループにするヒントを与えています。 : 関数 gcd() は可変引数関数で、全ての引数に gcd2() を適用し最大公約数を返します。 : 関数 lcm2() は、2つの整数の最小公倍数を、<math>GCD(m,n) \cdot LCM(m,n)=m \cdot n</math>を利用して求めています。 : 関数 lcm() は可変引数関数で、全ての引数に lcm2 を適用し最小公倍数を返します。 それぞれの関数定義は式形式で1行なので拍子抜けですが、概念を簡素にかけていると思います。 === 二分法 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} [[W:二分法|二分法]]を、若干 Kotlin らしく書いてみました。 ;[https://paiza.io/projects/HwIg-40sBXp5GOFWFTLKMA?language=kotlin 二分法]:<syntaxhighlight lang=kotlin line copy> import kotlin.math.abs tailrec fun bisection(low_: Number, high_: Number, f: (Double) -> Double) : Double { var low = low_.toDouble() var high = high_.toDouble() val x = (low + high) / 2; val fx = f(x); if (abs(fx) < +1.0e-10) return x; if (fx < 0.0) low = x; else high = x; return bisection(low, high, f); } fun main() { println(bisection(0, 3){x : Double -> x - 1}) println(bisection(0, 3){x : Double -> x * x - 1}) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 0.9999999999417923 1.0000000000291038 </syntaxhighlight> : [[旧課程(-2012年度)高等学校数学B/数値計算とコンピューター#2分法]]の例を Kotlin に移植しました。 : 命題の式をラムダで渡すのが肝ですが、Kotrinは関数の最後パラメーターが関数型の場合括弧の外に追い出せるので :: <code>bisection(0, 3){x : Double -> x - 1}</code>のような表現ができます。 : 引数で受取った範囲を一旦varに移替えているのは、関数の引数がイミュータブルなためです。 : また、どうせローカル変数に移すならパラメータは Number 型としてIntなども受け入れるようにし、.toDouble()で型を揃えています。 : このコードはまた、<code>[[#tailrec|tailrec]]</code> の好例にもなっています。 === 複素数型 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} オーソドックスな複素数型の実装(Kotlinの標準ライブラリーには複素数型が見当たらなかったので) {{:Kotlin/Complex.kt}} === クラス定義とインスタンス化とメンバー関数 === ;[https://paiza.io/projects/9XyNAIQyFNLCewZO020A6Q?language=kotlin シンプルなクラス定義]:<syntaxhighlight lang=kotlin line highlight="1-4,7,11" copy> class Hello(val s : String = "world") { override fun toString() = "Hello $s!" fun print() = println(s) } fun main() { val hello1 = Hello() println(hello1) hello1.print() val hello2 = Hello("my friend") println(hello2); hello2.print() print( """ Hello::class.simpleName => ${Hello::class.simpleName} hello1 => $hello1 hello2.s => ${hello2.s} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello world! world Hello my friend! my friend Hello::class.simpleName => Hello hello1 => Hello world! hello2.s => my friend </syntaxhighlight> : [[Ruby#クラス]]の例を、Kotlin に移植しました。 : 冒頭4行がクラス定義です。 : クラス定義に、他のオブジェクト指向言語ならコンストラクタに渡すような引数が渡されています。 : メンバーを公開するケースなら、この様に宣言的な引数リストを使うとメンバー定義と暗黙の初期値を与えられます。 : toString は、オブジェクトを文字列化するメンバー関数で、Anyの同名のメンバー関数をオーバーライドしています。 : print は、このクラスに独自なメンバー関数で、println() の戻値型(= Unit)を戻値型としています。 === ファイルの読出し === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} ;[https://paiza.io/projects/C2zvgreLywbWQvIGSzHGug?language=kotlin JavaのI/Oシステムを使いファイルを読込む]:<syntaxhighlight lang=kotlin line copy> import java.nio.file.Files import java.nio.file.Paths import java.nio.charset.Charset import java.io.IOException fun main() { try { for (s in Files.readAllLines(Paths.get("/etc/hosts"), Charset.forName("UTF-8"))) { println(s) } } catch (e: IOException) { e.printStackTrace() } } </syntaxhighlight> ;[https://paiza.io/projects/cfZOI-b1YK5S36_bao5Isw?language=kotlin readText版]:<syntaxhighlight lang=kotlin line copy> import java.io.File fun main(args: Array<String>) { print(File("/etc/hosts").readText()) } </syntaxhighlight> ==チートシート == {{先頭に戻る}} ;[[#エントリーポイント|エントリーポイント]] :;コマンドライン引数を受取らない場合 ::<syntaxhighlight lang=kotlin copy> fun main() { // ... } </syntaxhighlight> :;コマンドライン引数を受取る場合 ::<syntaxhighlight lang=kotlin copy> fun main(args: Array<String>) { println(args.contentToString()) } </syntaxhighlight> ;[[#コメント|コメント]]:<syntaxhighlight lang=kotlin style="width: fit-content" copy> // Kotlinには、行末で終わるコメントと fun main() { /* * 複数行に渡ることと * /* * 入れ子にすることができる * コメントがあります */ */ println("Hello, World!") } </syntaxhighlight> ;プリミティブデータ型 :{| class=wikitable style="text-align: center" !データ型!!サイズ<hr>(ビット)!!初期値 |- |Boolean||1||false |- |Byte||8||0 |- |Short||16||0 |- |Int||32||0 |- |Long||64||0L |- |Float||32||0.0f |- |Double||64||0.0 |} ;[[#変数|変数宣言]] :;[[#val|イミュータブル]]:<syntaxhighlight lang=kotlin inline>val 識別子 : 型 = 初期化式 ;</syntaxhighlight copy> ::;[[#型推論|型推論版]]:<syntaxhighlight lang=kotlin inline>val 識別子 = 初期化式 ;</syntaxhighlight copy> :;[[#var|ミュータブル]]:<syntaxhighlight lang=kotlin inline>var 識別子 : 型 = 初期化式 ;</syntaxhighlight copy> ; リテラル :; 整数リテラル:<syntaxhighlight lang=kotlin inline>123, 0b11010, 0o177, 0xbadbeef</syntaxhighlight copy> :; 浮動小数点数リテラル:<syntaxhighlight lang=kotlin inline>3.14, 1.2e-9</syntaxhighlight copy> :; 文字リテラル:<syntaxhighlight lang=kotlin inline>'a', '漢', '¥t'</syntaxhighlight copy> :; 文字列リテラル:<syntaxhighlight lang=kotlin inline>”abc”, "了解🏝👅"</syntaxhighlight copy> ::; 複数行に渡る文字列リテラル ::: <syntaxhighlight lang=kotlin style="width: fit-content" copy> """ 複数行に渡る場合は この様に 3つの"(ダブルクオーテーションマーク)で囲むことで記述できます。 """ </syntaxhighlight> :; 配列の生成:<syntaxhighlight lang=kotlin inline>arrayOf(2,3,5,7), Array(5){1+it)</syntaxhighlight copy> ; [[#制御構造|制御構造]] :; [[#分岐|分岐]] ::; [[#if|if]] :::;else節のないif ::::<syntaxhighlight lang=zig inline>if ( 条件式 ) 式</syntaxhighlight> ::::else節のないifは、値を取ろうとするとコンパイルエラーになります。 :::;ifの値 ::::<syntaxhighlight lang=zig inline>if ( 条件式 ) 式1 else 式2</syntaxhighlight> ::::条件式が false でなければifの値は 式1 ::::false ならば 式2 ::; [[#when|when]] :::;式で分岐:<syntaxhighlight lang=kotlin style="width: fit-content" copy> when ( 式 ) { 値0 -> 式0 値1, 値2... , 値n -> 式1 in 範囲式 -> 式2 !in 範囲式 -> 式3 is 型 -> 式4 !is 型 -> 式5   elase -> 式x } </syntaxhighlight> :::;式を省略すると true が仮定されます:<syntaxhighlight lang=kotlin style="width: fit-content" copy> when { 式0 -> 式0x 式1, 式2... , 式n -> 式1x   elase -> 式x } </syntaxhighlight> :::;値を返すwhen(による再帰):<syntaxhighlight lang=kotlin style="width: fit-content" copy> fun power(n: Int, i: Int) = when { i < 0 -> throw Exception("Negative powers of integers cannot be obtained.") i == 0 -> 1 i == 1 -> n else -> n * power(n, i - 1) } </syntaxhighlight> :; [[#繰返し処理|繰返し処理]] ::; [[#while|while]] :::<syntaxhighlight lang=kotlin copy> var i = 0 while (i < 5) { println(i) i++ } </syntaxhighlight> ::; [[#do-while|do-while]] :::<syntaxhighlight lang=kotlin copy> var i = 0 do { println(i) i++ } while (i < 5) </syntaxhighlight> ::; [[#for|for]] :::<syntaxhighlight lang=kotlin copy> for (i in 0 until 5) { println(i) } </syntaxhighlight> ; コレクション :;リストの生成 :;マップの生成 :;リストへのアクセス :;マップへのアクセス :;フィルタリング :;マップへの変換 ; クラス :;enum class :;abstract class ; 関数 :; 関数呼出し :; 関数定義 == KotlinとJavaの比較 == {{先頭に戻る}} KotlinとJavaは、どちらもJava Virtual Machine(JVM)上で動作するプログラミング言語です。以下は、KotlinとJavaの主な比較ポイントです。 # Null Safety(null安全性) #; Kotlin: Kotlinはnull安全性を重視しており、デフォルトで変数がnullになる可能性がある場合、その変数をnullableとして扱います。これにより、nullによる実行時のエラーを減少させます。 #; Java: 近年のJavaバージョンでは、<code>Optional</code>や<code>Nullable</code>などの概念が導入され、nullの扱いが改善されました。しかし、Kotlinのnull安全性はより厳格であり、コンパイル時の警告やエラーが発生しやすくなっています。 # コードの簡潔性 #; Kotlin: KotlinはJavaに比べてコードが簡潔で読みやすくなっています。これは、Kotlinがnullチェックや型推論などを自動的に処理し、冗長なコードを排除できるからです。 #; Java: Javaも近年ではラムダ式やストリームAPIなど、コードの簡潔性を向上させる機能が導入されていますが、依然として冗長なコードが残ることがあります。 # 関数型プログラミング #; Kotlin: Kotlinは関数型プログラミングをサポートしており、ラムダ式や高階関数の使用が簡単です。 #; Java: Javaも関数型プログラミングをサポートしていますが、Kotlinの方がよりシンプルになっています。 # 互換性 #; Kotlin: KotlinはJavaのライブラリやフレームワークを使用することができ、Javaとの相互運用性が高いです。また、JavaからKotlinに変換することも可能です。 #; Java: JavaはKotlinのコードを直接使用することはできませんが、既存のJavaコードとの連携がスムーズです。 # パフォーマンス #; Kotlin: KotlinはJavaに比べて少し遅いとされていますが、実際のアプリケーションではその違いがほとんど実感できないことが多いです。KotlinはJavaのバイトコードに変換されるため、ほとんど同じパフォーマンスを実現できます。 # ツールのサポート #; Kotlin: KotlinはJavaと同じツールを使用できるため、Javaエコシステムのメリットを享受しながら、より現代的な言語機能を利用できます。 総合的に見ると、KotlinはJavaよりも簡潔で読みやすく、より現代的な言語機能を備えています。ただし、Javaのライブラリやフレームワークを使用する場合は、Javaを使用することが必要な場合があります。 == KotlinとScalaの比較 == {{先頭に戻る}} KotlinとScalaは、どちらもJVM(Java Virtual Machine)上で動作する静的型付け言語であり、それぞれ異なる特徴を持っています。以下に、KotlinとScalaをいくつかの側面で比較してみます。 # パフォーマンス #; Kotlin: Kotlinは、Javaと同等のパフォーマンスを提供し、メモリ使用量が比較的少ないです。Androidアプリケーションの開発においては特に優れた性能を発揮します。 #; Scala: Scalaは一般的にはJavaよりも高速であるとされていますが、同時に多くのメモリを使用します。複雑なシステムの開発において、高いパフォーマンスが求められる場面で利用されます。 # 文法 #; Kotlin: Kotlinの文法はJavaに似ており、より簡素であり、Javaからの移行が容易です。これにより、Java開発者にとっては理解しやすいものです。 #; Scala: Scalaの文法は高度であり、関数型プログラミングの概念を強力にサポートしています。初めてのユーザーにとっては学習コストが高いかもしれませんが、高度な機能を提供しています。 # 開発用途 #; Kotlin: Kotlinは主にAndroidアプリケーションの開発に最適化されています。Android Studioでのサポートが強力であり、Androidエコシステムとの統合がスムーズです。 #; Scala: Scalaは複雑なシステムや大規模なプロジェクトの開発に適しています。特に関数型プログラミングの特徴を生かした開発に向いています。 # 可読性 #; Kotlin: KotlinはJavaと同じように、シンプルで読みやすいコードを書くことができます。文法がシンプルであるため、可読性が高いです。 #; Scala: Scalaは高度な機能を提供するが故に、可読性が低下する可能性があります。特に初心者にとっては、学習コストが高いと感じることがあります。 # 拡張性 #; Kotlin: Kotlinはよりシンプルでクラスベースのプログラミングスタイルを提供しており、拡張性があります。拡張関数や拡張プロパティなどが利用できます。 #; Scala: Scalaは関数型プログラミングの特徴を強調しており、高度な拡張性を提供しています。パターンマッチングや型クラスなどが利用できます。 総合的に見ると、KotlinはJavaからの移行が容易であり、Androidアプリケーションの開発に特に適しています。一方で、Scalaは関数型プログラミングの特徴を生かして複雑なシステムの開発に向いており、高度な拡張性を提供しています。選択する言語は、開発の目的や開発者のスキルセットによって異なることがあります。 == KotlinとSwiftの比較 == {{先頭に戻る}} KotlinとSwiftは、それぞれAndroidとiOSのアプリ開発で主に使用されるプログラミング言語です。以下に、両言語の類似点と相違点をいくつか挙げてみます。 ;類似点: :;静的型付け: ::KotlinとSwiftは両方とも静的型付け言語であり、コンパイル時に型の確認が行われます。これにより、実行時エラーを事前に把握しやすくなり、安全性が向上します。 :;モダンな構文: ::どちらの言語もモダンで読みやすい構文を採用しており、コードの記述が簡潔になっています。これにより、開発者は効率的かつ迅速にコードを書くことができます。 :;ヌル安全性: ::KotlinとSwiftはヌル安全性の考え方を取り入れており、ヌルポインターによるエラーを防ぐための手段を提供しています。これにより、安定したアプリケーションの開発が可能です。 ;相違点: :;ターゲットプラットフォーム: ::Kotlinは主にAndroidアプリ開発に焦点を当てていますが、JetBrainsによって開発・サポートされているため、マルチプラットフォーム開発にも利用されています。 ::SwiftはAppleが開発し、iOS、macOS、watchOS、tvOSなどのApple製品向けのアプリ開発に特化しています。 :;開発元とサポート: ::KotlinはJetBrainsによって開発・サポートされています。JetBrainsはプロの開発者向けのツールを提供しており、Kotlinの統合も図られています。 ::SwiftはAppleによって開発され、iOSや関連プラットフォーム向けに積極的にサポートされています。Xcodeなどの開発ツールも提供されています。 :;言語機能の違い: ::KotlinはJavaとの相互運用性が高く、既存のJavaコードとの統合が容易です。これにより、Android開発においても既存のJavaライブラリを利用することができます。 ::SwiftはObjective-Cとの相互運用性があり、iOS開発においてはObjective-Cコードとの統合が可能です。SwiftはObjective-Cよりもシンプルであり、関数型プログラミングの機能も強化されています。 :;構文と特徴: ::KotlinはJavaに似た構文を持ちつつ、いくつかの新しい機能や改善を提供しています。Javaからの移行が容易であり、Androidアプリケーション開発に適しています。 ::SwiftはObjective-Cよりもシンプルで読みやすい構文を持っており、関数型プログラミングの機能が強化されています。iOSアプリケーション開発において使用されます。 どちらの言語も優れた特性を持っており、選択はプロジェクトのニーズや開発者の好みによって異なります。 == エントリーポイント == {{先頭に戻る}} Kotlinでは、関数 mainがエントリーポイントです。 ;noop.kt:<syntaxhighlight lang=kotlin copy> fun main() {} </syntaxhighlight> なにもしないプログラムはこの様になります。 === コマンドライン引数を受取る場合 === ;use-args.kt:<syntaxhighlight lang=kotlin copy> fun main(args: Array<String>) { println(args.contentToString()) } </syntaxhighlight> ;Shell:<syntaxhighlight lang=text> % kotlinc use-args.kt -include-runtime -d use-args.jar % java -jar use-args.jar 123 abc 漢字 [123, abc, 漢字] % _ </syntaxhighlight> == パッケージ == {{先頭に戻る}} パッケージの指定は、ソースファイルの冒頭(shebang!の次)で行ってください<ref>[https://kotlinlang.org/docs/basic-syntax.html#package-definition-and-imports Package definition and imports]</ref>。 :<syntaxhighlight lang="Kotlin"> package my.demo import kotlin.text.* // Imprementation </syntaxhighlight> ディレクトリとパッケージの一致は必須ではなく、ソースファイルはファイルシステム上に任意に配置することができます。 === ディフォルトインポート === Kotlinでは、特定のパッケージやクラスを明示的にインポートすることなく、いくつかのデフォルトのインポートが提供されています。これにより、コードをより簡潔にし、冗長性を減少させることができます。以下は、デフォルトでインポートされる主要なパッケージです。 ;kotlin.*: Kotlinの基本的な機能や標準ライブラリが含まれています。これにより、Kotlinの核となる機能を利用するための基本的な道具が提供されます。 ;kotlin.annotation.*: アノテーション関連の機能が含まれています。アノテーションは、プログラムにメタデータを追加するための重要な手段です。 ;kotlin.collections.*: コレクション関連のクラスや関数が含まれています。これにより、リスト、セット、マップなどのデータ構造を効果的に扱うための機能が提供されます。 ;kotlin.comparisons.*: 比較関連の機能が含まれています。ソートや比較などの操作をより容易に行うことができます。 ;kotlin.io.*: 入出力関連の機能が含まれています。例えば、ファイルの読み書きや標準出力への出力などが簡単に行えます。 ;kotlin.ranges.*: 範囲関連の機能が含まれています。これを使用することで、特定の範囲内の要素を操作する際に便利なメソッドが提供されます。 ;kotlin.sequences.*: シーケンス処理関連の機能が含まれています。シーケンスを使用することで、遅延評価を活用して効率的なデータ処理が可能です。 ;kotlin.text.*: テキスト処理関連の機能が含まれています。文字列の操作やフォーマットなどが簡単に行えます。 また、ターゲットプラットフォームに応じて、追加のデフォルトインポートが行われます。 ;JVM: :;java.lang.*: Javaの基本的なクラスや機能が含まれています。これにより、Javaとの互換性が確保されます。 :;kotlin.jvm.*: JVM関連の機能が含まれています。 ;JS: :;kotlin.js.*: JavaScript関連の機能が含まれています。 上記のパッケージは、明示的にインポートすることなく既にインポートされています<ref>[https://kotlinlang.org/docs/packages.html#default-imports Default imports]</ref>。 このようなデフォルトのインポートにより、開発者は冗長なコードを書かずに済み、効率的にKotlinの機能を利用することができます。 ---- 以下は、デフォルトでインポートされる主要なパッケージの概要を表形式でまとめたものです。 :{| class=wikitable |+ デフォルトでインポートされる主要なパッケージ !パッケージ!!内容の概要 |- !kotlin.* |Kotlinの基本的な機能や標準ライブラリ |- !kotlin.annotation.* |アノテーション関連の機能 |- !kotlin.collections.* |コレクション関連のクラスや関数 |- !kotlin.comparisons.* |比較関連の機能 |- !kotlin.io.* |入出力関連の機能 |- !kotlin.ranges.* |範囲関連の機能 |- !kotlin.sequences.* |シーケンス処理関連の機能 |- !kotlin.text.* |テキスト処理関連の機能 |} また、ターゲットプラットフォームによっては、追加のデフォルトインポートが行われます。 :{| class=wikitable |+ ターゲットプラットフォーム別の追加のデフォルトインポート !ターゲットプラットフォーム!!追加されるパッケージの概要 |- !JVM |java.lang.*: Javaの基本的なクラスや機能 |kotlin.jvm.*: JVM関連の機能 |- !JS |kotlin.js.*: JavaScript関連の機能 |} これらのデフォルトインポートは、通常のKotlinプロジェクトで基本的な操作や機能を利用するための便利な手段となります。 === インポート === デフォルトインポートとは別に、各ファイルは独自の <code>[[#import|import]]</code> ディレクティブを含むことができます。 単一の名前でインポートすることができます。 import org.example.Message // Message は無条件にアクセスできます。 または、パッケージ、クラス、オブジェクトなどのスコープのすべてのアクセス可能なコンテンツをインポートすることができます。 import org.example.* // 'org.example' に含まれるすべてのコンテンツにアクセスできるようになります。 名前の衝突がある場合、as キーワードを使用して、衝突するエンティティの名前をローカルに変更することで、曖昧さをなくすことができます。 import org.example.Message // Message にアクセスできるようになります。 import org.test.Message as testMessage // testMessage は 'org.test.Message' を表しています。 import キーワードは、クラスのインポートに限定されません。他の宣言をインポートするためにも使用することができます。 * トップレベルの関数およびプロパティ * オブジェクト宣言の中で宣言された関数やプロパティ * enum 定数 === トップレベル宣言の可視性 === トップレベル宣言が private とマークされている場合、その宣言が行われたファイルに対してプライベートとなります。 {{See also|[[#可視性修飾子|可視性修飾子]]}} == トップレベルオブジェクト == {{先頭に戻る}} いかなる関数スコープにも属さないオブジェクトのことを、トップレベルオブジェクト( ''top level object'' )と言います<ref>[https://kotlinlang.org/spec/syntax-and-grammar.html#grammar-rule-topLevelObject topLevelObject]</ref>。 ;[https://paiza.io/projects/jKQiCwDXdUOhVY7dIoDmKg?language=kotlin トップレベルオブジェクトの前方参照は許される]:<syntaxhighlight lang="Kotlin"> val a = 10 fun main() { println("a =$a, b = $b") } val b = 32 </syntaxhighlight> ;実行結果:<syntaxhighlight lang="text"> a = 10, b = 32 </syntaxhighlight> :この例では変数 <var>b</var> の参照が前方参照になっていますが、<var>b</var> はトップレベルオブジェクトなので参照解決されます。 == コメント == {{先頭に戻る}} Kotlinには、行末で終わるコメントと、複数行に渡ることと、入れ子にすることができるコメントがあります。 ;[https://pl.kotl.in/F-bmww7Bt comments.kt]:<syntaxhighlight lang="Kotlin"> // Kotlinには、行末で終わるコメントと fun main() { /* * 複数行に渡ることと * /* * 入れ子にすることができる * コメントがあります */ */ println("Hello, World!") } </syntaxhighlight> : <code>/* ... */</code>タイプのコメントは、入れ子にできるのが多くのプログラミング言語と異なります。 :: Kotlinの他には、[[Scala]]と[[D言語]]がコメントを入れ子にできます。 == 基本型 == {{先頭に戻る}} Kotlinでは、任意のインスタンスに対してプロパティーを参照したりメンバー関数を呼出すことができるという意味で、すべてのインスタンスがクラスに属しています。 いくつかの型は特別な内部表現を持つことができます。例えば、数字、文字、ブール値は実行時にプリミティブ値として表現できますが、ユーザーからは参照されるときに自動的にボックス化されるので普通のクラスのインスタンスのように見えます。 これらの型は基本的にJavaのプリミティブに一対一に対応しますが、Stringだけはjava.lang.Stringクラスに対応しています。 基本型は Package kotlin で定義されています。 ; Kotlinの基本型 :;[[#論理型|論理型]]:<code>[[#Boolean|Boolean]]</code> {{---}} true, false :;[[#数値型|数値型]] ::;符号付き整数型:<code>[[#Byte|Byte]]</code> <code>[[#Short|Short]]</code> <code>[[#Int|Int]]</code> <code>[[#Long|Long]]</code> ::;符号無し整数型:<code>[[#UByte|UByte]]</code> <code>[[#UShort|UShort]]</code> <code>[[#UInt|UInt]]</code> <code>[[#ULong|ULong]]</code> :;[[#浮動小数点数型|浮動小数点数型]]:<code>[[#Float|Float]]</code><code>[[#Double|Double]]</code> :;[[#文字型|文字型]]: <code>[[#Char|Char]]</code> :;[[#文字列型|文字列型]]:<code>[[#String|String]]</code> ;[https://pl.kotl.in/sePeMiW1A primitive.kt]:<syntaxhighlight lang="Kotlin"> fun main() { println("値 : simpleName") println("----------------") arrayOf(true, 2.toByte(), 3.toUByte(), 5.toShort(), 7.toUShort(), 11, 13U, 17L, 19UL, 1.23, 3.14F, 'C', "abc").forEach { println("$it : ${it::class.simpleName}") } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 値 : simpleName ---------------- true : Boolean 2 : Byte 3 : UByte 5 : Short 7 : UShort 11 : Int 13 : UInt 17 : Long 19 : ULong 1.23 : Double 3.14 : Float C : Char abc : String </syntaxhighlight> :{| class="wikitable" |+ 基本型<ref>[https://kotlinlang.org/docs/basic-types.html Basic types]</ref> |- ! 型 ! Javaの型 ! リテラル表現 |- ! <syntaxhighlight lang=kotlin inline>Boolean</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>boolean</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>false, true</syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>Byte</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>byte</syntaxhighlight> | <syntaxhighlight lang=kotlin inline></syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>Short</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>short</syntaxhighlight> | <syntaxhighlight lang=kotlin inline></syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>Int</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>int</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>123, 0x17, 0b10110110</syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>Long</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>long</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>123L, 0x17L, 0b10110110L</syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>Double</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>double</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>1.73205080757,6.62607015e-34</syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>Float</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>float</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>1.73205080757f</syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>String</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>java.lang.String</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>"Simple sample text."</syntaxhighlight copy> |- ! <syntaxhighlight lang=kotlin inline>Char</syntaxhighlight copy> ! <syntaxhighlight lang=java inline>char</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>'Q'</syntaxhighlight copy> |} === 論理型 === Kotlinの論理型は <code>{{Anchor|Boolean}}</code> で ;偽: <code>{{Anchor|false}}</code> ;真: <code>{{Anchor|true}}</code> の2つの値以外は取りえません。 JVMでは、この型の非[[#Nullable|Nullable]]値は、プリミティブ型のbooleanの値として表現されます。 論理型と数値型は可換ではないので、制御構造の条件式などでもゼロとの比較を行う必要があります。 {{See also|[[#Nullable|Nullable]]}} === 数値型 === Kotlinの数値型は、[[#整数型|整数型]]と[[#浮動小数点数型|浮動小数点数型]]に分かれています。 これらの型は、抽象クラスである <code>{{Anchor|Number}}</code> クラスから派生しており、具象クラスとして利用されます。 なお、[[#文字型|文字型]]は数値型と可換ではありません。 ==== 整数型 ==== Kotlinの整数型には、符号付き整数型と符号なし整数型があります。 符号なし整数型の名前は、対応する符号付き整数型の名前の先頭に <code>U</code> を補ったものになります。以下が主な整数型です: :{| class=wikitable |+ 整数型 |- ! <code>{{Anchor|Byte}}</code> | 符号付き1バイト整数 |- ! <code>{{Anchor|Short}}</code> | 符号付き2バイト整数 |- ! <code>{{Anchor|Int}}</code> | 符号付き4バイト整数 |- ! <code>{{Anchor|Long}}</code> | 符号付き8バイト整数 |- ! <code>{{Anchor|UByte}}</code> | 符号なし1バイト整数 |- ! <code>{{Anchor|UShort}}</code> | 符号なし2バイト整数 |- ! <code>{{Anchor|UInt}}</code> | 符号なし4バイト整数 |- ! <code>{{Anchor|ULong}}</code> | 符号なし8バイト整数 |} ==== 浮動小数点数型 ==== Kotlinの浮動小数点数型には、以下の2つがあります: :{| class=wikitable |+ 浮動小数点数型 |- ! <code>{{Anchor|Float}}</code> | 単精度浮動小数点数;ISO/IEC/IEEE 60559:2011-06 のbinary32 |- ! <code>{{Anchor|Double}}</code> | 倍精度浮動小数点数;ISO/IEC/IEEE 60559:2011-06 のbinary64 |} これらの数値型は、数学的な演算や精密な計算に利用され、Kotlin言語において数値処理をサポートする基本的な要素となっています。 === 文字型 === {{先頭に戻る}} {{Anchor|Char}}クラスは文字を表すクラスです。'a' のようなKotlinプログラム内の文字リテラルはすべてこのクラスのインスタンスとして実装されています<ref>[https://kotlinlang.org/docs/characters.html Characters]</ref><ref name=char>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-char/ Char]</ref>。 <code>Char</code>は、16ビットのUnicode文字を表します。これは、Charがすべての文字をユニコード文字を表すことが'''出来ない'''事をしめしています。 ;[https://pl.kotl.in/KRFm8vVVb Charで表現できない文字]:<syntaxhighlight lang="Kotlin" highlight=4> fun main() { val ascii = 'A' val kanji = '漢' val emoji = '🏝' } </syntaxhighlight> ;コンパイル結果:<syntaxhighlight lang=text> Too many characters in a character literal ''🏝'' </syntaxhighlight> : 🏝のUnicodeはU+1F3DDと16ビットを超えているので Char には収容できません。 : 絵文字以外にもサロゲートペアはあり、サロゲートペア以外にも合成文字も16ビットを超えるものがあります。 Kotlinは、Javaの文字エンコーディングシステムを引継いだので、Charの収まらない文字の問題に限らずUnicodeを内部エンコーディングに使っていることに起因する厄介ごとと付き合い続ければなりません。 ==== 演算子 ==== Charでは、いくつかの演算子が定義されています<ref name=char/>。 ;[https://pl.kotl.in/pQ82wUEc_ Charクラスの演算子]:<syntaxhighlight lang="Kotlin" line> fun main() { var a = 'K' println("var a = 'K'") a-- println("a-- ⇒ $a") a++ println("a++ ⇒ $a") println("'C' - 'A' ⇒ ${'C' - 'A'}") println("'C' - 2 ⇒ ${'C' - 2}") println("'A' + 2 ⇒ ${'A' + 2}") println("'A'..'C' ⇒ ${'A' .. 'C'}") println("'A'..<'C' ⇒ ${'A' ..< 'C'}") println("'A' + \"BCD\" ⇒ ${'A' + "BCD"}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> var a = 'K' a-- ⇒ J a++ ⇒ K 'C' - 'A' ⇒ 2 'C' - 2 ⇒ A 'A' + 2 ⇒ C 'A'..'C' ⇒ A..C 'A'..<'C' ⇒ A..B 'A' + "BCD" ⇒ ABCD </syntaxhighlight> ==== エスケープシーケンス ==== 特殊文字は、エスケープする \(バックスラッシュ)から始まります。以下のエスケープシーケンスに対応しています。 :{| class="sortable wikitable" |+ エスケープシーケンス |- !表現!!意味 |- !\t |水平tab |- !\b |バックスペース |- !\n |改行(LF) |- !\r |キャリッジリターン(CR) |- !\' | シングルクォーテーション |- !\" |ダブルクオーテーションマーク |- !\\ |バックスラッシュ |- !\$ |ドル記号 |} その他の文字をエンコードする場合は、Unicodeエスケープシーケンス構文を使用します。'\uFF00' を使用します。 === 文字列型 === {{先頭に戻る}} {{Anchor|String}} クラスは文字列を表すクラスです。"abc" のようなKotlinプログラム内の文字列リテラルはすべてこのクラスのインスタンスとして実装されています<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/ String]</ref>。 Kotlinでは、文字列( <code>String</code> )と文字( <code>Char</code> )とは直接の関係はありません(StringはCharの配列ではありません)。 ==== 演算子 ==== Stringでは、加算演算子を連結として定義されています<ref>[https://github.com/JetBrains/kotlin/blob/f3385fbdcb8b9dc29661a8a4973c855cdcf73767/core/builtins/native/kotlin/String.kt#L30 kotlin/core/builtins/native/kotlin/String.kt]</ref>。 :<syntaxhighlight lang="Kotlin"> public operator fun plus(other: Any?): String </syntaxhighlight> 加算演算子( <code>+</code> )は、文字列( this )と与えられた他のオブジェクトの文字列表現を連結して得られる文字列を返します<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/plus.html plus - Kotlin Programming Language]</ref>。 ;[https://pl.kotl.in/1KlKcFKGs 文字列の+演算子]:<syntaxhighlight lang="Kotlin"> fun main() { val str = "ABC" + 12 println(str + true + listOf(1,2,3)) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ABC12true[1, 2, 3] </syntaxhighlight> ==== テンプレートリテラル ==== 既に紹介したように、Stringクラスのリテラルは "(ダブルクオーテーション)で括った文字列です。 Stringリテラルには変数や式を埋込むことが出来ます。 このように、変数や式が埋込まれたStringリテラルのことを{{Anchor|テンプレートリテラル}}といいます。 ;[https://pl.kotl.in/uBCbpW7Mc テンプレートリテラル]:<syntaxhighlight lang="Kotlin"> fun main() { var n = 10 println("変数 n の値は $n です。") println("式 n + 13 の値は ${n + 13} です。") println("${'$'} 自体を書きたいときは、 \\\$ と \$ の直前に \\ を置きエスケープします(\$\$ではありません)。") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 変数 n の値は 10 です。 式 n + 13 の値は 23 です。 $ 自体を書きたいときは、 \$ と $ の直前に \ を置きエスケープします($$ではありません)。 </syntaxhighlight> ==== 生文字列 ==== 生文字列( ''Raw strings'' )は、改行や任意のテキストを含むことができます。トリプルクォート(”””; ''triple quote'' )で区切られ、エスケープを含まず、改行や他の任意の文字を含むことができます<ref>[https://kotlinlang.org/docs/strings.html#raw-strings Raw strings]</ref>。 ;[https://pl.kotl.in/7Pqk1IwPo 生文字列]:<syntaxhighlight lang="Kotlin"> fun main() { var n = 10 print( """ 変数 n の値は $n です。 式 n + 13 の値は ${n + 13} です。 ${'$'} 自体を書きたいときは、 \$ と $ の直前に \ を置きエスケープします($$ ではありません)。 """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 変数 n の値は 10 です。 式 n + 13 の値は 23 です。 $ 自体を書きたいときは、 \$ と $ の直前に \ を置きエスケープします($$ ではありません)。 </syntaxhighlight> ==== エスケープシーケンス ==== {{See|[[#エスケープシーケンス|文字型のエスケープシーケンス]]}} ==== コードポイント ==== ;[https://pl.kotl.in/7Pqk1IwPo 文字列のn番目のコードポイント]:<syntaxhighlight lang="Kotlin"> fun main() { val str = "ABC漢字🏝𠮷" var i = 0 while (i < str.length) { println(Integer.toHexString(str.codePointAt(i))) i++ } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text highlight="7,9"> 41 42 43 6f22 5b57 1f3dd dfdd 20bb7 dfb7 </syntaxhighlight> : codePointAt()でサロゲートペアの2ワード目を読むと… === Array === Kotlinで配列型は Array で、main() の引数でも使われています<ref>[https://kotlinlang.org/docs/arrays.html Array]</ref><ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/ Array]</ref>。 [[#Array()|Array()]], [[#arrayOf()|arrayOf()]], arrayOfNulls() や emptyArray() で生成します。 ==== Array() ==== ;[https://paiza.io/projects/sywOsCKIuSuu8x2BrbdfwQ?language=kotlin Array()を使ったArrayの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val ary = Array(5){it} println("ary::class.simpleName ⇒ ${ary::class.simpleName}") println("ary[0]::class.simpleName ⇒ ${ary[0]::class.simpleName}") ary.forEach{print("$it ")} println("") val ary2 = Array(5){(it*it).toString()} println("ary2[0]::class.simpleName ⇒ ${ary2[0]::class.simpleName}") ary2.forEach{print("$it ")} println("") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary::class.simpleName ⇒ Array ary[0]::class.simpleName ⇒ Int 0 1 2 3 4 ary2[0]::class.simpleName ⇒ String 0 1 4 9 16 </syntaxhighlight> : Array()はArrayのコンストラクターで、引数として要素数をとり、ブロックが初期化式になります。 ==== プリミティブ型配列 ==== Kotlinには、IntArray、DoubleArray、BooleanArray、CharArrayなどのプリミティブ型を要素とする配列のクラスが用意されています。 これらを総称してプリミティブ型配列( Primitive type arrays )と呼びます<ref>[https://kotlinlang.org/docs/arrays.html#primitive-type-arrays Primitive type arrays]</ref>。 プリミティブ型配列は、機能的にはArray<T>のTにプリミティブ型を与えたものと変わりありませんが、ボックス化されないので性能向上とフットプリントの削減が期待できます。 このため、プリミティブ型配列はArrayを継承していません。 StringArray はありません。 ;[https://paiza.io/projects/tgs7lwP0-La0B-TUJ--kug?language=kotlin IntArray()を使ったIntArrayの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val ary = IntArray(5){it} println( """ ary::class.simpleName ⇒ ${ary::class.simpleName} ary[0]::class.simpleName ⇒ ${ary[0]::class.simpleName} ary => $ary ary.joinToString() ⇒ ${ary.joinToString()} ary.contentToString() => ${ary.contentToString()} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary::class.simpleName ⇒ IntArray ary[0]::class.simpleName ⇒ Int ary => [I@1c6b6478 ary.joinToString() ⇒ 0, 1, 2, 3, 4 ary.contentToString() => [0, 1, 2, 3, 4] </syntaxhighlight> ==== arrayOf() ==== ;[https://paiza.io/projects/avmXjK5ilEp1Xl-_CSnMfw?language=kotlin arrayOf()を使ったArrayの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val ary = arrayOf(1, 9, 3, 5, 23, 1) println("${ary::class.simpleName}") println("${ary[0]::class.simpleName}") for (s in ary) if (s > 10) break else print("$s ") println("") run { ary.forEach{ if (it > 10) return@run else print("$it ") } } println("") var i = 0 while (i < ary.size) ary[i] = i++ ary.forEach{print("$it ")} } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Array Int 1 9 3 5 1 9 3 5 </syntaxhighlight> : arrayOf()は可変長引数の関数で、引数が生成されるArrayの要素になります。 : Arrayの要素の型は、型強制できる最小公倍数的な方になります(例えば Int と Long が混在していたら Long)。 == 特別な型 == {{先頭に戻る}} 基本型の他にも幾つかの特別な型があります。 これらは、基本型同様 Package kotlin で定義されています。 ; 特別な型 :;Kotlinのクラス階層のルート:<code>[[#Any|Any]]</code> :;戻値型未指定な関数の型:<code>[[#Unit|Unit]]</code> :;存在しない値を表す型:<code>[[#Nothing|Nothing]]</code> === Any === AnyはKotlinのクラス階層のルートです。すべてのKotlinクラスはAnyをスーパークラスとして持っています。 クラス定義で継承元を指定しないと Any が暗黙の継承元になります。 また、Anyクラスのオブジェクトは、あらゆるオブジェクトを代入できます。 ;[https://pl.kotl.in/k-36Q8gd6 AnyのArray]:<syntaxhighlight lang="Kotlin"> fun main() { arrayOf(4, "abc", 'a', listOf(2,5,6)).forEach{ println("$it(${it::class.simpleName})") } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 4(Int) abc(String) a(Char) [2, 5, 6](ArrayList) </syntaxhighlight> === Unit === Unitは、何も返さない関数の戻値の型です。JVMでは、Javaのvoid型に相当します。 :<code>pub main() : Unit {}</code> は :<code>pub main() {}</code> と等価です。 === Nothing === Nothingはインスタンスを持ちません。例えば、ある関数の戻り値がNothingであれば、それは決して戻らない(常に例外を投げる)ことを意味します<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-nothing.html Nothing]</ref>。 == Null安全 == KotlinのNULL安全性(Null safety)とNullableに関して、以下のポイントが重要です。 # Null安全性: Kotlinの目標の一つは、null参照によるエラー(The Billion Dollar Mistakeとも呼ばれる)の危険性を排除することです。Javaを含む多くのプログラミング言語で見られる最も一般的な落とし穴の一つは、null参照のメンバーにアクセスすると、null参照例外が発生することです(JavaではNullPointerException、NPEと呼ばれます)。 # Nullable型と非Nullable型: Kotlinの型システムでは、nullを保持できる参照(Nullable型)と、保持できない参照(非Nullable型)とを区別します。たとえば、String型の通常の変数はnullを保持できませんが、NullableなString型はnullを保持できます。 # Nullable型の宣言: nullを許容する型を宣言するには、型名の後ろに「?」を付けます。例えば、String型のNullableな変数を宣言する場合は、<code>String?</code>とします。 # Nullable型の安全な操作: Nullableな変数やプロパティに安全にアクセスする方法として、以下のような手法があります。 #* <code>?.</code>演算子: セーフコール演算子は、nullチェックを行い、nullでない場合にのみメンバーにアクセスします。 #* <code>?:</code>演算子: Elvis演算子は、nullでない場合には左側の値を、nullの場合には右側の値を返します。 #* <code>!!</code>演算子: null許容型の値を非Nullable型として扱い、nullの場合にはNullPointerExceptionをスローします。 # Null安全性の確認: null安全性の確認は、条件式で明示的に行うことができます。<code>if (variable != null)</code>のような形で、nullチェックを行い、それに応じた処理を行います。 # Safe casts: 安全なキャスト演算子<code>as?</code>を使用すると、通常のキャストでClassCastExceptionが発生する可能性がある場合でも、nullを返すことができます。 KotlinのNull安全性とNullable型は、プログラミングにおける安全性と信頼性を向上させるための重要な機能です。これらの機能を適切に理解し、利用することで、Nullによるエラーを最小限に抑えることができます。 Javaを含む多くのプログラミング言語における最も一般的な落とし穴の1つは、Null参照のメンバーにアクセスするとNull参照例外が発生することです。Javaでは、これはNullPointerException、略してNPEと呼ばれるものに相当します<ref>[https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-null-types Nullable types and non-null types]</ref>。 KotlinでNPEが発生する原因として考えられるのは、以下の通りです。 * NullPointerException()を明示的に呼び出した場合。 * 後述する !! 演算子の使用。 * 初期化に関するデータの不整合(以下のような場合)。 ** コンストラクターで使用可能な未初期化の this がどこかで渡され使用されている (「リーキング this」)。 ** スーパークラスのコンストラクターが、派生クラスの実装で未初期化の状態を使用しているオープンメンバーを呼出す場合。 * Java との相互運用。 ** プラットフォーム型のNull参照のメンバにアクセスしようとする。 ** Java との相互運用に使用される汎用型の Nullability の問題。例えば、ある Java コードが Kotlin の MutableList<String> に null を追加し、それを操作するために MutableList<String?> が必要になることがあります。 ** その他、外部のJavaコードによって引き起こされる問題。 === Nullable === Kotlinの型システムでは、nullを保持できる参照(Null可能参照; ''nullable references'' )とそうでない参照(非Null参照; ''non-null references'' )を区別しています。例えば、String型の通常の変数はnullを保持できません。 :<syntaxhighlight lang=kotlin line highlight=2 copy> var a: String = "abc" // 通常の初期化ではデフォルトで非nullを意味します // a = null // コンパイルエラー! </syntaxhighlight> nullを許容するには、<code>String?</code>と書いて変数をnull可能な文字列として宣言します。 :<syntaxhighlight lang=kotlin line highlight="1,2" copy> var b: String? = "abc" // nullに設定可能 b = null // OK prinlnt(b) </syntaxhighlight> さて、<var>a</var>のメンバー関数を呼び出したり、プロパティーにアクセスしたりしても、NPEが発生しないことが保証されています。 :<syntaxhighlight lang=kotlin line copy> val l = a.length </syntaxhighlight> しかし、<var>b</var>のメンバー関数を呼び出したり、プロパティーにアクセスしたりすると、それは安全ではなく、コンパイラはエラーを報告します。 :<syntaxhighlight lang=kotlin line copy> val l = b.length </syntaxhighlight> それでもそのプロパティにアクセスする必要がありますよね?そのためには、いくつかの方法があります。 === 条件におけるnullのチェック === まず、bがnullかどうかを明示的にチェックし、2つの選択肢を別々に処理することができます。 :<syntaxhighlight lang=kotlin line copy> val l = if (b != null) b.length else -1 </syntaxhighlight> コンパイラーは実行したチェックの情報を記録し、ifの内部でlengthの呼出しを可能にする。より複雑な条件もサポートされています。 :<syntaxhighlight lang=kotlin line copy> val b: String? = "Kotlin" if (b != null && b.length > 0) { print("文字列の長さは ${b.length}") } else { print("空文字列") } </syntaxhighlight> 註:b が immutable な場合 (つまり、チェックから使用までの間に変更されないローカル変数か、 バッキングフィールドを持つオーバーライド不可のメンバー変数) にのみ有効です。 === !!演算子 === Not-Null断定演算子(!!)で任意の値をnullでない型に変換し、値がnullの場合は例外をスローします。<code>b!!</code>と書くと、<var>b</var>の非null値(例えばこの例ではString)を返し、<var>b</var>がnullの場合はNPEを投げます。 :<syntaxhighlight lang=kotlin line copy> val l = b!!.length </syntaxhighlight> このように、NPEを発生させたい場合は、明示的に要求する必要があり、突然発生することはありません。 === ?.演算子 === :<syntaxhighlight lang=kotlin line highlight=5 copy> fun main() { var str: String? = "Hello" // ?を使ってnullを許容する str = null // 問題なくnullを代入できる val length = str?.length // 安全呼び出し演算子でnullチェックしつつプロパティにアクセス println("Length: $length") } </syntaxhighlight> <code>?.</code> 演算子は、null安全性を保証しつつ、<code>str</code> 変数がnullでない場合に <code>length</code> プロパティにアクセスします。<code>str</code> がnullの場合、<code>length</code> には <code>null</code> が代入されます。 このように、<code>?.</code> 演算子はnull値を安全に処理するために使用されます。例えば、Javaの場合、nullチェックを行わないとNullPointerExceptionが発生しますが、Kotlinでは <code>?.</code> 演算子を使用することで、nullに対する操作を安全に行うことができます。 == 識別子 == {{先頭に戻る}} 変数の名前のような名前を識別子( ''identifiers'' )と呼びます<ref>[https://kotlinlang.org/spec/syntax-and-grammar.html#identifiers Identifiers]</ref>。 変数ほかに、関数、クラス、クラスのメンバー、クラスのメンバー関数、enum、ラベルなどの名前も識別子です。 * 同じ名前空間の中では識別子は重複できません。 * 識別子に使える文字は、英数字・_(アンダーバー)・Unicode文字です。 * 識別子の最初に数字を使うことはできません。 * 識別子の大文字小文字は区別されます。 * キーワードの使用には制限があります。 * キーワードや空白を含む文字列など上のルールに従わない文字列は、`(バッククオーテーション)で囲むと識別子として使うことができます。 {{See also|[[#キーワード|キーワード]]}} == 変数 == {{先頭に戻る}} Kotlinでは、変数は使う前にかならず宣言する必要があります。 === val と var === ==== val ==== ;[https://pl.kotl.in/8PE1c8KR3 変数を使った単純なコード]:<syntaxhighlight lang=kotlin line highlight="2,3" copy> fun main() { val hello = "Hello, World!" println(hello) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, World! </syntaxhighlight> :[[#Hello world|Hello world]]の例と結果は同じですが、変数<var>hello</var>を導入しています。 :;変数 hello の宣言:<syntaxhighlight lang=kotlin line start=2 copy> val hello = "Hello, World!" </syntaxhighlight> :イミュータブル変数の宣言は、この様に:<syntaxhighlight lang=kotlin copy> val 識別子 = 初期化式 </syntaxhighlight> :の形式をとります。 :;変数 hello の値の参照:<syntaxhighlight lang=kotlin line start=3 copy> println(hello) </syntaxhighlight> :の様に識別子をそのまま書くことで、値(この場合は "Hello, World!")を参照できます。 :キーワード <code>val</code> を使って宣言された変数はイミュータブル( ''Immutable'' )です。 :: イミュータブルというのは、一度値が決めたら変更できないという意味です。 :イミュータブルな変数を「定数」ということがありますが、リテラルのことを定数ということもあるので、ここでは「イミュータブルな変数」と呼びます。 ==== var ==== ;[https://pl.kotl.in/8z57OJeNL ミュータブルな変数を使ったコード]:<syntaxhighlight lang=kotlin line highlight="2,4" copy> fun main() { var hello = "Hello, World!" println(hello) hello = "Hello, Kotlin!" println(hello) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, World! Hello, Kotlin! </syntaxhighlight> :;変数 hello の宣言:<syntaxhighlight lang=kotlin line start=2 copy> var hello = "Hello, World!" </syntaxhighlight> :ミュータブルな変数の宣言は、この様に:<syntaxhighlight lang=kotlin copy> var 識別子 = 初期化式 </syntaxhighlight> :の形式をとります。 :キーワード <code>var</code> を使って宣言された変数はイミュータブル( ''Immutable'' )です。 :: ミュータブルというのは、変数の値を何度でも変更できるという意味です。 :;変数 hello に新しい値を代入:<syntaxhighlight lang=kotlin line start=4 copy> hello = "Hello, Kotlin!" </syntaxhighlight> :Kotlinでは <code>=</code> が代入演算子です。 :: 代入の前の <var>hello</var> の値は <code>"Hello, World!"</code> でしたが、代入の後は <code>"Hello, Kotlin!"</code> になります。 ==== 型推論 ==== いままでの例で既に型推論( ''type inference'' ) は使われています。 変数を宣言するときに、特に型を明示しませんでしたが、初期化式の型から変数の型を特定していたのです。 ===== 型アノテーション ===== 初期化式は省略可能です。 その場合は変数の型がわからないので型アノテーション( ''type annotation'' )が必要になります。 ;[https://pl.kotl.in/EW6hk7OkA 型アノテーションを伴った変数宣言]:<syntaxhighlight lang=kotlin line highlight="2" copy> fun main() { var hello : String hello = "Hello, World!" println(hello) hello = "Hello, Kotlin!" println(hello) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, World! Hello, Kotlin! </syntaxhighlight> :;型アノテーションを伴った変数 hello の宣言:<syntaxhighlight lang=kotlin line start=2 copy> var hello : String </syntaxhighlight> ::<code>: String</code>が型アノテーションで :型アノテーションを伴った変数の宣言は、この様に:<syntaxhighlight lang=kotlin copy> var 識別子 : 型 </syntaxhighlight> :の形式をとります。 ::型アノテーションをイミュータブルな変数の宣言でも行えますが、事実上初期化式が必須なのでドキュメント性を高める以外の意味は希薄です。 {{See also|[[#基本型|基本型]]}} ===== シャドーイング ===== シャドーイング( ''Shadowing'' )とは、スコープ内の2つの宣言が同じ名前になり、より内側の識別子が外側の識別子を隠すことです。 ;[https://paiza.io/projects/etUJhoaySpr4RcwO9VwO-g?language=kotlin コード例]:<syntaxhighlight lang="Kotlin" line highlight="2,4"> fun main() { var i = 10 for (i in 1..3) println("for内: i = $i") println("for外: i = $i") } </syntaxhighlight> ;コンパイラーの警告:<syntaxhighlight lang=text> Main.kt:4:10: warning: name shadowed: i for (i in 1..3) ^ </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> for内: i = 1 for内: i = 2 for内: i = 3 for外: i = 10 </syntaxhighlight> : ループ変数 <var>i</var> と、2行目で宣言された変数 <var>i</var> の名前が衝突しいています。 : この様に名前が衝突した場合、スコープの内側のオブジェクトが参照されます。 : コンパイラーはシャドーイングを発見すると<code>warning: name shadowed: 識別子</code>と(エラーでなく)警告します。 多くのシャドーイングは無害ですが… ;ありがちな間違え:<syntaxhighlight lang="Kotlin" line highlight="2,3"> fun main() { for (i in 1..3) for (i in 1..4) println("(i, i) = ($i, $i)") } </syntaxhighlight> ;コンパイラーのエラー出力:<syntaxhighlight lang=text> Main.kt:3:14: warning: name shadowed: i for (i in 1..4) ^ </syntaxhighlight> ;修正例:<syntaxhighlight lang="Kotlin" line highlight="3,4"> fun main() { for (i in 1..3) for (j in 1..4) println("(i, j) = ($i, $j)") } </syntaxhighlight> : 行列式を扱っていると、よくやらかします。 ===== 分解宣言 ===== オブジェクトを複数の変数に分解して初期化する宣言する方法があり、分解宣言( ''Destructuring declarations'' )と呼ばれます<ref>[https://kotlinlang.org/docs/destructuring-declarations.html Destructuring declarations]</ref>。 ;分解宣言の例:<syntaxhighlight lang="Kotlin" line highlight="2,4"> fun main() { val (a, b) = Pair(3, 4) val (c, d) = Pair("abc", 3.14) val (e, f) = 'C' to null val (g, h, i) = Triple(1,2,3) val (j, k, l, m) = List(4){it*2} print( """ a = $a, b = $b c = $c, d = $d e = $e, f = $f g = $g, h = $h, i = $i j = $j, k = $k, l = $l, m = $m """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> a = 3, b = 4 c = abc, d = 3.14 e = C, f = null g = 1, h = 2, i = 3 j = 0, k = 2, l = 4, m = 6 </syntaxhighlight> : to は infix 宣言された関数です。 == 演算子 == {{先頭に戻る}} === 演算子の優先順位 === :{| class="wikitable" |+ 演算子の優先順位<ref>[https://kotlinlang.org/docs/reference/grammar.html#expressions Expressions]</ref> !優先順位 !種類 !記号 |- |高い |後置 |<code>++</code>, <code>--</code>, <code>.</code>, <code>?.</code>, <code>?</code> |- | |前置 |<code>-</code>, <code>+</code>, <code>++</code>, <code>--</code>, <code>!</code>, label |- | |型 |<code>:</code>, <code>as</code>, <code>as?</code> |- | |乗除算 |<code>*</code>, <code>/</code>, <code>%</code> |- | |加減算 |<code>+</code>, <code>-</code> |- | |範囲 |<code>..</code>, <code>..<</code> |- | |中置関数(Infix function) |simpleIdentifier |- | |エルビス |<code>?:</code> |- | |Named checks |<code>in</code>, <code>!in</code>, <code>is</code>, <code>!is</code> |- | |比較 |<code><</code>, <code>></code>, <code><=</code>, <code>>=</code> |- | |一致不一致 |<code>==</code>, <code>!=</code>, <code>===</code>, <code>!==</code> |- | |Conjunction |<code>&&</code> |- | |Disjunction |<code><nowiki>||</nowiki></code> |- | |スプレッド演算子 |<code>*</code> |- |低い |代入演算 |<code>=</code>, <code>+=</code>, <code>-=</code>, <code>*=</code>, <code>/=</code>, <code>%=</code> |} {{See also|[[#演算子と特殊シンボル|演算子と特殊シンボル]]}} === 演算子オーバーロード === {{先頭に戻る|style=border-top:1px solid gray;}} Kotlinでは、演算子はメソッド形式の別名を持ちます。 例えば、<code>a + b</code> は <code>a.plus(b)</code> とも書けます。 この plus メンバー関数を再定義すると、演算子オーバーロードができます<ref>[https://kotlinlang.org/docs/operator-overloading.html Operator overloading]</ref>。 ;[https://paiza.io/projects/mhnZrTY0BmuFApKNAy3oNw?language=kotlin コード例]:<syntaxhighlight lang=Kotlin highlight="4,22-25" line> fun main() { class Point(val x : Int = 0, val y : Int = 0) { override fun toString() ="Point(x=$x, y=$y)" operator fun plus (other: Point) = Point(x + other.x, y + other.y) operator fun minus(other: Point) = Point(x - other.x, y - other.y) operator fun unaryMinus() = Point(-x, -y) override fun equals(other: Any?) = when { this === other -> true other !is Point -> false x != other.x -> false else -> y == other.y } } val p = Point(15, 25) val q = Point(20, 30) print( """ p => $p p.x => ${p.x}, p.y => ${p.y} q => $q p.plus(q) => ${p.plus(q)} p + q => ${p + q} 12 + 5 => ${12 + 5} 12.plus(5) => ${12.plus(5)} ---- p - q => ${p - q} -p => ${-p} p == q => ${p == q} p != q => ${p != q} p == Point(15,25) => ${p == Point(15,25)} p != Point(15,25) => ${p != Point(15,25)} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> p => Point(x=15, y=25) p.x => 15, p.y => 25 q => Point(x=20, y=30) p.plus(q) => Point(x=35, y=55) p + q => Point(x=35, y=55) 12 + 5 => 17 12.plus(5) => 17 ---- p - q => Point(x=-5, y=-5) -p => Point(x=-15, y=-25) p == q => false p != q => true p == Point(15,25) => true p != Point(15,25) => false </syntaxhighlight> 演算子は、もちろん加算だけではありません。 :{| class="wikitable" style="float:left" |+ 単項演算子 ! 式 ! メソッド形式 |- |<code>+a</code> |<code>a.unaryPlus()</code> |- |<code>-a</code> |<code>a.unaryMinus()</code> |- |<code>!a</code> |<code>a.not()</code> |- |<code>a++</code> |<code>a.inc()</code> |- |<code>a--</code> |<code>a.dec()</code> |} :{| class="wikitable" style="float:left" |+ 算術演算 ! 式 ! メソッド形式 |- |<code>a + b</code> |<code>a.plus(b)</code> |- |<code>a - b</code> |<code>a.minus(b)</code> |- |<code>a * b</code> |<code>a.times(b)</code> |- |<code>a / b</code> |<code>a.div(b)</code> |- |<code>a % b</code> |<code>a.rem(b)</code> |- |<code>a..b</code> |<code>a.rangeTo(b)</code> |- |<code>a..<b</code> |<code>a.rangeUntil(b)</code> |} :{| class="wikitable" style="float:left" |+ 包含 ! 式 ! メソッド形式 |- |<code>a in b</code> |<code>b.contains(a)</code> |- |<code>a !in b</code> |<code>!b.contains(a)</code> |} :{| class="wikitable" style="float:left" |+ インデックスによる要素参照 ! 式 ! メソッド形式 |- |<code>a[i]</code> |<code>a.get(i)</code> |- |<code>a[i, j]</code> |<code>a.get(i, j)</code> |- |<code>a[i_1, ..., i_n]</code> |<code>a.get(i_1, ..., i_n)</code> |- |<code>a[i] = b</code> |<code>a.set(i, b)</code> |- |<code>a[i, j] = b</code> |<code>a.set(i, j, b)</code> |- |<code>a[i_1, ..., i_n] = b</code> |<code>a.set(i_1, ..., i_n, b)</code> |} :{| class="wikitable" style="float:left" |+ 関数的な呼出し ! 式 ! メソッド形式 |- |<code>a()</code> |<code>a.invoke()</code> |- |<code>a(i)</code> |<code>a.invoke(i)</code> |- |<code>a(i, j)</code> |<code>a.invoke(i, j)</code> |- |<code>a(i_1, ..., i_n)</code> |<code>a.invoke(i_1, ..., i_n)</code> |} :{| class="wikitable" style="float:left" |+ 代入演算 ! 式 ! メソッド形式 |- |<code>a += b</code> |<code>a.plusAssign(b)</code> |- |<code>a -= b</code> |<code>a.minusAssign(b)</code> |- |<code>a *= b</code> |<code>a.timesAssign(b)</code> |- |<code>a /= b</code> |<code>a.divAssign(b)</code> |- |<code>a %= b</code> |<code>a.remAssign(b)</code> |} :{| class="wikitable" style="float:left" |+ 一致・不一致 ! 式 ! メソッド形式 |- |<code>a == b</code> |<code>a?.equals(b) ?: (b === null)</code> |- |<code>a != b</code> |<code>!(a?.equals(b) ?: (b === null))</code> |} :{| class="wikitable" style="float:left" |+ 比較演算 ! 式 ! メソッド形式 |- |<code>a > b</code> |<code>a.compareTo(b) > 0</code> |- |<code>a < b</code> |<code>a.compareTo(b) < 0</code> |- |<code>a >= b</code> |<code>a.compareTo(b) >= 0</code> |- |<code>a <= b</code> |<code>a.compareTo(b) <= 0</code> |} <br style="clear:both"> {{:Kotlin/制御構造}} {{:Kotlin/関数}} == 拡張 == Kotlinでは、クラスやインターフェースを継承したり、Decoratorのようなデザインパターンを使わずに、新しい機能を拡張することができます。これは、拡張( ''extensions'' )と呼ばれる特別な宣言によって実現されます<ref>[https://kotlinlang.org/docs/extensions.html Extensions]</ref>。 === 拡張関数 === 拡張関数( ''Extension functions'' )を宣言するには、その名前の前に拡張される型を示すレシーバー型をつけます<ref>[https://kotlinlang.org/docs/extensions.html#extension-functions Extension functions]</ref>。以下は、Array<Int>にrotate関数を追加したものです。 ;[https://pl.kotl.in/FiS-uHjPC Array<Int>にrotate()を定義]:<syntaxhighlight lang=kotlin line highlight=2 copy> fun main() { fun Array<Int>.rotate() { val t = this[0] var i = 1 while (i < this.size) { this[i - 1] = this[i] i++ } this[this.size - 1] = t } var ary = arrayOf(2, 3, 5, 7, 11) println("ary = ${ary.map{it.toString()}.joinToString(" ")}") ary.rotate() println("ary = ${ary.map{it.toString()}.joinToString(" ")}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary = 2 3 5 7 11 ary = 3 5 7 11 2 </syntaxhighlight> === ジェネリックスと拡張関数 === 拡張関数でも[[#ジェネリックス|ジェネリックス]](型パラメーター)が使用可能です。 先の例は、Array<Int>とIntのアレイ専用でしたが、任意の型 T のアレイ Array<T> に拡張関数を拡張してみましょう。 ;[https://pl.kotl.in/P4tm3lb8h <T>Array<T>にrotate()を定義]:<syntaxhighlight lang=kotlin line highlight=2 copy> fun main() { fun <T> Array<T>.rotate() { val t = this[0] var i = 1 while (i < this.size) { this[i - 1] = this[i] i++ } this[this.size - 1] = t } var ary = arrayOf(2, 3, 5, 7, 11) println("ary = ${ary.map{it.toString()}.joinToString(" ")}") ary.rotate() println("ary = ${ary.map{it.toString()}.joinToString(" ")}") var fary = Array(8){ val x = 1.0 * it; x * x } println("fary = ${fary.map{it.toString()}.joinToString(" ")}") fary.rotate() println("fary = ${fary.map{it.toString()}.joinToString(" ")}") var sary = arrayOf("A", "B", "C", "D", "E", "F") println("sary = ${sary.map{it.toString()}.joinToString(" ")}") sary.rotate() println("sary = ${sary.map{it.toString()}.joinToString(" ")}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary = 2 3 5 7 11 ary = 3 5 7 11 2 fary = 0.0 1.0 4.0 9.0 16.0 25.0 36.0 49.0 fary = 1.0 4.0 9.0 16.0 25.0 36.0 49.0 0.0 sary = A B C D E F sary = B C D E F A </syntaxhighlight> === 拡張は静的に解決されます === 拡張は、一見するとクラスの中に後からメンバー関数を追加しているように見えるかもしれませんが、<code>インスタンス.メソッド(実引数リスト)</code> のパターンに合致する拡張定義があるかを静的に調べ、該当する拡張関数があればそれを呼出すことで実現しています。 このため拡張関数でメンバー関数をオーバーライドすることはできません。 == クラス == {{先頭に戻る}} Kotlinは関数型プログラミング言語であると同時に、クラスベースのオブジェクト指向プログラミング言語です。 クラス( ''class'' )はオブジェクトの設計図であり、インスタンスはその設計図に基づいて作成されます。 === クラス定義 === クラスは、キーワード <code>{{Anchor|class}}</code>を使って定義します。 ;[https://pl.kotl.in/WSxMHFtzA 空のクラスの定義とインスタンス化]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X // クラス定義 fun main() { val x = X() // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X </syntaxhighlight> ;[https://pl.kotl.in/WlVaRbKmX private なプロパティ s を持つクラスの定義]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X constructor(s: String) // クラス定義 fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 // x.s --- Unresolved reference: s ;; s は private なので、ここでは参照できません } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X </syntaxhighlight> : <syntaxhighlight lang=kotlin inline>class X constructor(s: String)</syntaxhighlight copy> : この文脈での[[#ソフト・キーワード|ソフト・キーワード]] {{Anchor|constructor}} は、以下のように省略可能です。 : <syntaxhighlight lang=kotlin inline>class X(s: String)</syntaxhighlight copy> ;[https://pl.kotl.in/R7Fzx9K3G public でイミュータブルなプロパティ s を持つクラスの定義]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X(val s: String) // クラス定義 fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 println("x.s = ${x.s}") // プロパティーの値を表示 // x.s = "xyz" --- Val cannot be reassigned ;; イミュータブルなプロパティーは書換え不可 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X x.s = abc </syntaxhighlight> : プロパティーの値の参照はできますが、<code>val</code> なので書換えはできません。 ;[https://pl.kotl.in/sAHYBVMIM public でミュータブルなプロパティ s を持つクラスの定義]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X(var s: String) // クラス定義 fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 println("x.s = ${x.s}") // プロパティーの値を表示 x.s = "xyz" // イミュータブルなプロパティーは値の書換えが可能 println("x.s = ${x.s}") // プロパティーの値を表示 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X x.s = abc x.s = xyz </syntaxhighlight> : コンストラクターのパラメーターを <code>val</code> から <code>val</code> に変更したので、ミュータブルとなりプロパティーの値を変更できるようになりました。 ;[https://pl.kotl.in/IODi_0xMo init はコンストラクターの後に呼出されるブロック]:<syntaxhighlight lang=kotlin line highlight="1-3" copy> class X(var s: String) { // クラス定義 init { println("init: s = ${s}") } } fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 println("x.s = ${x.s}") // プロパティーの値を表示 x.s = "xyz" // イミュータブルなプロパティーは値の書換えが可能 println("x.s = ${x.s}") // プロパティーの値を表示 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> init: s = abc X x.s = abc x.s = xyz </syntaxhighlight> : クラス定義冒頭のコンストラクターにはコードをかけないので init ブロックに書きます === クラスのメンバー === * [[#コンストラクター|コンストラクター]]( ''constructor'' ) * [[#メンバー関数|メンバー関数]] * [[#プロパティー|プロパティー]] * [[#インナークラス|インナークラス]]( ''inner class'' ) * [[#オブジェクト|オブジェクト]]の宣言 ==== コンストラクター ==== Kotlinのクラスはプライマリーコンストラクターと1つまたは複数のセカンダリーコンストラクターを持つことができます。プライマリーコンストラクターはクラスヘッダの一部で、クラス名とオプションの型パラメターの後に続きます。 {{See also|クラス定義}} ==== メンバー関数 ==== メンバー関数は、クラス定義の中で定義された関数です<ref>[https://kotlinlang.org/docs/functions.html#member-functions Member functions]</ref>。 メンバー関数の呼出はドット記法で行います。 メンバー関数からは、プライベートなクラスのメンバーにアクセスできます。 ==== プロパティ ==== ==== オブジェクト ==== オブジェクトは、匿名クラスの定義とインスタンス化を同時に行うものです。 ;[https://paiza.io/projects/HRaRjZqiJz8DxWz3gh_mEg?language=kotlin オブジェクトの例]:<syntaxhighlight lang=kotlin line copy> fun main() { var obj = object { var a = 3 var b = 4 override fun toString() = "($a, $b)" } println( """ obj => $obj obj.a => ${obj.a}, obj.b => ${obj.b} obj::class.simpleName => ${obj::class.simpleName} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> obj => (3, 4) obj.a => 3, obj.b => 4 obj::class.simpleName => null </syntaxhighlight> === 継承 === クラスは、明示的に継承元を指定しない場合は <code>Any</code> を継承します。 === 継承モディファイア === 継承モディファイア( ''inheritance modifier'' )には、次のような種類があり、これらのトークンは[[#モディファイア・キーワード|モディファイア・キーワード]]です。 ==== abstract ==== [[#抽象クラス|抽象クラス]]( ''abstract class'' )は、抽象メンバー関数( ''abstract method'' )だけを持つクラスです。 モディファイア・キーワード <code>abstract</code> は、抽象メンバー関数の定義でも使われます。 ==== final ==== [[#ファイナルクラス|ファイナルクラス]]( ''final class'' )は、継承を禁止したクラスです。 KotlinのクラスはJavaと異なり、ディフォルトで継承禁止なので、継承禁止を強調する意味しかありません。 モディファイア・キーワード <code>final</code> は、オーバーライド禁止メンバーの宣言でも使われます。 ==== open ==== [[#オープンクラス|オープンクラス]]( ''open class'' )は、継承を許可したクラスです。 KotlinのクラスはJavaと異なり、ディフォルトで継承禁止なので、継承を行う可能性がある場合は明示的に許可する必要があります。 モディファイア・キーワード <code>open</code> は、メンバー関数のオーバーライド許可でも使われます。 {{コラム|Kotlinのクラスはディフォルトでfinal|2= Javaと異なり、Kotlinのクラスはディフォルトでfinal(継承禁止)です。 これは、主にセキュリティー上の理由からで、クラスを継承することによりprotectedでの隠蔽に綻びが生じプログラムが「ハイジャック」されることの重要さに配慮したもので、 クラス設計に於いてのトレードオフ、「拡張性と頑強性」のディフォルトを頑強に振った言語設計になっています。 {{See also|[https://www.jpcert.or.jp/java-rules/obj00-j.html OBJ00-J. 不変条件を持つクラスやメソッドの拡張は信頼できるサブクラスのみに許す]}} }} === this === クラスのメンバー関数が、プロパティやメンバー関数を参照するとき、クラスの外の変数や関数との間で曖昧さが生じる事があります。 このようなときには、インスタンスを表すキーワード <code>{{Anchor|this}}</code> を使います<ref>[https://kotlinlang.org/docs/this-expressions.html This expressions]</ref>。 <code>this</code> はこのほか、2 次コンストラクタから同じクラスの別のコンストラクタを呼出すときにもつかわれます。 ;[https://paiza.io/projects/a6IABje1M-ZOPH4asPyCpQ?language=kotlin thisを使ったメンバー関数の限定]:<syntaxhighlight lang=kotlin line copy> fun main() { fun printLine() = println("Function") class Simple { fun printLine() = println("Method") fun printLineNone() = printLine() fun printLineThis() = this.printLine() } val s = Simple() s.printLine() s.printLineNone() s.printLineThis() } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Method Function Method </syntaxhighlight> : メンバー関数から同じクラスのメンバー関数を呼出すとき、同名の関数があると関数が呼出されます。 : メンバー関数から同じクラスのメンバー関数を呼出すときには、同名の関数があると関数が呼出されます。 === クラスモディファイア === クラスモディファイア( ''class modifier'' )には、次のような種類があり、これらのトークンは[[#モディファイア・キーワード|モディファイア・キーワード]]です。 ==== enum ==== [[#列挙型クラス|列挙型クラス]]( ''Enum class'' )は、有限個の識別子の集合を表現するために使用されます。 :<syntaxhighlight lang=kotlin copy> enum class DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY } fun main() { val today = DayOfWeek.MONDAY println("Today is $today") } </syntaxhighlight> ;特性と用途 * 特定の値の集合を表現するために使用されます(例: 曜日、状態など)。 * 定数のような振る舞いを持ち、列挙型の各要素は固定された値として使用されます。 ==== sealed ==== シールドクラス( ''Sealed class'' )は、制限されたクラス階層を表現するために使用されます。 :<syntaxhighlight lang=kotlin copy> sealed class Result { data class Success(val data: String) : Result() data class Error(val message: String) : Result() } fun handleResult(result: Result) { when (result) { is Result.Success -> println("Success: ${result.data}") is Result.Error -> println("Error: ${result.message}") } } fun main() { val successResult = Result.Success("Data") val errorResult = Result.Error("An error occurred") handleResult(successResult) handleResult(errorResult) } </syntaxhighlight> ;特性と用途 * 制限されたクラス階層を定義するために使用されます。サブクラスは通常、シールドクラス内にネストされます。 * シールドクラスのサブクラスは通常、特定の型の状態や結果を表現するために使用されます。 ==== annotation ==== [[#アノテーションクラス|アノテーションクラス]]( ''annotation class'' )は、コードにメタデータを付加するための手段を提供します。 :<syntaxhighlight lang=kotlin copy> annotation class Author(val name: String) @Author("John Doe") class Book { // ブックの定義 } fun main() { val book = Book::class.java val authorAnnotation = book.getAnnotation(Author::class.java) val authorName = authorAnnotation?.name println("Author: $authorName") } </syntaxhighlight> ;特性と用途 * コードに追加情報や設定を提供するために使用されます。 * ランタイムやコンパイル時にアノテーションを処理することで、特定の動作やコード生成をトリガーすることができます。 ==== data ==== [[#データクラス|データクラス]]( ''Data class'' )は、データを保持するためのクラスで、copy() などのメンバー関数がクラスを定義しただけで生えてきます。 :<syntaxhighlight lang=kotlin copy> data class Person(val name: String, val age: Int) fun main() { val person = Person("Alice", 25) val copyPerson = person.copy(age = 30) println(person) println(copyPerson) } </syntaxhighlight> ;特性と用途 * データのコンテナとして使用され、自動的にequals()、hashCode()、toString()、copy()メソッドが生成されます。 * イミュータブルなデータオブジェクトを簡潔に表現するために使用されます。 ==== inner ==== [[#インナークラス|インナークラス]]( ''Inner class'' )は、入れ子になった内側になったクラスが外側のクラスのメンバーにアクセスすることを可能にします。 :<syntaxhighlight lang=kotlin copy> class Outer { private val outerProperty = "Outer Property" inner class Inner { fun printOuterProperty() { println(outerProperty) } } } fun main() { val outer = Outer() val inner = outer.Inner() inner.printOuterProperty() } </syntaxhighlight> ;特性と用途 * 外側のクラスのインスタンスに紐づく内側のクラスを定義するために使用されます。 * 内側のクラスは外側のクラスの非公開メンバーやプロパティにアクセスすることができます。 ==== value ==== [[#値クラス|値クラス]]( ''Value class'' )は、イミュータブルなスカラー値の型を定義します。プロポーザル段階では inline class と呼ばれていました。 :<syntaxhighlight lang=kotlin copy> inline class Password(val value: String) fun main() { val password = Password("secret") println("Password: ${password.value}") } </syntaxhighlight> ;特性と用途 * 単一の値を表すために使用されます。プリミティブ型のように振る舞い、ボックス化のオーバーヘッドを回避します。 + ラッパークラスとして機能し、型安全性やコードの表現力を向上させます。 ==== object ==== [[#オブジェクト|オブジェクト]]( ''object'' )は、モディファイア・キーワードではありませんが、特殊なクラスの一種なので併せて紹介します。 オブジェクトは一過的な匿名クラスを定義し、そのインスタンスの生成を行います。 :<syntaxhighlight lang=kotlin copy> object Logger { fun log(message: String) { println("Log: $message") } } fun main() { Logger.log("Hello, World!") } </syntaxhighlight> ;特性と用途 * シングルトンパターンを実装するために使用されます。クラスの単一のインスタンスを表現し、グローバルなアクセスポイントとして機能します。 * 関連するメソッドやプロパティを含めることができ、特定の目的に特化したオブジェクトを表現することができます。 ;まとめ 各クラスモディファイアは、異なる用途や特性を持っており、柔軟なクラス定義を可能にします。 適切なモディファイアを選択することで、コードの意図を明確に表現し、保守性や可読性を向上させることができます。 === 可視性モディファイア === [[#クラス|クラス]]、[[#オブジェクト|オブジェクト]]、[[#インターフェース|インターフェース]]、[[#コンストラクター|コンストラクター]]、[[#関数|関数]]、および[[#プロパティ|プロパティ]]とその[[#セッター|セッター]]は、可視性モディファイア( ''Visibility modifiers'' )を持つことができます。ゲッターは常にそのプロパティと同じ可視性を持っています<ref>[https://kotlinlang.org/docs/visibility-modifiers.html Visibility modifiers]</ref>。 可視性モディファイアには、次のような4種類があり、これらのトークンは[[#モディファイア・キーワード|モディファイア・キーワード]]です。 * [[#private|private]] * [[#protected|protected]] * [[#internal|internal]] * [[#public|public]] デフォルトの可視性はpublicです。 ==== パッケージ ==== 関数、プロパティ、クラス、オブジェクト、およびインタフェースは、パッケージの中で直接「トップレベル」で宣言することができます。 * 可視性モディファイアを使用しない場合、デフォルトではpublicが使用され、宣言はどこでも見えるようになります。 * 宣言に private を指定すると、その宣言を含むファイル内でのみ可視化されます。 * internalと指定した場合は、同じモジュール内であればどこでも見えるようになります。 * protected修飾子は、トップレベルの宣言には使えません。 ==== クラスのメンバー ==== クラス内部で宣言されたメンバー。 * private は、そのメンバーがこのクラスの内部でのみ可視であることを意味します(そのクラスのすべてのメンバーを含む)。 * protected は、private とマークされたメンバーと同じ可視性を持ちますが、サブクラスでも可視化されることを意味します。 * internal は、宣言したクラスを見たこのモジュール内のクライアントが、その内部のメンバーを見ることができることを意味します。 * public は、宣言クラスを見たすべてのクライアントがその public メンバを見ることができることを意味します。 protectedまたはinternalメンバーをオーバーライド( ''override'' )し、可視性を明示的に指定しない場合、オーバーライドしたメンバーも元のメンバーと同じ可視性を持つことになります。 ===== コンストラクター ===== クラスの一次コンストラクタの可視性を指定するには、次の構文を使用します。 :<syntaxhighlight lang=kotlin copy> class C private constructor(a: Int) { ... } </syntaxhighlight> :ここでは、コンストラクターは private です。デフォルトでは、すべてのコンストラクターは public です。これは、クラスが見えるところならどこでもコンストラクターが見えるということです(裏を返せば、内部クラスのコンストラクターは同じモジュール内でしか見えないということです)。 ===== ローカル宣言 ===== ローカル変数、関数、クラスは可視性モディファイアを持つことができません。 ==== モジュール ==== internal 可視性モディファイアは、そのメンバーが同じモジュール内で可視であることを意味します。具体的にモジュールとは、例えば、一緒にコンパイルされたKotlinファイルの集合のことです。 * IntelliJ IDEAモジュール。 * Mavenプロジェクト * Gradleのソースセット(ただし、testのソースセットはmainの内部宣言にアクセスできる)。 * ''kotlinc'' Antタスクの1回の呼び出しでコンパイルされるファイル群。 === 抽象クラス === 抽象クラス( ''abstract class'' )は、抽象メソッド( ''abstract method'' )だけを持つクラスであり、直接のインスタンス化ができません。抽象メソッドは本体を持たず、具体的な実装はそのサブクラスに委ねられます。Kotlinでは、<code>abstract</code> キーワードを使用して抽象クラスと抽象メソッドを宣言します。 ==== 抽象クラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> abstract class Shape { abstract fun draw() } class Circle : Shape() { override fun draw() { println("Drawing a circle") } } class Rectangle : Shape() { override fun draw() { println("Drawing a rectangle") } } </syntaxhighlight> 上記の例では、<code>Shape</code> という抽象クラスがあります。このクラスは抽象メソッド <code>draw</code> を宣言しています。サブクラスである <code>Circle</code> と <code>Rectangle</code> は、それぞれ <code>draw</code> メソッドをオーバーライドして具体的な実装を提供します。 ==== 抽象クラスのインスタンス化 ==== :<syntaxhighlight lang=kotlin copy> fun main() { // コンパイルエラー: Cannot create an instance of an abstract class // val shape = Shape() val circle = Circle() circle.draw() val rectangle = Rectangle() rectangle.draw() } </syntaxhighlight> 抽象クラスは直接インスタンス化できないため、<code>Shape</code> クラスのインスタンスを作成しようとするとコンパイルエラーが発生します。代わりに、具象サブクラスである <code>Circle</code> や <code>Rectangle</code> のインスタンスを作成して使用します。 ==== 抽象プロパティとコンストラクタ ==== 抽象クラスは抽象プロパティを持つこともできます。また、抽象クラス自体はコンストラクタを持つことができます。 :<syntaxhighlight lang=kotlin copy> abstract class Shape(val name: String) { abstract fun draw() } class Circle(name: String) : Shape(name) { override fun draw() { println("Drawing a circle named $name") } } class Rectangle(name: String) : Shape(name) { override fun draw() { println("Drawing a rectangle named $name") } } </syntaxhighlight> この例では、<code>Shape</code> クラスはコンストラクタを持ち、<code>name</code> という抽象プロパティを宣言しています。サブクラスである <code>Circle</code> と <code>Rectangle</code> は、コンストラクタで <code>name</code> を渡し、<code>draw</code> メソッドをオーバーライドしています。 抽象クラスは、クラス階層の一部として柔軟で再利用可能なコードを設計する際に役立ちます。 ==== ユースケースとベストプラクティス ==== 抽象クラスは、以下のようなユースケースやベストプラクティスに適しています。 ;部分的な実装の提供: 抽象クラスは、一部のメソッドやプロパティの実装を提供することができます。これにより、サブクラスは抽象メソッドだけでなく、既存の実装を再利用できます。 :<syntaxhighlight lang=kotlin copy> abstract class Shape { fun commonMethod() { // 共通の実装 } abstract fun draw() } </syntaxhighlight> ;メソッドの強制: 抽象クラスには抽象メソッドが含まれており、これをサブクラスで実装することが義務付けられます。これにより、サブクラスが特定のメソッドを実装することが保証されます。 :<syntaxhighlight lang=kotlin copy> abstract class Printer { abstract fun print() } class LaserPrinter : Printer() { override fun print() { // レーザープリンターの実装 } } </syntaxhighlight> ;継承と拡張: 抽象クラスを使用すると、クラス階層を構築し、新しい機能を追加していくことができます。これは、将来的に変更や拡張が発生する可能性がある場合に特に役立ちます。 :<syntaxhighlight lang=kotlin copy> abstract class Animal { abstract fun makeSound() } class Dog : Animal() { override fun makeSound() { println("Woof!") } } class Cat : Animal() { override fun makeSound() { println("Meow!") } </syntaxhighlight> ;コンストラクタとプロパティ: 抽象クラスはコンストラクタを持ち、抽象プロパティを宣言できます。これにより、サブクラスが特定のプロパティを持つことが保証され、コンストラクタで初期化できます。 :<syntaxhighlight lang=kotlin copy> abstract class Vehicle(val model: String) { abstract fun start() abstract fun stop() } class Car(model: String) : Vehicle(model) { override fun start() { println("Starting the car") } override fun stop() { println("Stopping the car") } } </syntaxhighlight> ;複数のインターフェースの代替: 抽象クラスは複数のメソッドやプロパティをまとめて提供できるため、インターフェースが多すぎる場合に、抽象クラスを使用して階層を整理することができます。 :<syntaxhighlight lang=kotlin copy> abstract class UIControl { abstract fun render() abstract fun onClick() } class Button : UIControl() { override fun render() { println("Rendering button") } override fun onClick() { println("Button clicked") } } </syntaxhighlight> 抽象クラスは、柔軟性と再利用性を向上させるために使われますが、適切に設計される必要があります。必要以上に多くの機能を含めると、過度な依存関係が生まれる可能性があるため、慎重な設計が求められます。 === ファイナルクラス === ファイナルクラス(<code>final class</code>)は、Kotlinにおいて継承を禁止したクラスを指します。Kotlinでは、デフォルトでクラスが継承不可(<code>final</code>)となっており、継承可能にするためには明示的に<code>open</code>修飾子を使用する必要があります。そのため、<code>final</code>キーワードは主にオーバーライド禁止メンバーの宣言で使用され、クラス自体に適用することは少ないです。 ==== ファイナルクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> final class MyFinalClass { // クラスの定義 } </syntaxhighlight> 上記の例では、<code>MyFinalClass</code> はファイナルクラスとして宣言されています。このクラスは他のクラスから継承できません。 ==== オーバーライド禁止メンバーの宣言 ==== :<syntaxhighlight lang=kotlin copy> open class MyBaseClass { final fun myFinalMethod() { // オーバーライド禁止のメソッド } } </syntaxhighlight> 上記の例では、<code>MyBaseClass</code> の <code>myFinalMethod</code> は <code>final</code> 修飾子が付いており、このメソッドはオーバーライドできません。 ==== ファイナルクラスの利用例 ==== :<syntaxhighlight lang=kotlin copy> final class Configuration { // クラスの定義 } class ApplicationSettings(config: Configuration) { // FinalClass を利用したクラスの定義 } </syntaxhighlight> 上記の例では、<code>Configuration</code> クラスがファイナルクラスとして定義されています。このクラスは他のクラスから継承できないため、設定情報の不正な変更や上書きを防ぐことが期待されます。<code>ApplicationSettings</code> クラスは <code>Configuration</code> を利用してアプリケーションの設定を管理しています。 ファイナルクラスは特定の状況で利用され、継承を禁止してクラスの拡張を制御するために使用されます。 === オープンクラス === オープンクラス(<code>open class</code>)は、Kotlinにおいて継承を許可したクラスを指します。 Kotlinのクラスはデフォルトで継承不可(<code>final</code>)となっているため、クラスを継承可能にするには明示的に<code>open</code>修飾子を使用する必要があります。 ==== オープンクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> open class MyOpenClass { // クラスの定義 } </syntaxhighlight> 上記の例では、<code>MyOpenClass</code> はオープンクラスとして宣言されています。このクラスは他のクラスから継承できます。 ==== メソッドのオーバーライド許可 ==== :<syntaxhighlight lang=kotlin copy> open class MyBaseClass { open fun myMethod() { // オーバーライド可能なメソッド } } </syntaxhighlight> 上記の例では、<code>MyBaseClass</code> の <code>myMethod</code> は <code>open</code> 修飾子が付いており、このメソッドはオーバーライド可能です。 ==== オープンクラスの利用例 ==== :<syntaxhighlight lang=kotlin copy> open class Shape { open fun draw() { println("Drawing a shape") } } class Circle : Shape() { override fun draw() { println("Drawing a circle") } } class Square : Shape() { override fun draw() { println("Drawing a square") } } </syntaxhighlight> 上記の例では、<code>Shape</code> クラスがオープンクラスとして定義されています。<code>Circle</code> と <code>Square</code> クラスが <code>Shape</code> を継承し、<code>draw</code> メソッドをオーバーライドしています。これにより、各図形クラスは自身の特定の描画方法を持つことができます。 オープンクラスは継承を許可し、クラスの拡張やカスタマイズが可能となります。ただし、使用する際には慎重に設計し、必要なメソッドやプロパティに対してのみ<code>open</code>修飾子を使用することが推奨されます。 === 列挙型クラス === {{先頭に戻る}} 列挙型クラス( ''Enum classes'' )は、キーワード <code>enum</code> を <code>class</code> に前置して定義します<ref>[https://kotlinlang.org/docs/enum-classes.html Enum classes]</ref>。 [[Swift/オブジェクト指向#列挙型]]の例を Kotlin 向けにモディファイしました。 ;[https://paiza.io/projects/lW6ghepnPWyQnctPdyX6Zw?language=kotlin 列挙型クラスとメソッド]:<syntaxhighlight lang=kotlin line copy> enum class Azimuth { North, South, East, West; override fun toString() = when (this) { Azimuth.North -> "北" Azimuth.South -> "南" Azimuth.East -> "東" Azimuth.West -> "西" } fun deg() = when (this) { Azimuth.North -> 0 * 90 Azimuth.South -> 2 * 90 Azimuth.East -> 1 * 90 Azimuth.West -> 3 * 90 } } fun main() { val n = Azimuth.North println("n => $n, az.deg() => ${n.deg()}") println("------------------------------------") for (az in Azimuth.values()) { println("as.name =>${az.name}, as => $az, az.deg() => ${az.deg()}") } println(enumValues<Azimuth>().joinToString{it.name}) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> n => 北, az.deg() => 0 ------------------------------------ as.name =>North, as => 北, az.deg() => 0 as.name =>South, as => 南, az.deg() => 180 as.name =>East, as => 東, az.deg() => 90 as.name =>West, as => 西, az.deg() => 270 North, South, East, West </syntaxhighlight> : override fun toString() でEnumのディフォルトの文字列化メソッドをオーバーライドしています。 === シールドクラス === シールドクラス(<code>Sealed class</code>)は、制限されたクラス階層を表現するために使用される Kotlin 特有の機能です。シールドクラスは、特定のサブクラスのみを許容し、新しいサブクラスの追加を防ぎます。これにより、特定の型に対するパターンマッチングが容易になります。 ==== シールドクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> sealed class Result { data class Success(val data: String) : Result() data class Error(val message: String) : Result() object Loading : Result() } </syntaxhighlight> 上記の例では、<code>Result</code> クラスはシールドクラスとして宣言されています。このクラスには3つのサブクラスがあります:<code>Success</code>、<code>Error</code>、および <code>Loading</code>。<code>Success</code> と <code>Error</code> はデータクラスで、それぞれデータを保持します。<code>Loading</code> はオブジェクトクラスで、データを保持しません。 ==== シールドクラスの利用例 ==== :<syntaxhighlight lang=kotlin copy> fun processResult(result: Result) { when (result) { is Result.Success -> println("Success: ${result.data}") is Result.Error -> println("Error: ${result.message}") Result.Loading -> println("Loading...") } } </syntaxhighlight> 上記の例では、<code>Result</code> クラスのサブクラスごとに異なる処理を行う <code>processResult</code> 関数があります。<code>when</code> 式を使用して、特定のサブクラスに対するパターンマッチングを行っています。 ==== 利点 ==== * コンパイラがすべてのサブクラスを知っているため、<code>when</code> 式などのパターンマッチングが網羅的であることを確認できます。 * 新しいサブクラスが追加された場合、コンパイラは未処理のケースがあるかどうかを検知し、警告を発生させます。 ==== 制限 ==== * シールドクラスは同じファイル内で宣言されたクラスに対してしか有効ではありません。 シールドクラスは、特に固定されたクラス階層を表現する場合や、特定の型に対する安全なパターンマッチングを行う場合に便利です。 === アノテーションクラス === アノテーションクラス(<code>annotation class</code>)は、Kotlinにおいてコードにメタデータを付加するための手段を提供します。これにより、コンパイラや実行時の処理で追加の情報を提供することが可能となります。 ==== アノテーションクラスの宣言 ==== アノテーションクラスは、<code>@</code>シンボルを使って宣言されます。アノテーションクラスの主な目的は、アノテーションを作成し、それをコードの要素に適用することです。 :<syntaxhighlight lang=kotlin copy> annotation class MyAnnotation(val name: String, val version: Int) </syntaxhighlight> 上記の例では、<code>MyAnnotation</code> というアノテーションクラスが宣言されています。このアノテーションは、<code>name</code> と <code>version</code> というパラメータを持っています。 ==== アノテーションの利用 ==== アノテーションは、クラスや関数、プロパティなど、さまざまな要素に適用できます。 :<syntaxhighlight lang=kotlin copy> @MyAnnotation(name = "MyApp", version = 1) class MyClass { @MyAnnotation(name = "MyFunction", version = 2) fun myFunction() { // 関数の本体 } } </syntaxhighlight> 上記の例では、<code>MyClass</code> クラスとその中の <code>myFunction</code> 関数に <code>MyAnnotation</code> が適用されています。これにより、このクラスや関数に対する追加のメタデータが提供されます。 ==== アノテーションのプロセッシング ==== アノテーションをプロセッシングするためには、リフレクションやKotlinのアノテーションプロセッサを使用することがあります。これにより、アノテーションに関連する処理を行うカスタムロジックを実装できます。 :<syntaxhighlight lang=kotlin copy> // アノテーションプロセッサの例 fun processMyAnnotation(element: AnnotatedElement) { val myAnnotation = element.getAnnotation(MyAnnotation::class.java) if (myAnnotation != null) { println("Name: ${myAnnotation.name}, Version: ${myAnnotation.version}") } } </syntaxhighlight> 上記の例では、<code>AnnotatedElement</code>を受け取り、その要素に <code>MyAnnotation</code> が適用されているかを調べ、情報を取得しています。 アノテーションクラスは、コードにメタデータを追加し、プロセッシングや設定などの目的で使用されます。 === データクラス === データクラス(<code>Data class</code>)は、Kotlinにおいてデータの保持や操作を目的としたクラスで、<code>copy()</code> メソッドなどがクラスを定義するだけで自動的に生成されます。これにより、不変性やイミュータビリティ(immutable)を維持しながら、簡潔で効果的なデータクラスを作成できます。 ==== データクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> data class Person(val name: String, val age: Int) </syntaxhighlight> 上記の例では、<code>Person</code> クラスがデータクラスとして宣言されています。コンストラクタで定義されたプロパティ(<code>name</code> と <code>age</code>)に対して、<code>equals()</code>、<code>hashCode()</code>、<code>toString()</code> などの標準メソッドが自動的に生成されます。 ==== データクラスの利用 ==== :<syntaxhighlight lang=kotlin copy> val person1 = Person("Alice", 30) val person2 = Person("Alice", 30) // equals() メソッドにより、プロパティの内容が一致するか比較 println(person1 == person2) // true // toString() メソッドにより、クラスの内容を文字列として表示 println(person1.toString()) // Person(name=Alice, age=30) // copy() メソッドにより、一部のプロパティを変更した新しいインスタンスを作成 val modifiedPerson = person1.copy(age = 31) println(modifiedPerson) // Person(name=Alice, age=31) </syntaxhighlight> 上記の例では、<code>equals()</code> メソッドにより <code>person1</code> と <code>person2</code> の内容が一致するか比較され、<code>toString()</code> メソッドによりクラスの内容が文字列として表示されます。また、<code>copy()</code> メソッドを使って一部のプロパティを変更した新しいインスタンスを作成しています。 ==== データクラスの生成されるメソッド ==== データクラスが生成される主なメソッドは以下の通りです。 * <code>equals()</code>: プロパティごとの内容比較を行います。 * <code>hashCode()</code>: プロパティごとにハッシュコードを生成します。 * <code>toString()</code>: クラスの内容を文字列として返します。 * <code>copy()</code>: インスタンスのコピーを作成します。一部のプロパティを変更できます。 データクラスは、イミュータブルでありながら効果的にデータを操作するための便利な手段を提供します。 === インターフェース === Kotlinのインターフェース(<code>interface</code>)は、抽象的なメソッドの宣言と、メソッドの実装を含むことができます。インターフェースは、抽象クラスと異なり状態を保持することができません。プロパティを持つ場合、これらは抽象クラスであるか、アクセサーの実装を提供する必要があります<ref>[https://kotlinlang.org/docs/interfaces.html Interfaces]</ref>。 ==== インターフェースの宣言 ==== :<syntaxhighlight lang=kotlin copy> interface MyInterface { fun doSomething() // 抽象メソッドの宣言 fun doSomethingElse() { // デフォルトのメソッド実装 println("Default implementation of doSomethingElse") } val property: Int // 抽象プロパティの宣言 } </syntaxhighlight> 上記の例では、<code>MyInterface</code> インターフェースが、抽象メソッド <code>doSomething()</code> とデフォルトのメソッド <code>doSomethingElse()</code>、抽象プロパティ <code>property</code> を宣言しています。 ==== インターフェースの実装 ==== :<syntaxhighlight lang=kotlin copy> class MyClass : MyInterface { override fun doSomething() { // メソッドの実装 println("Implementation of doSomething") } override val property: Int get() = 42 // プロパティの実装 } </syntaxhighlight> 上記の例では、<code>MyClass</code> クラスが <code>MyInterface</code> インターフェースを実装しています。<code>doSomething()</code> メソッドと <code>property</code> プロパティをオーバーライドしています。 ==== インターフェースの複数準拠 ==== :<syntaxhighlight lang=kotlin copy> interface A { fun methodA() } interface B { fun methodB() } class C : A, B { override fun methodA() { // A インターフェースの実装 } override fun methodB() { // B インターフェースの実装 } } </syntaxhighlight> 上記の例では、<code>C</code> クラスが <code>A</code> インターフェースと <code>B</code> インターフェースの両方を実装しています。複数のインターフェースをカンマで区切って指定することができます。 ==== インターフェースの継承 ==== :<syntaxhighlight lang=kotlin copy> interface D : A, B { fun methodD() } </syntaxhighlight> 上記の例では、<code>D</code> インターフェースが <code>A</code> インターフェースと <code>B</code> インターフェースを継承しています。これにより、<code>D</code> インターフェースは <code>A</code> と <code>B</code> のメソッドを含むことになります。 Kotlinのインターフェースは、クラスが異なる振る舞いを持つ場合に簡潔で柔軟な解決策を提供します。異なるインターフェースを実装することで、複数の振る舞いを同じクラスで組み合わせることができます。 === インナークラス === インナークラス(<code>Inner class</code>)は、入れ子になった内側のクラスが外側のクラスのメンバーにアクセスすることを可能にします。これにより、外側のクラスと強い結びつきを持ちながら、内部で独自の振る舞いやデータを持つクラスを定義できます。 ==== インナークラスの宣言 ==== <syntaxhighlight lang=kotlin copy> class OuterClass { private val outerProperty: Int = 10 inner class InnerClass { fun printOuterProperty() { // OuterClass のプロパティにアクセス println("Outer property: $outerProperty") } } } </syntaxhighlight> 上記の例では、<code>OuterClass</code> という外側のクラスがあり、その中に <code>InnerClass</code> というインナークラスが定義されています。<code>InnerClass</code> は <code>OuterClass</code> のプロパティにアクセスすることができます。 ==== インナークラスの利用 ==== <syntaxhighlight lang=kotlin copy> fun main() { val outerInstance = OuterClass() val innerInstance = outerInstance.InnerClass() innerInstance.printOuterProperty() } </syntaxhighlight> 上記の例では、<code>OuterClass</code> のインスタンスを作成し、そのインナークラスである <code>InnerClass</code> のインスタンスを取得しています。そして、<code>InnerClass</code> のメソッドを呼び出して外側のクラスのプロパティにアクセスしています。 ==== インナークラスの特徴 ==== # 外部クラスへのアクセス: インナークラスは、外部クラスのメンバーにアクセスできます。外部クラスのプロパティやメソッドに直接アクセスできるため、疎結合な設計が可能です。 # thisキーワードの挙動: インナークラスでは、外部クラスのインスタンスにアクセスするために <code>this@OuterClass</code> のように明示的な指定ができます。これにより、外部クラスのメンバーと同じ名前のメンバーがインナークラス内にある場合に区別できます。 # 非静的なクラス: インナークラスは外部クラスのインスタンスに依存しており、非静的なクラスです。したがって、外部クラスのインスタンスが存在しないとインナークラスも存在しません。 インナークラスは、外部クラスとの緊密な連携が必要な場合や、外部クラスのプライベートなメンバーにアクセスする必要がある場合に有用です。 === 値クラス === 値クラス(<code>data class</code>)は、イミュータブルでスカラーな値の型を定義するための概念です。プロポーザル段階では <code>inline class</code> と呼ばれていました。値クラスは、プリミティブ型のように振る舞い、同時に型安全性を提供します。 ==== 値クラスの宣言 ==== <syntaxhighlight lang=kotlin copy> data class Email(val value: String) </syntaxhighlight> 上記の例では、<code>Email</code> という値クラスが宣言されています。この値クラスは、イミュータブルであり、<code>value</code> というプロパティを持っています。 ==== 値クラスの利用 ==== <syntaxhighlight lang=kotlin copy> fun main() { val email1 = Email("john@example.com") val email2 = Email("jane@example.com") println(email1 == email2) // 値クラスの比較 } </syntaxhighlight> 上記の例では、異なるインスタンスの <code>Email</code> クラスを作成し、その値が等しいかを比較しています。値クラスでは、プライマリコンストラクタの引数で値が確定し、その値に基づいて等価性が判定されます。 ==== 値クラスの特徴 ==== # イミュータブル性: 値クラスは不変(イミュータブル)であるため、一度生成されたインスタンスの値は変更されません。これにより、安全で予測可能なコードを実現します。 # 型安全性: 値クラスは型安全性を提供します。異なる値クラス間は厳密に区別され、混同されることがありません。 # 自動生成メソッド: 値クラスは <code>equals()</code> や <code>hashCode()</code> などのメソッドを自動生成します。これにより、等価性の確認やコレクションの利用が容易になります。 # ボクシングの回避: 値クラスはプリミティブ型のように振る舞い、一部のボクシングを回避します。これにより、メモリ効率が向上します。 値クラスは、ドメインモデリングや特定のデータ型を表現する際に有用であり、プロジェクト全体でのコードの理解性や保守性を向上させる役割を果たします。 === オブジェクト === オブジェクト(<code>object</code>)は、モディファイア・キーワードではありませんが、特殊なクラスの一種であり、一過的な匿名クラスを定義し、その唯一のインスタンスを生成します。オブジェクトはシングルトンのような振る舞いを持ち、一般的には特定の目的に使用されます。 ==== オブジェクトの宣言 ==== <syntaxhighlight lang=kotlin copy> object Logger { fun log(message: String) { println("Log: $message") } } </syntaxhighlight> 上記の例では、<code>Logger</code> という名前のオブジェクトが宣言されています。このオブジェクトはシングルトンであり、<code>log</code> メソッドを持っています。 ==== オブジェクトの利用 ==== <syntaxhighlight lang=kotlin copy> fun main() { Logger.log("This is a log message.") } </syntaxhighlight> 上記の例では、<code>Logger</code> オブジェクトの唯一のインスタンスにアクセスし、その <code>log</code> メソッドを呼び出しています。オブジェクトは初回のアクセス時に遅延初期化され、以降は同じインスタンスが再利用されます。 ==== オブジェクトの特徴 ==== # シングルトンパターン: オブジェクトはシングルトンとして振る舞います。クラスの唯一のインスタンスを持ち、それにアクセスするために新たなインスタンスを生成することはありません。 # 遅延初期化: オブジェクトは初回のアクセス時に初期化されます。これにより、プログラムが実際に必要なときに初期化処理が行われます。 # クラスメンバー: オブジェクトはメソッドやプロパティを持つことができます。これらは通常のクラスメンバーと同じようにアクセスできます。 # 継承不可: オブジェクトは継承できません。そのため、他のクラスがこのオブジェクトを継承することはできません。 オブジェクトは特定のタスクや目的に対して唯一のインスタンスを提供する場合に利用され、例えばロギングや設定の管理などに適しています。 == ジェネリックス == {{先頭に戻る}} ジェネリックス( ''Generics'' )とは、汎用的なクラス・関数やメソッドを特定の型に対応づける機能のことです<ref>[https://kotlinlang.org/docs/generics.html Generics: in, out, where]</ref>。 == キーワード一覧 == {{先頭に戻る}} Kotlinの{{Anchor|キーワード}}( ''Keywords'' )は * [[#ハード・キーワード|ハード・キーワード]] * [[#ソフト・キーワード|ソフト・キーワード]] * [[#モディファイア・キーワード|モディファイア・キーワード]] * [[#特殊識別子|特殊識別子]] * [[#演算子と特殊シンボル|演算子と特殊シンボル]] に分類されます<ref>[https://kotlinlang.org/docs/keyword-reference.html Keywords and operators]</ref>。 === ハード・キーワード === {{先頭に戻る|style=border-top:1px solid gray;}} 以下のトークンは、常にキーワードとして解釈され、識別子として使用することはできません<ref>[https://kotlinlang.org/docs/keyword-reference.html#hard-keywords Hard keywords]</ref>。 このようなキーワードをハード・キーワード( ''Hard keywords'' )と呼びます。 * <code>[[#as|as]]</code> *# 型キャスト( ''type casts'' )に使用されます。 *# インポートの別名の指定に使用されます。 * <code>[[#as?|as?]]</code> 安全なタイプキャスト( ''safe type casts'' )に使用されます。 * <code>[[#break|break]]</code> ループの実行を終了させます。 * <code>[[#class|class]]</code> クラスを宣言します。 * <code>[[#continue|continue]]</code> 最も近いループの次のステップに進みます。 * <code>[[#do|do]]</code> do/whileループ(条件式を後置するつループ)を開始します。 * <code>[[#else|else]]</code> 条件が偽のときに実行されるif式の分岐を定義します。 * <code>[[#false|false]]</code> Boolean型の「偽」の値を表します。 * <code>[[#for|for]]</code> forループを開始します。 * <code>[[#fun|fun]]</code> 関数を宣言します。 * <code>[[#if|if]]</code> if式の先頭です。 * <code>[[#in|in]]</code> *# forループで反復されるオブジェクトを指定します。 *# 値が範囲、コレクション、または「contains」メソッドを定義している他のエンティティに属しているかどうかを確認するための中置演算子として使用されます。 *# 同じ目的のためにwhen式で使用されます。 *# 型パラメータをcontravariantとしてマークします。 * <code>[[#!in|!in]]</code> *# 値が範囲、コレクション、または 'contains' メソッドを定義する他のエンティティに'''属さない'''ことを確認する演算子として使用されます。 *# 同じ目的のためにwhen式で使用されます。 *: <code>!in</code>で1つのトークンなので、! と in の間に空白を挟むことはできません。 * <code>[[#interface|interface]]</code> インターフェース( ''interfaces'' )を宣言します。 * <code>[[#is|is]]</code> *# 値が特定の型を持つかどうかをチェックします。 *# 同じ目的のwhen式で使用されます。 * <code>[[#!is|!is]]</code> *# 値が特定の型を持って'''いない'''かどうかをチェックします。 *# 同じ目的のwhen式で使用されます。 *: <code>!is</code>で1つのトークンなので、! と is の間に空白を挟むことはできません。 * <code>[[#null|null]]</code> どのオブジェクトも指していないオブジェクト参照を表す定数です。 * <code>[[#object|object]]</code> クラスとそのインスタンスを同時に宣言します。 * <code>[[#package|package]]</code> 現在のファイルのパッケージを指定します。 * <code>[[#return|return]]</code> 最も近い包含関数または無名関数からの呼出し元に戻ります。 * <code>[[#super|super]]</code> *# メソッドやプロパティのスーパークラス実装を参照します。 *# 二次コンストラクタ( ''secondary constructor'' )からスーパークラスのコンストラクタを呼び出します。 * <code>[[#this|this]]</code> *# 現在のレシーバを指します。 *# 2 次コンストラクタから同じクラスの別のコンストラクタを呼び出します。 * <code>[[#throw|throw]]</code> 例外を投げます。 * <code>[[#true|true]]</code> Boolean型の「真」の値を表します。 * <code>[[#try|try]]</code> 例外処理ブロックを開始します。 * <code>[[#typealias|typealias]]</code> 型の別名を宣言します。 * <code>[[#typeof|typeof]]</code> 将来の使用のために予約されています。 * <code>[[#val|val]]</code> 読取り専用のプロパティまたはローカル変数を宣言します。 * <code>[[#var|var]]</code> 変更可能なプロパティまたはローカル変数を宣言します。 * <code>[[#when|when]]</code> when式を開始します(与えられた分岐のうち1つを実行します)。 * <code>[[#while|while]]</code> while ループ(条件式を前置するループ)を開始します。 === ソフト・キーワード === {{先頭に戻る|style=border-top:1px solid gray;}} 以下のトークンは、それが適用される文脈( ''context'' )ではキーワードとして機能し、他の文脈では[[#識別子|識別子]]として使用することができます<ref>[https://kotlinlang.org/docs/keyword-reference.html#soft-keywords Soft keywords]</ref>。 このようなキーワードをソフト・キーワード( ''Soft keywords'' )と呼びます。 * <code>[[#by|by]]</code> *# インターフェース( ''interface'' )の実装( ''implementation'' )を別のオブジェクトに委譲( ''delegates'' )します。 *# プロパティーのアクセッサー( ''accessors'' )の実装を別のオブジェクトに委譲します。 * <code>[[#catch|catch]]</code> 特定の例外タイプ( ''specific exception type'' )を処理( ''handles'' )するブロックを開始します。 * <code>[[#constructor|constructor]]</code> 一次または二次コンストラクタを宣言します。 * <code>[[#delegate|delegate]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>( ''annotation use-site target'' )として使用されます。 * <code>[[#dynamic|dynamic]]</code> Kotlin/JS コードで動的な型を参照します。 * <code>[[#field|field]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#file|file]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#finally|finally]]</code> tryブロックが終了したときに必ず実行されるブロックを開始します。 * <code>[[#get|get]]</code> *# プロパティのゲッター( ''getter'' )を宣言します。 *# [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#import|import]]</code> 他のパッケージから現在のファイルに宣言をインポートします。 * <code>[[#init|init]]</code> イニシャライザーブロックを開始します。 * <code>[[#param|param]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#property|property]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#receiver|receiver]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#set|set]]</code> *# プロパティのセッター( ''setter'' )を宣言します。 *# [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#setparam|setparam]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#value|value]]</code> キーワード <code>class</code> を付けてインラインクラス( ''inline class'' )を宣言します。 * <code>[[#where|where]]</code> 汎用型パラメーター( ''a generic type parameter'' )の制約( ''constraints'' )を指定します。 ==== アノテーション使用側ターゲット ==== アノテーション使用側ターゲット( ''Annotation use-site target'' )は、Kotlinにおいてアノテーションが特定の要素に対して適用される位置を指定する構文です。これにより、生成されるJavaバイトコードにおいてアノテーションがどの要素に適用されるかを正確に指定できます<ref>[https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets Annotation use-site targets]</ref>。 ==== アノテーション使用側ターゲットの指定 ==== 以下は、一般的なアノテーション使用側ターゲットの指定方法です。 # プロパティにアノテーションを指定する場合: #:<syntaxhighlight lang=kotlin copy> class Example { @get:MyAnnotation val myProperty: Int = 42 } </syntaxhighlight> #:この例では、<code>@get:MyAnnotation</code> と指定することで、プロパティのgetterメソッドに対してアノテーションを指定しています。 # 1次コンストラクタのパラメータにアノテーションを指定する場合: #:<syntaxhighlight lang=kotlin copy> class Example(@param:MyAnnotation val value: String) </syntaxhighlight> #:この例では、<code>@param:MyAnnotation</code> と指定することで、1次コンストラクタのパラメータに対してアノテーションを指定しています。 ==== よく使われるアノテーション使用側ターゲット ==== # <code>@get</code>: プロパティのgetterメソッドに対してアノテーションを指定する。 # <code>@set</code>: プロパティのsetterメソッドに対してアノテーションを指定する。 # <code>@field</code>: プロパティ自体に対してアノテーションを指定する。 これらの使用側ターゲットを使うことで、アノテーションが生成される場所を明確に指定することができ、柔軟性を保ちつつ、正確な挙動を得ることができます。 === モディファイア・キーワード === {{先頭に戻る|style=border-top:1px solid gray;}} 以下のトークンは、宣言の修飾語リスト( ''modifier lists of declarations'' )のキーワードとして機能し、他のコンテキストでは識別子として使用することができます<ref>[https://kotlinlang.org/docs/keyword-reference.html#modifier-keywords Modifier keywords]</ref>。 このようなキーワードをモディファイア・キーワード( ''Modifier keywords'' )と呼びます。 * <code>[[#abstract|abstract]]</code> クラスやメンバが抽象的( ''as abstract'' )であることを表します。 * <code>[[#actual|actual]]</code> マルチプラットフォーム・プロジェクト( ''multiplatform projects'' )におけるプラットフォーム固有の実装( ''platform-specific implementation'' )を意味します。 * <code>[[#annotation|annotation]]</code> アノテーションクラス( ''an annotation class'' )を宣言します。 * <code>[[#companion|companion]]</code> コンパニオンオブジェクト( ''a companion object'' )を宣言します。 * <code>[[#const|const]]</code> プロパティをコンパイル時の定数( ''a compile-time constant'' )としてマークします。 * <code>[[#crossinline|crossinline]]</code> インライン関数に渡されるラムダで、ローカルでない返り値を禁止します。 * <code>[[#data|data]]</code> クラスの正規メンバー( ''canonical members'' )を生成するようにコンパイラーに指示します。 * <code>[[#enum|enum]]</code> 列挙型( ''an enumeration'' )を宣言します。 * <code>[[#expect|expect]]</code> 宣言がプラットフォーム固有( ''as platform-specific'' )のものであり、プラットフォーム・モジュール(platform modules )で実装されることを期待するものとしてマークします。 * <code>[[#external|external]]</code> Kotlin の外部で実装される宣言であることを示します(JNI または JavaScript でアクセス可能)。 * <code>[[#final|final]]</code> メンバーのオーバーライドを禁止します。 * <code>[[#infix|infix]]</code> 中置記法( ''infix notation'' )で関数を呼び出すことを許可します。 * <code>[[#inline|inline]]</code> 関数とその関数に渡されたラムダを呼出し先でインライン化することをコンパイラに指示します。 * <code>[[#inner|inner]]</code> ネストされたクラスから外側のクラスのインスタンスを参照できるようにします。 * <code>[[#internal|internal]]</code> 現在のモジュールで可視( ''as visible'' )となる宣言をマークします。 * <code>[[#lateinit|lateinit]]</code> コンストラクターの外部で非 null プロパティを初期化します。 * <code>[[#noinline|noinline]]</code> インライン関数に渡されたラムダをインライン化しないようにします。 * <code>[[#open|open]]</code> クラスのサブクラス化またはメンバーのオーバーライドを許可します。 * <code>[[#operator|operator]]</code> 関数が演算子をオーバーロードしているか、または規約を実装( ''implementing a convention'' )しているかをマークします。 * <code>[[#out|out]]</code> 型パラメータを共変( ''covariant'' )としてマークします。 * <code>[[#override|override]]</code> スーパークラスのメンバーのオーバーライドとしてメンバーにマークを付けます。 * <code>[[#private|private]]</code> 現在のクラスまたはファイル内で宣言が可視化( as visible )されるようにマークします。 * <code>[[#protected|protected]]</code> 現在のクラスとそのサブクラスで宣言が可視化されるようにマークします。 * <code>[[#public|public]]</code> 宣言がどこでも可視化されるようにマークします。 * <code>[[#reified|reified]]</code> インライン関数の型パラメーター( ''type parameter'' )を、実行時にアクセス可能なものとしてマークします。 * <code>[[#sealed|sealed]]</code> シールされたクラス( ''sealed class'' ; サブクラス化が制限されたクラス)を宣言します。 * <code>[[#suspend|suspend]]</code> 関数やラムダをサスペンド(コルーチンとして使用可能)するようにマークします。 * <code>[[#tailrec|tailrec]]</code> 関数を末尾再帰としてマークします (コンパイラーが再帰を反復に置換えることができます)。 * <code>[[#vararg|vararg]]</code> パラメーターに可変数の引数を渡せるようにします。 === 特殊識別子 === {{先頭に戻る|style=border-top:1px solid gray;}} 以下の識別子は,コンパイラーが特定の文脈で定義したもので、他の文脈では通常の識別子として使用することができます<ref>[https://kotlinlang.org/docs/keyword-reference.html#special-identifiers Special identifiers]</ref>。 このような識別子を特殊識別子( ''Special identifiers'' )と呼びます。 * <code>[[#field|field]]</code> プロパティーアクセサー( ''a property accessor'' )の内部で、プロパティーのバッキングフィールドを参照するために使用します。 * <code>[[#it|it]]</code> ラムダの内部で暗黙のうちにパラメーターを参照するために使用されます。 === 演算子と特殊シンボル === {{先頭に戻る|style=border-top:1px solid gray;}} Kotlinは以下の演算子( ''Operators'' )や特殊特殊シンボル( ''special symbols'' )をサポートしています<ref>[https://kotlinlang.org/docs/keyword-reference.html#operators-and-special-symbols Operators and special symbols]</ref>。 * <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, <code>%</code> {{---}} 算術演算子 *# <code>*</code> は、vararg パラメーターに配列を渡す場合にも使用されます。 * <code>=</code> *# 代入演算子 *# パラメーターのデフォルト値を指定するために使用されます。 * <code>+=</code>, <code>-=</code>, <code>*=</code>, <code>/=</code>, <code>%=</code> {{---}} 拡張された代入演算子。 * <code>++</code>, <code>--</code> {{---}} インクリメントおよびデクリメント演算子 * <code>&&</code>, <code>||</code>, <code>!</code> {{---}} 論理 'and', 'or', 'not' 演算子 (ビット演算には、対応する infix 関数を使用してください)。 * <code>==</code>, <code>!=</code> {{---}} 等号演算子 (非プリミティブ型では equals() に変換される)。 * <code>===</code>, <code>!==</code> {{---}} 参照系等号演算子( ''referential equality operators'' ) * <code><</code>, <code>></code>, <code><=</code>, <code>>=</code> {{---}} 比較演算子 (非プリミティブ型に対する compareTo() の呼出しに変換されます) * <code>[</code>, <code>]</code> {{---}} インデックス付きアクセス演算子(getとsetの呼び出しに変換されます) * <code>!!</code> 式が非nullであることを保証します。 * <code>?.</code> 安全な呼び出しを行います(レシーバーが非NULLの場合、メソッドを呼び出したり、プロパティにアクセスしたりします)。 * <code>?:</code> 左辺の値がNULLの場合、右辺の値を取ります(エルビス演算子)。 * <code>::</code> メンバー参照またはクラス参照を作成します。 * <code>..</code> 範囲( ''a range'' )を生成します。 * <code>:</code> 宣言の中で、名前と型を分離します。 * <code>?</code> 型をnull可能( ''as nullable'' )であるとマークします。 * <code>-></code> *# ラムダ式のパラメーターと本体を分離します。 *# 関数型のパラメーターと戻値の型宣言を分離します。 *# when式の条件分岐と本体を分離します。 * <code>@</code> *# アノテーションを導入します。 *# ループラベルを導入または参照します。 *# ラムダ・ラベルを導入または参照します。 *# 外部スコープから 'this' 式を参照します。 *# 外部のスーパークラスを参照します。 * <code>;</code> 同じ行にある複数のステートメントを区切ります。 * <code>$</code> 文字列テンプレート内で変数または式を参照します。 * <code>_</code> *# ラムダ式で使用しないパラメーターを置換えます。 *# 構造化宣言の未使用のパラメーターを代入します。 {{See also|[[#演算子の優先順位|演算子の優先順位]]}} == Kotlin標準ライブラリー == {{先頭に戻る}} Kotlin標準ライブラリー( ''Kotlin Standard Library'' )は、以下のような機能を提供します<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/ Kotlin Standard Library]</ref>。 * 慣用的なパターン(let、apply、use、synchronizedなど)を実装した高階関数。 * コレクション(eager)やシーケンス(lazy)に対するクエリ操作を提供する拡張関数。 * 文字列や文字列列を扱うための各種ユーティリティ * ファイル、IO、スレッドを便利に扱うための JDK クラスの拡張。 Kotlin標準ライブラリーはKotlin自身で書かれています。 ;[[ディフォルトインポート]]されるパッケージ * kotlin.* * [[#アノテーション|アノテーション]] * [[#コレクション|コレクション]] * [[#比較|比較]] * [[#入出力|入出力]] * [[#範囲|範囲]] * [[#シーケンス|シーケンス]] * [[#テキスト|テキスト]] === アノテーション === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.annotation.* === コレクション === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} Kotlinには、Arrayから始まり、Iterable, Collection, List, Set, Mapなどのコレクション型が豊富に用意されています。これらは主に <code>kotlin.collections</code> パッケージで提供されており、[[#ディフォルトインポート|ディフォルトインポート]]なので追加のインポートなしで利用できます<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/ Package kotlin.collections]</ref>。 :{| class=wikitable |+ 主要なパッケージとその機能の一覧 !パッケージ!!機能 |- !Iterable |要素の反復処理をサポート |- !Collection |要素のコレクションを表現 |- !List |要素数が固定で、要素の値を変更不可 |- !ArrayList |可変長の動的な配列 |- !MutableList |要素の変更が可能なリスト |- !Set |要素の重複を許さない |- !Map |キーと値のペアを保持する |- !MutableMap |要素の変更が可能なMap |- !LinkedHashSet |要素の挿入順を保持するSet |- !LinkedHashMap |要素の挿入順を保持するMap |} ==== Iterable ==== <code>Iterable</code> インターフェースは、Kotlinの標準ライブラリで使用される反復可能なコレクションの基本的なインターフェースです。このインターフェースは、コレクションが要素の反復処理を可能にするために必要な機能を提供します。 以下に、<code>Iterable</code> インターフェースの主な要素と使用法を示します: # <code>iterator()</code> メソッド: #* <code>iterator</code> メソッドは、コレクション内の要素を反復処理するためのイテレータを返します。 #* イテレータは、<code>hasNext()</code> メソッドで次の要素の有無を確認し、<code>next()</code> メソッドで次の要素を取得します。 #* 通常、<code>for</code> ループや <code>forEach</code> 関数を使用して、このメソッドを呼び出すことなくコレクションを反復処理できます。 #:<syntaxhighlight lang=kotlin copy> val iterable: Iterable<Int> = listOf(1, 2, 3, 4, 5) // for ループを使用した反復処理 for (element in iterable) { println(element) } // forEach 関数を使用した反復処理 iterable.forEach { element -> println(element) } </syntaxhighlight> # <code>forEach</code> 拡張関数: #* <code>Iterable</code> インターフェースには、<code>forEach</code> という拡張関数があります。これはラムダ式を使用して各要素に対する処理を行います。 #:<syntaxhighlight lang=kotlin copy> val iterable: Iterable<Int> = listOf(1, 2, 3, 4, 5) // forEach 関数を使用した反復処理 iterable.forEach { element -> println(element) } </syntaxhighlight> #使用例: #* <code>Iterable</code> は多くの Kotlin のコレクションで使用されます。例えば、<code>List</code>、<code>Set</code>、<code>Map</code> などが <code>Iterable</code> インターフェースを実装しています。 #* <code>Iterable</code> を実装することで、コレクションが要素の反復処理をサポートし、<code>for</code> ループや <code>forEach</code> 関数などで簡単に使用できます。 #:<syntaxhighlight lang=kotlin copy> // List は Iterable インターフェースを実装している val list: Iterable<Int> = listOf(1, 2, 3, 4, 5) // for ループを使用した反復処理 for (element in list) { println(element) } </syntaxhighlight> <code>Iterable</code> インターフェースは、Kotlinでコレクションを扱う際に非常に重要であり、様々な反復処理操作を可能にします。 ==== Collection ==== <code>Collection</code> インターフェースは、Kotlinの標準ライブラリで提供されるコレクション型の基本インターフェースの一つです。このインターフェースは、複数の要素を保持するデータ構造を表現し、それらの要素に対する基本的な操作を提供します。 以下に、<code>Collection</code> インターフェースの主な特徴と使用法を示します: # 要素の追加と削除: #* <code>Collection</code> インターフェースは、要素の追加や削除といった基本的な操作を提供します。 #* <code>add(element: E)</code> メソッドを使用して要素を追加し、<code>remove(element: E)</code> メソッドを使用して指定した要素を削除します。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // 要素の追加はサポートされない // collection.add(6) // エラー // 要素の削除 val modifiedCollection = collection - 3 println(modifiedCollection) // [1, 2, 4, 5] </syntaxhighlight> # 要素の存在確認: #* <code>contains(element: E)</code> メソッドを使用して、指定した要素がコレクション内に存在するかどうかを確認できます。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // 要素の存在確認 val containsThree = collection.contains(3) println(containsThree) // true </syntaxhighlight> # サイズの取得: #* <code>size</code> プロパティを使用して、コレクション内の要素の総数を取得できます。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // コレクションのサイズ取得 val size = collection.size println(size) // 5 </syntaxhighlight> # 反復処理: #* <code>Iterable</code> インターフェースを継承しているため、<code>forEach</code> 関数などを使用してコレクション内の要素を反復処理できます。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // forEach 関数を使用した反復処理 collection.forEach { element -> println(element) } </syntaxhighlight> # 他のコレクションとの操作: #* <code>Collection</code> インターフェースを実装するコレクションは、他のコレクションとの操作を行うための便利な関数を提供します。例えば、和集合、差集合、共通要素などを計算できます。 #:<syntaxhighlight lang=kotlin copy> val collection1: Collection<Int> = listOf(1, 2, 3, 4, 5) val collection2: Collection<Int> = listOf(4, 5, 6, 7, 8) // 和集合 val unionResult = collection1 union collection2 println(unionResult) // [1, 2, 3, 4, 5, 6, 7, 8] // 差集合 val subtractResult = collection1 subtract collection2 println(subtractResult) // [1, 2, 3] // 共通要素 val intersectResult = collection1 intersect collection2 println(intersectResult) // [4, 5] </syntaxhighlight> <code>Collection</code> インターフェースは、Kotlinのコレクションの基本的な機能を提供し、様々な種類のコレクションがこれを実装しています。これにより、異なる種類のコレクションを一貫して扱うことができます。 ==== List ==== Listは、要素数が固定で要素の値を変更できないコレクションです。 ===== List() ===== ;[https://paiza.io/projects/vmrFKnU_3qj5d04hJPmuWA?language=kotlin List()を使ったListの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val list = List(5){it} println("list::class.simpleName ⇒ ${list::class.simpleName}") println("list[0]::class.simpleName ⇒ ${list[0]::class.simpleName}") list.forEach{print("$it ")} println("") val list2 = List(5){(it*it).toString()} println("list2[0]::class.simpleName ⇒ ${list2[0]::class.simpleName}") list2.forEach{print("$it ")} println("") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> list::class.simpleName ⇒ ArrayList list[0]::class.simpleName ⇒ Int 0 1 2 3 4 list2[0]::class.simpleName ⇒ String 0 1 4 9 16 </syntaxhighlight> : List()はListのコンストラクターで、引数として要素数をとり、ブロックが初期化式になります。 ===== listOf ===== ;[https://paiza.io/projects/D17B4n-k7dGdKdxlrw5m2Q?language=kotlin listOf()を使ったListの生成] :<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val list = listOf(1, 9, 3, 5, 23, 1) println("${list::class.simpleName}") println("${list[0]::class.simpleName}") for (s in list) if (s > 10) break else print("$s ") println("") run { list.forEach{ if (it > 10) return@run else print("$it ") } } println("") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ArrayList Int 1 9 3 5 1 9 3 5 </syntaxhighlight> : ListOf()は可変長引数の関数で、引数が生成されるListの要素になります。 : Listの要素の型は、型強制できる最小公倍数的な方になります(例えば Int と Long が混在していたら Long)。 ==== ArrayList ==== :<syntaxhighlight lang=Kotlin line> fun main() { // ArrayListを使ったListの生成 val arrayList = ArrayList<String>() arrayList.add("Kotlin") arrayList.add("Java") arrayList.add("Python") println("${arrayList::class.simpleName}") for (lang in arrayList) { println(lang) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ArrayList Kotlin Java Python </syntaxhighlight> 上記の例では、<code>ArrayList</code> を使ってListを生成しています。ArrayListは要素の順序が保持され、可変長の動的な配列を表現します。<code>add</code> メソッドを使用して要素を追加することができます。 ==== MutableList ==== <syntaxhighlight lang=kotlin copy> fun main() { // MutableListを使ったListの生成 val mutableList = mutableListOf(1, 2, 3, 4, 5) mutableList.add(6) println("${mutableList::class.simpleName}") for (num in mutableList) { print("$num ") } println("") } </syntaxhighlight> ;実行結果 :<syntaxhighlight lang=text> ArrayList 1 2 3 4 5 6 </syntaxhighlight> <code>mutableListOf()</code> を使って <code>MutableList</code> を生成し、<code>add</code> メソッドを使用して要素を追加しています。MutableListは要素の変更が可能なListです。 これらの例から分かるように、Kotlinのコレクションは型安全で、読み取り専用と可変なコレクションの違いが明確になっています。リストの他にも、SetやMapも用意されており、それぞれの特徴に応じて適切なものを選択できます。 ==== ユースケース ==== <code>kotlin.collections</code> パッケージのコレクションクラスや関連機能は、さまざまなプログラミングシナリオで利用されます。以下は、<code>kotlin.collections</code> の主なユースケースのいくつかです: # データの格納と操作: List、Set、Mapなどのコレクションは、データを効果的に格納し、操作するために使用されます。例えば、リストは順序つきのデータの集合を表現し、セットは一意な要素の集合を表現します。 # 反復処理とフィルタリング: Iterable インターフェースを使用してコレクションを反復処理し、必要なデータを抽出することができます。これは、フィルタリングや変換などの操作に役立ちます。 # 不変性と可変性の管理: List と MutableList、Set と MutableSet、Map と MutableMap など、各コレクションには不変なバージョンと可変なバージョンがあります。これにより、不変性を保ちながら必要に応じてデータを変更できます。 # 関数型プログラミング: コレクション操作には関数型プログラミングのアプローチがあり、<code>filter</code>、<code>map</code>、<code>reduce</code> などの関数を使用してデータを処理できます。 以下は、これらのユースケースの簡単な例です: <syntaxhighlight lang=kotlin copy> // データの格納と操作 val list = listOf(1, 2, 3, 4, 5) val set = setOf(1, 2, 3, 4, 5) val map = mapOf(1 to "one", 2 to "two", 3 to "three") // 反復処理とフィルタリング val filteredList = list.filter { it > 2 } // 不変性と可変性の管理 val mutableList = mutableListOf(1, 2, 3) mutableList.add(4) // 関数型プログラミング val squaredValues = list.map { it * it } val sum = list.reduce { acc, value -> acc + value } </syntaxhighlight> これらの例は一部の機能を示すものであり、<code>kotlin.collections</code> のコレクションは、さまざまなプログラミングニーズに対応する強力なツールセットを提供します。 ==== ベストプラクティス ==== <code>kotlin.collections</code> を使用する際のベストプラクティスはいくつかあります。以下にいくつか挙げてみましょう: # 不変性の推奨: 不変なコレクション(<code>List</code>、<code>Set</code>、<code>Map</code>など)を使用することを検討してください。不変なコレクションは変更不可能でスレッドセーフであり、プログラムの安全性を向上させるのに役立ちます。 #:<syntaxhighlight lang=kotlin copy> // 不変なリスト val immutableList = listOf(1, 2, 3) // 不変なセット val immutableSet = setOf("apple", "orange", "banana") // 不変なマップ val immutableMap = mapOf(1 to "one", 2 to "two", 3 to "three") </syntaxhighlight> # Nullableなコレクションの適切な扱い: コレクション内の要素が <code>null</code> になりうる場合、Nullableなコレクション(<code>List?</code>、<code>Set?</code>、<code>Map?</code>など)を使用して適切にハンドリングしましょう。 #:<syntaxhighlight lang=kotlin copy> // Nullableなリスト val nullableList: List<Int>? = // ... // Nullableなセット val nullableSet: Set<String>? = // ... // Nullableなマップ val nullableMap: Map<Int, String>? = // ... </syntaxhighlight> # 関数型プログラミングの活用: <code>filter</code>、<code>map</code>、<code>reduce</code>、<code>fold</code> などの関数型プログラミングの機能を活用して、コードを簡潔で読みやすくしましょう。 #:<syntaxhighlight lang=kotlin copy> val numbers = listOf(1, 2, 3, 4, 5) val evenSquared = numbers .filter { it % 2 == 0 } .map { it * it } .sum() </syntaxhighlight> # 適切なコレクションの選択: 使用ケースによって適切なコレクションを選択しましょう。例えば、要素の順序が重要な場合は <code>List</code>、一意性が必要な場合は <code>Set</code>、キーと値のペアが必要な場合は <code>Map</code> を使用します。 #:<syntaxhighlight lang=kotlin copy> // 要素の順序が重要 val orderedList = listOf(1, 2, 3, 4, 5) // 一意性が必要 val uniqueSet = setOf("apple", "orange", "banana") // キーと値のペアが必要 val keyValueMap = mapOf(1 to "one", 2 to "two", 3 to "three") </syntaxhighlight> これらのベストプラクティスは、コードの品質、パフォーマンス、保守性を向上させるのに役立ちます。使用ケースによって最適なアプローチを選択することが重要です。 === 比較 === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.comparisons.* === 入出力 === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.io.* === 範囲 === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.ranges.* === シーケンス === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.sequences.* === テキスト === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.text.* ---- === コレクション類似クラス === {{先頭に戻る}} [TODO:Rangeはコレクションではないので再分類が必要] <code>println((1..5).javaClass.kotlin)</code>の結果が示す通り、範囲リテラル<code>1..5</code>は<code>class kotlin.ranges.IntRange</code>です。 コレクションは、Ranges以外にも、Sequences・Ranges・Lists・Arrays・Sets・Mapsなどがあります。これは網羅していませんし、上記の forプロトコルに従ったクラスを作れば、ユーザー定義のコレクションも作成できます。 ;[https://paiza.io/projects/zw6faeOmsjuZVF3D3WY_-g?language=kotlin 様々なコレクション]:<syntaxhighlight lang="Kotlin"> fun main(args: Array<String>) { val collections = arrayOf( 1..5, 1..8 step 2, 5 downTo 1, 8 downTo 1 step 2, 'A'..'Z', listOf(2,3,5), setOf(7,11,13)) println("$collections(${collections.javaClass.kotlin})") for (collection in collections) { print(collection) print(": ") for (x in collection) { print(x) print(" ") } print(": ") println(collection.javaClass.kotlin) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> class kotlin.Array 1..5: 1 2 3 4 5 : class kotlin.ranges.IntRange 1..7 step 2: 1 3 5 7 : class kotlin.ranges.IntProgression 5 downTo 1 step 1: 5 4 3 2 1 : class kotlin.ranges.IntProgression 8 downTo 2 step 2: 8 6 4 2 : class kotlin.ranges.IntProgression A..Z: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z : class kotlin.ranges.CharRange [2, 3, 5]: 2 3 5 : class java.util.Arrays$ArrayList [7, 11, 13]: 7 11 13 : class java.util.LinkedHashSet </syntaxhighlight> : 二重のforループで、外周はコレクションのコレクションで、内周は個々のコレクションの要素をイテレーションしています。 === スコープ関数 === {{先頭に戻る|style=border-top:1px solid gray;}} ==== repeat関数 ==== Kotlinの標準ライブラリーにあるrepeat関数は、定数回の繰返しが必要な時に便利です<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html repeat - Kotlin Programming Language]</ref>。 ;[https://paiza.io/projects/LHnnORcAjUhvb_qW9ysIvw?language=kotlin repeat関数]:<syntaxhighlight lang="kotlin"> fun main() { repeat(5) { println("it = $it") } run { repeat(3) { i -> repeat(4) { j -> println("(i, j) = ($i, $j)") if (i == 1 && j == 2) { return@run } } } } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> it = 0 it = 1 it = 2 it = 3 it = 4 (i, j) = (0, 0) (i, j) = (0, 1) (i, j) = (0, 2) (i, j) = (0, 3) (i, j) = (1, 0) (i, j) = (1, 1) (i, j) = (1, 2) </syntaxhighlight> :<var>it</var>は、暗黙のループ変数です。 :多重ループでは、ループ変数の名前が固定では都合が悪いので、ブロックの先頭で<code>識別子名 -></code> とすることで明示的に名前をつけることができます。 :多重ループを run 関数で括ることで多重ループからの大域脱出を実現しています。 ==== ブロックを受取る関数 ==== repeat関数もそうですが、Kotlinにはブロックを受取る関数(やメソッド)があります。 ;[https://paiza.io/projects/AZT2juUGcUnyjqgDx4G85g?language=kotlin ブロックを受取る関数]:<syntaxhighlight lang="kotlin"> fun main(args: Array<String>) { val ary = Array(5) { 2 * it + 1 } ary.forEach{ println(it) } println(ary.map{ it.toString() }.joinToString(" ")) println(ary.reduce{ sum, el -> sum + el }) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 1 3 5 7 9 1 3 5 7 9 25 </syntaxhighlight> :ブロックで配列の初期化を行う場合、<var>it</var>は順位になります。 :コレクションのforEachメソッドもブロックを取ります。 :コレクションのreduceメソッドもブロックを取りますが、累算値と要素の2つを取るので、名付けが必要です。 このように、ブロックを取るメソッドを使うとコレクションに関する操作を簡素に書けます。 == Coroutine == {{先頭に戻る}} Kotlinは、言語レベルでコルーチンをサポートし、機能の大部分をライブラリに委ねることで、この問題を柔軟に解決しています。 ;Shell:<syntaxhighlight lang=console> $ cat coroutine.kt import kotlinx.coroutines.* fun main() = runBlocking { launch { delay(500L) for (ch in "World!\n") { print(ch) delay(100L) } } print("Hello ") } $ locate /kotlinx-coroutines /usr/local/share/kotlin/lib/kotlinx-coroutines-core-jvm.jar $ kotlinc -cp /usr/local/share/kotlin/lib/kotlinx-coroutines-core-jvm.jar coroutine.kt -include-runtime -d coroutine.jar $ java -cp ./coroutine.jar:/usr/local/share/kotlin/lib/kotlinx-coroutines-core-jvm.jar CoroutineKt Hello World! </syntaxhighlight> == Kotlin Script == {{先頭に戻る}} Kotlin Script では、.jar を生成せず、そのままコードが実行されます。 また、main 関数をエントリーポイントはぜず、スクリプトの書かれた順に評価します。 ;Shell:<syntaxhighlight lang=console> % cat hello.kts println("Hello, World!") % kotlinc -script hello.kts Hello, World! % _ </syntaxhighlight> ビルドツールの Gradle では、従来は Groovy がビルド構成ファイルに使われていましたが、Kotlin Script への移行が進んでいます。 ;ワンライナー:<syntaxhighlight lang=console> % kotlin -e 'repeat(3){println("Hello!($it)")}' Hello!(0) Hello!(1) Hello!(2) % _ </syntaxhighlight> == 改廃された技術 == Kotlinの改廃された技術や利用が推奨されない技術は、言語やエコシステムの進化、新しい要求、セキュリティ上の懸念などにより置き換えられます。以下に、代表的な技術を示します。 === Kotlin Android Extensions === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2021年(Kotlin 1.6.20で非推奨化) ; 廃止または衰退の理由 : View BindingやJetpack Composeなど、より安全で効率的なUI開発ツールが普及したため、利用が非推奨化されました。 ; 代替技術 : View BindingやJetpack Composeを使用することが推奨されます。 === Synthetic Properties for Views === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2021年(非推奨化) ; 廃止または衰退の理由 : Null安全性やビルドプロセスの問題から、公式に非推奨となりました。 ; 代替技術 : View Bindingを使用することで、同様の機能を安全に実現できます。 === Kotlin Scripting旧形式 (kotlin.script.experimental) === * '''対象:''' kotlin.script.experimental APIの旧バージョン ; 利用推奨されない理由 : 新しいAPI(kotlin.script.experimental.jvmなど)がより柔軟で強力であるため、旧形式は非推奨となりました。 ; 代替技術 : 最新のKotlin Scripting APIを使用してください。 === Kotlin Coroutinesの旧形式 === * '''対象:''' kotlinx.coroutinesの旧バージョン(0.x系) ; 利用推奨されない理由 : 古いバージョンではAPIが安定しておらず、最新の1.x系バージョンでは大幅な改善と安定化が図られています。 ; 推奨バージョン : 最新の1.x系またはそれ以降を使用してください。 === Experimental API === * '''対象:''' <code>@Experimental</code>や<code>@UseExperimental</code>アノテーションでラベル付けされたAPI ; 利用推奨されない理由 : 将来のリリースで仕様変更や削除が行われる可能性があるため、慎重に利用する必要があります。 ; 代替技術 : 安定版APIがリリースされた場合、それに切り替えることが推奨されます。 === Kotlin/NativeのC Interop旧形式 === * '''対象:''' Kotlin/NativeにおけるC Interopの旧形式 ; 利用推奨されない理由 : 最新のKotlin/NativeバージョンでInteropが改善され、旧形式は非推奨となりました。 ; 代替技術 : 最新のC Interop形式や公式ドキュメントに基づいた方法を使用してください。 === Kotlin Multiplatform Pluginの旧形式 === * '''対象:''' Kotlin Multiplatform Pluginの旧バージョン ; 利用推奨されない理由 : 最新バージョンではモジュール分割や依存関係管理の改善が行われ、旧バージョンの利用は推奨されなくなりました。 ; 代替技術 : 最新のKotlin Multiplatform Pluginを利用してください。 === Java 6および7向けのサポート === * '''サポート開始年:''' 2011年(初期Kotlin) * '''サポート終了年:''' 2020年(Kotlin 1.6以降で非推奨化) ; 廃止または衰退の理由 : 古いJavaバージョンの市場シェアが低下したため、KotlinチームはJava 8以降に焦点を当てています。 ; 代替技術 : Java 8以降を対象にKotlinを使用することが推奨されます。 == 脚註 == <references /> == 外部リンク == * [https://kotlinlang.org/ Kotlin Programming Language] - 公式サイト ** [https://kotlinlang.org/spec/introduction.html Kotlin language specification] ** [https://play.kotlinlang.org/ Kotlin Playground: Edit, Run, Share Kotlin Code Online] [[Category:Kotlin|*]] [[Category:プログラミング言語]] {{NDC|007.64}} tcubbhwfph9iv7uar7vsc4ihodri030 263777 263776 2024-11-18T10:28:46Z Ef3 694 Fix markup 263777 wikitext text/x-wiki {{Pathnav|メインページ|工学|情報技術|プログラミング}} ---- {{Wikipedia}} <div style="width: fit-content;float:left; margin: 0 2rem 0 0">__TOC__</div> '''Kotlin'''は、[[w:JetBrains|JetBrains]]社によって開発された静的型付けされたオブジェクト指向のプログラミング言語で、[[W:Java仮想マシン|Java仮想マシン]](JVM)上で動作します。[[JavaScript]]や、[[W:LLVM|LLVMフレームワーク]]を介して多くのプラットフォームで実行可能なコードにもコンパイルできます。 また、Kotlin/Wasmは、Kotlinの新しいコンパイルターゲットであり、WebAssemblyをサポートする環境やデバイス上で実行可能なアプリケーションを作成することができます。これにより、Kotlinの強力な機能と柔軟性を活用して、Webアプリケーションやクライアントサイドのプログラミングにも取り組むことができます。 Kotlinは[[Java]]よりも簡潔で型安全性が高く、[[Scala]]よりもシンプルな言語を目指して開発されました。Scalaと比較して、簡略化された結果、コンパイルが高速化され、IDEでの言語サポートも充実しています。また、KotlinはJavaと完全な互換性があり、Java開発者は徐々に導入することができます。特に、KotlinはAndroidにも組み込まれており、既存のAndroidアプリケーションは、アプリケーション全体を書き換えることなくKotlinで新機能を実装することができます。Kotlin FoundationがKotlin™商標を守っています。 == はじめに == === 予備知識 === Kotlinは多様なプラットフォームで利用できるモダンで柔軟なプログラミング言語です。 このチュートリアルに取り組む前に、以下の予備知識が役立ちます。 ;プログラミング基礎: : 変数、制御構造(条件分岐、ループ)、関数など、プログラミングの基本的な概念を理解していることが望ましいです。これらの概念はKotlinを含む多くのプログラミング言語で共通しています。 ;オブジェクト指向プログラミング(OOP): :Kotlinはオブジェクト指向の概念を採用しており、クラス、オブジェクト、継承、ポリモーフィズムなどのOOPの基本的な理解が重要です。 ;Javaの基本知識(Kotlin/JVMの場合): :KotlinはJavaとの高い互換性を有しています。Javaの基本的な概念やJavaの標準ライブラリについての基本的な知識があると、Kotlin/JVMの理解がより深まります。 ;Web開発基礎(Kotlin/JSの場合): :Kotlin/JSはJavaScriptに変換され、Web開発に利用されます。HTMLやCSS、基本的なWeb開発の知識があると、Kotlin/JSを使用したWebアプリケーションの開発がスムーズに進みます。 ;ネイティブ開発基礎(Kotlin/Nativeの場合): :Kotlin/Nativeはネイティブな実行コードを生成し、組み込みシステムやiOSアプリケーションなどで利用されます。ネイティブ開発の基本的な知識があると、Kotlin/Nativeを活用した開発がしやすくなります。 以上の予備知識を持っていると、Kotlinをより効果的に学習し、異なるプラットフォームでの利用に対応することができます。各プラットフォームにおけるKotlinの特徴や最適な利用法を理解することで、幅広い開発環境で柔軟かつ効率的なプログラミングが可能になります。 ==== プログラミング経験者へ ==== Kotlinを学ぶ際に他の言語のプログラミング経験がある場合、以下のアドバイスが役立つかもしれません。 ;Java経験者へのアドバイス: :KotlinはJavaとの互換性が高いため、既存のJavaコードとの統合がスムーズに行えます。JavaのコードをKotlinに変換することも可能です。 :Kotlinの拡張関数やラムダ式など、新しい機能を積極的に試してみましょう。これにより、コードの簡潔性と可読性が向上します。 ;他の静的型付け言語経験者へのアドバイス: :Kotlinも静的型付け言語であり、型推論が強力です。しかし、null安全性や拡張関数など、他の言語にはない独自の機能にも焦点を当てて学習しましょう。 :Kotlinのコルーチンを利用して非同期処理を書くことで、他の言語での非同期コードよりもシンプルで効率的なコードを書けます。 ;関数型プログラミング経験者へのアドバイス: :Kotlinは関数型プログラミングの概念をサポートしています。ラムダ式や高階関数を駆使して、より宣言的で簡潔なコードを書く方法を探求してみてください。 :Kotlinの拡張関数やパターンマッチングを利用することで、関数型プログラミングの手法をさらに発展させることができます。 ;Android開発者へのアドバイス: :KotlinはAndroidの公式開発言語として広く採用されています。既存のJavaベースのAndroidプロジェクトでもKotlinへの移行が可能です。Android Studioとの統合を利用して、Androidアプリケーションの開発にKotlinを組み込んでみましょう。 総じて、Kotlinは他のプログラミング言語において得た経験を活かしやすい言語です。適応期間は短く、生産性を高めるために積極的に新しい機能や手法を試してみることが重要です。また、公式のドキュメントやサンプルコードを利用して、Kotlinの言語仕様やベストプラクティスに精通することもおすすめです。 ==== プログラミング未経験者へ ==== プログラミング未経験者がKotlinやプログラミング全般に取り組む際のアドバイスは以下の通りです: ;基本的なプログラミング概念の理解: :プログラミングの基本概念(変数、条件分岐、ループなど)を理解することから始めましょう。これらの基本的な概念はほぼ全てのプログラミング言語で共通しています。 ;Kotlinの特徴を理解: :KotlinがJavaとの互換性が高く、Androidアプリケーション開発で広く使われていることを知りましょう。Kotlinはコードの簡潔性や可読性を向上させるための多くの機能を提供しています。 ;オンライン教材やチュートリアルを活用: :オンライン上には多くの無料または低コストでプログラミングを学べる教材やチュートリアルがあります。これらのリソースを活用して基礎から学び、実際に手を動かしながら進めてみましょう。 ;実践を重視: :理論だけでなく、実際にコードを書いてみることが非常に重要です。小さなプログラムから始め、段階的に難易度を上げながら進めていくと良いでしょう。 ;エラーを恐れず、デバッグの練習: :プログラムでエラーが発生することはよくあることです。エラーを見つけて修正することはプログラミングの一部であり、そのプロセスを恐れずに経験してみましょう。 ;プロジェクトを通じた学習: :実際のプロジェクトに取り組むことで、プログラミングの実践的な側面を理解しやすくなります。小さなプロジェクトから始め、徐々に複雑性を増していくと良いでしょう。 ;コミュニティへの参加: :Kotlinやプログラミングに関するコミュニティやフォーラムに参加すると、他の学習者や経験者からのアドバイスやサポートを得ることができます。質問をしてコミュニケーションをとることも大切です。 ;継続的な学習と興味を持つ: プログラミングは絶え間ない学習が求められる分野です。新しい技術やツールに興味を持ち、継続的に学び続けることでスキルを向上させることができます。 プログラミングはスキルの向上に時間がかかるものですが、継続的な努力と実践を通じて着実に成長していきます。最初は小さなステップから始め、徐々に進んでいくことが大切です。 === Hello world === {{先頭に戻る|style=border-top:1px solid gray;}} 他の多くのチュートリアルがそうであるように、 私たちもまずはKotlinの世界にあいさつすることから始めましょう。hello.ktというファイルを作り、次のように書いて保存して下さい(Kotlinのソースファイルの拡張子は .kt です)。 ;[https://pl.kotl.in/JCCTJjX4_ hello.kt]:<syntaxhighlight lang=kotlin copy> fun main() = println("Hello, World!") </syntaxhighlight> それでは、ソースプログラムをコンパイルして実行してみましょう。 :<syntaxhighlight lang="console"> % kotlinc hello.kt -include-runtime -d hello.jar % java -jar hello.jar Hello, World! % _ </syntaxhighlight> # <code>fun main()</code> : #* <code>fun</code>は関数(function)を宣言するためのキーワードです。 #* <code>main</code>はプログラムのエントリーポイントとなる特別な関数の名前です。通常、プログラムの実行が始まるところです。 # <code>=</code> : #* このイコール記号は、関数の本体が始まることを示します。Kotlinでは、単一の式の関数を記述する際に、本体とイコールを省略して1行で記述できます。 # <code>println("Hello, World!")</code> : #* <code>println</code>はコンソールに文字列を表示するための関数です。<code>("Hello, World!")</code>は引数として渡される文字列です。 #* この行全体は、関数の呼び出しとして、文字列 "Hello, World!" をコンソールに表示するものです。 これにより、この一行のコードは「<code>main</code>という関数を宣言し、その中で 'Hello, World!' という文字列をコンソールに表示する」という単純なプログラムを実現しています。Kotlinはこのようにシンプルかつ読みやすい構文を持っており、初学者にも優れた学習言語となっています。 <br style="clear:both"> === クイックツアー === Kotlinのクイックツアーでは、基本的な構文や機能に焦点を当て、簡単なコード例を通じて言語の特徴を理解していきます。 # 変数と基本的なデータ型 #:<syntaxhighlight lang=kotlin copy> fun main() { // 変数の宣言 val message: String = "Hello, Kotlin!" // 自動型推論も可能 val number = 42 // 文字列テンプレート println("$message The answer is $number") } </syntaxhighlight> # 条件分岐とループ #:<syntaxhighlight lang=kotlin copy> fun main() { val score = 75 // 条件分岐 if (score >= 80) { println("Great job!") } else if (score >= 60) { println("Good job!") } else { println("You can do better.") } // ループ for (i in 1..5) { println("Count: $i") } } </syntaxhighlight> # 関数の定義と呼び出し #:<syntaxhighlight lang=kotlin copy> fun main() { // 関数の呼び出し greet("Alice") // 関数の定義 fun greet(name: String) { println("Hello, $name!") } } </syntaxhighlight> # クラスとオブジェクト #:<syntaxhighlight lang=kotlin copy> fun main() { // クラスの定義 class Person(val name: String, val age: Int) // オブジェクトの作成 val person = Person("John", 25) // プロパティへのアクセス println("${person.name} is ${person.age} years old.") } </syntaxhighlight> # Null安全性 #:<syntaxhighlight lang=kotlin copy> fun main() { // Null許容型 var name: String? = "Bob" // 安全呼び出し演算子 val length: Int? = name?.length // Elvis演算子 val result = name ?: "Guest" println("Name length: $length") println("Result: $result") } </syntaxhighlight> # 拡張関数 #:<syntaxhighlight lang=kotlin copy> fun main() { // 拡張関数の定義 fun String.addExclamation(): String { return "$this!" } // 拡張関数の呼び出し val greeting = "Hello".addExclamation() println(greeting) } </syntaxhighlight> # コルーチン #:<syntaxhighlight lang=kotlin copy> import kotlinx.coroutines.* fun main() { // コルーチンの起動 GlobalScope.launch { delay(1000) // 1秒待つ println("World!") } println("Hello, ") // プログラムを待機して終了しないようにする Thread.sleep(2000) // 2秒待つ } </syntaxhighlight> # Kotlin DSL #:<syntaxhighlight lang=kotlin copy> data class Person(val name: String, val age: Int) fun buildPerson(block: PersonBuilder.() -> Unit): Person { val builder = PersonBuilder() builder.block() return builder.build() } class PersonBuilder { var name: String = "" var age: Int = 0 fun build(): Person { return Person(name, age) } } fun main() { val person = buildPerson { name = "Alice" age = 30 } println("Built person: $person") // => Built person: Person(name=Alice, age=30) } </syntaxhighlight> #: この例では、Kotlin DSLを使用して、特定のドメイン(ここでは<code>Person</code>オブジェクトの構築)に特化した言語拡張を行っています。 # Smart cast #: Kotlinは型の安全性を高めるためにスマートキャストを提供しています。これにより、条件分岐やインスタンスのチェック後に自動的にキャストが行われ、冗長なキャストを省略できます。 #:<syntaxhighlight lang=kotlin copy> fun processValue(value: Any) { if (value is String) { // valueはString型として扱われる println(value.length) // ここでlengthプロパティにアクセスできる } if (value is Int) { // valueはInt型として扱われる println(value * 2) // ここでvalueをIntとして使用できる } // スマートキャストを利用することで、valueがどの型であるかを明示的にキャストする必要がない } fun main() { processValue("Hello") // 出力: 5 (Stringの長さ) processValue(10) // 出力: 20 (Intを2倍にした値) } </syntaxhighlight> これらの例はKotlinの基本を紹介するものであり、より高度な概念や機能も学ぶことができます。 {{:Kotlin/インストール方法}} {{:Kotlin/実行方法}} == 特徴 == {{先頭に戻る}} ; [[W:コンパイル型言語|コンパイル型言語]] : Kotlinはコンパイラーとして実装されています。REPLやスクリプティングエンジンもあります。 :; Kotlin/JVM: 1つまたは複数のソースコードをコンパイルしてJavaバイトコードを生成し、生成したJavaバイトコードを実行します。 :; Kotlin/JS: 1つまたは複数のソースコードをコンパイルしてJavaScriptを生成し、生成したJavaScriptを実行します。 :; Kotlin/Native: 1つまたは複数のソースコードをコンパイルしてLLVMインフラストラクチャーをバックエンドに実行形式を生成し、生成した実行形式を実行します。 :; Kotlin/Wasm: 1つまたは複数のソースコードをコンパイルしてWebAssembly(Wasm)バイナリを生成し、WebAssembly仮想マシン上で実行します。 ; [[W:静的型付け|静的型付け]] : 値・変数・関数のパラメーター・関数の戻値などの型はコンパイル時に検証され、[[W:型安全性|型安全性]]が担保されます。 ; [[W:例外#コンピュータと例外|例外]] : try-catch-finally 形の例外処理をサポートします。 ; [[W:多重定義#演算子の多重定義|演算子オーバーロード]]: サポートします。<code>a + b</code> は、メソッド形式 <code>a.plus(b)</code> と同義です。 ; [[W:多義定義|関数オーバーロード]] : 同じ名前で引数の数が異なる関数を定義することが可能です。 ; [[#ラムダ式|ラムダ式]]: サポートします。<code>{ a: Int, b: Int -> a + b }</code> ; [[#無名関数|無名関数]]: サポートします。<code>fun(a: Int, b: int) = a + b</code> ; [[#拡張関数|拡張関数]]: 既存のクラスに新しいメソッドを生やすことができます。これは Java のクラスライブラリーのクラスも例外ではありません。 ; 宣言や定義にはキーワードを伴う: 関数定義なら <code>fun</code>、定数宣言なら <code>val</code>、変数宣言なら <code>var</code>、クラス定義なら <code>class</code> など、明示的にキーワードを使い宣言するので grep フレンドリーです。また、列挙型は <code>enum</code> ではなく、<code>enum class</code> で列挙だと知らなくても '''class''' で検索すれば見落としません。C/C++は、<code>int f(int ch){...}, int i = 9;</code>のように、よく読まないと関数定義なのか変数宣言かわからないのとは対照的です。特にC++は、<code>int a(3)</code>が関数定義なのか変数宣言なのかに曖昧さがあり、パースの時点では確定せずコンパイラーもプログラマーも悩まされます。 ; [[W:型推論|型推論]] : サポートします。 ; [[W:ガベージコレクション|ガベージコレクション]] : サポートします。 ; [[W:クラス (コンピュータ)|クラス]] : クラスベースのオブジェクト指向言語です。 :; 全てがオブジェクト : Javaで言うプリミティブもオブジェクトで、メソッドを持ちます。 :; 祖先クラス : Any :; [[#コンストラクタ|コンストラクター]] : [[#プライマリーコンストラクター|プライマリーコンストラクター]]・[[#セカンダリコンストラクター|セカンダリコンストラクター]]・[[#init|init]] の3つのメソッドがインスタンス化の機能が割振られます。 :; [[#デストラクタ|デストラクター]] : ありません。 :; [[W:継承 (プログラミング)|継承]] : 単一継承をサポートします。 :; 抽象クラス : [[Java]] や [[Go]] の interface や [[Swift]] の protocol はありませんが、abstract class があります。 ; Mix-in : サポートします。 ; [[#名前空間|名前空間]] : [[#パッケージ|パッケージ]]が名前空間を持ちます。 ; defer : ありません。 ; 分岐構造は式 : [[#if|if]], [[#when|when]]は式です。 ; 文末の<code>;</code>(セミコロン): 必要ありません。 == コード・ギャラリー == {{先頭に戻る}} === エラトステネスの篩 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} エラトステネスの篩を、若干 Kotlin らしく書いてみました。 ;[https://pl.kotl.in/YOo5wiNi3 エラトステネスの篩]:<syntaxhighlight lang=kotlin line copy> fun eratosthenes(n: Int) { var sieve = BooleanArray(n + 1){ it >= 2 } for (i in 2..<sieve.size) { if (!sieve[i]) continue; for (j in i * i until sieve.size step i) sieve[j] = false if (i * i >= sieve.size) break; } for (i in 2..<sieve.size) { if (!sieve[i]) continue; print("$i ") } } fun main() { eratosthenes(100); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 </syntaxhighlight> : 使用頻度の高い sieve は、実行効率の良いプリミティブ型配列の BooleanArray として、初期化式を it >= 2 として宣言と同時に素数候補をマークしました。 : <var>i</var> のループはオーソドックスな IntRange をコレクションにした for ですが、<var>j</var> のループは少し変則的で until は制御構造に見えますが、メソッド <code>infix Int.until(to: Int) : IntProgression</code> で、infix 修飾による中置構文です。 === 最大公約数と最小公倍数 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} 最大公約数と最小公倍数を、若干 Kotlin らしく書いてみました。 ;[https://pl.kotl.in/eumYGumM7 最大公約数と最小公倍数]:<syntaxhighlight lang=kotlin line copy> tailrec fun gcd2(a: Int, b: Int): Int = if (b == 0) a else gcd2(b, a % b) fun gcd(vararg numbers: Int): Int = numbers.reduce(::gcd2) fun lcm2(a: Int, b: Int): Int = a * b / gcd2(a, b) fun lcm(vararg numbers: Int): Int = numbers.reduce(::lcm2) fun main() { println("gcd2(30, 45) => ${gcd2(30, 45)}") println("gcd(30, 72, 12) => ${gcd(30, 72, 12)}") println("lcm2(30, 72) => ${lcm2(30, 72)}") println("lcm(30,42,72) => ${lcm(30,42,72)}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> gcd2(30, 45) => 15 gcd(30, 72, 12) => 6 lcm2(30, 72) => 360 lcm(30,42,72) => 2520 </syntaxhighlight> : 関数 gcd2() は、2つの整数の最大公約数を[[W:ユークリッドの互除法|ユークリッドの互除法]]で求めています。 :: gcd2() の修飾子 <code>tailrec</code> は、コンパイラーに末尾再帰が行なわれていることを教え、再帰をループにするヒントを与えています。 : 関数 gcd() は可変引数関数で、全ての引数に gcd2() を適用し最大公約数を返します。 : 関数 lcm2() は、2つの整数の最小公倍数を、<math>GCD(m,n) \cdot LCM(m,n)=m \cdot n</math>を利用して求めています。 : 関数 lcm() は可変引数関数で、全ての引数に lcm2 を適用し最小公倍数を返します。 それぞれの関数定義は式形式で1行なので拍子抜けですが、概念を簡素にかけていると思います。 === 二分法 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} [[W:二分法|二分法]]を、若干 Kotlin らしく書いてみました。 ;[https://paiza.io/projects/HwIg-40sBXp5GOFWFTLKMA?language=kotlin 二分法]:<syntaxhighlight lang=kotlin line copy> import kotlin.math.abs tailrec fun bisection(low_: Number, high_: Number, f: (Double) -> Double) : Double { var low = low_.toDouble() var high = high_.toDouble() val x = (low + high) / 2; val fx = f(x); if (abs(fx) < +1.0e-10) return x; if (fx < 0.0) low = x; else high = x; return bisection(low, high, f); } fun main() { println(bisection(0, 3){x : Double -> x - 1}) println(bisection(0, 3){x : Double -> x * x - 1}) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 0.9999999999417923 1.0000000000291038 </syntaxhighlight> : [[旧課程(-2012年度)高等学校数学B/数値計算とコンピューター#2分法]]の例を Kotlin に移植しました。 : 命題の式をラムダで渡すのが肝ですが、Kotrinは関数の最後パラメーターが関数型の場合括弧の外に追い出せるので :: <code>bisection(0, 3){x : Double -> x - 1}</code>のような表現ができます。 : 引数で受取った範囲を一旦varに移替えているのは、関数の引数がイミュータブルなためです。 : また、どうせローカル変数に移すならパラメータは Number 型としてIntなども受け入れるようにし、.toDouble()で型を揃えています。 : このコードはまた、<code>[[#tailrec|tailrec]]</code> の好例にもなっています。 === 複素数型 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} オーソドックスな複素数型の実装(Kotlinの標準ライブラリーには複素数型が見当たらなかったので) {{:Kotlin/Complex.kt}} === クラス定義とインスタンス化とメンバー関数 === ;[https://paiza.io/projects/9XyNAIQyFNLCewZO020A6Q?language=kotlin シンプルなクラス定義]:<syntaxhighlight lang=kotlin line highlight="1-4,7,11" copy> class Hello(val s : String = "world") { override fun toString() = "Hello $s!" fun print() = println(s) } fun main() { val hello1 = Hello() println(hello1) hello1.print() val hello2 = Hello("my friend") println(hello2); hello2.print() print( """ Hello::class.simpleName => ${Hello::class.simpleName} hello1 => $hello1 hello2.s => ${hello2.s} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello world! world Hello my friend! my friend Hello::class.simpleName => Hello hello1 => Hello world! hello2.s => my friend </syntaxhighlight> : [[Ruby#クラス]]の例を、Kotlin に移植しました。 : 冒頭4行がクラス定義です。 : クラス定義に、他のオブジェクト指向言語ならコンストラクタに渡すような引数が渡されています。 : メンバーを公開するケースなら、この様に宣言的な引数リストを使うとメンバー定義と暗黙の初期値を与えられます。 : toString は、オブジェクトを文字列化するメンバー関数で、Anyの同名のメンバー関数をオーバーライドしています。 : print は、このクラスに独自なメンバー関数で、println() の戻値型(= Unit)を戻値型としています。 === ファイルの読出し === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コード・ギャラリー}} ;[https://paiza.io/projects/C2zvgreLywbWQvIGSzHGug?language=kotlin JavaのI/Oシステムを使いファイルを読込む]:<syntaxhighlight lang=kotlin line copy> import java.nio.file.Files import java.nio.file.Paths import java.nio.charset.Charset import java.io.IOException fun main() { try { for (s in Files.readAllLines(Paths.get("/etc/hosts"), Charset.forName("UTF-8"))) { println(s) } } catch (e: IOException) { e.printStackTrace() } } </syntaxhighlight> ;[https://paiza.io/projects/cfZOI-b1YK5S36_bao5Isw?language=kotlin readText版]:<syntaxhighlight lang=kotlin line copy> import java.io.File fun main(args: Array<String>) { print(File("/etc/hosts").readText()) } </syntaxhighlight> ==チートシート == {{先頭に戻る}} ;[[#エントリーポイント|エントリーポイント]] :;コマンドライン引数を受取らない場合 ::<syntaxhighlight lang=kotlin copy> fun main() { // ... } </syntaxhighlight> :;コマンドライン引数を受取る場合 ::<syntaxhighlight lang=kotlin copy> fun main(args: Array<String>) { println(args.contentToString()) } </syntaxhighlight> ;[[#コメント|コメント]]:<syntaxhighlight lang=kotlin style="width: fit-content" copy> // Kotlinには、行末で終わるコメントと fun main() { /* * 複数行に渡ることと * /* * 入れ子にすることができる * コメントがあります */ */ println("Hello, World!") } </syntaxhighlight> ;プリミティブデータ型 :{| class=wikitable style="text-align: center" !データ型!!サイズ<hr>(ビット)!!初期値 |- |Boolean||1||false |- |Byte||8||0 |- |Short||16||0 |- |Int||32||0 |- |Long||64||0L |- |Float||32||0.0f |- |Double||64||0.0 |} ;[[#変数|変数宣言]] :;[[#val|イミュータブル]]:<syntaxhighlight lang=kotlin inline>val 識別子 : 型 = 初期化式 ;</syntaxhighlight> ::;[[#型推論|型推論版]]:<syntaxhighlight lang=kotlin inline>val 識別子 = 初期化式 ;</syntaxhighlight> :;[[#var|ミュータブル]]:<syntaxhighlight lang=kotlin inline>var 識別子 : 型 = 初期化式 ;</syntaxhighlight> ; リテラル :; 整数リテラル:<syntaxhighlight lang=kotlin inline>123, 0b11010, 0o177, 0xbadbeef</syntaxhighlight> :; 浮動小数点数リテラル:<syntaxhighlight lang=kotlin inline>3.14, 1.2e-9</syntaxhighlight> :; 文字リテラル:<syntaxhighlight lang=kotlin inline>'a', '漢', '¥t'</syntaxhighlight> :; 文字列リテラル:<syntaxhighlight lang=kotlin inline>”abc”, "了解🏝👅"</syntaxhighlight> ::; 複数行に渡る文字列リテラル ::: <syntaxhighlight lang=kotlin style="width: fit-content" copy> """ 複数行に渡る場合は この様に 3つの"(ダブルクオーテーションマーク)で囲むことで記述できます。 """ </syntaxhighlight> :; 配列の生成:<syntaxhighlight lang=kotlin inline>arrayOf(2,3,5,7), Array(5){1+it)</syntaxhighlight> ; [[#制御構造|制御構造]] :; [[#分岐|分岐]] ::; [[#if|if]] :::;else節のないif ::::<syntaxhighlight lang=zig inline>if ( 条件式 ) 式</syntaxhighlight> ::::else節のないifは、値を取ろうとするとコンパイルエラーになります。 :::;ifの値 ::::<syntaxhighlight lang=zig inline>if ( 条件式 ) 式1 else 式2</syntaxhighlight> ::::条件式が false でなければifの値は 式1 ::::false ならば 式2 ::; [[#when|when]] :::;式で分岐:<syntaxhighlight lang=kotlin style="width: fit-content" copy> when ( 式 ) { 値0 -> 式0 値1, 値2... , 値n -> 式1 in 範囲式 -> 式2 !in 範囲式 -> 式3 is 型 -> 式4 !is 型 -> 式5   elase -> 式x } </syntaxhighlight> :::;式を省略すると true が仮定されます:<syntaxhighlight lang=kotlin style="width: fit-content" copy> when { 式0 -> 式0x 式1, 式2... , 式n -> 式1x   elase -> 式x } </syntaxhighlight> :::;値を返すwhen(による再帰):<syntaxhighlight lang=kotlin style="width: fit-content" copy> fun power(n: Int, i: Int) = when { i < 0 -> throw Exception("Negative powers of integers cannot be obtained.") i == 0 -> 1 i == 1 -> n else -> n * power(n, i - 1) } </syntaxhighlight> :; [[#繰返し処理|繰返し処理]] ::; [[#while|while]] :::<syntaxhighlight lang=kotlin copy> var i = 0 while (i < 5) { println(i) i++ } </syntaxhighlight> ::; [[#do-while|do-while]] :::<syntaxhighlight lang=kotlin copy> var i = 0 do { println(i) i++ } while (i < 5) </syntaxhighlight> ::; [[#for|for]] :::<syntaxhighlight lang=kotlin copy> for (i in 0 until 5) { println(i) } </syntaxhighlight> ; コレクション :;リストの生成 :;マップの生成 :;リストへのアクセス :;マップへのアクセス :;フィルタリング :;マップへの変換 ; クラス :;enum class :;abstract class ; 関数 :; 関数呼出し :; 関数定義 == KotlinとJavaの比較 == {{先頭に戻る}} KotlinとJavaは、どちらもJava Virtual Machine(JVM)上で動作するプログラミング言語です。以下は、KotlinとJavaの主な比較ポイントです。 # Null Safety(null安全性) #; Kotlin: Kotlinはnull安全性を重視しており、デフォルトで変数がnullになる可能性がある場合、その変数をnullableとして扱います。これにより、nullによる実行時のエラーを減少させます。 #; Java: 近年のJavaバージョンでは、<code>Optional</code>や<code>Nullable</code>などの概念が導入され、nullの扱いが改善されました。しかし、Kotlinのnull安全性はより厳格であり、コンパイル時の警告やエラーが発生しやすくなっています。 # コードの簡潔性 #; Kotlin: KotlinはJavaに比べてコードが簡潔で読みやすくなっています。これは、Kotlinがnullチェックや型推論などを自動的に処理し、冗長なコードを排除できるからです。 #; Java: Javaも近年ではラムダ式やストリームAPIなど、コードの簡潔性を向上させる機能が導入されていますが、依然として冗長なコードが残ることがあります。 # 関数型プログラミング #; Kotlin: Kotlinは関数型プログラミングをサポートしており、ラムダ式や高階関数の使用が簡単です。 #; Java: Javaも関数型プログラミングをサポートしていますが、Kotlinの方がよりシンプルになっています。 # 互換性 #; Kotlin: KotlinはJavaのライブラリやフレームワークを使用することができ、Javaとの相互運用性が高いです。また、JavaからKotlinに変換することも可能です。 #; Java: JavaはKotlinのコードを直接使用することはできませんが、既存のJavaコードとの連携がスムーズです。 # パフォーマンス #; Kotlin: KotlinはJavaに比べて少し遅いとされていますが、実際のアプリケーションではその違いがほとんど実感できないことが多いです。KotlinはJavaのバイトコードに変換されるため、ほとんど同じパフォーマンスを実現できます。 # ツールのサポート #; Kotlin: KotlinはJavaと同じツールを使用できるため、Javaエコシステムのメリットを享受しながら、より現代的な言語機能を利用できます。 総合的に見ると、KotlinはJavaよりも簡潔で読みやすく、より現代的な言語機能を備えています。ただし、Javaのライブラリやフレームワークを使用する場合は、Javaを使用することが必要な場合があります。 == KotlinとScalaの比較 == {{先頭に戻る}} KotlinとScalaは、どちらもJVM(Java Virtual Machine)上で動作する静的型付け言語であり、それぞれ異なる特徴を持っています。以下に、KotlinとScalaをいくつかの側面で比較してみます。 # パフォーマンス #; Kotlin: Kotlinは、Javaと同等のパフォーマンスを提供し、メモリ使用量が比較的少ないです。Androidアプリケーションの開発においては特に優れた性能を発揮します。 #; Scala: Scalaは一般的にはJavaよりも高速であるとされていますが、同時に多くのメモリを使用します。複雑なシステムの開発において、高いパフォーマンスが求められる場面で利用されます。 # 文法 #; Kotlin: Kotlinの文法はJavaに似ており、より簡素であり、Javaからの移行が容易です。これにより、Java開発者にとっては理解しやすいものです。 #; Scala: Scalaの文法は高度であり、関数型プログラミングの概念を強力にサポートしています。初めてのユーザーにとっては学習コストが高いかもしれませんが、高度な機能を提供しています。 # 開発用途 #; Kotlin: Kotlinは主にAndroidアプリケーションの開発に最適化されています。Android Studioでのサポートが強力であり、Androidエコシステムとの統合がスムーズです。 #; Scala: Scalaは複雑なシステムや大規模なプロジェクトの開発に適しています。特に関数型プログラミングの特徴を生かした開発に向いています。 # 可読性 #; Kotlin: KotlinはJavaと同じように、シンプルで読みやすいコードを書くことができます。文法がシンプルであるため、可読性が高いです。 #; Scala: Scalaは高度な機能を提供するが故に、可読性が低下する可能性があります。特に初心者にとっては、学習コストが高いと感じることがあります。 # 拡張性 #; Kotlin: Kotlinはよりシンプルでクラスベースのプログラミングスタイルを提供しており、拡張性があります。拡張関数や拡張プロパティなどが利用できます。 #; Scala: Scalaは関数型プログラミングの特徴を強調しており、高度な拡張性を提供しています。パターンマッチングや型クラスなどが利用できます。 総合的に見ると、KotlinはJavaからの移行が容易であり、Androidアプリケーションの開発に特に適しています。一方で、Scalaは関数型プログラミングの特徴を生かして複雑なシステムの開発に向いており、高度な拡張性を提供しています。選択する言語は、開発の目的や開発者のスキルセットによって異なることがあります。 == KotlinとSwiftの比較 == {{先頭に戻る}} KotlinとSwiftは、それぞれAndroidとiOSのアプリ開発で主に使用されるプログラミング言語です。以下に、両言語の類似点と相違点をいくつか挙げてみます。 ;類似点: :;静的型付け: ::KotlinとSwiftは両方とも静的型付け言語であり、コンパイル時に型の確認が行われます。これにより、実行時エラーを事前に把握しやすくなり、安全性が向上します。 :;モダンな構文: ::どちらの言語もモダンで読みやすい構文を採用しており、コードの記述が簡潔になっています。これにより、開発者は効率的かつ迅速にコードを書くことができます。 :;ヌル安全性: ::KotlinとSwiftはヌル安全性の考え方を取り入れており、ヌルポインターによるエラーを防ぐための手段を提供しています。これにより、安定したアプリケーションの開発が可能です。 ;相違点: :;ターゲットプラットフォーム: ::Kotlinは主にAndroidアプリ開発に焦点を当てていますが、JetBrainsによって開発・サポートされているため、マルチプラットフォーム開発にも利用されています。 ::SwiftはAppleが開発し、iOS、macOS、watchOS、tvOSなどのApple製品向けのアプリ開発に特化しています。 :;開発元とサポート: ::KotlinはJetBrainsによって開発・サポートされています。JetBrainsはプロの開発者向けのツールを提供しており、Kotlinの統合も図られています。 ::SwiftはAppleによって開発され、iOSや関連プラットフォーム向けに積極的にサポートされています。Xcodeなどの開発ツールも提供されています。 :;言語機能の違い: ::KotlinはJavaとの相互運用性が高く、既存のJavaコードとの統合が容易です。これにより、Android開発においても既存のJavaライブラリを利用することができます。 ::SwiftはObjective-Cとの相互運用性があり、iOS開発においてはObjective-Cコードとの統合が可能です。SwiftはObjective-Cよりもシンプルであり、関数型プログラミングの機能も強化されています。 :;構文と特徴: ::KotlinはJavaに似た構文を持ちつつ、いくつかの新しい機能や改善を提供しています。Javaからの移行が容易であり、Androidアプリケーション開発に適しています。 ::SwiftはObjective-Cよりもシンプルで読みやすい構文を持っており、関数型プログラミングの機能が強化されています。iOSアプリケーション開発において使用されます。 どちらの言語も優れた特性を持っており、選択はプロジェクトのニーズや開発者の好みによって異なります。 == エントリーポイント == {{先頭に戻る}} Kotlinでは、関数 mainがエントリーポイントです。 ;noop.kt:<syntaxhighlight lang=kotlin copy> fun main() {} </syntaxhighlight> なにもしないプログラムはこの様になります。 === コマンドライン引数を受取る場合 === ;use-args.kt:<syntaxhighlight lang=kotlin copy> fun main(args: Array<String>) { println(args.contentToString()) } </syntaxhighlight> ;Shell:<syntaxhighlight lang=text> % kotlinc use-args.kt -include-runtime -d use-args.jar % java -jar use-args.jar 123 abc 漢字 [123, abc, 漢字] % _ </syntaxhighlight> == パッケージ == {{先頭に戻る}} パッケージの指定は、ソースファイルの冒頭(shebang!の次)で行ってください<ref>[https://kotlinlang.org/docs/basic-syntax.html#package-definition-and-imports Package definition and imports]</ref>。 :<syntaxhighlight lang="Kotlin"> package my.demo import kotlin.text.* // Imprementation </syntaxhighlight> ディレクトリとパッケージの一致は必須ではなく、ソースファイルはファイルシステム上に任意に配置することができます。 === ディフォルトインポート === Kotlinでは、特定のパッケージやクラスを明示的にインポートすることなく、いくつかのデフォルトのインポートが提供されています。これにより、コードをより簡潔にし、冗長性を減少させることができます。以下は、デフォルトでインポートされる主要なパッケージです。 ;kotlin.*: Kotlinの基本的な機能や標準ライブラリが含まれています。これにより、Kotlinの核となる機能を利用するための基本的な道具が提供されます。 ;kotlin.annotation.*: アノテーション関連の機能が含まれています。アノテーションは、プログラムにメタデータを追加するための重要な手段です。 ;kotlin.collections.*: コレクション関連のクラスや関数が含まれています。これにより、リスト、セット、マップなどのデータ構造を効果的に扱うための機能が提供されます。 ;kotlin.comparisons.*: 比較関連の機能が含まれています。ソートや比較などの操作をより容易に行うことができます。 ;kotlin.io.*: 入出力関連の機能が含まれています。例えば、ファイルの読み書きや標準出力への出力などが簡単に行えます。 ;kotlin.ranges.*: 範囲関連の機能が含まれています。これを使用することで、特定の範囲内の要素を操作する際に便利なメソッドが提供されます。 ;kotlin.sequences.*: シーケンス処理関連の機能が含まれています。シーケンスを使用することで、遅延評価を活用して効率的なデータ処理が可能です。 ;kotlin.text.*: テキスト処理関連の機能が含まれています。文字列の操作やフォーマットなどが簡単に行えます。 また、ターゲットプラットフォームに応じて、追加のデフォルトインポートが行われます。 ;JVM: :;java.lang.*: Javaの基本的なクラスや機能が含まれています。これにより、Javaとの互換性が確保されます。 :;kotlin.jvm.*: JVM関連の機能が含まれています。 ;JS: :;kotlin.js.*: JavaScript関連の機能が含まれています。 上記のパッケージは、明示的にインポートすることなく既にインポートされています<ref>[https://kotlinlang.org/docs/packages.html#default-imports Default imports]</ref>。 このようなデフォルトのインポートにより、開発者は冗長なコードを書かずに済み、効率的にKotlinの機能を利用することができます。 ---- 以下は、デフォルトでインポートされる主要なパッケージの概要を表形式でまとめたものです。 :{| class=wikitable |+ デフォルトでインポートされる主要なパッケージ !パッケージ!!内容の概要 |- !kotlin.* |Kotlinの基本的な機能や標準ライブラリ |- !kotlin.annotation.* |アノテーション関連の機能 |- !kotlin.collections.* |コレクション関連のクラスや関数 |- !kotlin.comparisons.* |比較関連の機能 |- !kotlin.io.* |入出力関連の機能 |- !kotlin.ranges.* |範囲関連の機能 |- !kotlin.sequences.* |シーケンス処理関連の機能 |- !kotlin.text.* |テキスト処理関連の機能 |} また、ターゲットプラットフォームによっては、追加のデフォルトインポートが行われます。 :{| class=wikitable |+ ターゲットプラットフォーム別の追加のデフォルトインポート !ターゲットプラットフォーム!!追加されるパッケージの概要 |- !JVM |java.lang.*: Javaの基本的なクラスや機能 |kotlin.jvm.*: JVM関連の機能 |- !JS |kotlin.js.*: JavaScript関連の機能 |} これらのデフォルトインポートは、通常のKotlinプロジェクトで基本的な操作や機能を利用するための便利な手段となります。 === インポート === デフォルトインポートとは別に、各ファイルは独自の <code>[[#import|import]]</code> ディレクティブを含むことができます。 単一の名前でインポートすることができます。 import org.example.Message // Message は無条件にアクセスできます。 または、パッケージ、クラス、オブジェクトなどのスコープのすべてのアクセス可能なコンテンツをインポートすることができます。 import org.example.* // 'org.example' に含まれるすべてのコンテンツにアクセスできるようになります。 名前の衝突がある場合、as キーワードを使用して、衝突するエンティティの名前をローカルに変更することで、曖昧さをなくすことができます。 import org.example.Message // Message にアクセスできるようになります。 import org.test.Message as testMessage // testMessage は 'org.test.Message' を表しています。 import キーワードは、クラスのインポートに限定されません。他の宣言をインポートするためにも使用することができます。 * トップレベルの関数およびプロパティ * オブジェクト宣言の中で宣言された関数やプロパティ * enum 定数 === トップレベル宣言の可視性 === トップレベル宣言が private とマークされている場合、その宣言が行われたファイルに対してプライベートとなります。 {{See also|[[#可視性修飾子|可視性修飾子]]}} == トップレベルオブジェクト == {{先頭に戻る}} いかなる関数スコープにも属さないオブジェクトのことを、トップレベルオブジェクト( ''top level object'' )と言います<ref>[https://kotlinlang.org/spec/syntax-and-grammar.html#grammar-rule-topLevelObject topLevelObject]</ref>。 ;[https://paiza.io/projects/jKQiCwDXdUOhVY7dIoDmKg?language=kotlin トップレベルオブジェクトの前方参照は許される]:<syntaxhighlight lang="Kotlin"> val a = 10 fun main() { println("a =$a, b = $b") } val b = 32 </syntaxhighlight> ;実行結果:<syntaxhighlight lang="text"> a = 10, b = 32 </syntaxhighlight> :この例では変数 <var>b</var> の参照が前方参照になっていますが、<var>b</var> はトップレベルオブジェクトなので参照解決されます。 == コメント == {{先頭に戻る}} Kotlinには、行末で終わるコメントと、複数行に渡ることと、入れ子にすることができるコメントがあります。 ;[https://pl.kotl.in/F-bmww7Bt comments.kt]:<syntaxhighlight lang="Kotlin"> // Kotlinには、行末で終わるコメントと fun main() { /* * 複数行に渡ることと * /* * 入れ子にすることができる * コメントがあります */ */ println("Hello, World!") } </syntaxhighlight> : <code>/* ... */</code>タイプのコメントは、入れ子にできるのが多くのプログラミング言語と異なります。 :: Kotlinの他には、[[Scala]]と[[D言語]]がコメントを入れ子にできます。 == 基本型 == {{先頭に戻る}} Kotlinでは、任意のインスタンスに対してプロパティーを参照したりメンバー関数を呼出すことができるという意味で、すべてのインスタンスがクラスに属しています。 いくつかの型は特別な内部表現を持つことができます。例えば、数字、文字、ブール値は実行時にプリミティブ値として表現できますが、ユーザーからは参照されるときに自動的にボックス化されるので普通のクラスのインスタンスのように見えます。 これらの型は基本的にJavaのプリミティブに一対一に対応しますが、Stringだけはjava.lang.Stringクラスに対応しています。 基本型は Package kotlin で定義されています。 ; Kotlinの基本型 :;[[#論理型|論理型]]:<code>[[#Boolean|Boolean]]</code> {{---}} true, false :;[[#数値型|数値型]] ::;符号付き整数型:<code>[[#Byte|Byte]]</code> <code>[[#Short|Short]]</code> <code>[[#Int|Int]]</code> <code>[[#Long|Long]]</code> ::;符号無し整数型:<code>[[#UByte|UByte]]</code> <code>[[#UShort|UShort]]</code> <code>[[#UInt|UInt]]</code> <code>[[#ULong|ULong]]</code> :;[[#浮動小数点数型|浮動小数点数型]]:<code>[[#Float|Float]]</code><code>[[#Double|Double]]</code> :;[[#文字型|文字型]]: <code>[[#Char|Char]]</code> :;[[#文字列型|文字列型]]:<code>[[#String|String]]</code> ;[https://pl.kotl.in/sePeMiW1A primitive.kt]:<syntaxhighlight lang="Kotlin"> fun main() { println("値 : simpleName") println("----------------") arrayOf(true, 2.toByte(), 3.toUByte(), 5.toShort(), 7.toUShort(), 11, 13U, 17L, 19UL, 1.23, 3.14F, 'C', "abc").forEach { println("$it : ${it::class.simpleName}") } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 値 : simpleName ---------------- true : Boolean 2 : Byte 3 : UByte 5 : Short 7 : UShort 11 : Int 13 : UInt 17 : Long 19 : ULong 1.23 : Double 3.14 : Float C : Char abc : String </syntaxhighlight> :{| class="wikitable" |+ 基本型<ref>[https://kotlinlang.org/docs/basic-types.html Basic types]</ref> |- ! 型 ! Javaの型 ! リテラル表現 |- ! <syntaxhighlight lang=kotlin inline>Boolean</syntaxhighlight> ! <syntaxhighlight lang=java inline>boolean</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>false, true</syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>Byte</syntaxhighlight> ! <syntaxhighlight lang=java inline>byte</syntaxhighlight> | <syntaxhighlight lang=kotlin inline></syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>Short</syntaxhighlight> ! <syntaxhighlight lang=java inline>short</syntaxhighlight> | <syntaxhighlight lang=kotlin inline></syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>Int</syntaxhighlight> ! <syntaxhighlight lang=java inline>int</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>123, 0x17, 0b10110110</syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>Long</syntaxhighlight> ! <syntaxhighlight lang=java inline>long</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>123L, 0x17L, 0b10110110L</syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>Double</syntaxhighlight> ! <syntaxhighlight lang=java inline>double</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>1.73205080757,6.62607015e-34</syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>Float</syntaxhighlight> ! <syntaxhighlight lang=java inline>float</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>1.73205080757f</syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>String</syntaxhighlight> ! <syntaxhighlight lang=java inline>java.lang.String</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>"Simple sample text."</syntaxhighlight> |- ! <syntaxhighlight lang=kotlin inline>Char</syntaxhighlight> ! <syntaxhighlight lang=java inline>char</syntaxhighlight> | <syntaxhighlight lang=kotlin inline>'Q'</syntaxhighlight> |} === 論理型 === Kotlinの論理型は <code>{{Anchor|Boolean}}</code> で ;偽: <code>{{Anchor|false}}</code> ;真: <code>{{Anchor|true}}</code> の2つの値以外は取りえません。 JVMでは、この型の非[[#Nullable|Nullable]]値は、プリミティブ型のbooleanの値として表現されます。 論理型と数値型は可換ではないので、制御構造の条件式などでもゼロとの比較を行う必要があります。 {{See also|[[#Nullable|Nullable]]}} === 数値型 === Kotlinの数値型は、[[#整数型|整数型]]と[[#浮動小数点数型|浮動小数点数型]]に分かれています。 これらの型は、抽象クラスである <code>{{Anchor|Number}}</code> クラスから派生しており、具象クラスとして利用されます。 なお、[[#文字型|文字型]]は数値型と可換ではありません。 ==== 整数型 ==== Kotlinの整数型には、符号付き整数型と符号なし整数型があります。 符号なし整数型の名前は、対応する符号付き整数型の名前の先頭に <code>U</code> を補ったものになります。以下が主な整数型です: :{| class=wikitable |+ 整数型 |- ! <code>{{Anchor|Byte}}</code> | 符号付き1バイト整数 |- ! <code>{{Anchor|Short}}</code> | 符号付き2バイト整数 |- ! <code>{{Anchor|Int}}</code> | 符号付き4バイト整数 |- ! <code>{{Anchor|Long}}</code> | 符号付き8バイト整数 |- ! <code>{{Anchor|UByte}}</code> | 符号なし1バイト整数 |- ! <code>{{Anchor|UShort}}</code> | 符号なし2バイト整数 |- ! <code>{{Anchor|UInt}}</code> | 符号なし4バイト整数 |- ! <code>{{Anchor|ULong}}</code> | 符号なし8バイト整数 |} ==== 浮動小数点数型 ==== Kotlinの浮動小数点数型には、以下の2つがあります: :{| class=wikitable |+ 浮動小数点数型 |- ! <code>{{Anchor|Float}}</code> | 単精度浮動小数点数;ISO/IEC/IEEE 60559:2011-06 のbinary32 |- ! <code>{{Anchor|Double}}</code> | 倍精度浮動小数点数;ISO/IEC/IEEE 60559:2011-06 のbinary64 |} これらの数値型は、数学的な演算や精密な計算に利用され、Kotlin言語において数値処理をサポートする基本的な要素となっています。 === 文字型 === {{先頭に戻る}} {{Anchor|Char}}クラスは文字を表すクラスです。'a' のようなKotlinプログラム内の文字リテラルはすべてこのクラスのインスタンスとして実装されています<ref>[https://kotlinlang.org/docs/characters.html Characters]</ref><ref name=char>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-char/ Char]</ref>。 <code>Char</code>は、16ビットのUnicode文字を表します。これは、Charがすべての文字をユニコード文字を表すことが'''出来ない'''事をしめしています。 ;[https://pl.kotl.in/KRFm8vVVb Charで表現できない文字]:<syntaxhighlight lang="Kotlin" highlight=4> fun main() { val ascii = 'A' val kanji = '漢' val emoji = '🏝' } </syntaxhighlight> ;コンパイル結果:<syntaxhighlight lang=text> Too many characters in a character literal ''🏝'' </syntaxhighlight> : 🏝のUnicodeはU+1F3DDと16ビットを超えているので Char には収容できません。 : 絵文字以外にもサロゲートペアはあり、サロゲートペア以外にも合成文字も16ビットを超えるものがあります。 Kotlinは、Javaの文字エンコーディングシステムを引継いだので、Charの収まらない文字の問題に限らずUnicodeを内部エンコーディングに使っていることに起因する厄介ごとと付き合い続ければなりません。 ==== 演算子 ==== Charでは、いくつかの演算子が定義されています<ref name=char/>。 ;[https://pl.kotl.in/pQ82wUEc_ Charクラスの演算子]:<syntaxhighlight lang="Kotlin" line> fun main() { var a = 'K' println("var a = 'K'") a-- println("a-- ⇒ $a") a++ println("a++ ⇒ $a") println("'C' - 'A' ⇒ ${'C' - 'A'}") println("'C' - 2 ⇒ ${'C' - 2}") println("'A' + 2 ⇒ ${'A' + 2}") println("'A'..'C' ⇒ ${'A' .. 'C'}") println("'A'..<'C' ⇒ ${'A' ..< 'C'}") println("'A' + \"BCD\" ⇒ ${'A' + "BCD"}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> var a = 'K' a-- ⇒ J a++ ⇒ K 'C' - 'A' ⇒ 2 'C' - 2 ⇒ A 'A' + 2 ⇒ C 'A'..'C' ⇒ A..C 'A'..<'C' ⇒ A..B 'A' + "BCD" ⇒ ABCD </syntaxhighlight> ==== エスケープシーケンス ==== 特殊文字は、エスケープする \(バックスラッシュ)から始まります。以下のエスケープシーケンスに対応しています。 :{| class="sortable wikitable" |+ エスケープシーケンス |- !表現!!意味 |- !\t |水平tab |- !\b |バックスペース |- !\n |改行(LF) |- !\r |キャリッジリターン(CR) |- !\' | シングルクォーテーション |- !\" |ダブルクオーテーションマーク |- !\\ |バックスラッシュ |- !\$ |ドル記号 |} その他の文字をエンコードする場合は、Unicodeエスケープシーケンス構文を使用します。'\uFF00' を使用します。 === 文字列型 === {{先頭に戻る}} {{Anchor|String}} クラスは文字列を表すクラスです。"abc" のようなKotlinプログラム内の文字列リテラルはすべてこのクラスのインスタンスとして実装されています<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/ String]</ref>。 Kotlinでは、文字列( <code>String</code> )と文字( <code>Char</code> )とは直接の関係はありません(StringはCharの配列ではありません)。 ==== 演算子 ==== Stringでは、加算演算子を連結として定義されています<ref>[https://github.com/JetBrains/kotlin/blob/f3385fbdcb8b9dc29661a8a4973c855cdcf73767/core/builtins/native/kotlin/String.kt#L30 kotlin/core/builtins/native/kotlin/String.kt]</ref>。 :<syntaxhighlight lang="Kotlin"> public operator fun plus(other: Any?): String </syntaxhighlight> 加算演算子( <code>+</code> )は、文字列( this )と与えられた他のオブジェクトの文字列表現を連結して得られる文字列を返します<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-string/plus.html plus - Kotlin Programming Language]</ref>。 ;[https://pl.kotl.in/1KlKcFKGs 文字列の+演算子]:<syntaxhighlight lang="Kotlin"> fun main() { val str = "ABC" + 12 println(str + true + listOf(1,2,3)) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ABC12true[1, 2, 3] </syntaxhighlight> ==== テンプレートリテラル ==== 既に紹介したように、Stringクラスのリテラルは "(ダブルクオーテーション)で括った文字列です。 Stringリテラルには変数や式を埋込むことが出来ます。 このように、変数や式が埋込まれたStringリテラルのことを{{Anchor|テンプレートリテラル}}といいます。 ;[https://pl.kotl.in/uBCbpW7Mc テンプレートリテラル]:<syntaxhighlight lang="Kotlin"> fun main() { var n = 10 println("変数 n の値は $n です。") println("式 n + 13 の値は ${n + 13} です。") println("${'$'} 自体を書きたいときは、 \\\$ と \$ の直前に \\ を置きエスケープします(\$\$ではありません)。") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 変数 n の値は 10 です。 式 n + 13 の値は 23 です。 $ 自体を書きたいときは、 \$ と $ の直前に \ を置きエスケープします($$ではありません)。 </syntaxhighlight> ==== 生文字列 ==== 生文字列( ''Raw strings'' )は、改行や任意のテキストを含むことができます。トリプルクォート(”””; ''triple quote'' )で区切られ、エスケープを含まず、改行や他の任意の文字を含むことができます<ref>[https://kotlinlang.org/docs/strings.html#raw-strings Raw strings]</ref>。 ;[https://pl.kotl.in/7Pqk1IwPo 生文字列]:<syntaxhighlight lang="Kotlin"> fun main() { var n = 10 print( """ 変数 n の値は $n です。 式 n + 13 の値は ${n + 13} です。 ${'$'} 自体を書きたいときは、 \$ と $ の直前に \ を置きエスケープします($$ ではありません)。 """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 変数 n の値は 10 です。 式 n + 13 の値は 23 です。 $ 自体を書きたいときは、 \$ と $ の直前に \ を置きエスケープします($$ ではありません)。 </syntaxhighlight> ==== エスケープシーケンス ==== {{See|[[#エスケープシーケンス|文字型のエスケープシーケンス]]}} ==== コードポイント ==== ;[https://pl.kotl.in/7Pqk1IwPo 文字列のn番目のコードポイント]:<syntaxhighlight lang="Kotlin"> fun main() { val str = "ABC漢字🏝𠮷" var i = 0 while (i < str.length) { println(Integer.toHexString(str.codePointAt(i))) i++ } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text highlight="7,9"> 41 42 43 6f22 5b57 1f3dd dfdd 20bb7 dfb7 </syntaxhighlight> : codePointAt()でサロゲートペアの2ワード目を読むと… === Array === Kotlinで配列型は Array で、main() の引数でも使われています<ref>[https://kotlinlang.org/docs/arrays.html Array]</ref><ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-array/ Array]</ref>。 [[#Array()|Array()]], [[#arrayOf()|arrayOf()]], arrayOfNulls() や emptyArray() で生成します。 ==== Array() ==== ;[https://paiza.io/projects/sywOsCKIuSuu8x2BrbdfwQ?language=kotlin Array()を使ったArrayの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val ary = Array(5){it} println("ary::class.simpleName ⇒ ${ary::class.simpleName}") println("ary[0]::class.simpleName ⇒ ${ary[0]::class.simpleName}") ary.forEach{print("$it ")} println("") val ary2 = Array(5){(it*it).toString()} println("ary2[0]::class.simpleName ⇒ ${ary2[0]::class.simpleName}") ary2.forEach{print("$it ")} println("") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary::class.simpleName ⇒ Array ary[0]::class.simpleName ⇒ Int 0 1 2 3 4 ary2[0]::class.simpleName ⇒ String 0 1 4 9 16 </syntaxhighlight> : Array()はArrayのコンストラクターで、引数として要素数をとり、ブロックが初期化式になります。 ==== プリミティブ型配列 ==== Kotlinには、IntArray、DoubleArray、BooleanArray、CharArrayなどのプリミティブ型を要素とする配列のクラスが用意されています。 これらを総称してプリミティブ型配列( Primitive type arrays )と呼びます<ref>[https://kotlinlang.org/docs/arrays.html#primitive-type-arrays Primitive type arrays]</ref>。 プリミティブ型配列は、機能的にはArray<T>のTにプリミティブ型を与えたものと変わりありませんが、ボックス化されないので性能向上とフットプリントの削減が期待できます。 このため、プリミティブ型配列はArrayを継承していません。 StringArray はありません。 ;[https://paiza.io/projects/tgs7lwP0-La0B-TUJ--kug?language=kotlin IntArray()を使ったIntArrayの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val ary = IntArray(5){it} println( """ ary::class.simpleName ⇒ ${ary::class.simpleName} ary[0]::class.simpleName ⇒ ${ary[0]::class.simpleName} ary => $ary ary.joinToString() ⇒ ${ary.joinToString()} ary.contentToString() => ${ary.contentToString()} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary::class.simpleName ⇒ IntArray ary[0]::class.simpleName ⇒ Int ary => [I@1c6b6478 ary.joinToString() ⇒ 0, 1, 2, 3, 4 ary.contentToString() => [0, 1, 2, 3, 4] </syntaxhighlight> ==== arrayOf() ==== ;[https://paiza.io/projects/avmXjK5ilEp1Xl-_CSnMfw?language=kotlin arrayOf()を使ったArrayの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val ary = arrayOf(1, 9, 3, 5, 23, 1) println("${ary::class.simpleName}") println("${ary[0]::class.simpleName}") for (s in ary) if (s > 10) break else print("$s ") println("") run { ary.forEach{ if (it > 10) return@run else print("$it ") } } println("") var i = 0 while (i < ary.size) ary[i] = i++ ary.forEach{print("$it ")} } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Array Int 1 9 3 5 1 9 3 5 </syntaxhighlight> : arrayOf()は可変長引数の関数で、引数が生成されるArrayの要素になります。 : Arrayの要素の型は、型強制できる最小公倍数的な方になります(例えば Int と Long が混在していたら Long)。 == 特別な型 == {{先頭に戻る}} 基本型の他にも幾つかの特別な型があります。 これらは、基本型同様 Package kotlin で定義されています。 ; 特別な型 :;Kotlinのクラス階層のルート:<code>[[#Any|Any]]</code> :;戻値型未指定な関数の型:<code>[[#Unit|Unit]]</code> :;存在しない値を表す型:<code>[[#Nothing|Nothing]]</code> === Any === AnyはKotlinのクラス階層のルートです。すべてのKotlinクラスはAnyをスーパークラスとして持っています。 クラス定義で継承元を指定しないと Any が暗黙の継承元になります。 また、Anyクラスのオブジェクトは、あらゆるオブジェクトを代入できます。 ;[https://pl.kotl.in/k-36Q8gd6 AnyのArray]:<syntaxhighlight lang="Kotlin"> fun main() { arrayOf(4, "abc", 'a', listOf(2,5,6)).forEach{ println("$it(${it::class.simpleName})") } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 4(Int) abc(String) a(Char) [2, 5, 6](ArrayList) </syntaxhighlight> === Unit === Unitは、何も返さない関数の戻値の型です。JVMでは、Javaのvoid型に相当します。 :<code>pub main() : Unit {}</code> は :<code>pub main() {}</code> と等価です。 === Nothing === Nothingはインスタンスを持ちません。例えば、ある関数の戻り値がNothingであれば、それは決して戻らない(常に例外を投げる)ことを意味します<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-nothing.html Nothing]</ref>。 == Null安全 == KotlinのNULL安全性(Null safety)とNullableに関して、以下のポイントが重要です。 # Null安全性: Kotlinの目標の一つは、null参照によるエラー(The Billion Dollar Mistakeとも呼ばれる)の危険性を排除することです。Javaを含む多くのプログラミング言語で見られる最も一般的な落とし穴の一つは、null参照のメンバーにアクセスすると、null参照例外が発生することです(JavaではNullPointerException、NPEと呼ばれます)。 # Nullable型と非Nullable型: Kotlinの型システムでは、nullを保持できる参照(Nullable型)と、保持できない参照(非Nullable型)とを区別します。たとえば、String型の通常の変数はnullを保持できませんが、NullableなString型はnullを保持できます。 # Nullable型の宣言: nullを許容する型を宣言するには、型名の後ろに「?」を付けます。例えば、String型のNullableな変数を宣言する場合は、<code>String?</code>とします。 # Nullable型の安全な操作: Nullableな変数やプロパティに安全にアクセスする方法として、以下のような手法があります。 #* <code>?.</code>演算子: セーフコール演算子は、nullチェックを行い、nullでない場合にのみメンバーにアクセスします。 #* <code>?:</code>演算子: Elvis演算子は、nullでない場合には左側の値を、nullの場合には右側の値を返します。 #* <code>!!</code>演算子: null許容型の値を非Nullable型として扱い、nullの場合にはNullPointerExceptionをスローします。 # Null安全性の確認: null安全性の確認は、条件式で明示的に行うことができます。<code>if (variable != null)</code>のような形で、nullチェックを行い、それに応じた処理を行います。 # Safe casts: 安全なキャスト演算子<code>as?</code>を使用すると、通常のキャストでClassCastExceptionが発生する可能性がある場合でも、nullを返すことができます。 KotlinのNull安全性とNullable型は、プログラミングにおける安全性と信頼性を向上させるための重要な機能です。これらの機能を適切に理解し、利用することで、Nullによるエラーを最小限に抑えることができます。 Javaを含む多くのプログラミング言語における最も一般的な落とし穴の1つは、Null参照のメンバーにアクセスするとNull参照例外が発生することです。Javaでは、これはNullPointerException、略してNPEと呼ばれるものに相当します<ref>[https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-null-types Nullable types and non-null types]</ref>。 KotlinでNPEが発生する原因として考えられるのは、以下の通りです。 * NullPointerException()を明示的に呼び出した場合。 * 後述する !! 演算子の使用。 * 初期化に関するデータの不整合(以下のような場合)。 ** コンストラクターで使用可能な未初期化の this がどこかで渡され使用されている (「リーキング this」)。 ** スーパークラスのコンストラクターが、派生クラスの実装で未初期化の状態を使用しているオープンメンバーを呼出す場合。 * Java との相互運用。 ** プラットフォーム型のNull参照のメンバにアクセスしようとする。 ** Java との相互運用に使用される汎用型の Nullability の問題。例えば、ある Java コードが Kotlin の MutableList<String> に null を追加し、それを操作するために MutableList<String?> が必要になることがあります。 ** その他、外部のJavaコードによって引き起こされる問題。 === Nullable === Kotlinの型システムでは、nullを保持できる参照(Null可能参照; ''nullable references'' )とそうでない参照(非Null参照; ''non-null references'' )を区別しています。例えば、String型の通常の変数はnullを保持できません。 :<syntaxhighlight lang=kotlin line highlight=2 copy> var a: String = "abc" // 通常の初期化ではデフォルトで非nullを意味します // a = null // コンパイルエラー! </syntaxhighlight> nullを許容するには、<code>String?</code>と書いて変数をnull可能な文字列として宣言します。 :<syntaxhighlight lang=kotlin line highlight="1,2" copy> var b: String? = "abc" // nullに設定可能 b = null // OK prinlnt(b) </syntaxhighlight> さて、<var>a</var>のメンバー関数を呼び出したり、プロパティーにアクセスしたりしても、NPEが発生しないことが保証されています。 :<syntaxhighlight lang=kotlin line copy> val l = a.length </syntaxhighlight> しかし、<var>b</var>のメンバー関数を呼び出したり、プロパティーにアクセスしたりすると、それは安全ではなく、コンパイラはエラーを報告します。 :<syntaxhighlight lang=kotlin line copy> val l = b.length </syntaxhighlight> それでもそのプロパティにアクセスする必要がありますよね?そのためには、いくつかの方法があります。 === 条件におけるnullのチェック === まず、bがnullかどうかを明示的にチェックし、2つの選択肢を別々に処理することができます。 :<syntaxhighlight lang=kotlin line copy> val l = if (b != null) b.length else -1 </syntaxhighlight> コンパイラーは実行したチェックの情報を記録し、ifの内部でlengthの呼出しを可能にする。より複雑な条件もサポートされています。 :<syntaxhighlight lang=kotlin line copy> val b: String? = "Kotlin" if (b != null && b.length > 0) { print("文字列の長さは ${b.length}") } else { print("空文字列") } </syntaxhighlight> 註:b が immutable な場合 (つまり、チェックから使用までの間に変更されないローカル変数か、 バッキングフィールドを持つオーバーライド不可のメンバー変数) にのみ有効です。 === !!演算子 === Not-Null断定演算子(!!)で任意の値をnullでない型に変換し、値がnullの場合は例外をスローします。<code>b!!</code>と書くと、<var>b</var>の非null値(例えばこの例ではString)を返し、<var>b</var>がnullの場合はNPEを投げます。 :<syntaxhighlight lang=kotlin line copy> val l = b!!.length </syntaxhighlight> このように、NPEを発生させたい場合は、明示的に要求する必要があり、突然発生することはありません。 === ?.演算子 === :<syntaxhighlight lang=kotlin line highlight=5 copy> fun main() { var str: String? = "Hello" // ?を使ってnullを許容する str = null // 問題なくnullを代入できる val length = str?.length // 安全呼び出し演算子でnullチェックしつつプロパティにアクセス println("Length: $length") } </syntaxhighlight> <code>?.</code> 演算子は、null安全性を保証しつつ、<code>str</code> 変数がnullでない場合に <code>length</code> プロパティにアクセスします。<code>str</code> がnullの場合、<code>length</code> には <code>null</code> が代入されます。 このように、<code>?.</code> 演算子はnull値を安全に処理するために使用されます。例えば、Javaの場合、nullチェックを行わないとNullPointerExceptionが発生しますが、Kotlinでは <code>?.</code> 演算子を使用することで、nullに対する操作を安全に行うことができます。 == 識別子 == {{先頭に戻る}} 変数の名前のような名前を識別子( ''identifiers'' )と呼びます<ref>[https://kotlinlang.org/spec/syntax-and-grammar.html#identifiers Identifiers]</ref>。 変数ほかに、関数、クラス、クラスのメンバー、クラスのメンバー関数、enum、ラベルなどの名前も識別子です。 * 同じ名前空間の中では識別子は重複できません。 * 識別子に使える文字は、英数字・_(アンダーバー)・Unicode文字です。 * 識別子の最初に数字を使うことはできません。 * 識別子の大文字小文字は区別されます。 * キーワードの使用には制限があります。 * キーワードや空白を含む文字列など上のルールに従わない文字列は、`(バッククオーテーション)で囲むと識別子として使うことができます。 {{See also|[[#キーワード|キーワード]]}} == 変数 == {{先頭に戻る}} Kotlinでは、変数は使う前にかならず宣言する必要があります。 === val と var === ==== val ==== ;[https://pl.kotl.in/8PE1c8KR3 変数を使った単純なコード]:<syntaxhighlight lang=kotlin line highlight="2,3" copy> fun main() { val hello = "Hello, World!" println(hello) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, World! </syntaxhighlight> :[[#Hello world|Hello world]]の例と結果は同じですが、変数<var>hello</var>を導入しています。 :;変数 hello の宣言:<syntaxhighlight lang=kotlin line start=2 copy> val hello = "Hello, World!" </syntaxhighlight> :イミュータブル変数の宣言は、この様に:<syntaxhighlight lang=kotlin copy> val 識別子 = 初期化式 </syntaxhighlight> :の形式をとります。 :;変数 hello の値の参照:<syntaxhighlight lang=kotlin line start=3 copy> println(hello) </syntaxhighlight> :の様に識別子をそのまま書くことで、値(この場合は "Hello, World!")を参照できます。 :キーワード <code>val</code> を使って宣言された変数はイミュータブル( ''Immutable'' )です。 :: イミュータブルというのは、一度値が決めたら変更できないという意味です。 :イミュータブルな変数を「定数」ということがありますが、リテラルのことを定数ということもあるので、ここでは「イミュータブルな変数」と呼びます。 ==== var ==== ;[https://pl.kotl.in/8z57OJeNL ミュータブルな変数を使ったコード]:<syntaxhighlight lang=kotlin line highlight="2,4" copy> fun main() { var hello = "Hello, World!" println(hello) hello = "Hello, Kotlin!" println(hello) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, World! Hello, Kotlin! </syntaxhighlight> :;変数 hello の宣言:<syntaxhighlight lang=kotlin line start=2 copy> var hello = "Hello, World!" </syntaxhighlight> :ミュータブルな変数の宣言は、この様に:<syntaxhighlight lang=kotlin copy> var 識別子 = 初期化式 </syntaxhighlight> :の形式をとります。 :キーワード <code>var</code> を使って宣言された変数はイミュータブル( ''Immutable'' )です。 :: ミュータブルというのは、変数の値を何度でも変更できるという意味です。 :;変数 hello に新しい値を代入:<syntaxhighlight lang=kotlin line start=4 copy> hello = "Hello, Kotlin!" </syntaxhighlight> :Kotlinでは <code>=</code> が代入演算子です。 :: 代入の前の <var>hello</var> の値は <code>"Hello, World!"</code> でしたが、代入の後は <code>"Hello, Kotlin!"</code> になります。 ==== 型推論 ==== いままでの例で既に型推論( ''type inference'' ) は使われています。 変数を宣言するときに、特に型を明示しませんでしたが、初期化式の型から変数の型を特定していたのです。 ===== 型アノテーション ===== 初期化式は省略可能です。 その場合は変数の型がわからないので型アノテーション( ''type annotation'' )が必要になります。 ;[https://pl.kotl.in/EW6hk7OkA 型アノテーションを伴った変数宣言]:<syntaxhighlight lang=kotlin line highlight="2" copy> fun main() { var hello : String hello = "Hello, World!" println(hello) hello = "Hello, Kotlin!" println(hello) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, World! Hello, Kotlin! </syntaxhighlight> :;型アノテーションを伴った変数 hello の宣言:<syntaxhighlight lang=kotlin line start=2 copy> var hello : String </syntaxhighlight> ::<code>: String</code>が型アノテーションで :型アノテーションを伴った変数の宣言は、この様に:<syntaxhighlight lang=kotlin copy> var 識別子 : 型 </syntaxhighlight> :の形式をとります。 ::型アノテーションをイミュータブルな変数の宣言でも行えますが、事実上初期化式が必須なのでドキュメント性を高める以外の意味は希薄です。 {{See also|[[#基本型|基本型]]}} ===== シャドーイング ===== シャドーイング( ''Shadowing'' )とは、スコープ内の2つの宣言が同じ名前になり、より内側の識別子が外側の識別子を隠すことです。 ;[https://paiza.io/projects/etUJhoaySpr4RcwO9VwO-g?language=kotlin コード例]:<syntaxhighlight lang="Kotlin" line highlight="2,4"> fun main() { var i = 10 for (i in 1..3) println("for内: i = $i") println("for外: i = $i") } </syntaxhighlight> ;コンパイラーの警告:<syntaxhighlight lang=text> Main.kt:4:10: warning: name shadowed: i for (i in 1..3) ^ </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> for内: i = 1 for内: i = 2 for内: i = 3 for外: i = 10 </syntaxhighlight> : ループ変数 <var>i</var> と、2行目で宣言された変数 <var>i</var> の名前が衝突しいています。 : この様に名前が衝突した場合、スコープの内側のオブジェクトが参照されます。 : コンパイラーはシャドーイングを発見すると<code>warning: name shadowed: 識別子</code>と(エラーでなく)警告します。 多くのシャドーイングは無害ですが… ;ありがちな間違え:<syntaxhighlight lang="Kotlin" line highlight="2,3"> fun main() { for (i in 1..3) for (i in 1..4) println("(i, i) = ($i, $i)") } </syntaxhighlight> ;コンパイラーのエラー出力:<syntaxhighlight lang=text> Main.kt:3:14: warning: name shadowed: i for (i in 1..4) ^ </syntaxhighlight> ;修正例:<syntaxhighlight lang="Kotlin" line highlight="3,4"> fun main() { for (i in 1..3) for (j in 1..4) println("(i, j) = ($i, $j)") } </syntaxhighlight> : 行列式を扱っていると、よくやらかします。 ===== 分解宣言 ===== オブジェクトを複数の変数に分解して初期化する宣言する方法があり、分解宣言( ''Destructuring declarations'' )と呼ばれます<ref>[https://kotlinlang.org/docs/destructuring-declarations.html Destructuring declarations]</ref>。 ;分解宣言の例:<syntaxhighlight lang="Kotlin" line highlight="2,4"> fun main() { val (a, b) = Pair(3, 4) val (c, d) = Pair("abc", 3.14) val (e, f) = 'C' to null val (g, h, i) = Triple(1,2,3) val (j, k, l, m) = List(4){it*2} print( """ a = $a, b = $b c = $c, d = $d e = $e, f = $f g = $g, h = $h, i = $i j = $j, k = $k, l = $l, m = $m """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> a = 3, b = 4 c = abc, d = 3.14 e = C, f = null g = 1, h = 2, i = 3 j = 0, k = 2, l = 4, m = 6 </syntaxhighlight> : to は infix 宣言された関数です。 == 演算子 == {{先頭に戻る}} === 演算子の優先順位 === :{| class="wikitable" |+ 演算子の優先順位<ref>[https://kotlinlang.org/docs/reference/grammar.html#expressions Expressions]</ref> !優先順位 !種類 !記号 |- |高い |後置 |<code>++</code>, <code>--</code>, <code>.</code>, <code>?.</code>, <code>?</code> |- | |前置 |<code>-</code>, <code>+</code>, <code>++</code>, <code>--</code>, <code>!</code>, label |- | |型 |<code>:</code>, <code>as</code>, <code>as?</code> |- | |乗除算 |<code>*</code>, <code>/</code>, <code>%</code> |- | |加減算 |<code>+</code>, <code>-</code> |- | |範囲 |<code>..</code>, <code>..<</code> |- | |中置関数(Infix function) |simpleIdentifier |- | |エルビス |<code>?:</code> |- | |Named checks |<code>in</code>, <code>!in</code>, <code>is</code>, <code>!is</code> |- | |比較 |<code><</code>, <code>></code>, <code><=</code>, <code>>=</code> |- | |一致不一致 |<code>==</code>, <code>!=</code>, <code>===</code>, <code>!==</code> |- | |Conjunction |<code>&&</code> |- | |Disjunction |<code><nowiki>||</nowiki></code> |- | |スプレッド演算子 |<code>*</code> |- |低い |代入演算 |<code>=</code>, <code>+=</code>, <code>-=</code>, <code>*=</code>, <code>/=</code>, <code>%=</code> |} {{See also|[[#演算子と特殊シンボル|演算子と特殊シンボル]]}} === 演算子オーバーロード === {{先頭に戻る|style=border-top:1px solid gray;}} Kotlinでは、演算子はメソッド形式の別名を持ちます。 例えば、<code>a + b</code> は <code>a.plus(b)</code> とも書けます。 この plus メンバー関数を再定義すると、演算子オーバーロードができます<ref>[https://kotlinlang.org/docs/operator-overloading.html Operator overloading]</ref>。 ;[https://paiza.io/projects/mhnZrTY0BmuFApKNAy3oNw?language=kotlin コード例]:<syntaxhighlight lang=Kotlin highlight="4,22-25" line> fun main() { class Point(val x : Int = 0, val y : Int = 0) { override fun toString() ="Point(x=$x, y=$y)" operator fun plus (other: Point) = Point(x + other.x, y + other.y) operator fun minus(other: Point) = Point(x - other.x, y - other.y) operator fun unaryMinus() = Point(-x, -y) override fun equals(other: Any?) = when { this === other -> true other !is Point -> false x != other.x -> false else -> y == other.y } } val p = Point(15, 25) val q = Point(20, 30) print( """ p => $p p.x => ${p.x}, p.y => ${p.y} q => $q p.plus(q) => ${p.plus(q)} p + q => ${p + q} 12 + 5 => ${12 + 5} 12.plus(5) => ${12.plus(5)} ---- p - q => ${p - q} -p => ${-p} p == q => ${p == q} p != q => ${p != q} p == Point(15,25) => ${p == Point(15,25)} p != Point(15,25) => ${p != Point(15,25)} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> p => Point(x=15, y=25) p.x => 15, p.y => 25 q => Point(x=20, y=30) p.plus(q) => Point(x=35, y=55) p + q => Point(x=35, y=55) 12 + 5 => 17 12.plus(5) => 17 ---- p - q => Point(x=-5, y=-5) -p => Point(x=-15, y=-25) p == q => false p != q => true p == Point(15,25) => true p != Point(15,25) => false </syntaxhighlight> 演算子は、もちろん加算だけではありません。 :{| class="wikitable" style="float:left" |+ 単項演算子 ! 式 ! メソッド形式 |- |<code>+a</code> |<code>a.unaryPlus()</code> |- |<code>-a</code> |<code>a.unaryMinus()</code> |- |<code>!a</code> |<code>a.not()</code> |- |<code>a++</code> |<code>a.inc()</code> |- |<code>a--</code> |<code>a.dec()</code> |} :{| class="wikitable" style="float:left" |+ 算術演算 ! 式 ! メソッド形式 |- |<code>a + b</code> |<code>a.plus(b)</code> |- |<code>a - b</code> |<code>a.minus(b)</code> |- |<code>a * b</code> |<code>a.times(b)</code> |- |<code>a / b</code> |<code>a.div(b)</code> |- |<code>a % b</code> |<code>a.rem(b)</code> |- |<code>a..b</code> |<code>a.rangeTo(b)</code> |- |<code>a..<b</code> |<code>a.rangeUntil(b)</code> |} :{| class="wikitable" style="float:left" |+ 包含 ! 式 ! メソッド形式 |- |<code>a in b</code> |<code>b.contains(a)</code> |- |<code>a !in b</code> |<code>!b.contains(a)</code> |} :{| class="wikitable" style="float:left" |+ インデックスによる要素参照 ! 式 ! メソッド形式 |- |<code>a[i]</code> |<code>a.get(i)</code> |- |<code>a[i, j]</code> |<code>a.get(i, j)</code> |- |<code>a[i_1, ..., i_n]</code> |<code>a.get(i_1, ..., i_n)</code> |- |<code>a[i] = b</code> |<code>a.set(i, b)</code> |- |<code>a[i, j] = b</code> |<code>a.set(i, j, b)</code> |- |<code>a[i_1, ..., i_n] = b</code> |<code>a.set(i_1, ..., i_n, b)</code> |} :{| class="wikitable" style="float:left" |+ 関数的な呼出し ! 式 ! メソッド形式 |- |<code>a()</code> |<code>a.invoke()</code> |- |<code>a(i)</code> |<code>a.invoke(i)</code> |- |<code>a(i, j)</code> |<code>a.invoke(i, j)</code> |- |<code>a(i_1, ..., i_n)</code> |<code>a.invoke(i_1, ..., i_n)</code> |} :{| class="wikitable" style="float:left" |+ 代入演算 ! 式 ! メソッド形式 |- |<code>a += b</code> |<code>a.plusAssign(b)</code> |- |<code>a -= b</code> |<code>a.minusAssign(b)</code> |- |<code>a *= b</code> |<code>a.timesAssign(b)</code> |- |<code>a /= b</code> |<code>a.divAssign(b)</code> |- |<code>a %= b</code> |<code>a.remAssign(b)</code> |} :{| class="wikitable" style="float:left" |+ 一致・不一致 ! 式 ! メソッド形式 |- |<code>a == b</code> |<code>a?.equals(b) ?: (b === null)</code> |- |<code>a != b</code> |<code>!(a?.equals(b) ?: (b === null))</code> |} :{| class="wikitable" style="float:left" |+ 比較演算 ! 式 ! メソッド形式 |- |<code>a > b</code> |<code>a.compareTo(b) > 0</code> |- |<code>a < b</code> |<code>a.compareTo(b) < 0</code> |- |<code>a >= b</code> |<code>a.compareTo(b) >= 0</code> |- |<code>a <= b</code> |<code>a.compareTo(b) <= 0</code> |} <br style="clear:both"> {{:Kotlin/制御構造}} {{:Kotlin/関数}} == 拡張 == Kotlinでは、クラスやインターフェースを継承したり、Decoratorのようなデザインパターンを使わずに、新しい機能を拡張することができます。これは、拡張( ''extensions'' )と呼ばれる特別な宣言によって実現されます<ref>[https://kotlinlang.org/docs/extensions.html Extensions]</ref>。 === 拡張関数 === 拡張関数( ''Extension functions'' )を宣言するには、その名前の前に拡張される型を示すレシーバー型をつけます<ref>[https://kotlinlang.org/docs/extensions.html#extension-functions Extension functions]</ref>。以下は、Array<Int>にrotate関数を追加したものです。 ;[https://pl.kotl.in/FiS-uHjPC Array<Int>にrotate()を定義]:<syntaxhighlight lang=kotlin line highlight=2 copy> fun main() { fun Array<Int>.rotate() { val t = this[0] var i = 1 while (i < this.size) { this[i - 1] = this[i] i++ } this[this.size - 1] = t } var ary = arrayOf(2, 3, 5, 7, 11) println("ary = ${ary.map{it.toString()}.joinToString(" ")}") ary.rotate() println("ary = ${ary.map{it.toString()}.joinToString(" ")}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary = 2 3 5 7 11 ary = 3 5 7 11 2 </syntaxhighlight> === ジェネリックスと拡張関数 === 拡張関数でも[[#ジェネリックス|ジェネリックス]](型パラメーター)が使用可能です。 先の例は、Array<Int>とIntのアレイ専用でしたが、任意の型 T のアレイ Array<T> に拡張関数を拡張してみましょう。 ;[https://pl.kotl.in/P4tm3lb8h <T>Array<T>にrotate()を定義]:<syntaxhighlight lang=kotlin line highlight=2 copy> fun main() { fun <T> Array<T>.rotate() { val t = this[0] var i = 1 while (i < this.size) { this[i - 1] = this[i] i++ } this[this.size - 1] = t } var ary = arrayOf(2, 3, 5, 7, 11) println("ary = ${ary.map{it.toString()}.joinToString(" ")}") ary.rotate() println("ary = ${ary.map{it.toString()}.joinToString(" ")}") var fary = Array(8){ val x = 1.0 * it; x * x } println("fary = ${fary.map{it.toString()}.joinToString(" ")}") fary.rotate() println("fary = ${fary.map{it.toString()}.joinToString(" ")}") var sary = arrayOf("A", "B", "C", "D", "E", "F") println("sary = ${sary.map{it.toString()}.joinToString(" ")}") sary.rotate() println("sary = ${sary.map{it.toString()}.joinToString(" ")}") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ary = 2 3 5 7 11 ary = 3 5 7 11 2 fary = 0.0 1.0 4.0 9.0 16.0 25.0 36.0 49.0 fary = 1.0 4.0 9.0 16.0 25.0 36.0 49.0 0.0 sary = A B C D E F sary = B C D E F A </syntaxhighlight> === 拡張は静的に解決されます === 拡張は、一見するとクラスの中に後からメンバー関数を追加しているように見えるかもしれませんが、<code>インスタンス.メソッド(実引数リスト)</code> のパターンに合致する拡張定義があるかを静的に調べ、該当する拡張関数があればそれを呼出すことで実現しています。 このため拡張関数でメンバー関数をオーバーライドすることはできません。 == クラス == {{先頭に戻る}} Kotlinは関数型プログラミング言語であると同時に、クラスベースのオブジェクト指向プログラミング言語です。 クラス( ''class'' )はオブジェクトの設計図であり、インスタンスはその設計図に基づいて作成されます。 === クラス定義 === クラスは、キーワード <code>{{Anchor|class}}</code>を使って定義します。 ;[https://pl.kotl.in/WSxMHFtzA 空のクラスの定義とインスタンス化]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X // クラス定義 fun main() { val x = X() // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X </syntaxhighlight> ;[https://pl.kotl.in/WlVaRbKmX private なプロパティ s を持つクラスの定義]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X constructor(s: String) // クラス定義 fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 // x.s --- Unresolved reference: s ;; s は private なので、ここでは参照できません } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X </syntaxhighlight> : <syntaxhighlight lang=kotlin inline>class X constructor(s: String)</syntaxhighlight> : この文脈での[[#ソフト・キーワード|ソフト・キーワード]] {{Anchor|constructor}} は、以下のように省略可能です。 : <syntaxhighlight lang=kotlin inline>class X(s: String)</syntaxhighlight> ;[https://pl.kotl.in/R7Fzx9K3G public でイミュータブルなプロパティ s を持つクラスの定義]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X(val s: String) // クラス定義 fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 println("x.s = ${x.s}") // プロパティーの値を表示 // x.s = "xyz" --- Val cannot be reassigned ;; イミュータブルなプロパティーは書換え不可 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X x.s = abc </syntaxhighlight> : プロパティーの値の参照はできますが、<code>val</code> なので書換えはできません。 ;[https://pl.kotl.in/sAHYBVMIM public でミュータブルなプロパティ s を持つクラスの定義]:<syntaxhighlight lang=kotlin line highlight="1,4" copy> class X(var s: String) // クラス定義 fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 println("x.s = ${x.s}") // プロパティーの値を表示 x.s = "xyz" // イミュータブルなプロパティーは値の書換えが可能 println("x.s = ${x.s}") // プロパティーの値を表示 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> X x.s = abc x.s = xyz </syntaxhighlight> : コンストラクターのパラメーターを <code>val</code> から <code>val</code> に変更したので、ミュータブルとなりプロパティーの値を変更できるようになりました。 ;[https://pl.kotl.in/IODi_0xMo init はコンストラクターの後に呼出されるブロック]:<syntaxhighlight lang=kotlin line highlight="1-3" copy> class X(var s: String) { // クラス定義 init { println("init: s = ${s}") } } fun main() { val x = X("abc") // インスタンス化 println("${x::class.simpleName}") // クラス名を表示 println("x.s = ${x.s}") // プロパティーの値を表示 x.s = "xyz" // イミュータブルなプロパティーは値の書換えが可能 println("x.s = ${x.s}") // プロパティーの値を表示 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> init: s = abc X x.s = abc x.s = xyz </syntaxhighlight> : クラス定義冒頭のコンストラクターにはコードをかけないので init ブロックに書きます === クラスのメンバー === * [[#コンストラクター|コンストラクター]]( ''constructor'' ) * [[#メンバー関数|メンバー関数]] * [[#プロパティー|プロパティー]] * [[#インナークラス|インナークラス]]( ''inner class'' ) * [[#オブジェクト|オブジェクト]]の宣言 ==== コンストラクター ==== Kotlinのクラスはプライマリーコンストラクターと1つまたは複数のセカンダリーコンストラクターを持つことができます。プライマリーコンストラクターはクラスヘッダの一部で、クラス名とオプションの型パラメターの後に続きます。 {{See also|クラス定義}} ==== メンバー関数 ==== メンバー関数は、クラス定義の中で定義された関数です<ref>[https://kotlinlang.org/docs/functions.html#member-functions Member functions]</ref>。 メンバー関数の呼出はドット記法で行います。 メンバー関数からは、プライベートなクラスのメンバーにアクセスできます。 ==== プロパティ ==== ==== オブジェクト ==== オブジェクトは、匿名クラスの定義とインスタンス化を同時に行うものです。 ;[https://paiza.io/projects/HRaRjZqiJz8DxWz3gh_mEg?language=kotlin オブジェクトの例]:<syntaxhighlight lang=kotlin line copy> fun main() { var obj = object { var a = 3 var b = 4 override fun toString() = "($a, $b)" } println( """ obj => $obj obj.a => ${obj.a}, obj.b => ${obj.b} obj::class.simpleName => ${obj::class.simpleName} """ ) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> obj => (3, 4) obj.a => 3, obj.b => 4 obj::class.simpleName => null </syntaxhighlight> === 継承 === クラスは、明示的に継承元を指定しない場合は <code>Any</code> を継承します。 === 継承モディファイア === 継承モディファイア( ''inheritance modifier'' )には、次のような種類があり、これらのトークンは[[#モディファイア・キーワード|モディファイア・キーワード]]です。 ==== abstract ==== [[#抽象クラス|抽象クラス]]( ''abstract class'' )は、抽象メンバー関数( ''abstract method'' )だけを持つクラスです。 モディファイア・キーワード <code>abstract</code> は、抽象メンバー関数の定義でも使われます。 ==== final ==== [[#ファイナルクラス|ファイナルクラス]]( ''final class'' )は、継承を禁止したクラスです。 KotlinのクラスはJavaと異なり、ディフォルトで継承禁止なので、継承禁止を強調する意味しかありません。 モディファイア・キーワード <code>final</code> は、オーバーライド禁止メンバーの宣言でも使われます。 ==== open ==== [[#オープンクラス|オープンクラス]]( ''open class'' )は、継承を許可したクラスです。 KotlinのクラスはJavaと異なり、ディフォルトで継承禁止なので、継承を行う可能性がある場合は明示的に許可する必要があります。 モディファイア・キーワード <code>open</code> は、メンバー関数のオーバーライド許可でも使われます。 {{コラム|Kotlinのクラスはディフォルトでfinal|2= Javaと異なり、Kotlinのクラスはディフォルトでfinal(継承禁止)です。 これは、主にセキュリティー上の理由からで、クラスを継承することによりprotectedでの隠蔽に綻びが生じプログラムが「ハイジャック」されることの重要さに配慮したもので、 クラス設計に於いてのトレードオフ、「拡張性と頑強性」のディフォルトを頑強に振った言語設計になっています。 {{See also|[https://www.jpcert.or.jp/java-rules/obj00-j.html OBJ00-J. 不変条件を持つクラスやメソッドの拡張は信頼できるサブクラスのみに許す]}} }} === this === クラスのメンバー関数が、プロパティやメンバー関数を参照するとき、クラスの外の変数や関数との間で曖昧さが生じる事があります。 このようなときには、インスタンスを表すキーワード <code>{{Anchor|this}}</code> を使います<ref>[https://kotlinlang.org/docs/this-expressions.html This expressions]</ref>。 <code>this</code> はこのほか、2 次コンストラクタから同じクラスの別のコンストラクタを呼出すときにもつかわれます。 ;[https://paiza.io/projects/a6IABje1M-ZOPH4asPyCpQ?language=kotlin thisを使ったメンバー関数の限定]:<syntaxhighlight lang=kotlin line copy> fun main() { fun printLine() = println("Function") class Simple { fun printLine() = println("Method") fun printLineNone() = printLine() fun printLineThis() = this.printLine() } val s = Simple() s.printLine() s.printLineNone() s.printLineThis() } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Method Function Method </syntaxhighlight> : メンバー関数から同じクラスのメンバー関数を呼出すとき、同名の関数があると関数が呼出されます。 : メンバー関数から同じクラスのメンバー関数を呼出すときには、同名の関数があると関数が呼出されます。 === クラスモディファイア === クラスモディファイア( ''class modifier'' )には、次のような種類があり、これらのトークンは[[#モディファイア・キーワード|モディファイア・キーワード]]です。 ==== enum ==== [[#列挙型クラス|列挙型クラス]]( ''Enum class'' )は、有限個の識別子の集合を表現するために使用されます。 :<syntaxhighlight lang=kotlin copy> enum class DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY } fun main() { val today = DayOfWeek.MONDAY println("Today is $today") } </syntaxhighlight> ;特性と用途 * 特定の値の集合を表現するために使用されます(例: 曜日、状態など)。 * 定数のような振る舞いを持ち、列挙型の各要素は固定された値として使用されます。 ==== sealed ==== シールドクラス( ''Sealed class'' )は、制限されたクラス階層を表現するために使用されます。 :<syntaxhighlight lang=kotlin copy> sealed class Result { data class Success(val data: String) : Result() data class Error(val message: String) : Result() } fun handleResult(result: Result) { when (result) { is Result.Success -> println("Success: ${result.data}") is Result.Error -> println("Error: ${result.message}") } } fun main() { val successResult = Result.Success("Data") val errorResult = Result.Error("An error occurred") handleResult(successResult) handleResult(errorResult) } </syntaxhighlight> ;特性と用途 * 制限されたクラス階層を定義するために使用されます。サブクラスは通常、シールドクラス内にネストされます。 * シールドクラスのサブクラスは通常、特定の型の状態や結果を表現するために使用されます。 ==== annotation ==== [[#アノテーションクラス|アノテーションクラス]]( ''annotation class'' )は、コードにメタデータを付加するための手段を提供します。 :<syntaxhighlight lang=kotlin copy> annotation class Author(val name: String) @Author("John Doe") class Book { // ブックの定義 } fun main() { val book = Book::class.java val authorAnnotation = book.getAnnotation(Author::class.java) val authorName = authorAnnotation?.name println("Author: $authorName") } </syntaxhighlight> ;特性と用途 * コードに追加情報や設定を提供するために使用されます。 * ランタイムやコンパイル時にアノテーションを処理することで、特定の動作やコード生成をトリガーすることができます。 ==== data ==== [[#データクラス|データクラス]]( ''Data class'' )は、データを保持するためのクラスで、copy() などのメンバー関数がクラスを定義しただけで生えてきます。 :<syntaxhighlight lang=kotlin copy> data class Person(val name: String, val age: Int) fun main() { val person = Person("Alice", 25) val copyPerson = person.copy(age = 30) println(person) println(copyPerson) } </syntaxhighlight> ;特性と用途 * データのコンテナとして使用され、自動的にequals()、hashCode()、toString()、copy()メソッドが生成されます。 * イミュータブルなデータオブジェクトを簡潔に表現するために使用されます。 ==== inner ==== [[#インナークラス|インナークラス]]( ''Inner class'' )は、入れ子になった内側になったクラスが外側のクラスのメンバーにアクセスすることを可能にします。 :<syntaxhighlight lang=kotlin copy> class Outer { private val outerProperty = "Outer Property" inner class Inner { fun printOuterProperty() { println(outerProperty) } } } fun main() { val outer = Outer() val inner = outer.Inner() inner.printOuterProperty() } </syntaxhighlight> ;特性と用途 * 外側のクラスのインスタンスに紐づく内側のクラスを定義するために使用されます。 * 内側のクラスは外側のクラスの非公開メンバーやプロパティにアクセスすることができます。 ==== value ==== [[#値クラス|値クラス]]( ''Value class'' )は、イミュータブルなスカラー値の型を定義します。プロポーザル段階では inline class と呼ばれていました。 :<syntaxhighlight lang=kotlin copy> inline class Password(val value: String) fun main() { val password = Password("secret") println("Password: ${password.value}") } </syntaxhighlight> ;特性と用途 * 単一の値を表すために使用されます。プリミティブ型のように振る舞い、ボックス化のオーバーヘッドを回避します。 + ラッパークラスとして機能し、型安全性やコードの表現力を向上させます。 ==== object ==== [[#オブジェクト|オブジェクト]]( ''object'' )は、モディファイア・キーワードではありませんが、特殊なクラスの一種なので併せて紹介します。 オブジェクトは一過的な匿名クラスを定義し、そのインスタンスの生成を行います。 :<syntaxhighlight lang=kotlin copy> object Logger { fun log(message: String) { println("Log: $message") } } fun main() { Logger.log("Hello, World!") } </syntaxhighlight> ;特性と用途 * シングルトンパターンを実装するために使用されます。クラスの単一のインスタンスを表現し、グローバルなアクセスポイントとして機能します。 * 関連するメソッドやプロパティを含めることができ、特定の目的に特化したオブジェクトを表現することができます。 ;まとめ 各クラスモディファイアは、異なる用途や特性を持っており、柔軟なクラス定義を可能にします。 適切なモディファイアを選択することで、コードの意図を明確に表現し、保守性や可読性を向上させることができます。 === 可視性モディファイア === [[#クラス|クラス]]、[[#オブジェクト|オブジェクト]]、[[#インターフェース|インターフェース]]、[[#コンストラクター|コンストラクター]]、[[#関数|関数]]、および[[#プロパティ|プロパティ]]とその[[#セッター|セッター]]は、可視性モディファイア( ''Visibility modifiers'' )を持つことができます。ゲッターは常にそのプロパティと同じ可視性を持っています<ref>[https://kotlinlang.org/docs/visibility-modifiers.html Visibility modifiers]</ref>。 可視性モディファイアには、次のような4種類があり、これらのトークンは[[#モディファイア・キーワード|モディファイア・キーワード]]です。 * [[#private|private]] * [[#protected|protected]] * [[#internal|internal]] * [[#public|public]] デフォルトの可視性はpublicです。 ==== パッケージ ==== 関数、プロパティ、クラス、オブジェクト、およびインタフェースは、パッケージの中で直接「トップレベル」で宣言することができます。 * 可視性モディファイアを使用しない場合、デフォルトではpublicが使用され、宣言はどこでも見えるようになります。 * 宣言に private を指定すると、その宣言を含むファイル内でのみ可視化されます。 * internalと指定した場合は、同じモジュール内であればどこでも見えるようになります。 * protected修飾子は、トップレベルの宣言には使えません。 ==== クラスのメンバー ==== クラス内部で宣言されたメンバー。 * private は、そのメンバーがこのクラスの内部でのみ可視であることを意味します(そのクラスのすべてのメンバーを含む)。 * protected は、private とマークされたメンバーと同じ可視性を持ちますが、サブクラスでも可視化されることを意味します。 * internal は、宣言したクラスを見たこのモジュール内のクライアントが、その内部のメンバーを見ることができることを意味します。 * public は、宣言クラスを見たすべてのクライアントがその public メンバを見ることができることを意味します。 protectedまたはinternalメンバーをオーバーライド( ''override'' )し、可視性を明示的に指定しない場合、オーバーライドしたメンバーも元のメンバーと同じ可視性を持つことになります。 ===== コンストラクター ===== クラスの一次コンストラクタの可視性を指定するには、次の構文を使用します。 :<syntaxhighlight lang=kotlin copy> class C private constructor(a: Int) { ... } </syntaxhighlight> :ここでは、コンストラクターは private です。デフォルトでは、すべてのコンストラクターは public です。これは、クラスが見えるところならどこでもコンストラクターが見えるということです(裏を返せば、内部クラスのコンストラクターは同じモジュール内でしか見えないということです)。 ===== ローカル宣言 ===== ローカル変数、関数、クラスは可視性モディファイアを持つことができません。 ==== モジュール ==== internal 可視性モディファイアは、そのメンバーが同じモジュール内で可視であることを意味します。具体的にモジュールとは、例えば、一緒にコンパイルされたKotlinファイルの集合のことです。 * IntelliJ IDEAモジュール。 * Mavenプロジェクト * Gradleのソースセット(ただし、testのソースセットはmainの内部宣言にアクセスできる)。 * ''kotlinc'' Antタスクの1回の呼び出しでコンパイルされるファイル群。 === 抽象クラス === 抽象クラス( ''abstract class'' )は、抽象メソッド( ''abstract method'' )だけを持つクラスであり、直接のインスタンス化ができません。抽象メソッドは本体を持たず、具体的な実装はそのサブクラスに委ねられます。Kotlinでは、<code>abstract</code> キーワードを使用して抽象クラスと抽象メソッドを宣言します。 ==== 抽象クラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> abstract class Shape { abstract fun draw() } class Circle : Shape() { override fun draw() { println("Drawing a circle") } } class Rectangle : Shape() { override fun draw() { println("Drawing a rectangle") } } </syntaxhighlight> 上記の例では、<code>Shape</code> という抽象クラスがあります。このクラスは抽象メソッド <code>draw</code> を宣言しています。サブクラスである <code>Circle</code> と <code>Rectangle</code> は、それぞれ <code>draw</code> メソッドをオーバーライドして具体的な実装を提供します。 ==== 抽象クラスのインスタンス化 ==== :<syntaxhighlight lang=kotlin copy> fun main() { // コンパイルエラー: Cannot create an instance of an abstract class // val shape = Shape() val circle = Circle() circle.draw() val rectangle = Rectangle() rectangle.draw() } </syntaxhighlight> 抽象クラスは直接インスタンス化できないため、<code>Shape</code> クラスのインスタンスを作成しようとするとコンパイルエラーが発生します。代わりに、具象サブクラスである <code>Circle</code> や <code>Rectangle</code> のインスタンスを作成して使用します。 ==== 抽象プロパティとコンストラクタ ==== 抽象クラスは抽象プロパティを持つこともできます。また、抽象クラス自体はコンストラクタを持つことができます。 :<syntaxhighlight lang=kotlin copy> abstract class Shape(val name: String) { abstract fun draw() } class Circle(name: String) : Shape(name) { override fun draw() { println("Drawing a circle named $name") } } class Rectangle(name: String) : Shape(name) { override fun draw() { println("Drawing a rectangle named $name") } } </syntaxhighlight> この例では、<code>Shape</code> クラスはコンストラクタを持ち、<code>name</code> という抽象プロパティを宣言しています。サブクラスである <code>Circle</code> と <code>Rectangle</code> は、コンストラクタで <code>name</code> を渡し、<code>draw</code> メソッドをオーバーライドしています。 抽象クラスは、クラス階層の一部として柔軟で再利用可能なコードを設計する際に役立ちます。 ==== ユースケースとベストプラクティス ==== 抽象クラスは、以下のようなユースケースやベストプラクティスに適しています。 ;部分的な実装の提供: 抽象クラスは、一部のメソッドやプロパティの実装を提供することができます。これにより、サブクラスは抽象メソッドだけでなく、既存の実装を再利用できます。 :<syntaxhighlight lang=kotlin copy> abstract class Shape { fun commonMethod() { // 共通の実装 } abstract fun draw() } </syntaxhighlight> ;メソッドの強制: 抽象クラスには抽象メソッドが含まれており、これをサブクラスで実装することが義務付けられます。これにより、サブクラスが特定のメソッドを実装することが保証されます。 :<syntaxhighlight lang=kotlin copy> abstract class Printer { abstract fun print() } class LaserPrinter : Printer() { override fun print() { // レーザープリンターの実装 } } </syntaxhighlight> ;継承と拡張: 抽象クラスを使用すると、クラス階層を構築し、新しい機能を追加していくことができます。これは、将来的に変更や拡張が発生する可能性がある場合に特に役立ちます。 :<syntaxhighlight lang=kotlin copy> abstract class Animal { abstract fun makeSound() } class Dog : Animal() { override fun makeSound() { println("Woof!") } } class Cat : Animal() { override fun makeSound() { println("Meow!") } </syntaxhighlight> ;コンストラクタとプロパティ: 抽象クラスはコンストラクタを持ち、抽象プロパティを宣言できます。これにより、サブクラスが特定のプロパティを持つことが保証され、コンストラクタで初期化できます。 :<syntaxhighlight lang=kotlin copy> abstract class Vehicle(val model: String) { abstract fun start() abstract fun stop() } class Car(model: String) : Vehicle(model) { override fun start() { println("Starting the car") } override fun stop() { println("Stopping the car") } } </syntaxhighlight> ;複数のインターフェースの代替: 抽象クラスは複数のメソッドやプロパティをまとめて提供できるため、インターフェースが多すぎる場合に、抽象クラスを使用して階層を整理することができます。 :<syntaxhighlight lang=kotlin copy> abstract class UIControl { abstract fun render() abstract fun onClick() } class Button : UIControl() { override fun render() { println("Rendering button") } override fun onClick() { println("Button clicked") } } </syntaxhighlight> 抽象クラスは、柔軟性と再利用性を向上させるために使われますが、適切に設計される必要があります。必要以上に多くの機能を含めると、過度な依存関係が生まれる可能性があるため、慎重な設計が求められます。 === ファイナルクラス === ファイナルクラス(<code>final class</code>)は、Kotlinにおいて継承を禁止したクラスを指します。Kotlinでは、デフォルトでクラスが継承不可(<code>final</code>)となっており、継承可能にするためには明示的に<code>open</code>修飾子を使用する必要があります。そのため、<code>final</code>キーワードは主にオーバーライド禁止メンバーの宣言で使用され、クラス自体に適用することは少ないです。 ==== ファイナルクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> final class MyFinalClass { // クラスの定義 } </syntaxhighlight> 上記の例では、<code>MyFinalClass</code> はファイナルクラスとして宣言されています。このクラスは他のクラスから継承できません。 ==== オーバーライド禁止メンバーの宣言 ==== :<syntaxhighlight lang=kotlin copy> open class MyBaseClass { final fun myFinalMethod() { // オーバーライド禁止のメソッド } } </syntaxhighlight> 上記の例では、<code>MyBaseClass</code> の <code>myFinalMethod</code> は <code>final</code> 修飾子が付いており、このメソッドはオーバーライドできません。 ==== ファイナルクラスの利用例 ==== :<syntaxhighlight lang=kotlin copy> final class Configuration { // クラスの定義 } class ApplicationSettings(config: Configuration) { // FinalClass を利用したクラスの定義 } </syntaxhighlight> 上記の例では、<code>Configuration</code> クラスがファイナルクラスとして定義されています。このクラスは他のクラスから継承できないため、設定情報の不正な変更や上書きを防ぐことが期待されます。<code>ApplicationSettings</code> クラスは <code>Configuration</code> を利用してアプリケーションの設定を管理しています。 ファイナルクラスは特定の状況で利用され、継承を禁止してクラスの拡張を制御するために使用されます。 === オープンクラス === オープンクラス(<code>open class</code>)は、Kotlinにおいて継承を許可したクラスを指します。 Kotlinのクラスはデフォルトで継承不可(<code>final</code>)となっているため、クラスを継承可能にするには明示的に<code>open</code>修飾子を使用する必要があります。 ==== オープンクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> open class MyOpenClass { // クラスの定義 } </syntaxhighlight> 上記の例では、<code>MyOpenClass</code> はオープンクラスとして宣言されています。このクラスは他のクラスから継承できます。 ==== メソッドのオーバーライド許可 ==== :<syntaxhighlight lang=kotlin copy> open class MyBaseClass { open fun myMethod() { // オーバーライド可能なメソッド } } </syntaxhighlight> 上記の例では、<code>MyBaseClass</code> の <code>myMethod</code> は <code>open</code> 修飾子が付いており、このメソッドはオーバーライド可能です。 ==== オープンクラスの利用例 ==== :<syntaxhighlight lang=kotlin copy> open class Shape { open fun draw() { println("Drawing a shape") } } class Circle : Shape() { override fun draw() { println("Drawing a circle") } } class Square : Shape() { override fun draw() { println("Drawing a square") } } </syntaxhighlight> 上記の例では、<code>Shape</code> クラスがオープンクラスとして定義されています。<code>Circle</code> と <code>Square</code> クラスが <code>Shape</code> を継承し、<code>draw</code> メソッドをオーバーライドしています。これにより、各図形クラスは自身の特定の描画方法を持つことができます。 オープンクラスは継承を許可し、クラスの拡張やカスタマイズが可能となります。ただし、使用する際には慎重に設計し、必要なメソッドやプロパティに対してのみ<code>open</code>修飾子を使用することが推奨されます。 === 列挙型クラス === {{先頭に戻る}} 列挙型クラス( ''Enum classes'' )は、キーワード <code>enum</code> を <code>class</code> に前置して定義します<ref>[https://kotlinlang.org/docs/enum-classes.html Enum classes]</ref>。 [[Swift/オブジェクト指向#列挙型]]の例を Kotlin 向けにモディファイしました。 ;[https://paiza.io/projects/lW6ghepnPWyQnctPdyX6Zw?language=kotlin 列挙型クラスとメソッド]:<syntaxhighlight lang=kotlin line copy> enum class Azimuth { North, South, East, West; override fun toString() = when (this) { Azimuth.North -> "北" Azimuth.South -> "南" Azimuth.East -> "東" Azimuth.West -> "西" } fun deg() = when (this) { Azimuth.North -> 0 * 90 Azimuth.South -> 2 * 90 Azimuth.East -> 1 * 90 Azimuth.West -> 3 * 90 } } fun main() { val n = Azimuth.North println("n => $n, az.deg() => ${n.deg()}") println("------------------------------------") for (az in Azimuth.values()) { println("as.name =>${az.name}, as => $az, az.deg() => ${az.deg()}") } println(enumValues<Azimuth>().joinToString{it.name}) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> n => 北, az.deg() => 0 ------------------------------------ as.name =>North, as => 北, az.deg() => 0 as.name =>South, as => 南, az.deg() => 180 as.name =>East, as => 東, az.deg() => 90 as.name =>West, as => 西, az.deg() => 270 North, South, East, West </syntaxhighlight> : override fun toString() でEnumのディフォルトの文字列化メソッドをオーバーライドしています。 === シールドクラス === シールドクラス(<code>Sealed class</code>)は、制限されたクラス階層を表現するために使用される Kotlin 特有の機能です。シールドクラスは、特定のサブクラスのみを許容し、新しいサブクラスの追加を防ぎます。これにより、特定の型に対するパターンマッチングが容易になります。 ==== シールドクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> sealed class Result { data class Success(val data: String) : Result() data class Error(val message: String) : Result() object Loading : Result() } </syntaxhighlight> 上記の例では、<code>Result</code> クラスはシールドクラスとして宣言されています。このクラスには3つのサブクラスがあります:<code>Success</code>、<code>Error</code>、および <code>Loading</code>。<code>Success</code> と <code>Error</code> はデータクラスで、それぞれデータを保持します。<code>Loading</code> はオブジェクトクラスで、データを保持しません。 ==== シールドクラスの利用例 ==== :<syntaxhighlight lang=kotlin copy> fun processResult(result: Result) { when (result) { is Result.Success -> println("Success: ${result.data}") is Result.Error -> println("Error: ${result.message}") Result.Loading -> println("Loading...") } } </syntaxhighlight> 上記の例では、<code>Result</code> クラスのサブクラスごとに異なる処理を行う <code>processResult</code> 関数があります。<code>when</code> 式を使用して、特定のサブクラスに対するパターンマッチングを行っています。 ==== 利点 ==== * コンパイラがすべてのサブクラスを知っているため、<code>when</code> 式などのパターンマッチングが網羅的であることを確認できます。 * 新しいサブクラスが追加された場合、コンパイラは未処理のケースがあるかどうかを検知し、警告を発生させます。 ==== 制限 ==== * シールドクラスは同じファイル内で宣言されたクラスに対してしか有効ではありません。 シールドクラスは、特に固定されたクラス階層を表現する場合や、特定の型に対する安全なパターンマッチングを行う場合に便利です。 === アノテーションクラス === アノテーションクラス(<code>annotation class</code>)は、Kotlinにおいてコードにメタデータを付加するための手段を提供します。これにより、コンパイラや実行時の処理で追加の情報を提供することが可能となります。 ==== アノテーションクラスの宣言 ==== アノテーションクラスは、<code>@</code>シンボルを使って宣言されます。アノテーションクラスの主な目的は、アノテーションを作成し、それをコードの要素に適用することです。 :<syntaxhighlight lang=kotlin copy> annotation class MyAnnotation(val name: String, val version: Int) </syntaxhighlight> 上記の例では、<code>MyAnnotation</code> というアノテーションクラスが宣言されています。このアノテーションは、<code>name</code> と <code>version</code> というパラメータを持っています。 ==== アノテーションの利用 ==== アノテーションは、クラスや関数、プロパティなど、さまざまな要素に適用できます。 :<syntaxhighlight lang=kotlin copy> @MyAnnotation(name = "MyApp", version = 1) class MyClass { @MyAnnotation(name = "MyFunction", version = 2) fun myFunction() { // 関数の本体 } } </syntaxhighlight> 上記の例では、<code>MyClass</code> クラスとその中の <code>myFunction</code> 関数に <code>MyAnnotation</code> が適用されています。これにより、このクラスや関数に対する追加のメタデータが提供されます。 ==== アノテーションのプロセッシング ==== アノテーションをプロセッシングするためには、リフレクションやKotlinのアノテーションプロセッサを使用することがあります。これにより、アノテーションに関連する処理を行うカスタムロジックを実装できます。 :<syntaxhighlight lang=kotlin copy> // アノテーションプロセッサの例 fun processMyAnnotation(element: AnnotatedElement) { val myAnnotation = element.getAnnotation(MyAnnotation::class.java) if (myAnnotation != null) { println("Name: ${myAnnotation.name}, Version: ${myAnnotation.version}") } } </syntaxhighlight> 上記の例では、<code>AnnotatedElement</code>を受け取り、その要素に <code>MyAnnotation</code> が適用されているかを調べ、情報を取得しています。 アノテーションクラスは、コードにメタデータを追加し、プロセッシングや設定などの目的で使用されます。 === データクラス === データクラス(<code>Data class</code>)は、Kotlinにおいてデータの保持や操作を目的としたクラスで、<code>copy()</code> メソッドなどがクラスを定義するだけで自動的に生成されます。これにより、不変性やイミュータビリティ(immutable)を維持しながら、簡潔で効果的なデータクラスを作成できます。 ==== データクラスの宣言 ==== :<syntaxhighlight lang=kotlin copy> data class Person(val name: String, val age: Int) </syntaxhighlight> 上記の例では、<code>Person</code> クラスがデータクラスとして宣言されています。コンストラクタで定義されたプロパティ(<code>name</code> と <code>age</code>)に対して、<code>equals()</code>、<code>hashCode()</code>、<code>toString()</code> などの標準メソッドが自動的に生成されます。 ==== データクラスの利用 ==== :<syntaxhighlight lang=kotlin copy> val person1 = Person("Alice", 30) val person2 = Person("Alice", 30) // equals() メソッドにより、プロパティの内容が一致するか比較 println(person1 == person2) // true // toString() メソッドにより、クラスの内容を文字列として表示 println(person1.toString()) // Person(name=Alice, age=30) // copy() メソッドにより、一部のプロパティを変更した新しいインスタンスを作成 val modifiedPerson = person1.copy(age = 31) println(modifiedPerson) // Person(name=Alice, age=31) </syntaxhighlight> 上記の例では、<code>equals()</code> メソッドにより <code>person1</code> と <code>person2</code> の内容が一致するか比較され、<code>toString()</code> メソッドによりクラスの内容が文字列として表示されます。また、<code>copy()</code> メソッドを使って一部のプロパティを変更した新しいインスタンスを作成しています。 ==== データクラスの生成されるメソッド ==== データクラスが生成される主なメソッドは以下の通りです。 * <code>equals()</code>: プロパティごとの内容比較を行います。 * <code>hashCode()</code>: プロパティごとにハッシュコードを生成します。 * <code>toString()</code>: クラスの内容を文字列として返します。 * <code>copy()</code>: インスタンスのコピーを作成します。一部のプロパティを変更できます。 データクラスは、イミュータブルでありながら効果的にデータを操作するための便利な手段を提供します。 === インターフェース === Kotlinのインターフェース(<code>interface</code>)は、抽象的なメソッドの宣言と、メソッドの実装を含むことができます。インターフェースは、抽象クラスと異なり状態を保持することができません。プロパティを持つ場合、これらは抽象クラスであるか、アクセサーの実装を提供する必要があります<ref>[https://kotlinlang.org/docs/interfaces.html Interfaces]</ref>。 ==== インターフェースの宣言 ==== :<syntaxhighlight lang=kotlin copy> interface MyInterface { fun doSomething() // 抽象メソッドの宣言 fun doSomethingElse() { // デフォルトのメソッド実装 println("Default implementation of doSomethingElse") } val property: Int // 抽象プロパティの宣言 } </syntaxhighlight> 上記の例では、<code>MyInterface</code> インターフェースが、抽象メソッド <code>doSomething()</code> とデフォルトのメソッド <code>doSomethingElse()</code>、抽象プロパティ <code>property</code> を宣言しています。 ==== インターフェースの実装 ==== :<syntaxhighlight lang=kotlin copy> class MyClass : MyInterface { override fun doSomething() { // メソッドの実装 println("Implementation of doSomething") } override val property: Int get() = 42 // プロパティの実装 } </syntaxhighlight> 上記の例では、<code>MyClass</code> クラスが <code>MyInterface</code> インターフェースを実装しています。<code>doSomething()</code> メソッドと <code>property</code> プロパティをオーバーライドしています。 ==== インターフェースの複数準拠 ==== :<syntaxhighlight lang=kotlin copy> interface A { fun methodA() } interface B { fun methodB() } class C : A, B { override fun methodA() { // A インターフェースの実装 } override fun methodB() { // B インターフェースの実装 } } </syntaxhighlight> 上記の例では、<code>C</code> クラスが <code>A</code> インターフェースと <code>B</code> インターフェースの両方を実装しています。複数のインターフェースをカンマで区切って指定することができます。 ==== インターフェースの継承 ==== :<syntaxhighlight lang=kotlin copy> interface D : A, B { fun methodD() } </syntaxhighlight> 上記の例では、<code>D</code> インターフェースが <code>A</code> インターフェースと <code>B</code> インターフェースを継承しています。これにより、<code>D</code> インターフェースは <code>A</code> と <code>B</code> のメソッドを含むことになります。 Kotlinのインターフェースは、クラスが異なる振る舞いを持つ場合に簡潔で柔軟な解決策を提供します。異なるインターフェースを実装することで、複数の振る舞いを同じクラスで組み合わせることができます。 === インナークラス === インナークラス(<code>Inner class</code>)は、入れ子になった内側のクラスが外側のクラスのメンバーにアクセスすることを可能にします。これにより、外側のクラスと強い結びつきを持ちながら、内部で独自の振る舞いやデータを持つクラスを定義できます。 ==== インナークラスの宣言 ==== <syntaxhighlight lang=kotlin copy> class OuterClass { private val outerProperty: Int = 10 inner class InnerClass { fun printOuterProperty() { // OuterClass のプロパティにアクセス println("Outer property: $outerProperty") } } } </syntaxhighlight> 上記の例では、<code>OuterClass</code> という外側のクラスがあり、その中に <code>InnerClass</code> というインナークラスが定義されています。<code>InnerClass</code> は <code>OuterClass</code> のプロパティにアクセスすることができます。 ==== インナークラスの利用 ==== <syntaxhighlight lang=kotlin copy> fun main() { val outerInstance = OuterClass() val innerInstance = outerInstance.InnerClass() innerInstance.printOuterProperty() } </syntaxhighlight> 上記の例では、<code>OuterClass</code> のインスタンスを作成し、そのインナークラスである <code>InnerClass</code> のインスタンスを取得しています。そして、<code>InnerClass</code> のメソッドを呼び出して外側のクラスのプロパティにアクセスしています。 ==== インナークラスの特徴 ==== # 外部クラスへのアクセス: インナークラスは、外部クラスのメンバーにアクセスできます。外部クラスのプロパティやメソッドに直接アクセスできるため、疎結合な設計が可能です。 # thisキーワードの挙動: インナークラスでは、外部クラスのインスタンスにアクセスするために <code>this@OuterClass</code> のように明示的な指定ができます。これにより、外部クラスのメンバーと同じ名前のメンバーがインナークラス内にある場合に区別できます。 # 非静的なクラス: インナークラスは外部クラスのインスタンスに依存しており、非静的なクラスです。したがって、外部クラスのインスタンスが存在しないとインナークラスも存在しません。 インナークラスは、外部クラスとの緊密な連携が必要な場合や、外部クラスのプライベートなメンバーにアクセスする必要がある場合に有用です。 === 値クラス === 値クラス(<code>data class</code>)は、イミュータブルでスカラーな値の型を定義するための概念です。プロポーザル段階では <code>inline class</code> と呼ばれていました。値クラスは、プリミティブ型のように振る舞い、同時に型安全性を提供します。 ==== 値クラスの宣言 ==== <syntaxhighlight lang=kotlin copy> data class Email(val value: String) </syntaxhighlight> 上記の例では、<code>Email</code> という値クラスが宣言されています。この値クラスは、イミュータブルであり、<code>value</code> というプロパティを持っています。 ==== 値クラスの利用 ==== <syntaxhighlight lang=kotlin copy> fun main() { val email1 = Email("john@example.com") val email2 = Email("jane@example.com") println(email1 == email2) // 値クラスの比較 } </syntaxhighlight> 上記の例では、異なるインスタンスの <code>Email</code> クラスを作成し、その値が等しいかを比較しています。値クラスでは、プライマリコンストラクタの引数で値が確定し、その値に基づいて等価性が判定されます。 ==== 値クラスの特徴 ==== # イミュータブル性: 値クラスは不変(イミュータブル)であるため、一度生成されたインスタンスの値は変更されません。これにより、安全で予測可能なコードを実現します。 # 型安全性: 値クラスは型安全性を提供します。異なる値クラス間は厳密に区別され、混同されることがありません。 # 自動生成メソッド: 値クラスは <code>equals()</code> や <code>hashCode()</code> などのメソッドを自動生成します。これにより、等価性の確認やコレクションの利用が容易になります。 # ボクシングの回避: 値クラスはプリミティブ型のように振る舞い、一部のボクシングを回避します。これにより、メモリ効率が向上します。 値クラスは、ドメインモデリングや特定のデータ型を表現する際に有用であり、プロジェクト全体でのコードの理解性や保守性を向上させる役割を果たします。 === オブジェクト === オブジェクト(<code>object</code>)は、モディファイア・キーワードではありませんが、特殊なクラスの一種であり、一過的な匿名クラスを定義し、その唯一のインスタンスを生成します。オブジェクトはシングルトンのような振る舞いを持ち、一般的には特定の目的に使用されます。 ==== オブジェクトの宣言 ==== <syntaxhighlight lang=kotlin copy> object Logger { fun log(message: String) { println("Log: $message") } } </syntaxhighlight> 上記の例では、<code>Logger</code> という名前のオブジェクトが宣言されています。このオブジェクトはシングルトンであり、<code>log</code> メソッドを持っています。 ==== オブジェクトの利用 ==== <syntaxhighlight lang=kotlin copy> fun main() { Logger.log("This is a log message.") } </syntaxhighlight> 上記の例では、<code>Logger</code> オブジェクトの唯一のインスタンスにアクセスし、その <code>log</code> メソッドを呼び出しています。オブジェクトは初回のアクセス時に遅延初期化され、以降は同じインスタンスが再利用されます。 ==== オブジェクトの特徴 ==== # シングルトンパターン: オブジェクトはシングルトンとして振る舞います。クラスの唯一のインスタンスを持ち、それにアクセスするために新たなインスタンスを生成することはありません。 # 遅延初期化: オブジェクトは初回のアクセス時に初期化されます。これにより、プログラムが実際に必要なときに初期化処理が行われます。 # クラスメンバー: オブジェクトはメソッドやプロパティを持つことができます。これらは通常のクラスメンバーと同じようにアクセスできます。 # 継承不可: オブジェクトは継承できません。そのため、他のクラスがこのオブジェクトを継承することはできません。 オブジェクトは特定のタスクや目的に対して唯一のインスタンスを提供する場合に利用され、例えばロギングや設定の管理などに適しています。 == ジェネリックス == {{先頭に戻る}} ジェネリックス( ''Generics'' )とは、汎用的なクラス・関数やメソッドを特定の型に対応づける機能のことです<ref>[https://kotlinlang.org/docs/generics.html Generics: in, out, where]</ref>。 == キーワード一覧 == {{先頭に戻る}} Kotlinの{{Anchor|キーワード}}( ''Keywords'' )は * [[#ハード・キーワード|ハード・キーワード]] * [[#ソフト・キーワード|ソフト・キーワード]] * [[#モディファイア・キーワード|モディファイア・キーワード]] * [[#特殊識別子|特殊識別子]] * [[#演算子と特殊シンボル|演算子と特殊シンボル]] に分類されます<ref>[https://kotlinlang.org/docs/keyword-reference.html Keywords and operators]</ref>。 === ハード・キーワード === {{先頭に戻る|style=border-top:1px solid gray;}} 以下のトークンは、常にキーワードとして解釈され、識別子として使用することはできません<ref>[https://kotlinlang.org/docs/keyword-reference.html#hard-keywords Hard keywords]</ref>。 このようなキーワードをハード・キーワード( ''Hard keywords'' )と呼びます。 * <code>[[#as|as]]</code> *# 型キャスト( ''type casts'' )に使用されます。 *# インポートの別名の指定に使用されます。 * <code>[[#as?|as?]]</code> 安全なタイプキャスト( ''safe type casts'' )に使用されます。 * <code>[[#break|break]]</code> ループの実行を終了させます。 * <code>[[#class|class]]</code> クラスを宣言します。 * <code>[[#continue|continue]]</code> 最も近いループの次のステップに進みます。 * <code>[[#do|do]]</code> do/whileループ(条件式を後置するつループ)を開始します。 * <code>[[#else|else]]</code> 条件が偽のときに実行されるif式の分岐を定義します。 * <code>[[#false|false]]</code> Boolean型の「偽」の値を表します。 * <code>[[#for|for]]</code> forループを開始します。 * <code>[[#fun|fun]]</code> 関数を宣言します。 * <code>[[#if|if]]</code> if式の先頭です。 * <code>[[#in|in]]</code> *# forループで反復されるオブジェクトを指定します。 *# 値が範囲、コレクション、または「contains」メソッドを定義している他のエンティティに属しているかどうかを確認するための中置演算子として使用されます。 *# 同じ目的のためにwhen式で使用されます。 *# 型パラメータをcontravariantとしてマークします。 * <code>[[#!in|!in]]</code> *# 値が範囲、コレクション、または 'contains' メソッドを定義する他のエンティティに'''属さない'''ことを確認する演算子として使用されます。 *# 同じ目的のためにwhen式で使用されます。 *: <code>!in</code>で1つのトークンなので、! と in の間に空白を挟むことはできません。 * <code>[[#interface|interface]]</code> インターフェース( ''interfaces'' )を宣言します。 * <code>[[#is|is]]</code> *# 値が特定の型を持つかどうかをチェックします。 *# 同じ目的のwhen式で使用されます。 * <code>[[#!is|!is]]</code> *# 値が特定の型を持って'''いない'''かどうかをチェックします。 *# 同じ目的のwhen式で使用されます。 *: <code>!is</code>で1つのトークンなので、! と is の間に空白を挟むことはできません。 * <code>[[#null|null]]</code> どのオブジェクトも指していないオブジェクト参照を表す定数です。 * <code>[[#object|object]]</code> クラスとそのインスタンスを同時に宣言します。 * <code>[[#package|package]]</code> 現在のファイルのパッケージを指定します。 * <code>[[#return|return]]</code> 最も近い包含関数または無名関数からの呼出し元に戻ります。 * <code>[[#super|super]]</code> *# メソッドやプロパティのスーパークラス実装を参照します。 *# 二次コンストラクタ( ''secondary constructor'' )からスーパークラスのコンストラクタを呼び出します。 * <code>[[#this|this]]</code> *# 現在のレシーバを指します。 *# 2 次コンストラクタから同じクラスの別のコンストラクタを呼び出します。 * <code>[[#throw|throw]]</code> 例外を投げます。 * <code>[[#true|true]]</code> Boolean型の「真」の値を表します。 * <code>[[#try|try]]</code> 例外処理ブロックを開始します。 * <code>[[#typealias|typealias]]</code> 型の別名を宣言します。 * <code>[[#typeof|typeof]]</code> 将来の使用のために予約されています。 * <code>[[#val|val]]</code> 読取り専用のプロパティまたはローカル変数を宣言します。 * <code>[[#var|var]]</code> 変更可能なプロパティまたはローカル変数を宣言します。 * <code>[[#when|when]]</code> when式を開始します(与えられた分岐のうち1つを実行します)。 * <code>[[#while|while]]</code> while ループ(条件式を前置するループ)を開始します。 === ソフト・キーワード === {{先頭に戻る|style=border-top:1px solid gray;}} 以下のトークンは、それが適用される文脈( ''context'' )ではキーワードとして機能し、他の文脈では[[#識別子|識別子]]として使用することができます<ref>[https://kotlinlang.org/docs/keyword-reference.html#soft-keywords Soft keywords]</ref>。 このようなキーワードをソフト・キーワード( ''Soft keywords'' )と呼びます。 * <code>[[#by|by]]</code> *# インターフェース( ''interface'' )の実装( ''implementation'' )を別のオブジェクトに委譲( ''delegates'' )します。 *# プロパティーのアクセッサー( ''accessors'' )の実装を別のオブジェクトに委譲します。 * <code>[[#catch|catch]]</code> 特定の例外タイプ( ''specific exception type'' )を処理( ''handles'' )するブロックを開始します。 * <code>[[#constructor|constructor]]</code> 一次または二次コンストラクタを宣言します。 * <code>[[#delegate|delegate]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>( ''annotation use-site target'' )として使用されます。 * <code>[[#dynamic|dynamic]]</code> Kotlin/JS コードで動的な型を参照します。 * <code>[[#field|field]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#file|file]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#finally|finally]]</code> tryブロックが終了したときに必ず実行されるブロックを開始します。 * <code>[[#get|get]]</code> *# プロパティのゲッター( ''getter'' )を宣言します。 *# [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#import|import]]</code> 他のパッケージから現在のファイルに宣言をインポートします。 * <code>[[#init|init]]</code> イニシャライザーブロックを開始します。 * <code>[[#param|param]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#property|property]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#receiver|receiver]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#set|set]]</code> *# プロパティのセッター( ''setter'' )を宣言します。 *# [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#setparam|setparam]]</code> [[#アノテーション使用側ターゲット|アノテーション使用側ターゲット]]<sup>[仮訳]</sup>として使用されます。 * <code>[[#value|value]]</code> キーワード <code>class</code> を付けてインラインクラス( ''inline class'' )を宣言します。 * <code>[[#where|where]]</code> 汎用型パラメーター( ''a generic type parameter'' )の制約( ''constraints'' )を指定します。 ==== アノテーション使用側ターゲット ==== アノテーション使用側ターゲット( ''Annotation use-site target'' )は、Kotlinにおいてアノテーションが特定の要素に対して適用される位置を指定する構文です。これにより、生成されるJavaバイトコードにおいてアノテーションがどの要素に適用されるかを正確に指定できます<ref>[https://kotlinlang.org/docs/annotations.html#annotation-use-site-targets Annotation use-site targets]</ref>。 ==== アノテーション使用側ターゲットの指定 ==== 以下は、一般的なアノテーション使用側ターゲットの指定方法です。 # プロパティにアノテーションを指定する場合: #:<syntaxhighlight lang=kotlin copy> class Example { @get:MyAnnotation val myProperty: Int = 42 } </syntaxhighlight> #:この例では、<code>@get:MyAnnotation</code> と指定することで、プロパティのgetterメソッドに対してアノテーションを指定しています。 # 1次コンストラクタのパラメータにアノテーションを指定する場合: #:<syntaxhighlight lang=kotlin copy> class Example(@param:MyAnnotation val value: String) </syntaxhighlight> #:この例では、<code>@param:MyAnnotation</code> と指定することで、1次コンストラクタのパラメータに対してアノテーションを指定しています。 ==== よく使われるアノテーション使用側ターゲット ==== # <code>@get</code>: プロパティのgetterメソッドに対してアノテーションを指定する。 # <code>@set</code>: プロパティのsetterメソッドに対してアノテーションを指定する。 # <code>@field</code>: プロパティ自体に対してアノテーションを指定する。 これらの使用側ターゲットを使うことで、アノテーションが生成される場所を明確に指定することができ、柔軟性を保ちつつ、正確な挙動を得ることができます。 === モディファイア・キーワード === {{先頭に戻る|style=border-top:1px solid gray;}} 以下のトークンは、宣言の修飾語リスト( ''modifier lists of declarations'' )のキーワードとして機能し、他のコンテキストでは識別子として使用することができます<ref>[https://kotlinlang.org/docs/keyword-reference.html#modifier-keywords Modifier keywords]</ref>。 このようなキーワードをモディファイア・キーワード( ''Modifier keywords'' )と呼びます。 * <code>[[#abstract|abstract]]</code> クラスやメンバが抽象的( ''as abstract'' )であることを表します。 * <code>[[#actual|actual]]</code> マルチプラットフォーム・プロジェクト( ''multiplatform projects'' )におけるプラットフォーム固有の実装( ''platform-specific implementation'' )を意味します。 * <code>[[#annotation|annotation]]</code> アノテーションクラス( ''an annotation class'' )を宣言します。 * <code>[[#companion|companion]]</code> コンパニオンオブジェクト( ''a companion object'' )を宣言します。 * <code>[[#const|const]]</code> プロパティをコンパイル時の定数( ''a compile-time constant'' )としてマークします。 * <code>[[#crossinline|crossinline]]</code> インライン関数に渡されるラムダで、ローカルでない返り値を禁止します。 * <code>[[#data|data]]</code> クラスの正規メンバー( ''canonical members'' )を生成するようにコンパイラーに指示します。 * <code>[[#enum|enum]]</code> 列挙型( ''an enumeration'' )を宣言します。 * <code>[[#expect|expect]]</code> 宣言がプラットフォーム固有( ''as platform-specific'' )のものであり、プラットフォーム・モジュール(platform modules )で実装されることを期待するものとしてマークします。 * <code>[[#external|external]]</code> Kotlin の外部で実装される宣言であることを示します(JNI または JavaScript でアクセス可能)。 * <code>[[#final|final]]</code> メンバーのオーバーライドを禁止します。 * <code>[[#infix|infix]]</code> 中置記法( ''infix notation'' )で関数を呼び出すことを許可します。 * <code>[[#inline|inline]]</code> 関数とその関数に渡されたラムダを呼出し先でインライン化することをコンパイラに指示します。 * <code>[[#inner|inner]]</code> ネストされたクラスから外側のクラスのインスタンスを参照できるようにします。 * <code>[[#internal|internal]]</code> 現在のモジュールで可視( ''as visible'' )となる宣言をマークします。 * <code>[[#lateinit|lateinit]]</code> コンストラクターの外部で非 null プロパティを初期化します。 * <code>[[#noinline|noinline]]</code> インライン関数に渡されたラムダをインライン化しないようにします。 * <code>[[#open|open]]</code> クラスのサブクラス化またはメンバーのオーバーライドを許可します。 * <code>[[#operator|operator]]</code> 関数が演算子をオーバーロードしているか、または規約を実装( ''implementing a convention'' )しているかをマークします。 * <code>[[#out|out]]</code> 型パラメータを共変( ''covariant'' )としてマークします。 * <code>[[#override|override]]</code> スーパークラスのメンバーのオーバーライドとしてメンバーにマークを付けます。 * <code>[[#private|private]]</code> 現在のクラスまたはファイル内で宣言が可視化( as visible )されるようにマークします。 * <code>[[#protected|protected]]</code> 現在のクラスとそのサブクラスで宣言が可視化されるようにマークします。 * <code>[[#public|public]]</code> 宣言がどこでも可視化されるようにマークします。 * <code>[[#reified|reified]]</code> インライン関数の型パラメーター( ''type parameter'' )を、実行時にアクセス可能なものとしてマークします。 * <code>[[#sealed|sealed]]</code> シールされたクラス( ''sealed class'' ; サブクラス化が制限されたクラス)を宣言します。 * <code>[[#suspend|suspend]]</code> 関数やラムダをサスペンド(コルーチンとして使用可能)するようにマークします。 * <code>[[#tailrec|tailrec]]</code> 関数を末尾再帰としてマークします (コンパイラーが再帰を反復に置換えることができます)。 * <code>[[#vararg|vararg]]</code> パラメーターに可変数の引数を渡せるようにします。 === 特殊識別子 === {{先頭に戻る|style=border-top:1px solid gray;}} 以下の識別子は,コンパイラーが特定の文脈で定義したもので、他の文脈では通常の識別子として使用することができます<ref>[https://kotlinlang.org/docs/keyword-reference.html#special-identifiers Special identifiers]</ref>。 このような識別子を特殊識別子( ''Special identifiers'' )と呼びます。 * <code>[[#field|field]]</code> プロパティーアクセサー( ''a property accessor'' )の内部で、プロパティーのバッキングフィールドを参照するために使用します。 * <code>[[#it|it]]</code> ラムダの内部で暗黙のうちにパラメーターを参照するために使用されます。 === 演算子と特殊シンボル === {{先頭に戻る|style=border-top:1px solid gray;}} Kotlinは以下の演算子( ''Operators'' )や特殊特殊シンボル( ''special symbols'' )をサポートしています<ref>[https://kotlinlang.org/docs/keyword-reference.html#operators-and-special-symbols Operators and special symbols]</ref>。 * <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>, <code>%</code> {{---}} 算術演算子 *# <code>*</code> は、vararg パラメーターに配列を渡す場合にも使用されます。 * <code>=</code> *# 代入演算子 *# パラメーターのデフォルト値を指定するために使用されます。 * <code>+=</code>, <code>-=</code>, <code>*=</code>, <code>/=</code>, <code>%=</code> {{---}} 拡張された代入演算子。 * <code>++</code>, <code>--</code> {{---}} インクリメントおよびデクリメント演算子 * <code>&&</code>, <code>||</code>, <code>!</code> {{---}} 論理 'and', 'or', 'not' 演算子 (ビット演算には、対応する infix 関数を使用してください)。 * <code>==</code>, <code>!=</code> {{---}} 等号演算子 (非プリミティブ型では equals() に変換される)。 * <code>===</code>, <code>!==</code> {{---}} 参照系等号演算子( ''referential equality operators'' ) * <code><</code>, <code>></code>, <code><=</code>, <code>>=</code> {{---}} 比較演算子 (非プリミティブ型に対する compareTo() の呼出しに変換されます) * <code>[</code>, <code>]</code> {{---}} インデックス付きアクセス演算子(getとsetの呼び出しに変換されます) * <code>!!</code> 式が非nullであることを保証します。 * <code>?.</code> 安全な呼び出しを行います(レシーバーが非NULLの場合、メソッドを呼び出したり、プロパティにアクセスしたりします)。 * <code>?:</code> 左辺の値がNULLの場合、右辺の値を取ります(エルビス演算子)。 * <code>::</code> メンバー参照またはクラス参照を作成します。 * <code>..</code> 範囲( ''a range'' )を生成します。 * <code>:</code> 宣言の中で、名前と型を分離します。 * <code>?</code> 型をnull可能( ''as nullable'' )であるとマークします。 * <code>-></code> *# ラムダ式のパラメーターと本体を分離します。 *# 関数型のパラメーターと戻値の型宣言を分離します。 *# when式の条件分岐と本体を分離します。 * <code>@</code> *# アノテーションを導入します。 *# ループラベルを導入または参照します。 *# ラムダ・ラベルを導入または参照します。 *# 外部スコープから 'this' 式を参照します。 *# 外部のスーパークラスを参照します。 * <code>;</code> 同じ行にある複数のステートメントを区切ります。 * <code>$</code> 文字列テンプレート内で変数または式を参照します。 * <code>_</code> *# ラムダ式で使用しないパラメーターを置換えます。 *# 構造化宣言の未使用のパラメーターを代入します。 {{See also|[[#演算子の優先順位|演算子の優先順位]]}} == Kotlin標準ライブラリー == {{先頭に戻る}} Kotlin標準ライブラリー( ''Kotlin Standard Library'' )は、以下のような機能を提供します<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/ Kotlin Standard Library]</ref>。 * 慣用的なパターン(let、apply、use、synchronizedなど)を実装した高階関数。 * コレクション(eager)やシーケンス(lazy)に対するクエリ操作を提供する拡張関数。 * 文字列や文字列列を扱うための各種ユーティリティ * ファイル、IO、スレッドを便利に扱うための JDK クラスの拡張。 Kotlin標準ライブラリーはKotlin自身で書かれています。 ;[[ディフォルトインポート]]されるパッケージ * kotlin.* * [[#アノテーション|アノテーション]] * [[#コレクション|コレクション]] * [[#比較|比較]] * [[#入出力|入出力]] * [[#範囲|範囲]] * [[#シーケンス|シーケンス]] * [[#テキスト|テキスト]] === アノテーション === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.annotation.* === コレクション === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} Kotlinには、Arrayから始まり、Iterable, Collection, List, Set, Mapなどのコレクション型が豊富に用意されています。これらは主に <code>kotlin.collections</code> パッケージで提供されており、[[#ディフォルトインポート|ディフォルトインポート]]なので追加のインポートなしで利用できます<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/ Package kotlin.collections]</ref>。 :{| class=wikitable |+ 主要なパッケージとその機能の一覧 !パッケージ!!機能 |- !Iterable |要素の反復処理をサポート |- !Collection |要素のコレクションを表現 |- !List |要素数が固定で、要素の値を変更不可 |- !ArrayList |可変長の動的な配列 |- !MutableList |要素の変更が可能なリスト |- !Set |要素の重複を許さない |- !Map |キーと値のペアを保持する |- !MutableMap |要素の変更が可能なMap |- !LinkedHashSet |要素の挿入順を保持するSet |- !LinkedHashMap |要素の挿入順を保持するMap |} ==== Iterable ==== <code>Iterable</code> インターフェースは、Kotlinの標準ライブラリで使用される反復可能なコレクションの基本的なインターフェースです。このインターフェースは、コレクションが要素の反復処理を可能にするために必要な機能を提供します。 以下に、<code>Iterable</code> インターフェースの主な要素と使用法を示します: # <code>iterator()</code> メソッド: #* <code>iterator</code> メソッドは、コレクション内の要素を反復処理するためのイテレータを返します。 #* イテレータは、<code>hasNext()</code> メソッドで次の要素の有無を確認し、<code>next()</code> メソッドで次の要素を取得します。 #* 通常、<code>for</code> ループや <code>forEach</code> 関数を使用して、このメソッドを呼び出すことなくコレクションを反復処理できます。 #:<syntaxhighlight lang=kotlin copy> val iterable: Iterable<Int> = listOf(1, 2, 3, 4, 5) // for ループを使用した反復処理 for (element in iterable) { println(element) } // forEach 関数を使用した反復処理 iterable.forEach { element -> println(element) } </syntaxhighlight> # <code>forEach</code> 拡張関数: #* <code>Iterable</code> インターフェースには、<code>forEach</code> という拡張関数があります。これはラムダ式を使用して各要素に対する処理を行います。 #:<syntaxhighlight lang=kotlin copy> val iterable: Iterable<Int> = listOf(1, 2, 3, 4, 5) // forEach 関数を使用した反復処理 iterable.forEach { element -> println(element) } </syntaxhighlight> #使用例: #* <code>Iterable</code> は多くの Kotlin のコレクションで使用されます。例えば、<code>List</code>、<code>Set</code>、<code>Map</code> などが <code>Iterable</code> インターフェースを実装しています。 #* <code>Iterable</code> を実装することで、コレクションが要素の反復処理をサポートし、<code>for</code> ループや <code>forEach</code> 関数などで簡単に使用できます。 #:<syntaxhighlight lang=kotlin copy> // List は Iterable インターフェースを実装している val list: Iterable<Int> = listOf(1, 2, 3, 4, 5) // for ループを使用した反復処理 for (element in list) { println(element) } </syntaxhighlight> <code>Iterable</code> インターフェースは、Kotlinでコレクションを扱う際に非常に重要であり、様々な反復処理操作を可能にします。 ==== Collection ==== <code>Collection</code> インターフェースは、Kotlinの標準ライブラリで提供されるコレクション型の基本インターフェースの一つです。このインターフェースは、複数の要素を保持するデータ構造を表現し、それらの要素に対する基本的な操作を提供します。 以下に、<code>Collection</code> インターフェースの主な特徴と使用法を示します: # 要素の追加と削除: #* <code>Collection</code> インターフェースは、要素の追加や削除といった基本的な操作を提供します。 #* <code>add(element: E)</code> メソッドを使用して要素を追加し、<code>remove(element: E)</code> メソッドを使用して指定した要素を削除します。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // 要素の追加はサポートされない // collection.add(6) // エラー // 要素の削除 val modifiedCollection = collection - 3 println(modifiedCollection) // [1, 2, 4, 5] </syntaxhighlight> # 要素の存在確認: #* <code>contains(element: E)</code> メソッドを使用して、指定した要素がコレクション内に存在するかどうかを確認できます。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // 要素の存在確認 val containsThree = collection.contains(3) println(containsThree) // true </syntaxhighlight> # サイズの取得: #* <code>size</code> プロパティを使用して、コレクション内の要素の総数を取得できます。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // コレクションのサイズ取得 val size = collection.size println(size) // 5 </syntaxhighlight> # 反復処理: #* <code>Iterable</code> インターフェースを継承しているため、<code>forEach</code> 関数などを使用してコレクション内の要素を反復処理できます。 #:<syntaxhighlight lang=kotlin copy> val collection: Collection<Int> = listOf(1, 2, 3, 4, 5) // forEach 関数を使用した反復処理 collection.forEach { element -> println(element) } </syntaxhighlight> # 他のコレクションとの操作: #* <code>Collection</code> インターフェースを実装するコレクションは、他のコレクションとの操作を行うための便利な関数を提供します。例えば、和集合、差集合、共通要素などを計算できます。 #:<syntaxhighlight lang=kotlin copy> val collection1: Collection<Int> = listOf(1, 2, 3, 4, 5) val collection2: Collection<Int> = listOf(4, 5, 6, 7, 8) // 和集合 val unionResult = collection1 union collection2 println(unionResult) // [1, 2, 3, 4, 5, 6, 7, 8] // 差集合 val subtractResult = collection1 subtract collection2 println(subtractResult) // [1, 2, 3] // 共通要素 val intersectResult = collection1 intersect collection2 println(intersectResult) // [4, 5] </syntaxhighlight> <code>Collection</code> インターフェースは、Kotlinのコレクションの基本的な機能を提供し、様々な種類のコレクションがこれを実装しています。これにより、異なる種類のコレクションを一貫して扱うことができます。 ==== List ==== Listは、要素数が固定で要素の値を変更できないコレクションです。 ===== List() ===== ;[https://paiza.io/projects/vmrFKnU_3qj5d04hJPmuWA?language=kotlin List()を使ったListの生成]:<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val list = List(5){it} println("list::class.simpleName ⇒ ${list::class.simpleName}") println("list[0]::class.simpleName ⇒ ${list[0]::class.simpleName}") list.forEach{print("$it ")} println("") val list2 = List(5){(it*it).toString()} println("list2[0]::class.simpleName ⇒ ${list2[0]::class.simpleName}") list2.forEach{print("$it ")} println("") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> list::class.simpleName ⇒ ArrayList list[0]::class.simpleName ⇒ Int 0 1 2 3 4 list2[0]::class.simpleName ⇒ String 0 1 4 9 16 </syntaxhighlight> : List()はListのコンストラクターで、引数として要素数をとり、ブロックが初期化式になります。 ===== listOf ===== ;[https://paiza.io/projects/D17B4n-k7dGdKdxlrw5m2Q?language=kotlin listOf()を使ったListの生成] :<syntaxhighlight lang=Kotlin highlight=2 line> fun main() { val list = listOf(1, 9, 3, 5, 23, 1) println("${list::class.simpleName}") println("${list[0]::class.simpleName}") for (s in list) if (s > 10) break else print("$s ") println("") run { list.forEach{ if (it > 10) return@run else print("$it ") } } println("") } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ArrayList Int 1 9 3 5 1 9 3 5 </syntaxhighlight> : ListOf()は可変長引数の関数で、引数が生成されるListの要素になります。 : Listの要素の型は、型強制できる最小公倍数的な方になります(例えば Int と Long が混在していたら Long)。 ==== ArrayList ==== :<syntaxhighlight lang=Kotlin line> fun main() { // ArrayListを使ったListの生成 val arrayList = ArrayList<String>() arrayList.add("Kotlin") arrayList.add("Java") arrayList.add("Python") println("${arrayList::class.simpleName}") for (lang in arrayList) { println(lang) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> ArrayList Kotlin Java Python </syntaxhighlight> 上記の例では、<code>ArrayList</code> を使ってListを生成しています。ArrayListは要素の順序が保持され、可変長の動的な配列を表現します。<code>add</code> メソッドを使用して要素を追加することができます。 ==== MutableList ==== <syntaxhighlight lang=kotlin copy> fun main() { // MutableListを使ったListの生成 val mutableList = mutableListOf(1, 2, 3, 4, 5) mutableList.add(6) println("${mutableList::class.simpleName}") for (num in mutableList) { print("$num ") } println("") } </syntaxhighlight> ;実行結果 :<syntaxhighlight lang=text> ArrayList 1 2 3 4 5 6 </syntaxhighlight> <code>mutableListOf()</code> を使って <code>MutableList</code> を生成し、<code>add</code> メソッドを使用して要素を追加しています。MutableListは要素の変更が可能なListです。 これらの例から分かるように、Kotlinのコレクションは型安全で、読み取り専用と可変なコレクションの違いが明確になっています。リストの他にも、SetやMapも用意されており、それぞれの特徴に応じて適切なものを選択できます。 ==== ユースケース ==== <code>kotlin.collections</code> パッケージのコレクションクラスや関連機能は、さまざまなプログラミングシナリオで利用されます。以下は、<code>kotlin.collections</code> の主なユースケースのいくつかです: # データの格納と操作: List、Set、Mapなどのコレクションは、データを効果的に格納し、操作するために使用されます。例えば、リストは順序つきのデータの集合を表現し、セットは一意な要素の集合を表現します。 # 反復処理とフィルタリング: Iterable インターフェースを使用してコレクションを反復処理し、必要なデータを抽出することができます。これは、フィルタリングや変換などの操作に役立ちます。 # 不変性と可変性の管理: List と MutableList、Set と MutableSet、Map と MutableMap など、各コレクションには不変なバージョンと可変なバージョンがあります。これにより、不変性を保ちながら必要に応じてデータを変更できます。 # 関数型プログラミング: コレクション操作には関数型プログラミングのアプローチがあり、<code>filter</code>、<code>map</code>、<code>reduce</code> などの関数を使用してデータを処理できます。 以下は、これらのユースケースの簡単な例です: <syntaxhighlight lang=kotlin copy> // データの格納と操作 val list = listOf(1, 2, 3, 4, 5) val set = setOf(1, 2, 3, 4, 5) val map = mapOf(1 to "one", 2 to "two", 3 to "three") // 反復処理とフィルタリング val filteredList = list.filter { it > 2 } // 不変性と可変性の管理 val mutableList = mutableListOf(1, 2, 3) mutableList.add(4) // 関数型プログラミング val squaredValues = list.map { it * it } val sum = list.reduce { acc, value -> acc + value } </syntaxhighlight> これらの例は一部の機能を示すものであり、<code>kotlin.collections</code> のコレクションは、さまざまなプログラミングニーズに対応する強力なツールセットを提供します。 ==== ベストプラクティス ==== <code>kotlin.collections</code> を使用する際のベストプラクティスはいくつかあります。以下にいくつか挙げてみましょう: # 不変性の推奨: 不変なコレクション(<code>List</code>、<code>Set</code>、<code>Map</code>など)を使用することを検討してください。不変なコレクションは変更不可能でスレッドセーフであり、プログラムの安全性を向上させるのに役立ちます。 #:<syntaxhighlight lang=kotlin copy> // 不変なリスト val immutableList = listOf(1, 2, 3) // 不変なセット val immutableSet = setOf("apple", "orange", "banana") // 不変なマップ val immutableMap = mapOf(1 to "one", 2 to "two", 3 to "three") </syntaxhighlight> # Nullableなコレクションの適切な扱い: コレクション内の要素が <code>null</code> になりうる場合、Nullableなコレクション(<code>List?</code>、<code>Set?</code>、<code>Map?</code>など)を使用して適切にハンドリングしましょう。 #:<syntaxhighlight lang=kotlin copy> // Nullableなリスト val nullableList: List<Int>? = // ... // Nullableなセット val nullableSet: Set<String>? = // ... // Nullableなマップ val nullableMap: Map<Int, String>? = // ... </syntaxhighlight> # 関数型プログラミングの活用: <code>filter</code>、<code>map</code>、<code>reduce</code>、<code>fold</code> などの関数型プログラミングの機能を活用して、コードを簡潔で読みやすくしましょう。 #:<syntaxhighlight lang=kotlin copy> val numbers = listOf(1, 2, 3, 4, 5) val evenSquared = numbers .filter { it % 2 == 0 } .map { it * it } .sum() </syntaxhighlight> # 適切なコレクションの選択: 使用ケースによって適切なコレクションを選択しましょう。例えば、要素の順序が重要な場合は <code>List</code>、一意性が必要な場合は <code>Set</code>、キーと値のペアが必要な場合は <code>Map</code> を使用します。 #:<syntaxhighlight lang=kotlin copy> // 要素の順序が重要 val orderedList = listOf(1, 2, 3, 4, 5) // 一意性が必要 val uniqueSet = setOf("apple", "orange", "banana") // キーと値のペアが必要 val keyValueMap = mapOf(1 to "one", 2 to "two", 3 to "three") </syntaxhighlight> これらのベストプラクティスは、コードの品質、パフォーマンス、保守性を向上させるのに役立ちます。使用ケースによって最適なアプローチを選択することが重要です。 === 比較 === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.comparisons.* === 入出力 === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.io.* === 範囲 === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.ranges.* === シーケンス === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.sequences.* === テキスト === {{先頭に戻る|title=Kotlin標準ライブラリーに戻る|label=Kotlin標準ライブラリー}} kotlin.text.* ---- === コレクション類似クラス === {{先頭に戻る}} [TODO:Rangeはコレクションではないので再分類が必要] <code>println((1..5).javaClass.kotlin)</code>の結果が示す通り、範囲リテラル<code>1..5</code>は<code>class kotlin.ranges.IntRange</code>です。 コレクションは、Ranges以外にも、Sequences・Ranges・Lists・Arrays・Sets・Mapsなどがあります。これは網羅していませんし、上記の forプロトコルに従ったクラスを作れば、ユーザー定義のコレクションも作成できます。 ;[https://paiza.io/projects/zw6faeOmsjuZVF3D3WY_-g?language=kotlin 様々なコレクション]:<syntaxhighlight lang="Kotlin"> fun main(args: Array<String>) { val collections = arrayOf( 1..5, 1..8 step 2, 5 downTo 1, 8 downTo 1 step 2, 'A'..'Z', listOf(2,3,5), setOf(7,11,13)) println("$collections(${collections.javaClass.kotlin})") for (collection in collections) { print(collection) print(": ") for (x in collection) { print(x) print(" ") } print(": ") println(collection.javaClass.kotlin) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> class kotlin.Array 1..5: 1 2 3 4 5 : class kotlin.ranges.IntRange 1..7 step 2: 1 3 5 7 : class kotlin.ranges.IntProgression 5 downTo 1 step 1: 5 4 3 2 1 : class kotlin.ranges.IntProgression 8 downTo 2 step 2: 8 6 4 2 : class kotlin.ranges.IntProgression A..Z: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z : class kotlin.ranges.CharRange [2, 3, 5]: 2 3 5 : class java.util.Arrays$ArrayList [7, 11, 13]: 7 11 13 : class java.util.LinkedHashSet </syntaxhighlight> : 二重のforループで、外周はコレクションのコレクションで、内周は個々のコレクションの要素をイテレーションしています。 === スコープ関数 === {{先頭に戻る|style=border-top:1px solid gray;}} ==== repeat関数 ==== Kotlinの標準ライブラリーにあるrepeat関数は、定数回の繰返しが必要な時に便利です<ref>[https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/repeat.html repeat - Kotlin Programming Language]</ref>。 ;[https://paiza.io/projects/LHnnORcAjUhvb_qW9ysIvw?language=kotlin repeat関数]:<syntaxhighlight lang="kotlin"> fun main() { repeat(5) { println("it = $it") } run { repeat(3) { i -> repeat(4) { j -> println("(i, j) = ($i, $j)") if (i == 1 && j == 2) { return@run } } } } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> it = 0 it = 1 it = 2 it = 3 it = 4 (i, j) = (0, 0) (i, j) = (0, 1) (i, j) = (0, 2) (i, j) = (0, 3) (i, j) = (1, 0) (i, j) = (1, 1) (i, j) = (1, 2) </syntaxhighlight> :<var>it</var>は、暗黙のループ変数です。 :多重ループでは、ループ変数の名前が固定では都合が悪いので、ブロックの先頭で<code>識別子名 -></code> とすることで明示的に名前をつけることができます。 :多重ループを run 関数で括ることで多重ループからの大域脱出を実現しています。 ==== ブロックを受取る関数 ==== repeat関数もそうですが、Kotlinにはブロックを受取る関数(やメソッド)があります。 ;[https://paiza.io/projects/AZT2juUGcUnyjqgDx4G85g?language=kotlin ブロックを受取る関数]:<syntaxhighlight lang="kotlin"> fun main(args: Array<String>) { val ary = Array(5) { 2 * it + 1 } ary.forEach{ println(it) } println(ary.map{ it.toString() }.joinToString(" ")) println(ary.reduce{ sum, el -> sum + el }) } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 1 3 5 7 9 1 3 5 7 9 25 </syntaxhighlight> :ブロックで配列の初期化を行う場合、<var>it</var>は順位になります。 :コレクションのforEachメソッドもブロックを取ります。 :コレクションのreduceメソッドもブロックを取りますが、累算値と要素の2つを取るので、名付けが必要です。 このように、ブロックを取るメソッドを使うとコレクションに関する操作を簡素に書けます。 == Coroutine == {{先頭に戻る}} Kotlinは、言語レベルでコルーチンをサポートし、機能の大部分をライブラリに委ねることで、この問題を柔軟に解決しています。 ;Shell:<syntaxhighlight lang=console> $ cat coroutine.kt import kotlinx.coroutines.* fun main() = runBlocking { launch { delay(500L) for (ch in "World!\n") { print(ch) delay(100L) } } print("Hello ") } $ locate /kotlinx-coroutines /usr/local/share/kotlin/lib/kotlinx-coroutines-core-jvm.jar $ kotlinc -cp /usr/local/share/kotlin/lib/kotlinx-coroutines-core-jvm.jar coroutine.kt -include-runtime -d coroutine.jar $ java -cp ./coroutine.jar:/usr/local/share/kotlin/lib/kotlinx-coroutines-core-jvm.jar CoroutineKt Hello World! </syntaxhighlight> == Kotlin Script == {{先頭に戻る}} Kotlin Script では、.jar を生成せず、そのままコードが実行されます。 また、main 関数をエントリーポイントはぜず、スクリプトの書かれた順に評価します。 ;Shell:<syntaxhighlight lang=console> % cat hello.kts println("Hello, World!") % kotlinc -script hello.kts Hello, World! % _ </syntaxhighlight> ビルドツールの Gradle では、従来は Groovy がビルド構成ファイルに使われていましたが、Kotlin Script への移行が進んでいます。 ;ワンライナー:<syntaxhighlight lang=console> % kotlin -e 'repeat(3){println("Hello!($it)")}' Hello!(0) Hello!(1) Hello!(2) % _ </syntaxhighlight> == 改廃された技術 == Kotlinの改廃された技術や利用が推奨されない技術は、言語やエコシステムの進化、新しい要求、セキュリティ上の懸念などにより置き換えられます。以下に、代表的な技術を示します。 === Kotlin Android Extensions === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2021年(Kotlin 1.6.20で非推奨化) ; 廃止または衰退の理由 : View BindingやJetpack Composeなど、より安全で効率的なUI開発ツールが普及したため、利用が非推奨化されました。 ; 代替技術 : View BindingやJetpack Composeを使用することが推奨されます。 === Synthetic Properties for Views === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2021年(非推奨化) ; 廃止または衰退の理由 : Null安全性やビルドプロセスの問題から、公式に非推奨となりました。 ; 代替技術 : View Bindingを使用することで、同様の機能を安全に実現できます。 === Kotlin Scripting旧形式 (kotlin.script.experimental) === * '''対象:''' kotlin.script.experimental APIの旧バージョン ; 利用推奨されない理由 : 新しいAPI(kotlin.script.experimental.jvmなど)がより柔軟で強力であるため、旧形式は非推奨となりました。 ; 代替技術 : 最新のKotlin Scripting APIを使用してください。 === Kotlin Coroutinesの旧形式 === * '''対象:''' kotlinx.coroutinesの旧バージョン(0.x系) ; 利用推奨されない理由 : 古いバージョンではAPIが安定しておらず、最新の1.x系バージョンでは大幅な改善と安定化が図られています。 ; 推奨バージョン : 最新の1.x系またはそれ以降を使用してください。 === Experimental API === * '''対象:''' <code>@Experimental</code>や<code>@UseExperimental</code>アノテーションでラベル付けされたAPI ; 利用推奨されない理由 : 将来のリリースで仕様変更や削除が行われる可能性があるため、慎重に利用する必要があります。 ; 代替技術 : 安定版APIがリリースされた場合、それに切り替えることが推奨されます。 === Kotlin/NativeのC Interop旧形式 === * '''対象:''' Kotlin/NativeにおけるC Interopの旧形式 ; 利用推奨されない理由 : 最新のKotlin/NativeバージョンでInteropが改善され、旧形式は非推奨となりました。 ; 代替技術 : 最新のC Interop形式や公式ドキュメントに基づいた方法を使用してください。 === Kotlin Multiplatform Pluginの旧形式 === * '''対象:''' Kotlin Multiplatform Pluginの旧バージョン ; 利用推奨されない理由 : 最新バージョンではモジュール分割や依存関係管理の改善が行われ、旧バージョンの利用は推奨されなくなりました。 ; 代替技術 : 最新のKotlin Multiplatform Pluginを利用してください。 === Java 6および7向けのサポート === * '''サポート開始年:''' 2011年(初期Kotlin) * '''サポート終了年:''' 2020年(Kotlin 1.6以降で非推奨化) ; 廃止または衰退の理由 : 古いJavaバージョンの市場シェアが低下したため、KotlinチームはJava 8以降に焦点を当てています。 ; 代替技術 : Java 8以降を対象にKotlinを使用することが推奨されます。 == 脚註 == <references /> == 外部リンク == * [https://kotlinlang.org/ Kotlin Programming Language] - 公式サイト ** [https://kotlinlang.org/spec/introduction.html Kotlin language specification] ** [https://play.kotlinlang.org/ Kotlin Playground: Edit, Run, Share Kotlin Code Online] [[Category:Kotlin|*]] [[Category:プログラミング言語]] {{NDC|007.64}} sy81r20n7e2n59kojnq68dt3spzfl1h Go 0 28505 263757 263400 2024-11-18T09:30:51Z Ef3 694 /* 目次 */ ;[[/改廃された技術|改廃された技術]] 263757 wikitext text/x-wiki {{Pathnav|メインページ|工学|情報技術|プログラミング}} Goは、Googleが開発したオープンソースの汎用プログラミング言語であり、システムプログラミングを主な目的として設計されています<ref name="Introduction">{{cite book | url = https://go.dev/ref/spec#Introduction | title = The Go Programming Language Specification Language version go1.23 (June 13, 2024) | chapter = Introduction¶ | date = June 13, 2024 | publisher = The Go website }}</ref>。 静的型付け言語であるため、高速で効率的なプログラムを作成することができ、また、並行処理を簡単に実装できるため、高い並行性を持ちます。 Goの文法はシンプルで読みやすく、効率的にコーディングできるため、開発者は迅速に新しいコードを書くことができます。 Goは自動的にメモリを管理するため、メモリ管理に関する手間を減らすことができます。 さらに、Windows、macOS、Linuxなど、多くのプラットフォームで動作し、標準ライブラリが豊富であり、多くの外部ライブラリが存在するため、広範な用途に対応することができます。 Goのコミュニティは活発であり、多くの開発者が参加しているため、質問や問題解決のためのリソースが豊富であり、新しい機能やライブラリが定期的にリリースされています。 この教科書では、初めてGoを学ぶ人から、より高度なトピックに興味のある人まで、幅広い読者を対象に、Goの基本から応用までを網羅的に解説します。 __TOC__ == 目次 == ;チュートリアル篇 : [[/環境構築|環境構築]] : [[/実行の方法|実行の方法]] {{---}} [[Go/実行の方法#Hello, World|Hello, World]] : [[/文法の概要|文法の概要]] : [[/変数|変数と型変換]] : [[/算術演算と数学関数|算術演算と数学関数]] : [[/条件分岐と繰り返し|条件分岐と繰り返し]] {{---}} if, switch, select, for, break, continue, return : [[/関数|関数]] : [[/メソッドとインターフェース|メソッドとインターフェース]] : [[/ジェネリクス|ジェネリクス]] : [[/再帰的関数呼出し|再帰的関数呼出し]] : [[/メソッドチェイン|メソッドチェイン]] : [[/defer,panicとrecover|defer, panicとrecover]] : [[/並行処理|並行処理]] : [[/配列とスライス|配列型とスライス型]] : [[/マップ|マップ型]] : [[/構造体|構造体型と構造体スライス]] : [[/Goのプログラムがどんなアセンブリにコンパイルされるか?|Goのプログラムがどんなアセンブリにコンパイルされるか?]] {{---}} go tool objdump : [[/クロスコンパイル|クロスコンパイル]] {{---}} GOOS, GOARCH : [[/cgoでGoのコードからCの関数を利用する|cgoでGoのコードからCの関数を利用する]] {{---}} cgo : [[/Goのコードでgoのバージョンを調べる方法|Goのコードでgoのバージョンを調べる方法]] : [[/HTTP|HTTP]] : [[/ファイル入出力|ファイル入出力]] : [[/コードギャラリー|コードギャラリー]] ;リファレンス篇 : [[/ソースコードの表現方法|ソースコードの表現方法]] : [[/キーワードと宣言済み識別子|キーワードと宣言済み識別子]] {{---}} [[/キーワードと宣言済み識別子#キーワード|キーワード]]・[[/キーワードと宣言済み識別子#宣言済み識別子|宣言済み識別子]]([[/キーワードと宣言済み識別子#組込み型|組込み型]]・[[/キーワードと宣言済み識別子#組込み関数|組込み関数]]) : [[/字句的要素|字句的要素]] : [[/定数と変数|定数と変数]] {{---}} [[/定数と変数#定数|定数]]([[/定数と変数#iota|iota]])・[[/定数と変数#変数|変数]] : [[/型|型]] : [[/型と値の特性|型と値の特性]] : [[/ブロック・宣言とスコープ|ブロック・宣言とスコープ]] {{---}} [[/ブロック・宣言とスコープ#ブロック|ブロック]]・[[/ブロック・宣言とスコープ#宣言とスコープ|宣言とスコープ]] : [[/式|式]] {{---}} [[/式#演算子|演算子]] : [[/文|文]] : [[/パッケージ|パッケージ]] : [[/プログラムの初期化と実行|プログラムの初期化と実行]] : [[/エラー|エラー]] : [[/EBNF|EBNF]] ;[[/標準ライブラリー|標準ライブラリー篇]] ;[[/改廃された技術|改廃された技術]] == バージョン間の変更点 == Go は、約半年ごとに新しいバージョンがリリースされます。バージョンが変わると、言語仕様に追加変更があったり、ツールチェーン、ランタイム、およびライブラリの実装に変更が加えられることがあり、稀に既存のプログラムに影響が出ることもあります。以下に、最新のバージョンから順に変更点を記載します。 === Go 1.23 === Go 1.23が、2024年8月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.23 | title = Go 1.23 Release Notes - The Go Programming Language | date = 2024/08/13 | accessdate = 2024/11/13 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.23 | title = Go 1.23 is released! - The Go Programming Language | date = 2024/08/13 | accessdate = 2024/11/13 }}</ref>。 Go 1.23のリリースでは、いくつかの重要な新機能と改善が含まれています。最も注目すべき変更点は以下です。 {{Main|[https://go.dev/doc/go1.23 Go 1.23 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.23 Go 1.23 is released! The Go Blog]}} ; 言語の変更点: :# "for-range" ループでイテレータ関数がサポートされるようになりました。これにより、カスタムイテレーション値を生成する関数を使用できます。 :# ジェネリック型エイリアスのプレビューサポートが追加されました(GOEXPERIMENT=aliastypeparamsを有効にする必要があります)。 ; 新しい標準パッケージ: :# uniqueパッケージ:値の正規化(インターン化やハッシュコンス化)を行うための機能を提供します。 :# iterパッケージ:ユーザー定義のイテレータ機能を提供します。 :# structsパッケージ:構造体のメモリレイアウトなどのプロパティを制御する機能を提供します。 ; パフォーマンスの改善点: :# Profile Guided Optimization (PGO)のビルドオーバーヘッドが大幅に削減されました。以前は100%以上の増加が見られましたが、今回のリリースでは一桁台のパーセンテージまで改善されています。 :# コンパイラがローカル変数のスタックフレームスロットを最適化し、関数内の異なる領域で重複して使用できるようになり、スタック使用量が削減されました。 ; テレメトリーと開発者ツール: :# Goツールチェーンが使用状況と問題点の統計情報を収集できるテレメトリー機能が追加されました(オプトイン方式)。 :# go vetコマンドにstdversionアナライザーが追加され、使用しているGoバージョンと互換性のないシンボルの参照を検出できるようになりました。 ; プラットフォームサポートの変更: :# macOSは11 (Big Sur)以降が必要になりました。 :# Linux kernelは2.6.32以降が必要です(Go 1.24では3.2以降になる予定)。 :# OpenBSDの64-bit RISC-Vサポートが試験的に追加されました。 また、time.TimerとTime.Tickerの実装が大幅に改善され、未使用のタイマーがガベージコレクションの対象となるようになりました。セキュリティ面では、TLSクライアントがEncrypted Client Helloをサポートし、3DESの暗号スイートがデフォルトリストから削除されるなどの改善が行われています。 === Go 1.22 === Go 1.22が、2024年2月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.22 | title = Go 1.22 Release Notes - The Go Programming Language | date = 2024/02/06 | accessdate = 2024/02/11 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.22 | title = Go 1.22 is released! - The Go Programming Language | date = 2024/02/06 | accessdate = 2024/02/11 }}</ref>。 Go 1.22のリリースでは、いくつかの重要な新機能と改善が含まれています。最も注目すべき変更点は以下です。 {{Main|[https://go.dev/doc/go1.22 Go 1.22 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.22 Go 1.22 is released! The Go Blog]}} ; 言語の変更点: :# 長らく問題視されてきた「for」ループの変数スコープが変更されました。以前は変数が一度だけ作成され、各イテレーションで更新されていましたが、Go 1.22以降は各イテレーションで新しい変数が作成されるようになり、意図しない共有の問題が解消されました。 :# 整数の範囲に対する<code>range</code>のサポートが追加されました。例えば、<code>for i := range 10</code>のような構文が可能になりました。 ; パフォーマンスの改善点: :# ガベージコレクションのメタデータを各ヒープオブジェクトの近くに配置するように最適化されました。これにより、CPUパフォーマンスが1-3%向上し、ほとんどのGoプログラムのメモリオーバーヘッドが約1%削減されました。 :# コンパイラのプロファイル誘導最適化(PGO)が改善され、より多くのインターフェースメソッド呼び出しの仮想化解除が可能になりました。代表的なGoプログラムの多くで、PGOを有効にすることで2-14%のパフォーマンス向上が見られます。 :# コンパイラは仮想化解除とインライン化を交互に行うようになり、インターフェースメソッド呼び出しの最適化が向上しました。 ; 標準ライブラリの追加と改善: :# 標準ライブラリで初めてのv2パッケージとなる<code>math/rand/v2</code>が追加されました。新しいパッケージでは、ChaCha8とPCGという2つの現代的な疑似乱数生成器を提供し、より高速なアルゴリズムを採用しています。 :# <code>net/http.ServeMux</code>のHTTPルーティングがより表現力豊かになりました。メソッドとワイルドカードをサポートし、例えば"POST /items/create"や"/items/{id}"のようなパターンが使用可能になりました。 :# <code>database/sql</code>パッケージに<code>Null[T]</code>型が追加され、任意の型のnullableカラムをスキャンする機能が提供されます。 :# <code>go/version</code>パッケージが追加され、Goバージョン文字列の検証と比較機能が提供されます。 :# <code>slices</code>パッケージに複数のスライスを連結する<code>Concat</code>関数が追加されました。 ; ツールの改善: :# Goコマンドでワークスペースのvendorディレクトリがサポートされるようになりました。<code>go work vendor</code>でディレクトリを作成し、<code>-mod=vendor</code>フラグで使用できます。 :# トレースツールのWebUIが改良され、スレッド指向のビューでトレースを探索できるようになりました。また、すべてのシステムコールの完全な実行時間が表示されるようになりました。 :# <code>go vet</code>ツールに新しい警告が追加され、appendに値を渡し忘れた場合や、time.Since呼び出しの遅延に関する問題を検出できるようになりました。 また、macOSのx86-64アーキテクチャ(darwin/amd64)向けのGoツールチェーンが、デフォルトで位置独立実行形式(PIE)を生成するようになりました。Go 1.23以降はmacOS 11 Big Sur以降が必要になることも発表されています。 === Go 1.21 === Go 1.21が、2023年8月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.21 | title = Go 1.21 Release Notes - The Go Programming Language | date = 2023/08/08 | accessdate = 2023-11-28 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.21 | title = Go 1.21 is released! - The Go Programming Language 5| date = 2023/08/08 | accessdate = 2023-11-28 }}</ref>。 {{Main|[https://go.dev/doc/go1.21 Go 1.21 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.21 Go 1.21 is released! The Go Blog]}} Go 1.21では、リリースの番号付けにわずかな変更が導入されました。Go 1.Nは、過去にGo言語のバージョン全体とリリースファミリー、およびそのファミリー内の最初のリリースを指すために使用されていました。しかし、Go 1.21から、最初のリリースはGo 1.N.0となりました。今日、Go 1.21言語とその初期実装であるGo 1.21.0リリースが公開されています。これらのノートは「Go 1.21」と呼ばれますが、go versionなどのツールは「go1.21.0」と報告されます(Go 1.21.1にアップグレードするまで)。 ; ツールの改善点: :# Profile Guided Optimization(PGO)機能が一般利用可能になりました。<code>default.pgo</code>という名前のファイルがメインパッケージのディレクトリにある場合、<code>go</code>コマンドはそれを使用してPGOビルドを有効にします。 :# <code>go</code>ツールは今後の言語の後方互換性と前方互換性をサポートします。 ; 言語の変更点: :# 新しい組み込み関数 <code>min</code>、<code>max</code>、<code>clear</code> が追加されました。 :# ジェネリック関数の型推論がいくつか改善され、仕様書の型推論の説明が拡張されました。 :# Goプログラミングの最も一般的な落とし穴の1つに取り組む予定で、そのプレビューがGo 1.21に含まれています。これは環境変数を使用してコードで有効にできます。詳細はLoopvarExperiment wikiページを参照してください。 ;標準ライブラリの追加点: :# 構造化ログのための新しいlog/slogパッケージが追加されました。 :# 任意の要素型のスライスに対する共通操作のための新しいslicesパッケージが追加されました。これには、一般的により高速で使いやすいソート関数も含まれています。 :# 任意のキーまたは要素型のマップに対する共通操作のための新しいmapsパッケージが追加されました。 :# 順序付けられた値を比較するための新しいユーティリティを提供するcmpパッケージが追加されました。 ; 性能の改善点: :# PGOを有効にした際のパフォーマンス向上に加えて、以下のような改善があります。 :# Goコンパイラ自体がPGOを有効にして再ビルドされ、ホストアーキテクチャによってはプログラムのビルドが2〜4%高速化されました。 :# ガベージコレクターの調整により、一部のアプリケーションではテールレイテンシーが最大40%削減される場合があります。 :# runtime/traceでトレースを収集する際のCPUコストが、amd64およびarm64で大幅に低減されました。 ; 新しいWASIポート: :# Go 1.21には、WebAssembly System Interface(WASI)の実験的なポートが追加されました(GOOS=wasip1、GOARCH=wasm)。 :# より一般的なWebAssembly(Wasm)コードの記述を容易にするために、コンパイラはWasmホストからの関数のインポートのための新しい指令 <code>go:wasmimport</code> をサポートしています。 === Go 1.20 === Go 1.20が、2023年2月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.20 | title = Go 1.20 Release Notes - The Go Programming Language | date = 2023/02/01 | accessdate = 2023-03-05 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.20 | title = Go 1.20 is released! - The Go Programming Language | date = 2023/02/01 | accessdate = 2023-03-05 }}</ref>。 {{Main|[https://go.dev/doc/go1.20 Go 1.20 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.20 Go 1.20 is released! The Go Blog]}} Go 1.20では、スライスから配列への変換が可能になりました。また、unsafeパッケージには新しい関数が追加され、スライスや文字列の値を構築および分解する完全な機能が提供されるようになりました。また、新しい仕様により、構造体のフィールドと配列の要素の比較が最初の不一致で停止するようになり、厳密に比較できない型引数を持つ型パラメータを使用して、比較制約に制限された型をインスタンス化することが可能になりました。 === Go 1.19 === Go 1.19が、2022年8月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.19 | title = Go 1.19 Release Notes - The Go Programming Language | date = 2022/08/02 | accessdate = 2022-08-04 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.19 | title = Go 1.19 is released! - The Go Programming Language | date = 2022/08/02 | accessdate = 2022-08-04 }}</ref>。 {{Main|[https://go.dev/doc/go1.19 Go 1.19 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.19 Go 1.19 is released! The Go Blog]}} Go 1.19では、ツールチェーン、ランタイム、およびライブラリの実装に変更が加えられています。言語にはわずかな修正があり、既存のプログラムには影響がないです。メモリモデルも更新され、C、C ++、Java、JavaScript、Rust、Swiftなどのメモリモデルに合わせられた。Go 1.19では、sync/atomicパッケージに新しい型が導入され、atomic.Int64やatomic.Pointer[T]などのatomic値をより簡単に使用できるようになっています。Go 1の互換性を維持しており、ほとんどのGoプログラムは引き続き従前どおりにコンパイルおよび実行されることが予想されます。 === Go 1.18 === Go 1.18が、2022年3月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.18 | title = Go 1.18 Release Notes - The Go Programming Language | date = 2022/03/10 | accessdate = 2022-08-04 }}</ref>。 {{Main|[https://go.dev/doc/go1.18 Go 1.18 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.18 Go 1.18 is released! The Go Blog]}} Go 1.18 には、型パラメータプロポーザル<ref>{{cite book | url=https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md | title=Type Parameters Proposal | accessdate=2021-09-30 }}</ref>で説明されたジェネリック機能の実装が含まれています。 以下は、最も目に付く変更点のリストです。 # 関数と型宣言の構文に型パラメータが使えるようになりました。⇒ [[/関数#ジェネリック関数]] # パラメータ化された関数や型は、その後に角括弧で型引数のリストを記述することでインスタンス化することができます。 # 新しいトークン <code>~</code> が演算子および区切子(punctuation)に追加されました。⇒ [[/字句的要素#演算子と区切子]] # インターフェイス型の構文では、任意の型(インターフェイスの型名だけでなく)、unionや~T型要素を埋め込むことができるようになりました。このようなインターフェースは、型制約としてのみ使用することができます。インターフェイスはメソッドと同様に型の集合を定義するようになりました。⇒ [[/型#インターフェース型]] # 新しい事前宣言された識別子<code>any</code>は空のインターフェースの別名です。これは <code>interface{} </code>の代わりに使用することができます。 # 新しい宣言済み識別子 <code>comparable</code> は <code>==</code> や <code>!=</code> を使って比較できる全ての型の集合を表すインターフェースです. ジェネリックを使った実験的なパッケージが3つあり、便利かもしれません。これらのパッケージは x/exp リポジトリにあります。これらのパッケージの API は Go 1 の保証の対象外であり、ジェネリックの経験を積むにつれて変更される可能性があります。 ;golang.org/x/exp/constraints :<code>constraints.Ordered</code>のようなジェネリックコードに便利な制約です。 ;golang.org/x/exp/slices :任意の要素タイプのスライス上で操作するジェネリック関数のコレクションです。 ;golang.org/x/exp/maps :任意のキーや要素タイプのマップ上で操作するジェネリック関数のコレクションです。 ---- Go 1.18は、言語、ツールチェーン、ランタイム、ライブラリに変更があり、互換性が保たれている。最大の変更点は、ジェネリックスの導入である。ジェネリックスはバックワード互換性があるが、実際に多くの人が書き、使用して初めて本番環境で十分にテストされる。ジェネリックスの使用は推奨されるが、本番環境で使用する場合は注意が必要である。ジェネリックスにはいくつかの制限があるが、これらは将来的に改善される可能性がある。これらの変更により、Goエコシステム全体に影響があり、完全なサポートには時間がかかるだろう。 === Go 1.17 === Go 1.17が、2021年8月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.17 | title = Go 1.17 Release Notes - The Go Programming Language | date = 2021/08/16 | accessdate = 2023-03-06 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.17 | title = Go 1.17 is released! - The Go Programming Language | date = 2021/08/16 | accessdate = 2023-03-06 }}</ref>。 {{Main|[https://go.dev/doc/go1.17 Go 1.17 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.17 Go 1.17 is released! The Go Blog]}} Go 1.17は、ツールチェーン、ランタイム、およびライブラリの実装の変更が中心で、ほとんどの変更は互換性が維持されています。言語自体には3つの小さな強化があり、スライスから配列ポインタへの変換、unsafe.Add、unsafe.Sliceが追加されました。このうち、スライスから配列ポインタへの変換が実行時にpanicを引き起こす場合があるため、タイプ変換が実行時にpanicを引き起こす可能性があることを考慮する必要があります。新しいプログラムを書く場合も、以前と同様に、unsafe.Pointerの安全ルールに従う必要があります。 === Go 1.16 === Go 1.16が、2021年2月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.16 | title = Go 1.16 Release Notes - The Go Programming Language | date = 2021/02/16 | accessdate = 2023-03-06 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.16 | title = Go 1.16 is released! - The Go Programming Language | date = 2021/02/16 | accessdate = 2023-03-06 }}</ref>。 {{Main|[https://go.dev/doc/go1.16 Go 1.16 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.16 Go 1.16 is released! The Go Blog]}} Go 1.16では、ツールチェーン、ランタイム、ライブラリの実装が変更されています。Go 1の互換性を維持しながら、ほとんどのプログラムが従来通りにコンパイルおよび実行できるようになっています。言語には変更はありません。 === Go 1.15 === Go 1.15が、2020年8月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.15 | title = Go 1.15 Release Notes - The Go Programming Language | date = 2020/08/11 | accessdate = 2023-03-12 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.15 | title = Go 1.15 is released! - The Go Programming Language | date = 2020/08/11 | accessdate = 2023-03-12 }}</ref>。 {{Main|[https://go.dev/doc/go1.15 Go 1.15 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.15 Go 1.15 is released! The Go Blog]}} Go 1.15では、リンカーの大幅な改良、高いコア数での小規模オブジェクトの割り当ての改善、X.509 CommonNameの非推奨化、そして新しい埋め込みtzdataパッケージの追加が含まれています。 === Go 1.14 === Go 1.14が、2020年2月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.14 | title = Go 1.14 Release Notes - The Go Programming Language | date = 2020/02/25 | accessdate = 2023-03-12 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.14 | title = Go 1.14 is released! - The Go Programming Language | date = 2020/02/25 | accessdate = 2023-03-12 }}</ref>。 {{Main|[https://go.dev/doc/go1.14 Go 1.14 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.14 Go 1.14 is released! The Go Blog]}} Go 1.14では、オーバーラップするインターフェースの提案により、埋め込まれたインターフェースで同じ名前とシグネチャを持つメソッドを許可するようになりました。しかし、インターフェース内で宣言されたメソッドは以前と同様にユニークである必要があります。 === Go 1.13 === Go 1.13が、2019年2月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.13 | title = Go 1.13 Release Notes - The Go Programming Language | date = 2019/09/03 | accessdate = 2023-03-12 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.13 | title = Go 1.13 is released! - The Go Programming Language | date = 2019/09/03 | accessdate = 2023-03-12 }}</ref>。 {{Main|[https://go.dev/doc/go1.13 Go 1.13 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.13 Go 1.13 is released! The Go Blog]}} Go 1.13では、数字リテラルの接頭辞が変更され、バイナリ整数、8進数整数、16進数浮動小数点数、虚数リテラル、数字区切りが使用できるようになりました。さらに、符号付きシフトカウントの制限が撤廃され、制限がなくなりました。これらの変更は、コンパイラの変更によって実現されました。Go 1.13を使用するには、go.modファイルで言語バージョンを指定する必要があります。 === Go 1.12 === Go 1.12が、2019年2月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.12 | title = Go 1.12 Release Notes - The Go Programming Language | date = 2019/02/25 | accessdate = 2024/11/13 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.12 | title = Go 1.12 is released! - The Go Programming Language | date = 2019/02/25 | accessdate = 2024/11/13 }}</ref>。 Go 1.12のリリースには、いくつかの新機能と改善が含まれ、Go言語のパフォーマンスやユーザビリティがさらに向上しました。以下が主な変更点です。 {{Main|[https://go.dev/doc/go1.12 Go 1.12 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.12 Go 1.12 is released! The Go Blog]}} ; 主要な新機能: :# Windows向けに、標準ライブラリがコントロールグループのサポートやシステムコールの改善により、性能向上と安定性が強化されました。 :# macOS向けの新しいサポートとして、ヒープメモリ使用量の削減や効率化が進められました。 ; パフォーマンスの改善点: :# 文字列操作の最適化が行われ、<code>strings.Trim</code>や<code>strings.Index</code>のパフォーマンスが向上しました。 :# 並列ガベージコレクションが改良され、メモリ管理の効率が向上しています。 :# コンパイラの境界チェックが一部のパターンで自動的に省略されるようになり、コード生成の効率がさらに向上しました。 ; デバッグ機能の改善: :# より正確な変数位置とスタック情報の提供により、デバッグ体験が改善されています。 :# 新たにDWARF生成の機能が拡充され、特に最適化コードにおいて、デバッグ情報の信頼性が高まりました。 ; ランタイムの改善: :# Windows上で、64ビットプロセスのアドレス空間使用が最適化され、より多くのメモリを使用可能になりました。 :# Goランタイムのシグナルハンドリングが強化され、システムシグナルの処理能力が向上しました。 ; 標準ライブラリの改善: :# <code>crypto/x509</code>パッケージで、証明書の検証がmacOSのシステム証明書ストアを使用するようになり、macOSでの信頼性が向上しました。 :# <code>net/http</code>において、HTTP/2の接続管理が改善され、特に大量接続環境での安定性が増しました。 :# <code>os</code>パッケージの<code>Process.Signal</code>がWindowsでも利用可能となり、Windows上のプロセス管理機能が強化されました。 ; ツールの改善: :# <code>go test</code>コマンドに<code>-json</code>フラグが追加され、テスト結果をJSON形式で出力できるようになりました。 :# goコマンドが<code>go.sum</code>ファイルを自動的に更新し、依存関係の信頼性が向上しています。 :# <code>gofmt</code>において、特定のコードパターンの整形が改良され、より一貫したコードスタイルが保たれます。 また、OpenBSD 6.4以降、macOS 10.11 El Capitan以降、またはWindows 7以降が必要となり、これらのOSの以前のバージョンのサポートが終了しました。リリースノートでは、Go 1の互換性は維持されており、ほとんどのGoプログラムは以前と同様に動作すると述べられています。 === Go 1.11 === Go 1.11が、2018年8月にリリースされました<ref>{{cite book | url = https://go.dev/doc/go1.11 | title = Go 1.11 Release Notes - The Go Programming Language | date = 2018/08/24 | accessdate = 2024/11/13 }}</ref><ref>{{cite book | url = https://go.dev/blog/go1.11 | title = Go 1.11 is released! - The Go Programming Language | date = 2018/08/24 | accessdate = 2024/11/13 }}</ref>。 Go 1.11のリリースでは、いくつかの重要な新機能と改善が含まれています。最も注目すべき変更点は以下です。 {{Main|[https://go.dev/doc/go1.11 Go 1.11 Release Notes - The Go Programming Language]|[https://go.dev/blog/go1.11 Go 1.11 is released! The Go Blog]}} ; 主要な新機能: :# モジュールサポートの実験的な導入により、GOPATHに依存しない開発が可能になりました。バージョン管理と依存関係管理が統合され、より信頼性の高いビルドが実現できます。 :# WebAssembly(js/wasm)の実験的なポートが追加され、syscall/jsパッケージを通じてJavaScriptとの連携が可能になりました。 :# RISCVアーキテクチャ向けのGOARCH値("riscv"と"riscv64")が予約されました。 ; パフォーマンスの改善点: :# マップのクリア操作が最適化され、<code>for k := range m { delete(m, k) }</code>のようなコードが効率的に実行されるようになりました。 :# スライス拡張の<code>append(s, make([]T, n)...)</code>が最適化されました。 :# コンパイラの境界チェックと分岐除去が大幅に改善され、より効率的なコードが生成されるようになりました。 ; デバッグ機能の改善: :# 最適化されたバイナリのデバッグ情報が大幅に改善され、変数位置情報、行番号、ブレークポイント位置がより正確になりました。 :# DWARFセクションがデフォルトで圧縮されるようになりました。 :# デバッガー内からのGo関数呼び出しが実験的にサポートされました。 ; ランタイムの改善: :# スパースヒープレイアウトの採用により、Goヒープサイズの制限(従来は512GiB)が撤廃されました。 :# macOSとiOSで、カーネルの直接呼び出しの代わりにlibSystem.dylibを使用するように変更され、将来のOSバージョンとの互換性が向上しました。 ; 標準ライブラリの改善: :# <code>crypto/cipher</code>パッケージに、非標準のタグ長をサポートするGCM実装が追加されました。 :# <code>net/http</code>の<code>Transport</code>型に、ホストごとの最大接続数を制限する<code>MaxConnsPerHost</code>オプションが追加されました。 :# <code>os</code>パッケージに、ユーザー固有のキャッシュディレクトリを取得する<code>UserCacheDir</code>関数が追加されました。 ; ツールの改善: :# 環境変数<code>GOFLAGS</code>が導入され、goコマンドのデフォルトフラグを設定できるようになりました。 :# godocのWebサーバーが、APIの新機能がどのGoバージョンで導入されたかを表示するようになりました。 また、OpenBSD 6.2以降、macOS 10.10 Yosemite以降、またはWindows 7以降が必要となり、これらのOSの以前のバージョンのサポートが終了しました。リリースノートでは、Go 1の互換性は維持されており、ほとんどのGoプログラムは以前と同様に動作すると述べられています。 ==脚註 == <references /> == 参考文献 == *{{cite book | url = https://go.dev/ref/spec | title = The Go Programming Language Specification | date = JJune 13, 2024 | publisher = The Go website }} == 外部リンク == {{Wikipedia|Go (プログラミング言語)|Go}} {{Wikiversity|Topic:Go|Go}} * [https://go.dev/ The Go Programming Language] - 公式サイト * [https://go.dev/play/ The Go Playground] {{DEFAULTSORT:GO}} [[Category:Go|*]] [[Category:プログラミング言語]] {{NDC|007.64}} j2y5bmtsovs3msk1fet9wn2z1avehlu Go/メソッドとインターフェース 0 31356 263744 223986 2024-11-18T05:19:06Z Ef3 694 校閲と推敲 263744 wikitext text/x-wiki {{Nav}} == Goはオブジェクト指向言語? == Goはオブジェクト指向の機能を持っているものの、従来のオブジェクト指向言語とは異なるアプローチを取っています。 まず、Goにはクラスという概念はありません。代わりに、構造体(<code>struct</code>)を用いて型を定義します。Goでは、型の定義にメソッドを追加することで、オブジェクト指向プログラミングに必要な基本的な機能を提供しています。これにより、オブジェクト指向の考え方を実現することができます。 Goのメソッドは、クラスベースのオブジェクト指向言語におけるメソッドとは異なり、Kotlinの拡張関数に似た性質を持っています。 また、Goはインターフェース(<code>interface</code>)をサポートしています。インターフェースは、実装すべきメソッドを定義する抽象的な型であり、実装の詳細を指定する必要はありません。インターフェースは複数の型によって実装可能で、ポリモーフィズムを実現します。 さらに、Goにはクラスの継承機能はありません。代わりに「埋め込み(embedding)」という仕組みを利用します。埋め込みは、ある構造体に別の構造体を埋め込むことで、継承に似た機能を提供します。 このように、Goは従来のオブジェクト指向言語とは異なるアプローチを取りますが、オブジェクト指向プログラミングの基本的な要素を備えています。 == メソッド == === メソッド呼び出し === Goでは、メソッド呼び出しにドット記法が使用されます。例えば、以下のような形式で呼び出します: :<syntaxhighlight lang=text> オブジェクト.メソッド(引数) </syntaxhighlight> === メソッド定義 === Goでは、構造体やその他の型にメソッドを定義できます。メソッドは、通常の関数と同様にパラメータを取りますが、最初のパラメータには、メソッドが呼び出される型のインスタンスを指定する必要があります。このパラメータは「レシーバー」と呼ばれ、通常、最初の文字を小文字にした名前を付けます。 例:[https://play.golang.org/p/XhZw6iPBzta メソッドの例] :<syntaxhighlight lang=go copy> package main import "fmt" type Number int func (n Number) pow() Number { return n * n } func main() { n := Number(7) m := n.pow() fmt.Printf("%v(%T)\n", m, m) } </syntaxhighlight> ;実行結果: :<syntaxhighlight lang=text> 49(main.Number) </syntaxhighlight> 解説: * <code>type Number int</code>:Goの組み込み型にはメソッドを定義できないため、型定義を行います(この例では<code>Number</code>という新しい型を定義しています)。 * メソッド定義: :<syntaxhighlight lang=go copy> func (n Number) pow() Number { return n * n } </syntaxhighlight> ここで、<code>(n Number)</code>はレシーバーで、<code>pow</code>がメソッド名です。レシーバーがあることで、これは関数とは異なることがわかります。 * メソッド呼び出し: *:<syntaxhighlight lang=go copy> m := n.pow() </syntaxhighlight> <code>n.pow()</code>がメソッドコールであり、<code>n.</code>は関数呼び出しにはない、メソッド特有のレシーバーを示しています。 * <code>fmt.Printf</code>での表示: *:<syntaxhighlight lang=go copy> fmt.Printf("%v(%T)\n", m, m) </syntaxhighlight> ここでは、C言語の<code>printf</code>にはない<code>%v</code>(値の表示)と<code>%T</code>(型名の表示)を使っています。この出力結果から、Goの<code>fmt</code>パッケージがどのように動作するか、また型をどのように表示するかについて理解できます。 Goの標準ライブラリである<code>reflect</code>パッケージの<code>TypeOf</code>関数を使用して型情報を取得しているため、型名の表示が可能です。 == インターフェース == まず次のコードを観てみましょう。 ;[https://play.golang.org/p/NQWyuMYdMr8 例] :<syntaxhighlight lang=go line copy> package main import "fmt" type GeoCoord struct { longitude, latitude float64 } func main() { sites := map[string]GeoCoord{ "東京駅": {139.7673068, 35.6809591}, "シドニー・オペラハウス": {151.215278, -33.856778}, "グリニッジ天文台": {-0.0014, 51.4778}, } for name, gc := range sites { fmt.Printf("%v: %v\n", name, gc) } } </syntaxhighlight> ;実行例:<syntaxhighlight lang=go copy> 東京駅: {139.7673068 35.6809591} シドニー・オペラハウス: {151.215278 -33.856778} グリニッジ天文台: {-0.0014 51.4778} </syntaxhighlight> fmt.Printf の "%v は便利ですね。ユーザー定義の型の変数を渡しても良きに計らってくれます。 === fmt.Stringer === ユーザー定義の型の変数を、応用に即した形式で文字列化したいケースは多々あります。 ;[https://play.golang.org/p/yTrN1xZqgkd Stringメソッドの例]:<syntaxhighlight lang=go highlight="9-21" line copy> package main import "fmt" type GeoCoord struct { longitude, latitude float64 } func (gc GeoCoord) String() string { ew, ns := "東経", "北緯" long, lat := gc.longitude, gc.latitude if long < 0.0 { ew = "西経" long = -long } if lat < 0.0 { ns = "南緯" lat = -lat } return fmt.Sprintf("(%s: %f, %s: %f)", ew, long, ns, lat) } func main() { sites := map[string]GeoCoord{ "東京駅": {139.7673068, 35.6809591}, "シドニー・オペラハウス": {151.215278, -33.856778}, "グリニッジ天文台": {-0.0014, 51.4778}, } for name, gc := range sites { fmt.Printf("%v: %v\n", name, gc) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 東京駅: (東経: 139.767307, 北緯: 35.680959) シドニー・オペラハウス: (東経: 151.215278, 南緯: 33.856778) グリニッジ天文台: (西経: 0.001400, 北緯: 51.477800) </syntaxhighlight> :GeoCoord 型にメソッド String() を定義しました。 :実行結果をご覧になると判る通り String() が %v で使われています。 これは、どういうことでしょうか?Printfが定義されてるfmtパッケージの働きです。具体的には、 ;[https://golang.org/src/fmt/print.go fmt.Stringer]:<syntaxhighlight lang=go copy> type Stringer interface { String() string } </syntaxhighlight> String()メソッド1つが定義されたインターフェース型の型fmt.Stringerが fmt パッケージの中で参照されているため、型にString()メソッドが定義されていれば、ディフォルトの構造体文字列化に変わってString()メソッドが使われるからです。 ==== 大圏距離を求めるメソッドを追加 ==== ;[https://go.dev/play/p/7pdVaR12AM1 大圏距離を求めるメソッドdistanceを追加]:<syntaxhighlight lang=go highlight="26-31" line copy> package main import ( "fmt" "math" ) type GeoCoord struct { longitude, latitude float64 } func (gc GeoCoord) String() string { ew, ns := "東経", "北緯" long, lat := gc.longitude, gc.latitude if long < 0.0 { ew = "西経" long = -long } if lat < 0.0 { ns = "南緯" lat = -lat } return fmt.Sprintf("(%s: %f, %s: %f)", ew, long, ns, lat) } func (gc GeoCoord) distance(other GeoCoord) float64 { i := math.Pi / 180 r := 6371.008 return math.Acos(math.Sin(gc.latitude*i)*math.Sin(other.latitude*i)+ math.Cos(gc.latitude*i)*math.Cos(other.latitude*i)*math.Cos(gc.longitude*i-other.longitude*i)) * r } func main() { sites := map[string]GeoCoord{ "東京駅": {139.7673068, 35.6809591}, "シドニー・オペラハウス": {151.215278, -33.856778}, "グリニッジ天文台": {-0.0014, 51.4778}, } for name, gc := range sites { fmt.Printf("%v: %v\n", name, gc) } ks := []string{} for k, _ := range sites { ks = append(ks, k) } for i := 0; i < len(sites); i++ { ksi, ksx := ks[i], ks[(i+1)%len(sites)] fmt.Printf("%v - %v: %v [km]\n", ksi, ksx, sites[ksi].distance(sites[ksx])) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 東京駅: (東経: 139.767307, 北緯: 35.680959) シドニー・オペラハウス: (東経: 151.215278, 南緯: 33.856778) グリニッジ天文台: (西経: 0.001400, 北緯: 51.477800) 東京駅 - シドニー・オペラハウス: 7823.269299386704 [km] シドニー・オペラハウス - グリニッジ天文台: 16987.2708377249 [km] グリニッジ天文台 - 東京駅: 9560.546566490015 [km] </syntaxhighlight> :2点間の距離 func (gc GeoCoord) distance(other GeoCoord) float64 を定義しました。 {{See also|[[W:大円距離|大圏距離]]}} === interface{} === interface{} は、JavaScript の変数や VB の Variant 型の様に全てのインスタンスを参照できる型として振る舞います。 ;[https://play.golang.org/p/rHYb5oBNdS6 interface{}]:<syntaxhighlight lang=go line copy> package main import ( "fmt" ) func main() { var i interface{} fmt.Println(i) i = 0 fmt.Println(i) i = "abc" fmt.Println(i) i = []float64{1, 2, 3, 4, 5} fmt.Println(i) i = struct { name string age int }{"joe", 14} fmt.Println(i) } </syntaxhighlight> ;実行例:<syntaxhighlight lang=go copy> <nil> 0 abc [1 2 3 4 5] {joe 14} </syntaxhighlight> === 型アサーション === interfaceから値を取り出す方法が型アサーションです。 ;[https://play.golang.org/p/yjgjJcHwqB9 型アサーション]:<syntaxhighlight lang=go line copy> package main import "fmt" func main() { i := interface{}("String") s := i.(string) fmt.Println(s) // n := i.(int) ⇒ panic: interface conversion: interface {} is string, not int n, ok := i.(int) fmt.Println(n, ok) // 0 false x, ok := i.(string) fmt.Println(x, ok) // hello true } </syntaxhighlight> ;実行例:<syntaxhighlight lang=go copy> String 0 false String true </syntaxhighlight> === interfaceと型スイッチ === ;[https://play.golang.org/p/DPGW_zt8Z5m interfaceと型スイッチ]:<syntaxhighlight lang=go line copy> package main import "fmt" func main() { ts(42) ts("Sting") ts(nil) } func ts(i interface{}) { switch v := i.(type) { case int: fmt.Printf("Power of %v is %v\n", v, v*v) case string: fmt.Printf("%q is %v bytes long\n", v, len(v)) default: fmt.Printf("I don't know about type %T!\n", v) } } </syntaxhighlight> ;実行例:<syntaxhighlight lang=go copy> Power of 42 is 1764 "Sting" is 5 bytes long I don't know about type <nil>! </syntaxhighlight> :型スイッチでは、switch の式の部分に インスタンス.(type) のように型アサーションの構文を使います。 :型スイッチでは、case は式ではなく型を取ります。 {{DEFAULTSORT:めそつとといんたふえす}} [[Category:Go]] 7e6lnbnd7vfvlb5ipg7fxec0w43paca COBOL 0 32370 263765 244013 2024-11-18T09:53:10Z Ef3 694 /*改廃された技術*/ COBOLの改廃された技術や利用が推奨されない技術は、言語の標準化、現代的なプログラミング手法の導入、保守性の向上などによって置き換えられてきました。以下に、代表的な技術を示します。 263765 wikitext text/x-wiki <small>[[メインページ]] > [[工学]] > [[情報技術]] > [[プログラミング]] > [[COBOL]]</small> COBOL(コボル)は、1959年に事務処理用に開発されたプログラミング言語です。 名前は「Common Business Oriented Language」(共通事務処理用言語)に由来します。 [[Fortran]]・[[Lisp]]とともに最も古いプログラミング言語の1つですが、 それ故、多くのソフトウェア資産の蓄積があり、2022年の今日でも現役のプログラミング言語として使用されています。 == COBOLの特徴 == COBOLの特徴を簡単なコード例とともに示します。以下は、COBOLのいくつかの特徴を示す基本的なコードスニペットです。 # データ定義の明確さ #: この例では、<code>Employee-Record</code>というデータ構造を定義しています。各フィールドは<code>PIC</code>(Picture)クラウスを使用してデータの型と桁数を指定しています。 #:<syntaxhighlight lang=cobolfree copy> IDENTIFICATION DIVISION. PROGRAM-ID. SampleProgram. DATA DIVISION. WORKING-STORAGE SECTION. 01 Employee-Record. 05 Employee-ID PIC 9(5). 05 Employee-Name PIC X(20). 05 Employee-Salary PIC 9(7)V99. PROCEDURE DIVISION. </syntaxhighlight> # 構造化プログラミング #: COBOLは構造化プログラミングをサポートしており、<code>IF</code>文を通じて条件分岐を行います。 #:<syntaxhighlight lang=cobolfree copy> IF Employee-Salary > 50000 DISPLAY 'High Salary'. ELSE DISPLAY 'Low Salary'. </syntaxhighlight> # データベースへのアクセス #: 上記の例では、COBOLがデータベースへのアクセスを可能にするためのSQL文を使用しています。 #:<syntaxhighlight lang=cobolfree copy> EXEC SQL DECLARE EmployeeCursor CURSOR FOR SELECT Employee-Name, Employee-Salary FROM EmployeeTable WHERE Department = 'IT'. EXEC SQL OPEN EmployeeCursor. PERFORM UNTIL SQLCODE NOT = 0 EXEC SQL FETCH NEXT FROM EmployeeCursor INTO :Employee-Name, :Employee-Salary END-EXEC. DISPLAY 'Employee: ' Employee-Name 'Salary: ' Employee-Salary. END-PERFORM. EXEC SQL CLOSE EmployeeCursor. </syntaxhighlight> == 簡単なCOBOLプログラム == 以下は簡単なCOBOLのプログラムです。 ;[https://paiza.io/projects/TLWqnDzo0jQ0VBCz8EgLZA?language=cobol hello.cbl]:<syntaxhighlight lang=cobolfree copy> IDENTIFICATION DIVISION. PROGRAM-ID. HELLO. PROCEDURE DIVISION. DISPLAY "Hello World 12345!". STOP RUN. </syntaxhighlight> ;実行結果:<syntaxhighlight lang="text"> Hello World! </syntaxhighlight> {{コラム|width=100%|オンラインのコンパイル・実行環境|2= [https://paiza.io/ paiza.IO] の様な、オンラインのコンパイル・実行環境であればウェブブラウザーだけで、COBOLのプログラムをコンパイル・実行できます。 上の例の、[https://paiza.io/projects/TLWqnDzo0jQ0VBCz8EgLZA?language=cobol hello.cbl] のようなリンク先を開くと、ウェブブラウザー上でコンパイル・実行することが出来ます。 }} == 環境構築 == === GnuCobol === GnuCOBOL(旧OpenCOBOL、短期間GNU Cobolとして知られていました)は、COBOLのフリーな実装です。 GnuCOBOLは、ネイティブのCコンパイラを使用するCへのトランスコンパイラです。 ==== GNU/Linuxの場合 ==== ディストリビューションにより、パッケージマネージャとパッケージ体系に違いがありますが、例えば Fedora Linux では、 <syntaxhighlight lang="bash"> $ sudo dnf install gnucobol $ cobc --version cobc (GnuCOBOL) 3.1.2.0 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart Built Jan 26 2021 00:00:00 Packaged Dec 23 2020 12:04:58 UTC C version "11.0.0 20210123 (Red Hat 11.0.0-0)" loading standard configuration file 'default.conf' </syntaxhighlight> :で導入およびバージョンの確認できます。 === FreeBSDの場合 === FreeBSD Ports/Packages Collection の、<code>ports/lang/gnucobol</code> にあるので、 :<syntaxhighlight lang="csh"> % sudo make -C /usr/ports/lang/gnucobol all install clean </syntaxhighlight> でビルドしインストールできます。 また :<syntaxhighlight lang="csh"> % sudo pkg install gnu-cobol-3.1.2_1 </syntaxhighlight> でビルド済みパッケージをインストールできますが、GnuCOBOL自身のバージョンアップやportsのパッチレベルの更新で <code>gnu-cobol-3.1.2_1</code>の部分は変わるので、 :<syntaxhighlight lang="csh"> % pkg search cobol gnu-cobol-3.1.2_1 Open-source COBOL compiler </syntaxhighlight> の様に、最初に最新のパッケージ名を確認してください。 ;バージョンを確認:<syntaxhighlight lang="shell"> % cobc -V cobc (GnuCOBOL) 3.1.2.0 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart Built Nov 12 2022 15:48:13 Packaged Dec 23 2020 12:04:58 UTC C version "FreeBSD Clang 14.0.5 (https://github.com/llvm/llvm-project.git llvmorg-14.0.5-0-gc12386ae247c)" % _ </syntaxhighlight> == コマンドラインでのコンパイルと実行 == [[#簡単なCOBOLプログラム|簡単なCOBOLプログラム]]のソースコードを hello.cbl という名前で保存し、コンパイルし実行してみよう。 :<syntaxhighlight lang="console" Line> % cobc -x hello.cbl % ls hello hello.cbl % ./hello Hello World 12345! </syntaxhighlight> # 実行ファイル <code>hello</code> を得るためにCOBOLコンパイラ cobc に −x をつけてコンパイル #* -x をつけないとシェアードライブラリが出来、これは実行できません。 # 確認してみると # hello が出来ている # 早速実行すると # 正しく表示 == COBOLの正書法 == COBOLの正書法には、自由書式正書法と固定書式正書法の2種類があります。 それぞれの正書法には以下のような特徴があります。 ;固定形式正書法 :一連番号領域、標識領域、プログラム記述領域など、行内の文字位置によって使い方が明確に定義されている書き方です。 ;自由書式正書法 :一連番号領域や標識領域がなく、プログラムは行のどの位置にも書くことが出来ます。 処理系によっては、コマンドラインオプションなどで正書法の切り替えが可能な場合があるので、詳しくは使用している処理系のマニュアルを参照してください。 == COBOLプログラムの構成 == === COBOLプログラムのトップレベルの構成 === COBOLプログラムのトップレベルは * 見出し部(IDENTIFICATION DIVISION) * 環境部(ENVIRONMENT DIVISION) * データ部(DATA DIVISION) * 手続き部(PROCEDURE DIVISION) の4つのパートから構成され、順序もこの順序である必要があります。 === 見出し部(IDENTIFICATION DIVISION) === IDENTIFICATION DIVISIONは、COBOLプログラムの最初のパートで、 プログラム名、作成者、作成日などのプログラム保守情報を含みます。 これらは、見出し部の段落として記述します。 :<syntaxhighlight lang=cobolfree copy> IDENTIFICATION DIVISION. PROGRAM-ID. SampleProgram. AUTHOR. YourName. </syntaxhighlight> === 環境部(ENVIRONMENT DIVISION) === ENVIRONMENT DIVISIONは、COBOLプログラムの2番目のパートで、 作成するプログラムをコンパイルして実行するコンピュータの名前、環境変数の受け渡しに関する情報、プログラムとの間で読み書きするファイルの名前と種類を定義します。 :<syntaxhighlight lang=cobolfree copy> ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. IBM-PC. </syntaxhighlight> === データ部(DATA DIVISION) === DATA DIVISIONはCOBOLプログラムの3番目のパートで、これまでのDIVISIONはCOBOLプログラムを構築するためのメタデータで、 DATA DIVISIONからが実際にプログラムを構築していくところだと言えます。 DATA DIVISIONでは、入出力ファイルの配置、データ項目(変数)、外部プログラムとのインタフェース(引数)など、プログラムで扱うすべてのデータを定義します。 :<syntaxhighlight lang=cobolfree copy> DATA DIVISION. WORKING-STORAGE SECTION. 01 Employee-Name PIC X(30). 01 Employee-Age PIC 9(3). FILE SECTION. 01 Employee-File. 05 Employee-ID PIC 9(5). 05 Employee-Salary PIC 9(7)V99. </syntaxhighlight> === 手続き部(PROCEDURE DIVISION) === PROCEDURE DIVISIONは、COBOLプログラムの最後のパートで、プログラムが実行する処理を記述します。 :<syntaxhighlight lang=cobolfree copy> PROCEDURE DIVISION. DISPLAY 'Enter employee name: '. ACCEPT Employee-Name. DISPLAY 'Enter employee age: '. ACCEPT Employee-Age. IF Employee-Age > 30 DISPLAY 'Senior Employee' ELSE DISPLAY 'Junior Employee'. </syntaxhighlight> 前3つのDIVISIONとは異なり、手続き部には定義された節や段落の様な既定の構造はありません。 節や段落は、プログラマが必要に応じて作成します。 COBOLにおいて、FortranのSubroutineやC言語の関数に相当する構文は、主に「サブルーチン」と「関数」です。以下に、それぞれの概要を説明します。 # サブルーチン(Subroutine): #* COBOLにおいて、サブルーチンはプログラム内の再利用可能なブロックを指します。サブルーチンは、PERFORM文を使用して呼び出されます。サブルーチン内で実行される処理は、呼び出し元に戻るまで制御が戻りません。 #:<syntaxhighlight lang=cobolfree copy> IDENTIFICATION DIVISION. PROGRAM-ID. MainProgram. DATA DIVISION. WORKING-STORAGE SECTION. 01 Counter PIC 9(3) VALUE 0. PROCEDURE DIVISION. PERFORM Display-Message THRU Display-Message. DISPLAY 'Back in the main program.'. Display-Message. ADD 1 TO Counter. DISPLAY 'Message number ' Counter. </syntaxhighlight> #: 上記の例では、<code>Display-Message</code>がサブルーチンとなり、これを<code>PERFORM</code>文で呼び出しています。 # 関数(Function): #* COBOLにおいて、関数は一般的なプログラミング言語での関数と同様、特定の計算や処理を実行し、その結果を呼び出し元に返すものです。関数は<code>FUNCTION</code>キーワードを使用して呼び出されます。 #:<syntaxhighlight lang=cobolfree copy> IDENTIFICATION DIVISION. PROGRAM-ID. MainProgram. DATA DIVISION. WORKING-STORAGE SECTION. 01 Value-A PIC 9(3) VALUE 10. 01 Value-B PIC 9(3) VALUE 20. 01 Result PIC 9(3). PROCEDURE DIVISION. COMPUTE Result = Add-Values(Value-A, Value-B). DISPLAY 'The result is: ' Result. FUNCTION Add-Values. PARAMETERS Value-X, Value-Y. COMPUTE Add-Values = Value-X + Value-Y. </syntaxhighlight> #:上記の例では、<code>Add-Values</code>が関数となり、これを<code>COMPUTE</code>文で呼び出しています。 COBOLのサブルーチンと関数は、プログラムの構造を明確にし、再利用性を高めるために使われます。 {{コラム|width=100%|他言語のプログラマのCOBOLへの移行での注意点|2=他のプログラミング言語からCOBOLへの移行においては、特定のプログラマがCOBOLという異なる言語に適応するためのいくつかの注意点があります。 以下は、他の言語のプログラマがCOBOLに移行する際に留意すべき点です。 ;自然言語に近い文法:COBOLは英語に近い自然言語の文法を持つため、通常のプログラミング言語とは異なる表現があります。英文のような記述やDIVISION、SECTION、PARAGRAPHの概念に慣れる必要があります。 ;データ指向プログラミング:COBOLは主にデータ指向プログラミングに焦点を当てています。他のプログラミング言語でよく見られるオブジェクト指向プログラミングの概念とは異なります。データ構造やレコードの定義が特に重要です。 ;ビジネスアプリケーションの特性:COBOLは主にビジネスアプリケーションの開発に使用されており、金融や保険などの分野で広く利用されています。ビジネスルールの理解や、大規模なデータ処理、バッチ処理の概念について理解が必要です。 ;移植性の懸念:COBOLは主にメインフレームやミッドレンジコンピュータ上で実行されることが多いです。他の言語と異なる実行環境に適応するために、COBOLが実行されるプラットフォームに関する理解が必要です。 ;標準ライブラリの習得:COBOLの標準ライブラリは、ビジネスアプリケーションに特有の機能を提供します。他のプログラミング言語の標準ライブラリとは異なるため、これを理解し、活用することが必要です。 ;ツールや開発環境の違い:COBOL用の開発ツールや統合開発環境は他の言語とは異なるものがあります。これらのツールや環境に慣れる必要があります。 COBOLは長寿で広く使用されている言語ですが、他の言語からの移行者にとっては新しい概念や文法に適応する過程があるかもしれません。十分なトレーニングと実践が必要です。 }} == COBOLの変遷 == COBOL(Common Business-Oriented Language)は、ビジネスアプリケーション向けに開発されたプログラミング言語で、1959年にアメリカ国防総省の委員会が設立したCODASYL(Conference on Data Systems Languages)委員会によって設計されました。以下に、COBOLの変遷について簡単に説明します。 ; 初期の開発(1959年 - 1960年代): COBOLは、ビジネスアプリケーションのニーズに対応するために開発されました。この時期、主にメインフレームコンピュータで使用され、COBOLプログラムはバッチ処理やファイル処理に利用されました。 ;COBOL 60 :COBOLはANSI(American National Standards Institute)やISO(International Organization for Standardization)によって標準化され、これによって異なるベンダー間でのプログラムの互換性が向上しました。 :1959年に初めてCOBOLが発表され、その初版として知られています。しかし、このバージョンはあまり広く使われませんでした。 ;COBOL 61 (Revised COBOL 60):COBOL 60の修正版として、1961年に発表されました。これはCOBOLの最初の主要なリリースで、いくつかの文法の変更や追加が行われました。 ;COBOL 65:1965年にはCOBOL 65が発表され、新しい機能や拡張が導入されました。 ;COBOL 68:1968年にCOBOL 68が登場し、いくつかの機能が改訂され、新しい機能も導入されました。このバージョンは標準規格として広く受け入れられました。 ;COBOL 74:1974年に発表され、COBOL 68をベースにしていくつかの変更や追加が行われました。これにより、ファイル操作などが改善されました。 ;COBOL 85:1985年にはCOBOL 85が発表されました。これは大規模なリファクタリングが行われ、構造化プログラミングや新しいデータ型の導入などが含まれました。COBOL 85はANSIとISOによって標準化されました。 ;COBOL 2002:COBOL 2002は、2002年に登場しました。このバージョンでは、オブジェクト指向プログラミングのサポートやXMLの処理などが追加されました。 ;COBOL 2014:2014年に発表されたCOBOL 2014では、新しい機能や改訂が導入され、モダンな開発環境に対応するための取り組みが行われました。 これらのバージョンは、COBOLの進化を示しています。それぞれの規格で新しい機能や改善が導入され、COBOLは長い間にわたって広く利用され続けています。 == 改廃された技術 == COBOLの改廃された技術や利用が推奨されない技術は、言語の標準化、現代的なプログラミング手法の導入、保守性の向上などによって置き換えられてきました。以下に、代表的な技術を示します。 === ALTER文 === * '''サポート開始年:''' COBOL-60 * '''サポート終了年:''' COBOL 2002で非推奨 ; 廃止または衰退の理由 : プログラムの流れを動的に変更する機能であり、保守性が著しく低下し、スパゲッティコードの原因となるため。 ; 代替技術 : EVALUATE文や構造化プログラミング手法の使用が推奨されます。 === ENTER文 === * '''サポート開始年:''' COBOL-60 * '''サポート終了年:''' COBOL 85で廃止 ; 廃止または衰退の理由 : 他言語との連携のために使用されていましたが、標準化された呼び出し規約の登場により不要となりました。 ; 代替技術 : CALL文による標準的なサブプログラム呼び出しが推奨されます。 === NOTE段落 === * '''サポート開始年:''' 初期のCOBOL * '''サポート終了年:''' COBOL 2002で非推奨 ; 廃止または衰退の理由 : コメントとして使用されていましたが、より明確な方法が導入されました。 ; 代替技術 : アスタリスク(*)で始まるコメント行や>>による固定形式のコメントが推奨されます。 === EXAMINE文 === * '''サポート開始年:''' COBOL-60 * '''サポート終了年:''' COBOL 85で廃止 ; 廃止または衰退の理由 : 文字列操作機能として限定的で、より強力な代替手段が導入されました。 ; 代替技術 : INSPECT文による文字列操作が推奨されます。 === GO TO文(プロシージャ外への分岐) === * '''サポート開始年:''' COBOL-60 * '''サポート終了年:''' 現在も使用可能だが強く非推奨 ; 廃止または衰退の理由 : プログラムの構造を複雑にし、デバッグや保守を困難にするため。 ; 代替技術 : PERFORM文や構造化プログラミング手法の使用が推奨されます。 === TRANSFORM文 === * '''サポート開始年:''' 初期のCOBOL方言 * '''サポート終了年:''' 標準COBOLでは採用されず ; 廃止または衰退の理由 : ベンダー固有の機能であり、移植性に問題があったため。 ; 代替技術 : INSPECT文やSTRING/UNSTRING文による文字列操作が推奨されます。 === 固定形式プログラム記述 === * '''サポート開始年:''' COBOL-60 * '''サポート終了年:''' 現在も使用可能だが新規開発では非推奨 ; 廃止または衰退の理由 : パンチカードの制約に基づく古い形式で、可読性と保守性に問題があります。 ; 代替技術 : フリー形式のプログラム記述形式が推奨されます。 === ON文 === * '''サポート開始年:''' 初期のCOBOL * '''サポート終了年:''' COBOL 2002で非推奨 ; 廃止または衰退の理由 : 例外処理として不十分で、より体系的な方法が導入されました。 ; 代替技術 : DECLARATIVES部や構造化された例外処理の使用が推奨されます。 === DATA RECORDS句 === * '''サポート開始年:''' COBOL-60 * '''サポート終了年:''' COBOL 2002で非推奨 ; 廃止または衰退の理由 : ファイル記述において冗長で、より簡潔な方法が導入されました。 ; 代替技術 : RECORD句やモダンなファイル記述方法の使用が推奨されます。 == 脚註 == <references /> {{DEFAULTSORT:COBOL}} [[Category:COBOL|*]] [[Category:プログラミング言語]] htqnbumwfob91c8mdmhops6c0cuhqmg Go/ブロック・宣言とスコープ 0 32545 263745 201517 2024-11-18T05:50:47Z Ef3 694 校閲と推敲 263745 wikitext text/x-wiki {{Nav}} = ブロック = ブロック(''Blocks'')は、一致する波括弧の中に宣言とステートメントを並べた、空の可能性のあるシーケンスです<ref name="Blocks">{{cite book | url = https://golang.org/ref/spec#Blocks | title = The Go Programming Language Specification | chapter = Blocks ¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 ;構文:<syntaxhighlight lang=ebnf> Block = "{" StatementList "}" ; StatementList = { Statement ";" } ; </syntaxhighlight> ソースコードには、明示的なブロックの他に、暗黙のブロックがあります。 # すべてのGoのソーステキストを包含する''ユニバーサルブロック''(''universe block'')があります。 # 各パッケージには、そのパッケージの全てのGoソースを含む''package block''があります。 # 各ファイルには、そのファイルに含まれる全てのGoのソースを含む''file block''があります。 # 各 "if"、"for"、"switch" 文は、それぞれの暗黙のブロックとみなされます。 # "switch "または "select" 文の各節は、暗黙のブロックとして機能します。 ブロックはスコーピングに影響を与えます。 = 宣言とスコープ = 宣言とスコープ(''Declarations and scope'')<ref name="Declarations_and_scope">{{cite book | url = https://golang.org/ref/spec#Declarations_and_scope | title = The Go Programming Language Specification | chapter = Declarations and scope¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref> 宣言は、空白でない識別子を、定数、型、変数、関数、ラベル、パッケージに結びつけるものです。 プログラム内のすべての識別子は宣言されなければなりません。 同一ブロック内で2回宣言することはできず、ファイルブロックとパッケージブロックの両方で宣言することはできません。 空白の識別子は、他の識別子と同様に宣言の中で使用することができますが、結合を導入しないため、宣言されません。 パッケージブロックでは、識別子initはinit関数の宣言にのみ使用することができ、空白の識別子のように新しいバインディングを導入することはありません。 ;構文:<syntaxhighlight lang=ebnf> Declaration = ConstDecl | TypeDecl | VarDecl ; TopLevelDecl = Declaration | FunctionDecl | MethodDecl ; </syntaxhighlight> 宣言された識別子のスコープは、その識別子が指定された定数、型、変数、関数、ラベル、パッケージを示すソーステキストの範囲です。 Goはブロックを使って語彙的にスコープを設定します。 # 宣言済みの識別子のスコープは''ユニバーサルブロック''です。 # 定数、型、変数、トップレベルで宣言された関数(メソッドは除く)を示す識別子のスコープは、パッケージブロックです。 # インポートされたパッケージのパッケージ名のスコープは、インポート宣言のあるファイルのファイルブロックとなります。 # メソッドのレシーバー、関数の仮引数、結果変数を示す識別子のスコープは、関数本体となります。 # 関数内で宣言された定数や変数の識別子のスコープは、ConstSpecまたはVarSpec(短い変数宣言の場合はShortVarDecl)の末尾から、最も内側の包含ブロックの末尾までとなります。 # 関数内で宣言された型識別子のスコープは、TypeSpec内の識別子から始まり、最も内側の包含ブロックの終わりで終わります。 ブロックで宣言された識別子は、内側のブロックで再宣言することができる。内側の宣言の識別子がスコープ内にある間は、内側の宣言によって宣言されたエンティティを表します。 package節は宣言ではなく、パッケージ名はどのスコープにも表示されない。その目的は、同じパッケージに属するファイルを識別することと、インポート宣言のデフォルトのパッケージ名を指定することです。 === ラベルスコープ === ラベルは[[#ラベル付きステートメント|ラベル付きステートメント]]で宣言され、'''break''', '''continue''', '''goto''' 文で使用されます<ref name="Label_scopes">{{cite book | url = https://golang.org/ref/spec#Label_scopes | title = The Go Programming Language Specification | chapter = Label scopes¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 一度も使用されないラベルを定義することは違法です。 他の識別子とは異なり、ラベルはブロックスコープを持たず、ラベルではない識別子とは衝突しません。 ラベルのスコープは、ラベルが宣言されている関数のボディであり、ネストされた関数のボディは含まれません。 ==== ラベル付きステートメント ==== ラベル付けされたステートメントは、'''goto''', '''break''', '''continue''' 文のターゲットになることがあります<ref name="Labeled_statements">{{cite book | url = https://golang.org/ref/spec#Labeled_statements | title = The Go Programming Language Specification | chapter = Labeled statements¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 ;構文:<syntaxhighlight lang=ebnf> LabeledStmt = Label ":" Statement ; Label = identifier ; </syntaxhighlight> ;例:<syntaxhighlight lang=go copy> Error: log.Panic("error encountered") </syntaxhighlight> === ブランク識別子 === ブランク識別子はアンダースコア文字「_」で表されます<ref name="Blank_identifier">{{cite book | url = https://golang.org/ref/spec#Blank_identifier | title = The Go Programming Language Specification | chapter = Blank identifier¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 通常の(ブランクではない)識別子の代わりに匿名のプレースホルダーとして機能し、宣言、オペランド、代入において特別な意味を持ちます。 === 宣言済み識別子 === ユニバースブロックでは、いくつかの識別子が暗黙的に宣言されています<ref name="Predeclared_identifiers">{{cite book | url = https://golang.org/ref/spec#Predeclared_identifiers | title = The Go Programming Language Specification | chapter = Predeclared identifiers¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 {{See also|[[../キーワードと宣言済み識別子#宣言済み識別子|宣言済み識別子]]}} === エクスポートされた識別子 === 識別子は、他のパッケージからのアクセスを可能にするためにエクスポートすることができます。識別子は以下の場合にエクスポートされます<ref name="Exported_identifiers">{{cite book | url = https://golang.org/ref/spec#Exported_identifiers | title = The Go Programming Language Specification | chapter = Exported identifiers¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 # 識別子の名前の最初の文字が、Unicodeの大文字(Unicodeクラス "Lu")であること。 # 識別子がパッケージブロックで宣言されているか、フィールド名またはメソッド名であること。 それ以外の識別子はエクスポートされません。 === 識別子の一意性 === 識別子の集合が与えられたとき、識別子が集合内の他のすべてのものと異なる場合、その識別子は一意と呼ばれます<ref name="Uniqueness_of_identifiers">{{cite book | url = https://golang.org/ref/spec#Uniqueness_of_identifiers | title = The Go Programming Language Specification | chapter = Uniqueness of identifiers¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 2つの識別子が異なる場合とは、スペルが異なる場合や、異なるパッケージに含まれていてエクスポートされない場合などです。 それ以外の場合は、同じです。 === 定数宣言 === 定数宣言は、識別子のリスト(定数の名前)を定数式のリストの値に束縛します<ref name="Constant_declarations">{{cite book | url = https://golang.org/ref/spec#Constant_declarations | title = The Go Programming Language Specification | chapter = Constant declarations¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 識別子の数は式の数と等しくなければならず、左からn番目の識別子は右からn番目の式の値に束縛されます。 {{See also|[[../定数と変数#定数宣言|定数宣言]]}} === iota === 定数宣言の中で、宣言済み識別子 iota は、連続する型付けされていない整数定数を表します。その値は、定数宣言内のそれぞれのConstSpecのインデックスで、ゼロから始まります。この識別子は、関連する定数のセットを構築するために使用できます<ref name="Iota">{{cite book | url = https://golang.org/ref/spec#Iota | title = The Go Programming Language Specification | chapter = Iota¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref> {{See also|[[../定数と変数#iota|iota]]}} === 型宣言 === 型宣言は、識別子である型名を型に結びつけるものです。型宣言には、エイリアス宣言と型定義の2つの形式があります。<ref name="Type_declarations">{{cite book | url = https://golang.org/ref/spec#Type_declarations | title = The Go Programming Language Specification | chapter = Type declarations ¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 ;構文:<syntaxhighlight lang="ebnf"> TypeDecl = "type" ( TypeSpec | "(" { TypeSpec ";" } ")" ) ; TypeSpec = AliasDecl | TypeDef ; </syntaxhighlight> ;エイリアス宣言:エイリアス宣言は、識別子を与えられた型に結びつけるものです。 ;構文:<syntaxhighlight lang="ebnf"> AliasDecl = identifier "=" Type ; </syntaxhighlight> 識別子のスコープ内では、型のエイリアスとして機能します。 ;型定義:型定義は、与えられた型と同じ基本的な型と操作を持つ新しい別個の型を作成し、その型に識別子を結合します。 ;構文:<syntaxhighlight lang="ebnf"> TypeDef = identifier Type ; </syntaxhighlight> 新しい型は、定義された型と呼ばれます。この型は、作成された型を含め、他の型とは異なります。 === 変数宣言 === 変数宣言では、1つまたは複数の変数を作成し、対応する識別子を結合し、それぞれに型と初期値を与えます<ref name="Variable_declarations">{{cite book | url = https://golang.org/ref/spec#Variable_declarations | title = The Go Programming Language Specification | chapter = Variable declarations ¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 {{See also|[[../定数と変数#変数宣言|変数宣言]]}} === 短い変数宣言 === ;短い変数宣言:短い変数宣言は、以下の構文を使用します<ref name="Short_variable_declarations">{{cite book | url = https://golang.org/ref/spec#Short_variable_declarations | title = The Go Programming Language Specification | chapter = Short variable declarations ¶ | date = Jul 26, 2021 | publisher = The Go website }}</ref>。 ;構文:<syntaxhighlight lang="ebnf"> ShortVarDecl = IdentifierList ":=" ExpressionList ; </syntaxhighlight> : この構文は、初期化式を持つが型を持たない通常の変数宣言の短縮形です。 : この構文は、ユニバースブロック (''universe block'') の変数には適用できません。 : この構文は、if文, for文, switch文の初期化句(オプショナル)に使えます。 :;多値の短い変数宣言 ::(var と違って)同じ変数名を再宣言できる。 === 関数宣言 === <!-- Given the importance of functions, this section has always been woefully underdeveloped. Would be nice to expand this a bit. ---- 関数の重要性を考えると、このセクションはいつもひどく未開発です。 これを少し拡張するのはいいことだと思います。 --> 関数宣言(Function declarations)は、識別子である関数名を関数に結びつけるものです<ref name="Function_declarations">{{cite book | url = https://golang.org/ref/spec#Function_declarations | title = The Go Programming Language Specification | chapter = Function declarations¶ | date = March 10, 2022 | publisher = The Go website }}</ref>。 ;構文:<syntaxhighlight lang="ebnf"> FunctionDecl = "func" FunctionName [ TypeParameters ] Signature [ FunctionBody ] ; FunctionName = identifier ; FunctionBody = Block ; </syntaxhighlight> :Go1.18から、関数名と仮引数リストの前の丸括弧の間に鉤括弧でくくられた型パラメータを指定することが出来るようになりました。 関数のシグネチャが結果仮引数を宣言している場合、関数本体のステートメントリストは終了ステートメントで終わらなければなりません。 ;例:<syntaxhighlight lang=go copy> func IndexRune(s string, r rune) int { for i, c := range s { if c == r { return i } } // invalid: missing return statement } </syntaxhighlight> 関数宣言で型パラメータを指定した場合、関数名はジェネリック関数を表します。ジェネリック関数は、呼び出したり値として使用したりする前に、インスタンス化されなければなりません。 ;例:<syntaxhighlight lang=go copy> func min[T ~int|~float64](x, y T) T { if x < y { return x } return y } </syntaxhighlight> '''型パラメータを持たない'''関数宣言では、ボディを省略することができます。 このような宣言は、アセンブリルーチンのようなGoの外部で実装される関数のシグネチャを提供します。 ;例:<syntaxhighlight lang=go copy> func flushICache(begin, end uintptr) // 外部実装 </syntaxhighlight> === メソッド宣言 === メソッド(''A method'')とは、レシーバーを持つ関数です。メソッド宣言では、識別子であるメソッド名をメソッドに結びつけ、そのメソッドとレシーバーの基底型を関連付けます<ref name="Method_declarations">{{cite book | url = https://golang.org/ref/spec#Method_declarations | title = The Go Programming Language Specification | chapter = Method declarations¶ | date = March 10, 2022 | publisher = The Go website }}</ref>。 ;構文:<syntaxhighlight lang="ebnf"> MethodDecl = "func" Receiver MethodName Signature [ FunctionBody ] ; Receiver = Parameters ; </syntaxhighlight> レシーバーは、メソッド名の前にある追加の仮引数・セクションで指定されます。 この仮引数・セクションでは、単一の非可変仮引数であるレシーバーを宣言しなければなりません。 その型は、定義済みの型Tまたは定義済みの型Tへのポインタでなければならず、その後に角括弧で囲まれた型パラメータ名 [P1, P2, ...] のリストが続く場合もあります。 Tはレシーバー基底型と呼ばれます。レシーバー基底型はポインタやインタフェース型であってはならず、メソッドと同じパッケージで定義されなければなりません。メソッドはそのレシーバー基底型に束縛されていると言われ、メソッド名は型Tまたは*Tのセレクター内でのみ表示されます。 :Go1.18から、レシーバーも型パラメータを伴うことが出来る様になりました。 空白ではないレシーバーの識別子は、メソッドの署名(Signature)の中で一意でなければなりません。レシーバーの値がメソッドの内部で参照されない場合、その識別子は宣言で省略することができます。これは、関数やメソッドの仮引数についても同様です。 基底型の場合、それに束縛されるメソッドの空白でない名前は一意でなければならない。基本型が構造体の場合、空白でないメソッド名とフィールド名は一意でなければなりません。 型 <code>Point</code> が定義されている場合の宣言は ;例:<syntaxhighlight lang=go copy> package main import ( "fmt" "math" ) type Point struct { x, y float64 } func (p *Point) Length() float64 { return math.Hypot(p.x, p.y) } func (p *Point) Scale(factor float64) { p.x *= factor p.y *= factor } func main() { p := Point{3.0, 4.0} len := p.Length() fmt.Println("len = ", len) } </syntaxhighlight> レシーバーの型が*PointであるメソッドLengthとScaleを基本型Pointにバインドします。 レシーバーの基本型がジェネリック型の場合、レシーバー仕様(receiver specification)はメソッドが使用する対応する型パラメータを宣言する必要があります。 これにより、レシーバー型パラメータはメソッドから利用できるようになります。 型パラメタの宣言は、文法的にはレシーバー基本型のインスタンス化のようなもので、型引数は宣言された型パラメタを示す識別子で、レシーバー基本型の各型パラメタに対して1つずつ宣言する必要があります。 型パラメータ名はレシーバー基本型の定義にある対応するパラメータ名と一致する必要はなく、空白でないパラメータ名はすべてレシーバー仮引数セクションとメソッドシグネチャーで一意である必要があります。レシーバー型パラメターの制約は、レシーバー基本型の定義が暗示するものであり、対応する型パラメターは対応する制約を持ちます。 ;例:<syntaxhighlight lang=go copy> type Pair[A, B any] struct { a A b B } func (p Pair[A, B]) Swap() Pair[B, A] { … } // AとBのレシーバー宣言 func (p Pair[First, _]) First() First { … } // レシーバーは First を宣言、これは Pair の A に対応する </syntaxhighlight> {{Nav}} == 脚註 == <references /> ckfdjr4u6zw5gpwg26dmbbvmb35p0g1 Rust 0 32885 263754 263482 2024-11-18T09:24:54Z Ef3 694 /*改廃された技術*/ Rustの改廃された技術や利用が推奨されない技術は、言語標準の進化、安全性の向上、エコシステムの成熟などによって置き換えられます。以下に、代表的な技術を示します。 263754 wikitext text/x-wiki {{Pathnav|メインページ|工学|情報技術|プログラミング}} Rustは、安全性とパフォーマンスを兼ね備えたモダンなシステムプログラミング言語です。本書では、Rustの基礎から応用までを網羅し、実践的なプログラミングスキルの習得を目指します。Rustは初めてのプログラミング言語としても、既存のスキルをさらに強化するためにも最適です。その特徴である所有権システムや並行性モデルについても詳しく解説し、堅牢で効率的なプログラムを構築するための知識を提供します。一緒にRustの世界を探求し、その魅力を存分に体験していきましょう。 == はじめに == Rust(ラスト)は、高性能かつ安全な並行処理を実現するために設計されたマルチパラダイム汎用プログラミング言語です<ref>{{cite web |url=https://graydon2.dreamwidth.org/247406.html |title=Rust is mostly safety |last=Hoare |first=Graydon |date=2016-12-28 |website=Graydon2 |publisher=Dreamwidth Studios |access-date=2021-12-03 |archive-date=2019-05-02 |archive-url=https://web.archive.org/web/20190502181357/https://graydon2.dreamwidth.org/247406.html |url-status=live }}</ref>。 Rustの構文はC++に似ており、ボローチェッカーを利用して参照の検証を行い、メモリ安全性を保証しています。ボローチェッカーはRustコンパイラによって提供される静的解析ツールで、所有権システムに基づいてコード内の不正な借用(ボロー)を検出します。これにより、メモリ管理においてガベージコレクターを使わずに安全性を実現し、場合によってはリファレンスカウントによるメモリ管理も行えます。 また、Rustはシステムプログラミング言語でありながら、関数型プログラミングの要素も取り入れ、低レベルのメモリ管理を可能にしています。これにより、高度な制御が求められるアプリケーション開発に適しており、実行時エラーの発生を抑えながら、安全で信頼性の高いコードを作成することができます。Rustを通じて、効率的かつ堅牢なプログラム構築のための新しい可能性を探求していきましょう。 {{コラム|width=100%|セルフホスティング|2=セルフホスティングとは、ソフトウェアが自分自身をコンパイルできる状態を指し、他のコンパイラを用意することなく、そのソフトウェア自体で再構築が可能であることを意味します。コンパイラにおけるセルフホスティングは、最初に構築されたコンパイラを用いて同じ言語で書かれたソースコードを再コンパイルし、新しいコンパイラを生成する手法です。このプロセスを繰り返すことで、コンパイラを改良したバージョンに更新していけるのが特徴です。 セルフホスティングは、信頼性と安定性を高める手段でもあり、自分自身をコンパイルできる状態であることがソフトウェアの品質向上に寄与します。また、コンパイラの開発者にとっても、その言語やコンパイラの動作原理や構造について理解を深める機会となり、より効率的でパフォーマンスの良いソフトウェアの開発につながります。Rustもセルフホスティングを実現しており、こうした継続的な改善を通じて、安全性とパフォーマンスの向上を目指しています。 }} == クイックツアー == Rustはメモリ安全性、並行性、パフォーマンスの向上に焦点を当てたモダンなプログラミング言語です。以下のRustのクイックツアーで、基本的な概念とコード例を紹介します。 # 基本構文: #: Rustプログラムは<code>main</code>関数から始まります。<code>println!</code> マクロを使って標準出力に文字列を出力できます。 #;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=65f8e3b00b49ca5c691cd61bfc32d1b7 hello.rs]:<syntaxhighlight lang=rust copy> fn main() { println!("Hello, world!"); } </syntaxhighlight> #;実行結果:<syntaxhighlight lang=text> Hello, world! </syntaxhighlight> #: [https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=65f8e3b00b49ca5c691cd61bfc32d1b7 hello.rs]は、[https://play.rust-lang.org/ Playground]に作った、このプログラムへのリンクになっています。 # データ型: #: Rustには整数、浮動小数点数、真偽値などの基本データ型があります。 #:<syntaxhighlight lang=rust copy> let age: i32 = 25; let salary: f64 = 50000.50; let is_rust_fun: bool = true; let message: &str = "Hello, Rust!"; </syntaxhighlight> # 制御構造: #: <code>if</code>、<code>else if</code>、<code>else</code> 文で条件分岐ができます。 #: <code>while</code> ループや <code>for</code> ループで繰り返し処理ができます。 #:<syntaxhighlight lang=rust copy> let num = 10; if num > 0 { println!("Positive"); } else if num < 0 { println!("Negative"); } else { println!("Zero"); } for i in 0..5 { println!("Iteration {}", i); } </syntaxhighlight> # 関数: #: 関数は <code>fn</code> キーワードを使って宣言します。 #:<syntaxhighlight lang=rust copy> fn add(a: i32, b: i32) -> i32 { a + b } fn main() { let result = add(5, 3); println!("Sum: {}", result); } </syntaxhighlight> # 所有権システム: #: Rustは所有権ベースのメモリ管理を採用しており、値の所有権が明確に定義されています。 #:<syntaxhighlight lang=rust copy> fn main() { let s1 = String::from("Hello"); let s2 = s1; // s1の所有権がs2に移動する(所有権の転送) // println!("{}", s1); // エラー!s1はもう有効ではない println!("{}", s2); // 正常に動作 } </syntaxhighlight> # 構造体とメソッド: #: 構造体はデータをまとめるためのカスタム型で、メソッドを持つことができます。 #:<syntaxhighlight lang=rust copy> struct Car { model: String, year: u32, } impl Car { fn display_info(&self) { println!("Model: {}, Year: {}", self.model, self.year); } } fn main() { let my_car = Car { model: String::from("TOYOTA 86"), year: 2022, }; my_car.display_info(); } </syntaxhighlight> ここでは、Rustの基本的な構文とコンセプトを簡単に紹介しました。 == rustcのバージョン確認 == やや力技ですが、Rustのコンパイラ rustc のバージョンをコードから確認できます。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=db39d32bceac679dd79591501075d7f6 version.rs]:<syntaxhighlight lang=rust copy> fn main() { let version = std::process::Command::new("rustc") .arg("--version") .output() .expect("Failed to get Rust version"); if version.status.success() { let stdout = String::from_utf8_lossy(&version.stdout); println!("Rust version: {}", stdout); } else { eprintln!("Failed to retrieve Rust version information"); } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Rust version: rustc 1.84.0-nightly (1e4f10ba6 2024-10-29) </syntaxhighlight> このコードは、Rustのプログラム内で<code>rustc --version</code>コマンドを実行し、その結果(Rustコンパイラのバージョン情報)を取得しています。 # <code>std::process::Command::new("rustc")</code>: <code>Command</code>構造体を使って新しいコマンドを作成しています。ここでは<code>rustc</code>というコマンドを実行するよう指定しています。 # <code>.arg("--version")</code>: <code>rustc</code>コマンドに<code>--version</code>引数を渡しています。これにより、Rustコンパイラのバージョン情報を取得するよう指示しています。 # <code>.output()</code>: <code>Command</code>を実行して、その結果を取得します。ここでは<code>--version</code>を指定した<code>rustc</code>コマンドを実行し、その出力を取得しています。 # <code>.expect("Failed to get Rust version")</code>: コマンドの実行が失敗した場合にエラーメッセージを表示します。 # <code>if version.status.success() { ... } else { ... }</code>: 実行結果の<code>status</code>をチェックして、コマンドが正常に終了したかどうかを確認します。もし成功していた場合は、コマンドの出力結果(Rustコンパイラのバージョン情報)を取得し、それを標準出力に表示します。もし失敗していた場合は、エラーメッセージを標準エラー出力に表示します。 このコードは、Rustのプログラム内で外部コマンドを実行してその出力を取得する方法を示しています。具体的には、Rustコンパイラのバージョン情報を取得してそれを表示する例です。 == コメント == Rustのコメントには、[[C言語]]/[[C++]]と同じく一行コメントと範囲コメントがあります。 ;一行コメント: <code>//</code>から行末までがコメントと見なされます。 ;範囲コメント : <code>/*</code>から<code>*/</code>までがコメントと見なされます。 : ネストは許されません。 ;コメントの例:<syntaxhighlight lang=rust copy> /* * プログラムのエントリーポイントは、main 関数です。 * 関数定義は fn から始まります。 */ fn main() { println!("Hello, world!"); // println! は関数ではなくマクロで、マクロは識別子の末尾に ! が付きます。 } </syntaxhighlight> == 変数と型 == Rustでは、変数を宣言する際にはデフォルトでimmutable(不変)です。変更可能な変数を宣言するには、<code>mut</code> キーワードを使用します。変数の型はコンパイラによって推論されることが一般的ですが、型を明示的に指定することもできます。 例えば、変数の宣言と型指定は以下のようになります: ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=8cddaf15c8b53acb5e0a2013a5cb8cc2 decl.rs]:<syntaxhighlight lang=rust copy> fn main() { // 型推論による変数の宣言 let x = 5; // 整数型 i32 として推論される let y = 3.14; // 浮動小数点型 f64 として推論される println!("x = {x}, y = {y}"); // 型を明示的に指定する let z: i64 = 100; // 64ビット整数型 i64 println!("z = {z}"); } </syntaxhighlight> Rustの基本的なデータ型には以下があります: * 整数型 (<code>i8</code>, <code>i16</code>, <code>i32</code>, <code>i64</code>, <code>i128</code>, <code>u8</code>, <code>u16</code>, <code>u32</code>, <code>u64</code>, <code>u128</code>など) * 浮動小数点型 (<code>f32</code>, <code>f64</code>) * 論理値型 (<code>bool</code>) * 文字型 (<code>char</code>) * ポインタ型 * タプル型 * 配列型 * 列挙型 * 構造体型 * 文字列型 (<code>&str</code>, <code>String</code>) Rustは静的型付け言語であり、変数の型はコンパイル時に確定されます。型の安全性に対する厳格なチェックを行うため、コンパイル時に型の整合性が確認されます。これにより、メモリの安全性やスレッドセーフなコードを書く際の支援が期待できます。 === 変数とミュータブル・イミュータブル === Rustでは、変数を宣言するにはキーワード '''let'''を使います。 ディフォルトでは[[#イミュータブル|イミュータブル]](''Immutable'';宣言後には代入不能)な変数が宣言されます。 [[#ミュータブル|ミュータブル]](''Mutable'';宣言後に代入可能)な変数を宣言するには、追加のキーワード '''mut''' を使います。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=9032ae8999c6cb3bf5412988320e50d7 hello-variables.rs]:<syntaxhighlight lang=rust highlight=2 line copy> fn main() { let hello : &str = "Hello, world!"; println!("{}", hello); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, world! </syntaxhighlight> :2行目の<syntaxhighlight lang=rust inline>let hello : &str = "Hello, world!";</syntaxhighlight>が変数宣言です<ref>文字リテラルであることを強調するなら<syntaxhighlight lang=rust inline>let hello : &'static str = "Hello, world!";</syntaxhighlight>とすべきだったかもしれません。</ref>。 ::&str(文字列のスライスのリファレンス)を型とする変数 <var>hello</var> を宣言し、"Hello, world!"で初期化しています。 ::Rustには強力な[[#型推論|型推論]]があり多くの場合不要ですが、<code>let 変数名 : 型名</code>の書式で型を伴い変数宣言することも出来ます。 mut をつけない場合には変数に「代入不能」と聞くと、C言語などを知っている人は「定数」を思い浮かべるかもしれませが、 Rustにおいて「定数」は, const 宣言された定数や, static 宣言されかつ mut で修飾されていない変数が相当します。 ==== 型推論 ==== Rust では、変数宣言が初期値を伴っていた場合、変数の型を省略することができ、初期値の型が変数の型になります。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=ac2b2d100ee8ea175178ebe9b1e26c61 hello-type-inference.rs]:<syntaxhighlight lang=rust highlight=2 line copy> fn main() { let hello = "Hello, world!"; println!("{hello}"); } </syntaxhighlight> ;実行結果:上に同じ ==== イミュータブル ==== Rust では、値が一度変数に let で束縛されると変更できません。これをイミュータブルと言います。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d13ccba2d1b5efef4ca929012eece549 hello-immutable.rs]:<syntaxhighlight lang=rust highlight='2,4' line copy> fn main() { let hello : &str = "Hello, world!"; println!("{hello}"); hello = "Hello, rust!"; println!("{hello}"); } </syntaxhighlight> ;コンパイル結果:<syntaxhighlight lang=text> error[E0384]: cannot assign twice to immutable variable `hello` --> src/main.rs:4:5 | 2 | let hello : &str = "Hello, world!"; | ----- | | | first assignment to `hello` | help: consider making this binding mutable: `mut hello` 3 | println!("{hello}"); 4 | hello = "Hello, rust!"; | ^^^^^^^^^^^^^^^^^^^^^^ cannot assign twice to immutable variable For more information about this error, try `rustc --explain E0384`. error: could not compile `playground` (bin "playground") due to 1 previous error </syntaxhighlight> :イミュータブルな変数には、代入できないというコンパイルエラーです。 ==== ミュータブル ==== 代入可能、すなわちミュータブルにするためには、変数宣言にあたり '''let''' に続けて '''mut''' をつけます。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=6bbb520249ebc44f7e341988dfad92a3 hello-mutable.rs]:<syntaxhighlight lang=rust highlight=2 line copy> fn main() { let mut hello : &str = "Hello, world!"; println!("{hello}"); hello = "Hello, rust!"; println!("{hello}"); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, world! Hello, rust! </syntaxhighlight> ==== 同じ変数名での宣言 ==== 同一スコープで同じ変数名での宣言は可能です。 同じ型である必要はありません。ミュータブルであるかイミュータブルであるかも問いません。 '''同じ変数名での宣言によって、それまで変数に束縛されていた値への参照がなくなります。''' ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=0604ce8c08449bba14b64f80c405815d 同じ変数名での宣言]:<syntaxhighlight lang=rust highlight='2,4' line copy> fn main() { let hello : &str = "Hello, world!"; println!("{}", hello); let hello = 154649; println!("{}", hello); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, world! 154649 </syntaxhighlight> ==== 定数 ==== Rustには2種類の定数があり、どちらもグローバルスコープを含む任意のスコープで宣言することができます。また、どちらも明示的な型を持っている必要があります。 * const: 不変の値 * static: 静的寿命を持つミュータブルな値 静的寿命は推論されるので、指定する必要はありません。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=901ef30e5d150a91c9fed78d63a4971d 2種類の定数]:<syntaxhighlight lang=rust highlight='2,3' line copy> const HELLO : &str = "Hello, world!"; static LANGUAGE: &str = "Rust"; fn main() { println!("{HELLO}"); println!("{LANGUAGE}"); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, world! Rust </syntaxhighlight> コードを書き換えてconst宣言や(ミュータブルな)static宣言された変数に代入をしようとすると、エラーになります。 ==== パターン ==== ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=9e938e1309c6ba12f760a6c6f0c9d210 pattern.rs]:<syntaxhighlight lang=rust line highlight=5 copy> fn main() { let (mut x, mut y) = (5, 29); println!("x={x} y={y}"); (x, y) = (y, x); println!("x={x} y={y}"); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> x=5 y=29 x=29 y=5 </syntaxhighlight> このコードは、<code>x</code> と <code>y</code> の値を交換するRustの機能を示しています。 * 最初の行では、<code>x</code> に 5 を、<code>y</code> に 29 を代入しています。 * 次の行では、<code>println!</code> マクロでは、交換後の <code>x</code> と <code>y</code> の値を表示しています。 * 次の行では、<code>(x, y) = (y, x);</code> という操作を行っています。これは、タプルを使って複数の変数に同時に値を代入しています。この場合、<code>(y, x)</code> というタプルの中身を <code>(x, y)</code> に順番に代入しています。これにより、<code>x</code> の値に <code>y</code> の値が入り、<code>y</code> の値に <code>x</code> の値が入ります。これによって <code>x</code> と <code>y</code> の値が交換されます。 *最後の <code>println!</code> マクロでは、交換後の <code>x</code> と <code>y</code> の値を表示しています。 このコードは、Rustのタプルを使った多値代入の機能を示しています。 === データ型 === Restには豊富なデータ型(''Data Types'')があり、それらを組み合わせて新しい型を作ることができます<ref>{{Cite web |url=https://doc.rust-lang.org/book/ch03-02-data-types.html |title=Data Types - The Rust Programming Language |accessdate=2021/12/08 }}</ref>。 ==== スカラー型(''Scalar Types'') ==== スカラー型は単一の値を表します。Rustには、整数、浮動小数点数、論理値、文字という4つの主要なスカラ型があります。 ===== 整数型(''Integer Types'') ===== Rustの整数型は、符号の有無とビット幅から12種類のバリエーションがあります。 :{| class=wikitable |+ Rustの整数型 !型名!!説明 |- !i8 |符号付き8ビット整数 |- !u8 |符号なし8ビット整数 |- !i16 |符号付き16ビット整数 |- !u16 |符号なし16ビット整数 |- !i32 |符号付き32ビット整数 |- !u32 |符号なし32ビット整数 |- !i64 |符号付き64ビット整数 |- !u64 |符号なし64ビット整数 |- !i128 |符号付き128ビット整数 |- !u128 |符号なし128ビット整数 |- !isize |符号付きでポインタと同じサイズの整数 |- !usize |符号なしでポインタと同じサイズの整数 |} :isizeとusizeのビット幅はプロセッサーのアーキテクチャーによって定義され、32ビットプロセッサーならば32、64ビットプロセッサーならば64です。 ===== 整数リテラル(''Integer literals'') ===== リテラル(''Literals'')とは、プログラミングのソースコードで使用される、数値や文字列などのデータを直接表現したものです。 :{| class=wikitable style="float:left" |+ 様々な整数リテラル !基数!!表現 |- !10 |19_800 |- !16 |0xbadbeef |- !8 |0o777 |- !2 |0b101_111_011 |- !バイト(u8のみ) |b'Q' |} ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=9c41862df3833ee7bd16169631d74de7 例]:<syntaxhighlight lang=rust style="float:left;width:24em; margin: 1em"> fn main() { println!("{:?}", 19_800); println!("{:x}", 0xbadbeef); println!("{:o}", 0o777); println!("{:b}", 0b101_111_011); println!("{}", b'Q'); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text style="float:left;width:12em; margin: 1em"> 19800 badbeef 777 101111011 81 </syntaxhighlight> :<br style="clear:both"> :数値リテラルには、123u8 の様に型名をタイプサーフィックス(''type suffix'')として補うことで、ビット幅を明記できます(オプショナル)。 ::指定されない場合は(バイト以外は)i32が仮定されます(isizeではありません)。 :数値リテラルには、読みやすさのため 9_281_636 のように、アンダースコア _ を補うことができます(オプショナル)。 なお、<code>{:x}</code>の<code>{x}</code>部分は[[#プレースホルダー|プレースホルダー]]の[[#フォーマッティング・トレイツ(Formatting traits)|ファーマッティング・トレイツ]]です。「x」なら16進数、oなら8進数、bなら2進数で出力します。 ===== 浮動小数点数型(''Floating-Point Types'') ===== Rustには、浮動小数点数を表現するための2つの主要な型があります。それぞれの型は、IEEE-754規格に従っています。 # <code>f32</code>: 32ビットの単精度浮動小数点数型です。精度は約6桁です。 # <code>f64</code>: 64ビットの倍精度浮動小数点数型です。精度は約15桁です。 Rustでは、浮動小数点数リテラルを書く場合、デフォルトで <code>f64</code> 型になります。例えば、<code>3.14</code> という浮動小数点数リテラルは、<code>f64</code> 型の数値になります。 以下は、<code>f32</code> 型と <code>f64</code> 型の浮動小数点数の使用例です。 :<syntaxhighlight lang=rust copy> fn main() { // デフォルトでは f64 型になる浮動小数点数 let my_float1 = 3.14; // f64 型 // サイズを明示して f32 型にする let my_float2: f32 = 2.718; // f32 型 // 浮動小数点数同士の計算 let sum = my_float1 + f64::from(my_float2); // f64 型にキャストして計算 println!("Sum: {}", sum); // f64 型の結果が出力される } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=rust copy> Sum: 5.857999935150147 </syntaxhighlight> 浮動小数点数は、数値計算や科学的な計算など、精度が求められる場面で使用されます。しかし、浮動小数点数の性質や精度による注意が必要な場面もありますので、注意深く扱う必要があります。 ===== 論理値型(''The Boolean Type'') ===== Rustにおける論理値型の型名は <code>bool</code> で、真の値は <code>true</code>、偽の値は <code>false</code> です。この型は非常に基本的で、条件分岐やブール演算などで使用されます。 以下は <code>bool</code> 型の使用例です。 :<syntaxhighlight lang=rust copy> fn main() { let is_rust_cool = true; // 真の値を持つ変数 let is_java_cool = false; // 偽の値を持つ変数 if is_rust_cool { println!("Rust is cool!"); // 条件が true の場合に実行される } else { println!("Rust is not cool."); // 条件が false の場合に実行される } // 論理演算 let result = is_rust_cool && is_java_cool; // 論理積 (AND) の例 println!("Result of logical AND: {}", result); // false が出力される } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Rust is cool! Result of logical AND: false </syntaxhighlight> <code>bool</code> 型は条件式の評価や論理演算に広く使用され、プログラムの流れを制御するための基本的な手段として重要な役割を果たします。 ===== 文字型(''The Character Type'') ===== Rustの文字型 <code>char</code> はUnicodeの単一の文字を表し、32ビットで符号化されます。Unicodeのサロゲートペアを含む広範な範囲の文字を表現できます。 以下のコードは、<code>char</code>型を使用してUnicode文字やサロゲートペアを扱う例です。 :<syntaxhighlight lang=rust copy> fn main() { // 単一のUnicode文字の表現 let unicode_char = '😊'; // 笑顔の絵文字 (U+1F60A) println!("Unicode char: {}", unicode_char); // サロゲートペアの表現 let surrogate_pair = '\u{1F601}'; // 涙の絵文字 (U+1F601) println!("Surrogate pair: {}", surrogate_pair); // char型のサイズを取得 println!("Size of char: {} bytes", std::mem::size_of::<char>()); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Unicode char: 😊 Surrogate pair: 😁 Size of char: 4 bytes </syntaxhighlight> ここでは、<code>'😊'</code> という絵文字や <code>\u{1F601}</code> というサロゲートペアを <code>char</code>型として表現しています。絵文字やサロゲートペアも正しく表示されることを確認できます。また、<code>std::mem::size_of::<char>()</code> を使って <code>char</code>型のサイズを表示しています。 ===== 文字列型(''The String Type'') ===== Rustには2つの主要な文字列型があります。 # <code>&str</code>型 (文字列スライス): #* メモリ内のデータへの不変の参照を表します。 #* UTF-8でエンコードされた文字列を参照します。 #* 文字列リテラルや他のデータ構造の一部として使用されます。 #:<syntaxhighlight lang=rust copy> let string_slice: &str = "Hello, Rust!"; // 文字列リテラルから作成された文字列スライス </syntaxhighlight> # <code>String</code>型: #* ヒープ上に確保された可変の文字列データを持ちます。 #* 動的に変更可能で、文字列の追加や削除、変更が可能です。 #:<syntaxhighlight lang=rust copy> let mut string_object = String::from("Hello"); // String型のインスタンスを生成 string_object.push_str(", Rust!"); // 文字列を追加 </syntaxhighlight> これらの型は互いに相互変換できます。例えば、<code>&str</code>から<code>String</code>への変換は<code>to_string()</code>メソッドを使用できます。 :<syntaxhighlight lang=rust copy> let my_string: String = "Hello".to_string(); // &strからStringへの変換 </syntaxhighlight> また、<code>String</code>から<code>&str</code>への変換は、<code>&</code>演算子を使用して参照を取得します。 :<syntaxhighlight lang=rust copy> let my_string: String = String::from("Hello"); let string_ref: &str = &my_string; // Stringから&strへの変換 </syntaxhighlight> 文字列操作に関しては、<code>String</code>型が動的に変更可能で柔軟性があり、<code>&str</code>型は主に静的な文字列の参照として使用されます。 ;様々な文字列リテラル ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=9c41862df3833ee7bd16169631d74de7 string.rs]:<syntaxhighlight lang=rust copy> fn main() { println!("{:?}", "hello"); // エスケープされた文字列 println!("{:?}", r#"hello"#); // エスケープされないraw文字列 println!("{:?}", b"hello"); // エスケープされたバイト文字列 println!("{:?}", br#"hello"#); // エスケープされないrawバイト文字列 } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> "hello" "hello" [104, 101, 108, 108, 111] [104, 101, 108, 108, 111] </syntaxhighlight> * <code>"{:?}"</code> はデバッグ用のフォーマット指定子で、デバッグ表示用の形式で出力します。 * <code>r#"..."#</code> はエスケープされない raw 文字列リテラルで、内部のエスケープが無視されます。 * <code>b"..."</code> はバイト文字列リテラルで、ASCII文字のバイト値の配列を示します。 * <code>br#"..."#</code> はエスケープされない raw バイト文字列リテラルです。 これらのリテラルは、異なる用途で利用されることがあり、それぞれの特性や振る舞いが異なります。 ===== ユニット型(''The Unit Type'') ===== Rustにおけるユニット型は<code>()</code>で表されます。ユニット型は特別な型であり、単一の値 <code>()</code> だけから成り立ちます。主に2つの用途があります: # 関数の戻り値としての利用: 副作用のない関数や手続きにおいて、何も返す必要がない場合にユニット型 <code>()</code> が使用されます。 #:<syntaxhighlight lang=rust copy> fn do_something() { // 何らかの処理 } fn main() { let result = do_something(); // 戻り値は () になる println!("result = {:?}", result); } </syntaxhighlight> # 構造体のフィールドとしての利用: 構造体のフィールドとしてユニット型を持つことで、その構造体のインスタンスが存在することを示す場合に使用されます。 #:<syntaxhighlight lang=rust copy> #[derive(Debug)] struct MarkerUnit; fn main() { let marker = MarkerUnit; // ユニット型を持つ構造体のインスタンス化 println!("marker = {:?}", marker); } </syntaxhighlight> ユニット型は一見すると何も持たない型ですが、プログラムの構造を表現するために重要な役割を果たしています。特に関数の戻り値として使用されることが多いです。 ==== 複合型(''Compound Types'') ==== 複合型(''Compound Types'')は、複数の値を1つの型にまとめることができます。 Rustにはタプルとアレイという2つのプリミティブな複合型があります。 ===== タプル型(''The Tuple Type'') ===== タプル(''The Tuple'')は、さまざまな型の値を1つの複合型にまとめる一般的な方法です。 タプルの長さは固定されており、一度宣言すると大きくしたり小さくしたりすることはできません。 ===== 配列型(''The Array Type'') ===== 複数の値の集まりを持つもう一つの方法として、配列(''The Array'')があります。 タプルとは異なり、配列の各要素は同じ型でなければなりません。 Rustの配列は、タプルと同じく長さが固定されています。 == プレースホルダー == println! マクロなどの文字表示マクロでは、文字列中の <code>{</code> <code>}</code> の位置に指定された書式で展開します<ref>[https://doc.rust-lang.org/std/fmt/ Module std::fmt]</ref>。 [[C言語]]の標準関数 printf() と機能は似ていますが書式は大きく異なり、[[Python]]のf文字列との共通点が多いです。 <!-- * Positional parameters * Named parameters * Formatting Parameters ** Width ** Fill/Alignment ** Sign/#/0 ** Precision * Localization * Escaping {} を表示したい時は {{}} とします * Related macros -- format! write! writeln! println! eprint! eprintln! --> === フォーマッティング・トレイツ(Formatting traits) === {{Ruby|空|から}}のプレースホルダー<code>{}</code>を指定すればその型の自然なフォーマット([https://doc.rust-lang.org/std/fmt/trait.Display.html fmt::Display]; 100 ならば "100")で文字列化されます。 しかし、基数を変えた16進数や8進数や2進数などでフォーマットをしたいときはフォーマッティング・トレイツ(Formatting traits)を使います<ref>[https://doc.rust-lang.org/std/fmt/#formatting-traits Formatting traits]</ref>。 ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=81cb5a55fcae676c094f2b74929f09b3 Formatting traits]:<syntaxhighlight lang=rust copy> fn main() { println!("{:?}", 100); println!("{:x}", 100); println!("{:o}", 100); println!("{:b}", 100); println!("{}", 100); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 100 64 144 1100100 100 </syntaxhighlight> フォーマッティング・トレイツは、Rustプログラミング言語におけるデータのフォーマット(整形)方法を定義するためのトレイト(trait)です。これらのトレイトは、<code>std::fmt</code>モジュールに定義されており、<code>std::fmt::Display</code>や<code>std::fmt::Debug</code>など、様々なフォーマット方法を提供します。 一般的なフォーマッティング・トレイツは以下のようになります: * Display: <code>std::fmt::Display</code>トレイトは、<code>{}</code>(中括弧)を使ったシンプルな人間が読みやすい形式での表示を提供します。これは、<code>println!</code>マクロや<code>format!</code>マクロで使われます。 * Debug: <code>std::fmt::Debug</code>トレイトは、<code>{:?}</code>を使ったデバッグ目的の表示を提供します。これは、デバッグ情報を表示する際に便利で、<code>println!("{:?}", variable)</code>のように使用されます。 * Binary: <code>std::fmt::Binary</code>トレイトは、<code>{:#b}</code>を使ってバイナリ表現での表示を提供します。 * Octal: <code>std::fmt::Octal</code>トレイトは、<code>{:#o}</code>を使って8進数表現での表示を提供します。 * LowerHex / UpperHex: <code>std::fmt::LowerHex</code>および<code>std::fmt::UpperHex</code>トレイトは、それぞれ<code>{:#x}</code>および<code>{:#X}</code>を使って16進数表現での表示を提供します。 これらのトレイトは、カスタム型をフォーマットする方法を指定するために、対応するメソッドを実装することで利用されます。 例えば、<code>Display</code>トレイトを実装することで、自分で定義した型を<code>{}</code>を使って表示することができます。 以下は、簡単な構造体<code>Person</code>に<code>Display</code>トレイトを実装して、<code>{}</code>を使ってカスタム型を表示する例です。 :<syntaxhighlight lang=rust copy> use std::fmt; // 構造体を定義 struct Person { name: String, age: u32, } // Displayトレイトの実装 impl fmt::Display for Person { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // カスタムフォーマットを定義する write!(f, "Name: {}, Age: {}", self.name, self.age) } } fn main() { let person = Person { name: String::from("Alice"), age: 30, }; // {}を使ってPerson型を表示 println!("Person Details: {}", person); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Person Details: Name: Alice, Age: 30 </syntaxhighlight> この例では、<code>Person</code>という構造体を定義し、<code>fmt::Display</code>トレイトを実装しています。<code>fmt</code>モジュール内の<code>Formatter</code>型を利用して、<code>write!</code>マクロを呼び出しています。<code>main</code>関数内で<code>println!</code>マクロを使って<code>Person</code>型を表示しています。これにより、<code>Person</code>型を<code>{}</code>を使って表示する方法が示されています。 == 所有権システム == Rustの所有権システムは、メモリ管理とリソースの安全な扱いを通じて安全性と並行性を確保する、言語の重要な特徴です。ここでは、Rustの所有権、借用、参照について、コードを交えて解説します。 === 所有概念 === Rustの所有概念は、変数がリソースの所有権を持ち、スコープを抜ける際にそのリソースを自動的に解放する仕組みです。この仕組みは、メモリ安全性を高めるための中心的な考え方です。 === コピーとムーブ === Rustでは、変数が参照しているデータがスタック上かヒープ上かによって、コピーやムーブの挙動が異なります。スタック上のプリミティブ型はコピーされますが、ヒープ上のデータはムーブされ、所有権が移動します。 ; コピーされるデータ :<syntaxhighlight lang=rust line copy> fn main() { let x = 5; let y = x; // xの値がコピーされる println!("x: {}, y: {}", x, y); // 両方の変数が利用可能 } </syntaxhighlight> この例では、整数型<code>x</code>の値がコピーされるため、<code>x</code>と<code>y</code>の両方が使用できます。 ; ムーブされるデータ :<syntaxhighlight lang=rust line copy> fn main() { let s1 = String::from("Hello"); let s2 = s1; // s1の所有権がs2に移動 // println!("{}", s1); // コンパイルエラー:s1はもう使用できない println!("{}", s2); // 正常に出力される } </syntaxhighlight> ここでは、<code>s1</code>の所有権が<code>s2</code>に移動するため、<code>s1</code>は利用できなくなります。 次に、コピーとムーブの違いを簡単に表にまとめます。 :{| class=wikitable |+ コピーとムーブの違い ! データ種別!! コピー !! ムーブ |- ! プリミティブ型(整数型、bool型など) | コピーされる | コピーされる |- ! ヒープ上のデータ(String型、Vec型など) | されない | 所有権が移動する |} === 借用と参照 === 所有権を移動せずにデータを利用する方法として、借用(参照)があります。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=91624181f640bfff93914d318547bfae 借用と参照の例] :<syntaxhighlight lang=rust line copy> fn main() { let s1 = String::from("Hello"); // s1を借用する(イミュータブルな参照) let len = calculate_length(&s1); println!("The length of '{}' is {}.", s1, len); // 正常に出力される } fn calculate_length(s: &String) -> usize { s.len() } </syntaxhighlight> この例では、<code>calculate_length</code>関数が<code>&String</code>型のイミュータブルな参照を受け取っているため、<code>s1</code>の所有権を渡すことなく値を参照できます。 === ミュータブルな参照 === 可変の値を変更するには、ミュータブルな参照を使います。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=1ef888bfe58461858b4cefe84d3b6fae ミュータブルな参照の例] :<syntaxhighlight lang=rust line copy> fn main() { let mut s = String::from("Hello"); change_string(&mut s); println!("{}", s); // "Hello, goodbye"が出力される } fn change_string(s: &mut String) { s.push_str(", goodbye"); } </syntaxhighlight> <code>&mut String</code>型のミュータブルな参照を利用して<code>change_string</code>関数で文字列を変更しています。 === 関数のパラメータにした変数は関数にムーブされる === Rustでは、関数の引数として変数を渡すと、所有権が関数にムーブされる場合があります。例で見てみましょう。 :<syntaxhighlight lang=rust copy> fn main() { let original = String::from("Hello, Rust!"); // String型の変数originalを作成 let moved = move_ownership(original); // originalがmove_ownership関数にムーブ // println!("original: {}", original); // コンパイルエラー println!("moved: {}", moved); // 正常に動作 } fn move_ownership(input: String) -> String { input } </syntaxhighlight> この例では、<code>original</code>が関数<code>move_ownership</code>にムーブされ、<code>original</code>は使用できなくなります。 === クローン === 所有権を共有したい場合、<code>clone</code>メソッドでデータの複製が可能です。 :<syntaxhighlight lang=rust copy> fn main() { let data1 = vec![1, 2, 3]; let data2 = data1.clone(); // データの複製 println!("{:?}", data1); // data1は所有権を保持している println!("{:?}", data2); // data2はクローンされたデータを持つ } </syntaxhighlight> この例では、<code>data1</code> の <code>clone</code> メソッドを呼び出すことで、ヒープ上にあるデータの複製を作成し、<code>data2</code> に格納します。このとき、<code>data1</code> と <code>data2</code> はそれぞれ独立した所有権を持つため、どちらかを変更してももう一方には影響しません。 クローンを作成することで、所有権が必要な場合でも、元のデータをそのまま保持しながらコピーを生成できるため、データの安全な扱いが可能です。 === ライフタイム === ライフタイムは、参照が有効である期間を示すRustの注釈で、所有権と借用のルールと密接に関係しています。ライフタイムを指定することで、コンパイラがメモリの安全性を保証し、不正なメモリアクセスや参照の無効化を防ぎます。 :<syntaxhighlight lang=rust copy> fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } </syntaxhighlight> この例では、<code>'a</code> というライフタイムパラメータを使って、<code>x</code> と <code>y</code> の参照が同じライフタイムを共有することをコンパイラに伝えています。これにより、返り値のライフタイムも入力引数と同じ期間で有効であることが保証されます。 ライフタイムは複雑な場面では特に重要となり、Rustの所有権システムがさらに強力にメモリ安全を保証する仕組みとなっています。 === Rc, Box と Drop === ==== Rc (Reference Counting) ==== <code>Rc</code>は参照カウントを用いたスマートポインタで、複数の所有者が同じデータを共有できるようにします。主にマルチスレッドを必要としない環境で利用され、<code>clone</code>メソッドでカウントを増加させることで、同じデータを複数の変数が所有できます。 :<syntaxhighlight lang=rust copy> use std::rc::Rc; let a = Rc::new(5); let b = Rc::clone(&a); // aとbが同じデータを共有 </syntaxhighlight> <code>Rc</code>はスレッドセーフではありませんが、シングルスレッドの環境でデータ共有を簡単に行えるため便利です。 ==== Box (Heap Allocation) ==== <code>Box</code>はデータをヒープに格納し、そのポインタをスタック上で保持するスマートポインタです。スタックではなくヒープにデータを配置したい場合に使用します。<code>Box</code>は最も単純なスマートポインタで、シングルオーナーのデータの所有権を提供します。 :<syntaxhighlight lang=rust copy> let b = Box::new(5); println!("b = {}", b); // ヒープ上に格納されたデータにアクセス </syntaxhighlight> ボックスは特に再帰的なデータ構造の作成やヒープメモリ管理に適しており、ポインタの解放はスコープを外れたときに自動で行われます。 ==== Drop (Resource Cleanup) ==== <code>Drop</code>トレイトは、オブジェクトがスコープを外れるときにリソースをクリーンアップするための機構を提供します。カスタムデストラクタを実装する際に使用され、例えばファイルハンドルやネットワークリソースなどのリソース解放に役立ちます。 :<syntaxhighlight lang=rust copy> struct CustomResource; impl Drop for CustomResource { fn drop(&mut self) { println!("CustomResourceが解放されました"); } } let resource = CustomResource; // スコープを抜けるときにdropメソッドが呼ばれる </syntaxhighlight> <code>Drop</code>トレイトにより、Rustは自動的にリソース管理を行い、メモリリークやリソースの取りこぼしを防ぎます。手動で<code>drop</code>を呼び出すことも可能ですが、通常はスコープ終了時に自動で解放されます。 ; まとめ Rustの所有権システムは、メモリ管理とデータ競合の予防において非常に強力な機能です。所有、借用、ムーブ、コピー、クローンといった各機能を活用することで、安全かつ効率的にメモリを管理できるようになります。特に、Rustではコンパイル時にこれらのルールが強制されるため、意図しないバグを未然に防ぐことができます。 Rustの所有権システムを深く理解することは、効率的で安全なコードを書くための第一歩です。<!ーー RcやBoxやDropもここか? ーー> == 制御構造 == Rust では、{{code|if}}や{{code|for}}などの制御構造も式です。 === 分岐 === Rust は、[[#if|if]] と [[#match|match]] の2つの分岐構文を持ちます。 ==== if ==== ifは、条件式に基づき分岐し、分岐先の式を評価します。 ifの値は、分岐先の式の値です。 elseを省略し条件式が偽であった場合のifの値は <code>()</code> です。 ;構文:<syntaxhighlight lang=ebnf> if-expr := if 条件式 '{' 式1 '}' [ else '{' 式2 ] '}' </syntaxhighlight> :;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=84117443c135c52137b9005717322e82 条件式に整数を使うと]:<syntaxhighlight lang=Rust line copy> fn main() { let i = 0; if i { println!("zero"); } } </syntaxhighlight> :;コンパイルエラー:<syntaxhighlight lang=text> error[E0308]: mismatched types --> src/main.rs:4:8 | 4 | if i { | ^ expected `bool`, found integer For more information about this error, try `rustc --explain E0308`. </syntaxhighlight> :: Rustでは、ifに限らず、条件式は、bool 型でなければいけません。 ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2c8960df447a87aaeaecced963d20cde if.rs]:<syntaxhighlight lang=rust line copy> fn main() { let i = 0; if i == 0 { println!("零"); } else { println!("非零"); } let s = if i == 0 { "ゼロ" } else { "非ゼロ" }; println!("{}", s); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 零 ゼロ </syntaxhighlight> :気をつけたいのは、式の値が参照されるifでは、それぞれの式(ここでは <code>"ゼロ"</code> と <code>"非ゼロ"</code>)にセミコロン<code> ; </code>を付けてはいけない点です。 :: もし セミコロン<code> ; </code> をつけると、ブロックの値は、Unit 型 <code>()</code> になります。 :: ifの、分岐先の2つの式の型は同じでなければいけません。 :: else節が省略された場合は、Unit 型を返さなければいけません。 ::: 式の最後に、セミコロン<code>};</code> が必要ということです<ref>C言語系では、式を文にする為いに<code>};</code> が必要です。Rustもそう説明されている場合がありますが、Rustでは式の型の一致が目的です。</ref>。 :また、<syntaxhighlight lang=rust inline>let s = if i == 0 {</syntaxhighlight>の文末の<code>};</code> のセミコロンも忘れがちです。 :Rust では if に限らず、コードブロックは式の一種で値を返します<ref>コードブロックが値を持つプログラミング言語としては、BCPL, [[Ruby]], [[Scala]]や[[Kotlin]]があります。</ref>。その場合、コードブロックの最後の式がコードブロックの値となりセミコロン<code> ; </code>は不要で、もし、<code> ; </code>をつけると<code> ; </code>の次の式(=空文)の値<code> () </code>がコードブロックの値になります。 この特徴は、関数型プログラミングを意識したものですが、同時に後に説明する所有権の移譲で重要な役割を果たします。 ===== if と else の連鎖 ===== ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=e3c9a903bc6baab687f697a83bde8928 if-else.rs]:<syntaxhighlight lang=rust line copy> fn main() { let n = 0.0 / 0.0; if n < 0.0 { println!("負の数"); } else if n > 0.0 { println!("正の数"); } else if n == 0.0 { println!("零"); } else { println!("{n}"); } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> NaN </syntaxhighlight> このコードの中で、次のことが行われています: # <code>n</code> に NaN(Not a Number)を代入しています。<code>0.0 / 0.0</code> は浮動小数点数のゼロで割り算を表し、NaN を返します。 # <code>if</code> 文で <code>n</code> の値に応じて条件分岐しています。 # <code>n</code> が負の数より小さい場合は、"負の数" と出力します。 # <code>n</code> が正の数より大きい場合は、"正の数" と出力します。 # <code>n</code> がゼロと等しい場合は、"零" と出力します。 # それ以外の場合は、<code>n</code> の値を <code>{n}</code> という形式で出力します。 しかし、Rustの浮動小数点数型では、NaN は <code><</code> や <code>></code> 、<code>==</code> などの比較演算子によって、他の数値との大小や等価性を比較することはできません。なぜなら NaN は "not a number" であり、数値としての大小関係が定義されていないためです。 そのため、このコードでは <code>n</code> が NaN である場合、どの条件にも合致せず、最後の <code>else</code> ブロックが実行されることになります。このブロックでは、<code>n</code> の値そのものを <code>{n}</code> という形式で出力しようとしています。 ==== Some() ==== Rustでは、C言語のNULLに相当する値は None です。 通常の変数は None の代入は受付けませんが、Some() を使うと None を取り得る変数が宣言できます<ref>[https://doc.rust-lang.org/stable/std/option/enum.Option.html Option in std::option - Rust]</ref>。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=afb9193c50a316090b6e3119f994f8cf some.rs]:<syntaxhighlight lang=rust line copy> fn main() { let mut x = Some(0); println!("{:?}({})", x, type_of(x)); x = None; println!("{:?}({})", x, type_of(x)); } fn type_of<T>(_: T) -> &'static str { std::any::type_name::<T>() } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Some(0)(core::option::Option<i32>) None(core::option::Option<i32>) </syntaxhighlight> Some() 及び None は、標準ライブラリ std::option で定義されていますが、初期化済みなので Use することなく、接頭辞Option::なしで使えます。 ==== if let ==== Rustには、<code>if let</code>という特別な制御構造があります。<code>if let</code>は、<code>match</code>式を簡略化するために使用されます。<code>if let</code>式は、単一のパターンを使用して、変数が指定された値にマッチした場合にのみ式を実行します。<code>if let</code>を使用すると、冗長なマッチングのコードを削減できます。 以下は、<code>if let</code>を使用した例です。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=0614af1127dbc6ec0d871443b16e6a67 if-let.rs]:<syntaxhighlight lang=rust style="width:40em"> fn main() { let mut v = vec![2, 3, 5]; if let Some(x) = v.pop() { println!("x = {}", x) } else { println!("done!") } if let Some(x) = v.pop() { println!("x = {}", x) } else { println!("done!") } if let Some(x) = v.pop() { println!("x = {}", x) } else { println!("done!") } if let Some(x) = v.pop() { println!("x = {}", x) } else { println!("done!") } if let Some(x) = v.pop() { println!("x = {}", x) } else { println!("done!") } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text style="width:40em"> x = 5 x = 3 x = 2 done! done! </syntaxhighlight> : <code>.pop()</code>メソッドは、ベクターから最後の要素を取り出し、それを返します。ただし、ベクターが空である場合は<code>None</code>を返します。 : 最初の行では、<code>vec![2, 3, 5]</code>という3つの要素を持つベクターを作成しています。 : その後、5回の<code>if let</code>式を使用して、ベクターから要素を取り出し、それを表示するか、ベクターが空の場合には<code>done!</code>と表示します。 : 各<code>if let</code>式では、変数<code>x</code>を定義しています。 :: <code>v.pop()</code>の返り値が<code>Some</code>であれば、ベクターの最後の要素が変数<code>x</code>に束縛され、<code>println!</code>マクロを使用して<code>x</code>を表示します。 :: そうでない場合、すなわち、ベクターが空である場合は、<code>else</code>節が実行されて、<code>done!</code>が表示されます。 ==== match ==== <code>match</code>は、値とパターンをマッチングして、対応するコードブロックを実行します。これは、複数の条件に基づいて処理を行う場合に非常に便利です。例えば、列挙型(enum)を使った状況では、<code>match</code>は特に有用です。 :<syntaxhighlight lang=rust copy> enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u32 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 }, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } } </syntaxhighlight> 上記の例では、<code>Coin</code>型の列挙子を受け取り、それぞれのコインに対する価値を返す関数が定義されています。<code>match</code>は<code>Coin</code>の値を取り、各列挙子に対応するコードブロックを実行します。例えば、<code>Coin::Penny</code>の場合、"Lucky penny!"というメッセージが表示され、1が返されます。 <code>match</code>は、パターンに加えて<code>if</code>条件も組み合わせて使用できます。 :<syntaxhighlight lang=rust copy> fn main() { let some_value = Some(5); match some_value { Some(x) if x < 5 => println!("Less than 5: {}", x), Some(x) => println!("Value: {}", x), None => println!("No value"), } } </syntaxhighlight> この例では、<code>Some</code>型の値を持つ変数を<code>match</code>で処理しています。<code>if</code>条件は<code>Some</code>型であり、かつその値が5未満の場合にマッチします。それ以外の場合、単に値を表示します。 <code>match</code>はRustの強力なツールであり、パターンマッチングにより、安全性と表現力を向上させます。 === 反復 === Rustには、以下のような反復構文があります。 # <code>[[#for|for]]</code>ループ ## <code>[[#iter()|iter()]]</code>メソッドを使用した反復処理 ## <code>[[#enumerate()|enumerate()]]</code>メソッドを使用した反復処理 ## <code>[[#zip()|zip()]]</code>メソッドを使用した反復処理 # <code>[[#while|while]]</code>ループ # <code>[[#loop|loop]]</code>ループ それぞれの構文について、詳しく解説していきます。 ==== for ==== Rust の '''for''' は、指定された範囲内の値を反復処理するために使用されます。通常、配列、ベクトル、範囲、またはイテレータなどの反復可能オブジェクトに対して使用されます。 ;構文:<syntaxhighlight lang=ebnf> for_expression = "for" loop_variable "in" expression "{" statement* "}"; loop_variable = pattern; expression = (expression_binop | expression_unop | expression) ; pattern = identifier | "_" | literal ; </syntaxhighlight> : <code>for_expression</code>はforループを表し、 <code>loop_variable</code>は反復処理のために使用される変数、 <code>expression</code>は反復処理の対象となるデータのソース、 <code>statement</code>はループ内で実行される文を表します。 <code>pattern</code>は、ループ変数の型と一致するパターンを表します。 : <code>identifier</code>は、識別子の名前を表します。 <code>literal</code>は、文字列、数値、真偽値などのリテラル値を表します。 : forループは、 <code>loop_variable</code>によって定義された変数に <code>expression</code>で指定されたデータソースの値を順番に割り当て、それぞれの値に対して <code>statement</code>を実行します。 : <code>identifier</code>は識別子を、<code>literal</code>はリテラルをしめします。 ===== Range ===== Rustにおける<code>range</code>は、範囲を表す型です。範囲の生成には2つの主要な方法があります。 ;..(半開区間) * <code>start..end</code>の形式で使用され、<code>start</code>から<code>end</code>の手前(<code>end</code>は含まれない)までの範囲を生成します。 例えば、<code>1..5</code>は1から4までの範囲を生成します。 ; ..= (閉区間) * <code>start..=end</code>の形式で使用され、<code>start</code>から<code>end</code>までの閉区間を生成します(<code>end</code>も含まれます)。 例えば、<code>1..=5</code>は1から5までの範囲を生成します。 これらの範囲は<code>for</code>ループの反復やイテレータの作成など、さまざまな場面で使用されます。例えば、<code>for</code>ループやイテレータを使って範囲内の要素を処理することができます。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=a3cd190fbd860ce8efb0d6276fb0858a for-in-range.rs]:<syntaxhighlight lang=rust copy> fn main() { // 半開区間の使用例 for i in 1..5 { println!("{i}"); // 1, 2, 3, 4が出力される } // 閉区間の使用例 for i in 1..=5 { println!("{i}"); // 1, 2, 3, 4, 5が出力される } } </syntaxhighlight> 範囲は整数や文字など、多くの型で使用できます。範囲の使用はイテレーションや特定の範囲内の操作を行う際に便利です。 ===== iter() ===== <code>Rust</code>における<code>iter()</code>は、コレクション(ベクター、配列、ハッシュマップなど)をイテレート可能な形に変換するメソッドです。イテレータは、コレクション内の要素を1つずつ処理するための仕組みを提供します。 基本的な使い方は以下のようになります: ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=d45c8c0ad55adb01e50456dd7270983c iter.rs]:<syntaxhighlight lang=rust copy> fn main() { let vec = vec![1, 2, 3, 4, 5]; // ベクターのイテレータを作成する let mut iter = vec.iter(); // イテレータを使って要素に順番にアクセスする while let Some(value) = iter.next() { println!("{value}"); } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 1 2 3 4 5 </syntaxhighlight> <code>iter()</code>メソッドは、イテレータを作成するための最も基本的な手段ですが、さまざまな応用もあります。 # <code>.map()</code>: イテレータを他の形に変換する場合に使われます。たとえば、各要素に対して関数を適用して新しいイテレータを作成します。 #:<syntaxhighlight lang=rust copy> fn main() { let vec = vec![1, 2, 3, 4, 5]; // 各要素を2倍する新しいイテレータを作成する let doubled_iter = vec.iter().map(|x| x * 2); for value in doubled_iter { println!("{value}"); } } </syntaxhighlight> # <code>.filter()</code>: 条件に一致する要素のみを含む新しいイテレータを作成します。 #:<syntaxhighlight lang=rust copy> fn main() { let vec = vec![1, 2, 3, 4, 5]; // 偶数の要素だけを含む新しいイテレータを作成する let even_iter = vec.iter().filter(|&x| x % 2 == 0); for value in even_iter { println!("{value}"); } } </syntaxhighlight> # <code>.fold()</code>: イテレータ内の要素を畳み込んで単一の値に集約します。 #:<syntaxhighlight lang=rust copy> fn main() { let vec = vec![1, 2, 3, 4, 5]; // 要素の合計を計算する let sum = vec.iter().fold(0, |acc, &x| acc + x); println!("合計: {sum}"); } </syntaxhighlight> # <code>.reduce()</code>: イテレータ内の要素を畳み込んで単一の値に集約します。 #:<syntaxhighlight lang=rust copy> fn main() { let vec = vec![1, 2, 3, 4, 5]; // 要素の合計を計算する let sum = vec.into_iter().reduce(|acc, x| acc + x); println!("合計: {:?}", sum); } </syntaxhighlight> これらは<code>iter()</code>を基盤として利用する機能の一部です。<code>Rust</code>のイテレータは非常に強力で、関数型プログラミングの概念を取り入れながら、効率的で安全なコードを記述するための重要な手段となっています。 ====== rev() ====== <code>iter()</code>メソッドに加えて、<code>rev()</code>メソッドを使用すると、要素を逆順で取り出すこともできます。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=83d50bb12645221a766052413a9d73b8 iter-rev.rs]:<syntaxhighlight lang=rust copy> fn main() { let v = vec![1, 3, 5, 7, 11]; for x in v.iter().rev() { println!("x = {}", x) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> x = 11 x = 7 x = 5 x = 3 x = 1 </syntaxhighlight> : このRustのコードは、 <code>for</code>ループを使用して、ベクトル <code>v</code>の要素を反復処理し、各要素の値を出力するものです。ただし、 <code>v</code>の要素を逆順に処理します。 : <code>v.iter().rev()</code>は、 <code>v</code>のイテレータを取得し、そのイテレータを逆順にするためのメソッドです。これにより、ベクトルの最後の要素から始まり、最初の要素まで逆順に反復処理します。 : <code>for</code>ループの本体では、 <code>println!</code>マクロを使用して、現在の <code>x</code>の値を表示しています。 <code>{}</code>はプレースホルダーであり、その場所に変数の値が挿入されます。この例では、 <code>{}</code>の中に <code>x</code>を指定して、ループの反復ごとに変化する <code>x</code>の値を表示しています。 ===== enumerate() ===== <code>enumerate()</code>メソッドを使用すると、要素のインデックスと値を同時に取り出すこともできます。 ;コード例:<syntaxhighlight lang=rust line copy> let v = vec![1, 2, 3]; for (i, val) in v.iter().enumerate() { println!("{}: {}", i, val); } </syntaxhighlight> : このコードでは、<code>v.iter().enumerate()</code>メソッドを使用して、<code>v</code>のイテレータを作成し、各要素のインデックスと値を同時に反復処理しています。<code>for</code>ループの本体では、変数<code>i</code>を使ってインデックス、<code>val</code>を使って値を表示しています。 ===== zip() ===== <code>zip()</code>メソッドを使用すると、複数のイテレータを同時に取り出すことができます。 ;コード例:<syntaxhighlight lang=rust line copy> let v1 = vec![1, 2, 3]; let v2 = vec!["one", "two", "three"]; for (i, val) in v1.iter().zip(v2.iter()) { println!("{}: {}", i, val); } </syntaxhighlight> : このコードは、<code>zip()</code>メソッドを使用して、2つのベクトルを同時に反復処理する方法を示しています。 : 最初の行で、整数のベクトル<code>v1</code>と文字列のベクトル<code>v2</code>を定義しています。 : 次に、<code>for</code>ループを使用して、<code>v1.iter()</code>と<code>v2.iter()</code>のイテレータを同時に取り出します。このとき、<code>(i, val)</code>というタプルの形式で、それぞれのイテレータから次の要素を取り出します。 : <code>println!</code>マクロの中で、<code>{}</code>に<code>i</code>と<code>val</code>をそれぞれ表示しています。<code>{}</code>の中にある<code>:</code>は区切り文字で、<code>i</code>と<code>val</code>を区別するために使用されています。 ==== while ==== Rustにおいて、<code>while</code>は指定した条件式が<code>true</code>である限り、ブロック内のコードを繰返し実行する制御構文です。 ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=47dc5b7c9d866b3f5913a77b9a55988e while.rs]:<syntaxhighlight lang=rust copy> fn main() { let mut i = 0; while i < 5 { println!("i = {}", i); i += 1 }; } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> i = 0 i = 1 i = 2 i = 3 i = 4 </syntaxhighlight> : このプログラムは、0から4までの数字を順番に表示するプログラムです。whileループを使用して、条件式<code>i < 5</code>が<code>true</code>である間、ループを継続します。ループの各イテレーションでは、<code>println!</code>マクロを使用して、変数<code>i</code>の現在の値を表示します。<code>i</code>の値は、ループ本文の最後で<code>i += 1</code>によって1ずつ増加します。条件式<code>i < 5</code>が<code>false</code>になったとき、ループが終了します。最終的に、0から4までの数字が順番に表示されます。 ===== while let ===== Rustの<code>while let</code>は、ループ処理の一種で、パターンマッチングを行い、パターンにマッチする値をループ内で取り出しながらループを繰り返します。 <code>while let</code>は、<code>match</code>構文の糖衣構文で、一つの値を取り出してパターンマッチングを行い、パターンにマッチする場合は値を取り出し、マッチしない場合はループを終了します。 ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0764d8389e3afc0854b4223b8db5a32b while-let.rs]:<syntaxhighlight lang=rust copy> fn main() { let mut n = Some(0); while let Some(i) = n { n = if i > 5 { None } else { println!("i = {}", i); Some(i + 1) } } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> i = 0 i = 1 i = 2 i = 3 i = 4 i = 5 </syntaxhighlight> : このコードは、<code>n</code> という <code>Option<i32></code> 型の変数を定義し、初期値を <code>Some(0)</code> として設定します。そして、<code>while</code> ループを使って <code>n</code> の値を取り出しながら、それが <code>None</code> でなければループを続けます。 : <code>while let</code> の条件式では、<code>n</code> が <code>Some(i)</code> とパターンマッチされ、<code>i</code> に値がバインディングされます。このパターンマッチにより、<code>n</code> が <code>Some(i)</code> でなければループは終了します。 : ループ本体では、<code>i</code> が <code>5</code> を超える場合は、<code>n</code> を <code>None</code> に更新してループを終了します。そうでなければ、<code>i</code> を表示して、<code>Some(i + 1)</code> を <code>n</code> に代入してループを継続します。 : このプログラムの出力は、0 から 5 までの数値が順番に表示されます。最後に <code>None</code> が表示されます。 ===== while let とベクトル ===== Rustの<code>while let</code>は、反復可能な値に対して、パターンマッチングを行いながら反復処理を行うことも出来ます。ベクトルに対してwhile letを使うと、ベクトルの末尾から要素を取り出しながら反復処理を行うことができます。 ;[https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=6b252d13f67df88f533e55dab5d3397c while-let-again.rs]:<syntaxhighlight lang=rust copy> fn main() { let mut v = vec![1, 3, 5, 7, 11]; while let Some(x) = v.pop() { println!("x = {}", x) } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> x = 11 x = 7 x = 5 x = 3 x = 1 </syntaxhighlight> : このコードは、可変長配列<code>v</code>に値を追加し、whileループでその配列から値を取り出し、それを表示するものです。 : まず、可変長配列<code>v</code>に<code>vec![1, 3, 5, 7, 11]</code>という値を設定しています。その後、<code>while let</code>式を使って、<code>v.pop()</code>の戻り値が<code>Some(x)</code>である限り、ループが継続されます。<code>v.pop()</code>は、<code>v</code>の最後の要素を取り出し、その要素があれば<code>Some</code>で包んで返し、なければ<code>None</code>を返します。 : <code>while let</code>式では、取り出した値が<code>Some(x)</code>である場合に、<code>println!("x = {}", x)</code>を実行して<code>x</code>の値を表示します。 : つまり、このコードは<code>v</code>の末尾から要素を取り出しながら、取り出した要素の値を表示するという処理を続け、最後に配列が空になったらループを終了します。 {{コラム|Rustにdo-whileはありません|2= Rustにdo-whileはありません。while の条件式に do のブロックを詰め込むことで同じことが実現できます。 ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=534d7cfaf805c7e8d99d4c1ba95ed3ab pseudo-do-while.rs]:<syntaxhighlight lang=rust highlight=6 line copy> fn main() { let mut i = 100; while { println!("{}", i); i += 1; i < 10 } {} } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 100 </syntaxhighlight> :whileの条件式が省略されたかのように見えますが、4,5,6行目を含むブロックが、while の条件式となり値はブロックの最後の6行目の式の値です。 :7行目の {} がループ本体です。 ;loopを使った例:<syntaxhighlight lang=rust line copy> fn main() { let mut i = 100; loop { println!("{}", i); i += 1; if !(i < 10) { break; } } } </syntaxhighlight> : loop のブロックの最後に脱出条件を書いた方がわかりやすいかもしれません。 }} ==== loop ==== <code>loop</code>は、明示的な条件式の指定がない限り、無限に繰り返されます。 ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9349b3eff79e311c70c87d20942cf8f2 loop-and-break.rs]:<syntaxhighlight lang=rust copy> fn main() { let mut i = 0; let result = loop { if i > 3 { break 100; } println!("i = {}", i); i += 1; }; println!("result = {}", result); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> i = 0 i = 1 i = 2 i = 3 result = 100 </syntaxhighlight> : 最初に、変数<code>i</code>を0に初期化します。そして、<code>loop</code>構文で、<code>i</code>が3より大きくなるまで繰り返します。 : 各反復中に、<code>if</code>文が使用されています。<code>if</code>の条件式は、<code>i</code>が3より大きくなった場合には<code>break 100;</code>が実行され、<code>loop</code>から脱出します。そうでない場合は、<code>println!()</code>関数を使用して、<code>i</code>の値を出力し、<code>i</code>を1増やします。 : 最後に、<code>loop</code>から脱出した後に<code>result</code>変数に格納される値は、<code>break</code>文の引数で指定された<code>100</code>です。そして、<code>println!()</code>関数を使用して、<code>result</code>の値を出力します。 : つまり、このコードは、<code>i</code>を0から3まで順に増やしながら、各値を出力し、<code>i</code>が3より大きくなったら100を返し、その後に<code>result</code>の値を出力するという処理を行っています。 ==== continue ==== <code>continue</code> を実行すると、ループのブロック内の残りの処理がスキップされ、反復処理が続行されます。 ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=49f7412cec92162b9d77881e08f43138 continue.rs]:<syntaxhighlight lang=rust highlight=9 line copy> fn main() { let mut i = 0; let result = loop { if i > 10 { break 100; } if i % 2 == 0 { i += 1; continue; } println!("i = {}", i); i += 1; }; println!("result = {}", result); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> i = 1 i = 3 i = 5 i = 7 i = 9 result = 100 </syntaxhighlight> : このコードは、0から10までの奇数を出力するプログラムです。 : まず、<code>i</code>変数を定義して0で初期化し、<code>result</code>変数を宣言しています。次に、<code>loop</code>キーワードでループを開始します。 : ループ本体では、<code>if</code>文を使って<code>i</code>が10より大きくなったら、<code>break</code>キーワードを使ってループを抜けます。これにより、11以上の奇数が出力されることはありません。 : 次に、<code>i</code>が偶数である場合は、<code>continue</code>キーワードを使ってループの先頭に戻ります。これにより、偶数はスキップされます。 : 最後に、<code>println!</code>マクロを使って現在の<code>i</code>の値を出力し、<code>i</code>を1増やします。 :ループが終了したら、最後に<code>result</code>の値を出力します。<code>break</code>キーワードが値を返すため、このループは<code>result</code>に100を設定します。 {{コラム|Rustのプログラミングでつまづきやすいところ|2=Rustはセーフティ、パフォーマンス、そしてエクスプレッションの柔軟性を組み合わせた高度なプログラミング言語です。初めてRustを使う場合、以下のようなトピックでつまづくことがよくあります。 #所有権と借用: Rustでは、各値には所有者があり、値のライフサイクルを追跡する必要があります。また、他のコードに値を渡すときは、その値を一時的に借りる必要があります。これらの概念が理解しづらい場合があります。 #ライフタイム: Rustでは、各値にはライフタイムがあり、その値が使用される期間を決定します。ライフタイムの概念が不明瞭になりがちで、特に複雑なデータ構造を扱う場合に問題が発生することがあります。 #パフォーマンスの最適化: Rustは高速な実行時パフォーマンスを提供しますが、それを達成するためには、手動でメモリ管理や最適化を行う必要があります。これらの最適化は、Rustの型システムと他の言語との違いを理解する必要があります。 #コンパイラエラー: Rustのコンパイラは非常に厳格で、コードがコンパイルできない場合があります。エラーメッセージは詳細で役に立ちますが、初めて見た場合は驚くかもしれません。 本書では、これらのトピックについて順次取り上げてゆきます。 }} == パターンマッチング == === パターンマッチングの概要 === ==== パターンマッチングの基本概念 ==== パターンマッチングは、プログラミング言語において特定のパターンとデータを照合し、条件に基づいた処理を行う手法です。この手法は、コードの可読性や柔軟性を高めるために広く使用されます。パターンマッチングの基本的な概念は、与えられたデータが特定のパターンに一致するかどうかを検査し、それに応じた処理を行います。 ==== Rustにおけるパターンマッチングの役割と重要性 ==== Rustでは、パターンマッチングは非常に重要な機能です。パターンマッチングは、異なる条件に基づいてコードをブロックに分割し、それぞれの条件に対して適切な処理を行うことができます。これにより、コードの複雑さが軽減され、可読性が向上します。また、Rustの型システムとの統合により、安全性やエラーハンドリングの向上も実現されます。 === 基本的なパターン === ==== リテラルパターン ==== リテラルパターンは、値そのものとマッチさせるための最も基本的なパターンです。以下の例では、<code>x</code>の値が<code>1</code>の場合にマッチします。 :<syntaxhighlight lang=rust copy> let x = 1; match x { 1 => println!("one"), _ => println!("not one"), } </syntaxhighlight> ==== 特定の値とのマッチング ==== リテラルパターンは、数値や文字列、真理値などの様々なリテラル値とマッチさせることができます。 :<syntaxhighlight lang=rust copy> let x = 'c'; match x { 'a' => println!("apple"), 'b' => println!("banana"), 'c' => println!("cherry"), // この行が実行される _ => println!("other"), } </syntaxhighlight> ==== 変数パターン ==== 変数パターンは、値を新しい変数にバインドするためのパターンです。以下の例では、<code>x</code>の値が<code>5</code>の場合に<code>y</code>に<code>5</code>がバインドされます。 :<syntaxhighlight lang=rust copy> let x = 5; match x { y => println!("x is {}", y), // この行が実行され、y = 5 } </syntaxhighlight> ==== 値を変数にバインドするパターン ==== 変数パターンは、値をパターン内の変数にバインドすることができます。これは、値を後で使用したり、条件分岐に利用したりするのに便利です。 :<syntaxhighlight lang=rust copy> let x = 10; match x { 0 => println!("x is zero"), y if y > 0 => println!("x is positive: {}", y), // この行が実行される y => println!("x is negative: {}", y), } </syntaxhighlight> ==== ワイルドカードパターン ==== ワイルドカードパターン(<code>_</code>)は、任意の値とマッチします。これは、特定の値を無視したい場合や、残りのパターンを捕捉したい場合に便利です。 :<syntaxhighlight lang=rust copy> let x = 42; match x { 0 => println!("x is zero"), _ => println!("x is something else"), // この行が実行される } </syntaxhighlight> ==== 任意の値とのマッチング ==== ワイルドカードパターンを使えば、任意の値とマッチさせることができます。これは、値を確認する必要がない場合や、デフォルトの処理を実行したい場合に役立ちます。 :<syntaxhighlight lang=rust copy> let x = 123; match x { 0 => println!("x is zero"), _ => println!("x is not zero"), // この行が実行される } </syntaxhighlight> === 列挙型とパターンマッチング === ==== 列挙型の定義と使い方 ==== Rustには、列挙型と呼ばれる特別な型があります。列挙型は、いくつかの列挙値のいずれかを取ることができる型です。以下の例では、<code>Direction</code>という列挙型を定義しています。 :<syntaxhighlight lang=rust copy> enum Direction { Up, Down, Left, Right, } </syntaxhighlight> 列挙型の値を作成するには、列挙型名とコロン(<code>:</code>)を使用します。 :<syntaxhighlight lang=rust copy> let up = Direction::Up; let down = Direction::Down; </syntaxhighlight> ==== 列挙型に対するパターンマッチングの活用 ==== 列挙型とパターンマッチングを組み合わせると、非常に強力なコードを書くことができます。以下の例では、<code>Direction</code>列挙型の値に対してパターンマッチングを行っています。 :<syntaxhighlight lang=rust copy> enum Direction { Up, Down, Left, Right, } fn get_direction_name(dir: Direction) -> &'static str { match dir { Direction::Up => "上", Direction::Down => "下", Direction::Left => "左", Direction::Right => "右", } } fn main() { let up = Direction::Up; let down = Direction::Down; println!("up: {}", get_direction_name(up)); // 上 println!("down: {}", get_direction_name(down)); // 下 } </syntaxhighlight> この例では、<code>get_direction_name</code>関数が列挙型<code>Direction</code>の値に対してパターンマッチングを行い、対応する文字列を返しています。 === 構造体とタプルのパターンマッチング === ==== 構造体の定義と使い方 ==== Rustでは、構造体を使ってデータを表現することができます。構造体は、フィールドと呼ばれる複数の値を持つことができます。以下の例では、<code>Person</code>という構造体を定義しています。 :<syntaxhighlight lang=rust copy> struct Person { name: String, age: u32, } </syntaxhighlight> 構造体のインスタンスを作成するには、構造体名とフィールド値を指定します。 :<syntaxhighlight lang=rust copy> let person = Person { name: String::from("Alice"), age: 30, }; </syntaxhighlight> ==== タプルの定義と使い方 ==== タプルは、異なる型の値を含むことができる集合体です。タプルは括弧<code>()</code>で囲んで定義します。 :<syntaxhighlight lang=rust copy> let tuple = (1, 3.14, "hello"); </syntaxhighlight> タプルの要素にアクセスするには、インデックスを使用します。 :<syntaxhighlight lang=rust copy> let x = tuple.0; // 1 let y = tuple.1; // 3.14 let z = tuple.2; // "hello" </syntaxhighlight> ==== 構造体とタプルに対するパターンマッチングの活用 ==== 構造体やタプルに対してパターンマッチングを行うことができます。これは、データの構造に基づいて処理を行う場合に非常に便利です。 :<syntaxhighlight lang=rust copy> struct Person { name: String, age: u32, } fn print_person_info(person: Person) { match person { Person { name, age } => println!("名前: {}, 年齢: {}", name, age), } } fn main() { let alice = Person { name: String::from("Alice"), age: 30, }; print_person_info(alice); } </syntaxhighlight> この例では、<code>print_person_info</code>関数が<code>Person</code>構造体のインスタンスに対してパターンマッチングを行い、名前と年齢を出力しています。 タプルに対してもパターンマッチングを行うことができます。 :<syntaxhighlight lang=rust copy> fn print_tuple_info(tuple: (u32, f64, &str)) { match tuple { (x, y, z) => println!("x: {}, y: {}, z: {}", x, y, z), } } fn main() { let tuple = (42, 3.14, "hello"); print_tuple_info(tuple); } </syntaxhighlight> この例では、<code>print_tuple_info</code>関数がタプル<code>(u32, f64, &str)</code>に対してパターンマッチングを行い、その要素を出力しています。 === パターンガード === ==== パターンガードの概要 ==== パターンガードは、パターンマッチングに条件を追加するための機能です。パターンに一致する値に対して、追加の条件を指定することで、より柔軟な処理を行うことができます。 ==== パターンガードの実装方法と使いどころ ==== パターンガードは、パターンに矢印(<nowiki><code>=></code></nowiki>)と条件式を追加することで実装します。条件式が真の場合のみ、パターンに一致したものとして処理されます。 :<syntaxhighlight lang=rust copy> let x = 10; match x { 2 | 5 | 10 if x % 2 == 0 => println!("x は偶数です"), _ => println!("x は奇数です"), } </syntaxhighlight> この例では、<code>x</code> が 2、5、10 のいずれかで、かつ偶数の場合は、"x は偶数です" と出力されます。 パターンガードは、様々な場面で活用することができます。 * 特定の条件を満たす値のみを処理したい場合 * エラー処理を行う場合 * 複雑なパターンを処理する場合 ==== ネストしたパターン ==== ==== ネストしたパターンの例 ==== ネストしたパターンは、複数のパターンを組み合わせたパターンです。パターンガードと組み合わせることで、より複雑な条件を処理することができます。 :<syntaxhighlight lang=rust copy> enum Color { Red, Green, Blue, } struct Point { x: i32, y: i32, color: Color, } let point = Point { x: 10, y: 20, color: Color::Red }; match point { Point { x, y, color: Color::Red } => println!("赤い点が ({}, {}) にあります", x, y), Point { x, y, color } => println!("({}, {}) に {} 色の点がいます", x, y, color), } </syntaxhighlight> この例では、<code>point</code> が <code>Point { x, y, color: Color::Red }</code> の形式の構造体である場合のみ、"赤い点が ({}, {}) にあります" と出力されます。<code>point</code> が <code>Point { x, y, color }</code> の形式の構造体である場合は、"({}, {}) に {} 色の点がいます" と出力され、<code>color</code> には <code>point</code> の <code>color</code> フィールドの値が格納されます。 ==== ネストしたパターンの利点と注意点 ==== ネストしたパターンを使用すると、複雑な条件を処理しやすくなります。しかし、パターンが複雑になりすぎると、コードが読みづらくなる可能性があります。 ==== エラーハンドリングとパターンマッチング ==== ==== ResultやOptionとの組み合わせ ==== <code>Result</code> や <code>Option</code> などの型とパターンマッチングを組み合わせることで、エラーハンドリングを効率的に行うことができます。 :<syntaxhighlight lang=rust copy> let result = read_file("filename.txt"); match result { Ok(contents) => println!("ファイルの内容: {}", contents), Err(error) => println!("エラー: {}", error), } </syntaxhighlight> この例では、<code>read_file</code> 関数が成功した場合のみ、ファイルの内容が出力されます。失敗した場合は、エラーメッセージが出力されます。 ==== エラーハンドリングにおけるパターンマッチングの有用性 ==== パターンマッチングを使用すると、エラー処理をより簡潔かつ分かりやすく記述することができます。また、エラーの種類ごとに異なる処理を行うこともできます。 === 高度なパターンマッチング === ==== パターンマッチングにおける複雑なパターンの扱い方 ==== パターンマッチングは、複雑なパターンを処理するために様々な機能を提供しています。 ; パターンガード : パターンに一致する値に対して、追加の条件を指定することができます。 ; ネストしたパターン : 複数のパターンを組み合わせたパターンを作成することができます。 ; パターン分解 : パターンに一致した値を複数の変数に格納することができます。 ; ガード付きパターン : パターンに一致する値に対して、条件分岐を実行することができます。 これらの機能を組み合わせることで、複雑なデータ構造を効率的に処理することができます。 ==== 複数のパターンに一致する場合の処理方法 ==== 複数のパターンに一致する場合は、パターンガードやネストしたパターンを使用して、どのパターンに一致するかを判別する必要があります。 == マクロ == Rustのマクロは、<code>macro_rules!</code>を使ったマクロと<code>proc_macro</code>を使ったプロシージャマクロの2種類があります。<code>macro_rules!</code>を使ったマクロはパターンマッチングを用いて簡易的なマクロを定義します。一方、<code>proc_macro</code>を使ったプロシージャマクロは、Rustのコードを受け取り、変換したり、新しいコードを生成するためのより柔軟なマクロです。 === <code>macro_rules!</code>を使ったマクロ === <code>macro_rules!</code>は、パターンに基づいてマッチングし、そのパターンに一致した場合に指定されたコードを生成する簡易なマクロを定義します。 例えば、<code>vec!</code>マクロは、可変長のベクタを生成するマクロです。これは<code>macro_rules!</code>を使って次のように実装されています。 :<syntaxhighlight lang=rust line copy> macro_rules! vec { // パターンマッチで要素を取得して新しいベクタを生成 ( $( $x:expr ),* ) => { { let mut temp_vec = Vec::new(); $(temp_vec.push($x);)* temp_vec } }; } fn main() { // `vec!`マクロを使ってベクタを生成 let my_vec = vec![1, 2, 3, 4]; // 生成されたベクタを表示 println!("{:?}", my_vec); } </syntaxhighlight> これは、<code>vec![1, 2, 3]</code>を使うと、<code>[1, 2, 3]</code>というベクタを生成します。このマクロは、<code>$( $x:expr ),*</code>のパターンに一致して、指定された式(<code>$x</code>)をベクタに挿入するコードを生成します。 === <code>proc_macro</code>を使ったプロシージャマクロ === <code>macro_rules!</code>を使わずにマクロを定義する方法もあります。これは、プロシージャマクロ(<code>proc_macro</code>)を使用した方法です。<code>proc_macro</code>は、<code>macro</code>キーワードによって定義される関数の一種で、Rustのコードを受け取り、そのコードを操作して変換することができます。 例えば、<code>vec!</code>マクロを<code>macro_rules!</code>ではなく、プロシージャマクロとして定義する場合は、<code>proc_macro</code>を使います。 :<syntaxhighlight lang=rust line copy> use proc_macro::TokenStream; use quote::quote; use syn::{parse_macro_input, Expr, parse_quote}; #[proc_macro] pub fn my_vec(input: TokenStream) -> TokenStream { // 入力をパース let input_expr: Expr = parse_macro_input!(input); // 入力を取得して新しいベクタを生成するコードを生成 let expanded = quote! { { let mut temp_vec = Vec::new(); temp_vec.push(#input_expr); temp_vec } }; // TokenStreamに変換して返す TokenStream::from(expanded) } </syntaxhighlight> この例では、<code>proc_macro</code>として<code>my_vec</code>という新しいマクロを定義しています。<code>my_vec</code>は、<code>proc_macro</code>の関数として定義され、Rustのコードを受け取り、それを操作して新しいコードを生成します。 このプロシージャマクロを使うと、次のようにマクロを呼び出すことができます。 :<syntaxhighlight lang=rust line copy> fn main() { let my_vec = my_vec!(42); println!("{:?}", my_vec); // [42] } </syntaxhighlight> この例では、<code>my_vec!</code>マクロを使用して、引数として<code>42</code>を渡しています。このマクロは、引数を含むベクタを生成するもので、<code>my_vec!(42)</code>は<code>[42]</code>というベクタを生成します。 この方法では、<code>proc_macro</code>を使用して、<code>macro_rules!</code>を使わずに独自のマクロを定義できます。ただし、この方法では<code>proc_macro</code>と関連するライブラリ(<code>syn</code>、<code>quote</code>など)を使用する必要があります。 === マクロ関数 === マクロ関数は、<code>macro_rules!</code>マクロを使って定義されます。 これは、マクロのパターンとそれに対する置換を定義するマクロです。 マクロの呼び出し元は、パターンにマッチする式を渡し、置換が適用されたコードが生成されます。 ;マクロ関数の例:<syntaxhighlight lang=rust line copy> macro_rules! say_hello { () => { println!("Hello, world!"); }; } fn main() { say_hello!(); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Hello, world! </syntaxhighlight> ;解説 :上記の例では、<code>say_hello!()</code>マクロを定義しています。これは、空の引数リストに対して<code>println!("Hello, world!")</code>を生成するマクロです。 === マクロ属性 === マクロ属性はRustのコンパイル時にコードを修飾するために使用されます。 通常は、関数や構造体、列挙型、フィールドなどに適用されます。 マクロ属性を使用することで、コンパイル時に生成されるコードに追加の情報を提供できます。 ;マクロ属性の例:<syntaxhighlight lang=rust line copy> #[derive(Debug)] struct MyStruct { my_field: i32, } fn main() { let my_struct = MyStruct { my_field: 42 }; println!("{:?}", my_struct); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> MyStruct { my_field: 42 } </syntaxhighlight> ;解説 :上記の例では、<code>#[derive(Debug)]</code>マクロ属性を使用しています。これは、<code>MyStruct</code>に<code>Debug</code>トレイトを実装するために必要なコードを生成するマクロ属性です。<code>println!</code>マクロで<code>my_struct</code>を表示する際に、<code>Debug</code>トレイトのメソッドを呼び出して情報を表示することができます。 == クレートとは == * '''Rustのパッケージ単位:''' Rustでは、コードのパッケージングや再利用のために「クレート」(Crate)という単位が使われます。1つのクレートには、1つ以上の関連するモジュールやデータ型が含まれます。 * '''Cargoによる管理:''' クレートは、RustのパッケージマネージャであるCargoによって管理されます。Cargoは、クレートの作成、ビルド、依存関係の解決などを自動化するツールです。 {{See also|Cargoハンドブック}} === クレートの構造 === 典型的なRustのクレートは、次のような構造を持ちます: :<syntaxhighlight lang=text> my_crate/ ├── src/ │ ├── main.rs │ ├── lib.rs │ └── other_module.rs ├── Cargo.toml └── README.md </syntaxhighlight> * '''src/:''' クレートのソースコードを含むディレクトリ。 * '''src/main.rs:''' クレートを実行するためのエントリポイント。 * '''src/lib.rs:''' ライブラリとしてコンパイルされる場合に使用されるエントリポイント。 * '''src/other_module.rs:''' 他のモジュール。 * '''Cargo.toml:''' クレートのメタデータ、依存関係、ビルド構成などを含むファイル。 * '''README.md:''' クレートのドキュメント。 === クレートの作成 === 新しいクレートを作成する手順は以下の通りです: # <code>cargo new</code>コマンドを使用して新しいクレートのディレクトリを作成します。 # <code>Cargo.toml</code>ファイルを編集して、クレートのメタデータを定義します。 # 必要に応じて、<code>src/main.rs</code>や他のモジュールを編集して、クレートのコードを実装します。 # <code>cargo run</code>コマンドを使用してクレートをビルドして実行します。 === クレートの公開 === クレートを他の開発者と共有するためには、それをcrates.ioという公式のクレートレジストリに公開する必要があります。公開手順は以下の通りです: # crates.ioにアカウントを作成します。 # <code>cargo login</code>コマンドを使用してcrates.ioにログインします。 # クレートのバージョン番号を更新します。 # <code>cargo publish</code>コマンドを使用してクレートを公開します。 === まとめ === Rustのクレートは、コードのパッケージングや再利用を容易にする重要な概念です。Cargoを使用してクレートを管理し、必要に応じてcrates.ioに公開することで、他の開発者とクレートを共有することができます。 Rustにおいて、パッケージはクレートと呼ばれます。クレートは、Rustのコードやライブラリをパッケージ化して共有できるようにするための仕組みです。クレートは、依存関係を解決するためのメタデータと、コードとその他のファイルから構成されています。 Rustには、<code>crates.io</code>という公式のクレートレジストリがあり、開発者はそこでクレートを共有したり、他の開発者が作成したクレートを使用したりできます。 <!-- *クレートとは何か **クレートの概要 **クレートとは何を提供するか **クレートの種類(バイナリ、ライブラリ、依存関係) *クレートの作成 **クレートの作成方法 **クレートの名前とバージョン管理 **クレートのファイル構造 **クレートのライセンス *クレートのビルド **Cargoの概要 **Cargoのインストールと初期化 **Cargo.tomlファイルの説明 *クレートのビルド方法 *クレートのテスト **テストの重要性 **ユニットテストと統合テストの違い **テストの書き方と実行方法 **テストの結果の確認方法 *クレートの公開 **クレートの公開方法 **crates.ioにクレートをアップロードする方法 **クレートのバージョン管理と更新方法 **クレートのドキュメントの生成と公開方法 *クレートの依存関係 **依存関係の概要 **依存関係の設定方法 **Cargo.lockファイルの役割 **依存関係のアップデート方法 *クレートのプロジェクト管理 **複数のクレートを管理する方法 **クレートの相互依存関係 **ワークスペースの作成と利用方法 **ワークスペースでの依存関係の管理方法 --> == 代数的データ型 == Rustにおける代数的データ型は、構造体(<code>struct</code>)と列挙型(<code>enum</code>)を指します。これらは複雑なデータ構造を表現するのに役立ちます。 === 構造体(struct) === 構造体は異なる型のフィールドを持つことができ、それぞれのフィールドは名前を持ちます。例えば: :<syntaxhighlight lang=rust copy> struct Point { x: i32, y: i32, } impl Point { fn new(x: i32, y: i32) -> Self { Self { x, y } } fn print(&self) { println!("x: {}, y: {}", self.x, self.y); } } fn main() { let origin = Point::new(0, 0); origin.print(); } </syntaxhighlight> === 列挙型(enum) === 列挙型は、いくつかの異なるバリアント(variant)の中から選択することができます。それぞれのバリアントはデータを持つことができます。 :<syntaxhighlight lang=rust copy> enum Shape { Circle(f64), // 半径を持つ Rectangle(f64, f64), // 幅と高さを持つ Square(f64), // 1辺の長さを持つ } impl Shape { fn area(&self) -> f64 { match self { Shape::Circle(radius) => std::f64::consts::PI * radius * radius, Shape::Rectangle(width, height) => width * height, Shape::Square(side) => side * side, } } } fn main() { let shapes = vec![ Shape::Circle(5.0), Shape::Rectangle(10.0, 20.0), Shape::Square(15.0), ]; for shape in &shapes { println!("Area: {}", shape.area()); } } </syntaxhighlight> これらの代数的データ型は、Rustで柔軟なデータ構造を表現する際に役立ちます。 == 属性(Attribute) == Rustの属性(Attribute)は、コンパイラに対してコードに関する追加情報や指示を提供するための注釈です。これらはコードの振る舞いや最適化、データレイアウト、コード生成に影響を与えます。属性は<code>#[...]</code>の形式で記述され、コンパイラやコードの挙動を制御します。Rustでは、属性を使用することでコードの効率性や可読性を高め、特定の機能を拡張できます。 ==== よく使用される属性 ==== # '''<code>#[derive(...)]</code>''' #* 自動導出(Derive Attribute)は、特定のトレイトを自動的に実装するために使用されます。 #* 例: <code>#[derive(Debug)]</code>は、構造体や列挙型に<code>Debug</code>トレイトを自動的に実装させ、<code>println!</code>でその内容を表示可能にします。 # '''<code>#[cfg(...)]</code>''' #* コンパイル時の条件を指定するために使います。条件に応じてコードの一部をコンパイルするかどうかを制御します。 #* 例: <code>#[cfg(target_os = "linux")]</code>は、ターゲットOSがLinuxの場合のみ有効です。 # '''<code>#[allow(...)]</code> / <code>#[deny(...)]</code> / <code>#[warn(...)]</code>''' #* コンパイラ警告のレベルを制御します。これにより、警告を許可、エラー化、または警告として表示させることができます。 #* 例: <code>#[deny(warnings)]</code>は、すべての警告をエラーとして扱います。 # '''<code>#[repr(...)]</code>''' #* データのレイアウト方法を指定します。構造体や列挙型のメモリ配置を変更するために使用されます。 #* 例: <code>#[repr(C)]</code>は、C言語と互換性のあるレイアウトを指定します。 # '''<code>#[inline]</code> / <code>#[noinline]</code>''' #* インライン展開の制御を行います。関数呼び出しのオーバーヘッドを削減するために使われ、最適化のためにインライン展開を促進します。 #* 例: <code>#[inline(always)]</code>は、関数が常にインライン展開されるように指定します。 # '''<code>#[test]</code> / <code>#[bench]</code>''' #* ユニットテストやベンチマークテストをマークするために使います。 #* 例: <code>#[test]</code>は関数をテスト対象として指定し、テストランナーによって自動的に実行されます。 # '''<code>#[macro_use]</code>''' #* マクロを利用する際に、外部クレートからマクロをインポートするために使います。 #* 例: <code>#[macro_use] extern crate serde_json;</code>で、<code>serde_json</code>クレートのマクロを利用できます。 # '''<code>#[feature(...)]</code>''' #* 実験的な機能を有効にするために使われます。安定版Rustで使用するには、<code>nightly</code>ビルドが必要です。 #* 例: <code>#[feature(proc_macro)]</code>はプロシージャマクロ機能を有効にします。 === Debugトレイト === <code>Debug</code>トレイトは、構造体や列挙型などのデータ構造をフォーマットして表示するために使われます。このトレイトを実装することで、デバッグ情報を簡単に出力することができます。 ==== 使用例 ==== :<syntaxhighlight lang=rust> #[derive(Debug)] struct MyStruct { name: String, age: u32, } fn main() { let my_data = MyStruct { name: String::from("Alice"), age: 30, }; // Debugトレイトを使用して構造体を表示 println!("My data: {:?}", my_data); } </syntaxhighlight> ;出力例: :<syntaxhighlight lang=text> My data: MyStruct { name: "Alice", age: 30 } </syntaxhighlight> このコード例では、<code>#[derive(Debug)]</code>を使って<code>MyStruct</code>構造体に<code>Debug</code>トレイトを実装し、<code>println!</code>マクロで<code>{:?}</code>フォーマット指定子を使って内容を表示しています。<code>Debug</code>トレイトを手動で実装することなく、簡単にデバッグ情報を出力できます。 === その他の属性 === * '''<code>#[allow(dead_code)]</code>''' ** 使用されていないコードに対する警告を無視します。特にデバッグコードや一時的な実装で便利です。 * '''<code>#[cfg_attr(...)]</code>''' ** 条件付きで属性を適用するために使います。<code>#[cfg]</code>と組み合わせることで、特定の条件下で属性を追加できます。 * '''<code>#[must_use]</code>''' ** 戻り値が使われなければコンパイラから警告を出します。戻り値を意図的に無視することを防ぎます。 Rustの属性は、コードの最適化やコンパイラの挙動、エラーチェックを制御するために強力なツールです。それぞれの属性は特定の目的を持っており、正しく使用することでコードの品質を向上させることができます。 == ジェネリックス == Rustにおけるジェネリクスは、特定の型に依存せず、複数の型で動作するコードを作成するための重要な機能です。ジェネリクスを使用することで、同じコードを複数の型で再利用したり、型安全性を保ちながら柔軟性を持たせたりすることができます。 === 基本的なジェネリクスの使用 === :<syntaxhighlight lang=rust copy> // Tというジェネリックな型を持つ関数 fn print_value<T: std::fmt::Display>(value: T) { println!("Value is: {}", value); } fn main() { // 使用例 print_value(10); // Tはi32として推論される print_value(2.73 as f32); // Tはf32として推論される print_value("Hello"); // Tは&strとして推論される } </syntaxhighlight> :この例では、<code>print_value</code>関数がジェネリックな型<code>T</code>を持ち、<code>T</code>は<code>std::fmt::Display</code>トレイトを実装している型に制限されています。<code>std::fmt::Display</code>トレイトは、<code>{}</code>でフォーマット可能な型を表します。 :引数<code>value</code>の型はコンパイル時に推論されます。 === ジェネリックな構造体 === :<syntaxhighlight lang=rust copy> // ジェネリックな構造体 struct Pair<T, U> { first: T, second: U, } fn main() { // 使用例 let pair_of_int_and_str = Pair { first: 10, second: "Hello" }; println!("first = {:?}, second = {:?}", pair_of_int_and_str.first, pair_of_int_and_str.second); } </syntaxhighlight> :<code>Pair</code>構造体は2つの異なる型を持つことができます。使用する際に具体的な型を指定することで、ジェネリックな構造体を作成できます。 === ジェネリックなトレイト === :<syntaxhighlight lang=rust copy> // ジェネリックなトレイト trait Printable { fn print(&self); } // TがPrintableトレイトを実装していることを要求する関数 fn print_trait<T: Printable>(item: T) { item.print(); } // 使用例 struct MyType; impl Printable for MyType { fn print(&self) { println!("Printing MyType"); } } fn main() { let obj = MyType; print_trait(obj); // Printableトレイトを実装したMyTypeのインスタンスを受け取る } </syntaxhighlight> :ここでは、<code>Printable</code>というジェネリックなトレイトを定義し、<code>print_trait</code>関数で<code>Printable</code>トレイトを実装した型<code>T</code>を受け取る方法を示しています。 ジェネリクスは、関数、構造体、列挙型、トレイトなどのRustのさまざまな要素で使用できます。これにより、柔軟性のあるコードを作成し、再利用性を高めることができます。 === 型制約 === ジェネリックスにおいては、型制約(type constraint)は、ジェネリックな型パラメータに対して特定の条件やトレイトの制約を課すことを指します。これにより、ジェネリックな型が特定の性質を持つことを保証し、安全性を確保することができます。 Rustでは、<code>trait</code>を使用して型制約を実装します。例えば、<code>std::fmt::Display</code>トレイトを持つ型に制約を課したい場合、以下のように実装します。 :<syntaxhighlight lang=rust copy> fn print_value<T: std::fmt::Display>(value: T) { println!("Value is: {}", value); } </syntaxhighlight> ここでは<code><T: std::fmt::Display></code>という構文を使用して、<code>T</code>が<code>std::fmt::Display</code>トレイトを実装している必要があることを宣言しています。この制約により、<code>print_value</code>関数は<code>std::fmt::Display</code>トレイトを実装した型に対してのみ呼び出しが可能になります。 また、複数のトレイト制約を持つこともできます。例えば、<code>std::fmt::Debug</code>と<code>std::fmt::Display</code>トレイトの両方を実装した型を要求する場合は、次のように書きます。 :<syntaxhighlight lang=rust copy> fn print_value<T: std::fmt::Debug + std::fmt::Display>(value: T) { println!("Value is: {:?}", value); } #[derive(Debug)] struct Point<T> { x: T, y: T, } // Point<T>型に対するDisplayトレイトの実装 impl<T: std::fmt::Display> std::fmt::Display for Point<T> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "Point({}, {})", self.x, self.y) } } fn main() { let int_point = Point { x: 5, y: 10 }; print_value(int_point); // `Point`型は`std::fmt::Debug`と`std::fmt::Display`を実装している let float_point = Point { x: 1.5, y: 3.2 }; print_value(float_point); // 同様に、`Point`型は`std::fmt::Debug`と`std::fmt::Display`を実装している } </syntaxhighlight> <code>T</code>が<code>std::fmt::Debug</code>と<code>std::fmt::Display</code>の両方を実装している必要があります。 これにより、ジェネリックなコードをより安全に、かつ特定の条件下で使用できるように制約を課すことができます。 == 例外処理 == Rustでは、<code>Result</code>型と<code>panic</code>による例外処理が一般的です。<code>Result</code>型は成功または失敗を表す列挙型で、<code>Ok</code>は成功時の値、<code>Err</code>はエラー時の情報を持ちます。 まず、<code>Result</code>型を使用した例を見てみましょう: :<syntaxhighlight lang=rust copy> use std::fs::File; use std::io::{self, Read}; fn read_file_contents(file_path: &str) -> Result<String, io::Error> { let mut file = File::open(file_path)?; let mut contents = String::new(); file.read_to_string(&mut contents)?; Ok(contents) } fn main() { let file_path = "/etc/hosts"; match read_file_contents(file_path) { Ok(contents) => println!("File contents: {}", contents), Err(e) => println!("Error reading file: {:?}", e), } } </syntaxhighlight> この例では、<code>read_file_contents</code>関数が<code>Result<String, io::Error></code>を返します。これは、成功時には文字列を<code>Ok</code>で、エラー時には<code>io::Error</code>を<code>Err</code>で返すことを示しています。ファイルを開いたり、読み込んだりするメソッドの呼び出しには<code>?</code>演算子を使用し、エラーが発生した場合は早期リターンしてエラーを返します。 <code>match</code>ブロックでは、<code>read_file_contents</code>の戻り値に対して<code>Ok</code>と<code>Err</code>の両方の可能性に対処し、それぞれ成功時の振る舞いとエラー時の振る舞いを定義しています。これにより、関数の呼び出し元で適切にエラーハンドリングを行うことができます。 === except() === また、Rustには<code>panic!</code>マクロを使用してプログラムを異常終了させる方法もあります。これは致命的なエラーが発生した場合に使用されますが、エラーを適切に処理するために<code>Result</code>型を使うことが推奨されます。 :<syntaxhighlight lang=rust copy> fn main() { let v = vec![1, 2, 3]; let index = 5; let value = v.get(index).expect("Failed to get the value at index"); println!("Value at index {}: {}", index, value); } </syntaxhighlight> この例では、<code>get</code>メソッドは<code>Option</code>型を返し、<code>expect</code>メソッドは<code>Some</code>の場合は中の値を返し、<code>None</code>の場合は指定したメッセージとともにプログラムを<code>panic</code>させます。 ただし、<code>expect</code>を使う際には、<code>panic</code>が発生した際に表示されるメッセージは注意深く選ぶ必要があります。 === panic!() === <code>panic!()</code>は通常、予期せぬ状況やプログラムの継続が不可能な状況で使われることがあります。以下はそのような例です。 :<syntaxhighlight lang=rust copy> fn divide(a: i32, b: i32) -> i32 { if b == 0 { panic!("Attempted to divide by zero!"); // 0で割ろうとした場合、致命的なエラーとしてpanic!()を呼ぶ } a / b // 正常な割り算を行う } fn main() { let dividend = 10; let divisor = 0; let result = divide(dividend, divisor); // divide関数を呼び出す println!("Result of division: {}", result); } </syntaxhighlight> この例では、<code>divide()</code>関数で<code>b</code>が0の場合に<code>panic!()</code>が呼ばれています。0で割ることは数学的に定義されていないため、これは致命的なエラーであり、プログラムの実行を中断させます。 <code>panic!()</code>は、このような状況に直面した場合に、プログラムを停止させるための手段として使われます。しかし、このようなエラーは通常、<code>if</code>文や<code>match</code>文などの条件分岐を使用して事前にチェックして、エラーハンドリングを行うことが推奨されます。 <code>Result</code>を使ってエラーハンドリングを行うことで、<code>panic!()</code>に頼らずにエラーを適切に処理できます。 :<syntaxhighlight lang=rust copy> fn divide(a: i32, b: i32) -> Result<i32, &'static str> { if b == 0 { Err("Attempted to divide by zero!") // 0で割ろうとした場合、エラーをResultで返す } else { Ok(a / b) // 正常な割り算の結果をOkで返す } } fn main() { let dividend = 10; let divisor = 0; match divide(dividend, divisor) { Ok(result) => println!("Result of division: {}", result), Err(e) => println!("Error: {}", e), // エラーを適切に処理する } } </syntaxhighlight> <code>divide()</code>関数は<code>Result<i32, &'static str></code>を返し、0で割るエラーの場合には<code>Err</code>を、正常な計算の場合には<code>Ok</code>を返します。<code>match</code>ブロックでは、<code>Ok</code>と<code>Err</code>の両方のケースを処理し、エラーが発生した場合にはエラーメッセージを表示します。 このように<code>Result</code>型を使用することで、エラーハンドリングを柔軟かつ安全に行うことができます。<code>panic!()</code>に頼るよりも、エラーを予測し、適切に処理する方が望ましいです。 === Option型 === <code>Option</code>型は、何らかの値が存在するかどうかを表現するRustの列挙型です。<code>Option</code>型は<code>Some</code>と<code>None</code>の2つのバリアントを持ち、<code>Some</code>は値が存在することを示し、<code>None</code>は値が存在しないことを示します。 <code>Option</code>型は、特定の操作が値を返さない可能性がある場合や、値が存在しない場合にエラーを返す代わりに<code>None</code>を返すために使われます。このような状況では、<code>Result</code>型を使用せずに、<code>Option</code>型が利用されることがあります。 以下は<code>Option</code>型の例です: :<syntaxhighlight lang=rust copy> fn divide(a: i32, b: i32) -> Option<i32> { if b == 0 { None // 0で割ろうとした場合、Noneを返す } else { Some(a / b) // 正常な割り算の結果をSomeで返す } } fn main() { let dividend = 10; let divisor = 0; match divide(dividend, divisor) { Some(result) => println!("Result of division: {}", result), // Someの場合は値を表示 None => println!("Error: Division by zero!"), // Noneの場合はエラーメッセージを表示 } } </syntaxhighlight> この例では、<code>divide()</code>関数は<code>Option<i32></code>を返し、0で割るエラーの場合には<code>None</code>を、正常な計算の場合には<code>Some</code>を返します。<code>match</code>ブロックでは、<code>Some</code>と<code>None</code>の両方のケースを処理し、<code>None</code>の場合はエラーメッセージを表示します。 <code>Option</code>型は、特に値が存在しないことが普通に起こり得る場面で、エラー処理や結果の取り扱いを行う際に有用です。例外的な状況ではなく、むしろ普通の操作の一部として考えられる「値の有無」を扱う際に利用されることが多いです。 == イテレーター == Rustの<code>Iterator</code>トレイトは、コレクションやデータのシーケンスを反復処理するための非常に強力な機能です。<code>Iterator</code>は、<code>next()</code> メソッドを提供し、それを使用して次の要素を返し、シーケンスの終わりに達した場合は <code>None</code> を返します。 基本的な使い方は次のようになります: # イテレータの作成: コレクションやデータからイテレータを作成します。<code>iter()</code>や<code>into_iter()</code>、<code>iter_mut()</code>などのメソッドを使用して、それぞれイミュータブルな参照、所有権、ミュータブルな参照を使ったイテレータを取得できます。 #:<syntaxhighlight lang=rust copy> let numbers = vec![1, 2, 3, 4, 5]; let mut iter = numbers.iter(); // イミュータブルなイテレータ </syntaxhighlight> # <code>next()</code>を使用した反復処理: <code>next()</code>メソッドを使って、イテレータから次の要素を取得します。 #:<syntaxhighlight lang=rust copy> match iter.next() { Some(number) => println!("Number: {}", number), None => println!("End of sequence"), } </syntaxhighlight> # forループを使用した反復処理: 一般的には、<code>for</code>ループを使用してイテレータを処理します。 #:<syntaxhighlight lang=rust copy> for number in numbers.iter() { println!("Number: {}", number); } </syntaxhighlight> === Iteratorトレイト === <code>Iterator</code>トレイトは、<code>map()</code>、<code>filter()</code>、<code>fold()</code>などの便利なメソッドも提供しており、これらを組み合わせることでデータを効果的に処理できます。 :<syntaxhighlight lang=rust copy> let numbers = vec![1, 2, 3, 4, 5]; // 各要素を2倍して新しいベクターを作成する let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect(); // 偶数のみをフィルタリングする let evens: Vec<i32> = numbers.into_iter().filter(|&x| x % 2 == 0).collect(); // 全要素を合計する let sum: i32 = numbers.iter().sum(); </syntaxhighlight> <code>Iterator</code>トレイトは、Rustでのデータ処理を非常に柔軟で効率的にします。関数型プログラミングの考え方に基づいた強力な機能を提供しています。 === 独自イテレータの実装 === <code>Iterator</code>トレイトを使用して独自のイテレータを実装する例を示します。 例えば、0から始まり、指定されたステップごとに増加するカウンターを作成するイテレータを実装してみましょう。 :<syntaxhighlight lang=rust copy> struct Counter { current: u32, step: u32, max: Option<u32>, } impl Counter { fn new(start: u32, step: u32, max: Option<u32>) -> Counter { Counter { current: start, step, max, } } } impl Iterator for Counter { type Item = u32; fn next(&mut self) -> Option<Self::Item> { match self.max { Some(max) if self.current >= max => None, _ => { let result = self.current; self.current += self.step; Some(result) } } } } fn main() { let counter = Counter::new(0, 2, Some(10)); for num in counter { println!("{}", num); } } </syntaxhighlight> この例では、<code>Counter</code>構造体は<code>Iterator</code>トレイトを実装しています。<code>next()</code>メソッドは、現在の値を返し、カウンターを指定されたステップで増分させます。また、<code>max</code>値が設定されており、その値に達するとイテレータは終了します。 <code>main()</code>関数内では、<code>Counter</code>イテレータを使用して0から10まで2ずつ増加する数列を生成しています。 <code>Iterator</code>トレイトを実装することで、独自のイテレータを作成し、柔軟な反復処理を行うことができます。 == impl == <code>impl</code>キーワードは、Rustで特定の型に対してメソッドやトレイトを実装するために使用されます。基礎から応用的な使い方まで見ていきましょう。 === 基礎的な使用例 === ; メソッドの実装 :<syntaxhighlight lang=rust copy> struct MyStruct { value: i32, } impl MyStruct { // MyStruct型に対するメソッドの実装 fn new(value: i32) -> MyStruct { MyStruct { value } } fn get_value(&self) -> i32 { self.value } } fn main() { let instance = MyStruct::new(42); println!("Value: {}", instance.get_value()); // メソッド呼び出し } </syntaxhighlight> <code>impl</code>ブロック内で、<code>MyStruct</code>に対する<code>new</code>メソッドと<code>get_value</code>メソッドを実装しています。<code>main</code>関数でこれらのメソッドを使用しています。 === 応用的な使用例 === ; トレイトの実装 :<syntaxhighlight lang=rust copy> trait Printable { fn print(&self); } struct MyType { value: i32, } impl Printable for MyType { fn print(&self) { println!("Value: {}", self.value); } } fn main() { let obj = MyType { value: 10 }; obj.print(); } </syntaxhighlight> {{コラム|width=100%|トレイトとインターフェイスやプロトコルとの類似性|2=トレイトは他の言語でのインターフェースやプロトコルに似ています。これらの概念は、異なる型や構造体が共通の振る舞いを持つことを許可し、それによってポリモーフィズム(多様性)を実現します。 ;インターフェース :共通の振る舞い: インターフェースは、異なるクラスが共通の振る舞いを持つことを保証します。他の言語では、この振る舞いはインターフェースで定義され、クラスはそれを実装します。 :メソッドの宣言: インターフェースでは、クラスが実装しなければならないメソッドの宣言が含まれます。 :多重継承の代替: インターフェースは多重継承の代替手段としても使われ、クラスは複数のインターフェースを実装することができます。 ;プロトコル :抽象的な振る舞いの定義: プロトコルは、特定の振る舞いや機能を表す抽象的な規約です。Swiftなどの言語ではプロトコルが使われ、クラスや構造体はそれらを適合させます。 :メソッドの要求: プロトコルは、適合する型によって実装されるメソッドやプロパティの要求を定義します。 :型の適合性の強化: プロトコルに適合することで、様々な型を同じ抽象的な概念に束縛することができます。 ;Rustのトレイト :共通の振る舞いの提供: トレイトは、構造体や他の型に共通の振る舞いを提供します。それぞれの型はトレイトを実装することで、その振る舞いを持つことができます。 :メソッドの宣言: トレイトではメソッドの宣言が行われ、それを実装することでトレイトが利用できるようになります。 :型間の相互運用性と柔軟性: トレイトは型間での相互運用性や柔軟性を提供し、異なる型が同じ振る舞いを共有することができます。 }} === ジェネリックな実装 === ; ジェネリックな構造体に対する実装 :<syntaxhighlight lang=rust copy> struct MyGeneric<T> { value: T, } impl<T> MyGeneric<T> { fn new(value: T) -> MyGeneric<T> { MyGeneric { value } } fn get_value(&self) -> &T { &self.value } } fn main() { let instance = MyGeneric::new(42); println!("Value: {:?}", instance.get_value()); let instance_str = MyGeneric::new("hello"); println!("Value: {:?}", instance_str.get_value()); } </syntaxhighlight> このコードは、<code>MyGeneric</code>を<code>i32</code>型と<code>&str</code>型の両方でインスタンス化しています。ジェネリックなデータ構造体とそのジェネリックなメソッドを利用して、異なる型に対して同じメソッドを使用する様子を示しています。<code>println!</code>マクロ内の<code>{:?}</code>は、<code>Debug</code>トレイトを実装する型の値を表示するためのフォーマット指定子です。 === 他の例 === ; 単純なトレイトの実装 :<syntaxhighlight lang=rust copy> trait Summary { fn summarize(&self) -> String; } struct Book { title: String, author: String, } impl Summary for Book { fn summarize(&self) -> String { format!("{} by {}", self.title, self.author) } } fn summarize_any(item: &impl Summary) -> String { item.summarize() } fn main() { let book = Book { title: String::from("Harry Potter"), author: String::from("J.K. Rowling"), }; println!("Summary: {}", summarize_any(&book)); } </syntaxhighlight> この例では、<code>Summary</code>トレイトを実装した様々な型に対して共通の<code>summary_any</code>関数を使用して、異なる型の値に対して要約を取得できます。 == 関数 == Rustでの関数は、プログラム内で再利用可能なコードブロックを定義するために使われます。関数は特定のタスクを実行するための手続きを含み、必要に応じて引数を受け取り、結果を返すことができます。基本的な関数の定義と使用方法を以下に示します。 === 関数の定義 === :<syntaxhighlight lang=rust copy> // 関数の定義 fn add(a: i32, b: i32) -> i32 { a + b // 最後の式の結果が自動的に返り値になる } </syntaxhighlight> この例では、<code>add</code>という名前の関数が定義されています。<code>a</code>と<code>b</code>は整数型(<code>i32</code>)の引数を受け取ります。<code>-> i32</code>は関数が<code>i32</code>型の値を返すことを示しています。 === 関数の呼び出し === :<syntaxhighlight lang=rust copy> let result = add(3, 5); println!("Result: {}", result); // "Result: 8"が出力される </syntaxhighlight> <code>add</code>関数は<code>3</code>と<code>5</code>を引数に取り、それらを足して<code>8</code>を返します。<code>println!</code>マクロを使ってその結果を出力しています。 === 引数と戻り値 === * 引数: 関数に渡す値。関数の定義において、引数は型を指定する必要があります。 * 戻り値: <code>-></code>演算子を使って関数が返す値の型を指定します。Rustでは最後の式の結果が自動的に返り値となります。 === パターンマッチングを使用した複数の戻り値 === Rustの関数は複数の値を返すこともできます。 :<syntaxhighlight lang=rust copy> fn calculate(a: i32, b: i32) -> (i32, i32) { (a + b, a - b) } let (sum, difference) = calculate(10, 5); println!("Sum: {}, Difference: {}", sum, difference); // "Sum: 15, Difference: 5"が出力される </syntaxhighlight> === 関数の機能 === * 再帰: 自分自身を呼び出すことができます。 * クロージャ: 無名の関数を作成し、変数にキャプチャさせることができます。 * ジェネリクス: 型を指定せずに関数を定義することができ、後から具体的な型を指定できます。 Rustの関数は安全性、速度、パターンマッチング、ジェネリクス、所有権など、言語の多くの特徴を活用しています。これらの特性は、Rustを強力なプログラミング言語にしています。 === ライフタイム: === Rustの関数とライフタイムは、関連性がありますが、関数のシグネチャ内でライフタイムを使用することは必ずしも必要ではありません。しかし、関数が参照を含む場合や、ジェネリクスを使う場合には、ライフタイムの指定が必要になることがあります。 ==== 関数内のライフタイム ==== :<syntaxhighlight lang=rust copy> fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } </syntaxhighlight> この例では、<code>longest</code>関数は2つの文字列スライスを引数として受け取り、それらのうち長さが長い方の参照を返します。<code>'a</code>はライフタイムパラメータであり、2つの引数と返り値の参照のライフタイムが同じことを示しています。これにより、返される参照が有効なスコープを保証します。 ==== ライフタイムの省略 ==== Rustでは、ライフタイムの省略規則があります。特定のパターンにおいては、コンパイラが暗黙的にライフタイムを推論することができます。例えば、次のような関数シグネチャではライフタイムの省略が行われます。 :<syntaxhighlight lang=rust copy> fn longest(x: &str, y: &str) -> &str { // ... } </syntaxhighlight> このような場合、コンパイラは適切なライフタイムを自動的に推論します。ただし、ライフタイムの省略は特定の条件に限定され、全ての場面で使えるわけではありません。 ライフタイムは主に、参照の有効期間を指定するために使用され、特に関数内で参照を扱う際に重要な役割を果たします。関数が複数の参照を扱い、それらの有効期間を整理する必要がある場合には、ライフタイムの指定が必要になることがあります。 === クロージャ: === Rustではクロージャも関数として扱われます。クロージャは自身のスコープ外の変数をキャプチャして利用できます。これは非常に便利で、関数よりも柔軟な振る舞いを提供します。 次のコード例では、クロージャと関数の組み合わせを使って、外部スコープの変数をキャプチャして利用する方法を示します。 :<syntaxhighlight lang=rust copy> fn main() { let base_number = 10; // クロージャの定義 let add_to_base = |x| x + base_number; let new_number = 7; // クロージャの使用 let result = add_to_base(new_number); println!("Result: {}", result); // "Result: 17"が出力される } </syntaxhighlight> この例では、<code>base_number</code>という変数が<code>add_to_base</code>クロージャにキャプチャされ、後でクロージャ内で使用されています。クロージャは外部の変数をキャプチャすることができ、そのコンテキストを保持して使用できる点が関数とは異なる特徴です。 Rustの関数は、パターンマッチングやジェネリクス、ライフタイム、クロージャなどの機能と組み合わせて、安全で効率的なコードを記述するための強力なツールです。 == 高階関数 == Rustは、関数型プログラミングの要素を備えた汎用プログラミング言語です。Rustでは、関数を変数やデータ構造に格納したり、関数を関数のパラメータとして渡したりすることができます。これらの機能は、高階関数として知られています。 Rustで高階関数を使用すると、コードの再利用性と保守性を向上させることができます。また、コードをより簡潔で読みやすくすることもできます。 Rustで高階関数を使用する方法はいくつかあります。 === 関数を変数に格納する === Rustでは、関数を変数に格納することができます。これにより、関数を繰り返し使用したり、関数を別の関数に渡したりすることができます。 :<syntaxhighlight lang=rust copy> fn square(x: i32) -> i32 { x * x } let square_function = square; println!("The square of 5 is {}", square_function(5)); </syntaxhighlight> このコードでは、square()関数をsquare_function変数に格納しています。その後、square_function()関数を呼び出すことで、square()関数と同じ結果を得ることができます。 === 関数を関数のパラメータとして渡す === Rustでは、関数を関数のパラメータとして渡すことができます。これにより、関数を別の関数に処理させることができます。 :<syntaxhighlight lang=rust copy> fn map_numbers(numbers: &[i32], f: fn(i32) -> i32) -> Vec<i32> { let mut result = Vec::new(); for number in numbers { result.push(f(number)); } result } fn square(x: i32) -> i32 { x * x } let numbers = [1, 2, 3, 4, 5]; let squared_numbers = map_numbers(numbers, square); println!("The squared numbers are: {:?}", squared_numbers); </syntaxhighlight> このコードでは、map_numbers()関数は、numbers配列の各要素をf関数に渡し、その結果を新しい配列に格納します。 === クロージャを使用する === Rustでは、クロージャを使用して高階関数を作成することができます。クロージャは、関数本体の一部として定義された関数です。クロージャは、変数やデータ構造を捕捉して、関数本体内で使用することができます。 :<syntaxhighlight lang=rust copy> fn filter_numbers(numbers: &[i32], f: impl Fn(i32) -> bool) -> Vec<i32> { let mut result = Vec::new(); for number in numbers { if f(number) { result.push(number); } } result } fn is_even(x: i32) -> bool { x % 2 == 0 } let numbers = [1, 2, 3, 4, 5]; let even_numbers = filter_numbers(numbers, is_even); println!("The even numbers are: {:?}", even_numbers); </syntaxhighlight> このコードでは、filter_numbers()関数は、numbers配列の各要素をfクロージャに渡し、その結果がtrueである場合、その要素を新しい配列に格納します。 Rustで高階関数を使用すると、コードの再利用性と保守性を向上させることができます。また、コードをより簡潔で読みやすくすることもできます。 == 標準ライブラリー == Rustの標準ライブラリー(Standard Library)は、Rustコンパイラにバンドルされており、基本的なデータ構造、OSとのやり取り、スレッド、ファイルI/O、ネットワーキングなどの多くの機能を提供しています。以下に、標準ライブラリーの主要なカテゴリを紹介します。 === コレクション(Collections) === * <code>Vec</code>, <code>VecDeque</code>: ベクターや双方向キューなどの動的な配列。 * <code>HashMap</code>, <code>BTreeMap</code>: ハッシュマップやBツリーマップなどのキーと値のペアを保持するマップ。 * <code>HashSet</code>, <code>BTreeSet</code>: ハッシュセットやBツリーセットなどのユニークな値を保持するセット。 === スレッドと同期(Concurrency) === * <code>std::thread</code>: スレッドの生成と操作を提供。 * <code>std::sync</code>: Mutex、Atomicなどの同期機能を提供するモジュール。 === ファイルI/Oとネットワーキング(I/O and Networking) === * <code>std::fs</code>: ファイルシステムとの相互作用を可能にするモジュール。 * <code>std::net</code>: ネットワーキングのためのモジュール。 === プリミティブ型(Primitive Types) === * <code>std::primitive</code>: Rustのプリミティブ型(整数、浮動小数点数など)の機能を提供。 === OS相互作用とその他(OS Interactions and Miscellaneous) === * <code>std::env</code>: 環境変数の取得などのOS環境に関する操作。 * <code>std::time</code>: 時間に関する機能を提供。 === 入出力(Input/Output) === * <code>std::io</code>: 標準入出力やバッファリング、ファイルI/OなどのI/O操作を提供。 === 文字列処理(String Manipulation) === * <code>std::str</code>: 文字列の操作、変換、検索などの機能を提供。 === メモリ管理(Memory Management) === * <code>std::alloc</code>: メモリの割り当てと解放のための機能。 === コンパイラ支援(Compiler Support) === * <code>std::marker</code>: マーカートレイトを提供し、コンパイラへのヒントを与える。 これらは標準ライブラリーの一部であり、Rustの基本的な機能を提供しています。開発者はこれらのモジュールや機能を組み合わせて、安全で効率的なプログラムを構築できます。 == コードギャラリー == このコードギャラリーは、さまざまなRustの機能やパターン、ベストプラクティスを示すためのサンプルコード集です。 === エラトステネスの篩 === :<syntaxhighlight lang=rust copy> fn eratosthenes(n: usize) { let mut sieve = vec![true; n + 1]; sieve[0] = false; sieve[1] = false; for i in 2..=n { if sieve[i] { // jをi*iから始める for j in (i * i..=n).step_by(i) { sieve[j] = false; } } if i * i >= n { break; } } for i in 2..=n { if sieve[i] { println!("{}", i); } } } fn main() { eratosthenes(100); } </syntaxhighlight> このRustのコードは、エラトステネスの篩を使用して与えられた範囲内の素数を見つけるものです。 # <code>eratosthenes</code> 関数は、与えられた <code>n</code> までの素数を見つけるためのエラトステネスの篩アルゴリズムを実装しています。このアルゴリズムでは、最初に <code>n + 1</code> サイズの <code>sieve</code> というブール型の配列を作成します。この配列は、各インデックスが素数かどうかを示します。 # <code>sieve[0]</code> と <code>sieve[1]</code> は素数ではないので、それらを <code>false</code> に設定します。 # 2 から <code>n</code> までの各数について、その数が素数である場合は、その数の倍数を素数ではないとマークします。これにより、素数の倍数を持つ数は素数ではないことがわかります。 # <code>main</code> 関数では、<code>eratosthenes</code> 関数を呼び出し、100までの素数を見つけます。見つかった素数は画面に出力されます。 このアルゴリズムは素数を見つけるための効率的な方法の一つであり、与えられた範囲内の素数を見つけることができます。 === 最大公約数と最小公倍数 === :<syntaxhighlight lang=rust copy> fn gcd2(m: i32, n: i32) -> i32 { if n == 0 { m } else { gcd2(n, m % n) } } fn gcd(ints: &[i32]) -> i32 { ints.iter().cloned().fold(ints[0], gcd2) } fn lcm2(m: i32, n: i32) -> i32 { m * n / gcd2(m, n) } fn lcm(ints: &[i32]) -> i32 { ints.iter().cloned().fold(ints[0], lcm2) } fn main() { println!("gcd2(30, 45) => {}", gcd2(30, 45)); println!("gcd(&[30, 72, 12]) => {}", gcd(&[30, 72, 12])); println!("lcm2(30, 72) => {}", lcm2(30, 72)); println!("lcm(&[30, 42, 72]) => {}", lcm(&[30, 42, 72])); } </syntaxhighlight> このコードは高階関数を利用しています。<code>fold</code>関数は特に重要で、与えられた配列内の要素に対して特定の操作を順番に適用することができます。 まず、<code>gcd</code>関数では、<code>ints</code>配列内の要素に対して<code>fold</code>関数を使って最大公約数(<code>gcd2</code>関数)を計算しています。<code>fold</code>は初期値として<code>ints[0]</code>を受け取り、各要素<code>value</code>に対して<code>gcd2</code>を適用し、次の要素に対して再帰的に<code>gcd2</code>を適用します。これにより、配列内のすべての要素の最大公約数が計算されます。 同様に、<code>lcm</code>関数も<code>fold</code>を利用しています。ここでは<code>lcm2</code>関数が利用され、各要素に対して最小公倍数を求めるための計算が行われます。 高階関数の利用により、配列内の要素に対して繰り返し処理を行う必要がある場合でも、シンプルで効率的なコードを書くことができます。 === 二分法 === [[W:二分法|二分法]] :<syntaxhighlight lang=rust copy> fn bisection(low: f64, high: f64, f: impl Fn(f64) -> f64) -> f64 { let x = (low + high) / 2.0; let fx = f(x); match () { _ if (fx.abs() - 1.0e-10) < f64::EPSILON => x, _ if fx < 0.0 => bisection(x, high, f), _ => bisection(low, x, f), } } fn main() { let result1 = bisection(0.0, 3.0, |x| x - 1.0); println!("{}", result1); let result2 = bisection(0.0, 3.0, |x| x * x - 1.0); println!("{}", result2); } </syntaxhighlight> : [[旧課程(-2012年度)高等学校数学B/数値計算とコンピューター#2分法]]の例を Rust に移植しました。 このRustのコードは、二分法(bisection method)を使って与えられた関数の根を見つけるものです。 <code>bisection</code>関数は、<code>low</code>から<code>high</code>の範囲で与えられた関数 <code>f</code> の根を探します。<code>f</code> は <code>Fn(f64) -> f64</code> のトレイトを実装しており、実際の関数の定義は呼び出し時に与えられます。 この関数は再帰的に呼び出されます。与えられた区間 <code>[low, high]</code> の中央値 <code>x</code> を求め、その点での関数の値 <code>f(x)</code> を計算します。この値が非常に小さいか(ここでは <code>1.0e-10</code>未満)、または非常に近い数になるまで <code>low</code> または <code>high</code> を更新して、区間を狭めていきます。 <code>main</code>関数では、2つの異なる関数 <code>x - 1</code> と <code>x^2 - 1</code> に対して <code>bisection</code> 関数を呼び出して、それぞれの関数の根を探し、<code>println!</code> マクロを使って根を表示しています。 === 構造体とメソッド === Rustにクラスはありませんが、構造体がメソッドを持つことが出来ます。 :<syntaxhighlight lang=rust copy> #[derive(Debug)] struct Hello { s: String, } impl Hello { fn new(s: &str) -> Hello { // 空文字列の場合は "world" を使用 let s = if s.is_empty() { "world" } else { s }; Hello { s: s.to_string() } } fn to_string(&self) -> String { format!("Hello {}!", self.s) } fn print(&self) { println!("{}", self.to_string()); // 直接to_stringを呼び出す } } fn main() { let hello1 = Hello::new(""); hello1.print(); // to_string()を呼ぶ必要がなくなる let hello2 = Hello::new("my friend"); hello2.print(); // 同上 println!( "Hello.constructor.name => Hello\nhello1 => {:?}\nhello2.s => {}", hello1, hello2.s ); } </syntaxhighlight> このRustのコードは、<code>Hello</code>という名前の構造体を定義し、その構造体に関連するメソッドや、<code>main()</code>関数を含んでいます。 まず、<code>Hello</code>構造体は<code>String</code>型の<code>s</code>フィールドを持っています。<code>#[derive(Debug)]</code>アトリビュートは、この構造体に<code>Debug</code>トレイトを自動的に実装するようコンパイラに指示しています。<code>Debug</code>トレイトを実装することで、デバッグ目的で構造体の内容を出力できるようになります。 <code>impl Hello</code>ブロックでは、<code>Hello</code>構造体に対するメソッドが定義されています。 * <code>new</code>メソッドは、引数として文字列を受け取り、それが空文字列の場合はデフォルトの文字列 "world" を持つ<code>Hello</code>構造体を生成します。それ以外の場合は、引数で渡された文字列を使用して<code>Hello</code>構造体を作成します。 * <code>to_string</code>メソッドは、<code>Hello</code>構造体のインスタンスに対して、挨拶文を含む文字列を生成します。 * <code>print</code>メソッドは、<code>Hello</code>構造体のインスタンスの<code>s</code>フィールド(挨拶文)を標準出力に表示します。 <code>main()</code>関数では、<code>Hello</code>構造体を使ってインスタンスを生成し、メソッドを呼び出しています。<code>println!</code>マクロを使用して、構造体やそのフィールドをデバッグ出力しています。最後の<code>println!</code>マクロでは、<code>hello1</code>のデバッグ表示(<code>{:?}</code>)と<code>hello2</code>の<code>s</code>フィールドを出力しています。 === 構造体とメソッド(2) === [[Go/メソッドとインターフェース]]からの移植です。 :<syntaxhighlight lang=go> use std::f64::consts::PI; #[derive(Debug)] struct GeoCoord { longitude: f64, latitude: f64, } impl GeoCoord { /// 地球の半径(キロメートル) const EARTH_RADIUS: f64 = 6371.008; /// 緯度・経度をラジアンに変換するための係数 const RADIAN_CONVERSION: f64 = PI / 180.0; /// 2つの地理座標間の距離を計算する fn distance(&self, other: &GeoCoord) -> f64 { let lat_i = self.latitude * Self::RADIAN_CONVERSION; let other_lat_i = other.latitude * Self::RADIAN_CONVERSION; let long_diff_i = (self.longitude - other.longitude) * Self::RADIAN_CONVERSION; let sin_lat = f64::sin(lat_i) * f64::sin(other_lat_i); let cos_lat = f64::cos(lat_i) * f64::cos(other_lat_i); let cos_long_diff = f64::cos(long_diff_i); let distance = f64::acos(sin_lat + cos_lat * cos_long_diff) * Self::EARTH_RADIUS; distance } } impl std::fmt::Display for GeoCoord { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let (ew, ns, long, lat) = format_coordinates(self.longitude, self.latitude); write!(f, "({}: {:.6}, {}: {:.6})", ew, long, ns, lat) } } /// 緯度・経度の値を適切にフォーマットする関数 fn format_coordinates(longitude: f64, latitude: f64) -> (&'static str, &'static str, f64, f64) { let (ew, long) = if longitude < 0.0 { ("西経", -longitude) } else { ("東経", longitude) }; let (ns, lat) = if latitude < 0.0 { ("南緯", -latitude) } else { ("北緯", latitude) }; (ew, ns, long, lat) } fn main() { let sites = vec![ ("東京駅", GeoCoord { longitude: 139.7673068, latitude: 35.6809591 }), ("シドニー・オペラハウス", GeoCoord { longitude: 151.215278, latitude: -33.856778 }), ("グリニッジ天文台", GeoCoord { longitude: -0.0014, latitude: 51.4778 }), ]; for (name, gc) in &sites { println!("{}: {}", name, gc); } for i in 0..sites.len() { let current_site = &sites[i]; let next_site = &sites[(i + 1) % sites.len()]; println!( "{} - {}: {:.2} [km]", current_site.0, next_site.0, current_site.1.distance(&next_site.1) ); } } </syntaxhighlight> === 逆ポーランド記法の解析と評価 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} 逆ポーランド記法は、数式の演算子を後置記法で表現する方法です。通常の中置記法では演算子がオペランドの間に置かれますが、逆ポーランド記法では演算子がオペランドの後ろに置かれます。これにより、括弧や演算子の優先順位を考える必要がなくなり、計算機で容易に評価できる形式になります。 例えば、中置記法での式 <code>3 + 4 * 5</code> は、逆ポーランド記法では <code>3 4 5 * +</code> と表現されます。この記法では、演算子が対象のオペランドに対して順番に適用されます。 :<syntaxhighlight lang=rust copy> enum Token { Add, Sub, Mul, Div, Operand(i32), } impl Token { fn evaluate(&self, stack: &mut Vec<i32>) -> Result<(), &'static str> { match self { Token::Add | Token::Sub | Token::Mul | Token::Div => { if stack.len() < 2 { return Err("Invalid expression: not enough operands for operator"); } let operand2 = stack.pop().unwrap(); let operand1 = stack.pop().unwrap(); match self { Token::Add => stack.push(operand1 + operand2), Token::Sub => stack.push(operand1 - operand2), Token::Mul => stack.push(operand1 * operand2), Token::Div => { if operand2 == 0 { return Err("Division by zero"); } stack.push(operand1 / operand2); } _ => unreachable!(), } } Token::Operand(num) => { stack.push(*num); } } Ok(()) } } fn evaluate_expression(expression: &str) -> Result<i32, &'static str> { let mut stack: Vec<i32> = Vec::new(); let tokens: Vec<Token> = expression .split_whitespace() .map(|token| { if let Ok(parsed_num) = token.parse::<i32>() { Token::Operand(parsed_num) } else { match token { "+" => Token::Add, "-" => Token::Sub, "*" => Token::Mul, "/" => Token::Div, _ => unreachable!(), } } }) .collect(); for token in tokens { if let Err(err) = token.evaluate(&mut stack) { return Err(err); } } if stack.len() != 1 { return Err("Invalid expression: too many operands or operators"); } Ok(stack[0]) } fn main() { let expression = "5 3 2 * + 8 2 / -"; match evaluate_expression(expression) { Ok(result) => println!("Result: {}", result), Err(err) => println!("Error: {}", err), } } </syntaxhighlight> このコードは、<code>Token</code>という列挙型を使って逆ポーランド記法の式を評価する関数を実装しています。 まず、<code>Token</code>は<code>Add</code>、<code>Sub</code>、<code>Mul</code>、<code>Div</code>、<code>Operand</code>の5つのバリアントを持ちます。<code>Operand</code>は整数値を保持します。 <code>Token</code>には<code>evaluate</code>というメソッドが実装されています。このメソッドでは、<code>Token</code>の各バリアントに対する処理が行われます。<code>Add</code>、<code>Sub</code>、<code>Mul</code>、<code>Div</code>の場合は、スタックから2つの値を取り出して、それらを演算し結果をスタックに積みます。<code>Operand</code>の場合は、その値をスタックに積みます。 <code>evaluate_expression</code>関数では、与えられた式をトークン化して<code>Token</code>のベクターに変換し、それぞれのトークンに対して<code>evaluate</code>メソッドを実行します。各トークンの評価においてエラーが発生した場合、そのエラーメッセージが直ちに返されます。最終的に、スタックに残った値が1つでない場合もエラーが返されます。 <code>main</code>関数では、<code>evaluate_expression</code>の結果に応じて結果を出力するか、エラーを表示します。これにより、逆ポーランド記法の式を評価し、正常な結果またはエラーメッセージを表示できます。 === 式を逆ポーランド記法に変換する(手書き) === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} :<syntaxhighlight lang=rust copy> #[derive(Debug, Clone, Copy)] enum Token { Number(i32), Plus, Minus, Multiply, Divide, } fn main() { let input = "12+34*56/78"; let tokens = parse_input(input); let rpn = infix_to_rpn(tokens); println!("{:?}", rpn); } fn parse_input(input: &str) -> Vec<Token> { let mut tokens = Vec::new(); let mut num = String::new(); for c in input.chars() { match c { '0'..='9' => num.push(c), // 数字を収集 '+' | '-' | '*' | '/' => { if !num.is_empty() { let n = num.parse().unwrap(); tokens.push(Token::Number(n)); // 数字をトークンに追加 num.clear(); // 数字をリセット } // 演算子をトークンに追加 match c { '+' => tokens.push(Token::Plus), '-' => tokens.push(Token::Minus), '*' => tokens.push(Token::Multiply), '/' => tokens.push(Token::Divide), _ => unreachable!(), } } _ => panic!("Invalid character in input!"), // 無効な文字の場合 } } // 最後の数値をトークンに追加 if !num.is_empty() { let n = num.parse().unwrap(); tokens.push(Token::Number(n)); } tokens } fn infix_to_rpn(tokens: Vec<Token>) -> Vec<Token> { let mut rpn = Vec::new(); let mut stack = Vec::new(); for token in tokens { match token { Token::Number(_) => rpn.push(token), // 数字はそのままRPNに追加 Token::Plus | Token::Minus | Token::Multiply | Token::Divide => { while let Some(&top) = stack.last() { if precedence(&token) <= precedence(&top) { rpn.push(stack.pop().unwrap()); // 優先順位が高い演算子を出力 } else { break; // 自分より優先順位が低い演算子が来たら中断 } } stack.push(token); // 演算子をスタックに追加 } } } // スタックに残った演算子を全てRPNに追加 while let Some(op) = stack.pop() { rpn.push(op); } rpn } fn precedence(token: &Token) -> i32 { match token { Token::Multiply | Token::Divide => 2, Token::Plus | Token::Minus => 1, _ => 0, } } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> [Number(12), Number(34), Number(56), Multiply, Number(78), Divide, Plus] </syntaxhighlight> このコードは、与えられた文字列を逆ポーランド記法(RPN)に変換するプログラムです。以下にその構造を解説します: # <code>Token</code> 列挙型: 数字と演算子を表す列挙型です。<code>Number</code> は数字を、<code>Plus</code>, <code>Minus</code>, <code>Multiply</code>, <code>Divide</code> はそれぞれ演算子を表します。<code>derive(Debug, Clone, Copy)</code> が付与されており、デバッグ表示やクローン、コピーが可能です。 # <code>parse_input</code> 関数: 与えられた文字列をトークンに分割します。数字の場合は文字列を数値に変換して <code>Token::Number</code> に、演算子の場合は対応する <code>Token</code> に変換し、それらを <code>Vec<Token></code> に収集します。 # <code>infix_to_rpn</code> 関数: 中置記法のトークンのベクターを逆ポーランド記法に変換します。スタックとRPNベクターを使用して、トークンを処理します。演算子の場合、スタックのトップとの優先順位を比較して、適切な順序でRPNに追加します。 # <code>precedence</code> 関数: 演算子の優先順位を返します。乗算と除算が優先され、それ以外の演算子は同じ優先順位です。 このコードは、入力された文字列を数値と演算子に分割し、それらを逆ポーランド記法に変換する機能を持っています。特定の演算子の優先順位を考慮しながら適切な順序で演算子を配置し、RPNを生成します。 === 式を逆ポーランド記法に変換する(手書き:別解:再帰下降パーサー) === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} :<syntaxhighlight lang=rust copy> #[derive(Debug, Clone, PartialEq)] // Cloneトレイトを追加 enum Token { Number(f64), Plus, Minus, Multiply, Divide, LParen, RParen, EOF, } struct Lexer<'a> { input: &'a str, position: usize, } impl<'a> Lexer<'a> { fn new(input: &'a str) -> Lexer<'a> { Lexer { input, position: 0 } } // 空白をスキップする fn skip_whitespace(&mut self) { while self.position < self.input.len() && self.input.chars().nth(self.position).unwrap().is_whitespace() { self.position += 1; } } // 次のトークンを取得する fn next_token(&mut self) -> Token { self.skip_whitespace(); if self.position >= self.input.len() { return Token::EOF; } let current_char = self.input.chars().nth(self.position).unwrap(); self.position += 1; // 次の位置に進める match current_char { '+' => Token::Plus, '-' => Token::Minus, '*' => Token::Multiply, '/' => Token::Divide, '(' => Token::LParen, ')' => Token::RParen, _ if current_char.is_digit(10) || current_char == '.' => { let start = self.position - 1; // トークンの開始位置 while self.position < self.input.len() && (self.input.chars().nth(self.position).unwrap().is_digit(10) || self.input.chars().nth(self.position).unwrap() == '.') { self.position += 1; } let number_str = &self.input[start..self.position]; Token::Number(number_str.parse::<f64>().unwrap()) } _ => panic!("Invalid character found: {}", current_char), } } } struct Parser<'a> { lexer: Lexer<'a>, current_token: Token, } impl<'a> Parser<'a> { fn new(mut lexer: Lexer<'a>) -> Parser<'a> { let current_token = lexer.next_token(); Parser { lexer, current_token } } // トークンを消費する fn eat(&mut self, token: Token) { if self.current_token == token { self.current_token = self.lexer.next_token(); } else { panic!("Invalid syntax"); } } // 項を解析する fn factor(&mut self) -> Vec<Token> { match self.current_token { Token::Number(num) => { self.eat(Token::Number(num)); vec![Token::Number(num)] } Token::LParen => { self.eat(Token::LParen); let result = self.expr(); self.eat(Token::RParen); result } _ => panic!("Invalid syntax"), } } // 積項を解析する fn term(&mut self) -> Vec<Token> { let mut result = self.factor(); while matches!(self.current_token, Token::Multiply | Token::Divide) { let op = self.current_token.clone(); self.eat(op.clone()); let mut next_factor = self.factor(); result.append(&mut next_factor); result.push(op); } result } // 式を解析する fn expr(&mut self) -> Vec<Token> { let mut result = self.term(); while matches!(self.current_token, Token::Plus | Token::Minus) { let op = self.current_token.clone(); self.eat(op.clone()); let mut next_term = self.term(); result.append(&mut next_term); result.push(op); } result } } // 逆ポーランド記法を生成する関数 fn generate_reverse_polish_notation(input: &str) -> Vec<Token> { let lexer = Lexer::new(input); let mut parser = Parser::new(lexer); parser.expr() } fn main() { let result = generate_reverse_polish_notation("12 + 34 * 56 / 78"); println!("{:?}", result); } </syntaxhighlight> コードは、与えられた数式を逆ポーランド記法に変換するためのプログラムです。ここでは、Lexer(字句解析器)とParser(構文解析器)という2つの主要な構成要素があります。 ; Token : <code>Token</code> 列挙型は、数式をトークンに分割するために使用されます。数字、演算子、および括弧のトークンを定義します。 ; Lexer : <code>Lexer</code> は、与えられた数式文字列をトークンに分割する役割を担います。<code>next_token</code> メソッドは、数式の文字列を走査して、各文字がどの種類のトークンに対応するかを判断します。 ; Parser : <code>Parser</code> は、Lexer によって生成されたトークンのストリームを受け取り、逆ポーランド表記に変換します。再帰的に式を解析し、優先順位を考慮しながら、逆ポーランド表記のトークン列を生成します。 :* <code>factor()</code> メソッドは、数または括弧で始まる要素(ファクター)を解析します。 :* <code>term()</code> メソッドは、乗算と除算の演算子を解析します。 :* <code>expr()</code> メソッドは、加算と減算の演算子を解析します。 ; generate_reverse_polish_notation 関数 : この関数は、与えられた数式文字列を逆ポーランド表記に変換します。Lexer を使ってトークンに分割し、Parser を使って逆ポーランド表記のトークン列を生成します。 ; main 関数 : <code>generate_reverse_polish_notation</code> を使って、指定された式を逆ポーランド表記で出力します。 逆ポーランド記法は、演算子がオペランドの後ろに置かれるので、式を解析してトークン列に変換することで、演算の優先順位を反映した形で数式を表現することができます。 ---- これらのコードは、与えられた数学式を逆ポーランド記法(Reverse Polish Notation, RPN)に変換する方法を示していますが、アプローチが異なります。 1番目のコードは、文字列を直接解析してトークンに分割し、その後逆ポーランド記法に変換しています。一方、2番目のコードは、字句解析器(lexer)とパーサー(parser)を使用して、トークンに分割し、その後パースして逆ポーランド記法に変換しています。 1番目のコードは、基本的な数値と演算子の処理に集中しています。一方で、2番目のコードは字句解析や構文解析の段階を厳密に分離しています。また、2番目のコードは小数点もサポートしており、より柔軟な数値表現を可能にしています。 どちらのコードも同じ目的を果たしていますが、アプローチの違いが見られます。1番目のコードはシンプルで直感的ですが、拡張性に欠けるかもしれません。 一方で、2番目のコードはより複雑ですが、より柔軟で拡張性があります。それぞれのコードには長所と短所がありますが、どちらも与えられた数式を逆ポーランド記法に変換する点では同等の結果を提供します。実際には2番めのコードは不動小数点数やカッコに対応しています。 === 式を逆ポーランド記法に変換する(nom版) === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} :<syntaxhighlight lang=rust copy> use nom::character::complete::{char, digit1}; use nom::combinator::map; use nom::multi::many0; use nom::sequence::delimited; use nom::IResult; #[derive(Debug, Clone, Copy)] enum Token { Number(i32), Plus, Minus, Multiply, Divide, } fn main() { let input = "12+34*56/78"; let (_, tokens) = parse_input(input).unwrap(); let rpn = infix_to_rpn(tokens); println!("{:?}", rpn); } fn parse_input(input: &str) -> IResult<&str, Vec<Token>> { many0(parse_token)(input) } fn parse_token(input: &str) -> IResult<&str, Token> { let (input, token) = delimited( nom::character::complete::space0, nom::branch::alt(( map(digit1, |s: &str| Token::Number(s.parse().unwrap())), map(char('+'), |_| Token::Plus), map(char('-'), |_| Token::Minus), map(char('*'), |_| Token::Multiply), map(char('/'), |_| Token::Divide), )), nom::character::complete::space0, )(input)?; Ok((input, token)) } fn infix_to_rpn(tokens: Vec<Token>) -> Vec<Token> { let mut rpn = Vec::new(); let mut stack = Vec::new(); for token in tokens { match token { Token::Number(_) => rpn.push(token), Token::Plus | Token::Minus | Token::Multiply | Token::Divide => { while let Some(top) = stack.last().copied() { if precedence(&token) <= precedence(&top) { rpn.push(stack.pop().unwrap()); } else { break; } } stack.push(token); } } } while let Some(op) = stack.pop() { rpn.push(op); } rpn } fn precedence(token: &Token) -> i32 { match token { Token::Multiply | Token::Divide => 2, Token::Plus | Token::Minus => 1, _ => 0, } } </syntaxhighlight> このコードは、<code>nom</code>というパーサーコンビネータライブラリを使用して、与えられた文字列を解析し、トークンに分割する機能を持っています。前のコードと比較してみましょう。 # <code>parse_input</code> 関数: <code>many0</code>コンビネータを使って、<code>parse_token</code>を繰り返し適用し、入力文字列をトークンのベクターに変換します。<code>IResult</code>型を返します。 # <code>parse_token</code> 関数: <code>delimited</code>コンビネータを使用してトークンの前後のスペースを処理し、与えられた文字列を様々なルールにマッチングさせます。数字、演算子それぞれのパースを行い、<code>Token</code>列挙型のトークンを返します。 # <code>infix_to_rpn</code> 関数: 前のコードと同じですが、与えられたトークンのベクターを逆ポーランド記法に変換する機能を持っています。 このコードは、<code>nom</code>を使ってトークン分割を行い、より柔軟なパースを可能にしています。<code>nom</code>を使用することで、トークンのパースやスペースの処理など、より複雑なルールを柔軟に記述できるようになります。 === 複素数式評価器 === {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} :<syntaxhighlight lang=rust copy> extern crate num_complex; use num_complex::Complex; #[derive(Debug, PartialEq, Clone)] enum Token { Number(Complex<f64>), Plus, Minus, Multiply, Divide, LParen, RParen, EOF, } struct Lexer<'a> { input: &'a str, position: usize, } impl<'a> Lexer<'a> { fn new(input: &'a str) -> Lexer<'a> { Lexer { input, position: 0 } } fn skip_whitespace(&mut self) { while self.position < self.input.len() && self.input.chars().nth(self.position).unwrap().is_whitespace() { self.position += 1; } } fn next_token(&mut self) -> Token { self.skip_whitespace(); if self.position >= self.input.len() { return Token::EOF; } let current_char = self.input.chars().nth(self.position).unwrap(); match current_char { '+' => { self.position += 1; Token::Plus } '-' => { self.position += 1; Token::Minus } '*' => { self.position += 1; Token::Multiply } '/' => { self.position += 1; Token::Divide } '(' => { self.position += 1; Token::LParen } ')' => { self.position += 1; Token::RParen } 'i' => { self.position += 1; Token::Number(Complex::new(0.0, 1.0)) } _ if current_char.is_digit(10) || current_char == '.' => { let start = self.position; while self.position < self.input.len() && (self.input.chars().nth(self.position).unwrap().is_digit(10) || self.input.chars().nth(self.position).unwrap() == '.') { self.position += 1; } let number_str = &self.input[start..self.position]; let number = number_str.parse::<f64>().unwrap(); if let Some('i') = self.input.chars().nth(self.position) { self.position += 1; Token::Number(Complex::new(0.0, number)) } else { Token::Number(Complex::new(number, 0.0)) } } _ => panic!("Invalid character found: {}", current_char), } } } struct Parser<'a> { lexer: Lexer<'a>, current_token: Token, } impl<'a> Parser<'a> { fn new(mut lexer: Lexer<'a>) -> Parser<'a> { let current_token = lexer.next_token(); Parser { lexer, current_token } } fn eat(&mut self, token: Token) { if self.current_token == token { self.current_token = self.lexer.next_token(); } else { panic!("Invalid syntax"); } } fn factor(&mut self) -> Complex<f64> { let token = self.current_token.clone(); match token { Token::Number(num) => { self.eat(Token::Number(num)); num } Token::LParen => { self.eat(Token::LParen); let result = self.expr(); self.eat(Token::RParen); result } _ => panic!("Invalid syntax"), } } fn term(&mut self) -> Complex<f64> { let mut result = self.factor(); while vec![Token::Multiply, Token::Divide].contains(&self.current_token) { let token = self.current_token.clone(); match token { Token::Multiply => { self.eat(Token::Multiply); let next_factor = self.factor(); result = result * next_factor; } Token::Divide => { self.eat(Token::Divide); let next_factor = self.factor(); result = result / next_factor; } _ => panic!("Invalid syntax"), } } result } fn expr(&mut self) -> Complex<f64> { let mut result = self.term(); while vec![Token::Plus, Token::Minus].contains(&self.current_token) { let token = self.current_token.clone(); match token { Token::Plus => { self.eat(Token::Plus); let next_term = self.term(); result = result + next_term; } Token::Minus => { self.eat(Token::Minus); let next_term = self.term(); result = result - next_term; } _ => panic!("Invalid syntax"), } } result } } fn main() { let lexer = Lexer::new("(2+ 3i)*4i"); let mut parser = Parser::new(lexer); let result = parser.expr(); println!("{:?}", result); } </syntaxhighlight> このコードは、数式をパースして複素数を計算する簡単な計算機の基本的な実装です。Rustの機能を活用して、トークン列を生成するLexerと、そのトークン列を解析して計算を行うParserを定義しています。 <code>Token</code>は、パーサーが認識するトークンの種類を表すenumです。<code>Lexer</code>は文字列を受け取り、その文字列をトークンに分割する役割を果たします。各トークンは、演算子や数値、括弧などを表現しています。<code>Parser</code>は、Lexerが生成したトークン列を受け取り、それを解析して数式を計算します。 <code>Lexer</code>は空白をスキップし、文字列を一文字ずつ見ていき、トークン列を生成します。<code>Parser</code>はトークン列を再帰的に解析し、四則演算を行って複素数を計算します。演算子の優先順位や括弧の処理も考慮されています。 このコードは、入力文字列 <code>(2+ 3i)*4i</code> を受け取り、それを計算して結果を表示します。各段階でトークンが正しく識別され、演算子や数値が正しく解釈されることを期待しています。 コード内のパニックは、予期しないトークンや構文エラーがあった場合に発生します。これらのエラーは、コードが期待する形式に文字列が合致しなかった場合に発生します。 このコードを用いると、複雑な数式も計算できますが、入力の検証やエラー処理についてはまだ改善の余地があります。 === 複素数 === :<syntaxhighlight lang=rust copy> extern crate num_complex; use num_complex::Complex; fn main() { // 複素数の作成 let a = Complex::new(3.0, 4.0); let b = Complex::new(-2.0, 5.0); println!("a: {a}"); println!("b: {b}"); println!("a + b: {}", a + b); println!("a - b: {}", a - b); println!("a * b: {}", a * b); println!("a / b: {}", a / b); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> a: 3+4i b: -2+5i a + b: 1+9i a - b: 5-1i a * b: -26+7i a / b: 0.4827586206896552-0.7931034482758621i </syntaxhighlight> このコードは、<code>num-complex</code>クレートを使用して複素数を扱うRustの例です。 # <code>extern crate num_complex;</code> および <code>use num_complex::Complex;</code> は、<code>num-complex</code>クレートから<code>Complex</code>型を使えるようにするためのインポートです。 # <code>Complex::new(3.0, 4.0);</code> および <code>Complex::new(-2.0, 5.0);</code> は、実部と虚部を指定して複素数を作成しています。 # <code>println!("a: {a}");</code> および <code>println!("b: {b}");</code> は、複素数 <code>a</code> と <code>b</code> を出力しています。 b: {}", a * b);</code>、<code>println!("a / b: {}", a / b);</code> は、それぞれ複素数 <code>a</code> と <code>b</code> の加算、減算、乗算、除算を行っています。結果を文字列として出力しています。 修正されたコードは次のようになります: == 改廃された技術 == Rustの改廃された技術や利用が推奨されない技術は、言語標準の進化、安全性の向上、エコシステムの成熟などによって置き換えられます。以下に、代表的な技術を示します。 === try! マクロ === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2018年(非推奨化) ; 廃止または衰退の理由 : より簡潔で表現力のある<code>?</code>演算子が導入され、エラーハンドリングがより簡単になりました。 ; 代替技術 : <code>?</code>演算子の使用が推奨されます。 === std::sync::Arc::get_mut_unchecked === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2018年(非推奨化) ; 利用推奨されない理由 : 安全性の問題があり、データ競合を引き起こす可能性があります。 ; 代替技術 : <code>get_mut()</code>または<code>make_mut()</code>の使用が推奨されます。 === std::env::home_dir === * '''対象:''' ホームディレクトリのパス取得 * '''サポート終了年:''' 2019年(非推奨化) ; 廃止または衰退の理由 : プラットフォーム間での一貫性の問題と、エッジケースでの不正確な結果。 ; 代替技術 : <code>dirs</code>クレートや<code>home</code>クレートの使用が推奨されます。 === catch_unwind_safe === * '''サポート開始年:''' 2016年 * '''サポート終了年:''' 2018年(非推奨化) ; 廃止または衰退の理由 : 安全性の保証に関する問題と、より良い代替手段の存在。 ; 代替技術 : <code>std::panic::catch_unwind</code>と適切なパニック安全性の設計が推奨されます。 === std::error::Error::description === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2019年(非推奨化) ; 廃止または衰退の理由 : エラーメッセージの国際化や詳細な文脈提供が困難でした。 ; 代替技術 : Display実装とError::sourceメソッドの使用が推奨されます。 === 古いRaw Pointersの特定の使用法 === * '''対象:''' 特定の生ポインタ操作 * '''サポート終了年:''' 継続的に改善 ; 廃止または衰退の理由 : メモリ安全性とプログラムの正確性に関する問題。 ; 代替技術 : 参照、Box、Rc、Arcなどの安全な所有権型の使用が推奨されます。 === std::thread::scoped === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2015年(早期に削除) ; 廃止または衰退の理由 : メモリ安全性の問題が発見され、より安全な代替手段が必要とされました。 ; 代替技術 : <code>crossbeam::scope</code>や<code>rayon</code>のスコープ付き並列処理が推奨されます。 === 古いマクロ定義構文 === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' なし(ただし新構文推奨) ; 廃止または衰退の理由 : 可読性とデバッグの困難さ、より表現力のある新しい構文の登場。 ; 代替技術 : <code>macro_rules!</code>の新しい構文やproc-macroの使用が推奨されます。 === std::ascii::AsciiExt === * '''サポート開始年:''' 2015年 * '''サポート終了年:''' 2019年(非推奨化) ; 廃止または衰退の理由 : トレイトの設計が最適でなく、より良い代替手段が標準ライブラリに追加されました。 ; 代替技術 : str、charの組み込みメソッドの使用が推奨されます。 === 古いFuture実装 === * '''対象:''' futures 0.1系 * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : async/await構文の導入により、より簡潔で理解しやすい非同期プログラミングが可能になりました。 ; 代替技術 : futures 0.3系とasync/await構文の使用が推奨されます。 == ほかの言語からの移植例 == === 順列・組合わせ === Goから[[Go/関数#順列・組合わせ|順列・組合わせ]]を移植 ==== 順列 ==== ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=73612aa97bd4a1541a0313f38effde87 順列]:<syntaxhighlight lang=rust line copy> fn permutation<T: Clone>(s: &[T], n: usize) -> Vec<Vec<T>> { if s.is_empty() { panic!("slice is nil"); } if n == 1 { let mut result = Vec::new(); for v in s.iter() { result.push(vec![v.clone()]); } return result; } let mut result = Vec::new(); for (i, v) in s.iter().enumerate() { let mut sf = Vec::new(); for (j, w) in s.iter().enumerate() { if j != i { sf.push(w.clone()); } } for w in permutation(&sf, n - 1) { let mut v_w = vec![v.clone()]; v_w.extend_from_slice(&w); result.push(v_w); } } result } fn main() { println!("{:?}", permutation(&[1, 2, 3], 1)); println!("{:?}", permutation(&[0, 1, 2], 2)); println!( "{:?}", permutation(&["abc".to_string(), "def".to_string(), "xyz".to_string()], 3) ); println!("{:?}", permutation::<i32>(&[], 2)); } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> [[1], [2], [3]] [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]] [["abc", "def", "xyz"], ["abc", "xyz", "def"], ["def", "abc", "xyz"], ["def", "xyz", "abc"], ["xyz", "abc", "def"], ["xyz", "def", "abc"]] </syntaxhighlight> ;解説 :上記の移植において、主に以下の点に注意が必要でした。 :* ジェネリック型の宣言方法がGoとは異なるため、<code>func Permutation[T any](s []T, n int)</code> のような書き方はできません。Rustでは、<code>fn permutation<T: Clone>(s: &[T], n: usize)</code> のように、<code><T></code>の前に<code>:</code>を付けてジェネリック境界を宣言します。 :* Goの<code>make</code>は、新しい配列やスライスを作成するための組み込み関数ですが、Rustでは<code>Vec::with_capacity()</code>や<code>Vec::new()</code>を使用します。 :* <code>panic!("slice is nil")</code>は、Rustのパニック処理において、エラーメッセージを伴うパニックを発生させるために使用されます。 :* <code>Vec</code>に要素を追加するには、Goの<code>append</code>に相当するRustのメソッドである<code>Vec::push()</code>や、<code>Vec::extend_from_slice()</code>を使用します。また、<code>Vec</code>の要素数は、<code>len()</code>ではなく<code>len()</code>と<code>Vec::capacity()</code>の両方を使って取得する必要があります。 ==== 組合わせ ==== ;[https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=06e15597fcf3bdc585abeccd3edb9454 組合わせ]:<syntaxhighlight lang=rust line copy> fn combination<T: Clone>(s: &[T], n: usize) -> Vec<Vec<T>> { if s.is_empty() { panic!("slice is empty"); } if n == 1 { let mut result = Vec::new(); for v in s { result.push(vec![v.clone()]); } return result; } let mut result = Vec::new(); for i in 0..=(s.len() - n) { let v = s[i].clone(); for w in combination(&s[i + 1..], n - 1) { let mut res = vec![v.clone()]; res.extend(w); result.push(res); } } return result; } fn main() { println!("{:?}", combination(&[1, 2, 3], 1)); println!("{:?}", combination(&[0, 1, 2], 2)); println!( "{:?}", combination(&["abc", "def", "xyz"], 3) ); // println!("{:?}", combination(&[], 2)); 要素型が確定できない } </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> [[1], [2], [3]] [[0, 1], [0, 2], [1, 2]] [["abc", "def", "xyz"]] </syntaxhighlight> ;解説 :上記の移植において、主に以下の点に注意が必要でした。 :*Rustのジェネリック関数の型パラメータには制約が必要なため、<code>T</code>がクローン可能であることを示す<code>Clone</code>トレイトを指定する必要があります。 :*Goのスライスと異なり、Rustのスライスは要素数が0の場合にも安全であるため、<code>ErrNilSlice</code>に相当する処理は<code>slice.is_empty()</code>で判定することができます。 :*Goのスライスと異なり、Rustのスライスは範囲外アクセスがパニックを引き起こすため、再帰呼び出し時にはスライスの範囲を明示的に指定する必要があります。 {{See also|JavaScript/オブジェクト#順列を求めるメソッドを配列に追加する|JavaScript/オブジェクト#組合わせを求めるメソッドを配列に追加する}} == 脚註 == <references /> == 外部リンク == {{Wikipedia|Rust (プログラミング言語)|Rust}} * [https://www.rust-lang.org/ 公式サイト(英語)] * [https://www.rust-lang.org/ja/ 公式サイト(日本語)] * [https://doc.rust-jp.rs/book-ja/title-page.html The Rust Programming Language 日本語版] * [https://doc.rust-lang.org/book/title-page.html The Rust Programming Language (英語版)] == 参考文献 == * {{Cite |author=Jim Blandy, Jason Orendorff |title=プログラミングRust |edition=第2版 |publisher=オライリージャパン |isbn=978-4873119786 |date=2022年1月19日 }} * {{Cite |author=Jim Blandy, Jason Orendorff |title=プログラミングRust |edition=第1版 |publisher=オライリージャパン |isbn=978-4873118550 |date=2018年8月10日 }} [[Category:Rust|*]] [[カテゴリ:プログラミング言語]] {{NDC|007.64}} hcy0p1itp9ii0jk16eobtov187e76k3 Wikibooks:サンドボックス 4 33504 263747 263239 2024-11-18T06:31:25Z ~2024-14353 84969 Temporary account のテスト 263747 wikitext text/x-wiki <!-- このコメントと説明文は消さないでください --> {{/説明文}} <!-- ここから下で、投稿の練習や実験を行ってください --> Temporary account のテスト [https://ja.wikibooks.org/wiki/%E7%89%B9%E5%88%A5:%E3%83%AD%E3%82%B0?type=newusers&user=&page=&wpdate=&tagfilter=&wpfilters%5B%5D=newusers&wpFormIdentifier=logeventslist アカウント作成記録], [https://www.mediawiki.org/wiki/Help:Temporary_accounts ヘルプ], [https://diff.wikimedia.org/2024/11/05/say-hi-to-temporary-accounts-easier-collaboration-with-logged-out-editors-with-better-privacy-protection/ Diff] --[[特別:投稿記録/&#126;2024-14353|&#126;2024-14353]] ([[利用者・トーク:&#126;2024-14353|会話]]) 2024年11月18日 (月) 06:31 (UTC) hcqa9cnajizeymouv14vehizefn2c9o 利用者:Kwawe 2 34770 263788 263425 2024-11-18T11:38:51Z Kwawe 68789 263788 wikitext text/x-wiki ※2022年6月にwikibooksに登録しております。 == Wikibooksの記述では == # 中学生高校生向けの新規執筆・改定執筆のWikibooksは敬体で記述しています。新課程の自然科学ほぼ全般(物理・生物・地学・理数探究基礎)、社会科学(公民)、人文科学全般、保健体育・家庭科を記述しています。 # 本文記述は、冗長表現をなくしています。詳しくは、国語表現の「[[高等学校国語表現/わかりやすい文を書く|わかりやすい文を書く]]」を参照してください。 # 大人向け法律学(刑法など)のWikibooksは、常体で記述しています。 # 大人向け経済原論(ミクロ経済学など)のWikibooksは、敬体で記述しています。 == 教科書 == Wikibooksの教科書目録の作成などを新課程版に更新しています。 当方、高等学校の旧課程教科書は数学・自然科学(物理・化学・生物・地学)・商業の一部・福祉の一部・公民・国語表現・人文科学(地理・歴史)の教科書を持参しています。 2023年からの新課程用は公共、歴史総合・日本史探究・世界史探究、家庭総合、理数探究基礎、生物全5冊、政治経済、数学[第一、数研の最新シリーズ]の教科書を持参しています。 ※基本、私の執筆するページは資料出所と出典を必ず掲載します。たとえそれが文部科学省の教科書だとしてもです。 == wikibooks執筆担当科目 ==  主に、高校生の教科書を中心に執筆していますが、中学生の実技教科、一般向けの経済原論も執筆しています。  執筆に時間がかかる科目「物理」「生物」「地歴の探究科目」「公共」は、更新頻度が減ります。 * [[高等学校理科 物理基礎|高等学校 物理基礎]]     [全般] * [[高等学校 物理|高等学校物理]]        [全般] * [[高等学校 生物基礎]]     [全般] * [[高等学校 生物]]       [全般] * [[高等学校 地学基礎]]     [全般] * [[高等学校 地学]]       [全般] * [[高等学校 理数探究基礎]]   [全般](3月中旬以降から執筆) * [[高等学校国語表現]]      [全般] * [[高等学校地理探究]]      [全般] * [[高等学校公共]]        [全般] * [[高等学校倫理]]        [全般] * [[ミクロ経済学]]        [全般] * [[高等学校世界史探究]]     [全般] * [[高等学校歴史総合]]      [全般](ほぼ内容完成) * [[高等学校家庭総合]]      [全般] * [[中学校音楽]]         [全般] * [[中学校家庭]]         [全般](衣生活と食生活は完成時期不明。) * [[中学校保健体育]]       [全般] * [[高等学校保健体育]]      [座学編・実技編両方全般] * [[高等学校日本史探究]]     [全般](2023年7月下旬以降執筆予定) 今後、順次執筆科目は増加予定です。 また、時期は未定ですが、看護とかも執筆していきたいと思います。(2023年2月04日追記) == 高校生に向けてメッセージ ==  私達は日本人ですから、日本語の文章でまず意味を理解しないと文字式や数式・公式も当然理解出来ません。そして、日本語の語彙を覚えないと当然国語の読解問題の記述問題も解けません。以上、私、当時元文系の高校生から見た視点です(大学卒業後、現在社会人)。あくまで、文字式や数式はイメージ的には図形と似たような感じで、これらをイラスト化にしているに過ぎません。 == 現在執筆中の内容 == ★日本史探究 * [[高等学校日本史探究/古代国家の形成Ⅱ|古代国家の形成Ⅱ]](新規執筆) * [[高等学校日本史探究/古代国家の形成Ⅲ|古代国家の形成Ⅲ]](新規執筆) * [[高等学校日本史探究/律令制度|律令制度]](新規執筆) == 過去執筆の事後処理予定[見直し、本文大幅修正] == ★歴史総合 ★生物 ★地学 ★保健体育 ★家庭科 == 今年執筆予定の内容 == ※予定よりかなり遅れており、変更の可能性もあります。 == リンク集 == * https://jawikibooks.wikiscan.org/users 55vf2u7cuxiozx9t19d3xlrcct1gkpy Julia 0 37378 263781 263496 2024-11-18T10:54:22Z Ef3 694 /*改廃された技術*/ Juliaの改廃された技術や利用が推奨されない技術は、言語の進化、パフォーマンスの向上、シンプルさの追求、新しいプログラミングパラダイムへの対応により置き換えられます。以下に、代表的な技術を示します。 263781 wikitext text/x-wiki {{Wikipedia|Julia (プログラミング言語)}} Juliaは高性能なプログラミング言語であり、主に科学計算やデータ解析に特化しています。その特徴は高速な実行速度と柔軟性にあります。このチュートリアルでは、Juliaの基本的な機能や文法、データ処理、関数の定義方法、そしてパッケージの使用方法などを解説します。 Juliaは初心者にも優しい言語であり、PythonやMATLABなど他の言語を使った経験がある人にとっても理解しやすいでしょう。このチュートリアルを通じて、Juliaのパワーと柔軟性に触れながら、効率的なコーディングを実現するための基礎を身につけることができます。Juliaはオープンソースであり、活発なコミュニティが存在するため、学習を進める上でのサポートも豊富です。 ==イントロダクション== ===Julia言語の概要=== Juliaは、高性能なプログラミング言語であり、特に科学計算やデータ解析の分野で広く利用されています。2012年に開発され、その後急速に普及し、多くの研究者、データサイエンティスト、エンジニアによって支持されています。Juliaの設計目標は、高いパフォーマンスと柔軟性を両立させることであり、その結果、数値計算や並列処理などの高度なタスクに対して優れた性能を発揮します。 ===Juliaの設計哲学=== Juliaの設計にはいくつかの重要な哲学が取り入れられています。その中でも特筆すべきは、可読性と拡張性に対する強いコミットメントです。Juliaのコードは、高レベルの抽象化と同時に、低レベルの詳細まで明示的に制御できるため、初心者からエキスパートまで幅広いユーザーに適しています。また、Juliaは動的言語でありながら、静的言語のような型推論機能を持ち、コードの効率性を保ちつつ開発速度を向上させることができます。 ===Juliaを使う上での利点=== Juliaを選択するメリットは多岐にわたります。まず、高速な実行速度が挙げられます。Juliaは、CやFortranに匹敵する性能を持ちながら、動的なスクリプト言語のような使いやすさも兼ね備えています。また、豊富なライブラリやパッケージエコシステムがあり、様々な用途に対応できます。さらに、PythonやMATLABとの親和性も高く、既存のコードやツールを再利用しながら移行することができます。 Juliaは、その優れた性能と柔軟性によって、科学技術計算の分野でますます重要な位置を占めています。このチュートリアルでは、Juliaの基本的な機能から応用まで幅広くカバーし、Juliaを使いこなすための知識を提供します。 == 初級編 == 初級編では、まず最初にJuliaのインストール方法を扱います。インストールは簡単で、公式のインストールスクリプトを使用することで数分で完了します。このステップをクリアすると、Juliaの環境が整い、プログラミング学習の準備が整います。Juliaのインストール後は、変数、データ型、制御構造など、プログラミングの基礎的な概念を学ぶことができます。Juliaのシンプルな構文と豊富な機能を活かして、プログラミングの世界に足を踏み入れましょう。 === Juliaのインストール === Juliaは、macOS、Windows、FreeBSD、Linuxのディストリビューションなどの主要なオペレーティングシステムで利用可能です。Juliaをインストールする手順は非常に簡単で、公式のインストールスクリプトを使用することで、数分でJuliaをセットアップできます。 ==== Unixタイプのシステムへのインストール ==== # インストールスクリプトの実行 #: 以下のコマンドをターミナルに入力して、Juliaの最新バージョンをインストールします。 #:<syntaxhighlight lang=shell> curl -fsSL https://install.julialang.org | sh </syntaxhighlight> #:このコマンドは、UnixタイプのシステムでJuliaをインストールするための推奨される方法です。 #: Windowsの場合は、別途手順があります。 # インストールの確認 #:インストールが完了すると、<code>julia</code> コマンドを使用してJuliaのREPL(Read-Eval-Print Loop)を起動できます。ターミナルで以下のコマンドを入力し、JuliaのREPLを開始します。 #:<syntaxhighlight lang=julia-repl> $ julia _ _ _ _(_)_ | Documentation: https://docs.julialang.org (_) | (_) (_) | _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.10.0 (2023-12-25) _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release |__/ | julia> 1+2*3 7 julia> typeof(3.14) Float64 julia> a=12/34 0.35294117647058826 julia> typeof(a) Float64 julia> exit() $ _ </syntaxhighlight> #:JuliaのREPLが起動すると、インストールが正常に完了したことを確認できます。 # バージョン管理とアップデート #: Juliaは、インストール後に自動的にアップデートされるJuliaupインストールマネージャーを含んでいます。<code>juliaup</code> コマンドを使用して、Juliaのバージョンを管理およびアップデートすることができます。 #:<syntaxhighlight lang=shell> juliaup --help </syntaxhighlight> #:このコマンドは、利用可能なオプションを表示します。 ==== Windows へのインストール ==== Juliaは、Windows環境でも簡単にインストールできます。以下の手順に従って、Juliaをセットアップしましょう。 # インストーラーのダウンロード #: まず、Juliaのダウンロードページ( https://julialang.org/downloads/ )にアクセスして、Windows用のインストーラーをダウンロードします。 # インストーラーの実行 #: ダウンロードが完了したら、ダウンロードしたインストーラーをダブルクリックして実行します。セットアップウィザードが表示されるので、指示に従ってインストールを進めます。 # インストールの確認 #: インストールが完了すると、スタートメニューやデスクトップにJuliaのショートカットが作成されます。Juliaを起動するには、ショートカットをクリックするか、スタートメニューからJuliaを検索して開きます。 #: Juliaが正常に起動し、REPL(Read-Eval-Print Loop)が表示されれば、インストールが成功しています。 # バージョン管理とアップデート #: Juliaは、インストールされたバージョンの管理とアップデートを簡単に行うことができます。Juliaupインストールマネージャーを使用して、バージョンの管理やアップデートを行うことができます。詳細は、Juliaupのドキュメントを参照してください。 ===プログラミングの基礎=== このセクションでは、プログラミングの基本的な概念を学びます。以下の内容に焦点を当てて、プログラミングの基盤を築いていきます。 ;変数: 代入によって値に付けられた名前です。再代入によって別の値を結びつけることができます。 ;データ型: 値の種類を表し、それぞれの操作方法が異なります。整数、浮動小数点数、文字列などがあります。 ;制御構造: プログラムの実行の流れを制御します。条件分岐(<code>if</code>文)、繰り返し(<code>for</code>ループ)などが含まれます。 ;関数: 一連の処理をまとめて名前を付け、再利用可能にします。 これらの概念は、Juliaだけでなく他のプログラミング言語でも共通しています。 ===Juliaの構文と基本操作=== Juliaの構文や基本的な操作方法を理解します。JuliaのREPL(Read-Eval-Print Loop)の使用方法も学びます。REPLはJuliaを対話的に使うための強力なツールであり、効率的な学習と開発に役立ちます。 #; コメント #: Juliaのコメントは単一行コメントと、複数行コメントがあります。 #:<syntaxhighlight lang=julia> # これは行コメントです。 #= これは 複数行の コメントです。 =# </syntaxhighlight> #; 変数とデータ型 #: 変数は型を持つことがありますが、明示的に型を指定する必要はありません。 #:; 型推論 #:: 変数に値が代入されるとき、その値から適切なデータ型を推論します。 #::<syntaxhighlight lang=julia> x = 10 # xの型は整数(Int64)と推論される y = 3.14 # yの型は浮動小数点数(Float64)と推論される z = "Hello" # zの型は文字列(String)と推論される </syntaxhighlight> #:; 型アノテーション #:: 型アノテーションを使用することで、変数の型を明示的に指定することもできます。 #::<syntaxhighlight lang=julia> x::Int64 = 10 # xは整数型(Int64)であることを明示的に指定 y::Float64 = 3.14 # yは浮動小数点数型(Float64)であることを明示的に指定 z::String = "Hello" # zは文字列型(String)であることを明示的に指定 </syntaxhighlight> #; 制御構造 #: <code>if</code>、<code>for</code>、<code>while</code>を使用してプログラムの流れを制御します。 #:<syntaxhighlight lang=julia> if x > 5 println("xは5より大きいです") else println("xは5以下です") end for i in 1:5 println("現在の値は$iです") end </syntaxhighlight> #; 関数の定義 #: <code>function</code>キーワードを使用して関数を定義します。 #:<syntaxhighlight lang=julia> function greet(name) println("こんにちは、$nameさん!") end greet("太郎") </syntaxhighlight> #; 配列とタプル #: 配列は要素の順序付き集合です。タプルは不変の配列であり、異なる型の要素を持つことができます。 #:<syntaxhighlight lang=julia> array = [1, 2, 3, 4, 5] # 配列の定義 tuple = (1, "hello", 3.14) # タプルの定義 </syntaxhighlight> #; REPLの使用 #: JuliaのREPL(Read-Eval-Print Loop)は対話的な開発に役立ちます。コードの断片を試して実行し、結果を即座に確認できます。 #:<syntaxhighlight lang=julia-repl> julia> x = 10 10 julia> x + 5 15 </syntaxhighlight> これらの構文要素はJuliaの基本的な機能であり、プログラミングの初心者から上級者まで幅広く活用されています。 ===変数=== 変数は、値につけられた名前で、プログラム内でデータを一時的に保存したり、処理の途中結果を保持したりするために使用されます。Juliaの変数は宣言することなく使い始めることができます。 ;代入と参照 :<syntaxhighlight lang=julia> x = 10 # 代入 println(x) # => 10 </syntaxhighlight> :このコードは、変数 <code>x</code> に整数値 <code>10</code> を代入し、その後 <code>println()</code> 関数を使用して <code>x</code> の値を参照し出力しています。出力結果は <code>10</code> になります。 ;再代入による値の更新 :<syntaxhighlight lang=julia> x = 10 # 最初の代入 println(x) # => 10 x = 20 # 新しい値を代入 println(x) # => 20 </syntaxhighlight> :このコードは、最初に変数 <code>x</code> に整数値 <code>10</code> を代入し、その後 <code>println()</code> 関数を使用して <code>x</code> の値を出力します。次に、変数 <code>x</code> に新しい値である整数値 <code>20</code> を再代入し、再び <code>println()</code> 関数を使用して <code>x</code> の値を出力します。 ;異なる型の値の再代入 :<syntaxhighlight lang=julia> x = 10 # 最初の代入 println(typeof(x)) # => Int64 println(x) # => 10 x = "Hello" # 新しい値を代入 println(typeof(x)) # => String println(x) # => Hello </syntaxhighlight> :このコードでは、最初に変数 <code>x</code> に整数値 <code>10</code> が代入されています。その後、<code>typeof()</code> 関数を使用して変数 <code>x</code> の型を出力し、<code>println()</code> 関数を使用して <code>x</code> の値を出力しています。その結果、<code>x</code> の型は <code>Int64</code> であり、値は <code>10</code> になります。 :次に、変数 <code>x</code> に文字列 <code>"Hello"</code> が再代入されています。再び、<code>typeof()</code> 関数を使用して <code>x</code> の型を出力し、<code>println()</code> 関数を使用して <code>x</code> の値を出力しています。その結果、<code>x</code> の型は <code>String</code> であり、値は <code>"Hello"</code> になります。 このように、同じ変数に異なる型の値を再代入することができます。 このことから、Juliaは動的型付けプログラミング言語と言えます。 ==== 定数 ==== Juliaにおいて、定数は変更不可能な値を表す変数です。定数は <code>const</code> キーワードを使って宣言されます。定数は、一度宣言されると、その後値を変更することはできません。定数は、関数内外で利用可能です。以下は、定数を宣言する例です。 :<syntaxhighlight lang=julia> const GRAVITY = 9.80665 </syntaxhighlight > この例では、<code>GRAVITY</code> という定数を宣言しています。この定数は、重力加速度を表す定数であり、値は <code>9.80665</code> であり、後から値を変更することはできません。 ==== 変数のスコープ ==== Juliaの変数のスコープは、他の多くのプログラミング言語と同様に、その変数がアクセス可能な範囲を指します。 Juliaでは、次のようなスコープがあります: # グローバルスコープ(Global Scope): #* グローバルスコープでは、プログラム全体から変数にアクセスできます。 #* グローバルスコープで定義された変数は、どこからでもアクセス可能です。 # ローカルスコープ(Local Scope): #* ローカルスコープでは、変数が関数やブロック内で定義され、その中でのみアクセス可能です。 #* 関数内で定義された変数は、その関数内でのみ利用できます。 # モジュールスコープ(Module Scope): #* モジュールスコープでは、モジュール内で定義された変数がアクセス可能です。 #* モジュール内で定義された変数は、そのモジュール内の関数やブロックからアクセスできますが、モジュールの外部からはドット表記を使用してアクセスする必要があります。 スコープ内での変数の振る舞いは、他のプログラミング言語と同様ですが、Juliaの場合、特に関数内での変数の振る舞いに関しては、ローカルスコープの規則が適用されます。たとえば、関数内で同じ名前の変数をグローバルスコープと同じ名前で定義すると、それは関数内でのみ有効なローカル変数となります。これは、Juliaの変数がデフォルトでローカルスコープを持つためです。 Juliaでは、関数内でグローバル変数を変更する場合、<code>global</code>キーワードを使用する必要があります。これにより、関数内でグローバル変数の値を更新することができます。例えば: :<syntaxhighlight lang=julia> x = 10 # グローバルスコープ function update_global() global x = 20 # グローバル変数 x の値を更新 end update_global() # 関数を呼び出す println(x) # 20 と出力される </syntaxhighlight > このように、Juliaではスコープのルールに従って変数が振る舞いますが、グローバル変数の更新など特定のケースでは明示的なキーワードが必要になることがあります。 ==== ユースケース ==== 変数はプログラミングにおいて非常に重要な概念であり、さまざまなユースケースがあります。 以下は、変数の主なユースケースのいくつかです: ;値の保持: 変数は値を一時的に格納するための仮想的なコンテナとして機能します。これにより、同じ値を何度も使用する場合や、値を後で変更する必要がある場合に便利です。 ;計算の中間結果: 複雑な計算を行う際には、計算の途中結果を変数に格納しておくことが便利です。これにより、コードの可読性が向上し、計算を追跡しやすくなります。 ;プログラムの状態管理: プログラムの実行中に変数を使用することで、プログラムの状態を管理することができます。例えば、ゲームのスコアやユーザーのログイン状態などを変数に格納しておくことができます。 ;反復処理の制御: ループ内で変数を使用して、反復処理の制御を行うことができます。変数を使用して反復回数をカウントしたり、リストや配列の要素にアクセスしたりすることができます。 ;関数の引数や戻り値: 関数の引数や戻り値として変数を使用することができます。関数は入力を受け取り、それに基づいて処理を行い、結果を変数として返すことができます。 これらのユースケースは、プログラムを効率的に記述し、管理するための基本的なツールとして変数がどれだけ重要であるかを示しています。 === 基礎的なデータ型と変数 === プログラミング言語では、データを扱う際に異なる種類のデータ型が使用されます。これらのデータ型には、整数、浮動小数点数、文字列、配列などがあります。Juliaは、これらのデータ型を使用してデータを格納し、処理します。 ==== 整数 (Integer) ==== 整数は、数値を表すための基本的なデータ型です。正の整数、負の整数、ゼロを表すことができます。Juliaでは、整数のサイズに応じて複数の型が提供されています。例えば、<code>Int8</code>、<code>Int16</code>、<code>Int32</code>、<code>Int64</code>などの符号付き整数型があります。 ==== 浮動小数点数 (Float) ==== 浮動小数点数は、小数点以下の数値を表すためのデータ型です。整数とは異なり、小数点以下の桁数を含めることができます。Juliaでは、<code>Float32</code>、<code>Float64</code>などの浮動小数点数型が提供されています。 ==== 文字列 (String) ==== 文字列は、テキストデータを表すためのデータ型です。Juliaでは、ダブルクォーテーション (<code>"</code>) で囲まれた文字列が使用されます。例えば、<code>"Hello"</code>や<code>"Julia"</code>などの文字列を表現することができます。 ==== 配列 (Array) ==== 配列は、複数の要素を順序付けて格納するデータ構造です。Juliaでは、角かっこ <code>[ ]</code> 内にカンマで区切られた要素を並べて表現します。例えば、<code>[1, 2, 3]</code>や<code>["a", "b", "c"]</code>などの配列を表現することができます。 これらの基礎的なデータ型と変数に関するコード例を示します。 :<syntaxhighlight lang=julia> # 整数型の変数 x = 10 println(typeof(x)) # => Int64 println(x) # => 10 # 浮動小数点数型の変数 y = 3.14 println(typeof(y)) # => Float64 println(y) # => 3.14 # 文字列型の変数 name = "Julia" println(typeof(name)) # => String println(name) # => Julia # 配列型の変数 numbers = [1, 2, 3, 4, 5] println(typeof(numbers)) # => Array{Int64,1} println(numbers) # => [1, 2, 3, 4, 5] </syntaxhighlight> このコードでは、整数型の変数 <code>x</code>、浮動小数点数型の変数 <code>y</code>、文字列型の変数 <code>name</code>、配列型の変数 <code>numbers</code> を定義しています。それぞれの変数の型や値を <code>typeof()</code> 関数や <code>println()</code> 関数を使用して出力しています。 ここの紹介したデータ型は、ごく一部ですが最も頻繁に使用するものです。 ===型アノテーション=== 型アノテーション(Type Annotation)とは、プログラミング言語において変数や関数などの要素に対して、明示的に型を指定することを指します。一般的に、動的型付けを採用する言語では、変数の型は実行時に値に基づいて推論されますが、静的型付けを採用する言語では、変数の型はコードの記述時点で明示的に指定する必要があります。 Juliaでは、動的型付けを採用していますが、型アノテーションを使用して明示的に型を指定することができます。これにより、コードの読みやすさやパフォーマンスの最適化が可能になります。型アノテーションは、関数の引数や戻り値、変数の宣言、配列や辞書の要素型などに適用されることがあります。Juliaでは、型アノテーションは <code>::</code> を用いて表現されます。 以下は、型アノテーションの例です。 :<syntaxhighlight lang=julia> # 整数型の変数 x x::Int = 10 # 浮動小数点数型の変数 y y::Float64 = 3.14 # 文字列型の変数 greeting greeting::String = "Hello, Julia!" # インデックス型の配列 indices indices::Array{Int, 1} = [1, 2, 3, 4, 5] # 2次元の浮動小数点数型の配列 matrix matrix::Array{Float64, 2} = [1.0 2.0 3.0; 4.0 5.0 6.0; 7.0 8.0 9.0] </syntaxhighlight> このコード例では、整数型 (<code>Int</code>)、浮動小数点数型 (<code>Float64</code>)、文字列型 (<code>String</code>) の変数と、それぞれの型を要素型とする配列が定義されています。これらの要素に対して型アノテーションが行われています。 ===型推論=== 型推論(type inference)は、プログラミング言語が変数や式の型をコードから推測し、静的に決定するプロセスです。Juliaでは、コンパイラが変数や関数の型を推論し、コンパイル時に型の整合性を確認します。 例えば、次のコードを見てみましょう。 :<syntaxhighlight lang=julia> x = 5 y = "hello" z = x + 3.5 </syntaxhighlight> この場合、Juliaは次のように型を推論します。 * <code>x</code> は整数型 (<code>Int</code>) と推論されます。 * <code>y</code> は文字列型 (<code>String</code>) と推論されます。 * <code>z</code> は浮動小数点数型 (<code>Float64</code>) と推論されます。 Juliaの型推論は非常に柔軟であり、静的型付け言語の利点と動的型付け言語の柔軟性を組み合わせています。これにより、コードが安全で高速に実行される一方で、冗長な型の明示が必要な場面を減らすことができます。 Juliaが採用している型推論のアルゴリズムは、静的型付けと動的型付けの特性を組み合わせたものです。Juliaの型推論は、静的解析を行いながらも、動的に型の推論を行うことができます。 具体的には、Juliaの型推論は以下の手順に基づいています。 ;変数の初期化: 変数が宣言され、初期化される際に、その値から型が推論されます。 ;関数の呼び出し: 関数が呼び出される際に、引数の型から関数の型を推論します。 ;演算子の適用: 演算子が適用される際に、そのオペランドの型から演算結果の型を推論します。 ;条件分岐: 条件分岐のブロック内での変数の型は、条件文による制約から推論されます。 ;ジェネリック関数の呼び出し: ジェネリック関数の型は、呼び出し時の引数の型に基づいて推論されます。 これらの手順により、Juliaは変数や関数の型を静的に推論し、コンパイル時に型の整合性を確認します。しかし、必要に応じて動的に型を追跡することもあります。この柔軟性により、Juliaは高速なコードの生成と柔軟なプログラミングを両立しています。 === 式と演算子 === Juliaにおいて、プログラムは基本的に式と演算子の組み合わせで構成されます。式は値を生成し、演算子はそれらの値に対して特定の操作を行います。ここでは、Juliaで使われる主要な演算子と式について説明します。 ==== 式 (Expressions) ==== 式はプログラム内で値を生成するコードの断片です。式は変数、リテラル、関数呼び出し、演算子の組み合わせなどで構成されます。Juliaの式は他の式や演算子と組み合わせることでより複雑な式を作ることができます。 ==== リテラル (Literals) ==== リテラルはプログラム内で固定された値を表現する方法です。例えば、整数や浮動小数点数、文字列、真偽値などがあります。以下は、いくつかのリテラルの例です: * 整数リテラル: <code>42</code>, <code>-10</code>, <code>0x1F</code> (16進数) * 浮動小数点数リテラル: <code>3.14</code>, <code>-0.01</code>, <code>2.5e-3</code> (指数表記) * 文字列リテラル: <code>"Hello, World!"</code>, <code>"Julia"</code> * 真偽値リテラル: <code>true</code>, <code>false</code> ==== 演算子 (Operators) ==== 演算子は式内で値に対する特定の操作を行います。Juliaにはさまざまな種類の演算子がありますが、以下は一般的な演算子の例です: * 算術演算子: <code>+</code> (加算), <code>-</code> (減算), <code>*</code> (乗算), <code>/</code> (除算), <code>÷</code> (整数除算), <code>%</code> (剰余) * 比較演算子: <code>==</code> (等しい), <code>!=</code> (等しくない), <code><</code> (未満), <code>></code> (超過), <code><=</code> (以下), <code>>=</code> (以上) * 論理演算子: <code>&&</code> (論理積), <code>||</code> (論理和), <code>!</code> (論理否定) * 代入演算子: <code>=</code> (代入), <code>+=</code>, <code>-=</code>, <code>*=</code>, <code>/=</code>, <code>^=</code>, など :<syntaxhighlight lang=julia> # 算術演算子 result_add = 10 + 5 result_subtract = 20 - 8 result_multiply = 6 * 4 result_divide = 100 / 10 # 整数除算演算子 result_integer_divide = 100 ÷ 10 result_integer_remainder = 17 % 5 # 比較演算子 equality_check = (result_add == result_subtract) inequality_check = (result_multiply != result_divide) less_than_check = (result_remainder < result_add) greater_than_check = (result_divide > result_subtract) less_than_or_equal_check = (result_multiply <= result_divide) greater_than_or_equal_check = (result_add >= result_subtract) # 論理演算子 logical_and = (result_add < 20) && (result_subtract > 0) logical_or = (result_multiply == 24) || (result_divide != 0) logical_not = !(result_remainder <= 4) # 代入演算子 x = 10 x += 5 # x = x + 5 y = 20 y -= 8 # y = y - 8 z = 6 z *= 4 # z = z * 4 w = 100 w /= 10 # w = w / 10 v = 5 v ^= 3 # v = v ^ 3 </syntaxhighlight> これらの演算子は式内で使用され、値や式に対して特定の操作を実行します。 ==== 優先順位と結合性 ==== 演算子には優先順位と結合性があります。優先順位は演算子が式内でどのような順序で評価されるかを示し、結合性は同じ優先順位の演算子がどのようにグループ化されるかを示します。Juliaには演算子の優先順位と結合性を定義する規則があります。 :{| class="wikitable" |+ 演算子の優先順位と結合方向 !演算子!!優先度!!結合方向 |- | () || 最も高い || 左から右へ |- | . [] || || 左から右へ |- | + - ~ ! || || 右から左へ |- | * / % ÷ \ || || 左から右へ |- | + - || || 左から右へ |- | < <= > >= || || 左から右へ |- | == != || || 左から右へ |- | & || || 左から右へ |- | <nowiki>|</nowiki> || || 左から右へ |- | && || || 左から右へ |- | <nowiki>||</nowiki> || || 左から右へ |- | ? : || || 右から左へ |- | = || 最も低い || 右から左へ |} Juliaの式と演算子を理解することは、プログラムを作成し理解する上で重要なスキルです。 これらの概念をマスターすることで、より効率的で正確なコードを書くことができます。 ;さまざまな演算子:<syntaxhighlight lang=julia> # 整数除算 7 ÷ 3 # => 2 # 剰余 7 % 3 # => 1 # 逆乗算 7 \ 3 # => 0.42857142857142855 == 3 / 7 # べき乗 2^3 # => 8 # 比較演算子 2 == 2 # => true 2 != 3 # => true 2 > 1 # => true 2 >= 2 # => true 1 < 2 # => true 2 <= 2 # => true # 論理演算子 true && false # => false true || false # => true !true # => false # ビット演算子 2 & 3 # => 2 2 | 3 # => 3 ~2 # => -3 2 >> 1 # => 1 2 << 1 # => 4 # 三項演算子 true ? "Yes" : "No" # => "Yes" </syntaxhighlight> ==== . 演算子(ベクトル化演算子) ==== Juliaの<code>.</code>演算子は、要素ごとの演算を行うためのベクトル化演算子です。これは、Julia言語において非常に重要な機能であり、ベクトルや行列などの要素ごとの演算を簡潔に行うことができます。 <code>.</code>演算子は、通常の演算子(加算、減算、乗算、除算など)の前に置くことで、ベクトルや行列の各要素にその演算を適用することができます。これにより、要素ごとの演算が非常に簡潔に記述でき、高速な処理が可能となります。 以下に、<code>.</code>演算子の使用例を示します。 :<syntaxhighlight lang=julia> # ベクトルの定義 a = [1, 2, 3] b = [4, 5, 6] # 要素ごとの加算 result_add = a .+ b println(result_add) # 出力: [5, 7, 9] # 要素ごとの乗算 result_mul = a .* b println(result_mul) # 出力: [4, 10, 18] </syntaxhighlight> このように、<code>.</code>演算子を使用することで、ベクトルの要素ごとの演算をシンプルに実行できます。 Juliaの<code>.</code>演算子は、数値演算だけでなく、関数の適用や論理演算など、さまざまな操作に対しても使用することができます。以下に、<code>.</code>演算子を使った異なる操作のコード例を示します。 ; 関数の適用: :<syntaxhighlight lang=julia> # 関数を定義 f(x) = x^2 # ベクトルの要素ごとに関数を適用 a = [1, 2, 3] result_func = f.(a) println(result_func) # 出力: [1, 4, 9] </syntaxhighlight> これらの例では、<code>.</code>演算子を使用して、関数や演算子をベクトルの各要素に適用しています。これにより、要素ごとの操作を簡潔に記述でき、柔軟性が高まります。Juliaの<code>.</code>演算子は、さまざまなデータ型や演算に対して利用でき、プログラミングの効率を向上させます。 ===== アダマール積 ===== アダマール積は、配列の対応する要素同士の積を計算して、新しい配列を生成する演算です。Juliaでは、最も基本的なアダマール積の計算方法は、要素同士の掛け算演算子.を使用することです。例えば、次のように2つの配列を用意し、それらのアダマール積を計算することができます。 :<syntaxhighlight lang=julia> a = [1, 2, 3] b = [4, 5, 6] c = a .* b # アダマール積を計算 println(c) # [4, 10, 18] を表示 </syntaxhighlight> このコードでは、<code>.*</code>を使って、要素ごとの掛け算演算子を配列aと配列bに適用し、新しい配列cを生成しています。したがって、アダマール積は新しい配列を生成するため、元の2つの配列とは異なります。 また、行列のアダマール積を計算するには、同じように各要素に掛け算演算子を適用します。例えば、次のように複数の行列のアダマール積を計算することができます。 :<syntaxhighlight lang=julia> a = [1 2; 3 4] b = [5 6; 7 8] c = [9 10; 11 12] d = a .* b .* c # アダマール積を計算 println(d) # [45 120 ;231 384] を表示 </syntaxhighlight> このコードでは、各行列に対して、掛け算演算子を適用し、新しい行列を生成しています。ここでも、元の行列とは異なる新しい行列が生成されます。 ==== 乗算演算子の省略 ==== Juliaでは、乗算演算子を省略することができます。この機能を使うと、リテラルや変数と数値の間に乗算演算子 <code>*</code> を明示的に書かずに、数値と乗算することができます。 具体的な例を見てみましょう: :<syntaxhighlight lang=julia> x = 3 println(10x) # 30 println(3.14x) # 9.42 println([1, 2, 3]x) # [3, 6, 9] println([1 2 3; 4 5 6]x) # [3 6 9; 12 15 18] </syntaxhighlight> 上記の例では、<code>10x</code>は<code>10 * x</code>と同じですが、乗算演算子 <code>*</code> を省略して記述されています。これにより、より簡潔なコードを書くことができます。ただし、変数名と数値の間にスペースがないことに注意してください。スペースがあるとJuliaは別の構文と解釈し、エラーが発生します。 以下は、map関数とdoブロックを使用して乗算演算子を省略する例です: :<syntaxhighlight lang=julia> # 乗算演算子を省略して、map関数で各要素を2倍にする result = map([1, 2, 3]) do x 2x # ここで乗算演算子 * が省略されている end println(result) # [2, 4, 6] </syntaxhighlight> この例では、map関数を使用して配列 [1, 2, 3] の各要素を2倍にしています。doブロック内で乗算演算子 * を省略して記述していますが、この構文は正しく解釈されます。doブロック内の式は、通常のコードと同じように評価されます。 ==== パイプ演算子(|>) ==== Juliaでは、パイプ演算子 <code>|></code> を使用して、関数の出力を次の関数の入力に直接渡すことができます。 これにより、関数を連鎖させることができ、コードの読みやすさが向上します。 パイプ演算子の一般的な構文は次のとおりです: :<syntaxhighlight lang=julia> result = input |> function1 |> function2 |> ... |> functionN </syntaxhighlight> これは、<code>input</code> を <code>function1</code> に適用し、その結果を <code>function2</code> に適用し、その結果を <code>function3</code> に適用し、そして最終的に <code>functionN</code> に適用するという意味です。 例えば、次のようなコードを考えてみましょう: :<syntaxhighlight lang=julia> result = f(g(h(x))) </syntaxhighlight> これをパイプ演算子を使用して書き直すと次のようになります: :<syntaxhighlight lang=julia> result = x |> h |> g |> f </syntaxhighlight> このようにパイプ演算子を使用することで、コードが左から右へと自然に読める形になり、ネストが深くなるのを防ぐことができます。 ==== 演算子の定義 ==== ===== ベクトルに新しい演算子<code>⊗</code>を定義する ===== Juliaでは、新しい演算子を定義する事もできます。 ここでは、<code>⊗</code>という新しい演算子を定義して、ベクトルのテンソル積を計算する関数を実装してみましょう。 ;tp.jl:<syntaxhighlight lang=julia> """ ⊗(v::Vector{T}, w::Vector{T}) where T ベクトル `v` と `w` のテンソル積を計算します。 """ function ⊗(v::Vector{T}, w::Vector{T}) where T [i * j for i in v for j in w] end v = [1, 2] w = [3, 4] result = v ⊗ w # テンソル積を計算する println(result) # 出力: [3, 4, 6, 8] </syntaxhighlight> このコードは、新しい演算子 <code>⊗</code> を定義し、その演算子を使用してベクトルのテンソル積を計算し、結果を出力しています。以下にそれぞれの部分の解説を提供します。 # <code>""" ベクトル</code> v<code>と</code>w <code>のテンソル積を計算します。 """</code> #* これは関数のドキュメンテーション文字列です。関数の機能や使い方を説明します。 # <code>function ⊗(v::Vector{T}, w::Vector{T}) where T</code> #* この行は、新しい演算子 <code>⊗</code> の定義を示しています。関数のシグネチャ(型指定と引数)が定義されています。 #* <code>v</code> と <code>w</code> は、それぞれ <code>Vector{T}</code> 型の引数です。<code>T</code> は型パラメータで、<code>Vector</code> 内の要素の型を表します。 # <code>[i * j for i in v for j in w]</code> #* 内包表記を使って、ベクトル <code>v</code> と <code>w</code> の各要素のペアごとに積を計算して、結果を一つのリストに集めます。 #* <code>for i in v for j in w</code> という構文は、<code>v</code> と <code>w</code> の要素の組み合わせを全て列挙するために使用されます。 # <code>v = [1, 2]</code>、<code>w = [3, 4]</code> #* テスト用のベクトル <code>v</code> と <code>w</code> を定義します。 # <code>result = v ⊗ w</code> #* 定義した演算子 <code>⊗</code> を使って、ベクトル <code>v</code> と <code>w</code> のテンソル積を計算します。 # <code>println(result)</code> #* 計算されたテンソル積を出力します。 ;テンソル積 :テンソル積(tensor product)は、線型代数や多変量解析などの数学分野で使用される概念です。テンソル積は、複数のベクトル空間やテンソル空間を組み合わせて新しい空間を生成する操作です。 :ベクトル空間 ''V'' 上のベクトル '''v''' とベクトル空間 ''W'' 上のベクトル '''w''' のテンソル積 '''v'''⊗'''w''' は、新しいベクトル空間 ''V''⊗''W'' 上の要素となります。このテンソル積は、''V'' の基底と ''W'' の基底のすべての組み合わせを考えて生成される基底を持つベクトル空間です。 :具体的には、ベクトル空間 ''V'' の基底を {'''e'''1​,'''e'''2​,…,'''e'''''n''​} 、ベクトル空間 ''W'' の基底を {'''f'''1​,'''f'''2​,…,'''f'''''m''​} とすると、''V''⊗''W'' の基底は {'''e'''''i''​⊗'''f'''''j''​} となります。 :テンソル積は、多くの分野で使用されます。例えば、量子力学では、複数の量子系の状態を表現するためにテンソル積が使用されます。また、画像処理や機械学習のニューラルネットワークなどの分野でも、テンソル積が利用されることがあります。 === 制御構造 === 制御構造(Control structures)とは、プログラムのフローを制御するための構造や機能のことです。プログラミング言語では、条件に応じて異なる操作を行ったり、同じ操作を繰り返したり、エラーを処理したりするために制御構造が使用されます。 ==== 複合式(Compound Expressions) ==== 複合式は、複数の式をまとめて一つの式として扱うための方法です。Juliaでは、<code>begin</code> キーワードを使用して複合式を開始し、<code>end</code> キーワードで終了します。また、<code>;</code> を使用して複数の式を1行にまとめることもできます。 :<syntaxhighlight lang=julia> begin # 複合式の開始 statement1 statement2 statement3 end </syntaxhighlight> または :<syntaxhighlight lang=julia> statement1; statement2; statement3 </syntaxhighlight> ==== 条件付き評価(Conditional Evaluation) ==== 条件付き評価は、特定の条件が満たされた場合に特定のコードブロックを実行するための方法です。Juliaでは、<code>if-elseif-else</code> 文や三項演算子 <code>?:</code> を使用して条件付き評価を行います。 :<syntaxhighlight lang=julia> if 条件1 # 条件1が真の場合に実行されるコード elseif 条件2 # 条件2が真の場合に実行されるコード else # どの条件も満たされない場合に実行されるコード end </syntaxhighlight> または :<syntaxhighlight lang=julia> 条件 ? 真だった時の値 : 偽だった時の値 </syntaxhighlight> ==== 短絡評価(Short-Circuit Evaluation) ==== 短絡評価は、論理演算子 <code>&&</code>(論理積)と <code>||</code>(論理和)が使用される条件式の評価方法です。Juliaでは、論理演算子が短絡評価を行います。左の条件式だけで結果が確定した場合、右の条件式は評価されません。 :<syntaxhighlight lang=julia> # AND(論理積)の場合、左の条件が偽なら右の条件は評価されない 条件1 && 条件2 # OR(論理和)の場合、左の条件が真なら右の条件は評価されない 条件1 || 条件2 </syntaxhighlight> ==== 繰り返し評価(Repeated Evaluation) ==== 繰り返し評価は、ループ構造を使用して特定のコードブロックを複数回実行する方法です。Juliaでは、<code>while</code> ループと <code>for</code> ループが使用されます。 ;while:<syntaxhighlight lang=julia> while 条件 # 条件が真の場合に実行されるコード end </syntaxhighlight> ;for:<syntaxhighlight lang=julia> for element in iterable # 各要素に対する処理 end </syntaxhighlight> ==== 例外処理(Exception Handling) ==== Juliaにおける例外処理は、予期しない状況やエラーが発生した場合にプログラムの正常な流れを中断し、エラーを処理する仕組みです。主な例外処理の構成要素は以下の通りです: # throw関数: 予期しない状況やエラーが発生したときに、明示的に例外を生成します。例えば、<code>throw(DomainError("Invalid input"))</code>とすることで、ドメインエラーが発生したことを示す例外を投げます。 # try-catch文: <code>try</code>ブロック内のコードを実行し、何らかの例外が発生した場合に<code>catch</code>ブロックでその例外を捕捉し、適切な処理を行います。例外が捕捉されない場合、プログラムは実行を続けます。以下はtry-catch文の例です: #:<syntaxhighlight lang=julia> try # 例外が発生する可能性のあるコード catch ex # 例外が発生した場合の処理 println("Error occurred: $ex") end </syntaxhighlight> # finally節: <code>finally</code>節は、<code>try</code>ブロック内のコードがどのような経路で終了しようとも、そのコードブロックが終了する際に実行されるコードを提供します。主に、リソースの解放などのクリーンアップ処理に使用されます。以下は<code>finally</code>節の例です: #:<syntaxhighlight lang=julia> try # 例外が発生する可能性のあるコード finally # クリーンアップ処理 end </syntaxhighlight> 例外処理を適切に使用することで、プログラムが予期せぬ状況やエラーに遭遇したときに、それに適切に対処できるようになります。 ==== タスク、またはコルーチン(Tasks) ==== タスクは、プログラムの実行を一時停止し、後で再開するための機能です。Juliaでは、<code>yieldto</code> 関数を使用してタスクを定義します。 :<syntaxhighlight lang=julia> function mytask() # タスクの処理 yieldto(main_task) # メインタスクに制御を戻す end </syntaxhighlight> ===== 条件式 ===== 条件式では真理値型(Boolean)が要求されます。 Juliaでは、整数値から真理値型への暗黙の変換は行われないので、条件式は明示的に真理値を提供する必要があります。 例えば、Juliaでは次のようなコードが考えられます: :<syntaxhighlight lang=julia> x = 5 # xの値が0でないかどうかを確認する if x != 0 println("xは正の値です") end </syntaxhighlight> この場合、条件式 <code>x > 0</code> は整数値 <code>x</code> の値が0でないかどうかを評価します。<code>x</code> の値が正の場合に条件が真となり、<code>println</code> 関数が実行されます。整数値がそのまま条件式に使用されることはなく、その値を評価するために比較演算子などの条件式を使用します。 ===== 制御構造のコードギャラリー ===== :<syntaxhighlight lang=julia> # 条件分岐(if-elseif-else) x = 10 if x > 0 println("Positive") # xが正の場合に実行 elseif x < 0 println("Negative") # xが負の場合に実行 else println("Zero") # どの条件にも該当しない場合に実行 end # 繰り返し(whileループ) i = 1 while i <= 5 println(i) # iの値を表示 i += 1 # iを1つ増やす end # 例外処理(try-catch) try x = 1 / 0 # ゼロで割り算を試みる catch println("Error occurred") # エラーが発生した場合に実行 end # 三項演算子 y = x > 0 ? "Positive" : "Non-positive" # xが正なら"Positive"、そうでなければ"Non-positive"をyに代入 # 論理演算子の短絡評価 z = false && (println("This won't be executed")) # 左側が偽なので右側は評価されない </syntaxhighlight> このコード例では、条件分岐、繰り返し、例外処理、三項演算子、論理演算子の短絡評価の各制御構造が使用されています。それぞれのブロックにはコメントが付いており、各制御構造がどのように機能するかが説明されています。 ==== フロー制御文 ==== Juliaには、ループの制御や例外処理の制御などを行うためのさまざまな制御文があります。以下にいくつかの主要なものを示します。 # break文: #* <code>break</code>: ループを途中で終了し、ループから抜け出すための制御文です。 # continue文: #* <code>continue</code>: ループの現在の反復を終了し、次の反復を開始するための制御文です。 # return文: #* <code>return</code>: 関数の実行を終了し、関数から値を返すための制御文です。 # throw文: #* <code>throw</code>: 例外を明示的に発生させ、例外処理ブロックでキャッチされるようにするための制御文です。 これらの制御文は、プログラムの実行フローを制御するために使用されます。例えば、<code>break</code>文はループ内の特定の条件下でループを終了するために使用され、<code>return</code>文は関数の実行を終了して値を返すために使用されます。<code>throw</code>文は、特定の条件下でエラーを発生させ、それを処理するための例外処理ブロックに制御を移すために使用されます。 ;コード例 :*以下は、制御文を網羅したJuliaのコード例です。コメントで各制御文の動作を説明しています。 :<syntaxhighlight lang=julia> function control_flow_example(x) # if文の例 if x > 0 println("xは正の値です") elseif x == 0 println("xはゼロです") else println("xは負の値です") end # whileループの例 println("カウントダウン開始:") i = x while i >= 0 println(i) i -= 1 end # forループの例 println("要素の表示:") for element in ["apple", "banana", "cherry"] println(element) end # break文の例 println("3以下の奇数の表示:") for i in 1:10 if i > 3 break # ループを終了する elseif iseven(i) continue # 偶数の場合は次の反復に進む end println(i) end # return文の例 println("10以下の素数のカウント:") function count_primes(n) count = 0 for i in 2:n if isprime(i) count += 1 end end return count # 関数の実行を終了し、countの値を返す end println("10以下の素数の数:", count_primes(10)) # throw文の例 println("エラーチェック:") function check_positive(x) if x <= 0 throw(ArgumentError("xは正の値でなければなりません")) end println("xは正の値です") end try check_positive(-5) catch e println("エラーが発生しました:", e) end end # メインの実行部分 control_flow_example(5) </syntaxhighlight> このコード例では、各種の制御文(if文、whileループ、forループ、break文、return文、throw文)を使用しています。それぞれの制御構造が、適切にプログラムのフローを制御しています。 ===内包表記=== 内包表記(comprehension)は、プログラミング言語において、コレクション(配列、リスト、セット、辞書など)を生成するための構文機能です。通常、内包表記は、ループや条件文を使用せずに、簡潔かつ効率的にコレクションを生成することができます。 ;配列(Array)の内包表記: :配列内包表記は、次のような構文を持ちます: :<syntaxhighlight lang=julia> [式 for item in iterable if 条件] </syntaxhighlight> :これは、iterableから要素を取り出し、条件が真の場合に式を評価して新しい配列を生成するという意味です。 :<syntaxhighlight lang=julia> # 0から9までの数値のうち、偶数のみを含む配列を生成 evens = [x for x in 0:9 if x % 2 == 0] </syntaxhighlight> ;セット(Set)の内包表記: :セット内包表記は、次のような構文を持ちます: :<syntaxhighlight lang=julia> {式 for item in iterable if 条件} </syntaxhighlight> :これは、iterableから要素を取り出し、条件が真の場合に式を評価して新しいセットを生成するという意味です。 :<syntaxhighlight lang=julia> # 0から9までの数値のうち、偶数のみを含むセットを生成 even_set = {x for x in 0:9 if x % 2 == 0} </syntaxhighlight> ;辞書(Dict)の内包表記: :辞書内包表記は、次のような構文を持ちます: :<syntaxhighlight lang=julia> {キー式 => 値式 for item in iterable if 条件} </syntaxhighlight> :これは、iterableから要素を取り出し、条件が真の場合にキー式と値式を評価して新しい辞書を生成するという意味です。 :<syntaxhighlight lang=julia> # 1から5までの数値をキーとし、それぞれのキーの2倍を値とする辞書を生成 double_dict = {x => 2x for x in 1:5} </syntaxhighlight> 内包表記は、よりコンパクトで読みやすいコードを書くための便利な手段です。 ==== 行列と内包表記 ==== 行列(Matrix)を生成するためにも、内包表記は非常に便利です。 特に、2次元配列を効率的に生成する際に役立ちます。以下に、マトリックスを生成する内包表記の例を示します。 :<syntaxhighlight lang=julia> matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)] print(matrix) </syntaxhighlight> # 3x3のマトリックスを生成する例 この例では、3x3のマトリックスが生成されます。各要素は、その行番号と列番号の積になります。生成されるマトリックスは以下のようになります: :<syntaxhighlight lang=julia> [[1, 2, 3], [2, 4, 6], [3, 6, 9]] </syntaxhighlight> このように、内包表記を使用することで、ネストされたループを避けてマトリックスを効率的に生成することができます。また、内包表記を使用することで、コードが簡潔になり、可読性が向上します。 さらに、内包表記を活用して条件に基づいたマトリックスの生成も可能です。例えば、特定の条件を満たす要素のみを含むマトリックスを生成することができます。内包表記を利用することで、このような操作を簡潔に記述することができます。 ===データ構造=== 配列、タプル、辞書などのデータ構造を学びます。これらの構造はデータを効果的に扱うための基本的なツールです。さらに、データのインデクシングやスライシングの方法も理解します。データ構造の選択と操作はプログラムの効率性に大きく影響するため、しっかりと理解しておきましょう。 ==== Juliaのデータ型 ==== Juliaには、様々なデータ型があります。主なデータ型は以下の通りです。 :{| class="wikitable" |+ Juliaの組み込み型の一覧 !型名 !typeof()表現 !説明 !リテラル |- |Bool型 (Booleans) |<code>Bool</code> |真理値を表す型。真(<code>true</code>)または偽(<code>false</code>)のいずれか。 |<code>true</code>, <code>false</code> |- |整数型 (Integers) |<code>Int64</code>, <code>Int32</code>, ...;<code>UInt64</code>, <code>UInt32</code>, ... |符号付き整数。64ビットや32ビットなどの幅が異なる。 |<code>42</code>, <code>-10</code> |- |浮動小数点数型 (Floating Point Numbers) |<code>Float64</code>, <code>Float32</code>, ... |浮動小数点数。64ビットや32ビットなどの幅が異なる。 |<code>3.14</code>, <code>2.718</code> |- |複素数型 (Complex Numbers) |<code>Complex{Float64}</code>, <code>Complex{Float32}</code>, ... |実部と虚部からなる複素数。実部と虚部は浮動小数点数。 |<code>1 + 2im</code>, <code>3 - 4im</code> |- |有理数型 (Rational Numbers) |<code>Rational{Int64}</code> |分子と分母からなる有理数。分子と分母は整数。 |<code>2//3</code>, <code>4//5</code> |- |文字型 (Character) |<code>Char</code> |Unicode文字。 |<code>'a'</code>, <code>'😊'</code> |- |文字列型 (String) |<code>String</code> |文字列。 |<code>"hello"</code>, <code>"Julia"</code> |- |配列型 (Arrays) |<code>Array{Int64,1}</code>, <code>Array{Float64,2}</code>, ... |要素の型と次元数によって定義される配列。 |<code>[1, 2, 3]</code>, <code>[1.0 2.0; 3.0 4.0]</code> |- |タプル型 (Tuples) |<code>Tuple{Int64, String, Float64}</code> |複数の要素をまとめた不変のコレクション。要素の型は指定される。 |<code>(1, "apple", 3.14")</code> |- |辞書型 (Dictionaries) |<code>Dict{String, Int64}</code> |キーと値のペアのコレクション。キーと値の型が指定される。 |<code>Dict("a" => 1, "b" => 2)</code> |- |範囲型 (Ranges) |<code>UnitRange{Int64}</code>, <code>StepRangeLen{Float64}</code>, ... |数値の範囲を表す型。 |<code>1:5</code>, <code>0:0.1:1</code> |- |Symbol型 (Symbols) |<code>Symbol</code> |シンボル。シンボルは一意の識別子を表します。 |<code>:apple</code>, <code>:Julia</code> |} :これらの組み込み型は、Juliaの基本的なデータ構造を構築するために使用されます。 ::Juliaには、型推論があるので、これらのデータ型を明示的に指定する必要はあまりありません。 ==== 文字列 ==== JuliaのStringは、テキストデータを表す不変のデータ型です。文字列は一連の文字(Unicode文字)から構成され、ダブルクォーテーションで囲まれます。例えば、<code>"Hello, world!"</code>のような文字列は、文字<code>H</code>、<code>e</code>、<code>l</code>、<code>l</code>、<code>o</code>、<code>,</code>、スペース、<code>w</code>、<code>o</code>、<code>r</code>、<code>l</code>、<code>d</code>、<code>!</code>の連続したシーケンスです。 JuliaのStringは不変のため、一度作成された文字列は変更できません。これは、文字列を変更する代わりに、新しい文字列を生成することになります。Juliaの文字列はUTF-8でエンコードされており、Unicodeの全ての文字をサポートしています。 JuliaのString型には、様々なメソッドが用意されており、文字列の操作や処理を行うための機能が豊富に提供されています。また、文字列補間や正規表現などの機能も利用することができます。 文字列は、Juliaでのテキスト処理、データ操作、文字列操作などの多くの場面で広く使用されます。 以下にjuliaの文字列のメソッドの一部を示します。 # 文字列の長さを取得する: <code>length(str)</code> #:<syntaxhighlight lang=julia> str = "Hello, world!" len = length(str) # 13 </syntaxhighlight> # 文字列の連結: <code>*</code>演算子または<code>string()</code>関数を使用します。 #:<syntaxhighlight lang=julia> str1 = "Hello, " str2 = "world!" concatenated_str = str1 + str2 # "Hello, world!" concatenated_str = string(str1, str2) # "Hello, world!" </syntaxhighlight> # 部分文字列を取得する: <code>subString(str, start_index, end_index)</code>または<code>str[start_index:end_index]</code> #:<syntaxhighlight lang=julia> str = "Hello, world!" sub_str = str[1:5] # "Hello" </syntaxhighlight> # 文字列を反転させる: <code>reverse(str)</code> #:<syntaxhighlight lang=julia> str = "Hello" reversed_str = reverse(str) # "olleH" </syntaxhighlight> # 大文字・小文字の変換: <code>uppercase(str)</code>, <code>lowercase(str)</code> #:<syntaxhighlight lang=julia> str = "Hello, world!" uppercase_str = uppercase(str) # "HELLO, WORLD!" lowercase_str = lowercase(str) # "hello, world!" </syntaxhighlight> # 文字列の分割: <code>split(str, [delim])</code> #:<syntaxhighlight lang=julia> str = "apple, banana, orange" words = split(str, ", ") # ["apple", "banana", "orange"] </syntaxhighlight> # 文字列の結合: <code>join(collection, [delim])</code> #:<syntaxhighlight lang=julia> words = ["apple", "banana", "orange"] sentence = join(words, ", ") # "apple, banana, orange" </syntaxhighlight> # 文字列の検索: <code>search(str, pattern)</code> #:<syntaxhighlight lang=julia> str = "Hello, world!" index = search(str, "world") # 8:12 </syntaxhighlight> これらは一部の基本的な文字列メソッドですが、Juliaにはさらに多くの文字列処理関数が用意されています。これらのメソッドを組み合わせて、さまざまな文字列操作を実行することができます。 {{コラム|コレクションと typeof|2=以下はJuliaのコード例です。各リテラル表現に対する<code>typeof</code>を表示し、コレクションとファイル入出力に関する一部の操作も実行しています。 :<syntaxhighlight lang=julia> # 配列 a = [1, 2, 3] println("a: ", typeof(a)) println("a[2]: ", typeof(a[2])) println("a[1:2]: ", typeof(a[1:2])) println("push!(a, 4): ", typeof(push!(a, 4))) # タプル t = (1, "hello", 3.14) println("t: ", typeof(t)) println("t[2]: ", typeof(t[2])) # 辞書 d = Dict("apple" => 1, "banana" => 2, "orange" => 3) println("d: ", typeof(d)) println("d[\"apple\"]: ", typeof(d["apple"])) # 集合 s = Set([1, 2, 3]) println("s: ", typeof(s)) println("pop!(s): ", typeof(pop!(s))) # 文字列 str = "hello world" println("str: ", typeof(str)) println("str[2]: ", typeof(str[2])) println("split(str): ", typeof(split(str))) # ファイル入出力 open("test.txt", "w") do file write(file, "hello world") end f = open("test.txt", "r") println("f: ", typeof(f)) println("readline(f): ", typeof(readline(f))) </syntaxhighlight> 実行結果は以下のようになります。 :<syntaxhighlight lang=julia> a: Array{Int64,1} a[2]: Int64 a[1:2]: Array{Int64,1} push!(a, 4): Array{Int64,1} t: Tuple{Int64, String, Float64} t[2]: String d: Dict{String, Int64} d["apple"]: Int64 s: Set{Int64} pop!(s): Int64 str: String str[2]: Char split(str): Array{SubString{String},1} f: IOStream readline(f): String </syntaxhighlight> }} Juliaのコレクション型は、複数の要素を一つのまとまりとして格納するデータ構造を指します。コレクション型は異なる要素の集まりを表現し、これらの要素にアクセスしたり操作したりするための方法を提供します。 Juliaの主要なコレクション型には以下のようなものがあります。 #配列(Array): #*要素の並び順が保持される可変長のコレクション。 #*異なる型の要素を含むことができる。 #*要素の追加や削除が可能。 #タプル(Tuple): #*固定長の不変なコレクション。 #*複数の型の要素を含むことができる。 #*要素の変更や追加ができない。 #辞書(Dict): #*キーと値のペアを関連付ける可変長のコレクション。 #*キーは一意でなければならない。 #*キーを使用して値にアクセスする。 #セット(Set): #*一意な要素のコレクション。 #*要素の順序は保持されない。 #*和集合や積集合などの集合演算に使用される。 これらのコレクション型は、異なるデータ構造や操作方法を提供し、さまざまな問題やアルゴリズムに対して適した方法でデータを表現します。 ==== 配列 ==== 配列(Array)は、同じ型の要素を順序付きで格納するデータ構造です。Juliaでは、配列は1次元から多次元までの次元を持つことができます。配列は非常に柔軟であり、数値、文字列、構造体など、さまざまな種類のデータを格納できます。 以下は、Juliaでの配列の例です: :<syntaxhighlight lang=julia> # 1次元の整数型の配列 array1 = [1, 2, 3, 4, 5] # 2次元の浮動小数点型の配列 array2 = [1.0 2.0 3.0; 4.0 5.0 6.0] # 3次元の文字列型の配列 array3 = ["a" "b"; "c" "d"][:, :, ones(String, 2)] # 1次元の空の配列 empty_array = Int[] </syntaxhighlight> 配列の要素へのアクセスは、添字を使用して行います。例えば、<code>array1</code>の2番目の要素にアクセスする場合は<code>array1[2]</code>とします。Juliaでは、添字は1から始まることに注意してください。 配列は可変長であり、要素の追加や削除、変更が可能です。例えば、<code>push!()</code>関数を使用して配列に要素を追加したり、<code>pop!()</code>関数を使用して配列から要素を削除したりすることができます。 ;配列のメソッド Juliaの配列は、多くの便利なメソッドを提供しています。以下に、一部の主要な配列メソッドを示します。 # 要素の追加と削除: #* <code>push!(array, value)</code>: 配列の末尾に要素を追加します。 #* <code>pop!(array)</code>: 配列の末尾の要素を削除して返します。 #* <code>append!(array1, array2)</code>: 配列2を配列1の末尾に結合します。 # 要素の操作: #* <code>sort(array)</code>: 配列の要素を昇順に並び替えます。 #* <code>reverse(array)</code>: 配列の要素を逆順にします。 #* <code>unique(array)</code>: 配列から重複した要素を削除します。 #* <code>filter(predicate, array)</code>: 条件を満たす要素のみを抽出します。 # 要素の検索と参照: #* <code>findall(predicate, array)</code>: 条件を満たす要素のインデックスを返します。 #* <code>in(element, array)</code>: 配列内に指定した要素が含まれているかどうかを確認します。 #* <code>getindex(array, indices...)</code>: 指定されたインデックスに対応する配列の要素を取得します。 # 配列の変換: #* <code>map(function, array)</code>: 配列の各要素に関数を適用します。 #* <code>reduce(function, array)</code>: 配列の要素を減少させます。 #* <code>reshape(array, dims)</code>: 配列の形状を変更します。 これらは一部の主要な配列メソッドですが、Juliaにはさらに多くの配列操作関数が用意されています。これらのメソッドを組み合わせて、さまざまな配列操作を実行できます。 :これらのメソッドは、Juliaの配列に対する一般的な操作の例にすぎません。詳細については、公式ドキュメント を参照してください。 ===== イディオム ===== Juliaで配列を効果的に操作するためのいくつかのイディオム(慣用句)があります。これらのイディオムは、コードを簡潔に保ちながら効率的にデータを処理するのに役立ちます。以下にいくつかの一般的な配列のイディオムを示します。 # 配列の生成: #* ゼロで初期化: <code>zeros()</code>関数や<code>fill()</code>関数を使用して、特定の値(通常はゼロ)で初期化された配列を生成します。 #:<syntaxhighlight lang=julia> zeros(Int, 5) # 整数型の配列 [0, 0, 0, 0, 0] fill(0, 5) # 0で初期化された配列 [0, 0, 0, 0, 0] </syntaxhighlight> #* 範囲の生成: <code>range()</code>関数を使用して、指定された範囲内の値を持つ配列を生成します。 #:<syntaxhighlight lang=julia> range(1, stop=10, step=2) # [1, 3, 5, 7, 9] </syntaxhighlight> #:<syntaxhighlight lang=julia> </syntaxhighlight> # 要素の変換: #* マップ関数: <code>map()</code>関数を使用して、配列の各要素に関数を適用します。 #:<syntaxhighlight lang=julia> array = [1, 2, 3, 4, 5] doubled_array = map(x -> 2x, array) # [2, 4, 6, 8, 10] </syntaxhighlight> # フィルタリング: #* フィルタ関数: <code>filter()</code>関数を使用して、配列の要素を条件に基づいてフィルタリングします。 #:<syntaxhighlight lang=julia> array = [1, 2, 3, 4, 5] even_numbers = filter(iseven, array) # [2, 4] </syntaxhighlight> # 要素の集約: #* reduce関数: <code>reduce()</code>関数を使用して、配列の要素を単一の値に集約します。 #:<syntaxhighlight lang=julia> array = [1, 2, 3, 4, 5] sum_of_array = reduce(+, array) # 15 </syntaxhighlight> これらのイディオムを使うことで、効率的で読みやすいJuliaコードを記述できます。それぞれの状況に応じて、最適なイディオムを選択し、活用してください。 ==== 多次元配列 ==== Juliaの多次元配列は、1次元配列に似た形式で定義されますが、複数の次元を持つ配列であり、要素へのアクセスにはインデックスのタプルが使用されます。 こちらがJuliaで多次元配列を使用する代表的なコード例です。 :<syntaxhighlight lang=julia> # 多次元配列の生成 A = [i+j for i in 1:3, j in 1:3] # 多次元配列の表示 println(A) # [2 3 4; 3 4 5; 4 5 6] # 多次元配列の要素の参照 println(A[2,3]) # 5 # 多次元配列の列の参照 println(A[2,:]) # [3, 4, 5] # 多次元配列の列の参照 println(A[:,1]) # [2, 3, 4] # 多次元配列の列の複製 println(A[:,:]) # [2 3 4; 3 4 5; 4 5 6] # 多次元配列の部分配列 println(A[1:2,2:3]) # [3 4; 4 5] # 多次元配列の変更 A[2,3] = 10 # 多次元配列に対する演算 B = A * A # 多次元配列の反復処理 for i in 1:size(B,1), j in 1:size(B,2) println(B[i,j]) end </syntaxhighlight> : このコードでは、<code>[i+j for i in 1:3, j in 1:3]</code>により3x3の多次元配列<code>A</code>が生成され、<code>println(A)</code>によりその中身が表示されます。 : 次に、<code>println(A[2,3])</code>により<code>A</code>の2行3列の要素が出力されます。そして、<code>A[2,3] = 10</code>によりこの要素の値が変更されます。 : また、<code>A * A</code>により<code>A</code>自身と同じ大きさの行列<code>B</code>が生成され、この行列に演算が行われます。そして、<code>for</code>ループを使用して、<code>B</code>の全要素を出力することができます。 ;多次元配列のメソッド 多次元配列(行列など)を扱う際に、便利なメソッドがいくつかあります。以下に、Juliaの多次元配列に関連する主要なメソッドのいくつかを示します。 # 次元とサイズ: #* <code>ndims(array)</code>: 配列の次元数を返します。 #* <code>size(array)</code>: 配列の各次元のサイズをタプルで返します。 # 要素のアクセス: #* <code>getindex(array, indices...)</code>または<code>array[indices...]</code>: 指定されたインデックスに対応する要素を取得します。 #* <code>setindex!(array, value, indices...)</code>または<code>array[indices...] = value</code>: 指定されたインデックスに対応する要素に値を設定します。 # 次元の変換: #* <code>reshape(array, dims)</code>: 配列の形状を変更します。 #* <code>permutedims(array, perm)</code>: 配列の次元を入れ替えます。 # 要素の統計情報: #* <code>minimum(array)</code>, <code>maximum(array)</code>: 配列内の最小値、最大値を取得します。 #* <code>sum(array)</code>, <code>mean(array)</code>: 配列内の合計、平均を計算します。 # 要素の操作: #* <code>map(f, array)</code>: 配列の各要素に関数を適用します。 #* <code>filter(f, array)</code>: 条件を満たす要素のみを抽出します。 これらのメソッドは、多次元配列を効果的に操作するためのツールとして役立ちます。Juliaの多次元配列は、数値計算やデータ処理などの多くのアプリケーションで広く使用されています。 ===== 多次元配列のイディオム ===== 多次元配列を効果的に操作するためのいくつかのイディオム(慣用句)があります。これらのイディオムを使用することで、コードをより効率的に記述できます。以下に、多次元配列のイディオムのいくつかを示します。 # 多次元配列の初期化: #* ランダムな値で初期化: <code>rand()</code>関数を使用して、指定された範囲内のランダムな値で初期化された多次元配列を生成します。 #:<syntaxhighlight lang=julia> rand(3, 3) # 3x3のランダムな値で初期化された配列 </syntaxhighlight> # 配列操作: #* 転置: <code>transpose()</code>関数を使用して、行列の転置を行います。 #:<syntaxhighlight lang=julia> A = [1 2; 3 4] transpose(A) # 転置された行列 </syntaxhighlight> # 要素へのアクセス: #* 行または列の選択: 列または行の選択には、配列のインデックスまたはスライスを使用します。 #:<syntaxhighlight lang=julia> A = [1 2 3; 4 5 6; 7 8 9] A[:, 2] # 2列目の要素 </syntaxhighlight> # 多次元配列の変換: #* 1次元配列への変換: <code>vec()</code>関数を使用して、多次元配列を1次元配列に変換します。 #:<syntaxhighlight lang=julia> A = [1 2; 3 4] vec(A) # 多次元配列を1次元配列に変換 </syntaxhighlight> # 多次元配列の操作: #* 要素の統計情報の計算: <code>minimum()</code>、<code>maximum()</code>、<code>mean()</code>などの関数を使用して、多次元配列の統計情報を計算します。 #:<syntaxhighlight lang=julia> A = [1 2 3; 4 5 6; 7 8 9] minimum(A) # 最小値 </syntaxhighlight> これらのイディオムは、多次元配列を操作する際に役立ちます。適切なイディオムを選択し、コードを効果的に記述してください。 ==== タプル ==== タプル(Tuple)は、固定長の順序付きコレクションであり、異なる型の要素を格納できます。タプルはリストや配列と同様に要素を含みますが、一度作成されたタプルの要素は変更できません。つまり、タプルは不変(immutable)です。 タプルは丸括弧 <code>()</code> で囲まれ、カンマ <code>,</code> で区切られた要素のリストで表現されます。以下は、いくつかのタプルの例です。 :<syntaxhighlight lang=julia> # 整数型のタプル tuple1 = (1, 2, 3, 4, 5) # 文字列型と浮動小数点型のタプル tuple2 = ("apple", 3.14, "banana") # 空のタプル empty_tuple = () </syntaxhighlight> タプルは、関数の返り値や複数の値をまとめて扱いたい場合などに便利です。また、パターンマッチングや関数の引数の受け渡し、データのグループ化など、さまざまな用途で使用されます。 タプルの要素へのアクセスは、インデックスを使用して行います。インデックスは1から始まります。例えば、<code>tuple1</code>の3番目の要素にアクセスするには、<code>tuple1[3]</code>とします。 :<syntaxhighlight lang=julia> println(tuple1[3]) # 出力: 3 </syntaxhighlight> タプルはイミュータブルであるため、一度作成されると要素を変更することはできません。しかし、タプルを使用して新しいタプルを作成することはできます。 ;タプルのメソッド タプルは不変(immutable)なので、タプル自体に変更を加えるメソッドはありません。しかし、タプルに関するいくつかの関数やメソッドが提供されています。以下にいくつかの例を示します。 # 要素へのアクセス: #* <code>getindex(tuple, index)</code>: 指定されたインデックスの要素を取得します。 # 要素の操作: #* <code>iterate(tuple)</code>: イテレーションプロトコルの一部として、タプルのイテレータを返します。 # 長さの取得: #* <code>length(tuple)</code>: タプルの要素数を返します。 これらのメソッドや関数を使用することで、タプルの内容を取得したり、操作したりすることができます。ただし、タプル自体は不変なので、要素の変更や追加、削除はできません。 ;まとめ:<syntaxhighlight lang=julia> # 1つのタプルを作成する場合 t1 = (1, 2, 3) # t1は (1, 2, 3)というタプルを表します # 要素が1つのタプルを作成する場合 t2 = (4,) # t2は (4,)というタプルを表します # タプルの要素には異なる型のオブジェクトを含めることができます t3 = ("apple", 3, true) # t3は ("apple",3,true)というタプルを表します # タプルの中に別のタプルを含めることができます t4 = ((1, 2), "hello") # t4は ((1,2),"hello")というタプルを表します # タプルの要素に変数を含めることができます a = 5 b = "World" t5 = (a, b) # t5は (5,"World")というタプルを表します # 2つのタプルを連結する場合、タプルの連結演算子である..を使用できます。 t6 = t1..t2 # さらに、配列をタプルに変換することができます。 a = [1, 2, 3] t7 = tuple(a) # タプルの要素にインデックスと値のペアを含める場合、enumerateを使用できます。 t8 = tuple(enumerate(a)) # 複数の要素を同時に取得するために、タプルを分解することができます。 x, y, z = t1 # タプルの要素を削除することはできませんが、範囲を指定して新しいタプルを作成することができます。 t9 = t1[1:2] # タプルの要素の和、積、最大値、最小値を取得するには、sum、prod、maximum、minimum関数を使用できます。 s = sum(t1) p = prod(t1) max_val = maximum(t1) min_val = minimum(t1) # タプルに対してiter関数を使用することにより、反復処理を行うこともできます。 for i in t1 println(i) end </syntaxhighlight> : 以上のように、Juliaでは、()で値をカンマで区切って囲んだり、タプル内に式を含めたり、コンストラクタを使用することでタプルを作成することができます。また、添え字を使用して単一の要素を取得するだけでなく、複数の要素を同時に取得するためにタプルを分解することもできます。さらに、タプルの要素を削除できないため、範囲を指定して新しいタプルを作成する必要があります。タプルを結合するには、..演算子を使用し、配列をタプルに変換することもできます。タプルは、sum、prod、maximum、minimum関数を使用して要素の和、積、最大値、最小値を見つけることができ、反復処理も行うことができます。 ===== イディオム ====== タプルを効果的に使用するためのいくつかのイディオム(慣用句)があります。タプルは不変(immutable)なので、要素を変更することはできませんが、その性質を活かしてさまざまな用途に利用できます。 以下に、タプルのイディオムの一部を示します。 #複数の値の同時割り当て #* タプルを使用して関数から複数の値を返すことができます。関数の返り値としてタプルを使用すると、複数の変数に値を同時に割り当てることができます。 #:<syntaxhighlight lang=julia> function get_coordinates() return (3, 4) end x, y = get_coordinates() </syntaxhighlight> #タプルの分解 #* タプルの要素に個々の変数を割り当てることができます。これにより、タプルの要素を個別に操作できます。 #:<syntaxhighlight lang=julia> coordinates = (3, 4) x, y = coordinates </syntaxhighlight> #イテレータとしての利用 #* タプルはイテレータとして使用できます。これは、forループなどの反復処理に役立ちます。 #:<syntaxhighlight lang=julia> coordinates = (3, 4) for coord in coordinates println(coord) end </syntaxhighlight> #* タプルの要素をパターンマッチングすることで、特定の構造を持つデータを抽出したり操作したりすることができます。 #:<syntaxhighlight lang=julia> coordinates = (3, 4) x, y = coordinates </syntaxhighlight> これらのイディオムを使用することで、タプルを効果的に活用し、柔軟なコードを記述することができます。 ==== 辞書 ==== 辞書(Dict; Dictionary)は、キーと値のペアを関連付けるデータ構造です。他の言語では連想配列やハッシュマップとも呼ばれます。Juliaの辞書は非常に柔軟で、異なる型のキーと値を持つことができます。 辞書は波括弧 <code>{}</code> で囲まれ、キーと値のペアはコロン <code>:</code> で区切られます。以下は、いくつかの辞書の例です。 :<syntaxhighlight lang=julia> # 文字列型のキーと整数型の値を持つ辞書 dict1 = Dict("apple" => 3, "banana" => 5, "orange" => 2) # 整数型のキーと文字列型の値を持つ辞書 dict2 = Dict(1 => "one", 2 => "two", 3 => "three") # 空の辞書 empty_dict = Dict() </syntaxhighlight> 辞書は、キーを使用して値にアクセスすることができます。キーはユニークであり、同じキーに対して異なる値を関連付けることはできません。キーが存在しない場合、エラーが発生します。 :<syntaxhighlight lang=julia> println(dict1["apple"]) # 出力: 3 println(dict2[2]) # 出力: "two" </syntaxhighlight> 辞書の操作には、キーと値の追加、削除、変更、検索などが含まれます。辞書は、データを効率的に検索および更新するために広く使用されます。Juliaの辞書は、ハッシュテーブルとして実装されており、高速なキーの検索を提供します。 ;辞書のメソッド Juliaの辞書(Dict)には、さまざまな便利なメソッドが用意されています。以下に、よく使われる辞書のメソッドの一部を示します。 # 要素の操作: #* <code>get(dict, key, default)</code>: 指定されたキーに対応する値を取得します。キーが存在しない場合は、デフォルト値を返します。 #* <code>setdefault!(dict, key, default)</code>: 指定されたキーが存在しない場合に、キーとデフォルト値を辞書に追加します。 # 要素の追加と削除: #* <code>push!(dict, key => value)</code>: 新しいキーと値のペアを辞書に追加します。 #* <code>delete!(dict, key)</code>: 指定されたキーに対応する要素を辞書から削除します。 # 要素の検査: #* <code>haskey(dict, key)</code>: 指定されたキーが辞書に存在するかどうかを確認します。 #* <code>isempty(dict)</code>: 辞書が空であるかどうかを確認します。 # キーと値の取得: #* <code>keys(dict)</code>: 辞書内のすべてのキーを返します。 #* <code>values(dict)</code>: 辞書内のすべての値を返します。 #* <code>pairs(dict)</code>: 辞書内のすべてのキーと値のペアを返します。 これらのメソッドを使用することで、辞書を効果的に操作し、データを取得および更新することができます。Juliaの辞書は非常に柔軟であり、さまざまなデータ操作に役立ちます。 ===== イディオム ===== 辞書を効果的に使用するためのいくつかのイディオム(慣用表現)があります。 これらのイディオムは、コードをより読みやすく、効率的にするために役立ちます。 以下に、よく使われる辞書のイディオムのいくつかを示します。 # デフォルト値の設定: 辞書から値を取得する際に、キーが存在しない場合のデフォルト値を設定する方法です。 #:<syntaxhighlight lang=julia> dict = Dict("apple" => 3, "banana" => 5) value = get(dict, "orange", 0) # キーが存在しない場合はデフォルト値0を使用 </syntaxhighlight> #キーの存在確認: 辞書内に特定のキーが存在するかどうかを確認する方法です。 #:<syntaxhighlight lang=julia> dict = Dict("apple" => 3, "banana" => 5) if haskey(dict, "apple") println("辞書に'apple'のキーが存在します") end </syntaxhighlight> #要素の追加と更新: 辞書に新しいキーと値のペアを追加したり、既存のキーの値を更新する方法です。 #:<syntaxhighlight lang=julia> dict = Dict("apple" => 3, "banana" => 5) dict["orange"] = 2 # 新しいキーと値のペアを追加 dict["banana"] = 6 # 既存のキーの値を更新 </syntaxhighlight> #ループ処理: 辞書内のすべてのキーと値のペアに対してループ処理を行う方法です。 #:<syntaxhighlight lang=julia> dict = Dict("apple" => 3, "banana" => 5) for (key, value) in pairs(dict) println("キー: $key, 値: $value") end </syntaxhighlight> これらのイディオムを使用することで、辞書を効果的に操作し、コードをより読みやすく、効率的にすることができます。Juliaの辞書は、データのマッピングや関連付けに広く使用され、多くのアプリケーションで重要な役割を果たしています。 ==== 集合 ==== 集合は、重複しない要素を複数個保持することができるコレクションです。 以下はJuliaで集合を扱う典型的なコード例です: :<syntaxhighlight lang=julia> # 集合の宣言 set1 = Set([1, 2, 3, 4]) set2 = Set([3, 4, 5, 6]) # 集合の和集合 set_union = union(set1, set2) @show set_union # Set([4, 2, 3, 5, 6, 1]) # 集合の積集合 set_intersection = intersection(set1, set2) @show set_intersection # Set([4, 3]) # 集合の差集合 set_difference = setdiff(set1, set2) @show set_difference # Set([2, 1]) # 集合の合併差 set_symmetric_difference = SymmetricDiff(set1, set2) @show set_symmetric_difference # SymmetricDiff(Set([4, 2, 3, 1]), Set([5, 6, 3, 4])) # 集合に要素が含まれるかどうかの確認 @show 2 in set1 # true @show 5 in set1 # false # 集合の要素数 @show length(set1) # 4 </syntaxhighlight> 上記のコードは、次のことを行います: * <code>Set</code>型の変数を宣言し、要素をセットアップします。 * 集合の和集合、積集合、差集合、合併差を計算します。 * 指定された要素が集合に含まれているかどうかを確認します。 * 集合の要素数を調べます。 以下はJuliaの<code>Set</code>型に含まれる典型的なメソッドとその引数、戻り値、および簡単な説明を表形式でまとめたものです。 {| class="wikitable" |+ 集合型のメソッド !メソッド名 !引数 !戻り値 !説明 |- |<code>union</code> |<code>set1::Set</code>, <code>set2::Set</code>, ... |<code>Set</code> |渡された全ての集合の和集合を返す |- |<code>intersect</code> |<code>set1::Set</code>, <code>set2::Set</code>, ... |<code>Set</code> |渡された全ての集合の積集合を返す |- |<code>setdiff</code> |<code>set1::Set</code>, <code>set2::Set</code> |<code>Set</code> |<code>set1</code>から<code>set2</code>に含まれる要素を取り除いた集合を返す |- |<code>symdiff</code> |<code>set1::Set</code>, <code>set2::Set</code> |<code>Set</code> |<code>set1</code>と<code>set2</code>の対称差、すなわち<code>set1</code>と<code>set2</code>のどちらかにだけ存在する要素から成る集合を返す |- |<code>issubset</code> |<code>set1::Set</code>, <code>set2::Set</code> |<code>Bool</code> |<code>set1</code>が<code>set2</code>の部分集合かどうかを返す |- |<code>isdisjoint</code> |<code>set1::Set</code>, <code>set2::Set</code> |<code>Bool</code> |<code>set1</code>と<code>set2</code>が共通の要素を持たないかどうかを返す |- |<code>push!</code> |<code>set::Set</code>, <code>value</code> |<code>Set</code> |<code>set</code>に<code>value</code>を追加して、更新された<code>set</code>を返す |- |<code>pop!</code> |<code>set::Set</code> |<code>Any</code> |<code>set</code>の中から一つの要素を取り出して、それを返す。<code>set</code>自身から取り除くことに注意。 |- |<code>findfirst</code> |<code>set::Set</code>, <code>value</code> |<code>Union{Int, Nothing}</code> |<code>set</code>内の先頭の<code>value</code>のインデックスを返す。<code>value</code>が存在しない場合は<code>nothing</code>を返す。 |- |<code>size</code> |<code>set::Set</code> |<code>(Int, )</code> |<code>set</code>の要素数をタプル形式で返す |- |<code>isempty</code> |<code>set::Set</code> |<code>Bool</code> |<code>set</code>が空かどうかを返す |- |<code>iterate</code> |<code>set::Set</code> |<code>Tuple{Any, Any}</code> or <code>nothing</code> |繰り返し処理に使用できるイテレータを返す。 |- |<code>collect</code> |<code>set::Set</code> |<code>Array</code> |<code>set</code>の要素を並べた配列を返す。 |} 注意:上記の表は、<code>Set</code>型が持つメソッドの一部のみを紹介したものです。また、実際のコードでこれらのメソッドを呼び出す際には、引数の型や数、戻り値の型も具体的な状況に応じて変える必要があります。 ====構造体(Struct)==== Juliaにおける<code>struct</code>は、新しいデータ型を定義するためのキーワードです。<code>struct</code>を使用して定義されたデータ型は、複数のフィールド(属性)を持つことができます。これらのフィールドは、データ型の構造を表現するために使用されます。 <code>struct</code>の構文は次のようになります: :<syntaxhighlight lang=julia> struct 構造体名 フィールド名1::型1 フィールド名2::型2 # 必要な数だけフィールドを追加 end </syntaxhighlight> 例えば、2次元の座標を表すデータ型を定義する場合、次のように<code>struct</code>を使用します: :<syntaxhighlight lang=julia> struct Point x::Float64 y::Float64 end </syntaxhighlight> この例では、<code>Point</code>という名前の新しいデータ型が定義されています。このデータ型は、2つの浮動小数点数フィールド<code>x</code>と<code>y</code>を持ちます。 <code>struct</code>で定義されたデータ型は、それぞれのインスタンスが固有の属性を持ちます。例えば、次のようにして新しい<code>Point</code>インスタンスを作成できます: :<syntaxhighlight lang=julia> p = Point(3.0, 4.0) </syntaxhighlight> このコードでは、<code>Point</code>型の新しいインスタンス<code>p</code>を作成し、その<code>x</code>属性には<code>3.0</code>、<code>y</code>属性には<code>4.0</code>が格納されます。 <code>struct</code>を使用することで、関連するデータをひとまとめにし、独自のデータ型を定義することができます。これにより、コードの構造がより明確になり、再利用性が向上します。 ===== structとメソッド ===== Juliaにおいて、<code>struct</code>とメソッドは密接に関連しています。<code>struct</code>で定義されたデータ型には、そのデータ型に関する操作を実行するためのメソッドを定義することができます。 たとえば、先ほどの<code>Point</code>構造体を例に挙げると、この構造体には座標間の距離を計算するメソッドを定義できます。次のようにしてメソッドを定義します: :<syntaxhighlight lang=julia> struct Point x::Float64 y::Float64 end # Point型のインスタンス同士の距離を計算するメソッド function distance(p1::Point, p2::Point) dx = p1.x - p2.x dy = p1.y - p2.y return sqrt(dx^2 + dy^2) end </syntaxhighlight> この例では、<code>distance</code>という名前の関数を定義しています。この関数は、2つの<code>Point</code>型のインスタンスを受け取り、それらの間の距離を計算します。このように、関数の引数に型を指定することで、その関数は指定された型のインスタンスに対してのみ動作します。 このメソッドを使用すると、例えば次のようにして2つの座標間の距離を計算できます: :<syntaxhighlight lang=julia> p1 = Point(1.0, 2.0) p2 = Point(4.0, 6.0) println(distance(p1, p2)) # 出力: 5.0 </syntaxhighlight> この例では、2つの<code>Point</code>型のインスタンス<code>p1</code>と<code>p2</code>を作成し、それらの間の距離を<code>distance</code>メソッドで計算しています。 <code>struct</code>とメソッドを組み合わせることで、特定のデータ型に対する操作を容易に定義し、コードの再利用性を向上させることができます。 ===関数とメソッド=== この節では、Juliaにおける関数とメソッドの基本的な概念について説明します。Juliaでは、関数は特定の処理を実行するための一連の命令をまとめたものであり、メソッドは関数の一種で、オブジェクトの型によって振る舞いが異なる関数のことです。Juliaの関数は多重ディスパッチをサポートしており、同じ関数名でも引数の型や数によって異なるメソッドが呼び出されます。これにより、柔軟性の高いプログラミングが可能になります。関数やメソッドの定義は簡潔で直感的であり、関数型プログラミングやオブジェクト指向プログラミングの両方の概念を組み合わせています。また、Juliaでは高階関数やクロージャなどの機能も豊富に備わっており、これらを組み合わせることで、より複雑な処理をシンプルな形で記述することが可能です。この節では、Juliaにおける関数とメソッドの使い方や定義方法、そして多重ディスパッチがどのように動作するかなどについて詳しく解説します。 {{コラム|オブジェクト指向言語のメソッドとJuliaのメソッド|2=オブジェクト指向言語のメソッドとJuliaのメソッドにはいくつかの重要な違いがあります。 ;静的型付け vs 動的型付け: 一般的なオブジェクト指向言語(例えば、JavaやC++)では、メソッドは特定のクラスに属し、そのクラスのインスタンスに対してのみ呼び出すことができます。これに対して、Juliaのメソッドは静的なクラスや型に結び付いておらず、引数の型に基づいて動的に呼び出されます。 ;多重ディスパッチ: Juliaのメソッドは多重ディスパッチをサポートしており、同じ名前の関数が異なる引数の型に対して複数の実装を持つことができます。これにより、異なる型に対して適切な振る舞いをするメソッドが呼び出されます。一方、多くのオブジェクト指向言語では、メソッドのオーバーロードは引数の数や型によってのみ行われ、動的ディスパッチが制限されています。 ;関数との統一性: Juliaでは、関数もメソッドも同じように定義されます。つまり、関数とメソッドの違いはほとんどありません。これにより、Juliaでは関数型プログラミングとオブジェクト指向プログラミングの両方の概念を自然に組み合わせることができます。 ;拡張性と柔軟性: Juliaのメソッドはオープンであり、既存の型やライブラリに新しいメソッドを追加することができます。これにより、外部ライブラリやプログラムを変更せずに新しい機能を追加することが容易になります。一方、多くのオブジェクト指向言語では、既存のクラスの拡張やメソッドの追加が制限される場合があります。 Juliaのメソッドは、これらの特性により、静的なオブジェクト指向言語とは異なる柔軟性と拡張性を提供しています。 }} ==== 関数とは? ==== 関数は、入力値を受け取り、それらを処理し、結果を出力する手続きや操作を指します。プログラミングにおいて、関数は再利用可能で独立したコードブロックを表し、特定のタスクや計算を実行するために使用されます。関数は、プログラムの構造化や効率的なコードの記述、処理の分割と抽象化を可能にします。 関数は、次のような特性を持つことがあります: ;入力 (引数): 関数は、1つ以上の入力を受け取ることができます。これらの入力は、関数が実行される際に処理されるデータや情報です。 ;処理: 関数は、受け取った入力を処理し、特定のアルゴリズムや手順に従って計算や操作を行います。 ;出力 (戻り値): 関数は、処理の結果として1つ以上の値を返すことがあります。これらの値は、関数が呼び出されたコードに返され、その後の処理に使用されることがあります。 ;再利用性: 関数は、複数の箇所で再利用することができます。同じ処理を複数の場所で実行する必要がある場合や、特定の機能を共通化する場合に便利です。 ;分割と抽象化: 関数は、プログラムを小さな部分に分割し、各部分を独立して扱うことができます。これにより、プログラム全体の複雑さを減らし、理解やメンテナンスを容易にします。 関数は、プログラム言語やフレームワークによって異なる構文や機能を持つことがありますが、基本的な概念と目的はほぼ同じです。 ==== 関数の定義と呼び出し ==== 関数の定義と呼び出しは、Juliaにおいて非常にシンプルで直感的です。以下に、基本的な方法を示します。 ===== 関数の定義 ===== Juliaでは、関数は <code>function</code> キーワードを使って定義されます。関数が1つの式で表される場合、短い形式の定義も可能です。 # 通常の定義: :<syntaxhighlight lang=julia> function greet(name) println("Hello, $name!") end </syntaxhighlight> # 短い形式の定義: :<syntaxhighlight lang=julia> greet(name) = println("Hello, $name!") </syntaxhighlight> ====== 関数定義の構文 ====== Juliaにおける基本的な関数定義の構文は以下の通りです。 :<syntaxhighlight lang=julia> function 関数名(パラメータ1, パラメータ2, ...) 関数本体 end </syntaxhighlight> または、短縮形として以下のように書くこともできます。 :<syntaxhighlight lang=julia> 関数名(パラメータ1, パラメータ2, ...) = 関数本体 </syntaxhighlight> これらの構文について詳細に説明します。 * <code>function</code>: 関数定義を開始するキーワードです。 * <code>関数名</code>: 定義する関数の名前です。関数名はアルファベットで始まり、数字やアンダースコア <code>_</code> を含むことができます。 * <code>(パラメータ1, パラメータ2, ...)</code>: 関数が受け取る引数のリストです。各パラメータは関数内で使用されます。パラメータの型を指定することもできますが、Juliaは動的型付け言語なので、通常は型の指定は不要です。 * <code>関数本体</code>: 関数が実行する処理を記述したコードブロックです。この部分には、関数が行う計算や操作の詳細が含まれます。 * <code>end</code>: 関数定義の終了を示すキーワードです。関数本体の終わりを示します。 * <code>戻り値</code>: 関数が返す値です。<code>return</code> キーワードの後に指定します。 <code>function</code> キーワードと <code>end</code> キーワードを使用して関数を定義する場合、<code>end</code> の直前に <code>return</code> を使用して戻り値を指定します。短縮形の構文では、<code>return</code> キーワードは省略され、関数本体の最後の式の値が自動的に戻り値となります。 ===== 関数の戻り値 ===== 関数の戻り値は、関数が処理を実行した後に呼び出し元に返される値です。Juliaでは、関数が値を返す際に <code>return</code> キーワードを使用しますが、<code>return</code> を明示的に書かなくても、関数の最後に評価された式が自動的に戻り値となります。 以下に、関数の戻り値の定義方法と呼び出し方の例を示します。 ====== 戻り値の定義方法 ====== :<syntaxhighlight lang=julia> function add(x, y) return x + y # xとyの合計を返す end </syntaxhighlight> あるいは :<syntaxhighlight lang=julia> add(x, y) = x + y # xとyの合計を返す </syntaxhighlight> 上記の例では、<code>add</code> 関数が <code>x</code> と <code>y</code> の合計を返します。 ====== 戻り値の呼び出し方 ====== :<syntaxhighlight lang=julia> result = add(3, 5) println(result) # 出力: 8 </syntaxhighlight> <code>add(3, 5)</code> を呼び出すと、関数内で <code>x</code> と <code>y</code> を合計した結果が戻り値となり、<code>result</code> 変数に代入されます。その後、<code>println(result)</code> を使って結果が出力されます。 Juliaでは、関数の最後に評価された式が自動的に戻り値となるため、<code>return</code> キーワードを省略しても問題ありません。 ===== 関数の呼び出し ===== 関数の呼び出しは、関数名に引数を渡すことで行います。引数はカンマで区切られます。 :<syntaxhighlight lang=julia> greet("Alice") # Hello, Alice! </syntaxhighlight> ===== デフォルト引数 ===== Juliaでは、デフォルト引数を持つ関数を定義することができます。デフォルト引数を持つパラメータは、関数の呼び出し時に省略することができます。 :<syntaxhighlight lang=julia> function greet(name="World") println("Hello, $name!") end greet() # Hello, World! greet("Alice") # Hello, Alice! </syntaxhighlight> ===== キーワード引数 ===== また、キーワード引数を使って関数を定義することもできます。これにより、引数の意味を明確にすることができます。 :<syntaxhighlight lang=julia> function greet(; name="World") println("Hello, $name!") end greet() # Hello, World! greet(name="Alice") # Hello, Alice! </syntaxhighlight> Juliaの関数は非常に柔軟であり、様々な引数の形式をサポートしています。これにより、関数をより効果的に使用することができます。 ==== 関数の引数と戻り値の型推論 ==== Juliaは動的型付け言語であり、関数の引数や戻り値の型を明示的に指定する必要はありません。代わりに、Juliaの型推論機能が関数の引数や戻り値の型を自動的に推論します。 以下は、型推論が行われる例です。 :<syntaxhighlight lang=julia> function add(x, y) return x + y end result = add(3, 5) println(result) # 出力: 8 </syntaxhighlight> この例では、<code>add</code> 関数の引数 <code>x</code> と <code>y</code> は明示的な型注釈が与えられていませんが、Juliaは与えられた引数が整数であることを推論します。また、<code>add</code> 関数の戻り値の型も整数として推論されます。 この例では、<code>add</code> 関数はジェネリック関数として定義されています。ジェネリック関数は、特定の型に依存せず、異なる型の引数に対して動作するように設計されています。Juliaの型推論機能が関数の引数や戻り値の型を自動的に推論することで、ジェネリック関数が異なる型の引数に対して適切に動作することが可能になります。 {{See|[[#ジェネリック関数|ジェネリック関数]]}} ===== 型推論に失敗するケース ===== 以下は、型推論が失敗する可能性のあるコード例です。 :<syntaxhighlight lang=julia> # 型推論が失敗する例 function my_func(x) if x > 0 return "Positive" else return -1 end end result = my_func(5) # エラー:型の一貫性がないため、型推論が失敗する可能性があります </syntaxhighlight> この例では、<code>my_func</code>関数は引数 <code>x</code> を受け取りますが、条件に応じて文字列または整数を返します。このような場合、型推論は失敗し、Juliaは適切な型を推論できません。その結果、<code>my_func(5)</code>を呼び出すと、型の一貫性がないためエラーが発生する可能性があります。この問題を解決するには、関数の戻り値の型を明示的に指定するか、関数を再設計して型の一貫性を確保する必要があります。 ==== 多重ディスパッチ ==== 多重ディスパッチ(Multiple Dispatch)は、プログラミング言語において、関数の振る舞いを引数の型や個数によって動的に決定する機能です。通常のオブジェクト指向プログラミング言語では、メソッドの呼び出しは一般的にレシーバ(オブジェクト)の型に基づいて行われますが、多重ディスパッチでは、引数の型や個数に基づいてメソッドの呼び出しを解決します。 Juliaの多重ディスパッチは、関数が複数のシグネチャ(引数の型と個数の組み合わせ)を持ち、実行時に最適なシグネチャが選択されるという仕組みです。これにより、同じ関数名を使用して異なる引数型に対応した複数の実装を定義することができます。さらに、新しい型を定義するときに既存の関数に対して新しい実装を追加することも容易です。 多重ディスパッチは、静的な型付け言語や動的な型付け言語の両方で利用されますが、Juliaのような動的型付け言語では特に強力な機能として活用されています。多重ディスパッチにより、柔軟性と効率性を両立させながら、複雑なプログラムの記述や拡張が容易になります。 以下は、Juliaでの多重ディスパッチのコード例です。 :<syntaxhighlight lang=julia> # 関数 add の定義 function add(x::Int, y::Int) println("Integers are being added.") return x + y end function add(x::Float64, y::Float64) println("Floats are being added.") return x + y end function add(x::String, y::String) println("Strings are being concatenated.") return x * y end # 関数 add の呼び出し println(add(1, 2)) # Integers are being added. 3 println(add(3.5, 2.5)) # Floats are being added. 6.0 println(add("Hello, ", "world!")) # Strings are being concatenated. Hello, world! </syntaxhighlight> この例では、<code>add</code> 関数が整数型、浮動小数点数型、文字列型の引数を受け取り、それぞれの型に対応する振る舞いを定義しています。関数を呼び出す際には、引数の型に応じて適切な実装が選択されます。 多重ディスパッチは他のプログラミング言語では、多重定義(Overloading)あるいは多態性(Polymorphism)とも言われます。 ==== 可変引数 ==== 可変引数は、関数に可変長の引数を渡すための仕組みです。Juliaでは、関数の引数の最後に三点リーダー(<code>...</code>)を使って可変引数を指定します。これにより、関数呼び出し時に任意の数の引数を渡すことができます。 以下は、可変引数を持つ関数の例です。 :<syntaxhighlight lang=julia> # 可変引数を持つ関数の定義 function sum_values(x::Number, y::Number...) total = x for val in y total += val end return total end # 関数の呼び出し println(sum_values(1, 2, 3, 4)) # 出力: 10 println(sum_values(1, 2, 3, 4, 5)) # 出力: 15 </syntaxhighlight> この例では、<code>sum_values</code>関数は最初の引数 <code>x</code> と可変長の引数 <code>y</code> を受け取り、これらの値を合計して返します。<code>y</code> の部分には任意の数の引数が渡されることができます。 ==== 多値返し ==== 多値返しは、関数が複数の値を返すことを意味します。Juliaでは、タプルを使用して複数の値をまとめて返すことができます。以下は、多値返しの例です。 :<syntaxhighlight lang=julia> # 多値返しの関数の定義 function divide_remainder(x::Int, y::Int) quotient = div(x, y) # 商を計算 remainder = rem(x, y) # 余りを計算 return quotient, remainder # タプルとして複数の値を返す end # 関数の呼び出しと多値の受け取り result = divide_remainder(10, 3) println("Quotient:", result[1]) # 商を表示 println("Remainder:", result[2]) # 余りを表示 </syntaxhighlight> この例では、<code>divide_remainder</code>関数が2つの整数を受け取り、商と余りを計算してタプルとして返します。関数を呼び出した後、タプルの要素にはインデックスを使用してアクセスできます。 ==== 関数呼び出し時の配列展開 ==== Juliaでは、関数呼び出し時に配列を展開して、複数の引数として渡すことができます。これにより、関数が可変数の引数を取る場合や、複数の要素をまとめて関数に渡す場合に便利です。以下は、配列展開を使用した関数呼び出しの例です。 :<syntaxhighlight lang=julia> # 配列展開を使用した関数呼び出し function sum_of_three_numbers(a, b, c) return a + b + c end args = [1, 2, 3] result = sum_of_three_numbers(args...) # 配列を展開して関数に渡す println("Sum of three numbers:", result) # 出力: 6 </syntaxhighlight> この例では、<code>sum_of_three_numbers</code>関数が3つの引数を取り、それらの値の合計を返します。<code>args</code>という配列を定義し、その配列を<code>...</code>を使って関数呼び出し時に展開しています。これにより、配列の各要素が個別の引数として関数に渡されます。 ==== 無名関数 ==== 無名関数(Anonymous Function)は、名前を持たない関数のことです。通常、関数を定義する際には名前が指定されますが、無名関数は名前がなく、その場で定義されます。無名関数は、一般的に他の関数の引数として渡されたり、高階関数内で使用されたりします。Juliaでは、無名関数は<code>function</code>キーワードを使用せずに、簡潔に表現することができます。例えば、<code>x -> x^2</code>という式は、引数xに対してxの二乗を返す無名関数を表します。 以下は、Juliaで無名関数を使用したコード例です。 :<syntaxhighlight lang=julia> # 無名関数を定義して変数に代入する方法 square = x -> x^2 cube = x -> x^3 # 無名関数を直接呼び出して使用する方法 println(square(5)) # 出力: 25 println(cube(3)) # 出力: 27 # 無名関数の型 println(typeof(square)) # 出力: var"#1#2" println(typeof(cube)) # 出力: var"#3#4" # 高階関数内で無名関数を使用する例 function apply_function(f, value) return f(value) end println(apply_function(x -> x * 2, 4)) # 出力: 8 </syntaxhighlight> : *このコードでは、無名関数を定義して変数に代入し、また無名関数を直接呼び出して使用する方法が示されています。<code>square</code>と<code>cube</code>という変数にそれぞれ二乗を計算する関数と三乗を計算する関数が代入されています。 : *次に、<code>apply_function</code>という高階関数が定義され、その中で無名関数が使用されています。<code>apply_function</code>は、与えられた関数 <code>f</code> を引数 <code>value</code> に適用してその結果を返します。 : *それぞれの無名関数は <code>var"#n#m"</code> の形式の型を持っています。これは、Juliaが無名関数を内部的にユニークに識別するために使用される名前です。 : このように、無名関数は関数を直接引数として渡したり、変数に代入したりする場合などに便利に使用されます。 Juliaでは、無名関数を定義してすぐに実行することができます。これを即時関数と呼びます。以下はその例です。 :<syntaxhighlight lang=julia> # 無名関数を即時実行する例 result = (x -> x^2)(5) println(result) # 出力: 25 </syntaxhighlight> このコードでは、<code>(x -> x^2)</code>が無名関数であり、その後の<code>(5)</code>でその無名関数がすぐに実行されています。その結果、<code>result</code>には<code>5^2</code>である<code>25</code>が代入されます。 Juliaでは、無名関数をラムダ式または匿名関数と呼びます。そのため、上記の例はラムダ式を使って無名関数を定義し、即時に実行しています。 ==== do ブロック ==== Juliaにおける<code>do</code>ブロックは、関数やマクロの呼び出し時に、その関数やマクロに対してブロックを渡すための構文です。通常、関数やマクロに対して1つ以上の式を渡す必要がある場合に使用されます。<code>do</code>ブロックは、関数型プログラミングやコールバック関数の定義などの場面でよく使用されます。 具体的には、以下のような形式で使用されます: :<syntaxhighlight lang=julia> function_with_do_block(args...) do # ブロック内のコード end </syntaxhighlight> または、マクロの場合: :<syntaxhighlight lang=julia> @macro_with_do_block(args...) do # ブロック内のコード end </syntaxhighlight> <code>do</code>ブロック内には、任意のコードが含まれることができます。このブロック内のコードは、関数やマクロの本体内で参照されることがあります。<code>do</code>ブロックは、関数の引数として渡すことができる無名関数やクロージャを定義するのに便利です。 <code>do</code>ブロックは、イテレータやジェネレータと組み合わせて使用されることがよくあります。 この場合、<code>do</code>ブロック内のコードは、イテレーション中に実行される処理を定義します。 例えば、次のコードは配列の各要素を2倍にする例です。 :<syntaxhighlight lang=julia> arr = [1, 2, 3, 4, 5] result = map(arr) do x 2 * x end </syntaxhighlight> この例では、<code>map</code>関数に<code>do</code>ブロックを使用して、各要素を2倍にする無名の関数を定義しています。この無名の関数は、<code>x</code>という引数を取り、その引数を2倍にして返します。<code>map</code>関数はこの無名の関数を配列の各要素に適用し、結果を<code>result</code>変数に格納します。 <code>do</code>ブロックを使用することで、コードがより簡潔で読みやすくなり、関数をより柔軟に使用することができます。 Juliaでは<code>do</code>ブロックを使用して、柔軟で拡張可能なコードを書くことができます。 ==== コードブロック ==== コードブロックは、プログラム内で複数の文をまとめて実行するための構造です。Juliaでは、<code>begin</code>キーワードと<code>end</code>キーワードで囲んだ部分がコードブロックとなります。これにより、複数の文を1つのまとまりとして扱うことができます。コードブロックの最後の式の値が、そのブロック全体の値となります。コードブロックは、関数の中でのみ使用するのではなく、任意のスコープ内で使用することができます。 以下は、Juliaでのコードブロックの使用例です。 :<syntaxhighlight lang=julia> # begin-endを使ったコードブロック result = begin x = 10 y = 20 x + y end println(result) # 出力: 30 # カッコでくくったコードブロック result = (x = 10; y = 20; x + y) println(result) # 出力: 30 </syntaxhighlight> これらの例では、<code>begin</code>キーワードと<code>end</code>キーワード、またはカッコでくくった部分がコードブロックとして機能し、その中に複数の文が含まれています。最後の式である<code>x + y</code>の結果がそれぞれのコードブロック全体の値となります。 ==== 高階関数 ==== 高階関数とは、他の関数を引数として受け取るか、または関数を戻り値として返す関数のことです。具体的には、<code>map</code>、<code>reduce</code>、<code>filter</code> などの関数がその代表的な例です。 ; map : <code>map</code> 関数は、与えられた関数をリストの各要素に適用し、その結果を新しいリストとして返します。 :<syntaxhighlight lang=julia> # 配列の各要素を2倍にする array = [1, 2, 3, 4, 5] doubled_array = map(x -> x * 2, array) println(doubled_array) # 出力: [2, 4, 6, 8, 10] </syntaxhighlight> ; filter : <code>filter</code> 関数は、与えられた述語関数(条件を満たすかどうかを返す関数)によって評価される条件を満たす要素のみを含む新しいリストを返します。 :<syntaxhighlight lang=julia> # 偶数のみを抽出する even_array = filter(x -> x % 2 == 0, array) println(even_array) # 出力: [2, 4] </syntaxhighlight> ; reduce : <code>reduce</code> 関数は、与えられた関数を使用してリストの各要素を結合し、単一の値を生成します。 :<syntaxhighlight lang=julia> # 配列の要素の合計を計算する sum_array = reduce(+, array) println(sum_array) # 出力: 15 </syntaxhighlight> これらの関数は、コードの簡潔さと可読性を向上させ、同じような操作を繰り返し実行する必要性を軽減します。 ==== 高階関数の内包表記による置き換え ==== 内包表記を使用して同じロジックを表現することができます。以下に、<code>map</code>、<code>filter</code>、<code>reduce</code> をそれぞれ内包表記で実装した例を示します。 ; map相当の内包表記 :<syntaxhighlight lang=julia> array = [1, 2, 3, 4, 5] doubled_array = [x * 2 for x in array] println(doubled_array) # 出力: [2, 4, 6, 8, 10] </syntaxhighlight> ; filter相当の内包表記 :<syntaxhighlight lang=julia> even_array = [x for x in array if x % 2 == 0] println(even_array) # 出力: [2, 4] </syntaxhighlight> ; reduce相当の内包表記 :<syntaxhighlight lang=julia> sum_array = sum([x for x in array]) println(sum_array) # 出力: 15 </syntaxhighlight> 内包表記は、関数の呼び出しを減らし、コードをより簡潔にするのに役立ちます。このような機能は、Juliaの柔軟性と表現力の一部であり、より簡潔なコードを書くための強力なツールとなります。 :内包表記については、項を改めて執筆予定です。 ==== 再帰的呼び出し ==== 再帰的呼び出しは、関数が自分自身を呼び出すことを指します。これは問題を解くのに非常に強力な手法であり、特に問題が再帰的な性質を持つ場合に有用です。Juliaでは、再帰的呼び出しは通常の関数呼び出しと同じように行われますが、適切な終了条件を設定することが重要です。典型的な例としては、階乗の計算や再帰的なデータ構造の操作があります。 :<syntaxhighlight lang=julia> function factorial(n) if n == 0 || n == 1 return 1 else return n * factorial(n - 1) end end println(factorial(5)) # 120 </syntaxhighlight> この例では、<code>factorial</code>関数が自分自身を呼び出しています。終了条件として、<code>n</code>が0または1の場合には1を返し、それ以外の場合には<code>n</code>と<code>factorial(n - 1)</code>の積を返します。これにより、5の階乗が計算されます。 ===== 末尾再帰 ===== 末尾再帰(tail recursion)は、再帰関数が自己呼び出しの最後の操作として再帰を行う形式を指します。末尾再帰の特徴は、再帰呼び出しが関数の最後に位置するため、新しいスタックフレームが生成されることなく、再帰の効率が向上することです。これにより、再帰が深くなってもスタックオーバーフローのリスクが軽減されます。 Juliaでは、末尾再帰最適化が可能であり、再帰関数が末尾再帰の形式であれば、最適化が自動的に適用されます。つまり、末尾再帰を使った関数は、非常に大きな入力に対しても効率的に動作します。 :<syntaxhighlight lang=julia> function factorial(n, acc=1) if n == 0 return acc else return factorial(n - 1, n * acc) end end println(factorial(5)) # 120 </syntaxhighlight> この例では、<code>factorial</code>関数が末尾再帰の形式で実装されています。再帰呼び出しが関数の最後の操作として行われており、最適化されたバージョンの末尾再帰として実行されます。 ==== クロージャ ==== クロージャは、関数とその関数が参照する環境(変数や関数など)を包み込んだものです。これにより、外部変数や外部関数を内部の関数が利用できるようになります。クロージャは、特定の状態を保持し、それを利用して動作する関数を定義する場合に便利です。 :<syntaxhighlight lang=julia> function make_multiplier(x) return y -> x * y end mul_by_5 = make_multiplier(5) println(mul_by_5(3)) # 15 </syntaxhighlight> この例では、<code>make_multiplier</code>関数がクロージャを生成します。<code>make_multiplier</code>関数は、<code>x</code>を引数として受け取り、無名関数<code>y -> x * y</code>を返します。この無名関数は外部の変数<code>x</code>を参照しており、その値を保持しています。<code>make_multiplier(5)</code>が返す関数を<code>mul_by_5</code>に割り当てて呼び出すことで、外部変数<code>x</code>の値が5であるクロージャが作成され、引数に渡された値との乗算が行われます。 ==== カリー化 ==== カリー化(currying)は、複数の引数を持つ関数を、1つの引数を受け取る関数の連鎖に変換するプロセスです。具体的には、複数の引数を持つ関数を部分適用して新しい関数を生成することで、1つの引数を受け取る関数に変換します。 :<syntaxhighlight lang=julia> function add(x, y) return x + y end curried_add = x -> y -> add(x, y) add_five = curried_add(5) println(add_five(3)) # 8 </syntaxhighlight> この例では、<code>add</code>関数が2つの引数を受け取る関数です。<code>curried_add</code>関数は、<code>add</code>関数をカリー化して1つの引数を受け取る関数を返します。このカリー化された関数を使って、新しい関数<code>add_five</code>を生成し、それに引数3を与えて呼び出すことで、最終的な結果を得ます。 ==== ジェネリック関数 ==== ジェネリック関数は、複数のデータ型に対して同じ名前の関数を定義し、それぞれのデータ型に応じた動作を行う仕組みです。これにより、型に依存しない汎用的な関数を作成することができます。Juliaでは、関数の多重ディスパッチを利用してジェネリック関数を定義します。 :<syntaxhighlight lang=julia> function myfunc(x::Int) println("This is an integer:", x) end function myfunc(x::Float64) println("This is a float:", x) end myfunc(5) # This is an integer: 5 myfunc(3.14) # This is a float: 3.14 </syntaxhighlight> この例では、<code>myfunc</code>という名前のジェネリック関数が定義されています。この関数は、整数型と浮動小数点数型の引数を取る2つのバージョンがあります。引数の型に応じて、適切な関数が呼び出されます。 Juliaの場合、[[#型アノテーション|型アノテーション]]を明示的に行うことが少ないので、無自覚にジェネリック関数を定義していることが多いです。 ====ジェネレーター==== ジェネレータ(Generators)は、遅延評価を利用して要素を動的に生成するための機能です。ジェネレータは、通常の関数と同様に定義されますが、<code>yield</code>キーワードを使用して要素を生成します。ジェネレータは、一度にすべての要素を生成せず、必要に応じて要素を生成します。これにより、大規模なデータセットを効率的に処理することができます。 以下は、ジェネレータの基本的な例です: :<syntaxhighlight lang=julia> function mygenerator() for i in 1:5 yield(i) end end # ジェネレータを作成 gen = mygenerator() # ジェネレータから要素を取得 for x in gen println(x) end </syntaxhighlight> この例では、<code>mygenerator</code>関数がジェネレータを定義し、1から5までの数値を順番に返します。ジェネレータは、<code>for</code>ループなどのイテレーション構造で使用されることが一般的です。ジェネレータは遅延評価を行うため、大規模なデータセットを扱う際に非常に便利です。 ====イテレーター==== Juliaのイテレータ(Iterators)は、データのシーケンスを反復処理するための機能です。イテレータは、特定のデータ構造(配列、範囲、コレクションなど)の要素に順番にアクセスする方法を提供します。これにより、大きなデータセットや無限のシーケンスを効率的に扱うことができます。 Juliaのイテレータは、遅延評価(Lazy evaluation)の概念を利用しており、イテレーションが必要な時点でのみ要素が計算されます。これにより、メモリや計算リソースを節約しつつ、必要な要素に順番にアクセスできます。 さまざまなイテレータ関数が提供されており、これらを組み合わせることで、データのフィルタリング、写像、集約、結合などの操作を柔軟に実行できます。イテレータは、Juliaのコードをより効率的かつ簡潔にするための重要な要素です。 ;ユーザー定義のイテレータの例 :<syntaxhighlight lang=julia> # 素数かどうかを判定する関数 function is_prime(n::Int) if n <= 1 return false elseif n <= 3 return true elseif n % 2 == 0 || n % 3 == 0 return false else i = 5 while i * i <= n if n % i == 0 || n % (i + 2) == 0 return false end i += 6 end return true end end struct PrimeIter current::Int end function Base.iterate(iter::PrimeIter, state=2) while true if is_prime(state) return (state, state + 1) end state += 1 end end # PrimeIterで10までの素数をイテレート for prime in PrimeIter(2) if prime > 10 break end println(prime) end </syntaxhighlight> このコードは、Juliaで素数を判定する関数 <code>is_prime</code> と、素数を返すイテレータ <code>PrimeIter</code> を定義しています。以下に、それぞれの部分の解説を行います。 ; is_prime * <code>is_prime(n::Int)</code> 関数は、与えられた整数 <code>n</code> が素数かどうかを判定します。 * 最初の条件文では、<code>n</code> が1以下の場合は素数ではないとして <code>false</code> を返します。 * 次の条件文では、<code>n</code> が3以下の場合は素数であるとして <code>true</code> を返します。 * その後の条件文では、<code>n</code> が2または3で割り切れる場合は素数ではないとして <code>false</code> を返します。 * これらの条件に該当しない場合、<code>n</code> が素数であるかどうかを確認するためのループが行われます。 * ループでは、6k±1 (ただし、kは自然数) の形を持つ数値に対して素数かどうかを判定します。 * <code>i</code> を初期値5で始め、<code>i * i</code> が <code>n</code> より大きくなるまでループします。 * ループ内で、<code>n</code> が <code>i</code> または <code>i + 2</code> で割り切れる場合は素数ではないとして <code>false</code> を返します。 * ループを抜けた場合、<code>n</code> は素数であると判断され、<code>true</code> を返します。 ; PrimeIter * <code>PrimeIter</code> は、素数を返すイテレータを定義するための型です。<code>current</code> フィールドは、現在の値を保持します。 * <code>Base.iterate(iter::PrimeIter, state=2)</code> 関数は、<code>PrimeIter</code> 型のオブジェクトに対して呼び出され、イテレーションを行います。 * ループ内では、<code>state</code> を素数判定関数 <code>is_prime</code> に渡して、素数かどうかを確認します。 * <code>is_prime(state)</code> が <code>true</code> を返す場合、その <code>state</code> を次の素数として返します。 * 素数でない場合は <code>state</code> をインクリメントして次の数に移ります。 ; 使用例 * <code>for</code> ループを使用して、<code>PrimeIter</code> で2から始まる素数を取得します。 * ループ内で、取得した素数が10を超える場合はループを終了します。 * ループ内で素数を出力します。 このコードを実行すると、2から7までの素数が順番に出力されます。 ===ファイル操作とモジュール=== ファイルの読み書きやモジュールの作成・使用方法を学びます。外部ファイルからデータを読み込んだり、結果をファイルに書き出したりすることは、実際のプログラミングで非常に重要です。また、モジュールを使用することで、関連する関数や型をまとめて効果的に管理し、再利用可能なコードを作成することができます。 ==== ファイル入出力 ==== Juliaでファイルの入出力を行うためには、標準のファイル操作関数やパッケージを使用します。以下に、基本的なファイルの読み書き操作の方法を示します。 ===== ファイルの読み込み===== :<syntaxhighlight lang=julia> # ファイルを読み込みモードで開く file = open("input.txt", "r") # ファイルから1行ずつ読み込む for line in eachline(file) println(line) end # ファイルを閉じる close(file) </syntaxhighlight> =====ファイルへの書き込み===== :<syntaxhighlight lang=julia> # ファイルを書き込みモードで開く file = open("output.txt", "w") # ファイルにテキストを書き込む println(file, "Hello, world!") println(file, "This is a new line.") # ファイルを閉じる close(file) </syntaxhighlight> =====CSVファイルの読み書き(CSV.jlパッケージを使用)===== :<syntaxhighlight lang=julia> using CSV # CSVファイルを読み込む data = CSV.read("data.csv") # CSVファイルに書き込む CSV.write("output.csv", data) </syntaxhighlight> =====JSONファイルの読み書き(JSON.jlパッケージを使用)===== :<syntaxhighlight lang=julia> using JSON # JSONファイルを読み込む data = JSON.parsefile("data.json") # JSONファイルに書き込む JSON.print(data, "output.json") </syntaxhighlight> これらは、Juliaでファイルの入出力を行う基本的な方法の一部です。 ファイルの読み込みや書き込み操作を行う際には、適切なエラーハンドリングを行うことも重要です。 ===== ユースケース ===== JuliaのファイルI/Oは、さまざまなユースケースで活用されます。以下に、一般的なユースケースの例を示します。 ;データの読み込みと解析: :テキストファイルやCSVファイルからデータを読み込み、それを解析してデータ処理や分析を行います。たとえば、統計データやログファイルからデータを読み取り、集計や可視化を行うことがあります。 ;データの書き込み: :プログラムの出力や結果をファイルに書き込むことがあります。たとえば、シミュレーションの結果や処理のログをファイルに保存します。 ;設定ファイルの読み書き: :アプリケーションの設定や構成をファイルに保存し、プログラムの実行時にそれを読み込むことがあります。設定ファイルは、プログラムの振る舞いや動作をカスタマイズするために使用されます。 ;外部データのインポートとエクスポート: :外部のデータや他のアプリケーションで生成されたデータを読み込み、Juliaのプログラムで使用することがあります。また、Juliaで処理したデータを他の形式にエクスポートすることもあります。 ;ファイルの操作と管理: :ファイルやディレクトリの作成、コピー、移動、削除など、ファイルシステムの操作を行うことがあります。これにより、プログラムがファイルシステム上でのデータの管理を行うことができます。 ;大規模データの処理: :大規模なデータセットをファイルから読み込み、分割処理や並列処理を行って効率的に処理することがあります。Juliaの並列処理機能を活用して、大規模なデータセットを効率的に処理することができます。 これらのユースケースは、JuliaのファイルI/O機能が広く活用されている例です。Juliaの柔軟なファイルI/O機能を活用することで、さまざまなデータ処理やファイル操作を効率的に行うことができます。 ===== ベストプラクティス ===== Juliaでファイルの入出力(I/O)を行う際のベストプラクティスには、以下のようなものがあります。 # エラーハンドリング: ファイルの読み込みや書き込み時には、エラーハンドリングを適切に行うことが重要です。ファイルが存在しない、アクセス権限がない、またはファイルが壊れている場合など、さまざまなエラーが発生する可能性があります。<code>try-catch</code>ブロックを使用してエラーをキャッチし、適切に処理することが推奨されます。 # ファイルの自動クローズ: ファイルを使用したら必ずクローズするようにしましょう。ファイルを開いた後は、作業が完了したら<code>close()</code>関数を使用してファイルを明示的に閉じることが重要です。ファイルを閉じないままにしておくと、リソースがリークする可能性があります。 # ファイルパスの管理: ファイルパスの管理には注意が必要です。ファイルパスはプラットフォームに依存することがありますので、<code>joinpath()</code>関数を使用してプラットフォームに依存しない方法でファイルパスを構築することをお勧めします。 # テキストファイルとバイナリファイルの区別: テキストファイルとバイナリファイルでは、データの扱い方が異なります。テキストファイルの場合は、<code>readline()</code>や<code>readlines()</code>関数を使用して行ごとに読み込みます。バイナリファイルの場合は、<code>read()</code>関数を使用してバイト単位で読み込みます。 # 高レベルなファイル操作関数の使用: 高レベルなファイル操作関数を使用すると、簡潔で効率的なコードを記述することができます。例えば、CSV.jlやJSON.jlなどのパッケージを使用すると、CSVファイルやJSONファイルの読み書きを簡単に行うことができます。 これらのベストプラクティスに従うことで、Juliaでのファイルの入出力操作をより安全で効率的に行うことができます。 === モジュール === Juliaのモジュールは、コードをまとめて管理するための機構です。以下は、Juliaのモジュールに関する主なポイントです: # 名前空間の導入: 各モジュールは新しいグローバルスコープを導入し、モジュール内の名前が外部と競合しないようにします。これにより、異なるモジュール間で同じ名前を使用することができます。 # 名前空間の管理: モジュールは、詳細な名前空間の管理を可能にします。モジュールはエクスポートする名前のセットを定義し、他のモジュールから名前をインポートできます。 # プリコンパイル: モジュールはプリコンパイルして高速な読み込みを可能にし、実行時の初期化コードを含めることができます。 # ファイルの組織化: モジュールは通常、ファイルにまとめて管理されますが、ファイル名とモジュール名は一般的には関連付けられていません。1つのモジュールに複数のファイルが含まれる場合や、逆もあります。 # 慣例: モジュールの本体をインデントしないことが推奨されています。モジュール名には'''UpperCamelCase'''が使用され、モジュールが類似の名前を含む場合は名前の衝突を避けるために複数形が使用されることがあります。 Juliaの名前空間管理には、修飾名、エクスポートリスト、特定の識別子のインポートやエクスポートなどの概念が含まれます: * 修飾名: グローバルスコープの関数、変数、型の名前はすべてモジュールに属します。修飾名を使用すると、親モジュールの外部でこれらの名前を参照できます。 * エクスポートリスト: 名前は、<code>export</code>を使用してモジュールのエクスポートリストに追加できます。これらの名前は、モジュールを使用する際にインポートされます。エクスポートリストはAPIを整理するのに役立ちますが、Juliaはモジュールの内部を完全に隠す機能を提供していません。 * 単独の <code>using</code> と <code>import</code>: <code>using ModuleName</code> は、モジュールに関連するコードを読み込み、モジュール名とエクスポートされた要素をグローバル名前空間に導入します。 <code>import .ModuleName</code> は、モジュール名だけをスコープに導入します。複数の <code>using</code> と <code>import</code> 文をカンマ区切りの式で組み合わせることができます。 * <code>as</code> を使った名前の変更: <code>import</code> や <code>using</code> で導入された識別子は、 <code>as</code> キーワードを使用して名前を変更できます。これは、名前の競合を回避したり、名前を短縮したりするために役立ちます。 * 名前の競合の処理: 同じ名前をエクスポートする複数のパッケージが存在する場合、競合が発生する可能性があります。解決策には、修飾名を使用する、識別子の名前を変更する、あるいは一つのモジュールから別のモジュールへの識別子のインポートなどがあります。 Juliaのモジュールシステムは、柔軟性があり、効果的な名前空間管理機能を提供しています。 ==== モジュールの定義と使用 ==== Juliaでのモジュールの定義と使用の例を示します。 :<syntaxhighlight lang=julia> # モジュールの定義 module MyModule # エクスポートする関数 export my_function # 関数の定義 function my_function(x) return x^2 end end # モジュールの使用 # モジュールをロード using .MyModule # モジュール内の関数を呼び出す result = MyModule.my_function(3) println(result) # 出力: 9 </syntaxhighlight> この例では、<code>MyModule</code> という名前のモジュールを定義し、その中で <code>my_function</code> という関数を定義しています。その後、<code>using .MyModule</code> を使ってモジュールをロードし、<code>MyModule.my_function</code> を呼び出しています。 ==== ドキュメント文字列(docstrings) ==== Juliaでは、関数やモジュールのドキュメントを記述するために、ドキュメント文字列(docstrings)を使用します。 これらのdocstringsは、関数やモジュールの先頭に配置され、関数の機能や引数、返り値、使用例などを説明します。 以下は、Juliaのドキュメントの例です。 :<syntaxhighlight lang=julia> """ add(x, y) `x`と`y`の和を計算する関数。 # 引数 - `x`: 加算する値の1つ。 - `y`: 加算する値のもう1つ。 # 戻り値 和の値を返す。 """ function add(x, y) return x + y end </syntaxhighlight> この例では、<code>MyModule</code> という名前のモジュールを定義し、その中で <code>my_function</code> という関数を定義しています。その後、<code>using .MyModule</code> を使ってモジュールをロードし、このようにして、関数の定義の直前に、3連のダブルクォートで囲まれたドキュメント文字列を記述します。これにより、関数<code>add</code>の使い方や機能が明確に説明されます。 ドキュメント文字列は、MarkdownやLaTeXの一部の書式をサポートし、より見やすく、読みやすいドキュメントを提供します。JuliaのREPLやヘルプシステムは、これらのドキュメント文字列を使用して関数やモジュールのドキュメントを表示します。 ===== ドキュメントの準備と生成 ===== Documenter.jlは、Juliaのドキュメント作成のためのツールです。MarkdownファイルとJuliaのインラインdocstringsを組み合わせて、1つの相互にリンクされたドキュメントにまとめます。 ====== インストール ====== Juliaのパッケージマネージャーを使用してDocumenter.jlをインストールします。 :<syntaxhighlight lang=julia> using Pkg Pkg.add("Documenter") </syntaxhighlight> ====== フォルダー構造のセットアップ ====== Documenterが期待する基本構造を生成するために、DocumenterToolsパッケージの<code>DocumenterTools.generate</code>関数を使用できます。 まず、ドキュメント化するJuliaモジュールが必要です。これは、PkgDev.generateで生成されたパッケージまたはJuliaのLOAD_PATHでアクセス可能な単一の.jlスクリプトである必要があります。このガイドでは、次のディレクトリレイアウトを持つExample.jlというパッケージを使用します。 :<syntaxhighlight lang=text> Example/ └ src/ └ Example.jl </syntaxhighlight> ドキュメントを格納する場所を決定する必要があります。このパッケージのトップレベルにdocs/という名前のフォルダーを使用することが推奨されます。 :<syntaxhighlight lang=text> Example/ ├ src/ │└ Example.jl └ docs/ └ ... </syntaxhighlight> docs/フォルダー内には、2つの要素を追加する必要があります。Markdownファイルが含まれ、完成したドキュメントの構築に使用されるJuliaスクリプトです。 :<syntaxhighlight lang=text> Example/ ├ src/ │└ Example.jl ├ docs/ │└ ... └ make.jl </syntaxhighlight> ====== 空のドキュメントのビルド ====== docs/ディレクトリがセットアップされたので、最初のドキュメントをビルドします。この時点では単一の空のファイルですが、後で追加していきます。 make.jlファイルに以下を追加します。 :<syntaxhighlight lang=julia> using Documenter, Example makedocs(sitename="My Documentation") </syntaxhighlight> これにより、Documenterがインストールされていることと、Example.jlパッケージがJuliaによって見つかることが前提となります。 次に、src/ディレクトリにindex.mdファイルを追加します。 その後、docs/ディレクトリから次のコマンドを実行します。 :<syntaxhighlight lang=shell> $ julia --project make.jl </syntaxhighlight> これにより、build/ディレクトリが生成されます。 ====== ドキュメント文字列の追加 ====== 次に、Exampleモジュールで定義されたドキュメント文字列をindex.mdファイルに組み込みます。 :<syntaxhighlight lang=julia> module Example export func """ func(x) 数値 `x` の2倍に1を加えたものを返します。 """ func(x) = 2x + 1 </syntaxhighlight> src/index.mdファイルに次を追加します。 :<syntaxhighlight lang=md> # Example.jl Documentation ```@docs func(x) </syntaxhighlight> ====== ドキュメントの生成 ====== make.jlファイルを再実行すると、build/index.mdにExample.func(x)のドキュメント文字列が表示されるはずです。 ===データ解析と可視化=== DataFrames.jlやPlots.jlなどのパッケージを使ってデータ解析や可視化を行う方法を学びます。データ解析と可視化はJuliaの強力な機能の一つであり、これらのパッケージを使用することでデータを効果的に分析し、可視化することができます。データのパターンやトレンドを発見し、洞察を得るために必要なスキルを身につけましょう。 == 中級編 == === パッケージの管理 === Juliaのパッケージは、Juliaプログラミング言語の機能や機能拡張を提供するためのコードやリソースの集合体です。これらのパッケージは、Juliaの機能を拡張し、特定のタスクやアプリケーションの開発を支援します。Juliaのパッケージは、関数、型、モジュール、データセット、プログラム、およびその他のリソースを提供することがあります。 一般的な用途には、データ解析、機械学習、科学計算、グラフィカルユーザーインターフェイス(GUI)、ウェブアプリケーション開発などが含まれます。これらのパッケージは、Juliaの豊富なエコシステムの一部であり、コミュニティによって開発、管理されています。 Juliaのパッケージ管理システムである'''Pkg'''を使用することで、Juliaの機能を拡張するためのパッケージのインストールや管理を行うことができます。パッケージは、さまざまなタスクやアプリケーションの開発に役立ちます。このセクションでは、Pkgを使用してパッケージを効果的に管理する方法について説明します。 ==== パッケージのインストール ==== 新しいパッケージをインストールするには、以下の手順に従います。 # JuliaのREPL(Read-Eval-Print Loop)を開きます。 # <code>]</code> を入力して、'''Pkgモード'''に切り替えます。 #:<syntaxhighlight lang=julia-repl> (@v1.10) pkg> _ </syntaxhighlight> #:<code>add PackageName</code> を入力して、必要なパッケージをインストールします。 #:たとえば、DataFramesパッケージをインストールするには、以下のように入力します。 #*<syntaxhighlight lang=julia-repl> (@v1.10) pkg> add DataFrames </syntaxhighlight> ==== パッケージのアップデート ==== インストールされているパッケージを最新のバージョンにアップデートするには、以下の手順に従います。 <code>update</code> コマンドを入力して、すべてのパッケージをアップデートします。 :*<syntaxhighlight lang=julia-repl> (@v1.10) pkg> update </syntaxhighlight> ====パッケージの削除==== 不要なパッケージを削除するには、以下の手順に従います。 <code>rm PackageName</code> を入力して、削除したいパッケージを指定します。 :*<syntaxhighlight lang=julia-repl> (@v1.10) pkg> rm PackageName </syntaxhighlight> ==== パッケージの検索 ==== 利用可能なパッケージを検索するには、以下の手順に従います。 <code>search Keyword</code> を入力して、キーワードに一致するパッケージを検索します。 :*<syntaxhighlight lang=julia-repl> (@v1.10) pkg> search Keyword </syntaxhighlight> ====パッケージの情報の表示==== インストールされているパッケージの情報を表示するには、以下の手順に従います。 <code>status</code> コマンドを入力して、インストールされているパッケージの一覧とそれぞれのバージョンを表示します。 :*<syntaxhighlight lang=julia-repl> (@v1.10) pkg> status </syntaxhighlight> これらの操作を通じて、Juliaのパッケージを効果的に管理し、プロジェクトの開発を円滑に進めることができます。 Juliaのパッケージエコシステムは非常に豊富であり、さまざまなニーズに対応できるパッケージが提供されています。 ====Pkgのサブコマンド一覧==== Juliaのパッケージ管理システムであるPkgは、REPL(Read-Eval-Print Loop)モードを提供しています。このモードでは、パッケージのインストール、更新、削除などの操作が行えます。以下に、Pkgの主なコマンドとその機能を示します。 * <code>activate</code>: パッケージマネージャが操作するプライマリ環境を設定します。 * <code>add</code>: プロジェクトにパッケージを追加します。 * <code>build</code>: パッケージのビルドスクリプトを実行します。 * <code>compat</code>: 現在のプロジェクトのcompatエントリを編集し、再度解決します。 * <code>develop</code>または<code>dev</code>: 開発用にパッケージの完全なリポジトリをローカルにクローンします。 * <code>free</code>: ピン、develop、またはリポジトリの追跡を停止します。 * <code>gc</code>: 一定時間使用されていないパッケージをガベージコレクトします。 * <code>generate</code>: 新しいプロジェクトのファイルを生成します。 * <code>help</code>または<code>?</code>: ヘルプメッセージを表示します。 * <code>instantiate</code>: プロジェクトの依存関係をすべてダウンロードします。 * <code>pin</code>: パッケージのバージョンをピン留めします。 * <code>precompile</code>: プロジェクトのすべての依存関係を事前コンパイルします。 * <code>redo</code>: アクティブなプロジェクトの最新の変更をやり直します。 * <code>remove</code>または<code>rm</code>: プロジェクトまたはマニフェストからパッケージを削除します。 * <code>resolve</code>: 開発中のパッケージの依存関係の変更からマニフェストを更新します。 * <code>status</code>または<code>st</code>: 環境の内容と変更の要約を表示します。 * <code>test</code>: パッケージのテストを実行します。 * <code>undo</code>: アクティブなプロジェクトの最新の変更を元に戻します。 * <code>update</code>または<code>up</code>: マニフェスト内のパッケージを更新します。 * <code>why</code>: パッケージがマニフェストに含まれる理由を表示します。 さらに、パッケージレジストリに関連するコマンドもあります。 * <code>registry add</code>: パッケージレジストリを追加します。 * <code>registry remove</code>または<code>rm</code>: パッケージレジストリを削除します。 * <code>registry status</code>または<code>st</code>: インストールされているパッケージレジストリに関する情報を表示します。 * <code>registry update</code>または<code>up</code>: パッケージレジストリを更新します。 これらのコマンドを使用して、Juliaのパッケージを効果的に管理できます。 ====ヘルプ==== <code>?</code>または<code>help</code>コマンドは、利用可能なコマンドとそれぞれの簡単な説明を表示します。これは、Pkgのコマンドを理解するための便利な方法です。 以下に、<code>?</code>または<code>help</code>コマンドの使用方法を示します。 # <code>?</code>または<code>help</code>を入力すると、利用可能なすべてのコマンドとそれぞれの簡単な説明が表示されます。 #; 例: #:<syntaxhighlight lang=julia-repl> (@v1.10) pkg> ? </syntaxhighlight> #:: または #:<syntaxhighlight lang=julia-repl> (@v1.10) pkg> help </syntaxhighlight> # 特定のコマンドに関する詳細なヘルプを表示するには、<code>?</code>または<code>help</code>の後にコマンド名を入力します。 #; 例: #:<syntaxhighlight lang=julia-repl> (@v1.10) pkg> ? add </syntaxhighlight> #:: または #:<syntaxhighlight lang=julia-repl> (@v1.10) pkg> help add </syntaxhighlight> このようにして、<code>?</code>または<code>help</code>コマンドを使用することで、Pkgのコマンドを効果的に理解し、利用できます。 ===高度なデータ構造とアルゴリズム=== 高度なデータ構造とアルゴリズムは、複雑な問題を解決するための不可欠なツールです。グラフ、木構造、ヒープなどのデータ構造は、データの組織化と効率的な操作を可能にし、様々なアプリケーションや分野で広く活用されています。Juliaの柔軟な言語機能を活用して、これらのデータ構造とアルゴリズムを実装し、問題を効率的に解決する方法を学びましょう。 ====グラフ==== グラフは、頂点(ノード)とそれらを接続する辺(エッジ)から構成されるデータ構造です。グラフは、現実世界のさまざまなネットワークや関係性をモデル化するために広く使用されています。ソーシャルネットワーク、経路計画、交通ネットワーク、通信ネットワークなど、多くの問題がグラフとして表現されます。 ;グラフの種類 :有向グラフ(Directed Graph) : エッジに向きがあるグラフで、頂点間の接続が一方向です。 :例えば、Twitterのフォローグラフは有向グラフとしてモデル化できます。 ;無向グラフ(Undirected Graph) : エッジに向きがないグラフで、頂点間の接続が双方向です。 :例えば、Facebookの友人関係は無向グラフとして表現できます。 ;重み付きグラフ(Weighted Graph) : エッジに重みが付いているグラフで、頂点間の接続にコストや距離が関連付けられます。 :交通ネットワークや物流ネットワークをモデル化するのに使用されます。 ;グラフアルゴリズム :グラフの構造を理解し、効率的な問題解決のために以下の基本的なアルゴリズムを実装することが重要です。 :;幅優先探索(Breadth-First Search, BFS): グラフ内のノードをレベルごとに探索して、最短経路を見つけるアルゴリズムです。キューを使用して実装されます。 :;深さ優先探索(Depth-First Search, DFS): グラフの最深部まで掘り下げてから戻ることで探索するアルゴリズムです。再帰またはスタックを使用して実装されます。 :;最短経路アルゴリズム(Shortest Path Algorithms): 与えられたグラフ内の最短経路を見つけるアルゴリズムです。代表的なものとしてダイクストラ法やベルマンフォード法があります。 :;最小全域木(Minimum Spanning Tree, MST): グラフ内の全ての頂点を含み、全ての辺の重みの合計が最小になる木を見つけるアルゴリズムです。プリム法やクラスカル法があります。 これらのアルゴリズムを理解し、適切な問題に適用することで、効率的なグラフの操作や解析が可能になります。 ====木構造==== 木構造は、階層的なデータを表現するためのデータ構造であり、ルートノードから始まり、子ノードが枝分かれしていく形をしています。木構造は、多くの分野で使用され、階層的な関係性や再帰的なデータの表現に適しています。代表的な用途としては、ファイルシステム、データベースの索引、再帰的なアルゴリズムの実装などが挙げられます。 ;木構造の特徴 :;ルートノード(Root Node): 木構造の最上位に位置するノードで、他のすべてのノードへの経路が存在します。 親ノードと子ノード(Parent and Child Nodes): 親ノードは、直下に1つ以上の子ノードを持つノードです。子ノードは、親ノードの下に配置され、その親ノードに関連付けられます。 :;枝分かれ(Branching): 子ノードが複数ある場合、それぞれの子ノードへの経路が枝分かれします。これにより、複数のパスが可能となります。 :;葉ノード(Leaf Node): 子を持たない末端のノードであり、枝分かれしないノードです。 ;代表的な木構造 :;二分木(Binary Tree): 各ノードが最大2つの子ノードを持つ木構造です。二分探索木(Binary Search Tree)は、二分木の一種で、左の子ノードの値が親ノードより小さく、右の子ノードの値が親ノードより大きいという条件を満たします。 :;赤黒木(Red-Black Tree): 二分探索木の一種で、特定の条件(赤黒の色付けとバランス条件)を満たすことで、操作の効率性を保つことができるデータ構造です。挿入や削除の操作が比較的高速であることが特徴です。 :;AVL木: 二分探索木の一種で、高さのバランスを保つための条件が厳密に定義されています。挿入や削除の際に回転操作を行うことで、常にバランスが保たれます。 ;木構造の操作 :木構造を操作する際には、以下のような基本的な操作が必要です。 :*ノードの挿入 :*ノードの削除 :*ノードの検索 :*木の走査(深さ優先探索、幅優先探索など) これらの操作を理解し、適切に実装することで、木構造を効果的に活用することができます。 ====ヒープ==== ヒープは、優先度付きキューを実装するためのデータ構造であり、最小値や最大値を高速に取得することができます。ヒープは、優先度付きキューの操作を効率的に行うために設計されており、ダイクストラ法やヒープソートなどのアルゴリズムで広く使用されています。 ===== ヒープの特徴 ===== # 完全二分木の性質: ヒープは、完全二分木として表現されます。完全二分木とは、すべてのノードが左から右へと埋まっており、最後のレベルを除いてすべてのレベルが完全に埋まっている木構造です。 # 最小ヒープと最大ヒープ: ヒープは、最小値を持つノードがルートに配置される場合を最小ヒープ、最大値を持つノードがルートに配置される場合を最大ヒープと呼びます。 # 親ノードと子ノードの関係: ヒープの各ノードは、その親ノードよりも優先度が高いか低いかに応じて配置されます。最小ヒープでは、親ノードの値が子ノードの値よりも小さいことが保証されます。最大ヒープではその逆です。 ===== ヒープの操作 ===== ヒープは、以下の操作をサポートします。 # 挿入(Insertion): ヒープに新しい要素を追加する操作です。新しい要素は、ヒープの末尾に追加され、適切な位置に再配置されます。 # 削除(Deletion): ヒープから最小値(または最大値)を取り出す操作です。取り出された要素は、ヒープの最後の要素と交換され、適切な位置に再配置されます。 # 最小値(最大値)の取得: ヒープから最小値(または最大値)を取得する操作です。最小値(または最大値)は常にヒープのルートに配置されているため、ヒープのルート要素を取得することで行われます。 # ヒープの構築: 与えられた要素の集合からヒープを構築する操作です。これにより、ランダムな要素の集合をヒープとして扱うことができます。 ===== ヒープの実装 ===== ヒープは、通常、配列を使用して実装されます。配列のインデックスを使用してノード間の親子関係を表現し、要素の挿入や削除が効率的に行われます。最小ヒープの場合、親ノードのインデックスを <code>i</code> とすると、左の子ノードのインデックスは <code>2i + 1</code>、右の子ノードのインデックスは <code>2i + 2</code> となります。 ヒープは、効率的な優先度付きキューの実装として広く使用され、多くのアルゴリズムやデータ構造において重要な役割を果たしています。 ====アルゴリズムの実装==== これらのデータ構造を理解したら、それらを使用したさまざまなアルゴリズムを実装することができます。例えば、グラフ探索アルゴリズム、最短経路探索アルゴリズム、ソートアルゴリズムなどがあります。これらのアルゴリズムは、問題の性質に応じて適切に選択され、実装される必要があります。 ;プログラム例 :以下は、Juliaで二分木を実装する例です。 :<syntaxhighlight lang=julia> struct TreeNode{T} value::T left::Union{TreeNode{T}, Nothing} right::Union{TreeNode{T}, Nothing} end function insert!(node::Union{TreeNode{T}, Nothing}, value::T) where T if node === nothing return TreeNode(value, nothing, nothing) elseif value < node.value node.left = insert!(node.left, value) else node.right = insert!(node.right, value) end return node end function search(node::Union{TreeNode{T}, Nothing}, value::T) where T if node === nothing return false elseif value == node.value return true elseif value < node.value return search(node.left, value) else return search(node.right, value) end end # 二分木の作成と操作の例 root = nothing root = insert!(root, 5) root = insert!(root, 3) root = insert!(root, 8) println(search(root, 3)) # true println(search(root, 7)) # false </syntaxhighlight> これは、基本的な二分木の実装と、ノードの挿入と検索の方法を示しています。これらの基本的なデータ構造とアルゴリズムを理解することで、さまざまな問題を解決するための基盤を築くことができます。 === 並列処理と分散処理 === Juliaの並列処理機能を活用して、処理を並列化する方法を学びます。並列処理は、計算を高速化し、大規模な問題を効率的に解決するための重要な手法です。また、分散処理を通じて複数の計算資源を効果的に活用する方法も学びます。 === 数値計算と最適化 === 数値計算や最適化問題を解くためのパッケージを使用して、数値計算と最適化の技術を学びます。数値計算は科学技術計算やエンジニアリングなどのさまざまな分野で重要な役割を果たします。また、最適化は問題の最適な解を見つけるための重要な手法です。 === 機械学習 === Flux.jlやMLJ.jlなどの機械学習ライブラリを使用して、機械学習モデルを実装し、データに対して学習させる方法を学びます。機械学習はデータ解析や予測モデリングなどの様々なタスクで利用され、現代の技術やビジネスにおいて重要な役割を果たしています。Juliaの豊富なパッケージを活用して、機械学習のスキルを磨きましょう。 −−−− === 線形代数演算 === Juliaの<code>LinearAlgebra</code>モジュールは、線形代数の基本的な機能を提供しています。具体的には、ベクトルや行列の演算、固有値や固有ベクトルの計算、疎行列の操作、LU分解やQR分解などが利用可能です。 Juliaの<code>LinearAlgebra</code>モジュールで定義されている主な関数と演算子は以下の通りです。 ==== 関数 ==== * <code>dot</code>: ベクトルのドット積を計算します。 * <code>norm</code>: ベクトルのノルムを計算します。 * <code>cross</code>: 3次元ベクトルの外積を計算します。 * <code>det</code>: 行列の行列式を計算します。 * <code>inv</code>: 行列の逆行列を計算します。 * <code>transpose</code>: 行列の転置行列を計算します。 * <code>adjoint</code>: 行列の随伴行列を計算します。 * <code>eigvals</code>: 行列の固有値を計算します。 * <code>eigvecs</code>: 行列の固有ベクトルを計算します。 * <code>lu</code>: 行列のLU分解を取得します。 * <code>qr</code>: 行列のQR分解を取得します。 * <code>svd</code>: 行列の特異値分解を取得します。 ==== 演算子 ==== * <code>*</code>: 行列の積を計算します。 * <code>'</code>: 行列の転置行列を計算します。 以下は、Juliaの<code>LinearAlgebra</code>モジュールを使った基本的な操作例です。 :<syntaxhighlight lang=julia-repl> $ julia _ _ _ _(_)_ | Documentation: https://docs.julialang.org (_) | (_) (_) | _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.10.0 (2023-12-25) _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release |__/ | julia> using LinearAlgebra julia> v1 = [1, 2, 3] 3-element Vector{Int64}: 1 2 3 julia> v2 = [4, 5, 6] 3-element Vector{Int64}: 4 5 6 julia> 2v1 3-element Vector{Int64}: 2 4 6 julia> v1 + v2 3-element Vector{Int64}: 5 7 9 julia> v1 - v2 3-element Vector{Int64}: -3 -3 -3 julia> dot(v1, v2) 32 julia> norm(v1) 3.7416573867739413 julia> A = [1 2 3;0 1 4;5 6 0] 3×3 Matrix{Int64}: 1 2 3 0 1 4 5 6 0 julia> transpose(A) 3×3 transpose(::Matrix{Int64}) with eltype Int64: 1 0 5 2 1 6 3 4 0 julia> inv(A) 3×3 Matrix{Float64}: -24.0 18.0 5.0 20.0 -15.0 -4.0 -5.0 4.0 1.0 julia> det(A) 0.9999999999999964 julia> A * v1 3-element Vector{Int64}: 14 14 17 julia> A * A 3×3 Matrix{Int64}: 16 22 11 20 25 4 5 16 39 julia> D = Diagonal([1, 2, 3]) 3×3 Diagonal{Int64, Vector{Int64}}: 1 ⋅ ⋅ ⋅ 2 ⋅ ⋅ ⋅ 3 julia> S = Symmetric(A) 3×3 Symmetric{Int64, Matrix{Int64}}: 1 2 3 2 1 4 3 4 0 julia> eigen(S) Eigen{Float64, Float64, Matrix{Float64}, Vector{Float64}} values: 3-element Vector{Float64}: -3.78840762859157 -0.9067918580419407 6.695199486633532 vectors: 3×3 Matrix{Float64}: -0.266182 0.807132 -0.526959 -0.55006 -0.576121 -0.604582 0.791569 -0.12893 -0.597324 julia> b = [1, 2, 3] 3-element Vector{Int64}: 1 2 3 julia> x = A \ b 3-element Vector{Float64}: 27.000000000000096 -22.00000000000008 6.00000000000002 julia> </syntaxhighlight> このコードでは、まずベクトル <code>v1</code> と <code>v2</code> を定義しています。その後、ベクトルのスカラー倍、加法、減法、内積、ノルムを計算し、結果を表示しています。 次に、行列 <code>A</code> を定義しています。この行列は 3x3 の整数行列であり、転置、逆行列、行列式、ベクトルとの積、行列との積を計算しています。また、対角行列 <code>D</code> も定義しています。 さらに、対称行列 <code>S</code> を定義し、その固有値と固有ベクトルを計算しています。 最後に、最小二乗法の演算を行っています。これは連立方程式 <code>Ax = b</code> の解 <code>x</code> を求める操作です。 このように、<code>LinearAlgebra</code>モジュールは、数値計算において基本的かつ重要な要素であるベクトルや行列の様々な操作を提供しています。 === 内積と外積 === まず、内積(ドット積)を計算する方法は以下の通りです。 LinearAlgebraモジュール(線形代数演算モジュール)の読み込み :<syntaxhighlight lang=julia> using LinearAlgebra </syntaxhighlight> 内積はベクトルの要素同士を掛け合わせたものを足し合わせた値となります。 Juliaでの内積の計算は以下のように行えます。 :<syntaxhighlight lang=julia> # ベクトルの定義 v1 = [1, 2, 3] v2 = [4, 5, 6] # 内積の計算 dot(v1, v2) # 32 </syntaxhighlight> 次に、外積を計算する方法は以下の通りです。 外積は2つのベクトルから、そのベクトルが張る平行四辺形の面積を求めることで計算できます。 Juliaでの外積の計算は以下のように行えます。 :<syntaxhighlight lang=julia> # ベクトルの定義 v1 = [1, 0, 0] v2 = [0, 1, 0] # 外積の計算 cross(v1, v2) # [0, 0, 1] </syntaxhighlight> ただし、外積の結果はベクトルですが、そのベクトルが張る平行四辺形の面積になっているわけではありません。外積の結果に絶対値を取ることで平行四辺形の面積を求めることができます。 :<syntaxhighlight lang=julia> # ベクトルの定義 v1 = [1, 0, 0] v2 = [0, 1, 0] # 外積の計算と面積の計算 norm(cross(v1, v2)) # 1.0 </syntaxhighlight> 以上が、Juliaを使って内積と外積を求める方法の簡単な解説です。 === プログラムの構造化 === ==== プログラムの分割 ==== ==== モジュール化されたプログラムのテスト ==== −−−− == 上級編 == === パフォーマンスチューニング === コードのパフォーマンスを向上させるためのテクニックや最適化手法を学びます。Juliaは高速な言語ですが、さらなるパフォーマンスの向上が求められる場合があります。効率的なアルゴリズムの選択、メモリ管理の最適化、並列処理の活用など、様々な方法を学びます。 === メタプログラミング === Juliaのメタプログラミング機能を使用して、コード生成やDSL(Domain Specific Language)の構築などを行う方法を学びます。メタプログラミングは、コードの自動生成や柔軟な言語拡張を可能にし、効率的なプログラムの作成に役立ちます。 === 深層学習 === Flux.jlやKnet.jlなどの深層学習フレームワークを使用して、ニューラルネットワークモデルを構築し、トレーニングする方法を学びます。深層学習は、画像認識、自然言語処理、音声認識などの分野で広く利用されており、Juliaを使った効果的な実装方法を習得します。 === ハイパフォーマンスコンピューティング === Juliaを使用して、高性能な計算を実行するためのテクニックやツールを学びます。並列処理、GPUプログラミング、分散コンピューティングなど、さまざまなアプローチを通じて、大規模な計算問題に対処するスキルを磨きます。 −−−− −−−− === 高度なトピックス === 「高度なトピックス」の章では、Julia言語でより高度なトピックスを扱います。この章では、メタプログラミング、並列処理と分散処理、プログラミングの最適化、GPUプログラミングの4つのセクションに分かれます。 #メタプログラミング {{---}} メタプログラミングとは、プログラムがプログラムを生成することを指します。Julia言語は、メタプログラミングに非常に適しているため、コード生成、コンパイル時のコード評価、マクロなどの機能を提供しています。このセクションでは、これらの機能について詳しく説明し、具体的な使用例を示します。 #並列処理と分散処理 {{---}} Julia言語は、マルチスレッド、マルチプロセス、そして分散コンピューティングを含む並列処理と分散処理に対して強力なサポートを提供しています。このセクションでは、これらの機能について詳しく説明し、具体的な使用例を示します。 #プログラミングの最適化 {{---}} Julia言語は、数値計算、科学技術計算など、高性能が必要なアプリケーションで使用されることが多いため、プログラミングの最適化が重要な課題です。このセクションでは、Juliaコードの最適化についての基本的な考え方を説明し、プロファイリング、コード生成、LLVMの最適化などの技術について詳しく説明します。 #GPUプログラミング {{---}} GPUプログラミングは、グラフィックス処理以外にも、データ処理、科学技術計算などの分野でも広く使用されるようになっています。Julia言語は、GPUプログラミングに対しても強力なサポートを提供しています。このセクションでは、GPUプログラミングについての基本的な考え方を説明し、Julia言語のGPUプログラミングのサポートについて説明します。 ==== メタプログラミング ==== この節では、Juliaのメタプログラミングについて説明します。メタプログラミングは、プログラムが自分自身を操作したり、自分自身を変更したりすることを指します。Juliaは、非常に強力なメタプログラミング機能を提供しており、これにより、高度なプログラムを書くことができます。 ===== マクロ ===== Juliaにおけるマクロは、プログラムの最終的な本体に生成されたコードを含めるメカニズムを提供します。マクロは、引数のタプルを返される式にマップし、その結果の式は実行時の eval 呼び出しを必要とせずに直接コンパイルされます。マクロの引数には、式、リテラル値、およびシンボルを含めることができます。 ====== 特徴 ====== Juliaのマクロは、いくつかの特徴を持っています: ;コードの生成と挿入: マクロは、プログラムの実行前にコードを生成し、そのコードをプログラムの本体に挿入することができます。これにより、繰り返しのパターンや共通の構造を自動的に生成し、効率的にコードを記述することができます。 ;パーサーレベルの実行: マクロはコードが解析される時点で実行されます。これにより、マクロは式の構造を調査し、必要に応じて変更することができます。これは、実行時ではなくパース時にコードを操作する能力を提供します。 式、リテラル、シンボルの引数: マクロは式、リテラル値、およびシンボルを引数として受け取ることができます。これにより、マクロはさまざまなタイプの引数を受け入れ、適切な処理を行うことができます。 ;名前空間の操作: マクロは、ローカルなスコープ内で変数を導入するために名前空間を操作することができます。これにより、マクロが生成する変数が衝突することなく、コードを安全に展開することができます。 ;ハイジーン: Juliaのマクロは、変数名やスコープの衝突を防ぐためにハイジーン機構を持っています。これにより、マクロが生成するコードが周囲のコンテキストと衝突することがなくなります。 ;ジェネリックな性質: マクロはジェネリックな性質を持ち、複数のメソッド定義を持つことができます。これにより、マクロは異なる引数に対して異なる振る舞いをすることができます。 ;AST(Abstract Syntax Tree)の操作: マクロは抽象構文木(AST)を操作する能力を持っています。これにより、マクロはコードの構造を調査し、必要に応じて変更することができます。 これらの特徴により、Juliaのマクロは非常に柔軟で強力なプログラミングツールとなっています。 ====== コード例 ====== Juliaのマクロは、@(アットマーク)に続くユニークな名前で宣言されたブロック内で定義されます。以下は非常にシンプルなマクロの例です: :<syntaxhighlight lang=julia-repl> julia> macro sayhello() return :( println("Hello, world!") ) end @sayhello (macro with 1 method) </syntaxhighlight> この例では、コンパイラは@sayhelloのすべてのインスタンスを以下のように置き換えます: :<syntaxhighlight lang=julia-repl> :( println("Hello, world!") ) </syntaxhighlight> @sayhelloがREPLに入力されると、式がすぐに実行されるため、評価結果のみが表示されます: :<syntaxhighlight lang=julia-repl> julia> @sayhello() Hello, world! </syntaxhighlight> さらに少し複雑なマクロを考えてみましょう: :<syntaxhighlight lang=julia-repl> julia> macro sayhello(name) return :( println("Hello, ", $name) ) end @sayhello (macro with 1 method) </syntaxhighlight> このマクロは1つの引数、つまりnameを取ります。@sayhelloが出会われると、クォートされた式は最終式に引数の値を展開します: :<syntaxhighlight lang=julia-repl> julia> @sayhello("human") Hello, human </syntaxhighlight> マクロを展開した戻り値の引用式を表示するには、関数macroexpandを使用できます(重要な注意:これはマクロのデバッグに非常に便利なツールです): :<syntaxhighlight lang=julia-repl> julia> ex = macroexpand(Main, :(@sayhello("human")) ) :(Main.println("Hello, ", "human")) julia> typeof(ex) Expr </syntaxhighlight> ここで、"human"リテラルが式に展開されていることがわかります。 ---- ;マトリックスを使ったアルゴリズム例 マクロを使用して、Juliaで簡単な行列操作を行うアルゴリズムの例を示します。この例では、2つの行列の積を計算する関数をマクロで定義します。 :<syntaxhighlight lang=julia> macro matrix_multiply(A, B) quote if size($A, 2) != size($B, 1) error("Matrix dimensions do not match: ", size($A), " and ", size($B)) else C = zeros(eltype($A), size($A, 1), size($B, 2)) for i in 1:size($A, 1) for j in 1:size($B, 2) for k in 1:size($A, 2) C[i, j] += $A[i, k] * $B[k, j] end end end C end end end </syntaxhighlight> このマクロでは、2つの行列AとBを引数として受け取り、それらの積を計算します。まず、行列の次元をチェックし、次元が一致しない場合はエラーを返します。次に、結果の行列Cを初期化し、3重のループを使用して積を計算します。最後に、結果の行列Cを返します。 このマクロを使用すると、次のように2つの行列の積を計算できます。 :<syntaxhighlight lang=julia> A = [1 2; 3 4] B = [5 6; 7 8] @matrix_multiply(A, B) </syntaxhighlight> この例では、行列AとBを定義し、@matrix_multiplyマクロを使用してそれらの積を計算しています。 ====== ユースケース ====== Juliaのマクロは、いくつかの一般的なユースケースで役立ちます: ;ドメイン固有言語(DSL)の作成: マクロを使用して、特定のドメインや問題領域に適した独自の言語を作成することができます。これにより、特定の問題を解決するための簡潔で明確な構文を提供し、コードの可読性を向上させることができます。 ;コードの自動生成: マクロを使用して、繰り返しのパターンや共通の構造を自動的に生成することができます。これにより、冗長なコードの記述を減らし、効率的なプログラミングを実現することができます。 ;メタプログラミング: マクロを使用して、実行時ではなくパース時にコードを操作することができます。これにより、プログラムをより動的に制御し、柔軟性を高めることができます。 ;最適化: マクロを使用して、コードを最適化することができます。特定のコンテキストや条件に基づいて、コードを変更し、パフォーマンスを向上させることができます。 ;デバッグ: マクロを使用して、デバッグ情報をコードに埋め込むことができます。これにより、実行時のエラーや問題のトラブルシューティングが容易になります。 ;リフレクション: マクロを使用して、実行時の情報をコードに埋め込むことができます。これにより、実行時にコードを動的に制御することができます。 ;外部ライブラリの拡張: マクロを使用して、外部ライブラリを拡張することができます。これにより、既存のライブラリに機能を追加したり、カスタマイズしたりすることができます。 これらのユースケースを活用することで、Juliaのマクロはコードの柔軟性、効率性、および保守性を向上させることができます。 ====== ベストプラクティス ====== Juliaのマクロを使用する際のベストプラクティスには、以下のようなものがあります: ;ドキュメントの提供: マクロを定義するときに、適切なドキュメントを提供することが重要です。マクロの目的、使用方法、および引数の意味を明確に説明し、他の開発者が理解しやすくします。 ;名前の衝突を避ける: マクロで導入される変数や関数の名前は、他の部分と衝突しないように注意する必要があります。一般的な命名規則に従い、名前の選択に注意を払います。 ;ハイジーンを守る: マクロが導入する変数や関数が周囲のコンテキストと衝突しないように、ハイジーンルールを遵守します。必要に応じて、gensym関数を使用して一意のシンボルを生成します。 ;効率性を考慮する: マクロは、コードの生成と展開の段階で実行されるため、効率的なコードを生成することが重要です。不要な計算や繰り返しを避け、コードのパフォーマンスを最適化します。 ;単純さを重視する: マクロは強力なツールであり、複雑な処理を行うことができますが、できるだけ単純な実装を心がけるべきです。複雑なマクロは理解が難しくなり、保守性が低下する可能性があります。 ;テストを実施する: マクロが正しく機能することを確認するために、適切なテストを実施します。異なるケースや境界条件をカバーし、予期しない挙動がないことを確認します。 ;デバッグ情報の提供: マクロが生成するコードには、デバッグ情報を埋め込むことが重要です。エラーメッセージやデバッグ用の情報を適切に設定し、トラブルシューティングを容易にします。 ;リファクタリングの検討: マクロを使用するとコードが複雑になる可能性があるため、適切なタイミングでコードをリファクタリングすることを検討します。複雑なマクロをより単純で理解しやすい形に変更することで、コードの保守性を向上させることができます。 これらのベストプラクティスに従うことで、Juliaのマクロを効果的に使用し、コードの品質と保守性を向上させることができます。 ====== イディオム ====== Juliaのマクロを使用する際によく見られるイディオム(慣用句)には次のようなものがあります: # 式のクオート: マクロの中でコードを生成する際には、式をクオートすることが一般的です。これにより、式が評価されるのではなく、そのままコードの一部として扱われます。例えば、<code>:(x + y)</code>のような形式がよく使われます。 # 式のスプライス: マクロ内で変数や式を展開する際には、<code>$</code>を使用して式をスプライスします。これにより、変数の値や式の結果をマクロの中に挿入することができます。 # gensym関数の使用: マクロで一意のシンボルを生成する場合には、<code>gensym</code>関数を使用します。これにより、名前の衝突を回避し、安全にマクロを定義することができます。 # エスケープ: マクロの引数をそのまま挿入する場合には、<code>esc</code>関数を使用してエスケープします。これにより、マクロが引数を変更せずにそのまま展開することができます。 # ドキュメントの提供: マクロを定義する際には、適切なコメントやドキュメントを提供することが重要です。マクロの目的、使用方法、および引数の意味を明確に説明し、他の開発者が理解しやすくします。 # ハイジーンを守る: マクロが導入する変数や関数が周囲のコンテキストと衝突しないように、ハイジーンルールを遵守します。必要に応じて、<code>gensym</code>関数を使用して一意のシンボルを生成します。 # マクロの使用例を提供: マクロを定義する際には、適切な使用例を提供することが重要です。他の開発者がマクロの意図と使用方法を理解しやすくなります。 これらのイディオムを使用することで、Juliaのマクロを効果的に定義し、他の開発者が理解しやすいコードを書くことができます。 ---- Juliaのメタプログラミングには、マクロと呼ばれる特殊な関数が使用されます。マクロは、実行時ではなく、コンパイル時に評価されます。つまり、コンパイル前にマクロが実行され、マクロが生成したコードが実行されます。マクロは、特別な構文を使用して定義されます。例えば、以下のように定義されます。 :<syntaxhighlight lang=julia> macro mymacro(x) # do something with x return quote # generated code end end </syntaxhighlight> マクロの引数は、通常の関数と同じように扱われますが、コンパイル時に評価されます。マクロの戻り値は、実行時ではなく、コンパイル時に評価されるJuliaの式でなければなりません。そのため、マクロは、動的な式を生成するために使用されます。 マクロを呼び出すには、<code>@マクロ名</code>のように<code>@</code>を付けます。例えば、先ほど定義したマクロを呼び出すには、以下のようにします。 :<syntaxhighlight lang=julia> @mymacro(x) </syntaxhighlight> ===== メタプログラミングの応用例 ===== Juliaのメタプログラミングには、様々な応用例があります。以下にいくつか例を挙げます。 * コード生成:メタプログラミングを使用して、特定の型やデータ構造に対する高度な最適化を行うことができます。例えば、特定の型のために最適化された専用の関数を生成することができます。 * ドメイン特化言語(DSL):Juliaのメタプログラミングを使用して、特定の問題に対する独自のドメイン特化言語を作成することができます。これにより、問題の表現力を向上させ、実行時間を短縮することができます。 * クエリエンジン:Juliaのメタプログラミングを使用して、高速なクエリエンジンを作成することができます。 ==== 並列処理と分散処理 ==== 「並列処理」とは、コンピューター上で同時に複数の処理を実行することを指します。一方、「分散処理」とは、複数のコンピューターで処理を分散し、協調して処理を行うことを指します。Juliaは、並列処理と分散処理に対応しており、それぞれに適した方法でプログラミングすることができます。 ===== 並列処理 ===== Juliaは、マルチスレッド処理をサポートしています。マルチスレッド処理を使用することで、複数のタスクを同時に実行することができます。Juliaのマルチスレッド処理は、スレッド間通信のためのチャンネルを提供しています。 以下は、マルチスレッド処理を使用して、1から10までの数字の合計を計算する例です。 :<syntaxhighlight lang=julia> function sum_range(start::Int, stop::Int, ch::Channel) s = 0 for i = start:stop s += i end put!(ch, s) end function parallel_sum(n::Int, num_threads::Int) ch = Channel{Int}(num_threads) chunk_size = ceil(Int, n / num_threads) for i = 1:num_threads start = (i - 1) * chunk_size + 1 stop = min(i * chunk_size, n) @async sum_range(start, stop, ch) end s = 0 for i = 1:num_threads s += take!(ch) end return s end @time parallel_sum(10, 2) # 55 </syntaxhighlight> この例では、sum_range関数が、指定された範囲の数字の合計を計算して、Channelに結果を送信します。parallel_sum関数では、指定された範囲を複数のチャンクに分割し、それぞれのチャンクを別々のスレッドで処理します。各スレッドの結果は、Channelに送信され、parallel_sum関数は各スレッドからの結果を収集して、最終的な結果を返します。 ==== プログラミングの最適化 ==== プログラムの実行速度は、多くの場合、最適化の対象となります。プログラムの高速化には、様々な方法がありますが、本書では、次のようなアプローチに焦点をあてます。 * アルゴリズムの最適化 * データ構造の最適化 * コードの最適化 ===== アルゴリズムの最適化 ===== アルゴリズムの最適化は、そのアルゴリズムが処理する問題に適したアルゴリズムを選択することによって実現できます。適切なアルゴリズムを選択することで、プログラムの実行速度を大幅に向上させることができます。 例えば、リスト内の要素を検索する場合、線形探索アルゴリズムよりも二分探索アルゴリズムの方が効率的です。また、ソートアルゴリズムを選択する際にも、問題によって最適なアルゴリズムが異なります。 ===== データ構造の最適化 ===== データ構造の最適化は、プログラムの実行速度に大きな影響を与えます。データ構造を適切に設計することによって、メモリ使用量を削減し、データアクセスの処理時間を短縮することができます。 例えば、多くの場合、配列の使用よりも、連結リストの使用の方が効率的です。また、ハッシュテーブルは、大量のデータを効率的に検索する場合に有効です。 ===== コードの最適化 ===== 最適なアルゴリズムと最適なデータ構造を選択しても、プログラムの実行時間を大幅に上げることができます。コードの最適化は、アルゴリズムやデータ構造を実現するためのコードを最適化することによって実現できます。 例えば、繰り返し処理内で同じ計算を何度も実行する場合、計算を多用しないようにコードを書くことで、プログラムの実行速度を上げることができます。また、高速なループ記法を使用することも、プログラムの速度を向上させることができます。 ===== まとめ ===== プログラムの最適化には、アルゴリズムの最適化、データ構造の最適化、コードの最適化の3つのアプローチがあります。これらのアプローチを駆使して、プログラムの実行速度を高速化することができます。 ==== GPUプログラミング ==== GPU(Graphics Processing Unit)は、グラフィックス処理のために開発されたプロセッサですが、数値計算や科学技術計算の分野でも利用されるようになっています。GPUはSIMD(Single Instruction Multiple Data)アーキテクチャを採用しており、同時に多数の演算を行うことができます。この特性を活かすことで、CPUに比べて高速な数値計算が可能になります。 juliaはGPUプログラミングをサポートしており、CuArraysと呼ばれるライブラリを介してCUDA APIを利用することができます。CUDAはNVIDIAが開発しているGPU向けの並列コンピューティングプラットフォームであり、GPUのパフォーマンスを最大限引き出すことができます。 ===== CuArraysのインストール ===== CuArraysを使用するには、以下のようにしてインストールする必要があります。 :<syntaxhighlight lang=julia> import Pkg Pkg.add("CuArrays") </syntaxhighlight> なお、CuArraysを利用するためにはCUDAがインストールされている必要があります。 ===== CuArraysの基本的な使い方 ===== CuArraysは、juliaの標準的な配列と同じように扱うことができます。以下はCuArraysでベクトルを作成する例です。 :<syntaxhighlight lang=julia> using CuArrays a = CuArray([1, 2, 3]) </syntaxhighlight> このようにすることで、ホスト側のメモリ内にある配列から、GPU側のメモリ内に配列をコピーすることができます。 CuArraysを使った計算は、通常のjuliaの配列と同じように行えます。ただし、計算を行う関数には、GPU側のメモリ上にある配列を引数とする必要があります。以下はCuArraysでベクトルの和を計算する例です。 :<syntaxhighlight lang=julia> using CuArrays a = CuArray([1, 2, 3]) b = CuArray([4, 5, 6]) c = a + b </syntaxhighlight> このようにすることで、ベクトルaとベクトルbの要素ごとの和を、ホスト側のメモリからGPU側のメモリに転送し、計算を行い、結果をGPU側のメモリからホスト側のメモリに転送します。 ===== カスタムカーネルの定義 ===== カスタムカーネルは、GPU上で並列に実行できる関数のことです。CuArraysは、CuKernelマクロを用いてカスタムカーネルを定義することができます。以下は、CuKernelマクロを用いて、ベクトルの和を計算するカスタムカーネルを定義する例です。 :<syntaxhighlight lang=julia> using CuArrays @cuda function vector_add!(c::CuDeviceArray{T,1}, a::CuDeviceArray{T,1}, b::CuDeviceArray{T,1}) where {T} i = threadIdx().x if i <= length(a) c[i] = a[i] + b[i] end return end </syntaxhighlight> このカスタムカーネルでは、各スレッドが配列の要素の合計値を計算し、結果をそれぞれのスレッドに返します。CuKernelが返す値は、並列処理されるスレッド数と同じです。 ===== カスタムカーネルの実行 ===== CuArraysには、CuKernelを実行するための関数が用意されています。以下は、CuArraysでベクトルの和を計算する例です。 :<syntaxhighlight lang=julia> using CuArrays a = CuArray([1, 2, 3]) b = CuArray([4, 5, 6]) c = similar(a) CuArrays.@cuda threads=128 vector_add!(c, a, b) </syntaxhighlight> この例では、カスタムカーネルを128個のスレッドで並列に実行しています。並列処理のため、スレッド数はGPUのコア数に比例するように決定されます。また、結果を格納するために、CuArrays.@cudaマクロでsimialar()関数を使用して、ホストメモリ上にある変数cと同じ型の変数をGPUメモリ内で作成しています。 ===== まとめ ===== CuArraysを用いることで、juliaでGPUプログラミングを簡単に行うことができます。カスタムカーネルを利用することで、GPUの性能を最大限に引き出すことができ、数値計算や科学技術計算において高速な処理を実現することができます。 ==附録トップ== === 附録 === {{先頭に戻る}} ==== コードギャラリー ==== {{先頭に戻る|title=附録に戻る|label=附録|style=border-top:1px solid gray;}} :<syntaxhighlight lang=julia highlight=18 copy> </syntaxhighlight> :<syntaxhighlight lang=text> </syntaxhighlight> ===== エラトステネスの篩 ===== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} エラトステネスの篩を、若干 Julia らしく書いてみました。 ;エラトステネスの篩:<syntaxhighlight lang=julia line copy> function eratosthenes(n) is_prime = trues(n) # 全ての数を素数と仮定する is_prime[1] = false # 1は素数ではない # 篩い落とす for i in 2:isqrt(n) if is_prime[i] is_prime[i*i:i:n] .= false end end # 素数を抽出 return [i for i in 2:n if is_prime[i]] end println(eratosthenes(100)) </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] </syntaxhighlight> ===== クイックソート ===== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} クイックソートを、若干 Julia らしく書いてみました。 ;クイックソート:<syntaxhighlight lang=Julia line> function quicksort(ary, low, high) if low >= high return end pivot = ary[(low + high) ÷ 2] i = low j = high while i <= j while ary[i] < pivot i += 1 end while ary[j] > pivot j -= 1 end if i <= j ary[i], ary[j] = ary[j], ary[i] i += 1 j -= 1 end end quicksort(ary, low, j) quicksort(ary, i, high) end ary = [9, 5, 7, 2, 4, 1, 8, 3, 10, 6] println("Original Array:\t", ary) quicksort(ary, 1, length(ary)) println("Sorted Array:\t", ary)</syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> Original Array:[9, 5, 7, 2, 4, 1, 8, 3, 10, 6] Sorted Array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] </syntaxhighlight> ===== 最大公約数と最小公倍数 ===== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} 最大公約数と最小公倍数を、若干 Julia らしく書いてみました。 ;最大公約数と最小公倍数:<syntaxhighlight lang=julia line copy> # gcd2は2つの整数mとnの最大公約数を計算します。 # n == 0の場合はmを返し、それ以外の場合はユークリッドの互除法に基づいて最大公約数を計算します。 gcd2(m, n) = n == 0 ? m : gcd2(n, m % n) # gcdは任意の長さの整数の引数の最大公約数を計算します。 gcd(ints...) = reduce(gcd2, ints) # lcm2は2つの整数mとnの最小公倍数を計算します。 # m * n ÷ gcd2(m, n) は最小公倍数を計算しています。 lcm2(m, n) = m * n ÷ gcd2(m, n) # lcmは任意の長さの整数の引数の最小公倍数を計算します。 lcm(ints...) = reduce(lcm2, ints) # gcd2、gcd、lcm2、lcmの各関数を呼び出します。 println("gcd2(30, 45) => ", gcd2(30, 45)) println("gcd(30, 72, 12) => ", gcd(30, 72, 12)) println("lcm2(30, 72) => ", lcm2(30, 72)) println("lcm(30, 42, 72) => ", lcm(30, 42, 72)) </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> gcd2(30, 45) => 15 gcd(30, 72, 12) => 6 lcm2(30, 72) => 360 lcm(30, 42, 72) => 2520 </syntaxhighlight> ===== 二分法 ===== {{先頭に戻る|title=コード・ギャラリーに戻る|label=コードギャラリー|style=border-top:1px solid gray;}} [[W:二分法|二分法]]を、若干 Julia らしく書いてみました。 ;二分法:<syntaxhighlight lang=julia line copy> # bisectionは関数fが0に等しくなる実数xを二分法で検索します。 # lowとhighは関数fの値が0より小さい範囲の下限と上限です。 # xは現在の中点です。 # fxは関数fのxの値です。 function bisection(low, high, f) x = (low + high) / 2 fx = f(x) if abs(fx) < 1.0e-10 return x end if fx < 0.0 low = x else high = x end return bisection(low, high, f) end println(bisection(0, 3, (x) -> x - 1)) println(bisection(0, 3, (x) -> x * x - 1)) </syntaxhighlight> ;実行結果:<syntaxhighlight lang=text> 0.9999999999417923 1.0000000000291038 </syntaxhighlight> : [[旧課程(-2012年度)高等学校数学B/数値計算とコンピューター#2分法]]の例を Julia に移植しました。 ==== 改廃された技術 ==== {{先頭に戻る|title=附録に戻る|label=附録|style=border-top:1px solid gray;}} Juliaの改廃された技術や利用が推奨されない技術は、言語の進化、パフォーマンスの向上、シンプルさの追求、新しいプログラミングパラダイムへの対応により置き換えられます。以下に、代表的な技術を示します。 ===== Nullable 型 ===== * '''サポート開始年:''' 2015年(Julia 0.4) * '''サポート終了年:''' 2017年(Julia 0.7で非推奨、1.0で削除) ; 廃止または衰退の理由 : 型安全性の向上とAPIの一貫性を保つため、<code>Nullable</code>型は削除され、<code>Union{T, Nothing}</code>が推奨されるようになりました。 ; 代替技術 : <code>Union{T, Nothing}</code>または<code>Missing</code>型を使用してください。 ===== ASCIIストリング (<code>ASCIIString</code>) 型 ===== * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2015年(Julia 0.4で削除) ; 廃止または衰退の理由 : Unicode対応の<code>String</code>型に統一し、文字列操作の柔軟性を向上させるため削除されました。 ; 代替技術 : <code>String</code>型を使用してください。 ===== UTF8String 型 ===== * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2015年(Julia 0.4で削除) ; 廃止または衰退の理由 : 文字列型を<code>String</code>に一本化することで、メンテナンスの容易性とAPIの一貫性を向上させるため削除されました。 ; 代替技術 : <code>String</code>型を使用してください。 ===== 旧式の型パラメータ記法 ===== * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2018年(Julia 0.7で非推奨、1.0で削除) ; 廃止または衰退の理由 : 型パラメータ記法を統一し、コードの読みやすさと一貫性を向上させるため廃止されました。 ; 代替技術 : 角括弧<code><:T</code>を使用した新しい記法を利用してください(例: <code>Vector{T} where T<:Number</code>)。 ===== 旧式のドット演算子によるベクトル化 ===== * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2017年(Julia 0.6で非推奨、0.7で削除) ; 廃止または衰退の理由 : ブロードキャスト構文を導入することで、より効率的かつ直感的な配列操作を可能にするため廃止されました。 ; 代替技術 : <code>.</code>を用いたブロードキャスト演算(例: <code>f.(x)</code>や<code>x .+ y</code>)を使用してください。 ===== Dict 型の作成における===>演算子 === * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2018年(Julia 0.7で非推奨、1.0で削除) ; 廃止または衰退の理由 : シンプルで直感的な構文に統一するため変更されました。 ; 代替技術 : <code>Pair</code>型を使用する記法(例: <code>Dict(:a ===> 1, :b ===> 2)</code>)を使用してください。 ===== require()関数 ===== * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2018年(Julia 0.7で非推奨、1.0で削除) ; 廃止または衰退の理由 : モジュール管理のための<code>import</code>と<code>using</code>に統一することで、可読性と保守性を向上させるため削除されました。 ; 代替技術 : <code>import</code>または<code>using</code>を使用してください。 ===== IntSet 型 ===== * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2015年(Julia 0.4で削除) ; 廃止または衰退の理由 : <code>Set{Int}</code>が同等の機能を提供し、冗長な型を排除するため削除されました。 ; 代替技術 : <code>Set{Int}</code>型を使用してください。 ===== evalfile()関数 ===== * '''サポート開始年:''' 2012年(初期バージョン) * '''サポート終了年:''' 2018年(Julia 0.7で非推奨、1.0で削除) ; 廃止または衰退の理由 : 安全性や可読性の観点から非推奨化されました。 ; 代替技術 : スクリプトを実行する場合は<code>include()</code>を使用してください。 ==== 用語集 ==== ===== Julia言語で使用される用語の説明 ===== 以下は、Julia言語で使用される用語の説明です。 * 関数(Function): 特定の処理を行うための一連のプログラムのことを指します。Juliaでは、関数はfunctionキーワードで定義されます。 * 引数(Argument): 関数に渡される値のことを指します。引数は、関数の実行に必要な情報を提供します。 * パラメータ(Parameter): 関数の定義において、関数に渡される引数の型を指定するために使用される変数のことを指します。 * 戻り値(Return value): 関数の実行結果として、関数から返される値のことを指します。 * データ型(Data type): データの種類を表すために使用される型のことを指します。Juliaでは、Int、Float64、Stringなどのデータ型があります。 * 変数(Variable): データを格納するための場所のことを指します。Juliaでは、変数は、=演算子を使用して値を代入することができます。 * 代入(Assignment): 変数に値を格納するための演算子のことを指します。Juliaでは、=演算子が代入演算子として使用されます。 * 配列(Array): 複数の要素を格納するためのデータ型のことを指します。Juliaでは、Array{T, N}型があります。 * 要素(Element): 配列内に格納されている値のことを指します。 * インデックス(Index): 配列内の要素にアクセスするために使用される番号のことを指します。 * スライス(Slice): 配列から一部の要素を取り出すための操作のことを指します。 * ループ(Loop): 繰り返し処理を実行するための構文のことを指します。Juliaでは、for文やwhile文があります。 * 条件分岐(Conditional branching): 条件によって処理を分岐するための構文のことを指します。Juliaでは、if文があります。 * 例外処理(Exception handling): プログラムの実行中に発生した例外を処理するための仕組みのことを指します ==== チートシート ==== ===== Julia言語でよく使われる構文の一覧 ===== 以下は、Julia言語でよく使われる構文の一覧です。 :<syntaxhighlight lang=julia> # 関数の定義 function square(x) return x^2 end # 条件分岐 x = 3 if x > 0 println("x is positive") elseif x < 0 println("x is negative") else println("x is zero") end # ループ for i in 1:5 println(i) end # whileループ i = 1 while i <= 5 println(i) i += 1 end # 配列の要素の取得 array = [1, 2, 3, 4, 5] println(array[3]) # 配列のスライス println(array[2:4]) # 代入 x = 5 y = x + 2 println(y) # 比較演算子 x = 5 y = 3 println(x > y) </syntaxhighlight > [[カテゴリ:数値解析]] [[カテゴリ:プログラミング言語]] tkcrz2yyzflr0it2bz6y901qboj9rgd 高等学校工業 化学工学/化学工場の特徴 0 37422 263729 226027 2024-11-18T02:14:02Z Ef3 694 校閲と推敲 263729 wikitext text/x-wiki 化学工場とは、原料や中間体を用いて化学反応を行い、最終製品を作り出す製造工場のことです。 化学工場の歴史は古く、19世紀に始まった化学産業の発展とともに成長してきました。繊維や染料、薬品といった産業の発展を支えてきたとされています。化学工業は、工業革命後の需要に応える形で急速に発展し、その後も世界中で重要な産業分野として成長を続けています。 化学工場の特徴は、危険物を扱うことが多く、運転には高度な技術と安全管理が必要とされます。反応装置や輸送設備、貯蔵施設における漏れや事故のリスクを最小限に抑えるため、厳格な安全基準が設けられています。また、原材料の供給や製品の出荷には大規模なインフラストラクチャーが必要であり、膨大な資金と時間がかかることが特徴と言えます。これらの工場は、効率的かつ安全に運営されることが求められ、エネルギー消費や排出物の管理も重要な要素となります。 化学プラントとは、石油化学プラントやエネルギー化学プラントなど、化学工学技術を用いて原料から最終製品を製造するプラントのことです。一方、化学工場は、より一般的な工場を指し、化学反応を行って製品を作り出すことが主な目的となります。また、化学プラントは、化学工場の一部として稼働する場合があり、複雑な化学処理が求められる場合に使われます。化学プラントは、製品の規模や生産プロセスが大規模で高度であり、しばしば連続的な生産が行われるため、化学工場とは異なる管理や設計が要求されます。 化学工場は、製造業の一部門として産業界において位置しています。繊維や医薬品、化粧品、食品など、人々の生活に必要な多様な製品を生産しています。特に、化学工場が生産する化学製品は、日常生活に密接に関連しており、消費者の生活を支えています。たとえば、医薬品の製造は病気の治療や予防に貢献し、化粧品や洗剤などの製品は美容や衛生に欠かせないものとなっています。 また、新しい材料や製品の開発、クリーンエネルギーの研究といった分野でも化学工場は活躍しています。再生可能エネルギーの材料や高性能なバッテリーの開発は、地球環境への負荷を減らし、持続可能な社会を築くための重要な分野となっています。さらに、化学工場は、リサイクル技術の発展や環境負荷の低減にも貢献しており、現代社会における環境意識の高まりとともに、その役割はますます重要になっています。 {{DEFAULTSORT:かかくこうしようのとくちよう}} [[Category:高等学校工業]] [[Category:化学工学]] be2wq7a7uxfkhppmzrp6m7r71ca29nm Go/コードギャラリー 0 38820 263746 263474 2024-11-18T06:15:48Z Ef3 694 /* エラトステネスの篩 */ リファクタリング 263746 wikitext text/x-wiki {{Nav}} このコードギャラリーは、さまざまなGoの機能やパターン、ベストプラクティスを示すためのサンプルコード集です。 == エラトステネスの篩 == :<syntaxhighlight lang=go copy> package main import "fmt" func eratosthenes(n int) { sieve := make([]bool, n+1) for i := 2; i < len(sieve); i++ { sieve[i] = true } for i, isPrime := range sieve { if isPrime { for j := i * i; j <= n; j += i { sieve[j] = false } } if i*i >= n { break } } for i, isPrime := range sieve { if isPrime { fmt.Print(i, " ") } } } func main() { eratosthenes(100) } </syntaxhighlight> このGoのコードは、エラトステネスの篩を使って与えられた上限値以下の素数を見つけるものです。エラトステネスの篩は、素数を見つけるための古典的なアルゴリズムで、与えられた範囲内の素数を効率的に見つけることができます。 コードの主なポイントは次のとおりです: # <code>eratosthenes</code> 関数は、与えられた上限値 <code>n</code> 以下の素数を見つけるための関数です。 # <code>sieve</code> というブール型のスライスを作成し、初期値はすべて <code>true</code> に設定されます。このスライスは素数かどうかを示すために使用されます。 <code>sieve[0]</code> と <code>sieve[1]</code> は素数ではないため、それぞれゼロ値 <code>false</code> に設定されます。 # <code>i</code> が2から始まり、<code>n</code> までループします。もし <code>isPrime</code> が <code>true</code>(素数である)場合は、# <code>i</code> を素数として出力し、その後の倍数を <code>false</code> にします。これにより、素数の倍数は素数ではないとマークされます。 # 内側のループでは、<code>i</code> の倍数をすべて篩い落とすため、<code>j</code> を <code>i</code> の倍数として増やしながら <code>sieve[j]</code> を <code>false</code> にしています。 # <code>main</code> 関数では、<code>eratosthenes</code> 関数を呼び出して上限値が100以下の素数を見つけ、それを出力します。 このコードでは、エラトステネスの篩を用いて効率的に素数を見つける方法が示されています。 == 最大公約数と最小公倍数 == :<syntaxhighlight lang=go copy> package main import "fmt" func reduce(operation func(int, int) int, values []int) int { result := values[0] for _, value := range values[1:] { result = operation(result, value) } return result } func gcd2(m, n int) int { if n == 0 { return m } return gcd2(n, m%n) } func gcd(ints ...int) int { return reduce(gcd2, ints) } func lcm2(m, n int) int { return m * n / gcd2(m, n) } func lcm(ints ...int) int { return reduce(lcm2, ints) } func main() { fmt.Printf("gcd2(30, 45) => %d\n", gcd2(30, 45)) fmt.Printf("gcd(30, 72, 12) => %d\n", gcd(30, 72, 12)) fmt.Printf("lcm2(30, 72) => %d\n", lcm2(30, 72)) fmt.Printf("lcm(30, 42, 72) => %d\n", lcm(30, 42, 72)) } </syntaxhighlight> このGoのコードは、最大公約数(GCD)と最小公倍数(LCM)を計算する関数を提供しています。これらの関数は、与えられた整数の配列を処理し、それぞれの計算を行います。 * <code>reduce</code>関数は、2つの引数を取り、指定された二項演算(<code>operation</code>)をスライスの要素に対して適用するためのものです。 * <code>result</code>は初期値として最初の要素(<code>values[0]</code>)を取り、それ以降の要素に対して <code>operation</code> を適用していきます。 * スライスの範囲演算子 <code>values[1:]</code> を使用して、最初の要素を除いた残りの要素に対して操作を行います。 == 二分法 == [[W:二分法|二分法]] :<syntaxhighlight lang=go copy> package main import ( "fmt" "math" ) func bisection(low, high float64, f func(float64) float64) float64 { x := (low + high) / 2 fx := f(x) if math.Abs(fx) < 1.0e-10 { return x } if fx < 0.0 { low = x } else { high = x } return bisection(low, high, f) } func main() { result1 := bisection(0, 3, func(x float64) float64 { return x - 1 }) fmt.Println(result1) result2 := bisection(0, 3, func(x float64) float64 { return x*x - 1 }) fmt.Println(result2) } </syntaxhighlight> : [[旧課程(-2012年度)高等学校数学B/数値計算とコンピューター#2分法]]の例を Go に移植しました。 このGoのコードは、2分法を用いて与えられた関数の数値解を求める方法を示しています。 === <code>bisection</code> 関数 === * <code>bisection</code> 関数は、与えられた上限値と下限値の範囲内で数値解を見つけるためのものです。 * <code>low</code> と <code>high</code> は、数値解を探す範囲を示します。 * <code>f</code> は、数値解を求めたい関数です。 * <code>x := (low + high) / 2</code> で、範囲の中間点を計算します。 * <code>fx := f(x)</code> で、関数 <code>f</code> を中間点 <code>x</code> に適用し、その結果を <code>fx</code> に代入します。 * <code>math.Abs(fx) < 1.0e-10</code> は、絶対値が非常に小さい値となった場合、つまり数値解が見つかった場合の条件です。この場合、<code>x</code> を返して探索を終了します。 * <code>fx < 0.0</code> の場合は、<code>low</code> の範囲を <code>x</code> に設定し、それ以外の場合は <code>high</code> の範囲を <code>x</code> に設定します。これにより、次の探索範囲を絞り込んでいきます。 * 最後に、絞り込まれた新しい範囲で再帰的に <code>bisection</code> 関数を呼び出します。 === <code>main</code> 関数 === * <code>main</code> 関数では、<code>bisection</code> 関数を使用して数値解を求めます。 * まず、<code>x - 1</code> という関数に対して2分法を適用し、数値解を見つけます。次に、<code>x^2 - 1</code> という関数に対しても同様の手順で数値解を見つけます。 * それぞれの数値解を出力しています。 このコードは、数値解を見つけるための2分法を実装し、与えられた関数に対して数値解を計算する方法を示しています。 == 構造体とメソッド == Goにクラスはありませんが、構造体がメソッドを持つことが出来ます。 :<syntaxhighlight lang=go copy> package main import "fmt" // Hello 構造体 type Hello struct { s string // 挨拶文に含める文字列 } // NewHello Hello構造体のコンストラクタ func NewHello(s string) *Hello { if s == "" { s = "world" // デフォルト値を設定 } return &Hello{s: s} } // ToString 挨拶文を文字列で表現するメソッド func (h *Hello) ToString() string { return fmt.Sprintf("Hello %s!", h.s) } // Print 挨拶文を出力するメソッド func (h *Hello) Print() { fmt.Println(h.s) } func main() { hello1 := NewHello("") fmt.Println(hello1.ToString()) hello1.Print() hello2 := NewHello("my friend") fmt.Println(hello2.ToString()) hello2.Print() fmt.Printf(` Hello.constructor.name => Hello hello1 => %+v hello2.s => %s `, hello1, hello2.s) } </syntaxhighlight> このGoのコードは、<code>Hello</code> 構造体を定義し、それに関連する関数とメソッドを使って挨拶文を扱う方法を示しています。 === <code>Hello</code> 構造体と <code>NewHello</code> コンストラクタ === * <code>Hello</code> 構造体は、挨拶文に含める文字列 <code>s</code> を持ちます。 * <code>NewHello</code> 関数は、<code>Hello</code> 構造体のコンストラクタです。引数が空の場合はデフォルトで "world" を設定します。 === <code>ToString</code> メソッド === * <code>ToString</code> メソッドは、<code>Hello</code> 構造体のメソッドです。挨拶文を文字列で表現します。 === <code>Print</code> メソッド === * <code>Print</code> メソッドは、<code>Hello</code> 構造体のメソッドで、挨拶文を出力します。 === <code>main</code> 関数 === * <code>main</code> 関数では、<code>NewHello</code> コンストラクタを使って2つの <code>Hello</code> インスタンスを作成します。 * それぞれのインスタンスに対して <code>ToString</code> メソッドを呼び出し、挨拶文を表示します。 * 同様に、<code>Print</code> メソッドを呼び出して挨拶文を出力します。 * <code>Printf</code> 関数を使用して、コンストラクタの名前、<code>hello1</code> の詳細情報、および <code>hello2</code> の文字列を出力します。 このコードは、Go言語でクラスの代わりに構造体とメソッドを使用して、オブジェクト指向プログラミングの概念を模倣しています。それぞれのメソッドは、構造体のインスタンスに結びついており、そのインスタンスに対して操作を行います。 == 逆ポーランド記法の解析と評価 == 逆ポーランド記法は、数式の演算子を後置記法で表現する方法です。通常の中置記法では演算子がオペランドの間に置かれますが、逆ポーランド記法では演算子がオペランドの後ろに置かれます。これにより、括弧や演算子の優先順位を考える必要がなくなり、計算機で容易に評価できる形式になります。 例えば、中置記法での式 <code>3 + 4 * 5</code> は、逆ポーランド記法では <code>3 4 5 * +</code> と表現されます。この記法では、演算子が対象のオペランドに対して順番に適用されます。 :<syntaxhighlight lang=go copy> package main import ( "fmt" "strconv" "strings" ) func evaluateExpression(expression string) (int, error) { tokens := strings.Fields(expression) stack := make([]int, 0) for _, token := range tokens { switch token { case "+", "-", "*", "/": if len(stack) < 2 { return 0, fmt.Errorf("invalid expression: not enough operands for %s operator", token) } operand2 := stack[len(stack)-1] operand1 := stack[len(stack)-2] stack = stack[:len(stack)-2] var result int switch token { case "+": result = operand1 + operand2 case "-": result = operand1 - operand2 case "*": result = operand1 * operand2 case "/": if operand2 == 0 { return 0, fmt.Errorf("division by zero") } result = operand1 / operand2 } stack = append(stack, result) default: num, err := strconv.Atoi(token) if err != nil { return 0, fmt.Errorf("invalid expression: %v is not a number", token) } stack = append(stack, num) } } if len(stack) != 1 { return 0, fmt.Errorf("invalid expression: too many operands or operators") } return stack[0], nil } func main() { expression := "5 3 2 * + 8 2 / -" result, err := evaluateExpression(expression) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Result:", result) } } </syntaxhighlight> このGoのコードは、逆ポーランド記法(逆ポーランド式、Postfix Notation)を使用して算術式を評価します。 === <code>evaluateExpression</code> 関数 === * <code>evaluateExpression</code> 関数は、逆ポーランド記法の式を受け取り、計算結果とエラーを返す関数です。 * 式をトークンに分割し、それぞれのトークンをスタックに積んでいきます。 * 演算子を見つけた場合は、スタックから必要な数のオペランドを取り出して、演算を行います。その結果をスタックに戻します。 * 数字を見つけた場合は、文字列から整数に変換してスタックに積みます。 * 除算 (<code>/</code>) の際にゼロで割り算が発生しないように注意しています。 === <code>main</code> 関数 === * <code>main</code> 関数では、<code>evaluateExpression</code> 関数を使用して、与えられた逆ポーランド記法の式を評価します。 * 式 <code>"5 3 2 * + 8 2 / -"</code> を評価し、結果を出力します。 このプログラムは、逆ポーランド記法を使用して四則演算を行う方法を示しています。それぞれの演算子や数値をトークンとして扱い、スタックを使用して計算を進めます。計算結果を正しく得るために、演算子とオペランドの関係性を考慮して処理しています。 {{Nav}} {{DEFAULTSORT:こときやらり}} [[Category:Go]] pgp9pr8u4lvzhjs0auqrfppvbsxd5xu Java/改廃された技術 0 39006 263741 241837 2024-11-18T04:15:30Z Ef3 694 校閲と推敲 263741 wikitext text/x-wiki == 改廃された技術 == Javaの改廃された技術や利用が推奨されない技術は、技術の進化、新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 === Java Applet === * '''サポート開始年:''' 1995年 * '''サポート終了年:''' 2020年 ; 廃止または衰退の理由 : セキュリティ上の問題やHTML5などの新しいウェブテクノロジーの台頭により、主要ブラウザがJava Appletのサポートを終了しました。 ; 代替技術 : HTML5やJavaScriptによるウェブアプリケーションの開発が一般的です。 === 古いJavaバージョン === * '''対象:''' Java 8以前のバージョン ; 利用推奨されない理由 : セキュリティパッチの提供が終了しているため、セキュリティリスクが高まります。 ; 推奨バージョン : 最新のLTS(Long Term Support)バージョンを使用することが推奨されます(例: Java 17、Java 21など)。 === deprecatedなメソッドやクラス === * '''対象:''' Java API内でdeprecatedとマークされたメソッドやクラス ; 利用推奨されない理由 : 将来のバージョンで削除される可能性があるため、新規コードでの利用を避けるべきです。 ; 代替策 : 公式ドキュメントを参照し、推奨される新しいメソッドやクラスを使用してください。 === RMI (Remote Method Invocation) === * '''サポート開始年:''' 1997年 * '''サポート終了年:''' なし(ただし利用は減少) ; 廃止または衰退の理由 : 分散オブジェクトシステムとして設計されましたが、gRPCやRESTful Webサービスなど、より軽量でシンプルなRPCフレームワークが登場したため、利用が減少しています。 ; 代替技術 : gRPCやRESTful APIが主に使用されます。 === EJB (Enterprise JavaBeans) === * '''サポート開始年:''' 1998年 * '''サポート終了年:''' なし(ただし利用は減少) ; 廃止または衰退の理由 : エンタープライズアプリケーション開発のためのコンポーネントモデルでしたが、Spring FrameworkやQuarkusなど、軽量なフレームワークが普及したため、利用が減少しました。 ; 代替技術 : Spring Framework、Jakarta EE、またはMicronautが一般的です。 === AWT (Abstract Window Toolkit) === * '''サポート開始年:''' 1995年 * '''サポート終了年:''' なし(一部機能は置き換えられました) ; 廃止または衰退の理由 : SwingやJavaFXなど、より強力で柔軟なGUIツールキットが開発され、AWTの一部機能が非推奨化されました。 ; 代替技術 : SwingやJavaFXが主に使用されます。 === Java Web Start === * '''サポート開始年:''' 2001年 * '''サポート終了年:''' 2019年(Oracle JDK 11以降で廃止) ; 廃止または衰退の理由 : セキュリティ上の懸念やブラウザベンダーによるサポートの停止により利用が減少しました。 ; 代替技術 : Spring BootやQuarkusによるウェブアプリケーション、もしくはJavaScriptベースのフレームワーク。 === Java Servlet API 2.x === * '''サポート開始年:''' 1999年 * '''サポート終了年:''' 2009年(Servlet 3.0以降に置き換えられました) ; 廃止または衰退の理由 : Servlet 3.0以降で非同期処理やセキュリティ機能が追加され、古いバージョンが推奨されなくなりました。 ; 代替技術 : Servlet 3.0以降のバージョン、またはSpring MVCなどのフレームワーク。 === JavaBeans === * '''サポート開始年:''' 1996年 * '''サポート終了年:''' なし(現役で使用される場合もあり) ; 廃止または衰退の理由 : モダンなフレームワーク(Spring Frameworkなど)の登場により、一部利用が減少しました。 ; 代替技術 : Spring FrameworkやJakarta Bean Validationなどが使用されます。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Java]] 5kayrurd8evp3sudj69vppe1teni0rw Java/基礎/クラス 0 39012 263737 241960 2024-11-18T03:11:54Z Ef3 694 校閲と推敲 263737 wikitext text/x-wiki {{Nav}} = クラス = クラスは、オブジェクト指向プログラミングの基本概念であり、データ(フィールド)と操作(メソッド)をまとめた設計図です。このセクションでは、Javaにおけるクラスの構造と使用方法を説明します。 == クラスの基本 == Javaにおけるクラスは、オブジェクトの属性と振る舞いを定義するための青写真です。クラスを基にしてオブジェクトを作成し、そのオブジェクトがプログラムで使用されます。 === クラスの役割 === * '''データの格納''' - クラスは、オブジェクトの状態を保持するためのフィールドを提供します。 * '''操作の実装''' - クラスは、オブジェクトが実行できるメソッドを定義します。 * '''コードの再利用''' - クラスを使用すると、共通の機能を再利用可能な単位として構築できます。 {{Main|Java/文法/クラス}} == Javaにおけるクラスの定義 == Javaでクラスを定義する際の構造と基本的な宣言方法を以下に示します。 === クラスの宣言 === 以下は、基本的なクラスの宣言例です。 :<syntaxhighlight lang=java copy> public class MyClass { // フィールド int myField; // メソッド void myMethod() { System.out.println("Hello, World!"); } } </syntaxhighlight> * <code>public</code>: このクラスが他のクラスからアクセス可能であることを示すアクセス修飾子。 * <code>class</code>: クラスを宣言するキーワード。 * <code>MyClass</code>: クラスの名前。 === インスタンス化とオブジェクトの作成 === クラスからオブジェクトを生成するには、<code>new</code> キーワードを使用します。 :<syntaxhighlight lang=java copy> MyClass myObject = new MyClass(); </syntaxhighlight> * <code>new</code>: メモリにオブジェクトを確保し、コンストラクタを呼び出します。 === フィールドとメソッドへのアクセス === オブジェクトを通じてフィールドやメソッドにアクセスします。 :<syntaxhighlight lang=java copy> myObject.myField = 10; // フィールドに値を代入 myObject.myMethod(); // メソッドを呼び出す </syntaxhighlight> == クラスの活用例 == 以下は、クラスを利用した簡単なプログラムの例です。 :<syntaxhighlight lang=java copy> public class Main { public static void main(String[] args) { MyClass myObject = new MyClass(); myObject.myField = 20; myObject.myMethod(); // "Hello, World!" を出力 } } </syntaxhighlight> === プログラムの解説 === * <code>Main</code> クラスはプログラムのエントリーポイントです。 * <code>MyClass</code> オブジェクトが生成され、<code>myField</code> に値を設定し、<code>myMethod</code> を呼び出しています。 == まとめ == クラスは、Javaにおけるオブジェクト指向プログラミングの基盤であり、コードの再利用性や管理の効率化に寄与します。この基本を理解することで、より複雑なオブジェクト指向プログラミングを習得するための基礎が築かれます。 {{Nav}} {{DEFAULTSORT:くらす}} [[Category:Java]] gg5ovrgnc2j4xd2psuwh4oiz1381nd1 Java/Optional 0 39013 263731 241953 2024-11-18T02:25:32Z Ef3 694 校閲と推敲 263731 wikitext text/x-wiki {{Nav}} == NULL許容型 == NULL許容型(nullable type)は、プログラミング言語において、変数が値を持たないことを明示的に許容する型のことです。通常、NULL許容型は、値が存在しないことを示すために特別な値(通常はNULL、nil、またはundefinedなど)を持ちます。 NULL許容型の主な目的は、nullポインタ例外などのランタイムエラーを回避し、プログラムの安全性を向上させることです。これにより、プログラマーは値が存在しない場合に備えて適切にコードを記述することができます。 多くのプログラミング言語でNULL許容型がサポートされています。例えば、JavaのOptional型、SwiftのOptional型、C#のNullable型などがあります。これらの型は、値が存在しない場合を明示的に示すことで、コードの安全性と可読性を向上させます。 以下は、各プログラミング言語におけるNULL許容型の例です: {| class="wikitable" |+ 各プログラミング言語におけるNULL許容型の例 !型 !言語 !説明 |- |Optional<T> |Java |JavaのOptional型は、値が存在しない場合にnullではなくOptional.empty()を返すため、nullポインタ例外を回避し、コードの安全性を向上させます。 |- |Type? |Kotlin |KotlinのNullable型は、変数やプロパティの型の末尾に "?" を付けることで、その変数やプロパティがnullを許容するNullable型として扱われます。 |- |Option<T> |Scala |ScalaのOption型は、Some値を持つ場合は値が存在し、Noneを持つ場合は値が存在しないことを示します。これにより、nullチェックやnullポインタ例外を回避することができます。 |- |Nullable<T> |C# |C#のNullable型は、値型にnullを割り当てるための型です。通常の値型ではnullを許可しないため、Nullable型を使用することでnull許容型を表現します。 |- |Optional<T> |Swift |SwiftのOptional型は、値が存在する場合はSome値を持ち、値が存在しない場合はnilを持ちます。これにより、nilチェックやnilによるクラッシュを回避するために使用されます。 |} == Optional == JavaのOptionalは、Java 8で導入されたクラスで、nullセキュリティという問題に対処するための手段の1つです。Optionalは、値が存在するかどうかを示すラッパークラスであり、nullを明示的に処理することなく、値の有無を安全に操作するための手段を提供します。 Optionalは以下のように使用できます: # Optionalの作成: Optional.ofNullable() メソッドを使用して、可能性のあるnull値を含むオブジェクトからOptionalを作成できます。 #:<syntaxhighlight lang=java copy> String str = null; Optional<String> optionalStr = Optional.ofNullable(str); </syntaxhighlight> # 値の取得: 値が存在する場合、Optional.get() メソッドを使用してその値を取得できます。ただし、値が存在しない場合は NoSuchElementException がスローされる可能性がありますので、Optional.isPresent() メソッドを使用して事前に値の存在を確認することが重要です。 #:<syntaxhighlight lang=java copy> if (optionalStr.isPresent()) { String value = optionalStr.get(); System.out.println("Value: " + value); } else { System.out.println("Value is not present."); } </syntaxhighlight> # 値の存在確認とデフォルト値の提供: 値が存在しない場合にデフォルト値を提供する場合は、Optional.orElse() メソッドを使用できます。 #:<syntaxhighlight lang=java copy> String valueOrDefault = optionalStr.orElse("Default Value"); </syntaxhighlight> # 値の存在確認と値の処理: 値が存在する場合のみ、値に対して処理を行いたい場合は、Optional.ifPresent() メソッドを使用できます。 #:<syntaxhighlight lang=java copy> optionalStr.ifPresent(value -> System.out.println("Value: " + value)); </syntaxhighlight> Optionalは、null値の扱いに関するバグを減らし、より安全で明確なコードを作成するのに役立ちます。 ただし、Optionalを過度に使用することは、コードを複雑にする可能性があるため、適切なバランスが必要です。 以下は、JavaのOptionalクラスの一部の主要なメソッドとその説明を表形式で示したものです。 {| class="wikitable" |+ Optionalクラスの主要なメソッド一覧 !メソッド !説明 |- |<code>empty()</code> |空のOptionalインスタンスを作成します。 |- |<code>of(T value)</code> |指定された非nullの値でOptionalインスタンスを作成します。 |- |<code>ofNullable(T value)</code> |指定された値がnullであれば空のOptional、そうでなければその値でOptionalインスタンスを作成します。 |- |<code>isPresent()</code> |Optionalに値が含まれている場合はtrueを返します。 |- |<code>ifPresent(Consumer<? super T> consumer)</code> |Optionalが値を含んでいる場合、指定されたコンシューマー関数を値に適用します。 |- |<code>get()</code> |値を取得します。値が存在しない場合は例外NoSuchElementExceptionをスローします。 |- |<code>orElse(T other)</code> |値が存在する場合はその値を返し、そうでなければ指定された値を返します。 |- |<code>orElseGet(Supplier<? extends T> supplier)</code> |値が存在する場合はその値を返し、そうでなければサプライヤー関数の結果を返します。 |- |<code>orElseThrow(Supplier<? extends X> exceptionSupplier)</code> |値が存在する場合はその値を返し、そうでなければ指定された例外をスローします。 |- |<code>filter(Predicate<? super T> predicate)</code> |値が述語によってテストされ、述語がtrueを返した場合はこのOptionalを返します。それ以外の場合は空のOptionalを返します。 |- |<code>map(Function<? super T, ? extends U> mapper)</code> |値を関数に適用し、結果が非nullであればそれを含むOptionalを返します。そうでなければ空のOptionalを返します。 |- |<code>flatMap(Function<? super T, Optional<nowiki><U>> mapper)</nowiki></code> |値を関数に適用し、結果が空のOptionalでない場合はそのOptionalを返します。そうでなければ空のOptionalを返します。 |- |<code>equals(Object obj)</code> |指定されたオブジェクトがこのOptionalと等しいかどうかを比較します。 |- |<code>hashCode()</code> |Optionalのハッシュコード値を返します。 |- |<code>toString()</code> |Optionalの文字列表現を返します。 |} これらのメソッドは、Java 8からOptionalクラスで導入され、nullを避けるために便利な方法を提供します。 == Optionalが出来ても、参照型はnullを取り得る == Optionalはnullを扱う際の安全性を向上させるための手段ですが、参照型には依然としてnullを取り得るという点に留意する必要があります。 Optionalは、主にnullを返す可能性のあるメソッドの戻り値や、メソッドの引数として使用されます。しかし、既存のコードや外部ライブラリとの連携、あるいは一時的なnull値の許容など、様々な理由でnullが依然として存在することがあります。 そのため、Optionalを使用することでnullの扱いを明確にすることができますが、すべてのnullを完全に排除することは難しい場合があります。したがって、プログラマーは依然としてnullの可能性に備えてコードを記述する必要があります。 {{Nav}} {{DEFAULTSORT:OPTIONAL}} [[Category:Java]] a27j5f7wkj2u55g97h8li4t8a9f8mpr Java/基礎/配列 0 39016 263736 242270 2024-11-18T03:01:45Z Ef3 694 校閲と推敲 263736 wikitext text/x-wiki {{Nav}} = 配列 = プログラミングにおける配列(Array)は、同じデータ型の要素が連続して格納されたデータ構造です。配列は、複数の値を一つの変数に格納するために使用され、要素はインデックス(通常は0から始まる整数)によって識別されます。効率的なデータアクセスと操作が可能で、データの集合を扱う際に重要な役割を果たします。 == 配列の特性 == 配列の主な特性は以下の通りです: # '''同じデータ型の要素''': 配列内のすべての要素は同じデータ型である必要があります。 # '''連続したメモリ領域''': 配列の要素は連続したメモリ領域に格納されます。 # '''要素のインデックス''': 通常、0から始まる整数インデックスでアクセスされます。 # '''固定サイズ''': 配列のサイズは作成時に決まり、変更できません。 == Javaの配列 == Javaの配列は、以下の特徴を持ちます: * オブジェクトとして扱われる。 * 固定サイズで、要素はインデックスを用いてアクセス可能。 === 基本操作 === 以下に配列の基本操作を示します。 :<syntaxhighlight lang=java copy> import java.util.Arrays; public class ArrayExample { public static void main(String[] args) { // 配列の宣言と初期化 int[] numbers = {5, 2, 7, 1, 9}; // 配列の要素へのアクセス System.out.println("First element: " + numbers[0]); // 配列の長さを取得 System.out.println("Array length: " + numbers.length); // 拡張forループで要素を反復 for (int num : numbers) { System.out.println(num); } // 配列のコピー int[] copy = Arrays.copyOf(numbers, numbers.length); System.out.println("Copied array: " + Arrays.toString(copy)); // 配列のソート Arrays.sort(numbers); System.out.println("Sorted array: " + Arrays.toString(numbers)); // 配列の比較 int[] numbers2 = {1, 2, 5, 7, 9}; System.out.println("Arrays are equal: " + Arrays.equals(numbers, numbers2)); } } </syntaxhighlight> このコードは、配列の基本的な操作を示しており、Javaの<code>java.util.Arrays</code>クラスが提供する便利なメソッドを活用しています。 === 配列の主なメソッド === 以下は、<code>java.util.Arrays</code>クラスで提供される主なメソッド一覧です。 :{| class="wikitable" |+ 配列のメソッド一覧 ! メソッド !! 説明 |- | <code>copyOf()</code> || 配列を指定した長さでコピーします。 |- | <code>sort()</code> || 配列を昇順にソートします。 |- | <code>equals()</code> || 配列同士を比較します。 |- | <code>binarySearch()</code> || ソートされた配列で二分探索を行います。 |- | <code>fill()</code> || 配列の全要素を指定値で初期化します。 |- | <code>toString()</code> || 配列を文字列として返します。 |} == 多次元配列 == 多次元配列は、配列の要素が配列となる構造です。以下は2次元および3次元配列の例です。 :<syntaxhighlight lang=java copy> // 2次元配列の宣言 int[][] twoDimArray = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; // 3次元配列の宣言 int[][][] threeDimArray = { { {1, 2}, {3, 4} }, { {5, 6}, {7, 8} } }; </syntaxhighlight> 多次元配列はネストされたforループで反復処理することが一般的です。 :<syntaxhighlight lang=java copy> // 2次元配列の反復処理 for (int[] row : twoDimArray) { for (int element : row) { System.out.print(element + " "); } System.out.println(); } </syntaxhighlight> == 参考文献 == * [https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html java.util.Arrays] {{Nav}} {{DEFAULTSORT:はいれつ}} [[Category:Java]] [[Category:配列|Java]] 1k61zn4p2v47hps5vy7oppo21ey48rh Java/基礎/文字列 0 39017 263728 241956 2024-11-18T00:24:41Z Ef3 694 校閲と推敲。サロゲートペアの説明を含め、Java 17以降の機能も記載。 263728 wikitext text/x-wiki {{Nav}} = 文字列 = プログラミングにおける文字列(String)は、文字の連続した列を表すデータ型です。文字列は、テキストや文字データを扱うための基本的なデータ構造であり、多くのプログラミング言語でサポートされています。 == 概要 == 文字列は、文字の配列として内部的に表現されます。各文字は、主にUnicodeやASCIIなどの文字コードで符号化され、文字列全体はそれらの文字の連続したシーケンスとして表現されます。 === 主な用途 === 文字列は、以下のような多様な用途で使用されます: # '''テキスト処理''' #* ユーザー入力の処理 #* ファイルの読み書き #* テキストの検索、置換、分割 #* 正規表現によるパターンマッチング # '''データ表現''' #* JSONやXMLなどの構造化データ #* URLやファイルパス #* 設定ファイルの内容 #* データベースクエリ # '''出力とフォーマット''' #* ログメッセージ #* 多言語対応(i18n)テキスト #* レポート生成 #* テンプレート処理 == Javaの文字列 == Javaの文字列は<code>java.lang.String</code>クラスで実装される不変(イミュータブル)なオブジェクトです。 === 文字とエンコーディング === Javaの文字列では、文字はUnicodeで表現されます: # '''文字の内部表現''' #* 基本的な文字は16ビットのchar型で表現 #* サロゲートペアを必要とする文字(絵文字や特殊な漢字など)は2つのchar値で表現 #* 文字列長(<code>length()</code>)はchar単位で計算されるため、サロゲートペアは2とカウント :<syntaxhighlight lang=java copy> public class StringEncodingExample { public static void main(String[] args) { // サロゲートペアを含む文字列 String text = "𠮷野家"; // "𠮷"は1文字だがサロゲートペア System.out.println("文字列の長さ: " + text.length()); // 4を表示("𠮷"が2文字分) // コードポイント単位での処理 System.out.println("実際の文字数: " + text.codePointCount(0, text.length())); // 3を表示 // 文字列内の各文字(コードポイント)を処理 text.codePoints().forEach(codePoint -> { System.out.printf("U+%04X ", codePoint); // Unicode コードポイントを16進数で表示 }); } } </syntaxhighlight> === 文字列操作の基本 === 以下は最新のJava(Java 17以降)での文字列操作の基本例です: :<syntaxhighlight lang=java copy> public class ModernStringExample { public static void main(String[] args) { // テキストブロック(Java 15以降) String multiLine = """ 複数行の テキストを 自然に書けます。 """; // 文字列結合(Java 11以降のrepeat()) String repeated = "Hello ".repeat(3); // 空白処理(Java 11以降) String text = " Hello, World! "; System.out.println(text.strip()); // 前後の空白を除去(Unicode対応) System.out.println(text.trim()); // 従来の空白除去 System.out.println("".isBlank()); // true(空または空白文字のみ) // 文字列変換(Java 17以降) String transformed = text .transform(String::strip) .transform(String::toUpperCase); // 行単位の処理(Java 11以降) multiLine.lines() .map(String::trim) .filter(line -> !line.isBlank()) .forEach(System.out::println); } } </syntaxhighlight> === メソッド一覧 === :{| class="wikitable" |+ 主要な文字列メソッド !メソッド !説明 !導入バージョン |- |<code>codePointAt(int index)</code> |指定位置のUnicodeコードポイントを取得 |Java 5 |- |<code>codePointCount(int begin, int end)</code> |指定範囲のコードポイント数を取得 |Java 5 |- |<code>strip()</code> |Unicode対応の空白除去 |Java 11 |- |<code>isBlank()</code> |空白文字のみかを判定 |Java 11 |- |<code>transform(Function<String,R> f)</code> |文字列に関数を適用 |Java 17 |- |<code>indent(int n)</code> |行のインデントを調整 |Java 17 |} === パフォーマンスと最適化 === 文字列処理を効率的に行うためのベストプラクティス: # '''StringBuilder の使用''' #* 大量の文字列結合には<code>StringBuilder</code>を使用 #* <code>String + String</code>の代わりに<code>StringBuilder.append()</code>を使用 # '''適切な文字処理''' #* サロゲートペアを含む可能性がある場合は<code>codePoints()</code>を使用 #* 文字数のカウントには<code>codePointCount()</code>を使用 # '''メモリ効率''' #* コンパクト文字列(Java 9以降): ASCII文字のみの場合、内部的に1バイト/文字で格納 #* 文字列プール: <code>intern()</code>メソッドによる文字列の共有 :<syntaxhighlight lang=java copy> public class StringPerformanceExample { public static void main(String[] args) { // 効率的な文字列結合 StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.append("Item ").append(i).append(", "); } String result = sb.toString(); // サロゲートペアを含む文字列の適切な処理 String text = "🌟Hello🌍"; // 絵文字を含む int charCount = text.length(); // 文字単位(不適切) int codePoints = text.codePointCount(0, text.length()); // 実際の文字数(適切) System.out.println("char count: " + charCount); // 7 (各絵文字が2文字としてカウント) System.out.println("actual count: " + codePoints); // 5 (実際の文字数) } } </syntaxhighlight> {{Nav}} {{DEFAULTSORT:もしれつ}} [[Category:Java]] ilbsyleuqqhym3p5sjyah0fty80eewx Java/基礎/コレクション 0 39018 263730 241959 2024-11-18T02:16:15Z Ef3 694 校閲と推敲 263730 wikitext text/x-wiki {{Nav}} = コレクション = プログラミングにおけるコレクション(Collection)は、複数の要素をまとめて管理するためのデータ構造です。コレクションは、配列やリスト、セット、マップなど、さまざまな形式で提供されます。これらのデータ構造は、異なる目的や要件に応じて使われ、データの格納、検索、操作、管理を行うための便利な手段として利用されます。 コレクションの主な特徴は以下の通りです: # '''動的サイズ:''' コレクションは通常、要素の追加や削除などの操作によって動的にサイズが変化します。配列のように固定サイズではなく、必要に応じて要素を増減させることができます。 # '''ジェネリック:''' 多くの場合、コレクションはジェネリック型をサポートしており、異なるデータ型の要素を格納することができます。これにより、汎用的なコレクションを作成し、様々な種類のデータを扱うことが可能になります。 # '''高度な操作:''' コレクションは、要素の追加、削除、検索、ソート、フィルタリングなど、さまざまな操作をサポートします。これにより、効率的なデータの管理や処理が可能になります。 # '''相互変換:''' コレクション間でデータを相互変換することができる場合があります。たとえば、配列をリストに変換したり、リストをセットに変換したりすることができます。 プログラミングにおけるコレクションは、さまざまな用途に活用されます。例えば、データの一時的な保存や処理、データの集計や集合演算、データの操作や変換など、さまざまな場面で利用されます。多くのプログラミング言語やフレームワークは、標準ライブラリやサードパーティライブラリを通じてさまざまなコレクションを提供しています。 == Javaのコレクション == Javaのコレクションは、複数の要素を格納し、効率的なデータ操作を可能にするためのフレームワークです。Javaのコレクションフレームワークは、<code>java.util</code>パッケージに含まれており、さまざまなインターフェースとそれらを実装するクラスが提供されています。主なコレクションインターフェースには、リスト、セット、マップなどがあります。 以下は、Javaのコレクションフレームワークを使った例を1つのソースコードにまとめたものです。 :<syntaxhighlight lang=java copy> import java.util.ArrayList; import java.util.HashSet; import java.util.HashMap; import java.util.LinkedList; import java.util.ArrayDeque; public class CollectionQuickTour { public static void main(String[] args) { // リストの例 var myList = new ArrayList<String>(); myList.add("Apple"); myList.add("Banana"); myList.add("Cherry"); System.out.print("List: " + myList); System.out.println("; The type of myList is: " + myList.getClass().getName()); // セットの例 var mySet = new HashSet<Integer>(); mySet.add(1); mySet.add(2); mySet.add(3); mySet.add(1); // 重複した要素は無視される System.out.print("Set: " + mySet); System.out.println("; The type of mySet is: " + mySet.getClass().getName()); // マップの例 var myMap = new HashMap<String, Integer>(); myMap.put("One", 1); myMap.put("Two", 2); myMap.put("Three", 3); System.out.print("Map: " + myMap); System.out.println("; The type of mySet is: " + myMap.getClass().getName()); // キューの例 var myQueue = new LinkedList<String>(); myQueue.add("First"); myQueue.add("Second"); myQueue.add("Third"); System.out.print("Queue: " + myQueue); System.out.println("; The type of myQueue is: " + myQueue.getClass().getName()); // デッキの例 var myDeque = new ArrayDeque<Integer>(); myDeque.addFirst(1); myDeque.addLast(2); myDeque.addLast(3); System.out.print("Deque: " + myDeque); System.out.println("; The type of myDeque is: " + myDeque.getClass().getName()); } } </syntaxhighlight> このコードでは、リスト、セット、マップ、キュー、デッキのそれぞれのコレクションを作成し、要素を追加しています。それぞれのコレクションの要素が出力されます。これにより、Javaのコレクションフレームワークの基本的な使い方を示しています。 以下は、Javaのコレクションフレームワークに含まれる主要なクラスとインターフェースの一覧を、名前、クラス・インターフェースの別、説明の順に表組みで示したものです。 :{| class=wikitable |+ コレクションフレームワークに含まれる主要なクラスとインターフェース一覧 |- !名前 !クラス・インターフェースの別 !説明 |- !Collection |インターフェース |オブジェクトのコレクションを表します。リスト、セット、キューなどの基本的な操作を提供します。 |- !List |インターフェース |順序付きの要素のコレクションを表します。要素の重複を許します。 |- !Set |インターフェース |重複を許さない要素のコレクションを表します。 |- !Map |インターフェース |キーと値のペアのコレクションを表します。キーは一意であり、各キーには1つの値が関連付けられます。 |- !Queue |インターフェース |FIFO (First-In-First-Out) データ構造を表します。要素の挿入はキューの末尾に行われ、削除はキューの先頭から行われます。 |- !Deque |インターフェース |双方向キュー (Double Ended Queue) データ構造を表します。要素の挿入と削除がキューの両端で行われます。 |- !ArrayList |クラス |動的配列を実装したリストです。 |- !LinkedList |クラス |リンクリストを実装したリストです。 |- !HashSet |クラス |ハッシュテーブルを使用して実装されたセットです。 |- !TreeSet |クラス |赤黒木を使用して実装されたセットです。要素は自然順序またはコンパレータによってソートされます。 |- !LinkedHashSet |クラス |ハッシュテーブルとリンクリストを組み合わせて実装されたセットです。要素の挿入順序を保持します。 |- !HashMap |クラス |ハッシュテーブルを使用して実装されたマップです。 |- !TreeMap |クラス |赤黒木を使用して実装されたマップです。キーは自然順序またはコンパレータによってソートされます。 |- !LinkedHashMap |クラス |ハッシュテーブルと双方向リンクリストを組み合わせて実装されたマップです。要素の挿入順序を保持します。 |} これらのクラスとインターフェースは、Javaのコレクションフレームワークを構成し、さまざまなデータ構造を効率的に操作するための手段を提供します。 === コレクションフレームワーク === Javaのコレクションフレームワークは、データを効率的に管理し、操作するための標準的なAPIセットです。これにより、プログラマーはリスト、セット、マップなどのさまざまなデータ構造を使用してデータを格納し、操作することができます。Javaのコレクションフレームワークは、<code>java.util</code>パッケージに含まれており、多くのインターフェースとクラスから構成されています。 コレクションフレームワークの主な特徴は次のとおりです: # '''柔軟性:''' コレクションフレームワークは、異なる種類のデータ構造を提供し、プログラマーがプログラムの要件に応じて適切なデータ構造を選択できるようにします。 # '''再利用性:''' 既存のコレクションクラスやインターフェースを使用することで、プログラマーは再利用可能なコードを作成しやすくなります。 # '''拡張性:''' コレクションフレームワークは、カスタムコレクションの作成や既存のコレクションの拡張を容易にします。プログラマーは独自のデータ構造を定義し、それをコレクションとして使用することができます。 # '''効率性:''' コレクションフレームワークは、データの効率的な格納、検索、操作を実現するために最適化されています。さまざまなデータ構造は、特定の操作に対して最適な性能を提供します。 # '''型安全性:''' ジェネリクスを使用することで、コンパイル時の型安全性が向上します。これにより、コンパイル時に型エラーを検出しやすくなります。 コレクションフレームワークは、Javaプログラミングにおいて非常に重要であり、さまざまなアプリケーションやライブラリで広く使用されています。プログラマーは、これらのAPIを十分に理解し、適切に活用することで、効率的で堅牢なコードを作成することができます。 {{Nav}} [[カテゴリ:Java|きそ はいれつ]] sxnyjm5l0m4o60j002trc8ia4exogai Java/基礎/例外処理 0 39019 263734 241961 2024-11-18T02:48:06Z Ef3 694 /*モダンな例外処理 */Java7以降の追加機能を加筆 263734 wikitext text/x-wiki {{Nav}} = 例外処理 = プログラミングにおける例外処理は、プログラムが実行中に発生する予期しないエラーや異常な状況に対処するための仕組みや手法を指します。プログラムが実行中にエラーが発生する可能性がある場合、例外処理はプログラムの安定性を維持し、クラッシュや異常終了を防ぎます。 以下は、プログラミングにおける例外処理の基本的な概念です: # '''例外の発生:''' プログラムが実行中にエラーが発生すると、通常のプログラムのフローが中断されます。このような状況を例外と呼びます。例外は、ゼロ除算、配列の範囲外アクセス、ファイルが見つからないなどのさまざまな条件で発生します。 # '''例外のスロー:''' プログラム内の特定の箇所で、例外が発生したことを明示的に示すことができます。この動作を例外のスローと呼びます。通常、特定の条件が満たされた場合やエラーが発生した場合に、例外をスローします。 # '''例外のキャッチ:''' プログラム内で例外がスローされた場合、適切な処理を行うために例外をキャッチすることができます。この動作を例外のキャッチと呼びます。例外をキャッチすることで、プログラムは正常に処理を継続するか、エラーを適切に通知することができます。 # '''例外ハンドリング:''' 例外をキャッチして処理する手法を例外ハンドリングと呼びます。例外ハンドリングでは、例外をキャッチし、エラーをログに記録したり、ユーザーにエラーメッセージを表示したり、プログラムの状態を回復させたりすることができます。 例外処理は、プログラミングにおいて非常に重要です。適切に実装された例外処理は、プログラムの安定性を高め、ユーザーエクスペリエンスを向上させるのに役立ちます。また、例外処理はデバッグや問題解決の際にも役立ちます。 == Javaの例外処理 == Javaの例外処理は、プログラム実行中に予期しない状況やエラーが発生した場合に、その状況を適切に処理するための仕組みです。Javaの例外処理は、プログラムの安全性や信頼性を高めるために非常に重要です。 例外は、実行時に発生するエラーの種類や条件を表します。例えば、ゼロ除算、配列の範囲外へのアクセス、ファイルが見つからないなどのエラーは、Javaの例外処理を使用して適切に処理することができます。 Javaの例外処理は以下のような特徴を持ちます: # '''例外クラスの階層構造:''' Javaでは、<code>Throwable</code> クラスを基底クラスとして、例外を表すさまざまなクラスが階層的に定義されています。<code>Throwable</code> クラスのサブクラスには、<code>Exception</code>(検査例外)や <code>RuntimeException</code>(非検査例外)などがあります。 # '''try-catch-finally ブロック:''' Javaでは、<code>try</code> ブロック内で例外が発生する可能性のあるコードを囲み、それに対する処理を <code>catch</code> ブロックで定義します。また、<code>finally</code> ブロックを使用して、例外の発生にかかわらず必ず実行される処理を記述することができます。 # '''例外のスロー:''' メソッド内で発生した例外を明示的に処理せずに、呼び出し元に例外をスローすることができます。これにより、例外を適切な場所で処理することができます。 # '''検査例外と非検査例外:''' Javaでは、検査例外(checked exception)と非検査例外(unchecked exception)の2種類の例外があります。検査例外はコンパイル時にチェックされるため、明示的に処理するか、メソッドの throws 宣言で伝播させる必要があります。一方、非検査例外は実行時に発生し、明示的な処理が必要ありません。 Javaの例外処理は、プログラムのロバストさを向上させ、予期しない状況に対処するための重要な手段です。例外処理を適切に使用することで、プログラムの安全性や信頼性を向上させることができます。 以下は、Javaの例外処理を1つのソースコードで解説したものです。 :<syntaxhighlight lang=java copy> public class ExceptionHandlingQuickTour { public static void main(String[] args) { try { // 例外が発生する可能性のあるコード int result = divide(10, 0); System.out.println("結果: " + result); // この行は実行されません } catch (ArithmeticException e) { // ArithmeticException が発生した場合の処理 System.out.println("0 で割ることはできません。"); } finally { // 必ず実行されるブロック System.out.println("プログラムの実行が完了しました。"); } } // 例外をスローする可能性のあるメソッド public static int divide(int num1, int num2) { if (num2 == 0) { throw new ArithmeticException("0 で割ることはできません。"); } return num1 / num2; } } </syntaxhighlight> この例では、次のような内容を含んでいます: # <code>main</code> メソッド内で <code>try-catch-finally</code> ブロックが使用されています。<code>try</code> ブロック内では例外が発生する可能性のあるコードが配置され、<code>catch</code> ブロックでは特定の例外が発生した場合の処理が定義されています。<code>finally</code> ブロックは例外の発生にかかわらず必ず実行されるブロックです。 # <code>divide</code> メソッドは、引数 <code>num2</code> が 0 の場合に <code>ArithmeticException</code> をスローする可能性があります。 # <code>main</code> メソッドでは、<code>divide</code> メソッドを呼び出し、0 で割るエラーが発生した場合に <code>ArithmeticException</code> をキャッチし、適切なメッセージを出力します。 # <code>finally</code> ブロックは、プログラムが正常に終了したかどうかに関係なく、必ず実行されることが保証されています。 === throws === Javaには <code>throws</code> キーワードがあります。<code>throws</code> キーワードは、メソッドが特定の例外をスローする可能性があることを宣言するために使用されます。 メソッドが特定の例外をスローする可能性がある場合、そのメソッドのシグネチャに <code>throws</code> キーワードを使用して、その例外を指定します。これにより、メソッドを呼び出す際に、呼び出し元がその例外を適切に処理するか、またはさらに上位の呼び出し元に例外を伝播させるかを決定できます。 例えば: :<syntaxhighlight lang=java copy> public void readFile() throws IOException { // ファイルを読み込む処理 } </syntaxhighlight> この例では、<code>readFile</code> メソッドが <code>IOException</code> をスローする可能性があることが宣言されています。メソッド内で <code>IOException</code> が発生する可能性がある場合、その例外をキャッチして処理するか、または <code>readFile</code> メソッドの呼び出し元で <code>try-catch</code> ブロックを使用して例外を処理する必要があります。 <code>throws</code> キーワードを使用することで、メソッドの呼び出し元がそのメソッドがスローする可能性がある例外に対処できるようになります。 === 例外クラス === Javaの例外には、いくつかの主要なクラスがあります。 以下に、Javaの例外クラスのいくつかを表組みで示します。 {| class="wikitable" |+ 主要な例外クラス !例外クラス !説明 |- |<code>ArithmeticException</code> |数学的な操作中に発生する例外(ゼロ除算など) |- |<code>ArrayIndexOutOfBoundsException</code> |配列への無効なインデックスアクセスが発生した場合の例外 |- |<code>NullPointerException</code> |ヌル参照が使用された場合の例外 |- |<code>IOException</code> |入出力操作中に発生する例外 |- |<code>FileNotFoundException</code> |ファイルが見つからない場合の例外 |- |<code>NumberFormatException</code> |文字列が数値に変換できない場合の例外 |- |<code>IllegalArgumentException</code> |メソッドに渡された引数が無効な場合の例外 |- |<code>RuntimeException</code> |実行時に発生する一般的な例外の基底クラス |} これらはJavaの例外の一部であり、それぞれ特定の状況や条件で発生します。Javaの例外処理では、これらの例外クラスを適切にキャッチして処理することが重要です。また、必要に応じて独自の例外クラスを定義することもできます。 === モダンな例外処理 === Java 7以降で導入された機能と、最新バージョンでの改善点を説明します: ==== try-with-resources ==== リソースの自動クローズを行う構文です: :<syntaxhighlight lang=java copy> public class ModernExceptionHandling { public static void readFile(String path) { // try-with-resources: リソースは自動的にクローズされます try (var reader = new BufferedReader(new FileReader(path))) { String line = reader.readLine(); System.out.println(line); } catch (IOException e) { System.err.println("ファイル読み込みエラー: " + e.getMessage()); } // finally不要: readerは自動的にクローズされます } // 複数のリソースを扱う例 public static void copyFile(String src, String dst) { try (var reader = new BufferedReader(new FileReader(src)); var writer = new BufferedWriter(new FileWriter(dst))) { reader.lines().forEach(line -> { try { writer.write(line); writer.newLine(); } catch (IOException e) { throw new UncheckedIOException(e); } }); } catch (IOException e) { System.err.println("ファイル操作エラー: " + e.getMessage()); } } } </syntaxhighlight> ==== マルチキャッチと型推論 ==== 複数の例外を効率的に処理する方法: :<syntaxhighlight lang=java copy> public class MultiCatchExample { public void processData() { try { // 複数の例外が発生する可能性がある処理 readFromFile(); processNumbers(); } catch (IOException | NumberFormatException e) { // 複数の例外を1つのcatchブロックで処理 logger.error("データ処理エラー", e); } } // Java 17以降の改善された型推論 public void handleException(Exception e) { if (e instanceof IOException || e instanceof SQLException ex) { // exの型が自動的に推論される logError(ex); } } } </syntaxhighlight> ==== 改善されたNullPointerException ==== Java 14以降で導入された詳細なNullPointerExceptionメッセージ: :<syntaxhighlight lang=java copy> public class ImprovedNPE { record Person(String name, Address address) {} record Address(String street) {} public void demonstrateNPE() { Person person = new Person("John", null); // 以下のコードは詳細なエラーメッセージを生成: // "Cannot invoke "ImprovedNPE.Address.street()" because the return value // of "ImprovedNPE.Person.address()" is null" String street = person.address().street(); } } </syntaxhighlight> === カスタム例外の設計 === モダンなJavaでのカスタム例外の実装例: :<syntaxhighlight lang=java copy> public class CustomExceptionExample { // カスタム例外クラス public sealed abstract class BusinessException extends Exception permits ValidationException, NotFoundException { private final String errorCode; protected BusinessException(String message, String errorCode) { super(message); this.errorCode = errorCode; } public String getErrorCode() { return errorCode; } } // 具体的な例外クラス public final class ValidationException extends BusinessException { public ValidationException(String message) { super(message, "VAL_001"); } } public final class NotFoundException extends BusinessException { public NotFoundException(String message) { super(message, "NOT_001"); } } } </syntaxhighlight> {{Nav}} {{DEFAULTSORT:れいかいしより}} [[Category:Java]] abdhv5f86rb4sbfrp91sk8b9vy23lsc Java/null 0 39022 263733 241907 2024-11-18T02:30:49Z Ef3 694 校閲と推敲 263733 wikitext text/x-wiki {{Nav}} == null == プログラミングにおける「null」とは、値が存在しないことを表す特別な値です。nullはプログラムで使用されるさまざまなデータ型(オブジェクト、配列、ポインタなど)の初期値として設定されることがあります。 主な用途としては以下のようなものがあります: # 値の不在を表現する: 変数が値を持たないことを示すために使用されます。例えば、ある関数が特定の条件下で値を返さない場合、通常はnullを返します。 # 初期化: 変数を初期化するために使用されることがあります。特に、オブジェクトや参照型の変数はnullで初期化されることがあります。 # オブジェクトの欠落を示す: オブジェクトが存在しないことを示すために使用されることがあります。例えば、あるオブジェクトのメンバー変数がnullであれば、そのオブジェクトが特定の状態にないことを意味することができます。 nullは便利な概念ですが、誤った使用やnullポインター例外などのランタイムエラーを引き起こす可能性があります。そのため、nullの使用は慎重に行う必要があります。近年のプログラミング言語では、null安全性を向上させるためにオプショナル型やnull許容型などの機能が導入されています。 == Javaにおけるnull == Javaにおける「null」とは、参照型(Reference Type)の変数が参照するオブジェクトが存在しないことを示す特別な値です。Javaのすべてのオブジェクトはヒープ領域に保存され、変数はそのオブジェクトへの参照(アドレス)を保持します。nullは、そのような参照がオブジェクトを指していないことを示します。 以下はnullの主な特徴です: # オブジェクトの不在を示す: 変数がnullを持っている場合、その変数がどのオブジェクトも指していないことを意味します。つまり、その変数には有効な値が含まれていないということです。 # 参照型の初期値: 参照型の変数はデフォルトでnullに初期化されます。つまり、明示的に値を設定しない限り、参照型の変数はnullを持ちます。 #:<syntaxhighlight lang=java copy> String str; // strはnullを持つ </syntaxhighlight> # NullPointerException(NPE): nullへの参照を解決しようとすると、NullPointerExceptionが発生する可能性があります。つまり、nullが予期せずプログラムの実行中に使用されるとエラーが発生します。 Javaでは、nullを適切に扱うことが重要です。nullをチェックし、nullポインターエクセプションを防ぐための適切な手段があります。 例えば、条件付きのnullチェックやOptionalクラスの使用などが挙げられます。以下のように、<code>Optional</code>を使うことで、<code>null</code>を扱う際のリスクを軽減できます: :<syntaxhighlight lang=java copy> Optional<String> optionalStr = Optional.ofNullable(str); optionalStr.ifPresent(s -> System.out.println(s)); // strがnullでない場合のみ処理が実行される </syntaxhighlight> Javaにはnull安全性を向上させるためのさまざまな手段があり、プログラマーはこれらの手段を活用してnull関連の問題を回避できます。 == 最新のnull安全性に関する動向 == 近年、多くのプログラミング言語はnull安全性を向上させるための新しい機能を提供しています。Javaでは、<code>Optional</code> クラスの導入により、nullの問題をより安全に扱えるようになりました。また、C#やKotlinなどの他の言語でも、null安全性を高める機能(例えば、null許容型や非null型の明示的な区別)が導入されています。これにより、開発者はnull関連のエラーを減らすことができ、コードの可読性と信頼性が向上しています。 {{Nav}} {{DEFAULTSORT:NULL}} [[Category:Java]] ig4ihvjjdj0zjn7afchfrpechguk5f2 ガリア戦記 第6巻/注解 0 42852 263723 263635 2024-11-17T12:31:14Z Linguae 449 /* 関連記事 */ 263723 wikitext text/x-wiki <div style="font-family:Arial Black;font-style:normal;font-size:15pt;color:#990033;text-align:center;background-color:#fff0ff;">C &middot; IVLII &middot; CAESARIS &middot; COMMENTARIORVM &middot; BELLI &middot; GALLICI</div> <div style="font-family:Arial Black;font-style:normal;font-size:30pt;color:#990033;text-align:center;background-color:#fff0ff;">LIBER &middot; SEXTVS</div> <span style="font-size:13pt;">『<span style="background-color:#ffc;">[[ガリア戦記 第6巻]]</span>』の単語や構文を詳しく読み解く <span style="background-color:#fc8;font-size:15pt;">'''[[ガリア戦記/注解編|注解編]]'''</span> の目次。</span> {| id="toc" style="border:0px #ddf; align:left;clear:all;" align="center" cellpadding="5" |- ! style="background:#ccf; text-align:center;" colspan="10"| ガリア戦記 第6巻 注解 |- style="background:#f8f8ff; text-align:right; font-size: 0.85em;" |[[/1節|1節]] |[[/2節|2節]] |[[/3節|3節]] |[[/4節|4節]] |[[/5節|5節]] |[[/6節|6節]] |[[/7節|7節]] |[[/8節|8節]] |[[/9節|9節]] |[[/10節|10節]] |- style="background:#f8f8ff; text-align:right; font-size: 0.85em;" |[[/11節|11節]] |[[/12節|12節]] |[[/13節|13節]] |[[/14節|14節]] |[[/15節|15節]] |[[/16節|16節]] |[[/17節|17節]] |[[/18節|18節]] |[[/19節|19節]] |[[/20節|20節]]<!-- |- style="background:#f8f8ff; text-align:right; font-size: 0.85em;" |[[/21節|21節]] |[[/22節|22節]] |[[/23節|23節]] |[[/24節|24節]] |[[/25節|25節]] |[[/26節|26節]] |[[/27節|27節]] |[[/28節|28節]] |[[/29節|29節]] |[[/30節|30節]] |- style="background:#f8f8ff; text-align:right; font-size: 0.85em;" |[[/31節|31節]] |[[/32節|32節]] |[[/33節|33節]] |[[/34節|34節]] |[[/35節|35節]] |[[/36節|36節]] |[[/37節|37節]] |[[/38節|38節]] |[[/39節|39節]] |[[/40節|40節]] |- style="background:#f8f8ff; text-align:right; font-size: 0.85em;" |[[/41節|41節]] |[[/42節|42節]] |[[/43節|43節]] |[[/44節|44節]] |[[/45節|45節]] |[[/46節|46節]] |[[/47節|47節]] |[[/48節|48節]] |[[/49節|49節]] |[[/50節|50節]] |- style="background:#f8f8ff; text-align:right; font-size: 0.85em;" |[[/51節|51節]] |[[/52節|52節]] |[[/53節|53節]] |[[/54節|54節]] |[[/55節|55節]] |[[/56節|56節]] |[[/57節|57節]] |[[/58節|58節]] | colspan="6" | |- style="background:#f8f8ff; text-align:right; font-size: 0.85em;" |[[/1節|1節]] |[[/2節|2節]] |[[/3節|3節]] |[[/4節|4節]] |[[/5節|5節]] |[[/6節|6節]] |[[/7節|7節]] |[[/8節|8節]] |[[/9節|9節]] |[[/0節|0節]] --> |- | style="background:#f5fefe; text-align:left; font-size: 0.8em;" colspan="10"| [[ガリア戦記 第1巻/注解|'''注解'''&nbsp; 第1巻]] | [[ガリア戦記 第2巻/注解|第2巻]] | [[ガリア戦記 第3巻/注解|第3巻]] | [[ガリア戦記 第4巻/注解|第4巻]] | [[ガリア戦記 第5巻/注解|第5巻]] | [[ガリア戦記 第6巻/注解|第6巻]] <!--| [[ガリア戦記 第7巻/注解|第7巻]] | [[ガリア戦記 第8巻/注解|第8巻]]--> |} <br style="clear:both;" /> __notoc__ == 各節注解 == [[画像:Gaule_-53.png|thumb|right|150px|ガリア戦記 第6巻の情勢図(BC53年)。<br>黄色の領域がローマ領。桃色が同盟部族領。]] ===ガッリア北部の平定=== *<span style="background-color:#fff;">[[/1節]] {{進捗|25%|2024-09-23}}</span> (129語) *<span style="background-color:#fff;">[[/2節]] {{進捗|25%|2024-09-29}}</span> (89語)   短い節 *<span style="background-color:#fff;">[[/3節]] {{進捗|25%|2024-10-06}}</span> (112語) *<span style="background-color:#fff;">[[/4節]] {{進捗|25%|2024-10-13}}</span> (86語)   短い節 *<span style="background-color:#fff;">[[/5節]] {{進捗|25%|2024-10-14}}</span> (150語) *<span style="background-color:#fff;">[[/6節]] {{進捗|25%|2024-10-20}}</span> (69語)   短い節 *<span style="background-color:#fff;">[[/7節]] {{進捗|25%|2024-10-30}}</span> (196語) *<span style="background-color:#fff;">[[/8節]] {{進捗|25%|2024-11-10}}</span> (210語) *<span style="background-color:#fff;">[[/9節]] {{進捗|25%|2024-11-13}}</span> (141語) ===第二次ゲルマーニア遠征=== *<span style="background-color:#fff;">[[/10節]] {{進捗|25%|2024-11-16}}</span> (143語) *<span style="background-color:#fff;">[[/11節]] {{進捗|00%|2024-11-14}}</span>  == 関連項目 == *<span style="background-color:#ffd;">[[ガリア戦記]]</span><!--【2006年4月23日起稿】--> **<span style="background-color:#ffd;">[[ガリア戦記/注解編]]</span><!--(2020-03-27)--> ***<span style="background-color:#ffd;">[[ガリア戦記/注解編/写本と校訂版]] {{進捗|00%|2020-04-17}}</span><!--(2020-04-17)--> **<span style="background-color:#ffd;">[[ガリア戦記/用例集]]          {{進捗|00%|2020-03-29}}</span><!--(2020-03-29)--> **[[ガリア戦記/内容目次]]:巻・章・節の内容を記した目次 {{進捗|75%|2011-04-02}} **[[ガリア戦記/参照画像一覧]]:本文で参照した画像一覧  {{進捗|75%|2011-04-16}} *<span style="background-color:#ffd;font-size:15px;">[[古典ラテン語]]                   {{進捗|00%|2018-04-18}} </span> <br><div style="font-size:20pt;"> Ā Ē Ī Ō Ū ā ē ī ō ū &nbsp; Ă Ĕ Ĭ Ŏ Ŭ ă ĕ ĭ ŏ ŭ </div> <div style="font-size:13pt;"> <math>\overline{\mbox{VIIII}} </math> </div><!-- [[w:Help:数式の表示]] --> <span style="font-family:Times New Roman;font-size:15pt;background-color:#fff;"></span> <span style="font-family:Times New Roman;font-size:15pt;"></span> <span style="font-family:Times New Roman;"></span> <!-- *<span style="font-family:Times New Roman;font-style:normal;font-size:15pt;">† : </span>校訂者が、テクストが壊れていると判断した部分をこの記号で囲んでいる。 --> <!-- <ruby><rb>●漢字●</rb><rp>(</rp><rt>●ルビ●</rt><rp>)</rp></ruby> --> <!-- *<span style="background-color:#ffd;">[[/注解/1節]] {{進捗|00%|2024-11-16}}</span> --> <!-- <span style="color:#009900;"></span> <small></small> **:<span style="color:#009900;">(訳注: **:<span style="color:#009900;font-family:Times New Roman;">(訳注: --> <!--❶--><!--❷--><!--❸--><!--❹--><!--❺--><!--❻--><!--❼--><!--❽--><!--❾--><!----><!----><!----><!----><!----> == 関連記事 == {{Wikisource|la:Commentarii de bello Gallico/Liber VI|ガリア戦記 第6巻(ラテン語)}} *ウィキソース **<span style="font-family:Times New Roman;">[[s:la:Commentarii de bello Gallico/Liber VI]] (第6巻 ラテン語)</span> **<span style="font-family:Times New Roman;">[[s:en:Commentaries on the Gallic War/Book 6]] (第6巻 英訳)</span> **<span style="font-family:Times New Roman;">[[s:fr:La Guerre des Gaules/Livre VI]] (第6巻 仏訳)</span> ---- {{Commons|Category:Battles of Caesar's Gallic Wars|Battles of Caesar's Gallic Warsのカテゴリ}} *<span style="font-family:Times New Roman;font-size:13pt;">[[wikt:fr:Catégorie:Mots en latin issus d’un mot en gaulois]]</span> ---- ;地名 *[[wikt:en:Gallia#Latin|Gallia]] **Gallia [[wikt:en:cisalpinus#Latin|cisalpīna]] **Gallia [[wikt:en:transalpinus#Latin|trānsalpīna]] **Gallia [[wikt:en:comatus#Latin|comāta]] ;部族 *[[wikt:en:Cherusci#Latin|Chēruscī]] *[[wikt:en:Germani#Latin|Germānī]] *[[wikt:en:Menapii#Latin|Menapiī]] *[[wikt:en:Suebi#Latin|Suēbī]] *[[wikt:en:Treveri#Latin|Trēverī]] *[[wikt:en:Ubii#Latin|Ubiī]] ;第6巻の登場人物 *[[wikt:en:Caesar#Latin|Caesar]] :  *[[wikt:en:Ambiorix#Latin|Ambiorīx]] : *[[wikt:en:Commius|Commius]] **[[w:コンミウス]] **[[w:la:Commius]] **[[w:en:Commius]] **[[w:fr:Commios]] *[[wikt:en:Cicero#Latin|Cicerō]] **[[w:クィントゥス・トゥッリウス・キケロ|クイーントゥス・トゥッリウス・キケロー]] **[[w:la:Quintus Tullius Cicero]] **[[w:en:Quintus Tullius Cicero]] **[[w:fr:Quintus Tullius Cicero]] *[[wikt:en:Crassus#Latin|Crassus]] *[[wikt:en:Labienus#Latin|Labiēnus]] **[[w:ティトゥス・ラビエヌス|ティトゥス・ラビエーヌス]] <!-- *? **Crassus ***[[w:プブリウス・リキニウス・クラッスス]] ***[[w:la:Publius Licinius Crassus]] ***[[w:en:Publius Licinius Crassus (son of triumvir)]] ***[[w:fr:Publius Crassus]] **Labienus (副官) ***[[w:la:Titus Labienus]] ***[[w:en:Titus Labienus]] ***[[w:fr:Titus Labienus]] **Brutus ***[[w:デキムス・ユニウス・ブルトゥス・アルビヌス]] ***[[w:la:Decimus Iunius Brutus Albinus]] ***[[w:en:Decimus Junius Brutus Albinus]] ***[[w:fr:Decimus Junius Brutus Albinus]] --> <br> ===第6巻の関連記事=== <!--【第6巻の関連記事】--> {{Commons|Category:Roman Britain|Roman Britainのカテゴリ}} <div style="font-family:Times New Roman;font-size:13pt;"> <!-- *[[c:Category:Armorica]] **[[c:Category:Maps of the Antiquity of Bretagne]] --> <hr> *[[c:Category:Ancient Roman ships]] <br> </span> <span style="font-family:Times New Roman;font-size:13pt;"></span> == 外部リンク == *[[ガリア戦記/注解編#外部リンク]] を参照。 *[[ガリア戦記/注解編/写本と校訂版#オンライン注釈書等]] 等を参照。 ===オンライン注釈書=== <div style="background-color:#eeeeee;"> ====Caesar's Gallic war : notes by F. W. Kelsey (1897)==== :C. Iuli Caesaris De bello gallico libri VII : ::Caesar's Gallic war : with an introduction, notes, and vocabulary ::: by [[w:en:Francis Kelsey|Francis Willey Kelsey (1858-1927)]], Fifteenth Edition (1897) :::: (HathiTrust Digital Library [[w:ハーティトラスト|ハーティトラスト・デジタルライブラリ]]で電子化) :: [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=19 Contents] (#19) ;:─TEXT─ :: '''Book 6''' : [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=219 Commentarius Sextus] &nbsp; (#219) ;:─NOTES─ :: '''Book 6''' # [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=441 I.] (#441), [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=442 II.-III.] (#442), [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=443 IV.-VII.] (#443), [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=444 VIII.-IX.] (#444), # [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=445 X.-XI.] (#445), [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=446 XII.-XIII.] (#446), [https://babel.hathitrust.org/cgi/pt?id=hvd.hn1tp9&seq=447 XIV.-XV.] (#447), </div> ====English translation by W. A. McDevitte & W. S. Bohn (1869)==== # [http://www.forumromanum.org/literature/caesar/gallic.html (www.forumromanum.org)] # (www.perseus.tufts.edu) ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.1 C. Julius Caesar, Gallic War, Book 6, chapter 1] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.2 C. Julius Caesar, Gallic War, Book 6, chapter 2] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.3 C. Julius Caesar, Gallic War, Book 6, chapter 3] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.4 C. Julius Caesar, Gallic War, Book 6, chapter 4] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.5 C. Julius Caesar, Gallic War, Book 6, chapter 5] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.6 C. Julius Caesar, Gallic War, Book 6, chapter 6] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.7 C. Julius Caesar, Gallic War, Book 6, chapter 7] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.8 C. Julius Caesar, Gallic War, Book 6, chapter 8] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.9 C. Julius Caesar, Gallic War, Book 6, chapter 9] ## [https://www.perseus.tufts.edu/hopper/text?doc=Caes.+Gal.+6.10 C. Julius Caesar, Gallic War, Book 6, chapter 10] <!-- ====Eastman, Frederick Carlos., D'Ooge, Benjamin L. 1860-1940.(1917)==== <span style="font-family:Times New Roman;font-style:normal;font-size:13pt;"> *[https://catalog.hathitrust.org/Record/001058370 Catalog Record: Caesar in Gaul and selections from the third... | HathiTrust Digital Library] (catalog.hathitrust.org) :[https://babel.hathitrust.org/cgi/pt?id=hvd.hn5cnb&view=1up&seq=7&skin=2021 #7 - Caesar in Gaul and selections from the third book of the Civil ... - Full View | HathiTrust Digital Library] (babel.hathitrust.org) :BOOK IV. [https://babel.hathitrust.org/cgi/pt?id=hvd.hn5cnb&view=1up&seq=393&skin=2021 #393 ] :IV.34,-38. [https://babel.hathitrust.org/cgi/pt?id=hvd.hn5cnb&view=1up&seq=403&skin=2021 #403 ] </span> --> ====Harkness, Albert (1889)==== <span style="font-family:Times New Roman;font-style:normal;"><span style="font-size:15pt;">Caesar's Commentaries on the Gallic War,  </span><span style="font-size:13pt;">with notes, dictionary, and a map of Gaul.</span><br>  <span style="font-size:15pt;">   edited by <u>[[w:en:Albert Harkness|Albert Harkness (1822-1907)]]</u> <ref>[http://onlinebooks.library.upenn.edu/webbin/book/lookupname?key=Harkness%2C%20Albert%2C%201822%2D1907 Harkness, Albert, 1822-1907 | The Online Books Page]</ref>, New York, [[w:en:D. Appleton & Company|D. Appleton and Company]], 1889 (Rivised Edition)</span></span> ::Caesar's commentaries on the Gallic war; with notes, dictionary, ... (Full View | HathiTrust Digital Library) ;  BOOK SIXTH :VI. 1.  [https://babel.hathitrust.org/cgi/pt?id=hvd.hn3hve&view=1up&seq=365 #365] ====Incerti auctoris(編者不詳)==== ; [https://books.google.co.jp/books?id=uLA8AAAAIAAJ&lpg=PA98&dq=Caesar+to+Cicero.+Be+of+good+courage.+Expect+aid&pg=PP1&redir_esc=y#v=onepage&q&f=false Caesar Gallic War V with vocabulary](第5巻)-Google ブックス(プレビュー) ;[https://www.latein.me/ Latein-Wörterbuch - Latein.me] # [https://www.latein.me/text/3/Caesar/37/De+Bello+Gallico+%28V%29/p/0 De Bello Gallico (V) - Caesar - Latein.me] <span style="font-family:Times New Roman;font-style:normal;font-size:13pt;"></span> ;nodictionaries.com <!-- :[https://nodictionaries.com/caesar/de-bello-gallico-1/1 '''Caesar De Bello Gallico 1''' 1 in Latin, with adjustable running vocabulary] :[https://nodictionaries.com/caesar/de-bello-gallico-2/1 '''Caesar De Bello Gallico 2''' 1 in Latin, with adjustable running vocabulary] :[https://nodictionaries.com/caesar/de-bello-gallico-3/1 '''Caesar De Bello Gallico 3''' 1 in Latin, with adjustable running vocabulary] :[https://nodictionaries.com/caesar/de-bello-gallico-4/1 '''Caesar De Bello Gallico 4''' 1 in Latin, with adjustable running vocabulary] --> :[https://nodictionaries.com/caesar/de-bello-gallico-5/1 Caesar De Bello Gallico 5 1 in Latin, with adjustable running vocabulary] ==脚注== <references /> [[Category:ガリア戦記 第6巻|*#]] o8ji3zj3np4lmdbhm3p3dko74uxncui 高等学校日本史探究/古代国家の形成Ⅰ 0 43191 263725 263700 2024-11-17T12:53:32Z Kwawe 68789 /* 推古朝の外交と内政 */ 表現を少し修正しました。 263725 wikitext text/x-wiki [[小学校・中学校・高等学校の学習]]>[[高等学校の学習]]>[[高等学校地理歴史]]>[[高等学校日本史探究]]>古代国家の形成Ⅰ ==6世紀の朝鮮半島と倭== 5世紀の朝鮮半島は、'''高句麗'''と'''百済'''の間で戦争になりました。475年、高句麗が漢城(百済の首都)を攻めました。その結果、百済の国王は降伏して、高句麗の兵士に殺されました。降伏後の百済は首都を熊津から扶余に引っ越し、'''加耶'''地域まで影響力を広げました。日本のヤマト政権も伽耶地域に関心がありました。加耶諸国と仲良くしたいので、兵士を朝鮮半島に送りました。しかし、伽耶諸国は「自分達の力だけで国を動かしていきたい」と考えるようになりました。512年、加耶地域の西側が百済の支配下に入るようになりました。6世紀を迎えると、'''新羅'''もかなり力をつけ始めます。新羅は百済と争いながら、伽耶諸国を新羅の領土に入れました。その結果、ヤマト政権は朝鮮半島の影響力を失いました。 継体天皇が亡くなると、ヤマト政権も'''大伴金村'''派(安閑天皇と宣化天皇)と'''蘇我稲目'''派('''欽明天皇''')に分かれました(二朝併立)。539年、大伴金村と蘇我稲目が仲直りします。仲直りすると、欽明天皇が国をまとめます。なお、大伴金村は'''物部尾輿'''から朝鮮半島政策でかなり怒られ、540年に政権を退くようになりました。 538年、仏教が朝鮮半島から日本に初めて伝わると、2つの意見に分かれました。蘇我稲目は「仏教を取り入れたい。」と考えました。一方、物部尾輿と中臣鎌子は「仏教を取り入れず、今までの神様を大切にしたい。」と考えました。こうして、蘇我稲目(蘇我氏)と物部尾輿(物部氏)・中臣鎌子(中臣氏)は争うようになります。この争いは子供にも引き継がれます。結局、<span style="color:#f29100">'''蘇我馬子'''</span>が仏教を取り入れるために王族や諸豪族を集めて、物部氏の代表(<span style="color:#f29100">'''物部守屋'''</span>)を587年に倒しました([[w:丁未の乱|丁未の乱]]<ref>この名称の記述は日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。なお、考古学者は、奈良県明日香村の石舞台古墳を上円下方墳と考えられています。かなり大きな横穴式石室が石舞台古墳にそのまま残っています。石舞台古墳は蘇我馬子のお墓(桃原墓)と考えられています。また、石舞台古墳近くの島庄遺跡は蘇我馬子の屋敷跡だと考えられています。 当時、国の施設('''屯倉''')・特別な人('''名代・子代''')を全国各地に置きました。また、有力豪族の代表(大夫)同士で話し合いをする仕組みも作りました。さらに、専門職('''品部''')も作られました。このように、国の仕組みが整うと、倭国も大きく変わりました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''蘇我氏はどうして大きくなりましたか?''' |- | style="padding:5px" |蘇我氏はかつて大和国の高市郡曽我地方に住んでいました。やがて、葛城家(大和南西部の一族)から離れるために、大和国の高市郡飛鳥地方に移ります(蘇我氏の独立)。蘇我稲目は大臣になり、かなり重要な政策を進めました。5世紀を迎えると、蘇我氏は当時の天皇家と結婚します。こうして蘇我氏は大きな力を持つようになり、日本各地に広がりました。また、蘇我稲目はお金や大切な物を斎蔵・内蔵・大蔵へ移して、渡来人の東漢氏に斎蔵・内蔵・大蔵の管理を任せました。さらに、蘇我稲目は自分の娘2人(堅塩媛と小姉君)を欽明天皇の妻にしました。その結果、蘇我氏は用明天皇・崇峻天皇・推古天皇と家族のような繋がりを持つようになり、ますます大きな力を持つようになりました。次の蘇我馬子は大臣になり、大夫と協力しながら政治のお仕事をしました。これに対して、崇峻天皇は蘇我馬子を恐れていました。592年、蘇我馬子は崇峻天皇を殺しました。 |} ==推古朝の外交と内政== 当時、政治の中心地は飛鳥にありました(<span style="color:#f29100">'''飛鳥時代'''</span>)。額田部皇女(豊御食炊屋姫)が蘇我馬子と豪族からの推薦で初めて女性天皇に選ばれました(<span style="color:#f29100">'''推古天皇'''</span>)。なお、額田部皇女(豊御食炊屋姫)は欽明天皇(父親)と蘇我堅塩媛(母親)の娘です。奈良県橿原市の植山古墳は東側と西側に横穴式石室を設けています。そのうち、西側の石室が推古天皇の墓だと考えられています。593年、<span style="color:#f29100">'''厩戸王'''</span>(<span style="color:#f29100">'''聖徳太子'''</span>:推古天皇の甥)が政治に携わるようになりました。そこから推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。それ以降、倭国は東アジアの国際関係を深めるようになりました。なお、日本書紀の「摂政」は平安時代の「摂政」と異なり、「誰かの代わりに政治をする。」という意味で使われます。 北朝の<span style="color:#f29100">'''隋'''</span>は勢力を伸ばし、南陳を589年に手に入れました。その結果、久しぶりに国がまとまりました。隋は法律を作り、朝鮮半島と倭国を攻めました。598年から高句麗に4回も軍隊を送りました。これに対して、高句麗・新羅・百済・倭国は国をまとめなければならないと思うようになりました。 5世紀頃、中国に使者を送らなくなると、倭国と中国の関係が途切れました。やがて、倭国は中国中心の考え方から抜け出して、新羅と新しい関係を作ろうとしました。倭国は新羅に3回(600年・602年・623年)も軍隊を送りました。特に、600年は新羅遠征軍と遣隋使の両方を送りました。 隋書東夷伝倭国条は第1回<span style="color:#f29100">'''遣隋使'''</span>について記されています。第1回遣隋使を隋へ送ると、隋の文帝から日本の政治と生活の仕方について厳しい意見がありました。それまで、倭国は朝鮮半島の国家と仲良くなるために、力の強さだけを見せればいいと考えていました。しかし、この厳しい意見から他の国と事前に話し合いをするようになりました。しかし、第1回遣隋使は日本の歴史書『日本書紀』に全く書かれていません。 倭国は隋と関わるうちに『政治の仕組みがまだまだ整っていないかも…』と気づきました。そこで、隋と仲良く付き合うために、厩戸王と蘇我馬子が中心になって冠位十二階と憲法十七条を作りました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''冠位十二階''' |- | style="padding:5px" |中国や朝鮮のやり方をお手本にして、冠位十二階を作りました。冠位十二階を説明すると、その人の良心(徳・仁・礼・信義・智)を評価します。そして、この評価を十二段階に分けて、その段階に合わせて六色の冠(紫・青・赤・黄・白・黒)を被るようになります。冠位十二階は生まれた時からではなく、個人の才能と個人の頑張り具合で評価されるようになっています。しかも一代限りなので、頑張れば冠位も上がりました。鞍作鳥・秦河勝・小野妹子は出身とか関係なく、自分の才能と自分の頑張りで冠位を貰えました。しかし、蘇我氏・王族・地方の豪族は冠位十二階の対象に含まれていません。 |- ! style="background: #F4ADA3" |'''憲法十七条''' |- | style="padding:5px" |憲法十七条は朝廷の仕事をするようになったら、どのような心構えで働けばいいのかについて記されています。憲法十七条は中国の影響を大きく受けており、儒教・仏教の考え方を上手く取り入れて定められました。また、隋に対して倭国の立場や意見をはっきり主張するために、憲法十七条を定めていました。この後、日本の政治の仕組みも少しずつ整いました。しかし、どこまで憲法十七条を守っていたのかまでは分かりません。憲法十七条の内容は次の通りです。 # みんな仲良く暮らしなさい。 # お坊さんを大切にしなさい。 # 天皇の言葉をしっかり聞きなさい。 # 礼儀作法を守りなさい。 # 裁判は公平に裁きなさい。 # いい人は褒めて、悪い人はしっかり注意しなさい。 # 自分の役割をきちんと果たしなさい。 # 早めに行って遅くまでしっかり働きなさい。 # 信頼関係を持ちなさい。 # 腹を立ててはいけません。 # 出来る役人は褒め、出来ない役人は注意しなさい。 # 国司・国造は、庶民から余計な税金を取ってはいけません。 # 役人は自分の仕事をしっかり理解しなさい。 # 他の人と比べてはいけません。 # 自分勝手にしないで、思いやりの心を持ちなさい。 # 庶民を引っ張っていく時は、周りの状況もしっかり見ながら進めなさい。 # 自分だけで決めないで、みんなで様々な意見を聞いてから決めなさい。 |}  国家組織を再編成した推古朝は、607年にも'''小野妹子'''を遣隋使として、派遣しました。この時妹子は、国書を隋の皇帝であった煬帝に差し出しましたが、無礼だとされました。なぜならその国書は、倭が隋に従属しないという態度を示していたためです。倭の五王までは、中国の王朝に冊封をもとめていたので大きな変化でした。結局、煬帝は、高句麗に侵攻している情勢もあって、裴世清を倭に送りました。  国家体制が充実してきた推古朝は、歴史書編纂にも取り組みました。厩戸王と蘇我馬子が中心となり、620年に『天皇記』や『国記』などを編纂しました。これらは、6世紀に成立した「帝紀」や「旧辞」を基に、天皇と諸氏の関係性を示し、天皇の支配が正当であることを示そうとしていたと考えられます。3度目の遣隋使では、留学生や留学僧を同行させました。中国の制度や思想、文化などを取り込もうとしたのです。このとき、留学生の'''高向玄理'''や留学僧の'''旻'''・'''南淵請安'''が重要です。その後、4度目の遣隋使として犬上御田鍬を送りましたが、これが最後の遣隋使となります。 ==7世紀の東アジアと倭国== 最初に、中国の歴史を説明します。618年、隋王朝が終わり、<span style="color:#f29100">'''唐王朝'''</span>に変わりました。唐王朝は、土地を公平に分けたり、税金の仕組みを整えたりして国をまとめました。太宗皇帝の頃、唐王朝が最も栄えました('''貞観の治''')。次に、朝鮮半島の歴史を説明します。641年、百済の義慈王は権力を奪いました。やがて、百済の義慈王は新羅へ翌年から攻めました。642年、高句麗宰相の泉蓋蘇文が権力を奪うために、国王・貴族を倒します。その後、百済と手を組んで、新羅の領土を狙うようになりました。こうして、新羅は四面楚歌の状態になったので、唐に助けを求めました。しかし、唐側は「助けてほしいなら、女王を変えてください。」と条件を出します。647年、新羅の中でも女王を交代するのか交代しないのかを巡って争いが始まりました。太宗皇帝は、644年から朝鮮半島の高句麗へ攻めました(駐蹕山の戦い<ref>この名称の記述も日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。この戦いから、東アジア全体が大きく変わります。倭国でも、「大きな戦いが朝鮮半島で起きているから、このままだと悪い方向に向かうようになるかもしれない。」と考えるようになりました。そこで、これまでの政治が大きく変わるようになりました。 父親の<span style="color:#f29100">'''蘇我蝦夷'''</span>は祖父の蘇我馬子から大臣の役目を引き継いで、少しずつ大きな力を持つようになります。舒明天皇~<span style="color:#f29100">'''皇極天皇'''</span>の時代を迎えると、息子の<span style="color:#f29100">'''蘇我入鹿'''</span>は父親の蘇我蝦夷よりもさらに大きな力を持つようになりました。643年、蘇我入鹿は'''山背大兄王'''(厩戸王の息子)とその家族を殺しました。蘇我氏は高句麗のやり方と同じように蘇我氏寄りの天皇を選んで、政治の実権を握ろうとしました。これに対して、<span style="color:#f29100">'''中大兄皇子・中臣鎌足'''</span>・蘇我倉山田石川麻呂は「このまま、蘇我氏が政治の実権を握ると問題になるかもしれない。」と考えるようになります。645年7月10日、飛鳥板蓋宮で蘇我入鹿を殺しました。翌日、父親の蘇我蝦夷も追い詰められて自殺しました(<span style="color:#f29100">'''[[w:乙巳の変|乙巳の変]]'''</span>)。この後、朝廷が国をまとめていくようになります。 == 資料出所 == * 平雅行、横田冬彦ほか編著『[https://www.jikkyo.co.jp/material/dbook/R5_chireki_20220510/?pNo=6 日本史探究]』実教出版株式会社 2023年 * 佐藤信、五味文彦ほか編著『[https://new-textbook.yamakawa.co.jp/j-history/ 詳説日本史探究]』株式会社山川出版社 2023年 * 渡邊晃宏ほか編著『[https://ten.tokyo-shoseki.co.jp/text/hs/shakai/16596/ 日本史探究]』東京書籍株式会社 2023年 * 山中裕典著'''『'''[https://www.amazon.co.jp/改訂版-大学入学共通テスト-歴史総合、日本史探究の点数が面白いほどとれる本-0からはじめて100までねらえる-山中/dp/4046062371 改訂版 大学入学共通テスト 歴史総合、日本史探究の点数が面白いほどとれる本]'''』'''株式会社KADOKAWA 2024年 * 佐藤信、五味文彦ほか編著『[https://www.amazon.co.jp/%E8%A9%B3%E8%AA%AC%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6-%E4%BD%90%E8%97%A4-%E4%BF%A1/dp/4634010739/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2JVCFQ6ZSAM4W&keywords=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6&qid=1673018227&sprefix=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6%2Caps%2C229&sr=8-1 詳説日本史研究]』株式会社山川出版社 2017年 * 河合敦著『[https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%84-%E6%B2%B3%E5%90%88%E6%95%A6%E3%81%AE-%E6%97%A5%E6%9C%AC%E5%8F%B2B-%E3%80%8C%E5%8E%9F%E5%A7%8B-%E9%8E%8C%E5%80%89%E3%80%8D%E3%81%AE%E7%89%B9%E5%88%A5%E8%AC%9B%E5%BA%A7-%E6%B2%B3%E5%90%88/dp/404600794X/ref=d_pd_sbs_sccl_2_1/355-7112149-5713814?pd_rd_w=H8Pxa&content-id=amzn1.sym.820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_p=820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_r=ZWG9FNM6AD22NFF5WK2G&pd_rd_wg=scszo&pd_rd_r=8c1e9eda-f944-4c80-9e4e-7e35244ab2a6&pd_rd_i=404600794X&psc=1 世界一わかりやすい河合敦の日本史B[原始~鎌倉]の特別講座]』株式会社KADOKAWA 2014年(絶版本) == ここに注意!! == [[カテゴリ:高等学校日本史探究]] r0kkjssfe3izhtqjzpg70qcvva4myzl 263778 263725 2024-11-18T10:33:06Z Kwawe 68789 /* 推古朝の外交と内政 */ 聖徳太子の記述を追加しました。 263778 wikitext text/x-wiki [[小学校・中学校・高等学校の学習]]>[[高等学校の学習]]>[[高等学校地理歴史]]>[[高等学校日本史探究]]>古代国家の形成Ⅰ ==6世紀の朝鮮半島と倭== 5世紀の朝鮮半島は、'''高句麗'''と'''百済'''の間で戦争になりました。475年、高句麗が漢城(百済の首都)を攻めました。その結果、百済の国王は降伏して、高句麗の兵士に殺されました。降伏後の百済は首都を熊津から扶余に引っ越し、'''加耶'''地域まで影響力を広げました。日本のヤマト政権も伽耶地域に関心がありました。加耶諸国と仲良くしたいので、兵士を朝鮮半島に送りました。しかし、伽耶諸国は「自分達の力だけで国を動かしていきたい」と考えるようになりました。512年、加耶地域の西側が百済の支配下に入るようになりました。6世紀を迎えると、'''新羅'''もかなり力をつけ始めます。新羅は百済と争いながら、伽耶諸国を新羅の領土に入れました。その結果、ヤマト政権は朝鮮半島の影響力を失いました。 継体天皇が亡くなると、ヤマト政権も'''大伴金村'''派(安閑天皇と宣化天皇)と'''蘇我稲目'''派('''欽明天皇''')に分かれました(二朝併立)。539年、大伴金村と蘇我稲目が仲直りします。仲直りすると、欽明天皇が国をまとめます。なお、大伴金村は'''物部尾輿'''から朝鮮半島政策でかなり怒られ、540年に政権を退くようになりました。 538年、仏教が朝鮮半島から日本に初めて伝わると、2つの意見に分かれました。蘇我稲目は「仏教を取り入れたい。」と考えました。一方、物部尾輿と中臣鎌子は「仏教を取り入れず、今までの神様を大切にしたい。」と考えました。こうして、蘇我稲目(蘇我氏)と物部尾輿(物部氏)・中臣鎌子(中臣氏)は争うようになります。この争いは子供にも引き継がれます。結局、<span style="color:#f29100">'''蘇我馬子'''</span>が仏教を取り入れるために王族や諸豪族を集めて、物部氏の代表(<span style="color:#f29100">'''物部守屋'''</span>)を587年に倒しました([[w:丁未の乱|丁未の乱]]<ref>この名称の記述は日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。なお、考古学者は、奈良県明日香村の石舞台古墳を上円下方墳と考えられています。かなり大きな横穴式石室が石舞台古墳にそのまま残っています。石舞台古墳は蘇我馬子のお墓(桃原墓)と考えられています。また、石舞台古墳近くの島庄遺跡は蘇我馬子の屋敷跡だと考えられています。 当時、国の施設('''屯倉''')・特別な人('''名代・子代''')を全国各地に置きました。また、有力豪族の代表(大夫)同士で話し合いをする仕組みも作りました。さらに、専門職('''品部''')も作られました。このように、国の仕組みが整うと、倭国も大きく変わりました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''蘇我氏はどうして大きくなりましたか?''' |- | style="padding:5px" |蘇我氏はかつて大和国の高市郡曽我地方に住んでいました。やがて、葛城家(大和南西部の一族)から離れるために、大和国の高市郡飛鳥地方に移ります(蘇我氏の独立)。蘇我稲目は大臣になり、かなり重要な政策を進めました。5世紀を迎えると、蘇我氏は当時の天皇家と結婚します。こうして蘇我氏は大きな力を持つようになり、日本各地に広がりました。また、蘇我稲目はお金や大切な物を斎蔵・内蔵・大蔵へ移して、渡来人の東漢氏に斎蔵・内蔵・大蔵の管理を任せました。さらに、蘇我稲目は自分の娘2人(堅塩媛と小姉君)を欽明天皇の妻にしました。その結果、蘇我氏は用明天皇・崇峻天皇・推古天皇と家族のような繋がりを持つようになり、ますます大きな力を持つようになりました。次の蘇我馬子は大臣になり、大夫と協力しながら政治のお仕事をしました。これに対して、崇峻天皇は蘇我馬子を恐れていました。592年、蘇我馬子は崇峻天皇を殺しました。 |} ==推古朝の外交と内政== 当時、政治の中心地は飛鳥にありました(<span style="color:#f29100">'''飛鳥時代'''</span>)。額田部皇女(豊御食炊屋姫)が蘇我馬子と豪族からの推薦で初めて女性天皇に選ばれました(<span style="color:#f29100">'''推古天皇'''</span>)。なお、額田部皇女(豊御食炊屋姫)は欽明天皇(父親)と蘇我堅塩媛(母親)の娘です。奈良県橿原市の植山古墳は東側と西側に横穴式石室を設けています。そのうち、西側の石室が推古天皇の墓だと考えられています。593年、<span style="color:#f29100">'''厩戸王'''</span>(<span style="color:#f29100">'''聖徳太子'''</span>:推古天皇の甥)が政治に携わるようになりました。そこから推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。それ以降、倭国は東アジアの国際関係を深めるようになりました。なお、日本書紀の「摂政」は平安時代の「摂政」と異なり、「誰かの代わりに政治をする。」という意味で使われます。 {| style="border:2px solid #9E7360;width:100%" cellspacing="0" ! style="background: #9E7360" |'''聖徳太子''' |- | style="padding:5px" |厩戸王(聖徳太子)は用明天皇(父親)と穴穂部皇女(母親)の息子です。実は、厩戸王(聖徳太子)の父親と母親はどちらも蘇我家でした。そして、推古天皇・蘇我馬子も蘇我氏の親戚関係なので、推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。なお、皇太子制度と摂政制度は飛鳥時代にありません。そのため、厩戸王は天皇の後継者として政治に関わるようになりました。しかし、どこまで推古天皇のお仕事を手伝っていたのかまでははっきりしません。厩戸王は残念ながら推古天皇より先に亡くなり、天皇になれませんでした。厩戸王はかなり早い時期から聖徳太子とも呼ばれ、様々な伝説も生まれました。厩戸王が亡くなってからも、一般民衆の間でますます尊敬されるようになりました。 |} 北朝の<span style="color:#f29100">'''隋'''</span>は勢力を伸ばし、南陳を589年に手に入れました。その結果、久しぶりに国がまとまりました。隋は法律を作り、朝鮮半島と倭国を攻めました。598年から高句麗に4回も軍隊を送りました。これに対して、高句麗・新羅・百済・倭国は国をまとめなければならないと思うようになりました。 5世紀頃、中国に使者を送らなくなると、倭国と中国の関係が途切れました。やがて、倭国は中国中心の考え方から抜け出して、新羅と新しい関係を作ろうとしました。倭国は新羅に3回(600年・602年・623年)も軍隊を送りました。特に、600年は新羅遠征軍と遣隋使の両方を送りました。 隋書東夷伝倭国条は第1回<span style="color:#f29100">'''遣隋使'''</span>について記されています。第1回遣隋使を隋へ送ると、隋の文帝から日本の政治と生活の仕方について厳しい意見がありました。それまで、倭国は朝鮮半島の国家と仲良くなるために、力の強さだけを見せればいいと考えていました。しかし、この厳しい意見から他の国と事前に話し合いをするようになりました。しかし、第1回遣隋使は日本の歴史書『日本書紀』に全く書かれていません。 倭国は隋と関わるうちに『政治の仕組みがまだまだ整っていないかも…』と気づきました。そこで、隋と仲良く付き合うために、厩戸王と蘇我馬子が中心になって冠位十二階と憲法十七条を作りました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''冠位十二階''' |- | style="padding:5px" |中国や朝鮮のやり方をお手本にして、冠位十二階を作りました。冠位十二階を説明すると、その人の良心(徳・仁・礼・信義・智)を評価します。そして、この評価を十二段階に分けて、その段階に合わせて六色の冠(紫・青・赤・黄・白・黒)を被るようになります。冠位十二階は生まれた時からではなく、個人の才能と個人の頑張り具合で評価されるようになっています。しかも一代限りなので、頑張れば冠位も上がりました。鞍作鳥・秦河勝・小野妹子は出身とか関係なく、自分の才能と自分の頑張りで冠位を貰えました。しかし、蘇我氏・王族・地方の豪族は冠位十二階の対象に含まれていません。 |- ! style="background: #F4ADA3" |'''憲法十七条''' |- | style="padding:5px" |憲法十七条は朝廷の仕事をするようになったら、どのような心構えで働けばいいのかについて記されています。憲法十七条は中国の影響を大きく受けており、儒教・仏教の考え方を上手く取り入れて定められました。また、隋に対して倭国の立場や意見をはっきり主張するために、憲法十七条を定めていました。この後、日本の政治の仕組みも少しずつ整いました。しかし、どこまで憲法十七条を守っていたのかまでは分かりません。憲法十七条の内容は次の通りです。 # みんな仲良く暮らしなさい。 # お坊さんを大切にしなさい。 # 天皇の言葉をしっかり聞きなさい。 # 礼儀作法を守りなさい。 # 裁判は公平に裁きなさい。 # いい人は褒めて、悪い人はしっかり注意しなさい。 # 自分の役割をきちんと果たしなさい。 # 早めに行って遅くまでしっかり働きなさい。 # 信頼関係を持ちなさい。 # 腹を立ててはいけません。 # 出来る役人は褒め、出来ない役人は注意しなさい。 # 国司・国造は、庶民から余計な税金を取ってはいけません。 # 役人は自分の仕事をしっかり理解しなさい。 # 他の人と比べてはいけません。 # 自分勝手にしないで、思いやりの心を持ちなさい。 # 庶民を引っ張っていく時は、周りの状況もしっかり見ながら進めなさい。 # 自分だけで決めないで、みんなで様々な意見を聞いてから決めなさい。 |}  国家組織を再編成した推古朝は、607年にも'''小野妹子'''を遣隋使として、派遣しました。この時妹子は、国書を隋の皇帝であった煬帝に差し出しましたが、無礼だとされました。なぜならその国書は、倭が隋に従属しないという態度を示していたためです。倭の五王までは、中国の王朝に冊封をもとめていたので大きな変化でした。結局、煬帝は、高句麗に侵攻している情勢もあって、裴世清を倭に送りました。  国家体制が充実してきた推古朝は、歴史書編纂にも取り組みました。厩戸王と蘇我馬子が中心となり、620年に『天皇記』や『国記』などを編纂しました。これらは、6世紀に成立した「帝紀」や「旧辞」を基に、天皇と諸氏の関係性を示し、天皇の支配が正当であることを示そうとしていたと考えられます。3度目の遣隋使では、留学生や留学僧を同行させました。中国の制度や思想、文化などを取り込もうとしたのです。このとき、留学生の'''高向玄理'''や留学僧の'''旻'''・'''南淵請安'''が重要です。その後、4度目の遣隋使として犬上御田鍬を送りましたが、これが最後の遣隋使となります。 ==7世紀の東アジアと倭国== 最初に、中国の歴史を説明します。618年、隋王朝が終わり、<span style="color:#f29100">'''唐王朝'''</span>に変わりました。唐王朝は、土地を公平に分けたり、税金の仕組みを整えたりして国をまとめました。太宗皇帝の頃、唐王朝が最も栄えました('''貞観の治''')。次に、朝鮮半島の歴史を説明します。641年、百済の義慈王は権力を奪いました。やがて、百済の義慈王は新羅へ翌年から攻めました。642年、高句麗宰相の泉蓋蘇文が権力を奪うために、国王・貴族を倒します。その後、百済と手を組んで、新羅の領土を狙うようになりました。こうして、新羅は四面楚歌の状態になったので、唐に助けを求めました。しかし、唐側は「助けてほしいなら、女王を変えてください。」と条件を出します。647年、新羅の中でも女王を交代するのか交代しないのかを巡って争いが始まりました。太宗皇帝は、644年から朝鮮半島の高句麗へ攻めました(駐蹕山の戦い<ref>この名称の記述も日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。この戦いから、東アジア全体が大きく変わります。倭国でも、「大きな戦いが朝鮮半島で起きているから、このままだと悪い方向に向かうようになるかもしれない。」と考えるようになりました。そこで、これまでの政治が大きく変わるようになりました。 父親の<span style="color:#f29100">'''蘇我蝦夷'''</span>は祖父の蘇我馬子から大臣の役目を引き継いで、少しずつ大きな力を持つようになります。舒明天皇~<span style="color:#f29100">'''皇極天皇'''</span>の時代を迎えると、息子の<span style="color:#f29100">'''蘇我入鹿'''</span>は父親の蘇我蝦夷よりもさらに大きな力を持つようになりました。643年、蘇我入鹿は'''山背大兄王'''(厩戸王の息子)とその家族を殺しました。蘇我氏は高句麗のやり方と同じように蘇我氏寄りの天皇を選んで、政治の実権を握ろうとしました。これに対して、<span style="color:#f29100">'''中大兄皇子・中臣鎌足'''</span>・蘇我倉山田石川麻呂は「このまま、蘇我氏が政治の実権を握ると問題になるかもしれない。」と考えるようになります。645年7月10日、飛鳥板蓋宮で蘇我入鹿を殺しました。翌日、父親の蘇我蝦夷も追い詰められて自殺しました(<span style="color:#f29100">'''[[w:乙巳の変|乙巳の変]]'''</span>)。この後、朝廷が国をまとめていくようになります。 == 資料出所 == * 平雅行、横田冬彦ほか編著『[https://www.jikkyo.co.jp/material/dbook/R5_chireki_20220510/?pNo=6 日本史探究]』実教出版株式会社 2023年 * 佐藤信、五味文彦ほか編著『[https://new-textbook.yamakawa.co.jp/j-history/ 詳説日本史探究]』株式会社山川出版社 2023年 * 渡邊晃宏ほか編著『[https://ten.tokyo-shoseki.co.jp/text/hs/shakai/16596/ 日本史探究]』東京書籍株式会社 2023年 * 山中裕典著'''『'''[https://www.amazon.co.jp/改訂版-大学入学共通テスト-歴史総合、日本史探究の点数が面白いほどとれる本-0からはじめて100までねらえる-山中/dp/4046062371 改訂版 大学入学共通テスト 歴史総合、日本史探究の点数が面白いほどとれる本]'''』'''株式会社KADOKAWA 2024年 * 佐藤信、五味文彦ほか編著『[https://www.amazon.co.jp/%E8%A9%B3%E8%AA%AC%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6-%E4%BD%90%E8%97%A4-%E4%BF%A1/dp/4634010739/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2JVCFQ6ZSAM4W&keywords=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6&qid=1673018227&sprefix=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6%2Caps%2C229&sr=8-1 詳説日本史研究]』株式会社山川出版社 2017年 * 河合敦著『[https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%84-%E6%B2%B3%E5%90%88%E6%95%A6%E3%81%AE-%E6%97%A5%E6%9C%AC%E5%8F%B2B-%E3%80%8C%E5%8E%9F%E5%A7%8B-%E9%8E%8C%E5%80%89%E3%80%8D%E3%81%AE%E7%89%B9%E5%88%A5%E8%AC%9B%E5%BA%A7-%E6%B2%B3%E5%90%88/dp/404600794X/ref=d_pd_sbs_sccl_2_1/355-7112149-5713814?pd_rd_w=H8Pxa&content-id=amzn1.sym.820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_p=820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_r=ZWG9FNM6AD22NFF5WK2G&pd_rd_wg=scszo&pd_rd_r=8c1e9eda-f944-4c80-9e4e-7e35244ab2a6&pd_rd_i=404600794X&psc=1 世界一わかりやすい河合敦の日本史B[原始~鎌倉]の特別講座]』株式会社KADOKAWA 2014年(絶版本) == ここに注意!! == [[カテゴリ:高等学校日本史探究]] ms3z7iwsw3zs5caezp5m0lk6yo8tzxv 263783 263778 2024-11-18T11:02:13Z Kwawe 68789 /* 推古朝の外交と内政 */ 第3次遣隋使と第4次遣隋使の内容を見直しました(推敲)。 263783 wikitext text/x-wiki [[小学校・中学校・高等学校の学習]]>[[高等学校の学習]]>[[高等学校地理歴史]]>[[高等学校日本史探究]]>古代国家の形成Ⅰ ==6世紀の朝鮮半島と倭== 5世紀の朝鮮半島は、'''高句麗'''と'''百済'''の間で戦争になりました。475年、高句麗が漢城(百済の首都)を攻めました。その結果、百済の国王は降伏して、高句麗の兵士に殺されました。降伏後の百済は首都を熊津から扶余に引っ越し、'''加耶'''地域まで影響力を広げました。日本のヤマト政権も伽耶地域に関心がありました。加耶諸国と仲良くしたいので、兵士を朝鮮半島に送りました。しかし、伽耶諸国は「自分達の力だけで国を動かしていきたい」と考えるようになりました。512年、加耶地域の西側が百済の支配下に入るようになりました。6世紀を迎えると、'''新羅'''もかなり力をつけ始めます。新羅は百済と争いながら、伽耶諸国を新羅の領土に入れました。その結果、ヤマト政権は朝鮮半島の影響力を失いました。 継体天皇が亡くなると、ヤマト政権も'''大伴金村'''派(安閑天皇と宣化天皇)と'''蘇我稲目'''派('''欽明天皇''')に分かれました(二朝併立)。539年、大伴金村と蘇我稲目が仲直りします。仲直りすると、欽明天皇が国をまとめます。なお、大伴金村は'''物部尾輿'''から朝鮮半島政策でかなり怒られ、540年に政権を退くようになりました。 538年、仏教が朝鮮半島から日本に初めて伝わると、2つの意見に分かれました。蘇我稲目は「仏教を取り入れたい。」と考えました。一方、物部尾輿と中臣鎌子は「仏教を取り入れず、今までの神様を大切にしたい。」と考えました。こうして、蘇我稲目(蘇我氏)と物部尾輿(物部氏)・中臣鎌子(中臣氏)は争うようになります。この争いは子供にも引き継がれます。結局、<span style="color:#f29100">'''蘇我馬子'''</span>が仏教を取り入れるために王族や諸豪族を集めて、物部氏の代表(<span style="color:#f29100">'''物部守屋'''</span>)を587年に倒しました([[w:丁未の乱|丁未の乱]]<ref>この名称の記述は日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。なお、考古学者は、奈良県明日香村の石舞台古墳を上円下方墳と考えられています。かなり大きな横穴式石室が石舞台古墳にそのまま残っています。石舞台古墳は蘇我馬子のお墓(桃原墓)と考えられています。また、石舞台古墳近くの島庄遺跡は蘇我馬子の屋敷跡だと考えられています。 当時、国の施設('''屯倉''')・特別な人('''名代・子代''')を全国各地に置きました。また、有力豪族の代表(大夫)同士で話し合いをする仕組みも作りました。さらに、専門職('''品部''')も作られました。このように、国の仕組みが整うと、倭国も大きく変わりました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''蘇我氏はどうして大きくなりましたか?''' |- | style="padding:5px" |蘇我氏はかつて大和国の高市郡曽我地方に住んでいました。やがて、葛城家(大和南西部の一族)から離れるために、大和国の高市郡飛鳥地方に移ります(蘇我氏の独立)。蘇我稲目は大臣になり、かなり重要な政策を進めました。5世紀を迎えると、蘇我氏は当時の天皇家と結婚します。こうして蘇我氏は大きな力を持つようになり、日本各地に広がりました。また、蘇我稲目はお金や大切な物を斎蔵・内蔵・大蔵へ移して、渡来人の東漢氏に斎蔵・内蔵・大蔵の管理を任せました。さらに、蘇我稲目は自分の娘2人(堅塩媛と小姉君)を欽明天皇の妻にしました。その結果、蘇我氏は用明天皇・崇峻天皇・推古天皇と家族のような繋がりを持つようになり、ますます大きな力を持つようになりました。次の蘇我馬子は大臣になり、大夫と協力しながら政治のお仕事をしました。これに対して、崇峻天皇は蘇我馬子を恐れていました。592年、蘇我馬子は崇峻天皇を殺しました。 |} ==推古朝の外交と内政== 当時、政治の中心地は飛鳥にありました(<span style="color:#f29100">'''飛鳥時代'''</span>)。額田部皇女(豊御食炊屋姫)が蘇我馬子と豪族からの推薦で初めて女性天皇に選ばれました(<span style="color:#f29100">'''推古天皇'''</span>)。なお、額田部皇女(豊御食炊屋姫)は欽明天皇(父親)と蘇我堅塩媛(母親)の娘です。奈良県橿原市の植山古墳は東側と西側に横穴式石室を設けています。そのうち、西側の石室が推古天皇の墓だと考えられています。593年、<span style="color:#f29100">'''厩戸王'''</span>(<span style="color:#f29100">'''聖徳太子'''</span>:推古天皇の甥)が政治に携わるようになりました。そこから推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。それ以降、倭国は東アジアの国際関係を深めるようになりました。なお、日本書紀の「摂政」は平安時代の「摂政」と異なり、「誰かの代わりに政治をする。」という意味で使われます。 {| style="border:2px solid #9E7360;width:100%" cellspacing="0" ! style="background: #9E7360" |'''聖徳太子''' |- | style="padding:5px" |厩戸王(聖徳太子)は用明天皇(父親)と穴穂部皇女(母親)の息子です。実は、厩戸王(聖徳太子)の父親と母親はどちらも蘇我家でした。そして、推古天皇・蘇我馬子も蘇我氏の親戚関係なので、推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。なお、皇太子制度と摂政制度は飛鳥時代にありません。そのため、厩戸王は天皇の後継者として政治に関わるようになりました。しかし、どこまで推古天皇のお仕事を手伝っていたのかまでははっきりしません。厩戸王は残念ながら推古天皇より先に亡くなり、天皇になれませんでした。厩戸王はかなり早い時期から聖徳太子とも呼ばれ、様々な伝説も生まれました。厩戸王が亡くなってからも、一般民衆の間でますます尊敬されるようになりました。 |} 北朝の<span style="color:#f29100">'''隋'''</span>は勢力を伸ばし、南陳を589年に手に入れました。その結果、久しぶりに国がまとまりました。隋は法律を作り、朝鮮半島と倭国を攻めました。598年から高句麗に4回も軍隊を送りました。これに対して、高句麗・新羅・百済・倭国は国をまとめなければならないと思うようになりました。 5世紀頃、中国に使者を送らなくなると、倭国と中国の関係が途切れました。やがて、倭国は中国中心の考え方から抜け出して、新羅と新しい関係を作ろうとしました。倭国は新羅に3回(600年・602年・623年)も軍隊を送りました。特に、600年は新羅遠征軍と遣隋使の両方を送りました。 隋書東夷伝倭国条は第1回<span style="color:#f29100">'''遣隋使'''</span>について記されています。第1回遣隋使を隋へ送ると、隋の文帝から日本の政治と生活の仕方について厳しい意見がありました。それまで、倭国は朝鮮半島の国家と仲良くなるために、力の強さだけを見せればいいと考えていました。しかし、この厳しい意見から他の国と事前に話し合いをするようになりました。しかし、第1回遣隋使は日本の歴史書『日本書紀』に全く書かれていません。 倭国は隋と関わるうちに『政治の仕組みがまだまだ整っていないかも…』と気づきました。そこで、隋と仲良く付き合うために、厩戸王と蘇我馬子が中心になって冠位十二階と憲法十七条を作りました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''冠位十二階''' |- | style="padding:5px" |中国や朝鮮のやり方をお手本にして、冠位十二階を作りました。冠位十二階を説明すると、その人の良心(徳・仁・礼・信義・智)を評価します。そして、この評価を十二段階に分けて、その段階に合わせて六色の冠(紫・青・赤・黄・白・黒)を被るようになります。冠位十二階は生まれた時からではなく、個人の才能と個人の頑張り具合で評価されるようになっています。しかも一代限りなので、頑張れば冠位も上がりました。鞍作鳥・秦河勝・小野妹子は出身とか関係なく、自分の才能と自分の頑張りで冠位を貰えました。しかし、蘇我氏・王族・地方の豪族は冠位十二階の対象に含まれていません。 |- ! style="background: #F4ADA3" |'''憲法十七条''' |- | style="padding:5px" |憲法十七条は朝廷の仕事をするようになったら、どのような心構えで働けばいいのかについて記されています。憲法十七条は中国の影響を大きく受けており、儒教・仏教の考え方を上手く取り入れて定められました。また、隋に対して倭国の立場や意見をはっきり主張するために、憲法十七条を定めていました。この後、日本の政治の仕組みも少しずつ整いました。しかし、どこまで憲法十七条を守っていたのかまでは分かりません。憲法十七条の内容は次の通りです。 # みんな仲良く暮らしなさい。 # お坊さんを大切にしなさい。 # 天皇の言葉をしっかり聞きなさい。 # 礼儀作法を守りなさい。 # 裁判は公平に裁きなさい。 # いい人は褒めて、悪い人はしっかり注意しなさい。 # 自分の役割をきちんと果たしなさい。 # 早めに行って遅くまでしっかり働きなさい。 # 信頼関係を持ちなさい。 # 腹を立ててはいけません。 # 出来る役人は褒め、出来ない役人は注意しなさい。 # 国司・国造は、庶民から余計な税金を取ってはいけません。 # 役人は自分の仕事をしっかり理解しなさい。 # 他の人と比べてはいけません。 # 自分勝手にしないで、思いやりの心を持ちなさい。 # 庶民を引っ張っていく時は、周りの状況もしっかり見ながら進めなさい。 # 自分だけで決めないで、みんなで様々な意見を聞いてから決めなさい。 |}  国家組織を再編成した推古朝は、607年にも'''小野妹子'''を遣隋使として、派遣しました。この時妹子は、国書を隋の皇帝であった煬帝に差し出しましたが、無礼だとされました。なぜならその国書は、倭が隋に従属しないという態度を示していたためです。倭の五王までは、中国の王朝に冊封をもとめていたので大きな変化でした。結局、煬帝は、高句麗に侵攻している情勢もあって、裴世清を倭に送りました。  国家体制が充実してきた推古朝は、歴史書編纂にも取り組みました。厩戸王と蘇我馬子が中心となり、620年に『天皇記』や『国記』などを編纂しました。これらは、6世紀に成立した「帝紀」や「旧辞」を基に、天皇と諸氏の関係性を示し、天皇の支配が正当であることを示そうとしていたと考えられます。 第3次遣隋使の中でも旻・高向玄理・南淵請安は、中国史の大きな転換点を実際に見ています。旻・高向玄理・南淵請安は日本に帰ってきてから、中大兄皇子・中臣鎌足・蘇我入鹿に中国の新しい知識を伝えました。やがて、中国の新しい知識が大化の改新につながるようになりました。結局、倭国は4回も遣隋使を送っています。その中でも、犬上御田鍬が第4次遣隋使の代表として隋に渡っています。 ==7世紀の東アジアと倭国== 最初に、中国の歴史を説明します。618年、隋王朝が終わり、<span style="color:#f29100">'''唐王朝'''</span>に変わりました。唐王朝は、土地を公平に分けたり、税金の仕組みを整えたりして国をまとめました。太宗皇帝の頃、唐王朝が最も栄えました('''貞観の治''')。次に、朝鮮半島の歴史を説明します。641年、百済の義慈王は権力を奪いました。やがて、百済の義慈王は新羅へ翌年から攻めました。642年、高句麗宰相の泉蓋蘇文が権力を奪うために、国王・貴族を倒します。その後、百済と手を組んで、新羅の領土を狙うようになりました。こうして、新羅は四面楚歌の状態になったので、唐に助けを求めました。しかし、唐側は「助けてほしいなら、女王を変えてください。」と条件を出します。647年、新羅の中でも女王を交代するのか交代しないのかを巡って争いが始まりました。太宗皇帝は、644年から朝鮮半島の高句麗へ攻めました(駐蹕山の戦い<ref>この名称の記述も日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。この戦いから、東アジア全体が大きく変わります。倭国でも、「大きな戦いが朝鮮半島で起きているから、このままだと悪い方向に向かうようになるかもしれない。」と考えるようになりました。そこで、これまでの政治が大きく変わるようになりました。 父親の<span style="color:#f29100">'''蘇我蝦夷'''</span>は祖父の蘇我馬子から大臣の役目を引き継いで、少しずつ大きな力を持つようになります。舒明天皇~<span style="color:#f29100">'''皇極天皇'''</span>の時代を迎えると、息子の<span style="color:#f29100">'''蘇我入鹿'''</span>は父親の蘇我蝦夷よりもさらに大きな力を持つようになりました。643年、蘇我入鹿は'''山背大兄王'''(厩戸王の息子)とその家族を殺しました。蘇我氏は高句麗のやり方と同じように蘇我氏寄りの天皇を選んで、政治の実権を握ろうとしました。これに対して、<span style="color:#f29100">'''中大兄皇子・中臣鎌足'''</span>・蘇我倉山田石川麻呂は「このまま、蘇我氏が政治の実権を握ると問題になるかもしれない。」と考えるようになります。645年7月10日、飛鳥板蓋宮で蘇我入鹿を殺しました。翌日、父親の蘇我蝦夷も追い詰められて自殺しました(<span style="color:#f29100">'''[[w:乙巳の変|乙巳の変]]'''</span>)。この後、朝廷が国をまとめていくようになります。 == 資料出所 == * 平雅行、横田冬彦ほか編著『[https://www.jikkyo.co.jp/material/dbook/R5_chireki_20220510/?pNo=6 日本史探究]』実教出版株式会社 2023年 * 佐藤信、五味文彦ほか編著『[https://new-textbook.yamakawa.co.jp/j-history/ 詳説日本史探究]』株式会社山川出版社 2023年 * 渡邊晃宏ほか編著『[https://ten.tokyo-shoseki.co.jp/text/hs/shakai/16596/ 日本史探究]』東京書籍株式会社 2023年 * 山中裕典著'''『'''[https://www.amazon.co.jp/改訂版-大学入学共通テスト-歴史総合、日本史探究の点数が面白いほどとれる本-0からはじめて100までねらえる-山中/dp/4046062371 改訂版 大学入学共通テスト 歴史総合、日本史探究の点数が面白いほどとれる本]'''』'''株式会社KADOKAWA 2024年 * 佐藤信、五味文彦ほか編著『[https://www.amazon.co.jp/%E8%A9%B3%E8%AA%AC%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6-%E4%BD%90%E8%97%A4-%E4%BF%A1/dp/4634010739/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2JVCFQ6ZSAM4W&keywords=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6&qid=1673018227&sprefix=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6%2Caps%2C229&sr=8-1 詳説日本史研究]』株式会社山川出版社 2017年 * 河合敦著『[https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%84-%E6%B2%B3%E5%90%88%E6%95%A6%E3%81%AE-%E6%97%A5%E6%9C%AC%E5%8F%B2B-%E3%80%8C%E5%8E%9F%E5%A7%8B-%E9%8E%8C%E5%80%89%E3%80%8D%E3%81%AE%E7%89%B9%E5%88%A5%E8%AC%9B%E5%BA%A7-%E6%B2%B3%E5%90%88/dp/404600794X/ref=d_pd_sbs_sccl_2_1/355-7112149-5713814?pd_rd_w=H8Pxa&content-id=amzn1.sym.820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_p=820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_r=ZWG9FNM6AD22NFF5WK2G&pd_rd_wg=scszo&pd_rd_r=8c1e9eda-f944-4c80-9e4e-7e35244ab2a6&pd_rd_i=404600794X&psc=1 世界一わかりやすい河合敦の日本史B[原始~鎌倉]の特別講座]』株式会社KADOKAWA 2014年(絶版本) == ここに注意!! == [[カテゴリ:高等学校日本史探究]] 1sjvk4rx3mgev6f37z1kqilmxte109i 263784 263783 2024-11-18T11:05:56Z Kwawe 68789 /* 推古朝の外交と内政 */ 重要用語を色太字化。 263784 wikitext text/x-wiki [[小学校・中学校・高等学校の学習]]>[[高等学校の学習]]>[[高等学校地理歴史]]>[[高等学校日本史探究]]>古代国家の形成Ⅰ ==6世紀の朝鮮半島と倭== 5世紀の朝鮮半島は、'''高句麗'''と'''百済'''の間で戦争になりました。475年、高句麗が漢城(百済の首都)を攻めました。その結果、百済の国王は降伏して、高句麗の兵士に殺されました。降伏後の百済は首都を熊津から扶余に引っ越し、'''加耶'''地域まで影響力を広げました。日本のヤマト政権も伽耶地域に関心がありました。加耶諸国と仲良くしたいので、兵士を朝鮮半島に送りました。しかし、伽耶諸国は「自分達の力だけで国を動かしていきたい」と考えるようになりました。512年、加耶地域の西側が百済の支配下に入るようになりました。6世紀を迎えると、'''新羅'''もかなり力をつけ始めます。新羅は百済と争いながら、伽耶諸国を新羅の領土に入れました。その結果、ヤマト政権は朝鮮半島の影響力を失いました。 継体天皇が亡くなると、ヤマト政権も'''大伴金村'''派(安閑天皇と宣化天皇)と'''蘇我稲目'''派('''欽明天皇''')に分かれました(二朝併立)。539年、大伴金村と蘇我稲目が仲直りします。仲直りすると、欽明天皇が国をまとめます。なお、大伴金村は'''物部尾輿'''から朝鮮半島政策でかなり怒られ、540年に政権を退くようになりました。 538年、仏教が朝鮮半島から日本に初めて伝わると、2つの意見に分かれました。蘇我稲目は「仏教を取り入れたい。」と考えました。一方、物部尾輿と中臣鎌子は「仏教を取り入れず、今までの神様を大切にしたい。」と考えました。こうして、蘇我稲目(蘇我氏)と物部尾輿(物部氏)・中臣鎌子(中臣氏)は争うようになります。この争いは子供にも引き継がれます。結局、<span style="color:#f29100">'''蘇我馬子'''</span>が仏教を取り入れるために王族や諸豪族を集めて、物部氏の代表(<span style="color:#f29100">'''物部守屋'''</span>)を587年に倒しました([[w:丁未の乱|丁未の乱]]<ref>この名称の記述は日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。なお、考古学者は、奈良県明日香村の石舞台古墳を上円下方墳と考えられています。かなり大きな横穴式石室が石舞台古墳にそのまま残っています。石舞台古墳は蘇我馬子のお墓(桃原墓)と考えられています。また、石舞台古墳近くの島庄遺跡は蘇我馬子の屋敷跡だと考えられています。 当時、国の施設('''屯倉''')・特別な人('''名代・子代''')を全国各地に置きました。また、有力豪族の代表(大夫)同士で話し合いをする仕組みも作りました。さらに、専門職('''品部''')も作られました。このように、国の仕組みが整うと、倭国も大きく変わりました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''蘇我氏はどうして大きくなりましたか?''' |- | style="padding:5px" |蘇我氏はかつて大和国の高市郡曽我地方に住んでいました。やがて、葛城家(大和南西部の一族)から離れるために、大和国の高市郡飛鳥地方に移ります(蘇我氏の独立)。蘇我稲目は大臣になり、かなり重要な政策を進めました。5世紀を迎えると、蘇我氏は当時の天皇家と結婚します。こうして蘇我氏は大きな力を持つようになり、日本各地に広がりました。また、蘇我稲目はお金や大切な物を斎蔵・内蔵・大蔵へ移して、渡来人の東漢氏に斎蔵・内蔵・大蔵の管理を任せました。さらに、蘇我稲目は自分の娘2人(堅塩媛と小姉君)を欽明天皇の妻にしました。その結果、蘇我氏は用明天皇・崇峻天皇・推古天皇と家族のような繋がりを持つようになり、ますます大きな力を持つようになりました。次の蘇我馬子は大臣になり、大夫と協力しながら政治のお仕事をしました。これに対して、崇峻天皇は蘇我馬子を恐れていました。592年、蘇我馬子は崇峻天皇を殺しました。 |} ==推古朝の外交と内政== 当時、政治の中心地は飛鳥にありました(<span style="color:#f29100">'''飛鳥時代'''</span>)。額田部皇女(豊御食炊屋姫)が蘇我馬子と豪族からの推薦で初めて女性天皇に選ばれました(<span style="color:#f29100">'''推古天皇'''</span>)。なお、額田部皇女(豊御食炊屋姫)は欽明天皇(父親)と蘇我堅塩媛(母親)の娘です。奈良県橿原市の植山古墳は東側と西側に横穴式石室を設けています。そのうち、西側の石室が推古天皇の墓だと考えられています。593年、<span style="color:#f29100">'''厩戸王'''</span>(<span style="color:#f29100">'''聖徳太子'''</span>:推古天皇の甥)が政治に携わるようになりました。そこから推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。それ以降、倭国は東アジアの国際関係を深めるようになりました。なお、日本書紀の「摂政」は平安時代の「摂政」と異なり、「誰かの代わりに政治をする。」という意味で使われます。 {| style="border:2px solid #9E7360;width:100%" cellspacing="0" ! style="background: #9E7360" |'''聖徳太子''' |- | style="padding:5px" |厩戸王(聖徳太子)は用明天皇(父親)と穴穂部皇女(母親)の息子です。実は、厩戸王(聖徳太子)の父親と母親はどちらも蘇我家でした。そして、推古天皇・蘇我馬子も蘇我氏の親戚関係なので、推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。なお、皇太子制度と摂政制度は飛鳥時代にありません。そのため、厩戸王は天皇の後継者として政治に関わるようになりました。しかし、どこまで推古天皇のお仕事を手伝っていたのかまでははっきりしません。厩戸王は残念ながら推古天皇より先に亡くなり、天皇になれませんでした。厩戸王はかなり早い時期から聖徳太子とも呼ばれ、様々な伝説も生まれました。厩戸王が亡くなってからも、一般民衆の間でますます尊敬されるようになりました。 |} 北朝の<span style="color:#f29100">'''隋'''</span>は勢力を伸ばし、南陳を589年に手に入れました。その結果、久しぶりに国がまとまりました。隋は法律を作り、朝鮮半島と倭国を攻めました。598年から高句麗に4回も軍隊を送りました。これに対して、高句麗・新羅・百済・倭国は国をまとめなければならないと思うようになりました。 5世紀頃、中国に使者を送らなくなると、倭国と中国の関係が途切れました。やがて、倭国は中国中心の考え方から抜け出して、新羅と新しい関係を作ろうとしました。倭国は新羅に3回(600年・602年・623年)も軍隊を送りました。特に、600年は新羅遠征軍と遣隋使の両方を送りました。 隋書東夷伝倭国条は第1回<span style="color:#f29100">'''遣隋使'''</span>について記されています。第1回遣隋使を隋へ送ると、隋の文帝から日本の政治と生活の仕方について厳しい意見がありました。それまで、倭国は朝鮮半島の国家と仲良くなるために、力の強さだけを見せればいいと考えていました。しかし、この厳しい意見から他の国と事前に話し合いをするようになりました。しかし、第1回遣隋使は日本の歴史書『日本書紀』に全く書かれていません。 倭国は隋と関わるうちに『政治の仕組みがまだまだ整っていないかも…』と気づきました。そこで、隋と仲良く付き合うために、厩戸王と蘇我馬子が中心になって冠位十二階と憲法十七条を作りました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''冠位十二階''' |- | style="padding:5px" |中国や朝鮮のやり方をお手本にして、冠位十二階を作りました。冠位十二階を説明すると、その人の良心(徳・仁・礼・信義・智)を評価します。そして、この評価を十二段階に分けて、その段階に合わせて六色の冠(紫・青・赤・黄・白・黒)を被るようになります。冠位十二階は生まれた時からではなく、個人の才能と個人の頑張り具合で評価されるようになっています。しかも一代限りなので、頑張れば冠位も上がりました。鞍作鳥・秦河勝・小野妹子は出身とか関係なく、自分の才能と自分の頑張りで冠位を貰えました。しかし、蘇我氏・王族・地方の豪族は冠位十二階の対象に含まれていません。 |- ! style="background: #F4ADA3" |'''憲法十七条''' |- | style="padding:5px" |憲法十七条は朝廷の仕事をするようになったら、どのような心構えで働けばいいのかについて記されています。憲法十七条は中国の影響を大きく受けており、儒教・仏教の考え方を上手く取り入れて定められました。また、隋に対して倭国の立場や意見をはっきり主張するために、憲法十七条を定めていました。この後、日本の政治の仕組みも少しずつ整いました。しかし、どこまで憲法十七条を守っていたのかまでは分かりません。憲法十七条の内容は次の通りです。 # みんな仲良く暮らしなさい。 # お坊さんを大切にしなさい。 # 天皇の言葉をしっかり聞きなさい。 # 礼儀作法を守りなさい。 # 裁判は公平に裁きなさい。 # いい人は褒めて、悪い人はしっかり注意しなさい。 # 自分の役割をきちんと果たしなさい。 # 早めに行って遅くまでしっかり働きなさい。 # 信頼関係を持ちなさい。 # 腹を立ててはいけません。 # 出来る役人は褒め、出来ない役人は注意しなさい。 # 国司・国造は、庶民から余計な税金を取ってはいけません。 # 役人は自分の仕事をしっかり理解しなさい。 # 他の人と比べてはいけません。 # 自分勝手にしないで、思いやりの心を持ちなさい。 # 庶民を引っ張っていく時は、周りの状況もしっかり見ながら進めなさい。 # 自分だけで決めないで、みんなで様々な意見を聞いてから決めなさい。 |}  国家組織を再編成した推古朝は、607年にも'''小野妹子'''を遣隋使として、派遣しました。この時妹子は、国書を隋の皇帝であった煬帝に差し出しましたが、無礼だとされました。なぜならその国書は、倭が隋に従属しないという態度を示していたためです。倭の五王までは、中国の王朝に冊封をもとめていたので大きな変化でした。結局、煬帝は、高句麗に侵攻している情勢もあって、裴世清を倭に送りました。  国家体制が充実してきた推古朝は、歴史書編纂にも取り組みました。厩戸王と蘇我馬子が中心となり、620年に『天皇記』や『国記』などを編纂しました。これらは、6世紀に成立した「帝紀」や「旧辞」を基に、天皇と諸氏の関係性を示し、天皇の支配が正当であることを示そうとしていたと考えられます。 第3次遣隋使の中でも<span style="color:#f29100">'''旻・高向玄理・南淵請安'''</span>は、中国史の大きな転換点を実際に見ています。旻・高向玄理・南淵請安は日本に帰ってきてから、中大兄皇子・中臣鎌足・蘇我入鹿に中国の新しい知識を伝えました。やがて、中国の新しい知識が大化の改新につながるようになりました。結局、倭国は4回も遣隋使を送っています。その中でも、犬上御田鍬が第4次遣隋使の代表として隋に渡っています。 ==7世紀の東アジアと倭国== 最初に、中国の歴史を説明します。618年、隋王朝が終わり、<span style="color:#f29100">'''唐王朝'''</span>に変わりました。唐王朝は、土地を公平に分けたり、税金の仕組みを整えたりして国をまとめました。太宗皇帝の頃、唐王朝が最も栄えました('''貞観の治''')。次に、朝鮮半島の歴史を説明します。641年、百済の義慈王は権力を奪いました。やがて、百済の義慈王は新羅へ翌年から攻めました。642年、高句麗宰相の泉蓋蘇文が権力を奪うために、国王・貴族を倒します。その後、百済と手を組んで、新羅の領土を狙うようになりました。こうして、新羅は四面楚歌の状態になったので、唐に助けを求めました。しかし、唐側は「助けてほしいなら、女王を変えてください。」と条件を出します。647年、新羅の中でも女王を交代するのか交代しないのかを巡って争いが始まりました。太宗皇帝は、644年から朝鮮半島の高句麗へ攻めました(駐蹕山の戦い<ref>この名称の記述も日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。この戦いから、東アジア全体が大きく変わります。倭国でも、「大きな戦いが朝鮮半島で起きているから、このままだと悪い方向に向かうようになるかもしれない。」と考えるようになりました。そこで、これまでの政治が大きく変わるようになりました。 父親の<span style="color:#f29100">'''蘇我蝦夷'''</span>は祖父の蘇我馬子から大臣の役目を引き継いで、少しずつ大きな力を持つようになります。舒明天皇~<span style="color:#f29100">'''皇極天皇'''</span>の時代を迎えると、息子の<span style="color:#f29100">'''蘇我入鹿'''</span>は父親の蘇我蝦夷よりもさらに大きな力を持つようになりました。643年、蘇我入鹿は'''山背大兄王'''(厩戸王の息子)とその家族を殺しました。蘇我氏は高句麗のやり方と同じように蘇我氏寄りの天皇を選んで、政治の実権を握ろうとしました。これに対して、<span style="color:#f29100">'''中大兄皇子・中臣鎌足'''</span>・蘇我倉山田石川麻呂は「このまま、蘇我氏が政治の実権を握ると問題になるかもしれない。」と考えるようになります。645年7月10日、飛鳥板蓋宮で蘇我入鹿を殺しました。翌日、父親の蘇我蝦夷も追い詰められて自殺しました(<span style="color:#f29100">'''[[w:乙巳の変|乙巳の変]]'''</span>)。この後、朝廷が国をまとめていくようになります。 == 資料出所 == * 平雅行、横田冬彦ほか編著『[https://www.jikkyo.co.jp/material/dbook/R5_chireki_20220510/?pNo=6 日本史探究]』実教出版株式会社 2023年 * 佐藤信、五味文彦ほか編著『[https://new-textbook.yamakawa.co.jp/j-history/ 詳説日本史探究]』株式会社山川出版社 2023年 * 渡邊晃宏ほか編著『[https://ten.tokyo-shoseki.co.jp/text/hs/shakai/16596/ 日本史探究]』東京書籍株式会社 2023年 * 山中裕典著'''『'''[https://www.amazon.co.jp/改訂版-大学入学共通テスト-歴史総合、日本史探究の点数が面白いほどとれる本-0からはじめて100までねらえる-山中/dp/4046062371 改訂版 大学入学共通テスト 歴史総合、日本史探究の点数が面白いほどとれる本]'''』'''株式会社KADOKAWA 2024年 * 佐藤信、五味文彦ほか編著『[https://www.amazon.co.jp/%E8%A9%B3%E8%AA%AC%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6-%E4%BD%90%E8%97%A4-%E4%BF%A1/dp/4634010739/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2JVCFQ6ZSAM4W&keywords=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6&qid=1673018227&sprefix=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6%2Caps%2C229&sr=8-1 詳説日本史研究]』株式会社山川出版社 2017年 * 河合敦著『[https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%84-%E6%B2%B3%E5%90%88%E6%95%A6%E3%81%AE-%E6%97%A5%E6%9C%AC%E5%8F%B2B-%E3%80%8C%E5%8E%9F%E5%A7%8B-%E9%8E%8C%E5%80%89%E3%80%8D%E3%81%AE%E7%89%B9%E5%88%A5%E8%AC%9B%E5%BA%A7-%E6%B2%B3%E5%90%88/dp/404600794X/ref=d_pd_sbs_sccl_2_1/355-7112149-5713814?pd_rd_w=H8Pxa&content-id=amzn1.sym.820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_p=820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_r=ZWG9FNM6AD22NFF5WK2G&pd_rd_wg=scszo&pd_rd_r=8c1e9eda-f944-4c80-9e4e-7e35244ab2a6&pd_rd_i=404600794X&psc=1 世界一わかりやすい河合敦の日本史B[原始~鎌倉]の特別講座]』株式会社KADOKAWA 2014年(絶版本) == ここに注意!! == [[カテゴリ:高等学校日本史探究]] 8jdkjkbtiucuy5z5rdbr7hoeqcehyb5 263786 263784 2024-11-18T11:30:56Z Kwawe 68789 /* 推古朝の外交と内政 */ 裴世清の記述を直しました(推敲)。 263786 wikitext text/x-wiki [[小学校・中学校・高等学校の学習]]>[[高等学校の学習]]>[[高等学校地理歴史]]>[[高等学校日本史探究]]>古代国家の形成Ⅰ ==6世紀の朝鮮半島と倭== 5世紀の朝鮮半島は、'''高句麗'''と'''百済'''の間で戦争になりました。475年、高句麗が漢城(百済の首都)を攻めました。その結果、百済の国王は降伏して、高句麗の兵士に殺されました。降伏後の百済は首都を熊津から扶余に引っ越し、'''加耶'''地域まで影響力を広げました。日本のヤマト政権も伽耶地域に関心がありました。加耶諸国と仲良くしたいので、兵士を朝鮮半島に送りました。しかし、伽耶諸国は「自分達の力だけで国を動かしていきたい」と考えるようになりました。512年、加耶地域の西側が百済の支配下に入るようになりました。6世紀を迎えると、'''新羅'''もかなり力をつけ始めます。新羅は百済と争いながら、伽耶諸国を新羅の領土に入れました。その結果、ヤマト政権は朝鮮半島の影響力を失いました。 継体天皇が亡くなると、ヤマト政権も'''大伴金村'''派(安閑天皇と宣化天皇)と'''蘇我稲目'''派('''欽明天皇''')に分かれました(二朝併立)。539年、大伴金村と蘇我稲目が仲直りします。仲直りすると、欽明天皇が国をまとめます。なお、大伴金村は'''物部尾輿'''から朝鮮半島政策でかなり怒られ、540年に政権を退くようになりました。 538年、仏教が朝鮮半島から日本に初めて伝わると、2つの意見に分かれました。蘇我稲目は「仏教を取り入れたい。」と考えました。一方、物部尾輿と中臣鎌子は「仏教を取り入れず、今までの神様を大切にしたい。」と考えました。こうして、蘇我稲目(蘇我氏)と物部尾輿(物部氏)・中臣鎌子(中臣氏)は争うようになります。この争いは子供にも引き継がれます。結局、<span style="color:#f29100">'''蘇我馬子'''</span>が仏教を取り入れるために王族や諸豪族を集めて、物部氏の代表(<span style="color:#f29100">'''物部守屋'''</span>)を587年に倒しました([[w:丁未の乱|丁未の乱]]<ref>この名称の記述は日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。なお、考古学者は、奈良県明日香村の石舞台古墳を上円下方墳と考えられています。かなり大きな横穴式石室が石舞台古墳にそのまま残っています。石舞台古墳は蘇我馬子のお墓(桃原墓)と考えられています。また、石舞台古墳近くの島庄遺跡は蘇我馬子の屋敷跡だと考えられています。 当時、国の施設('''屯倉''')・特別な人('''名代・子代''')を全国各地に置きました。また、有力豪族の代表(大夫)同士で話し合いをする仕組みも作りました。さらに、専門職('''品部''')も作られました。このように、国の仕組みが整うと、倭国も大きく変わりました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''蘇我氏はどうして大きくなりましたか?''' |- | style="padding:5px" |蘇我氏はかつて大和国の高市郡曽我地方に住んでいました。やがて、葛城家(大和南西部の一族)から離れるために、大和国の高市郡飛鳥地方に移ります(蘇我氏の独立)。蘇我稲目は大臣になり、かなり重要な政策を進めました。5世紀を迎えると、蘇我氏は当時の天皇家と結婚します。こうして蘇我氏は大きな力を持つようになり、日本各地に広がりました。また、蘇我稲目はお金や大切な物を斎蔵・内蔵・大蔵へ移して、渡来人の東漢氏に斎蔵・内蔵・大蔵の管理を任せました。さらに、蘇我稲目は自分の娘2人(堅塩媛と小姉君)を欽明天皇の妻にしました。その結果、蘇我氏は用明天皇・崇峻天皇・推古天皇と家族のような繋がりを持つようになり、ますます大きな力を持つようになりました。次の蘇我馬子は大臣になり、大夫と協力しながら政治のお仕事をしました。これに対して、崇峻天皇は蘇我馬子を恐れていました。592年、蘇我馬子は崇峻天皇を殺しました。 |} ==推古朝の外交と内政== 当時、政治の中心地は飛鳥にありました(<span style="color:#f29100">'''飛鳥時代'''</span>)。額田部皇女(豊御食炊屋姫)が蘇我馬子と豪族からの推薦で初めて女性天皇に選ばれました(<span style="color:#f29100">'''推古天皇'''</span>)。なお、額田部皇女(豊御食炊屋姫)は欽明天皇(父親)と蘇我堅塩媛(母親)の娘です。奈良県橿原市の植山古墳は東側と西側に横穴式石室を設けています。そのうち、西側の石室が推古天皇の墓だと考えられています。593年、<span style="color:#f29100">'''厩戸王'''</span>(<span style="color:#f29100">'''聖徳太子'''</span>:推古天皇の甥)が政治に携わるようになりました。そこから推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。それ以降、倭国は東アジアの国際関係を深めるようになりました。なお、日本書紀の「摂政」は平安時代の「摂政」と異なり、「誰かの代わりに政治をする。」という意味で使われます。 {| style="border:2px solid #9E7360;width:100%" cellspacing="0" ! style="background: #9E7360" |'''聖徳太子''' |- | style="padding:5px" |厩戸王(聖徳太子)は用明天皇(父親)と穴穂部皇女(母親)の息子です。実は、厩戸王(聖徳太子)の父親と母親はどちらも蘇我家でした。そして、推古天皇・蘇我馬子も蘇我氏の親戚関係なので、推古天皇・厩戸王・蘇我馬子の3人が力を合わせて国を治めるようになりました。なお、皇太子制度と摂政制度は飛鳥時代にありません。そのため、厩戸王は天皇の後継者として政治に関わるようになりました。しかし、どこまで推古天皇のお仕事を手伝っていたのかまでははっきりしません。厩戸王は残念ながら推古天皇より先に亡くなり、天皇になれませんでした。厩戸王はかなり早い時期から聖徳太子とも呼ばれ、様々な伝説も生まれました。厩戸王が亡くなってからも、一般民衆の間でますます尊敬されるようになりました。 |} 北朝の<span style="color:#f29100">'''隋'''</span>は勢力を伸ばし、南陳を589年に手に入れました。その結果、久しぶりに国がまとまりました。隋は法律を作り、朝鮮半島と倭国を攻めました。598年から高句麗に4回も軍隊を送りました。これに対して、高句麗・新羅・百済・倭国は国をまとめなければならないと思うようになりました。 5世紀頃、中国に使者を送らなくなると、倭国と中国の関係が途切れました。やがて、倭国は中国中心の考え方から抜け出して、新羅と新しい関係を作ろうとしました。倭国は新羅に3回(600年・602年・623年)も軍隊を送りました。特に、600年は新羅遠征軍と遣隋使の両方を送りました。 隋書東夷伝倭国条は第1回<span style="color:#f29100">'''遣隋使'''</span>について記されています。第1回遣隋使を隋へ送ると、隋の文帝から日本の政治と生活の仕方について厳しい意見がありました。それまで、倭国は朝鮮半島の国家と仲良くなるために、力の強さだけを見せればいいと考えていました。しかし、この厳しい意見から他の国と事前に話し合いをするようになりました。しかし、第1回遣隋使は日本の歴史書『日本書紀』に全く書かれていません。 倭国は隋と関わるうちに『政治の仕組みがまだまだ整っていないかも…』と気づきました。そこで、隋と仲良く付き合うために、厩戸王と蘇我馬子が中心になって冠位十二階と憲法十七条を作りました。 {| style="border:2px solid #F4ADA3;width:100%" cellspacing="0" ! style="background: #F4ADA3" |'''冠位十二階''' |- | style="padding:5px" |中国や朝鮮のやり方をお手本にして、冠位十二階を作りました。冠位十二階を説明すると、その人の良心(徳・仁・礼・信義・智)を評価します。そして、この評価を十二段階に分けて、その段階に合わせて六色の冠(紫・青・赤・黄・白・黒)を被るようになります。冠位十二階は生まれた時からではなく、個人の才能と個人の頑張り具合で評価されるようになっています。しかも一代限りなので、頑張れば冠位も上がりました。鞍作鳥・秦河勝・小野妹子は出身とか関係なく、自分の才能と自分の頑張りで冠位を貰えました。しかし、蘇我氏・王族・地方の豪族は冠位十二階の対象に含まれていません。 |- ! style="background: #F4ADA3" |'''憲法十七条''' |- | style="padding:5px" |憲法十七条は朝廷の仕事をするようになったら、どのような心構えで働けばいいのかについて記されています。憲法十七条は中国の影響を大きく受けており、儒教・仏教の考え方を上手く取り入れて定められました。また、隋に対して倭国の立場や意見をはっきり主張するために、憲法十七条を定めていました。この後、日本の政治の仕組みも少しずつ整いました。しかし、どこまで憲法十七条を守っていたのかまでは分かりません。憲法十七条の内容は次の通りです。 # みんな仲良く暮らしなさい。 # お坊さんを大切にしなさい。 # 天皇の言葉をしっかり聞きなさい。 # 礼儀作法を守りなさい。 # 裁判は公平に裁きなさい。 # いい人は褒めて、悪い人はしっかり注意しなさい。 # 自分の役割をきちんと果たしなさい。 # 早めに行って遅くまでしっかり働きなさい。 # 信頼関係を持ちなさい。 # 腹を立ててはいけません。 # 出来る役人は褒め、出来ない役人は注意しなさい。 # 国司・国造は、庶民から余計な税金を取ってはいけません。 # 役人は自分の仕事をしっかり理解しなさい。 # 他の人と比べてはいけません。 # 自分勝手にしないで、思いやりの心を持ちなさい。 # 庶民を引っ張っていく時は、周りの状況もしっかり見ながら進めなさい。 # 自分だけで決めないで、みんなで様々な意見を聞いてから決めなさい。 |}  国家組織を再編成した推古朝は、607年にも'''小野妹子'''を遣隋使として、派遣しました。この時妹子は、国書を隋の皇帝であった煬帝に差し出しましたが、無礼だとされました。なぜならその国書は、倭が隋に従属しないという態度を示していたためです。倭の五王までは、中国の王朝に冊封をもとめていたので大きな変化でした。 ところが、隋の煬帝は「高句麗と倭国が手を組むと、自分の国が困るかもしれない。」と心配になりました。そこで、隋の煬帝は裴世清を使者として倭国に送り、隋国と倭国の関係を保とうとしました。  国家体制が充実してきた推古朝は、歴史書編纂にも取り組みました。厩戸王と蘇我馬子が中心となり、620年に『天皇記』や『国記』などを編纂しました。これらは、6世紀に成立した「帝紀」や「旧辞」を基に、天皇と諸氏の関係性を示し、天皇の支配が正当であることを示そうとしていたと考えられます。 倭国は4回も遣隋使を送りました。第3次遣隋使の中でも<span style="color:#f29100">'''旻・高向玄理・南淵請安'''</span>は、中国史の大きな転換点を実際に見ています。旻・高向玄理・南淵請安は日本に帰ってきてから、中大兄皇子・中臣鎌足・蘇我入鹿に中国の新しい知識を伝えました。やがて、中国の新しい知識が大化の改新につながるようになりました。なお、犬上御田鍬は第4次遣隋使の代表として隋に渡っています。 ==7世紀の東アジアと倭国== 最初に、中国の歴史を説明します。618年、隋王朝が終わり、<span style="color:#f29100">'''唐王朝'''</span>に変わりました。唐王朝は、土地を公平に分けたり、税金の仕組みを整えたりして国をまとめました。太宗皇帝の頃、唐王朝が最も栄えました('''貞観の治''')。次に、朝鮮半島の歴史を説明します。641年、百済の義慈王は権力を奪いました。やがて、百済の義慈王は新羅へ翌年から攻めました。642年、高句麗宰相の泉蓋蘇文が権力を奪うために、国王・貴族を倒します。その後、百済と手を組んで、新羅の領土を狙うようになりました。こうして、新羅は四面楚歌の状態になったので、唐に助けを求めました。しかし、唐側は「助けてほしいなら、女王を変えてください。」と条件を出します。647年、新羅の中でも女王を交代するのか交代しないのかを巡って争いが始まりました。太宗皇帝は、644年から朝鮮半島の高句麗へ攻めました(駐蹕山の戦い<ref>この名称の記述も日本史探究の全教科書・全参考書・資料集に記載されていません。</ref>)。この戦いから、東アジア全体が大きく変わります。倭国でも、「大きな戦いが朝鮮半島で起きているから、このままだと悪い方向に向かうようになるかもしれない。」と考えるようになりました。そこで、これまでの政治が大きく変わるようになりました。 父親の<span style="color:#f29100">'''蘇我蝦夷'''</span>は祖父の蘇我馬子から大臣の役目を引き継いで、少しずつ大きな力を持つようになります。舒明天皇~<span style="color:#f29100">'''皇極天皇'''</span>の時代を迎えると、息子の<span style="color:#f29100">'''蘇我入鹿'''</span>は父親の蘇我蝦夷よりもさらに大きな力を持つようになりました。643年、蘇我入鹿は'''山背大兄王'''(厩戸王の息子)とその家族を殺しました。蘇我氏は高句麗のやり方と同じように蘇我氏寄りの天皇を選んで、政治の実権を握ろうとしました。これに対して、<span style="color:#f29100">'''中大兄皇子・中臣鎌足'''</span>・蘇我倉山田石川麻呂は「このまま、蘇我氏が政治の実権を握ると問題になるかもしれない。」と考えるようになります。645年7月10日、飛鳥板蓋宮で蘇我入鹿を殺しました。翌日、父親の蘇我蝦夷も追い詰められて自殺しました(<span style="color:#f29100">'''[[w:乙巳の変|乙巳の変]]'''</span>)。この後、朝廷が国をまとめていくようになります。 == 資料出所 == * 平雅行、横田冬彦ほか編著『[https://www.jikkyo.co.jp/material/dbook/R5_chireki_20220510/?pNo=6 日本史探究]』実教出版株式会社 2023年 * 佐藤信、五味文彦ほか編著『[https://new-textbook.yamakawa.co.jp/j-history/ 詳説日本史探究]』株式会社山川出版社 2023年 * 渡邊晃宏ほか編著『[https://ten.tokyo-shoseki.co.jp/text/hs/shakai/16596/ 日本史探究]』東京書籍株式会社 2023年 * 山中裕典著'''『'''[https://www.amazon.co.jp/改訂版-大学入学共通テスト-歴史総合、日本史探究の点数が面白いほどとれる本-0からはじめて100までねらえる-山中/dp/4046062371 改訂版 大学入学共通テスト 歴史総合、日本史探究の点数が面白いほどとれる本]'''』'''株式会社KADOKAWA 2024年 * 佐藤信、五味文彦ほか編著『[https://www.amazon.co.jp/%E8%A9%B3%E8%AA%AC%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6-%E4%BD%90%E8%97%A4-%E4%BF%A1/dp/4634010739/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2JVCFQ6ZSAM4W&keywords=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6&qid=1673018227&sprefix=%E6%97%A5%E6%9C%AC%E5%8F%B2%E7%A0%94%E7%A9%B6%2Caps%2C229&sr=8-1 詳説日本史研究]』株式会社山川出版社 2017年 * 河合敦著『[https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E4%B8%80%E3%82%8F%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%84-%E6%B2%B3%E5%90%88%E6%95%A6%E3%81%AE-%E6%97%A5%E6%9C%AC%E5%8F%B2B-%E3%80%8C%E5%8E%9F%E5%A7%8B-%E9%8E%8C%E5%80%89%E3%80%8D%E3%81%AE%E7%89%B9%E5%88%A5%E8%AC%9B%E5%BA%A7-%E6%B2%B3%E5%90%88/dp/404600794X/ref=d_pd_sbs_sccl_2_1/355-7112149-5713814?pd_rd_w=H8Pxa&content-id=amzn1.sym.820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_p=820591ed-a555-4556-9bf6-5ebd5493c69e&pf_rd_r=ZWG9FNM6AD22NFF5WK2G&pd_rd_wg=scszo&pd_rd_r=8c1e9eda-f944-4c80-9e4e-7e35244ab2a6&pd_rd_i=404600794X&psc=1 世界一わかりやすい河合敦の日本史B[原始~鎌倉]の特別講座]』株式会社KADOKAWA 2014年(絶版本) == ここに注意!! == [[カテゴリ:高等学校日本史探究]] 6pcuyijqglvb0hzxtufh4wr6mmzcttq トーク:高校化学 天然高分子化合物 1 43379 263742 2024-11-18T04:34:34Z ~2024-14912 84966 /* #アミノ酸の反応 */ 新しい節 263742 wikitext text/x-wiki == #アミノ酸の反応 == [https://upload.wikimedia.org/wikipedia/commons/3/39/アミノ酸のアミド化とエステル化.svg 画像]のアミドの構造が間違っています。具体的には、「<chem>NHCOOCH3</chem>」ではなく「<chem>NHCOCH3</chem>」です。画像の差し替えをお願いします。--[[特別:投稿記録/&#126;2024-14912|&#126;2024-14912]] ([[利用者・トーク:&#126;2024-14912|会話]]) 2024年11月18日 (月) 04:34 (UTC) 057xeeev029k8jkgdupawojyh9dj69j 263789 263742 2024-11-18T11:43:48Z Nermer314 62933 /* #アミノ酸の反応 */ 返信 263789 wikitext text/x-wiki == #アミノ酸の反応 == [https://upload.wikimedia.org/wikipedia/commons/3/39/アミノ酸のアミド化とエステル化.svg 画像]のアミドの構造が間違っています。具体的には、「<chem>NHCOOCH3</chem>」ではなく「<chem>NHCOCH3</chem>」です。画像の差し替えをお願いします。--[[特別:投稿記録/&#126;2024-14912|&#126;2024-14912]] ([[利用者・トーク:&#126;2024-14912|会話]]) 2024年11月18日 (月) 04:34 (UTC) :新しい画像に変更しました。--[[利用者:Nermer314|Nermer314]] ([[利用者・トーク:Nermer314|トーク]]) 2024年11月18日 (月) 11:43 (UTC) scmziqn1u7hd749bn4ak5szxs0cucif C Sharp/改廃された技術 0 43380 263748 2024-11-18T09:02:23Z Ef3 694 /*改廃された技術*/ C#の改廃された技術や利用が推奨されない技術は、.NET プラットフォームの進化、新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 /*Windows Forms(従来型)*/ サポート開始年: 2002年 サポート終了年: なし(.NET Framework版は維持モード) 廃止または衰退の理由 .NET Frameworkから.NET Core/.NET 5+への移行に伴い、クロスプラットフォーム対応やモダンなUI開発手法の需要が高まりました。 代替技術 WPF、.NET MAUI、BlazorなどのモダンなUIフレームワークが推奨されます。 /*ASP.NET Web Forms*/ サポート開始年: 2002年 サポート終了年: 2027年(.NET Framework 4.8のサポート終了時) 廃止または衰退の理由 ViewStateの重さ、テスト困難性、モダンなWeb開発手法との相性の悪さにより、新規開発での採用が減少しています。 263748 wikitext text/x-wiki C#の改廃された技術や利用が推奨されない技術について、以下にまとめました。 == 改廃された技術 == C#の改廃された技術や利用が推奨されない技術は、.NET プラットフォームの進化、新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 === Windows Forms(従来型) === * '''サポート開始年:''' 2002年 * '''サポート終了年:''' なし(.NET Framework版は維持モード) ; 廃止または衰退の理由 : .NET Frameworkから.NET Core/.NET 5+への移行に伴い、クロスプラットフォーム対応やモダンなUI開発手法の需要が高まりました。 ; 代替技術 : WPF、.NET MAUI、BlazorなどのモダンなUIフレームワークが推奨されます。 === ASP.NET Web Forms === * '''サポート開始年:''' 2002年 * '''サポート終了年:''' 2027年(.NET Framework 4.8のサポート終了時) ; 廃止または衰退の理由 : ViewStateの重さ、テスト困難性、モダンなWeb開発手法との相性の悪さにより、新規開発での採用が減少しています。 ; 代替技術 : ASP.NET Core MVC、Blazor、ASP.NET Core Razorページが推奨されます。 === LINQ to SQL === * '''サポート開始年:''' 2007年 ; 利用推奨されない理由 : Entity Frameworkの機能が充実し、Microsoft自身がEntity Frameworkの利用を推奨しているため。 ; 代替技術 : Entity Framework Core、Dapperなどの最新のORMが推奨されます。 === .NET Framework === * '''対象:''' .NET Framework 4.8以前のバージョン ; 利用推奨されない理由 : クロスプラットフォーム対応、パフォーマンス、最新機能の追加などの面で.NET Core/.NET 5+に劣るため。 ; 代替技術 : .NET 6.0以降のバージョンが推奨されます。 === WCF (Windows Communication Foundation) === * '''サポート開始年:''' 2006年 * '''サポート終了年:''' .NET Core以降はサポート終了 ; 廃止または衰退の理由 : .NET Coreおよびクロスプラットフォームでのサポートが終了し、より軽量なWeb APIの需要が高まったため。 ; 代替技術 : gRPC、ASP.NET Core Web API、MinimalAPIが推奨されます。 === Silverlight === * '''サポート開始年:''' 2007年 * '''サポート終了年:''' 2021年 ; 廃止または衰退の理由 : HTML5の普及とブラウザプラグインのサポート終了により、使用できなくなりました。 ; 代替技術 : Blazor、Progressive Web Apps (PWA)、モダンなJavaScriptフレームワーク。 === ASP.NET Membership === * '''サポート開始年:''' 2005年 * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : カスタマイズの難しさと、より柔軟なASP.NET Identity の登場により、利用が減少しました。 ; 代替技術 : ASP.NET Core Identity、カスタム認証システム。 === .NET XML Web Services === * '''サポート開始年:''' 2002年 ; 廃止または衰退の理由 : SOAPベースのWeb サービスからRESTful APIへの移行が進んだため。 ; 代替技術 : ASP.NET Core Web API、gRPC。 === RemotingサービスとChannel === * '''サポート開始年:''' 2002年 * '''サポート終了年:''' .NET Core以降サポート終了 ; 廃止または衰退の理由 : WCFの登場とその後のgRPCへの移行により、使用されなくなりました。 ; 代替技術 : gRPC、ASP.NET Core Web API。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:C Sharp]] pmx25fstvfb1fkhmh4g7s09ukp6osw4 C++/改廃された技術 0 43381 263749 2024-11-18T09:07:31Z Ef3 694 /*改廃された技術*/ C++の改廃された技術や利用が推奨されない技術は、言語標準の進化、新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 263749 wikitext text/x-wiki == 改廃された技術 == C++の改廃された技術や利用が推奨されない技術は、言語標準の進化、新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 === auto_ptr === * '''サポート開始年:''' 1998年(C++98) * '''サポート終了年:''' 2017年(C++17で完全削除) ; 廃止または衰退の理由 : コピーセマンティクスの問題や、ムーブセマンティクスのサポート不足により、予期せぬ動作を引き起こす可能性がありました。 ; 代替技術 : unique_ptr、shared_ptr、weak_ptrなどのモダンなスマートポインタが推奨されます。 === std::random_shuffle === * '''サポート開始年:''' 1998年(C++98) * '''サポート終了年:''' 2017年(C++17で削除) ; 廃止または衰退の理由 : 内部で使用する乱数生成器が実装依存であり、移植性や再現性に問題がありました。 ; 代替技術 : std::shuffle と <random> ライブラリの乱数生成器の組み合わせが推奨されます。 === std::strstream === * '''サポート開始年:''' 1998年(C++98) * '''サポート終了年:''' deprecated in C++98 ; 利用推奨されない理由 : メモリ管理の問題や使いにくさがあり、より安全で柔軟な代替手段が存在するため。 ; 代替技術 : std::stringstream、std::ostringstream、std::istringstream が推奨されます。 === throws指定子 === * '''対象:''' 関数宣言での例外指定 * '''サポート終了年:''' 2017年(C++17でdynamic exception specifications削除) ; 廃止または衰退の理由 : 実行時のオーバーヘッド、保守性の問題、例外仕様の厳格さによる柔軟性の欠如。 ; 代替技術 : noexcept指定子の使用が推奨されます。 === std::binary_function と std::unary_function === * '''サポート開始年:''' 1998年(C++98) * '''サポート終了年:''' 2017年(C++17で削除) ; 廃止または衰退の理由 : ラムダ式やstd::functionの導入により、より柔軟な関数オブジェクトの定義が可能になったため。 ; 代替技術 : ラムダ式、std::function、カスタム関数オブジェクトが推奨されます。 === register キーワード === * '''サポート開始年:''' C言語から継承 * '''サポート終了年:''' 2017年(C++17でストレージクラス指定子として廃止) ; 廃止または衰退の理由 : 最新のコンパイラは自動的に最適な変数の配置を決定できるため、キーワードとしての意味が失われました。 ; 代替技術 : コンパイラの最適化に任せることが推奨されます。 === std::allocator の古いメンバー関数 === * '''対象:''' construct()、destroy() など * '''サポート終了年:''' 2020年(C++20で削除) ; 廃止または衰退の理由 : より型安全で効率的なメモリ管理手法の導入により、古い手法が不要になりました。 ; 代替技術 : construct_at、destroy_at などの新しいメモリ管理関数が推奨されます。 === raw ポインタによるメモリ管理 === * '''サポート開始年:''' 言語の開始時から * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : メモリリーク、ダングリングポインタなどの問題を引き起こしやすく、安全性に欠けます。 ; 代替技術 : スマートポインタ(unique_ptr、shared_ptr)、STLコンテナの使用が推奨されます。 === std::iterator クラス === * '''サポート開始年:''' 1998年(C++98) * '''サポート終了年:''' 2017年(C++17でdeprecated) ; 廃止または衰退の理由 : イテレータの実装が複雑化し、基底クラスとしての有用性が低下したため。 ; 代替技術 : イテレータ要件を満たすカスタムクラスの直接実装が推奨されます。 === std::codecvt === * '''サポート開始年:''' 2011年(C++11) * '''サポート終了年:''' 2017年(C++17でdeprecated) ; 廃止または衰退の理由 : 設計上の問題や実装の複雑さにより、効果的な文字コード変換が困難でした。 ; 代替技術 : 外部ライブラリ(ICU、Boost.Locale)や、OS固有のAPI使用が推奨されます。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:C++]] 585zbmx7metsbkxai0n905834yxiwek C言語/改廃された技術 0 43382 263750 2024-11-18T09:11:44Z Ef3 694 /*改廃された技術*/ C言語の改廃された技術や利用が推奨されない技術は、言語標準の進化、新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 263750 wikitext text/x-wiki == 改廃された技術 == C言語の改廃された技術や利用が推奨されない技術は、言語標準の進化、新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 === K&R形式の関数定義 === * '''サポート開始年:''' 1972年 * '''サポート終了年:''' C99で非推奨(多くのコンパイラでは依然サポート) ; 廃止または衰退の理由 : 型安全性の欠如、コードの可読性の低下、現代的な開発ツールとの互換性の問題。 ; 代替技術 : ANSI C/ISO C形式の関数プロトタイプ宣言と定義が推奨されます。 === gets関数 === * '''サポート開始年:''' 1972年 * '''サポート終了年:''' 2011年(C11で削除) ; 廃止または衰退の理由 : バッファオーバーフローの脆弱性が存在し、深刻なセキュリティ問題を引き起こす可能性があります。 ; 代替技術 : fgets、gets_s(C11)の使用が推奨されます。 === BSD Signal Functions === * '''サポート開始年:''' BSD Unix * '''サポート終了年:''' なし(ただし非推奨) ; 利用推奨されない理由 : シグナルハンドリングの信頼性と移植性に問題があります。 ; 代替技術 : sigaction関数の使用が推奨されます。 === alloca関数 === * '''対象:''' スタック上の動的メモリ割り当て ; 利用推奨されない理由 : 移植性の問題、スタックオーバーフローのリスク、デバッグの困難さがあります。 ; 代替技術 : malloc/free、可変長配列(VLA)、または適切なサイズの固定配列の使用が推奨されます。 === tmpnam関数 === * '''サポート開始年:''' 1989年(ANSI C) * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : レースコンディションの脆弱性があり、セキュアな一時ファイル生成ができません。 ; 代替技術 : mkstemp、tmpfile関数の使用が推奨されます。 === atoi、atol、atof関数群 === * '''サポート開始年:''' 1989年(ANSI C) * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : エラー処理機能の欠如、入力の検証が不十分です。 ; 代替技術 : strtol、strtoul、strtod関数群の使用が推奨されます。 === 古い形式のコメント === * '''対象:''' /* */ スタイルのみのコメント * '''サポート終了年:''' なし(ただし//も推奨) ; 廃止または衰退の理由 : 複数行コメントのネストができず、コメントアウトが難しい場合があります。 ; 代替技術 : C99以降では//スタイルの単行コメントも使用可能です。 === register キーワード === * '''サポート開始年:''' 1972年 * '''サポート終了年:''' なし(ただし効果は実装依存) ; 廃止または衰退の理由 : 現代のコンパイラは自動的に最適なレジスタ割り当てを行えるため、キーワードの意味が薄れています。 ; 代替技術 : コンパイラの最適化に任せることが推奨されます。 === 固定サイズ整数型 === * '''対象:''' short、int、longなどの伝統的な整数型 * '''サポート終了年:''' なし(ただし用途による) ; 廃止または衰退の理由 : プラットフォーム依存のサイズ定義により、移植性と予測可能性に問題があります。 ; 代替技術 : stdint.hで定義されるint32_t、uint64_tなどの固定幅整数型が推奨されます。 === asctime、ctime関数 === * '''サポート開始年:''' 1989年(ANSI C) * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : バッファオーバーフローの可能性、Y2K問題、スレッド安全性の欠如があります。 ; 代替技術 : strftime関数、または時刻操作用の専用ライブラリの使用が推奨されます。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:C言語]] l4w4sllwfqkg0okkcicownaevn7nyh3 Fortran/改廃された技術 0 43383 263752 2024-11-18T09:17:28Z Ef3 694 /*改廃された技術*/ Fortranの改廃された技術や利用が推奨されない技術は、言語標準の進化、新しい要求、コード保守性の向上などによって置き換えられます。以下に、代表的な技術を示します。 263752 wikitext text/x-wiki == 改廃された技術 == Fortranの改廃された技術や利用が推奨されない技術は、言語標準の進化、新しい要求、コード保守性の向上などによって置き換えられます。以下に、代表的な技術を示します。 === COMMON文 === * '''サポート開始年:''' 1957年(FORTRAN I) * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : グローバル変数の使用によるコードの可読性低下、保守性の問題、並列処理での問題が発生します。 ; 代替技術 : MODULEとUSE文による変数共有が推奨されます。 === 固定形式ソース === * '''サポート開始年:''' 1957年(FORTRAN I) * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : 1-6列目が特殊な意味を持つ固定形式は、現代のプログラミング環境での可読性と保守性に問題があります。 ; 代替技術 : Fortran 90以降の自由形式ソースが推奨されます。 === GOTO文 === * '''サポート開始年:''' 1957年(FORTRAN I) * '''サポート終了年:''' なし(ただし非推奨) ; 利用推奨されない理由 : スパゲティコードを生みやすく、プログラムの流れが追いにくくなります。 ; 代替技術 : DO、IF-THEN-ELSE、SELECT CASE などの構造化プログラミング構文が推奨されます。 === Arithmetic IF === * '''対象:''' IF (expr) label1, label2, label3 * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : コードの可読性が低く、保守が困難です。 ; 代替技術 : IF-THEN-ELSE文、SELECT CASE文が推奨されます。 === EQUIVALENCE文 === * '''サポート開始年:''' FORTRAN II * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : メモリ配置の最適化を阻害し、可読性を低下させ、バグの原因となりやすい。 ; 代替技術 : 派生型(TYPE)、配列、ポインタの使用が推奨されます。 === PAUSE文 === * '''サポート開始年:''' 1957年(FORTRAN I) * '''サポート終了年:''' Fortran 95で削除 ; 廃止または衰退の理由 : インタラクティブな実行制御が不適切で、現代のプログラミング手法と整合性がありません。 ; 代替技術 : READ文、または言語処理系固有の対話的デバッグ機能の使用が推奨されます。 === Hollerith定数 === * '''サポート開始年:''' 1957年(FORTRAN I) * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : 文字列処理が複雑で、現代の文字エンコーディングとの互換性に問題があります。 ; 代替技術 : CHARACTER型と文字列リテラルの使用が推奨されます。 === ASSIGN文とAssigned GOTO === * '''サポート開始年:''' FORTRAN II * '''サポート終了年:''' Fortran 95で削除 ; 廃止または衰退の理由 : プログラムの流れが追いづらく、構造化プログラミングの原則に反します。 ; 代替技術 : サブルーチン、関数、SELECT CASE文の使用が推奨されます。 === DATA文(ブロック外) === * '''サポート開始年:''' FORTRAN IV * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : プログラムユニット外でのデータ初期化は保守性と可読性を低下させます。 ; 代替技術 : PARAMETER属性、型宣言時の初期化、MODULEでの変数定義が推奨されます。 === DO文(Statement Labels) === * '''サポート開始年:''' 1957年(FORTRAN I) * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : ラベルを使用したDOループは構造化プログラミングの原則に反し、エラーを起こしやすい。 ; 代替技術 : END DOを使用した構造化DOループ、DO WHILE、またはDO CONCURRENTが推奨されます。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Fortran]] dz1fim2tncicpseprlcwluibwjsek6r Go/改廃された技術 0 43384 263756 2024-11-18T09:30:02Z Ef3 694 /*改廃された技術*/ Goの改廃された技術や利用が推奨されない技術は、言語標準の進化、パフォーマンスの向上、セキュリティの考慮などによって置き換えられます。以下に、代表的な技術を示します。 263756 wikitext text/x-wiki == 改廃された技術 == Goの改廃された技術や利用が推奨されない技術は、言語標準の進化、パフォーマンスの向上、セキュリティの考慮などによって置き換えられます。以下に、代表的な技術を示します。 === context.TODO === * '''サポート開始年:''' 2014年 * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : コンテキストの適切な管理が難しく、デバッグや追跡が困難になります。 ; 代替技術 : context.Background()と明示的なコンテキスト管理が推奨されます。 === ioutil パッケージ === * '''サポート開始年:''' 2009年 * '''サポート終了年:''' Go 1.16で非推奨化 ; 利用推奨されない理由 : 機能が os パッケージと io パッケージに統合され、より一貫性のある API が提供されました。 ; 代替技術 : os パッケージと io パッケージの直接使用が推奨されます。 === golang.org/x/crypto/ssh/terminal === * '''対象:''' ターミナル操作 * '''サポート終了年:''' Go 1.16で移行推奨 ; 廃止または衰退の理由 : より適切なパッケージへの移行と、保守性の向上のため。 ; 代替技術 : golang.org/x/term パッケージの使用が推奨されます。 === http.CloseNotifier === * '''サポート開始年:''' 2011年 * '''サポート終了年:''' Go 1.7で非推奨化 ; 廃止または衰退の理由 : コンテキストベースの取り消し機能の導入により、より良い代替手段が利用可能になりました。 ; 代替技術 : context.Context による通知の管理が推奨されます。 === golang.org/x/net/context === * '''サポート開始年:''' 2014年 * '''サポート終了年:''' Go 1.7でstd contextパッケージ導入 ; 廃止または衰退の理由 : 標準ライブラリに context パッケージが追加されたため。 ; 代替技術 : context 標準パッケージの使用が推奨されます。 === go get による依存関係管理 === * '''サポート開始年:''' 2009年 * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : バージョン管理や依存関係の解決が不十分で、再現可能なビルドが困難でした。 ; 代替技術 : Go Modulesの使用が推奨されます。 === GOPATH ベースの開発 === * '''サポート開始年:''' 2009年 * '''サポート終了年:''' なし(ただし非推奨) ; 廃止または衰退の理由 : プロジェクト管理が複雑で、依存関係の管理が困難でした。 ; 代替技術 : Go Modulesによるプロジェクト管理が推奨されます。 === crypto/tls の古い暗号スイート === * '''対象:''' 古い SSL/TLS 実装 * '''サポート終了年:''' 継続的に非推奨化 ; 廃止または衰退の理由 : セキュリティ上の脆弱性や新しい暗号化標準への対応。 ; 代替技術 : 最新のTLS 1.3対応の暗号スイートの使用が推奨されます。 === syscall パッケージ(直接使用) === * '''サポート開始年:''' 2009年 * '''サポート終了年:''' なし(ただし直接使用は非推奨) ; 廃止または衰退の理由 : プラットフォーム依存性が高く、保守が困難です。 ; 代替技術 : golang.org/x/sys パッケージの使用が推奨されます。 === reflect.TypeOf().PkgPath() === * '''サポート開始年:''' 2009年 * '''サポート終了年:''' なし(ただし信頼性に問題) ; 廃止または衰退の理由 : モジュールパスとパッケージパスの不一致や、ビルド時の最適化による問題。 ; 代替技術 : より直接的なパッケージ識別方法や、型アサーションの使用が推奨されます。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Go]] bim90ms1kgkbzqm5655zt9v69353n8i Python/改廃された技術 0 43385 263758 2024-11-18T09:35:17Z Ef3 694 /*改廃された技術*/ Pythonの改廃された技術や利用が推奨されない技術は、言語標準の進化、セキュリティの向上、可読性の改善などによって置き換えられます。以下に、代表的な技術を示します。 263758 wikitext text/x-wiki == 改廃された技術 == Pythonの改廃された技術や利用が推奨されない技術は、言語標準の進化、セキュリティの向上、可読性の改善などによって置き換えられます。以下に、代表的な技術を示します。 === Python 2.x === * '''サポート開始年:''' 2000年 * '''サポート終了年:''' 2020年 ; 廃止または衰退の理由 : Unicode処理の問題、非同期処理の制限、その他多くの設計上の制約により、Python 3への移行が推奨されました。 ; 代替技術 : Python 3.x系の使用が推奨されます。 === print文 === * '''サポート開始年:''' Python 1.0 * '''サポート終了年:''' Python 3で文法変更 ; 利用推奨されない理由 : 特殊な文法が関数との一貫性を損ね、拡張性に制限がありました。 ; 代替技術 : print()関数の使用が推奨されます。 === xrange関数 === * '''対象:''' Python 2.xでの範囲生成 * '''サポート終了年:''' Python 3で統合 ; 廃止または衰退の理由 : range()とxrange()の区別が混乱を招き、メモリ効率の観点から単一の実装が望ましいとされました。 ; 代替技術 : Python 3のrange()関数(ジェネレータベース)が推奨されます。 === raw_input関数 === * '''サポート開始年:''' Python 1.0 * '''サポート終了年:''' Python 3で統合 ; 廃止または衰退の理由 : input()とraw_input()の区別が混乱を招き、セキュリティリスクがありました。 ; 代替技術 : Python 3のinput()関数が推奨されます。 === reduce()関数(標準組み込み) === * '''サポート開始年:''' Python 2.0 * '''サポート終了年:''' Python 3でfunctools moduleへ移動 ; 廃止または衰退の理由 : 可読性の低下と、より明示的な代替手段の存在。 ; 代替技術 : for ループ、list comprehension、または functools.reduce()の使用が推奨されます。 === cmp関数 === * '''サポート開始年:''' Python 1.0 * '''サポート終了年:''' Python 3で削除 ; 廃止または衰退の理由 : 比較ロジックの一貫性と可読性の向上のため。 ; 代替技術 : \_\_lt\_\_、\_\_gt\_\_などの特殊メソッド、または operator モジュールの使用が推奨されます。 === file型 === * '''サポート開始年:''' Python 1.0 * '''サポート終了年:''' Python 3で統合 ; 廃止または衰退の理由 : IOシステムの一貫性向上と、より柔軟なファイル処理の実現。 ; 代替技術 : open()関数とioモジュールの使用が推奨されます。 === execfile関数 === * '''サポート開始年:''' Python 1.0 * '''サポート終了年:''' Python 3で削除 ; 廃止または衰退の理由 : セキュリティリスクと、より明示的な代替手段の存在。 ; 代替技術 : exec(open(filename).read())の使用が推奨されます。 === apply()関数 === * '''サポート開始年:''' Python 1.0 * '''サポート終了年:''' Python 3で削除 ; 廃止または衰退の理由 : 引数展開構文(\*args, \*\*kwargs)の導入により不要になりました。 ; 代替技術 : 関数呼び出し時の\*と\*\*演算子の使用が推奨されます。 === unicode型 === * '''サポート開始年:''' Python 2.0 * '''サポート終了年:''' Python 3で統合 ; 廃止または衰退の理由 : 文字列処理の一貫性向上と、Unicodeの普遍的サポート。 ; 代替技術 : Python 3のstr型(Unicode文字列)の使用が推奨されます。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Python]] 0kqytkckd6ua0nhhjia6vfmxf2vixqy Haskell/改廃された技術 0 43386 263762 2024-11-18T09:40:01Z Ef3 694 /*改廃された技術*/ Haskellの改廃された技術や利用が推奨されない技術は、言語の進化、パフォーマンスの要求、より良い代替手段の出現などによって置き換えられてきました。以下に、代表的な技術を示します。 263762 wikitext text/x-wiki == 改廃された技術 == Haskellの改廃された技術や利用が推奨されない技術は、言語の進化、パフォーマンスの要求、より良い代替手段の出現などによって置き換えられてきました。以下に、代表的な技術を示します。 === String型 === * '''導入年:''' Haskell 1.0 (1990年) * '''非推奨化:''' 段階的 ; 利用推奨されない理由 : [String]型はリンクドリストとして実装されており、テキスト処理において性能面で問題があります。 ; 代替技術 : Data.Text(厳密なUnicodeテキスト処理用)やData.ByteString(バイナリデータ処理用)の使用が推奨されます。 === MonadError Error IO === * '''導入年:''' 1990年代 * '''非推奨化:''' 2010年代 ; 廃止または衰退の理由 : より型安全で表現力のある例外処理メカニズムの登場により、単純なMonadErrorの使用は減少しました。 ; 代替技術 : ExceptT、Either型、または特定のエラー型を持つカスタムモナドが推奨されます。 === Template Haskell(古い構文) === * '''導入年:''' 2002年 * '''更新:''' GHC 8.0 (2016年) ; 廃止または衰退の理由 : 新しい構文とAPIの導入により、古い形式のTemplate Haskell構文は非推奨となりました。 ; 代替技術 : 新しいQuasi-quotesやTemplate Haskell構文を使用します。 === FFI (古いスタイル) === * '''導入年:''' 2002年 * '''更新:''' 継続的 ; 廃止または衰退の理由 : ccallやstdcallなどの低レベルFFI呼び出しは、より安全で効率的な代替手段の登場により、直接的な使用が減少しています。 ; 代替技術 : inline-c、foreign-store、または新しいFFIバインディングジェネレータの使用が推奨されます。 === old-time パッケージ === * '''導入年:''' 初期のHaskell Platform * '''非推奨化:''' 2014年頃 ; 廃止または衰退の理由 : より機能的で効率的な時間処理ライブラリの登場により、old-timeパッケージは非推奨となりました。 ; 代替技術 : time パッケージの使用が推奨されます。 === MonadBase === * '''導入年:''' 2000年代初期 * '''非推奨化:''' 段階的 ; 廃止または衰退の理由 : より柔軟なモナド変換機能の登場により、単純なMonadBaseの使用は減少しました。 ; 代替技術 : MonadBaseControl、UnliftIO、または特定の用途に特化したモナド変換器の使用が推奨されます。 === Control.OldException === * '''導入年:''' GHC 6.x時代 * '''非推奨化:''' GHC 7.0以降 ; 廃止または衰退の理由 : 新しい例外システムの導入により、古い例外処理メカニズムは非推奨となりました。 ; 代替技術 : Control.Exception、safe-exceptionsパッケージ、またはカスタムエラー型の使用が推奨されます。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Haskell]] 2vjq27hihxxijmjd7tz16nl6fjoycoz PHP/改廃された技術 0 43387 263763 2024-11-18T09:45:38Z Ef3 694 /*改廃された技術*/ PHPの改廃された技術や利用が推奨されない技術は、セキュリティ要件の向上、言語の近代化、より良いプログラミング手法の確立などによって置き換えられてきました。以下に、代表的な技術を示します。 263763 wikitext text/x-wiki == 改廃された技術 == PHPの改廃された技術や利用が推奨されない技術は、セキュリティ要件の向上、言語の近代化、より良いプログラミング手法の確立などによって置き換えられてきました。以下に、代表的な技術を示します。 === mysql_* 関数群 === * '''サポート開始年:''' PHP 2.0 (1995年) * '''サポート終了年:''' PHP 7.0 (2015年) ; 廃止または衰退の理由 : セキュリティ上の問題(SQLインジェクションの危険性)や機能の制限により、完全に廃止されました。 ; 代替技術 : MySQLi拡張またはPDO(PHP Data Objects)の使用が推奨されます。 === register_globals === * '''サポート開始年:''' PHP 3 (1998年) * '''サポート終了年:''' PHP 5.4.0 (2012年) ; 廃止または衰退の理由 : 深刻なセキュリティ上の脆弱性を引き起こす可能性があるため、完全に削除されました。 ; 代替技術 : スーパーグローバル変数($_GET、$_POST、$_SESSION等)の使用が推奨されます。 === magic_quotes === * '''サポート開始年:''' PHP 3 * '''サポート終了年:''' PHP 5.4.0 (2012年) ; 廃止または衰退の理由 : セキュリティ機能として不十分で、予期せぬ動作を引き起こす可能性があったため廃止されました。 ; 代替技術 : htmlspecialchars()、PDOのプリペアドステートメント、またはフィルタ関数の使用が推奨されます。 === safe_mode === * '''サポート開始年:''' PHP 4 * '''サポート終了年:''' PHP 5.4.0 (2012年) ; 廃止または衰退の理由 : セキュリティモデルとして不完全で、多くの制限があったため廃止されました。 ; 代替技術 : オープンバジルやsuEXEC、またはPHPFPMの権限設定による適切なセキュリティ設定が推奨されます。 === ereg_* 関数群 === * '''サポート開始年:''' PHP 3 * '''サポート終了年:''' PHP 7.0 (2015年) ; 廃止または衰退の理由 : 古い正規表現エンジンを使用しており、パフォーマンスと機能の面で制限がありました。 ; 代替技術 : preg_*関数群(PCRE関数)の使用が推奨されます。 === mcrypt拡張 === * '''サポート開始年:''' PHP 4 * '''サポート終了年:''' PHP 7.2 (2017年) ; 廃止または衰退の理由 : 開発が停止したライブラリに依存しており、現代の暗号化要件を満たさなくなりました。 ; 代替技術 : OpenSSL拡張またはSodium拡張の使用が推奨されます。 === create_function() === * '''サポート開始年:''' PHP 4 * '''サポート終了年:''' PHP 7.2で非推奨、PHP 8.0で削除 ; 廃止または衰退の理由 : eval()に似た安全性の問題があり、パフォーマンスも悪かったため廃止されました。 ; 代替技術 : 無名関数(クロージャ)の使用が推奨されます。 === split() 関数 === * '''サポート開始年:''' PHP 3 * '''サポート終了年:''' PHP 7.0 (2015年) ; 廃止または衰退の理由 : ereg_*関数群の一部として、より効率的な代替手段の登場により廃止されました。 ; 代替技術 : explode()関数またはpreg_split()関数の使用が推奨されます。 === PHP短縮タグ === * '''サポート開始年:''' PHP 3 * '''サポート終了年:''' PHP 7.0で非推奨化が開始 ; 廃止または衰退の理由 : 設定依存の動作やXMLとの混同の可能性があるため、使用が推奨されなくなりました。 ; 代替技術 : 標準的なPHPタグ(<?php ?>)または<?= ?>の使用が推奨されます。 {{DEFAULTSORT:かいはい された きしつつ}} [[Category:PHP]] mkcnov5hqsrk8pkh76kt8qoba5ohefa JavaScript/改廃された技術 0 43388 263767 2024-11-18T10:03:37Z Ef3 694 /*改廃されたJavaScript技術 */ JavaScriptの改廃された技術や利用が推奨されない技術は、ウェブ技術の進化、新しい要件、セキュリティ上の懸念などにより置き換えられることがあります。以下に、代表的な技術を示します。 263767 wikitext text/x-wiki {{Nav}} == 改廃されたJavaScript技術 == JavaScriptの改廃された技術や利用が推奨されない技術は、ウェブ技術の進化、新しい要件、セキュリティ上の懸念などにより置き換えられることがあります。以下に、代表的な技術を示します。 === JavaScript <code>var</code> 宣言 === * '''サポート開始年:''' 1995年 * '''サポート終了年:''' 廃止はされていないが推奨されない *; 廃止または衰退の理由: *: <code>var</code> はスコープが関数単位であり、ブロックスコープを持たないため予期しないバグが発生しやすい。これに対して <code>let</code> や <code>const</code> はブロックスコープを持ち、より安全で直感的なコードが書けるため推奨される。 *; 代替技術: *: <code>let</code> や <code>const</code> を使用すること。 === JavaScript <code>document.write()</code> === * '''サポート開始年:''' 1996年 * '''サポート終了年:''' 廃止はされていないが推奨されない *; 廃止または衰退の理由: *: <code>document.write()</code> はページの読み込みをブロックし、パフォーマンスに悪影響を与える。また、モダンなウェブ開発手法において、動的なDOM操作のためのAPI(例: <code>appendChild</code> や <code>innerHTML</code>)が広く使われるようになった。 *; 代替技術: *: DOM操作API(例: <code>document.createElement()</code> と <code>appendChild()</code>)やテンプレートエンジン(例: Handlebars.js)を使用すること。 === JavaScript <code>alert()</code>, <code>confirm()</code>, <code>prompt()</code> === * '''サポート開始年:''' 1995年 * '''サポート終了年:''' 廃止はされていないが非推奨 *; 廃止または衰退の理由: *: ユーザー体験を阻害するため、モダンなウェブアプリケーションではほとんど使用されなくなった。また、UIのカスタマイズができないため、より柔軟な方法が求められる。 *; 代替技術: *: モーダルダイアログやカスタムUI(例: ReactやVue.jsのダイアログコンポーネント)。 === JavaScript <code>with</code> ステートメント === * '''サポート開始年:''' 1996年 * '''サポート終了年:''' 2011年(ECMAScript 5で非推奨化) *; 廃止または衰退の理由: *: スコープの曖昧さが原因で、予期しない挙動を引き起こしやすい。これにより、コードの可読性やデバッグ性が低下するため非推奨化された。 *; 代替技術: *: 明示的にオブジェクトを参照するコードを書くこと。例: <code>obj.property</code> を使用する。 === JavaScript <code>setTimeout</code> と <code>setInterval</code> によるタイマー === * '''サポート開始年:''' 1996年 * '''サポート終了年:''' 廃止はされていないが一部用途で非推奨 *; 廃止または衰退の理由: *: 正確な時間制御が難しく、負荷が高い場合にタイミングが遅れる可能性がある。特にアニメーションや時間感覚が重要なケースでは不適切。 *; 代替技術: *: モダンなアニメーションや時間制御には <code>requestAnimationFrame</code> や <code>setTimeout</code> のPromiseラッパーを使用することが推奨される。 === JavaScript非標準のイベントハンドラ <code>attachEvent</code> === * '''サポート開始年:''' 2000年(Internet Explorer専用) * '''サポート終了年:''' 2016年(Internet Explorer 11で終了) *; 廃止または衰退の理由: *: 標準化された <code>addEventListener</code> に置き換えられたため。<code>attachEvent</code> はIE独自の非標準APIであり、移植性が低かった。 *; 代替技術: *: 標準APIの <code>addEventListener</code> を使用すること。 === JavaScript <code>arguments.callee</code> === * '''サポート開始年:''' 1995年 * '''サポート終了年:''' 2015年(ECMAScript 5 Strict Modeで非推奨化) *; 廃止または衰退の理由: *: 再帰関数の名前を安全に変更できないなどの問題があった。モダンなJavaScriptでは名前付き関数式や関数の自己参照が可能になったため、非推奨となった。 *; 代替技術: *: 名前付き関数式やES6のアロー関数を使用すること。 === JavaScript古いモジュールローダー <code>require.js</code> === * '''サポート開始年:''' 2010年 * '''サポート終了年:''' 廃止はされていないが非推奨 *; 廃止または衰退の理由: *: ES6でモジュールシステム(<code>import/export</code>)が標準化されたため。<code>require.js</code> は依存管理が複雑で、ブラウザ環境以外では非効率的だった。 *; 代替技術: *: ES6モジュール(<code>import/export</code>)や、Node.jsでの<code>import</code>と<code>require</code>の併用。 === JavaScript jQuery === * '''サポート開始年:''' 2006年 * '''サポート終了年:''' 廃止はされていないが推奨されない *; 廃止または衰退の理由: *: モダンブラウザの標準APIが進化し、jQueryを使用する理由が減少した。また、ReactやVue.jsなどのフレームワークが普及し、jQueryのユースケースが狭まった。 *; 代替技術: *: ネイティブのDOM操作APIやモダンなフロントエンドフレームワーク。 {{Nav}} {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:JavaScript]] c766y1atbcvb6cmskgclfmbdsesjmjg Perl/改廃された技術 0 43389 263771 2024-11-18T10:10:11Z Ef3 694 /*改廃された技術*/ Perlの改廃された技術や利用が推奨されない技術は、言語の進化や新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 263771 wikitext text/x-wiki {{Nav}} == 改廃された技術 == Perlの改廃された技術や利用が推奨されない技術は、言語の進化や新しい要求、セキュリティ上の懸念などによって置き換えられます。以下に、代表的な技術を示します。 === Perl CGI === * '''サポート開始年:''' 1995年 * '''サポート終了年:''' 廃止はされていないが利用は減少 ; 廃止または衰退の理由 : セキュリティの脆弱性やパフォーマンスの低さ、そしてモダンなウェブフレームワーク(Ruby on RailsやDjango、Node.jsなど)の台頭により、利用が激減しました。 ; 代替技術 : MojoliciousやDancerなどのモダンなPerlフレームワーク、または他の言語のウェブフレームワーク。 === mod_perl === * '''サポート開始年:''' 1996年 * '''サポート終了年:''' 廃止はされていないが利用は減少 ; 廃止または衰退の理由 : 高度なApacheインテグレーションを提供しましたが、技術的な複雑さや他の軽量ウェブサーバ(nginxやNode.jsなど)の台頭により利用が減少しました。 ; 代替技術 : MojoliciousやPlackなどのPSGI対応のフレームワーク。 === Perl 5の古いバージョン === * '''対象:''' Perl 5.16以前のバージョン ; 利用推奨されない理由 : セキュリティパッチやバグ修正の提供が終了しているため、セキュリティリスクが高まります。 ; 推奨バージョン : 最新のPerl 5安定版を使用することが推奨されます(例: Perl 5.36など)。 === Perl 4 === * '''サポート開始年:''' 1991年 * '''サポート終了年:''' 2000年(事実上) ; 廃止または衰退の理由 : Perl 5のリリースにより、多くの新機能と改善が導入され、Perl 4は時代遅れとなりました。 ; 代替技術 : Perl 5以降のバージョンを使用してください。 === Perlモジュールの古い形式 (Makefile.PL) === * '''対象:''' ExtUtils::MakeMakerを使用した古いモジュールのビルド形式 ; 利用推奨されない理由 : モジュールの依存関係管理やインストールプロセスの改善が進み、よりモダンなツールが登場しました。 ; 代替技術 : Module::BuildやDist::Zillaなど、モダンなモジュール管理ツール。 === CGI::Application === * '''サポート開始年:''' 2001年 * '''サポート終了年:''' 廃止はされていないが利用は減少 ; 廃止または衰退の理由 : 古い構造のフレームワークであり、PSGIやPlackに基づく新しいエコシステムが普及しました。 ; 代替技術 : MojoliciousやCatalystなどのモダンなフレームワーク。 === Perl 6 (現在のRaku) === * '''サポート開始年:''' 2000年(開発開始)、2015年(正式リリース) * '''サポート終了年:''' Perl言語としては廃止(現在はRakuとして独立) ; 廃止または衰退の理由 : Perl 5との互換性がなく、Rakuという別の言語として独立しました。 ; 代替技術 : Perl 5を使用するか、Rakuを採用してください。 === 非推奨モジュール (deprecated modules) === * '''対象:''' 非推奨とマークされたCPANモジュールや標準モジュール ; 利用推奨されない理由 : 将来のPerlリリースで削除される可能性があるため、新規コードでの利用を避けるべきです。 ; 代替策 : CPANまたは公式ドキュメントを参照し、推奨されるモジュールを使用してください。 {{Nav}} {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Perl]] e4z9j8dijgbd741ehrslftquvaqvpu2 Lua/改廃された技術 0 43390 263779 2024-11-18T10:33:50Z Ef3 694 /*改廃された技術*/ Luaの改廃された技術や利用が推奨されない技術は、言語の進化や新しいニーズ、パフォーマンス向上の必要性に応じて置き換えられます。以下に、代表的な技術を示します。 263779 wikitext text/x-wiki == 改廃された技術 == Luaの改廃された技術や利用が推奨されない技術は、言語の進化や新しいニーズ、パフォーマンス向上の必要性に応じて置き換えられます。以下に、代表的な技術を示します。 === Lua 5.1のmodule関数 === * '''サポート開始年:''' 2006年(Lua 5.1) * '''サポート終了年:''' 2011年(Lua 5.2で非推奨化) ; 廃止または衰退の理由 : モジュール管理において隠れたグローバル参照の問題を引き起こす可能性があるため、非推奨化されました。 ; 代替技術 : 明示的なモジュール管理として<code>require</code>を使用し、ローカルスコープを活用する方法が推奨されます。 === Lua 5.1の環境テーブル (_ENV) === * '''対象:''' 環境テーブルとして使用されていた<code>setfenv</code>および<code>getfenv</code> ; 利用推奨されない理由 : <code>setfenv</code>や<code>getfenv</code>はコードの安全性を低下させ、デバッグが困難になることから、Lua 5.2以降では非推奨化されました。 ; 代替技術 : <code>_ENV</code>を使用して環境を管理することが推奨されます。 === Lua 5.1のロード関数 (loadstring) === * '''サポート開始年:''' 2006年(Lua 5.1) * '''サポート終了年:''' 2011年(Lua 5.2で非推奨化) ; 廃止または衰退の理由 : <code>loadstring</code>は<code>load</code>に完全に置き換えられ、両者の機能が統一されました。 ; 代替技術 : <code>load</code>関数を使用してください。 === 数値型としての整数と浮動小数点の分離 === * '''対象:''' Lua 5.2以前では数値型はすべて浮動小数点数として扱われていました。 ; 廃止または衰退の理由 : Lua 5.3で整数型が導入され、より効率的な数値演算が可能になりました。 ; 推奨技術 : Lua 5.3以降を使用し、必要に応じて整数型と浮動小数点型を使い分けてください。 === C APIの変更 === * '''対象:''' Lua 5.1以前のC APIの一部関数(例: <code>lua_objlen</code>) ; 利用推奨されない理由 : 一部の関数が非推奨となり、より明確で一貫性のある関数に置き換えられました。 ; 代替技術 : <code>lua_rawlen</code>などの新しいAPI関数を使用してください。 === Lua 5.1以前のコルーチンエラー処理 === * '''対象:''' コルーチン内でのエラー処理が非直感的だった点 ; 廃止または衰退の理由 : Lua 5.2以降で<code>xpcall</code>が改善され、コルーチン内でのエラー処理が簡潔になりました。 ; 代替技術 : Lua 5.2以降の<code>xpcall</code>を使用してください。 === Lua 5.2のgoto構文の導入 === * '''サポート開始年:''' 2011年(Lua 5.2) ; 利用推奨されない理由 : 一部ではコードの可読性を低下させるとして議論があり、乱用は推奨されません。 ; 推奨技術 : gotoを必要最小限で使用し、可能であれば明確な制御構造を利用してください。 === string.gfind (Lua 5.1) === * '''サポート開始年:''' 2006年(Lua 5.1) * '''サポート終了年:''' 2011年(Lua 5.2で非推奨化) ; 廃止または衰退の理由 : 一貫性と安全性の向上のため、<code>string.gfind</code>が<code>string.gmatch</code>に置き換えられました。 ; 代替技術 : <code>string.gmatch</code>を使用してください。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Lua]] gnv6eutqjk0ia13qp32gi81s1usi9rx Swift/改廃された技術 0 43391 263780 2024-11-18T10:45:10Z Ef3 694 /*改廃された技術*/ Swiftの改廃された技術や利用が推奨されない技術は、言語の進化や新しい要求、パフォーマンス向上の必要性に応じて置き換えられます。以下に、代表的な技術を示します。 263780 wikitext text/x-wiki == 改廃された技術 == Swiftの改廃された技術や利用が推奨されない技術は、言語の進化や新しい要求、パフォーマンス向上の必要性に応じて置き換えられます。以下に、代表的な技術を示します。 === <code>unowned</code>参照 === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2021年(Swift 5.5以降、非推奨化) ; 廃止または衰退の理由 : <code>unowned</code>参照は、予期せぬクラッシュを引き起こす可能性があるため、代わりに<code>weak</code>参照の使用が推奨されるようになりました。 ; 代替技術 : <code>weak</code>参照を使用し、強い参照サイクルを防ぎつつ、参照の解放タイミングを管理してください。 === <code>NSData</code>と<code>NSString</code> === * '''対象:''' <code>NSData</code>および<code>NSString</code>クラス ; 廃止または衰退の理由 : Swift 3以降、これらのクラスは<code>Data</code>および<code>String</code>に置き換えられました。 ; 代替技術 : <code>Data</code>および<code>String</code>を使用してください。これにより、Swiftの型安全性とパフォーマンスが向上します。 === <code>@objc</code>属性による互換性 === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2020年(Swift 5.3以降、制限的な利用が推奨) ; 廃止または衰退の理由 : Swiftの進化により、Objective-Cとの互換性が必ずしも必要でなくなり、<code>@objc</code>の使用はより限定的な場面に絞られました。 ; 代替技術 : Swiftの新しい機能(例: <code>protocol</code>)を利用し、Objective-Cとの相互運用を最小限に抑えてください。 === <code>++</code>および<code>--</code>演算子 === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2015年(Swift 2.0で削除) ; 廃止または衰退の理由 : 自増自減演算子(<code>++</code>および<code>--</code>)は、コードの可読性を低下させる可能性があり、より明示的な方法が推奨されるようになりました。 ; 代替技術 : 明示的な加算(<code>+=</code>)および減算(<code>-=</code>)を使用してください。 === Cスタイルのforループ === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2016年(Swift 3.0) ; 廃止または衰退の理由 : 冗長でエラーが発生しやすい構文であったため、削除されました。 ; 代替技術 : <code>for-in</code>ループを使用してください。 === <code>NSURLConnection</code> === * '''サポート開始年:''' 2009年(iOS 3.0) * '''サポート終了年:''' 2016年(iOS 9.0以降、非推奨化) ; 廃止または衰退の理由 : <code>NSURLConnection</code>は、非同期通信に関する新しいAPIである<code>URLSession</code>に置き換えられました。 ; 代替技術 : <code>URLSession</code>を使用して非同期通信を行うことが推奨されます。これにより、より効率的で柔軟なネットワーク操作が可能になります。 === <code>NSError</code>ベースのエラーハンドリング === * '''対象:''' <code>NSError</code>を使用したエラーハンドリング ; 廃止または衰退の理由 : Swift 2以降、エラーハンドリングは<code>try/catch</code>文を使用するように変更され、より簡潔で安全なエラーハンドリングが可能になりました。 ; 代替技術 : Swiftの<code>do-try-catch</code>構文を使用して、エラーハンドリングを行ってください。 === <code>var</code>による暗黙の可変性 === * '''対象:''' <code>var</code>キーワードによる暗黙的な可変性 ; 廃止または衰退の理由 : Swift 3以降、<code>let</code>と<code>var</code>の使い分けがより厳密にされ、明示的な可変性の制御が推奨されるようになりました。 ; 代替技術 : 不変オブジェクトを使用するために<code>let</code>を積極的に使用し、必要な場合にのみ<code>var</code>を使用してください。 === var キーワードによる関数スコープの変更 === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2016年(Swift 3.0) ; 廃止または衰退の理由 : 関数引数の<code>var</code>キーワードが予期せぬ副作用を引き起こす可能性があるため、非推奨化されました。 ; 代替技術 : 引数を変更可能にするには、ローカル変数を作成してください。 === <code>@IBOutlet</code>および<code>@IBAction</code>の強制的な接続 === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2020年(Swift 5.3以降、制限的な利用が推奨) ; 廃止または衰退の理由 : <code>@IBOutlet</code>および<code>@IBAction</code>の強制的な接続は、コードの可読性を損なう場合があり、よりクリーンな方法に置き換えられました。 ; 代替技術 : 宣言的なUI構築(例: SwiftUI)を使用し、UIコンポーネントとコードの結びつけを簡素化してください。 === <code>NSData</code>のファイル読み書き === * '''対象:''' <code>NSData</code>を使用したファイルの読み書き ; 廃止または衰退の理由 : Swift 3以降、<code>Data</code>に置き換えられ、より型安全で効率的なファイル操作が可能になりました。 ; 代替技術 : <code>Data</code>を使用して、ファイルの読み書きやバイナリデータの操作を行ってください。 === NSTimer (Timerの旧名称) === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2016年(Swift 3.0で名称変更) ; 廃止または衰退の理由 : Cocoa APIのモダン化の一環として、Swiftネイティブの命名規則に合わせるために名称が変更されました。 ; 代替技術 : <code>Timer</code>クラスを使用してください。 === AnyObject のプロトコル要件の変更 === * '''サポート開始年:''' 2014年(Swift 1.0) * '''サポート終了年:''' 2016年(Swift 3.0) ; 廃止または衰退の理由 : 型安全性を高め、誤用を防ぐために変更されました。 ; 代替技術 : 新しいSwiftプロトコルの設計を使用してください。 === Implicitly Unwrapped Optionals (IUO) === * '''対象:''' <code>!</code>を使用した暗黙的アンラップオプショナル ; 利用推奨されない理由 : 予期しないクラッシュを引き起こすリスクがあるため、新規コードでの使用が推奨されなくなりました。 ; 代替技術 : 必要に応じて明示的にアンラップするか、安全なオプショナルチェーンを使用してください。 === ストリングのインデックス型操作 === * '''対象:''' インデックスへの整数アクセス(例: <code>string[0]</code>) ; 利用推奨されない理由 : インデックス型がUnicodeスカラーを考慮したものに変更され、整数インデックスは非推奨化されました。 ; 代替技術 : <code>string.index(string.startIndex, offsetBy: n)</code>を使用してください。 === ArrayによるNS系クラスの置き換え === * '''対象:''' Objective-Cの<code>NSArray</code>などのコレクション型 ; 利用推奨されない理由 : Objective-CのNS系クラスはSwiftの型安全性を損なう可能性があるため、推奨されなくなりました。 ; 代替技術 : Swiftネイティブの<code>Array</code>、<code>Dictionary</code>、<code>Set</code>を使用してください。 === オブジェクトのWeak参照 === * '''対象:''' Objective-Cで使用された<code>unsafe_unretained</code> ; 利用推奨されない理由 : ARC(Automatic Reference Counting)を導入した後、メモリリークやクラッシュの原因となる<code>unsafe_unretained</code>の使用は非推奨化されました。 ; 代替技術 : <code>weak</code>または<code>unowned</code>キーワードを使用してください。 {{DEFAULTSORT:かいはい された きしゆつ}} [[Category:Swift]] 65xj3k4mziznbn0llwec8qvryoit1li