LoginSignup
6
2

More than 1 year has passed since last update.

【Clojure入門備忘録】apply関数

Last updated at Posted at 2019-07-29

Clojure入門中です。Scalaをやっていたので、Scalaのapplyとは明らかに異なるapply関数に戸惑いました。
そこでメンターが色々と教えてくれたので、咀嚼するために(+世の中に還元できたらいいなという気持ちで)軽くまとめました。

Clojureにおけるapplyとは

可変長引数と対になるようなもので、最終引数のシーケンスの中身を取り出して適用してくれる。

まあ概要はこんな感じ。以下で説明していく。

そもそも可変長引数ってどんなのだっけ

可変長引数(variable argument)とは、関数に与えた0個以上の実引数を1つのシーケンス(≒リストのようなもの)にまとめてくれるもの。

& <名前> で可変長引数にできる

まあこんな感じ
dev> (defn hello [& who]
  (println who))
#'dev/hello
dev> (hello "hoge")
(hoge)
nil
dev> (hello "hoge" "hoge")
(hoge hoge)
nil

標準ライブラリの+, -, *, / も可変長引数関数

まあこんな感じ
dev> (+)
0
dev> (+ 0)
0
dev> (+ 1 2)
3
dev> (+ 1 (- 1 2 3) (* 1 2 3))
3

で、可変長引数だと何ができないのか

ベクター [1 2 3] があって可変長引数関数 + を適用しようとしたとき、単純に適用することはできない。

まあこんな感じ
dev> (let [xs [1 2 3]]
       (+ xs))
Execution error (ClassCastException) at java.lang.Class/cast (Class.java:3606).
Cannot cast clojure.lang.PersistentVector to java.lang.Number

+ は引数として0個以上の数値(java.lang.Number)型の値を期待している。
とはいえ、ベクターの個々の要素を手でバラバラにして適用するのは汎用性に欠ける :innocent:

そこで apply の出番。

じゃあapplyをどうやって使う?

シンプルに apply をつければいい。

まあこんな感じ
dev> (apply + 1 2 3 [4 5])
15
dev> (apply + [1 2 3 4 5])
15

上記はいずれも(+ 1 2 3 4 5) と等価である。
Clojureでは標準ライブラリ関数にも可変長引数関数がとても多いらしく、コレクション(シーケンス)に可変長引数関数を適用したい状況で apply をよく使うとのこと。

最後に

勉強したことを整理するために備忘録的に書きました。
何か間違っていることや補足したい点があったら優しくマサカリを投げてください。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2