Swiftの代入演算子、算術演算子、複合代入演算子

代入、算術、複合代入演算子

ここでは、演算子で最も基本的な代入演算子と算術演算子について、その簡単な使い方を説明していきます。また、最後に代入と算術を組み合わせた複合代入演算子についても簡単に紹介します。複合代入演算子は慣れるまでちょっと難しいかもしれません。また、「演算が値を返すかどうか?」という戻り値の有無に関して、少し詳しく説明しています。蛇足ですが英語では演算子のことをoperator(オペレーター or オペレータ)と呼びます。

代入演算子(assignment operator)

代入演算子の基本的使い方

代入演算子は、定数・変数の初期化や代入の際に使用する演算子です。

let constant = 1 // 定数を初期化
var a = 2 // 変数を初期化
var b = 3
a = b // aにbを代入

代入演算子は右から左に作用する演算子です。例えばa=2は、「2aに代入する(a2を代入する)」と読めます。したがって、以下のような記述はエラーになります。

2 = a
//コンパイルエラー。a = 2と記述しないといけない

代入演算子は戻り値がない

演算等が返す値のことを戻り値(return value)と呼びます。実は、Swiftの代入演算子は値を返しません

正確に言うとこれは正しくないのですが、補足で少し説明します。

この後の算術演算子などと比較してもらうと良く分かると思いますが、例えば

b = a = 4
//コンパイルエラー

という記述はコンパイルエラーになります。演算の順番としては、(1)a4を代入するa=4、(2)その後、baを代入するb=aと読めそうです。ところが、a=4に戻り値がないので、bに値を代入することができません。

一見不便ですが、代入演算子に戻り値がないという仕様は、比較演算子(==)との混同を防いでくれます。例えば、

if a = b {
  print("aとbは同じです")
}
// エラー、"a == b"と書かないといけない

のように、本来使用するべき==との誤用を未然に防いでくれます。これは結構うれしい仕様です。


補足:代入演算子の戻り値について

「代入演算子は戻り値がない(値を返さない)」と書きましたが、実は空のtuple()を返しています。「戻り値がないという型」を表現するのに、良くVoidを使いますが、Swiftでは、Voidは空のtupleにtypealiasされています。

ですから、例えば以下のような記述は、意味があるかどうかは別にして、問題なく実行できます。

var a = 2
var b = 3
var c: Void = b = a
// または
var c: () = b = a

算術演算子(arithmetic operator)

四則演算(binary)の基本的な使い方

基本的な算術演算子は、+, -, *, /です。値同士や、定数・変数間の四則演算が可能です。

// 値
2 + 3
3.14 - 3.0
3.0 * 2.5
4 / 2
// 変数(定数でも大丈夫です)
var c = 2.0
var d = 3.0
c + d
c - d
c * d
c / d
// 値と変数
c + 3.0
// 演算後、代入
var result = c + d // resultは5.14

代入演算子のところで少し触れましたが、算術演算子は戻り値を返します。したがって、最後の行のように、演算の結果を変数や定数に代入(初期化)することが可能です。

異なる型の四則演算、四則演算の戻り値

ただし、異なる型を持った定数・変数間の演算は正しく型変換しないとコンパイルエラーになります(Swiftの型安全)。これは四則演算に限らず、後で説明する剰余演算子でも同様です。

var b = 3 // bはInt
var c = 2.0 // cはDouble
b + c // コンパイルエラー
// Intに型変換
b + Int(c)

算術演算子の戻り値は、演算に使用した値や変数の型になります。DoubleIntの演算ですと、Doubleが優先されますが、Intに型変換することも可能です。

// DoubleとIntの積
var e = 2 * 3.14 // 結果:6.28、eはDouble
var f = Int(2*3.14) // 結果:6, eはInt

また、+演算子はStringの連結(concatenation)に使えます(この英語は難しいですね)。

// 文字列の連結
"hello" + " world!"
let hello = "hello"
let world = "world!"
hello + " " + world

インクリメントとデクリメントはSwift 3から廃止

インクリメントとデクリメント演算子はSwift 3から廃止されたので使えません。

var a = 2
a++
//コンパイルエラー
//error: '++' is unavailable: it has been removed in Swift 3

インクリメントとデクリメントはSwift 2.2から非推奨

