What is the reason for which a function's return type cannot be var? - c#-3.0

e.g.
public var SomeMethod()
{
return "hello";
}
error:
The contextual keyword var may only appear within a local variable declaration
Thanks

C# only supports type inference for local variables. It doesn't support it for the return type of a non-anonymous function. This is a design decision. It's possible that they change it in the future. Languages like F# do in fact support return type inference so there's no inherent impossibility involved here. Of course, sometimes, the inferred return type may be ambiguous and requires further clarification in the languages that support it:
// not real C#:
public var Method(bool returnInt) {
if (returnInt) return 42; else return true;
}
// what's the return type of Method is going to be? ValueType? object? ...?

I would recommend that you read Why no var on fields?:
In my recent request for things that make you go hmmm, a reader notes that you cannot use "var" on fields.
Now you don't want to use var for a field but you do want to use it for another purpose other than how it is specified. That article should give you a little insight into the compiler implementation around the var feature (and why, perhaps, var is not a valid return type).
Now, all that being said, it would be perfectly valid for the return type of a method to be inferred by the type of the return expression.

Consider a potentially ambiguous situation, a slight enhancement of your question:
public var SomeMethod() {
return DateTime.Now.Second % 2 == 0 ? "hello" : 3;
}
Should the compiler raise an error or infer type System.Object?
Only at runtime can the correct type be resolved between int and string.
var must be used on the left side of an initialization statement because its type is inferred by the C# compiler from the resulting data type on the right side.
var thing = 3;
// infers System.Int32 from right side.
var thing = 3L;
// infers System.Int64 from right side.
// This also applies to methods and things that have a defined type on the right side:
var thing = obj.AnyMethod();
If you could use var in place of the method return type, how could the C# compiler easily infer that type from all the logic inside the method?
var MyCall() { // ??? could be various things really
// lots of logic...
}
Available C# alternative
However, what you might be looking for in the C# language is to allow an interchangeable return type from your method via a Type Parameter and Generics like so:
T MyCall<T>() {
// lots of logic...
The caller can then specify the type that will be returned. Example:
An int.
var result = MyCall<int>();
// var will infer System.Int32
A string.
var result = MyCall<string>();
// var will infer System.String

Related

F# Async<_> to Async<obj>

I am working with F# to develop PowerShell tooling. I am currently running into a block because Async<_>is a generic type that is not derived from a non-generic type, so I can't request an Async<_> or Async as a parameter value - I have to specify the exact generic type parameter.
(For those unfamiliar with the interaction between these two languages, I can write a class in a .NET language such as F#, derive it from a class in the PowerShell library, and give it a specific attribute and when I run PowerShell and import my library, my class is exposed as a command. The command type can't be generic. Properties of the type are exposed as PowerShell parameters.)
As far as I'm aware I can't avoid this by having a generic member on a non-generic type, so ideally I'd have a transformation attribute (for non-PS users, transformation attributes effectively perform type conversion during runtime parameter binding) to turn Async<_> into Async<obj>. For the most part, this would work great for me. However, I can't figure out a way to check if a value is Async<_>, because the check computation :? Async<_> at compile time ends up as computation :? Async<obj>, which is not, unfortunately, the same, and returns false when passed Async<int>.
I ran into a similar issue in C# and was able to leverage the dynamic keyword after running a reflection test, and making the parameter be of the derived base type System.Threading.Tasks.Task, e.g.
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHeirarchy;
var isTaskOf = task.GetType()
.GetProperty("GetAwaiter", flags)
.PropertyType
.GetMethod("GetResult", flags)
.ReturnType != typeof(void);
if (isTaskOf) {
var result = await (dynamic)task;
}
I am willing to do something like this in F# if possible, but:
I have not ben able to successfully get the dynamic lookup operator ? to compile. Specifically, "none of the types 'Async<'a>, string' support the '?' operator". Not sure what I'm doing wrong as the explanations look straightforward and I can't find any other reports of this message or requirements for that operator.
I don't know if that would even work or if that operator is only used to dynamically access a member of an object.
The solutions I have tried are:
/// Transform from Async<_> to Async<obj>
override _.Transform(_, item : obj) : obj =
match item with
// only matches Async<obj>. I get a compiler warning that _ is constrained to obj
| :? Async<_> as computation ->
let boxedComputation : Async<obj> = async { return! computation }
boxedComputation
// if the value is not an async computation, let it pass through. This will allow other transformation or type converters to try to convert the value
| _ -> item
override _.Transform(_, item) =
// no compiler warning about the type being constrained to obj, but the if test does not pass unless item is Async<obj>
if (item :? Async<_>) then async { return! item :?> Async<_> }
else item
The other thing I can think of is to use reflection entirely - get the async type, call all of the AsyncBuilder methods reflectively to create a computation expression, and then cast it to Async. As I'm fairly new to F# I'm not sure how well I'd be able to piece together a computation expression like that, and either way it seems a lot more complicated than it ought to be. I'm hoping there is some better way to identify the return type of an async computation and/or just box the result without caring what type it actually is.
EDIT
After trying something ridiculously complicated using reflection with the AsyncBuilder type I realized I could leverage it a little more simply. Here is my current working solution, but I'm still looking out for any better options.
static let boxAsyncReturnValue v = async { return v :> obj }
static let bindFunctionReflected = typeof<FSharpAsyncObjTransformationAttribute>.GetMethod(
nameof boxAsyncReturnValue,
BindingFlags.NonPublic ||| BindingFlags.Static
)
override _.Transform(engineIntrinsics, item) =
// I need to identify the current return type of the computation, and quit if "item" is not Async<_>
if item = null then item else
let itemType = item.GetType()
if not itemType.IsGenericType then item else
let genericItemType = itemType.GetGenericTypeDefinition()
if genericItemType <> typedefof<Async<_>> then item else
let returnType = itemType.GetGenericArguments()[0]
if returnType = typeof<obj> then item else
bindFunctionReflected.MakeGenericMethod(itemType).Invoke(null, [|item|])
This is how I would do it:
let convert (a: Async<_>) =
async {
let! x = a
return box x
}
And at compile time it behaves as you'd expect:
let a = async { return "hello" }
let o: Async<obj> = convert a
let res = Async.RunSynchronously o
printfn "%s" res // Error: expected type 'string' but is type 'obj'
printfn "%s" (unbox<string> res) // compiles, prints the string

Can I make a Swift data type infix operator?

So, I want to make an operator ('or') which will allow me to declare a variable like this:
var someNum: Int or Double
This bring an example. I want to actually use it on some custom made data types. But is it possible to make an operator for variable declarations that will allow for said variable to be one of two types depending on what its being assigned? I know what data types are possible of being entered, but unfortunately I would currently either assign it a type of 'Any' with a bunch of failsafe code implemented or change the original data types created. So I was just wondering if this is possible or might even exist.
I used this article as a reference, but from what I read I'm not sure if I can or how I would implement it for my needs.
Custom Operators in Swift
Thanks for any and all the help in advance.
You can't do this in the way you're asking. It's not possible syntactically to use a operator in a declaration like that.
What you can do is use an enum to distinguish the kinds:
enum NumericInput {
case integral(Int)
case fractional(Double)
}
and take that as the type of your variable:
var value: NumericInput
Then you say
value = .integral(someInteger)
You could do this with generics:
struct MyStruct<T>
{
var someNum: T
}
You can then explicitly state the dataType you wish to use by specifying the type on creation: let a = MyStruct<Int>(someNum: 4).
One thing Swift does that makes this all absolutely beautiful is derive the data type from the constructor, so you can also just do this:
let intStruct = MyStruct(someNum: 4)
let floatStruct = MyStruct(someNum: 5.0)
You can just declare the value with type Any.
For example,
var myVar: Any = shouldAssignDouble ? Double(20) : Float(20)
Later when you want to know if the actual type is a Float or Double, you can check it with
myVar is Double //returns true

How do I store a value of type Class<ClassImplementingProtocol> in a Dictionary of type [String:Class<Protocol>] in Swift?

I want to store a more specialized type in a Dictionary of type [String:SomeClass]. Here is some sample code illustrating my problem (also available to play with at https://swiftlang.ng.bluemix.net/#/repl/579756cf9966ba6275fc794a):
class Thing<T> {}
protocol Flavor {}
class Vanilla: Flavor {}
var dict = [String:Thing<Flavor>]()
dict["foo"] = Thing<Vanilla>()
It produces the error ERROR at line 9, col 28: cannot assign value of type 'Thing<Vanilla>' to type 'Thing<Any>?'.
I've tried casting Thing<Vanilla>() as Thing<Flavor> but that produces the error cannot convert value of type 'Thing<Vanilla>' to type 'Thing<Flavor>' in coercion.
I've also tried to define the Dictionary as type [String:Thing<Any>] but that doesn't change anything either.
How do I create a collection of different Things without resorting to plain [String:AnyObject]?
I should also mention that the class Thing is not defined by me (in fact it's about BoltsSwift Tasks), so the solution to create a base class of Thing without a type parameter doesn't work.
A Thing<Vanilla> is not a Thing<Flavor>. Thing is not covariant. There is no way in Swift to express that Thing is covariant. There are good reasons for this. If what you were asking for were allowed without careful rules around it, I would be allowed to write the following code:
func addElement(array: inout [Any], object: Any) {
array.append(object)
}
var intArray: [Int] = [1]
addElement(array: &intArray, object: "Stuff")
Int is a subtype of Any, so if [Int] were a subtype of [Any], I could use this function to append strings to an int array. That breaks the type system. Don't do that.
Depending on your exact situation, there are two solutions. If it is a value type, then repackage it:
let thing = Thing<Vanilla>(value: Vanilla())
dict["foo"] = Thing(value: thing.value)
If it is a reference type, box it with a type eraser. For example:
// struct unless you have to make this a class to fit into the system,
// but then it may be a bit more complicated
struct AnyThing {
let _value: () -> Flavor
var value: Flavor { return _value() }
init<T: Flavor>(thing: Thing<T>) {
_value = { return thing.value }
}
}
var dict = [String:AnyThing]()
dict["foo"] = AnyThing(thing: Thing<Vanilla>(value: Vanilla()))
The specifics of the type eraser may be different depending on your underlying type.
BTW: The diagnostics around this have gotten pretty good. If you try to call my addElement above in Xcode 9, you get this:
Cannot pass immutable value as inout argument: implicit conversion from '[Int]' to '[Any]' requires a temporary
What this is telling you is that Swift is willing to pass [Int] where you ask for [Any] as a special-case for Arrays (though this special treatment isn't extended to other generic types). But it will only allow it by making a temporary (immutable) copy of the array. (This is another example where it can be hard to reason about Swift performance. In situations that look like "casting" in other languages, Swift might make a copy. Or it might not. It's hard to be certain.)
One way to solve this is adding an initialiser to Thing and creating a Thing<Flavor> that will hold a Vanilla object.
It will look something like:
class Thing<T> {
init(thing : T) {
}
}
protocol Flavor {}
class Vanilla: Flavor {}
var dict = [String:Thing<Flavor>]()
dict["foo"] = Thing<Flavor>(thing: Vanilla())

Getting a function's return type in Swift

I realize that reflection isn't fully supported (yet) in Swift, but reflection run time methods are (apparently) supported. I'm trying to get the return type of a function at run time. Here's my example
let s:Selector = "willAnimateRotation"
var m:Method = class_getInstanceMethod(object_getClass(self), s)
let returnType = method_copyReturnType(m)
println("method: \(m); returnType: \(returnType)")
free(returnType)
Here's an example of my willAnimateRotation method, currently returning String:
private func willAnimateRotation() -> String {
return "abc"
}
The output of this does not seem to vary depending on the return type of the selector. E.g., with String or Void return type for the selector, I get the following output:
method: 0x0000000000000000; returnType: 0x0000000000000000
Thoughts?
ALSO: I'm actually not really trying to do this in Swift. I'm bridging an Objective-C class to Swift, and am getting the same results there, when the Objective-C code attempts to determine the return type of a Swift selector. That is, my end-goal in this case happens to be to use Objective-C to get the return type of a Swift selector.
OK. I've figured this out. The problem comes with my use of the "private" keyword. If you drop that and just use:
func willAnimateRotation() -> String {
return "abc"
}
The sample code above works fine.
In Swift you indicate the function’s return type with the return arrow -> (a hyphen followed by a right angle bracket), which is followed by the name of the type to return.

closures and withUnsafeBufferPointer() in swift

I'm just trying to get my head around closures in swift.
I want to use the withUnsafeBufferPointer method of an array. In the simplest form, I can do something like this successfully:
var aa:[UInt8] = [1,2,3,4,5,6,7,8]
var bb = aa.withUnsafeBufferPointer({$0.baseAddress})
I can also do this:
var bb = aa.withUnsafeBufferPointer({pointerVal in pointerVal.baseAddress})
however, I cannot do this without generating an error in xcode:
var bb = aa.withUnsafeBufferPointer({pointerVal in return pointerVal.baseAddress})
"Cannot convert the expression's type '((ST5)->(ST5)->ST4)->((ST5)->ST4)->ST4' to type 'R'
In the first two assignments, the return statement is implied. If I put it in explicitly, things fail. I cannot reconcile this with the documentation from Apple. (see chapter on closures in The Swift Programming Language). I want to put a more complex closure into this, which requires a return statement. What do I have to do in order to accomplish that?
Unless the closure contains only a single expression, you need to the specify parameters and the return type:
var bb = aa.withUnsafeBufferPointer({pointerVal -> UnsafePointer<UInt8> in return pointerVal.baseAddress})
or annotate the variable so that the compiler can infer the type:
var bb : UnsafePointer<UInt8> = aa.withUnsafeBufferPointer({pointerVal in return pointerVal.baseAddress})
But you should use the pointer to the array buffer only inside the closure.
Storing the pointer in a variable like this is unsafe because the array might
be deallocated, the compiler does not know that is is referenced via bb.