2025-12-15
この記事は
プログラミング言語の特有構文 Advent Calendar 2025
https://adventar.org/calendars/12640個人的な好みを交えて紹介します。
OCaml は勉強中なので、入門的な内容です。
二分探索のサンプルコード
言語の特徴をあえて使い実装している。
(* OCaml - パターンマッチ + パイプ演算子 + オプション型 *)
let binary_search arr target =
let rec go left right =
if left > right then None
else
let mid = (left + right) / 2 in
match compare arr.(mid) target with
| 0 -> Some mid
| n when n < 0 -> go (mid + 1) right
| _ -> go left (mid - 1)
in
go 0 (Array.length arr - 1)
let () =
[|1; 3; 5; 7; 9|]
|> fun arr -> binary_search arr 5
|> Option.value ~default:(-1)
|> print_int (* 2 *)だいぶ Haskell に似ているレイアウトでかける。
ピックアップ構文
ファンクタ
モジュールを引数に取り、新しいモジュールを生成する高階モジュール。
(* モジュールを引数に取るモジュール *)
module type OrderedType = sig
type t
val compare : t -> t -> int
end
module MakeSet (Ord : OrderedType) = struct
type elt = Ord.t
type t = elt list
let empty = []
let add x s = x :: s
end
module IntSet = MakeSet(Int)ジェネリクスのモジュール版のような機能。
ラベル付き引数とオプション引数
引数に名前を付けたり、デフォルト値を持つオプション引数を定義できる。
(* ラベル付き引数 ~name *)
let greet ~name ~greeting = greeting ^ ", " ^ name ^ "!"
let _ = greet ~name:"Alice" ~greeting:"Hello"
(* オプション引数 ?name *)
let greet ?(greeting="Hello") name = greeting ^ ", " ^ name ^ "!"
let _ = greet "Alice" (* "Hello, Alice!" *)
let _ = greet ~greeting:"Hi" "Bob" (* "Hi, Bob!" *)コメント構文 (* ... *)
ネスト可能なブロックコメント。
(* 単一行コメント *)
(* 複数行
コメント *)
(* ネストも可能
(* 内側のコメント *)
外側に戻る *)
(* コードをコメントアウトするとき便利
let x = (* 一時的に無効化 *) 1
*)見たことない記号の組み合わせを使っている。 ネスト可能なのが特殊だ。
パイプ演算子 |>
左の値を右の関数の第一引数として渡せる。
(* 左から右へデータを流す *)
[1; 2; 3; 4; 5]
|> List.filter (fun x -> x mod 2 = 0)
|> List.map (fun x -> x * 2)
|> List.fold_left (+) 0 (* 12 *)
(* 関数適用の逆順 *)
x |> f |> g (* = g (f x) *)F# や Elixir にも広まった。
let 式と let-in
ローカルバインディングや再帰関数を定義できる。
(* ローカルバインディング *)
let x = 1 in
let y = 2 in
x + y
(* 再帰関数 *)
let rec factorial n =
if n <= 1 then 1 else n * factorial (n - 1)
(* 相互再帰 *)
let rec even n = n = 0 || odd (n - 1)
and odd n = n <> 0 && even (n - 1)相互再帰の短絡評価は馴染みがないと不思議に見える。
パターンマッチング
match 式や function 構文で値の構造に基づいた分岐ができる。
(* match式 *)
let describe = function
| 0 -> "zero"
| 1 -> "one"
| n when n < 0 -> "negative"
| _ -> "other"
(* リストパターン *)
let rec sum = function
| [] -> 0
| x :: xs -> x + sum xs
(* タプルパターン *)
let fst (x, _) = xオプション型
値が存在しない可能性を Some と None で表現できる。
(* Some または None *)
let safe_div a b =
if b = 0 then None else Some (a / b)
(* パターンマッチで処理 *)
match safe_div 10 2 with
| Some x -> print_int x
| None -> print_string "error"
(* Option モジュール *)
Option.map (fun x -> x * 2) (Some 5) (* Some 10 *)
Option.value ~default:0 (Some 5) (* 5 *)
Option.bind (Some 5) (fun x -> Some (x * 2))Share