2017-10-30 5 views
2

Nil-Coalescing演算子はSwiftについての私の好きなものの1つです。 Swiftによく慣れて以来、私はいくつかの特殊なケースに遭遇しました。 1つは変数にOptionalの値を代入したい場合です。それ以外の場合は何もしません。私は現在、これを行うための二つの方法を参照してください。この文脈で値を変更しないNil-Coalescing演算子

var a : String? 
var b : String? 

// Possibly assign a non-nil value to a and/or b 

/* First Way */ 
a = b ?? a 

/* Second Way */ 
if let b = b { 
    a = b 
} 

を第一の方法は、おそらく罰金であるように、それはそうですが、変数はmapViewController.destinationCardTitleのようなはるかに長い名前を取得する場合、最初の方法は、かなり長い得ることができます。 の値をnilに、または空の場合はStringに割り当てることはできません。すでにnil以外の値が含まれていて、b = nilが含まれている場合は、aの値を変更しないためです。

aを2度書くことなく、基本的に次のようにする方法があるのだろうかと思います。

a = b ?? a 
+0

いただきまし間違っ二度書いて?あなた自身の演算子を書くことができます –

+1

変数名の長さはコードのパフォーマンスに全く影響しません;-) – vadian

+0

そうですが、私のコードの長さを減らすのがいいでしょう。さもなければ、私は、ハァハで始めるためにNil-Coalescingオペレーターを使用することはありません。 – ZGski

答えて

3

独自の中置演算子を設計することができます。この1上の大きなハンマーを使用します。

var a: String? 
var b: String? 

func attempt_To_Set_A_New_Value_To_A(using b: Any?) -> String { 
    if b != nil { 
     guard b is String else { 
      // OH no! It's not a string!!! 
      return "" 
     } 
     // Just to make sure.. 
     if let bString = b as? String { 
      return bString 
     } 
    } 
    // WARNING - b is definitely nil! 
    return "" 
} 

a = attempt_To_Set_A_New_Value_To_A(using b: b).isEmpty() ? a : attempt_To_Set_A_New_Value_To_A(using b: b) 

あなたはあまり楽しみたい、またはあなたは、単に悪い日を過ごしている場合は、私はおそらくそのように記述します:

if b != nil { a = b } 
+0

この(似たような)回答に対する私のコメントはhttps://stackoverflow.com/a/34710530/1187415にも適用されます。 –

+1

私はこの回答を見る前に私の答え(しかし一般的ではない)に類似したものを追加しました。これは私が示したものよりもきれいです。 – rmaddy

+1

@ MartinR 'a?= nil'はここで私のために働いた。私も計算されたプロパティでそれをテストします –

2

あなたの懸念は、長い変数名であるので、のは、長い変数名を使用しての可能性を見てみましょう:

ゼロ-合体:

aLongVariableName = bCrazyLongVariableName ?? aLongVariableName 

場合-てみましょう:

if let x = bCrazyLongVariableName { 
    aLongVariableName = x 
} 

if-nil:

if bCrazyLongVariableName != nil { 
    aLongVariableName = bCrazyLongVariableName 
} 

これらの3つの可能なオプションのうち、if letは、それぞれの長い変数名が一度しか表示されないため、最短のコードです。しかし、あなたはif let x =と中括弧のオーバーヘッドを持っています。したがって、その余分な構文に対抗するのに十分な長さの変数名を持つ必要があります。

個人的には、読みやすさは長さよりも重要です。コピー&ペーストははるかに少ないタイピングを意味します。このため、??を使用する方がはるかに良い解決策です。その意図ははっきりしています。

??を使用して、2番目のaを回避する方法について尋ねました。できません。あなたが探している実際のショートカットを提供する他の構文はありません。

inoutパラメータにはa、通常パラメータにはbを使用する関数を記述できます。

infix operator ?= 
func ?=<T>(lhs: inout T, rhs: T?) { 
    lhs = rhs ?? lhs 
} 

var a = "a" 
var b: String? = "b" 

a ?= b 

print(a) // "b\n" 
+0

本物の解答を提供する際に*可読性とコード長を考慮してくれてありがとう。 – ZGski

+0

1つの解決策が含まれている更新プログラムを参照してください。 – rmaddy

+0

「inout」はおそらく私の最善の策だと思います。私はちょうどこれを行うためのカスタム演算子を作るかもしれません。 – ZGski

-3

それは確かに興味深いです - あなたはスウィフトのうち、最大限に活用する絶好の機会を持っている場合、これは次のとおりです。

func x(_ a: inout String?, _ b: String?) { 
    if b != nil { 
     a = b 
    } 
} 

var a = String? 
var b = String? 

x(&a, b) 
+2

オプションのキャストbの前に 'b is String'をチェックする点は何ですか?文字列 '? –

+1

これはほとんど意味がありません。この関数は、コールサイトで何度も冗長になり、不必要に本体に巻き込まれ、その名前が言うことさえしません。 –

+0

それは間違いなく冗談です! ;) – nomadoda