上記の通り、インクリメントとデクリメントはSwift 3への移行で完全に削除されました。Swift 2.2の段階では削除はされていませんが、使用すると以下のようにwarningが出ます。

var a = 1
a++
// warning: '++' is deprecated: it will be removed in Swift 3

ですから、これまでインクリメントもしくはデクリメントを使っていた部分は、Swift 3への移行を見越して、複合代入演算子等で置き換えるのが良いかもしれません。

剰余演算(remainder)

剰余演算子%(remainder)はa/bで計算した結果の余りを返す演算子です。実際にやってみましょう

11 % 3 // 結果は2
12 % 3 // 結果は0

余りがない場合は0を返します。剰余演算子の計算アルゴリズムの図解は公式マニュアルが分かりやすいです

また、剰余計算は負の値-aに関しても可能で、

-11 % 3 // 結果は-2

のように、計算結果も負になります。
ただし、2項目bの符号は結果に影響を与えません。

11 % -3 // 結果は2
-11 % -3 // 結果は-2

Swift 3から浮動小数点型の剰余演算子は廃止

Swift 3から浮動小数点数に対しては、剰余演算子が適用出来なくなっています。

var g = 1.3
var h = 0.2
g % h
//コンパイルエラー
//error: '%' is unavailable: Use truncatingRemainder instead

コンパイルエラーを見ると分かりますが、代わりにインスタンスメソッドtruncatingRemainder(dividingBy:)を使えと言っています。

試しに実行してみると、

g.truncatingRemainder(dividingBy: h) // 0.1
// 浮動小数点数リテラルの場合
3.14.truncatingRemainder(dividingBy: 3.0) // 0.14

という感じになります。

インスタンスメソッド(instance methods)とは浮動小数点型が持つ関数のようなものです、つまり物凄く大雑把に言うとメソッドとは、型というローカルスコープに限定された関数のようなものです。メソッドに関しては、メソッドのページで詳しく説明しています。

単項符号演算子

勝手に造語しましたが、unary minus operatorとunary plus operatorをまとめたモノです。Unaryというのは「単項の」という形容詞ですので、unary minus operatorは

単項(1つの変数または値)に作用する負符号-の演算子

です。

具体的な使用例が分かりやすいと思いますが、例えば

var e = 2*3.14 // 先程使った変数
var thisIsMinus = -e // unary minus operatorで符号を反転
var thisIsPlus = -thisIsMinus // -(-e)=eなので、符号は+に

という感じで、変数(または定数)の直前に、スペースなしで符号を付けます。最初に定義した変数eは正の実数ですが、ここに負の符号を付けると当然負の実数になります(thisIsMinus)。そこに負の符号を当てると、元のeに戻ります。Unary minus operatorは、符号を反転させたい場合に使用する演算子になります。

一方で、unary plus operatorは実用性という点では皆無です。公式マニュアルでは、unary minus operatorを使う場合に、ソースコードの対称性を保つため(要は綺麗に見せるため)に使っても良い、という記述がありますが、本当にそれくらいしか用途が思いつかないです。

複合代入演算子(compound assignment operator)

複合代入演算子は代入演算子と算術演算子を組み合わせた演算子です。

var a = 3
a += 1 // a = a + 1
a -= 2 // a = a - 2
a *= 3 // a = a * 3
a /= 4 // a = a / 4

複合代入演算子はコメントに書いてあるような計算のショートカットになっています。

公式マニュアルにも書いてあるように、複合代入演算子は戻り値がありません。代入演算子と同じ扱いのようで、Voidを返します。

// Warningは出るがコンパイルは通る
var b = a += 1
print(b)
// "()"と表示

// これなら通るが、結果は上記のケースと同様
var b: () = a += 1
print(b)
// "()"と表示

したがって、上記例のように、無理やり複合代入演算子の戻り値を別の変数等に押し込むことが出来ますが、結果はVoidです。

まとめ

  • 代入演算は右から左に作用
  • 代入演算+Stringの連結にも使える
  • 代入演算子(複合代入演算子も)は返り値がない(or 返り値はVoid
  • 四則演算は型を合わせる
  • インクリメント(デクリメント)はSwift 3で完全に削除。Swift 2.2から非推奨。
  • 剰余演算子%はSwift 3から浮動小数点型(DoubleFloatなど)では適用出来ないので注意が必要