Last active
July 8, 2024 01:59
-
-
Save lagenorhynque/0e96d7f853a97ddf4d5e4cb8b45f587f to your computer and use it in GitHub Desktop.
read-only vs immutable lists in Kotlin, Scala and Clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
user=> (def xs [1 2 3]) | |
#'user/xs | |
;; Clojureの `[ ]` リテラルで得られるvector (シーケンシャルコレクションの一種)実装は独自のイミュータブルコレクション | |
user=> (class xs) | |
clojure.lang.PersistentVector | |
;; java.util.Listを実装している | |
user=> (instance? java.util.List xs) | |
true | |
;; 破壊的更新操作は実装されていないため実行時エラーになる | |
user=> (java.util.Collections/sort xs >) | |
Execution error (UnsupportedOperationException) at java.util.List/sort (List.java:514). | |
null | |
;; 例えば元のデータからJavaのArrayListを作れば破壊的更新ができるが、元のデータに影響することはない | |
user=> (def xs' (java.util.ArrayList. xs)) | |
#'user/xs' | |
user=> xs' | |
[1 2 3] | |
user=> (java.util.Collections/sort xs' >) | |
nil | |
user=> xs' | |
[3 2 1] | |
user=> xs | |
[1 2 3] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
>>> val xs: List<Int> = listOf(1, 2, 3) | |
// Kotlinの `listOf( )` で得られるList実装はjava.util.Arrays.asListで得られるものと同じ(ミュータブルな固定長リスト) | |
>>> xs::class | |
res1: kotlin.reflect.KClass<out kotlin.collections.List<kotlin.Int>> = class java.util.Arrays$ArrayList | |
// 実行時のオブジェクトはjava.util.Listを実装している(ただし、Kotlinとしてのインターフェースkotlin.collections.Listはjava.util.Listを実装していない) | |
// cf. Kotlinのmapped types: https://kotlinlang.org/docs/java-interop.html#mapped-types | |
>>> xs is java.util.List<*> | |
res2: kotlin.Boolean = true | |
// 破壊的なソート処理によって元のデータが更新できてしまう(イミュータブルコレクションではないことが分かる) | |
>>> java.util.Collections.sort(xs, { a, b -> b.compareTo(a) }) | |
>>> xs | |
res4: kotlin.collections.List<kotlin.Int> = [3, 2, 1] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
scala> val xs: List[Int] = List(1, 2, 3) | |
val xs: List[Int] = List(1, 2, 3) | |
// Scalaの `List( )` で得られるList実装は独自のイミュータブルコレクション | |
scala> xs.getClass | |
val res0: Class[? <: List[Int]] = class scala.collection.immutable.$colon$colon | |
// java.util.Listを実装していない | |
scala> xs.isInstanceOf[java.util.List[?]] | |
val res1: Boolean = false | |
// JavaのListインターフェースを実装していないためコンパイルエラーになる | |
scala> java.util.Collections.sort(xs, Ordering[Int].reverse) | |
-- [E007] Type Mismatch Error: ------------------------------------------------- | |
1 |java.util.Collections.sort(xs, Ordering[Int].reverse) | |
| ^^ | |
| Found: (xs : List[Int]) | |
| Required: java.util.List²[Int] | |
| | |
| where: List is a class in package scala.collection.immutable | |
| List² is a trait in package java.util | |
| | |
| longer explanation available when compiling with `-explain` | |
1 error found | |
// JavaのList実装に変換しても破壊的更新操作は実装されていないため実行時エラーになる | |
scala> import scala.jdk.CollectionConverters.* | |
scala> val xs_ = xs.asJava | |
val xs_: java.util.List[Int] = [1, 2, 3] | |
scala> java.util.Collections.sort(xs_, Ordering[Int].reverse) | |
java.lang.UnsupportedOperationException | |
at java.base/java.util.AbstractList.set(AbstractList.java:136) | |
at java.base/java.util.AbstractList$ListItr.set(AbstractList.java:439) | |
at java.base/java.util.List.sort(List.java:514) | |
at java.base/java.util.Collections.sort(Collections.java:179) | |
... 41 elided | |
// 例えば元のデータからJavaのArrayListを作れば破壊的更新ができるが、元のデータに影響することはない | |
scala> val xs2 = java.util.ArrayList(xs.asJava) | |
val xs2: java.util.ArrayList[Int] = [1, 2, 3] | |
scala> java.util.Collections.sort(xs2, Ordering[Int].reverse) | |
scala> xs2 | |
val res3: java.util.ArrayList[Int] = [3, 2, 1] | |
scala> xs | |
val res4: List[Int] = List(1, 2, 3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# REPL起動に利用するコマンドのバージョン確認 | |
$ kotlinc -version | |
info: kotlinc-jvm 2.0.0 (JRE 22.0.1) | |
$ scala -version | |
Scala code runner version 3.4.2 -- Copyright 2002-2024, LAMP/EPFL | |
$ clj -version | |
Clojure CLI version 1.11.3.1463 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment