Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将swift变量包装为可选变量的缩写?_Swift_Variables_Syntax_Casting_Optional - Fatal编程技术网

将swift变量包装为可选变量的缩写?

将swift变量包装为可选变量的缩写?,swift,variables,syntax,casting,optional,Swift,Variables,Syntax,Casting,Optional,Swift允许我们使用速记符号str以展开可选的文件。但是如果我们想做相反的事情呢 假设我有一个变量: var str = String() // String 是否有任何简写符号可将其转换为可选(即字符串?或字符串!) (例如,我想做一些类似于var strOptional=?(str)) 或者,如果没有此符号的简写,我如何将其转换为可选,而不明确提及其类型(例如,我不想提及String) 换句话说,我知道我可以使用以下任何方法将变量包装为可选变量: var strOptional = st

Swift允许我们使用速记符号
str以展开可选的文件。但是如果我们想做相反的事情呢

假设我有一个变量:

var str = String() // String
是否有任何简写符号可将其转换为可选(即
字符串?
字符串!

(例如,我想做一些类似于
var strOptional=?(str)

或者,如果没有此符号的简写,我如何将其转换为可选,而不明确提及其类型(例如,我不想提及
String

换句话说,我知道我可以使用以下任何方法将变量包装为可选变量:

var strOptional = str as String?
var strOptional: String? = str
var strOptional = String?(str)
。。。但在每种情况下,我都必须显式地编写
String

如果没有速记语法,我宁愿写这样的东西:
var strOptional=str作为typeof?(str)
。(优点是,如果变量的类型在代码库中频繁更改,那么更新的地方就会少一个。)


关于这一点的实际示例,假设我想使用AVCaptureDevice,并使用以下代码:

let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
device.lockForConfiguration(nil)
lockForConfiguration()
将在没有摄像机的设备上运行时崩溃,并且编译器不会就此向我发出警告。原因是根据文档[1],带有MediaType的
DefaultDevice
可能返回
nil
,但它被定义为返回
AVCaptureDevice

要修复这样的错误API,最好执行以下操作:

let device = ?(AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo))
。。。获取
AVCaptureDevice?
,并让编译器捕获我可能犯的任何错误

目前,我必须求助于更详细的:

let device: AVCaptureDevice? = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

另一个例子:

prefix operator ??? {}

prefix func ??? <T> (x: T) -> T? {
    return Optional(x)
}
在本例中,我希望为变量指定一个默认值,即字符串,但稍后,我可能希望为其指定一个
nil

var myString = "Hi"
// ...
if (someCondition()) {
    myString = nil // Syntax error: myString is String
}
目前我不得不求助于
var myString:String?=“Hi”
但是像
var myString=?(“Hi”)
这样的东西就不会那么冗长了



[1] 如果打开AVCaptureDevice.h,您将看到有关返回值的以下文档:“具有给定媒体类型的默认设备,如果不存在具有该媒体类型的设备,则为nil。”

要包装变量,可以使用运算符重载和通用函数。例如:

prefix operator ??? {}

prefix func ??? <T> (x: T) -> T? {
    return Optional(x)
}

据我所知,这个问题是以轻松的精神提出的,您可以定义一个后缀运算符,它使用的字符比理想解少一个字符(一对paren和一个问号):

也许狡猾运算符的一个更有趣的用法是更高阶的运算符函数,它将
T->U
s提升到
T?->U?
s

func opt <T, U> (f: T -> U) -> T? -> U? { // we'll implement this as an operator
    return { $0.map(f) }
}

postfix operator ->? {}
postfix func ->? <T, U> (f: T -> U) -> T? -> U? {
    return { $0.map(f) }
}
这相当于:

opt(square)(i)
debugPrintln(op.map(square))
这相当于(但可能比):

与“管道前进”操作符一起使用时,所有这些都更有意义:

infix operator |> { associativity left precedence 89 }
func |> <A, B>(a: A, f: A -> B) -> B {
    return f(a)
}

或者我们可以将它们合并到一个可选的管道转发中,它也可以处理隐式展开的选项:

infix operator ?> { associativity left precedence 89 }
func ?> <T, U> (lhs: T?, rhs: T -> U) -> U? {
    return lhs.map(rhs)
}

let im: Int! = 5
let op: Int? = 5

im ?> square |> debugPrintln //--> Optional(25)
op ?> square |> debugPrintln //--> Optional(25)

可选只是swift中的一个枚举,因此您可以执行:
Optional(str)

从swift界面:

/// A type that can represent either a `Wrapped` value or `nil`, the absence
/// of a value.
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
    case None
    case Some(Wrapped)
    /// Construct a `nil` instance.
    public init()
    /// Construct a non-`nil` instance that stores `some`.
    public init(_ some: Wrapped)
    /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
    @warn_unused_result
    public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
    /// Returns `nil` if `self` is `nil`, `f(self!)` otherwise.
    @warn_unused_result
    public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
    /// Create an instance initialized with `nil`.
    public init(nilLiteral: ())
}
///一种类型,可以表示'Wrapped'值或'nil',即不存在
///有价值的。
公共枚举可选:_可反射,NilLiteralConvertible{
无案例
包装箱(已包装)
///构造一个'nil'实例。
公共init()
///构造一个存储“some”的非“nil”实例。
public init(usome:Wrapped)
///如果`self==nil`,则返回`nil`。否则,返回`f(self!)`。
@警告未使用的结果
公共func地图(@noescape f:(包装)投掷->U)再次投掷->U?
///如果'self'为'nil',则返回'nil',否则返回'f(self!)'。
@警告未使用的结果
公共func平面图(@noescape f:(包装)投掷->U?)再投掷->U?
///创建一个用“nil”初始化的实例。
公共init(nilLiteral:())
}

Hmm,我删除了我的答案。你有足够的代表性仍然可以看到它。我的大部分答案仍然适用,但我认为,
AVCaptureDevice
是个顽固分子。当苹果第一次推出Swift时,基本上所有东西都会隐式地返回未包装的可选项,但他们应该将所有这些转换为非可选项或常规可选项。这就是Objective-C nullability宏的作用。@nhgrif:谢谢您的评论。我添加了另一个例子,说明这可能是有用的,它不涉及苹果的框架。在第二个例子中,我认为明确使用您的类型很重要。苹果没有将预处理器宏引入Swift是有原因的……我同意@nhgrif的观点。AVFoundation只是还没有移植。后者很明显是
让myString=Optional(“Hi”)
(但这不适用于
类型)。如果有人提出一些简单的语法,我不会反对,但我肯定不会创建运算符或任何类似的重载。你可以很容易地将它封装在一个名为
lift
的函数中,该函数接受可选或非可选,并返回可选。我正在研究完全相同的答案。这并不能解决函数返回显式展开的可选项(您希望将其视为常规可选项)的问题。例如,如果
func test()->Int!{return 17}
被这样调用,
让a=??test()
,那么
a
将具有类型
Int
而不是
Int?
。“?”不是一个糟糕的运算符选择,因为这是nil合并运算符的符号吗?
infix operator |> { associativity left precedence 89 }
func |> <A, B>(a: A, f: A -> B) -> B {
    return f(a)
}
i |> opt(square)
i |> square->?
infix operator ?> { associativity left precedence 89 }
func ?> <T, U> (lhs: T?, rhs: T -> U) -> U? {
    return lhs.map(rhs)
}

let im: Int! = 5
let op: Int? = 5

im ?> square |> debugPrintln //--> Optional(25)
op ?> square |> debugPrintln //--> Optional(25)
debugPrintln(op.map(square))
/// A type that can represent either a `Wrapped` value or `nil`, the absence
/// of a value.
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
    case None
    case Some(Wrapped)
    /// Construct a `nil` instance.
    public init()
    /// Construct a non-`nil` instance that stores `some`.
    public init(_ some: Wrapped)
    /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
    @warn_unused_result
    public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
    /// Returns `nil` if `self` is `nil`, `f(self!)` otherwise.
    @warn_unused_result
    public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
    /// Create an instance initialized with `nil`.
    public init(nilLiteral: ())
}