I am a bit confused about the code below and why the last 2 attempts to define a handler (Delegate) wont work.
//this works
let serializer_setting = new JsonSerializerSettings(Error = fun (sender:obj) (args:Serialization.ErrorEventArgs) -> ())
//this doesnt
let err_handler1 (sender:obj) (args:Serialization.ErrorEventArgs) = ()
let serializer_setting1 = new JsonSerializerSettings(Error = err_handler1)
//neither this
let err_handler2 = fun (sender:obj) (args:Serialization.ErrorEventArgs) -> ()
let serializer_setting2 = new JsonSerializerSettings(Error = err_handler2)
Aren't they exactly the same?
Edit
I also tried this
type Delegate = delegate of obj * ErrorEventArgs -> Unit
let err_handler1 (sender:obj) (args:Serialization.ErrorEventArgs) = ()
let serializer_setting1 = new JsonSerializerSettings(Error = new Delegate(err_handler1))
But this gives me the following error
Error 1 This expression was expected to have type
System.EventHandler<Serialization.ErrorEventArgs>
but here has type
Delegate
Edit 2
Taking the clue from Fyodor below if I do this
let serializer_setting1 = new JsonSerializerSettings(Error = System.EventHandler<Serialization.ErrorEventArgs>(err_handler1))
It works and this also makes sense - However I still don't understand why my approach using a Delegate wont work.
The two latter examples are F# functions, which are actually not normal .NET delegates.
For purposes of interoperability with the rest of .NET, however, the F# compiler will convert an F# function to a compatible delegate type when it can see that this is the expected type.
In the first example, Error must be a delegate, so the F# compiler can infer that it must perform the conversion.
In the two latter examples, the types of the functions are inferred by the compiler without taking into account how they're used, because the F# compiler only interprets code in a single pass from top to bottom.
When the compiler reaches the expression where the function is attempted assigned to Error, the function already has the incorrect type.
See the documentation for more information about delegates in F#.
Related
Consider these lines:
I create a NSButton based class with this:
typealias onClickHandler = (NSTextfieldSuper)->Void
var onClick: onClickHandler?
When the user clicks on an instance of that button, I do this:
if (self.onClick != nil) {
onClick?(self)
}
I use that button later, from another class, with this:
let button = SuperButton()
button.onClick = { (textField: NSTextfieldSuper)->Void in
}
I am not sure if this is the correct syntax. I would like to process the button sent from the first closure on the parent class, where the button is created.
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
I just want to process that button sent.
By the way, as a bonus, I have to initialize several buttons with this, all running the same function. It would be nice to do something like
func doSomething () {
}
and then
let button = SuperButton()
button.onClick = doSomething
any ideas?
This was the only form I was able to type this without Xcode complaining. If this is correct, what is the purpose of this ->Void there? What could this possibly returning?
It is the same as in your typealias, in Swift a function type has the form:
(parameter definitions) -> return type
and functions which return nothing have a return type of Void (similar to C). The full form off a closure expression is:
{ (parameter definitions) ->return typeinbody}
Without any inference this expression provides the full type of the closure, and the -> Void Return type in your example specifies that your closure returns nothing. In your assignment this full type will be checked at compile time to conform to the type of onClick.
Now Swift will infer lots of stuff and there are various shorthands available for closure expressions, you will find that Swift accepts:
button.onClick = { textField in }
as well here with both the argument and return types of the closure being inferred.
By the way, as a bonus, [...] any ideas?
Just make the types match:
func doSomething(textField : NSTextfieldSuper) { }
button.onClick = doSomething
Unlike in (Objective-)C functions and closures (blocks in C) are interchangeable (as they are in plenty of other languages, C is the oddfellow here)
HTH
I'm trying to convert a lua bridge from Swift 2 to Swift 3. I am not the original author so there are aspects of the library I don't know very well and the original author seems not interested to continue working on the project. I have most of the conversion done but there remain one place I'm stuck and could not figure out. I've tried searching on SO and on the Internet but could not find anything that could help me solve the problem.
If anyone is interested in looking at the full source code, here is my fork of the project on github: https://github.com/weyhan/lua4swift (My changes is in the Swift3 branch)
Allow me setup the context to the error I'm stuck on. There is a Userdata class, specifically in the method userdataPointer<T>() -> UnsafeMutablePointer<T> the c function lua_touserdata returns the block address of userdata as a void * pointer type.
Original code written in Swift 2:
public class Userdata: StoredValue {
public func userdataPointer<T>() -> UnsafeMutablePointer<T> {
push(vm)
let ptr = lua_touserdata(vm.vm, -1)
vm.pop()
return UnsafeMutablePointer<T>(ptr)
}
public func toCustomType<T: CustomTypeInstance>() -> T {
return userdataPointer().memory
}
public func toAny() -> Any {
return userdataPointer().memory
}
override public func kind() -> Kind { return .Userdata }
}
After the conversion with Xcode 8 migration tool, Xcode is complaining about the return line with error Cannot invoke initializer for type 'UnsafeMutablePointer<T>' with an argument list of type '(UnsafeMutableRawPointer?)':
return UnsafeMutablePointer<T>(ptr)
I've fixed it with:
return (ptr?.assumingMemoryBound(to: T.self))!
Following that above change, now Xcode 8 is now complaining about the calling statement in createCustomType:
public func createCustomType<T: CustomTypeInstance>(setup: (CustomType<T>) -> Void) -> CustomType<T> {
lua_createtable(vm, 0, 0)
let lib = CustomType<T>(self)
pop()
setup(lib)
registry[T.luaTypeName()] = lib
lib.becomeMetatableFor(lib)
lib["__index"] = lib
lib["__name"] = T.luaTypeName()
let gc = lib.gc
lib["__gc"] = createFunction([CustomType<T>.arg]) { args in
let ud = args.userdata
// ******* Here's the line that is causing problem in Swift 3
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
// *******
let o: T = ud.toCustomType()
gc?(o)
return .Nothing
}
if let eq = lib.eq {
lib["__eq"] = createFunction([CustomType<T>.arg, CustomType<T>.arg]) { args in
let a: T = args.customType()
let b: T = args.customType()
return .Value(eq(a, b))
}
}
return lib
}
Where I'm getting stuck is the line :
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
I believe the original author is attempting to clear the memory block where the pointer returned by userdataPointer() call is pointing to.
With the Xcode 8 auto migration tool the above line is converted as below:
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
However Xcode now is then complains that Cannot convert call result type 'UnsafeMutablePointer<_>' to expected type 'UnsafeMutableRawPointer'.
From my research, the change to the return line in userdataPointer seems correct, so I think the issue is with the cast to UnsafeMutableRawPointer. I've tried dropping the cast to UnsafeMutableRawPointer and invoke ud.userdataPointer().deinitialize() directly but I get this error Generic parameter 'T' could not be inferred.
Other things I've tried is to convert the UnsafeMutablePointer to UnsafeMutableRawPointer but It always result in Xcode 8 complaining one thing or another. Any suggestion on how to get this to work?
As you may have already found out, Swift 3 attempts to provide better type safety when it comes to pointers. UnsafeMutablePointer can now only represent a pointer to an instance of a known type. In Swift 2, a C void * was represented by UnsafeMutablePointer<Void>, allowing void and non-void pointers to be treated in the same way, including trying to call a de-initializer of the pointed-to type, which is what the destroy() method in the problematic line of code does:
(ud.userdataPointer() as UnsafeMutablePointer<Void>).destroy()
In Swift 3 the de-initializer on the pointee is called using the deinitialize() method of the UnsafeMutablePointer structure. It appears that the migration assistant got confused. The line
(ud.userdataPointer() as UnsafeMutableRawPointer).deinitialize()
makes little sense because (1) UnsafeMutablePointer cannot be converted using as to UnsafeMutableRawPointer;
(2) UnsafeMutableRawPointer has not deinitialize() method. In Swift 3, UnsafeMutableRawPointer is a special type to represent void*. It is actually quite understandable why the migration tool made this mistake: it blindly replaced destroy() with deinitialize() and UnsafeMutablePointer<Void> with the corresponding Swift 3 type UnsafeMutableRawPointer, without realizing that the conversion would not work.
I don't quite understand why calling destroy() on a void pointer would work in Swift 2. Maybe this was a bug in the program or some compiler trick allowed the correct de-initializer to be called. Without knowing enough about the code, I can't be more specific than to suggest analyzing it to figure out what is the type pointed to by that pointer on which destroy() was called. For example, if we know for sure that it is always the placeholder type T used on the following line:
let o: T = ud.toCustomType()
then the offending line simply becomes
(ud.userdataPointer() as UnsafeMutablePointer<T>).deinitialize()
We need the conversion in the parentheses to allow the compiler to infer the generic parameter.
Thank you for bringing up an interesting problem. BTW, once you get over this obstacle, you are likely to run into other problems. One thing that jumps out is that UnsafeMutablePointer has no .memory in Swift 3; you'll have to use .pointee instead.
Here's an update. After playing with Swift 2.2 on Linux, I realize that calling destroy() on an UnsafeMutablePointer<A> cast as UnsafeMutablePointer<Void> won't call A's deinitializer, even if it has one. So, you have to be careful with that line...
Try creating an instance of UnsafeMutableRawPointer instead of trying to cast it:
UnsafeMutableRawPointer<T>(ud.userdataPointer()).destroy()
In the following, the way I define Animator is common in OOP systems, where it is considered fine to mutate this object's state:
type MyViewController() =
inherit UIViewController()
//Is there a better way than this?
member val Animator = null with get, set
override this.ViewDidLoad() =
base.ViewDidLoad()
//this.View is defined in base class and is only valid *now*
this.Animator <- new UIDynamicAnimator(this.View)
Is there a more idiomatic way to define Animator that communicates: "null->object is ok, object -> object is forbidden"?
(Obviously, I could write a custom set function that checks and throws at runtime, but that seems more annoyingly "clever" than helpful.)
Once the library depends so heavily on inheritance, it is really hard to avoid the usual OO patterns, even when you're using F#. So to be fair, I would probably write exactly the same code you did and just live with the fact that this part of the code is not going to be that pretty (and use more functional approach in the parts of the application where you're not forced into OO style by the framework).
Also, in this case, I'd just live with the null - you can use option, but you're not getting any benefits, because you cannot do much if the value is None anyway.
Presumably, in your full source code, you are overriding other methods of the class and you are creating Animator so that it can be used in the other methods. One thing you could do is to extract the code from the class and write something like this:
type IInitializedView =
abstract OtherMethod : UIViewController -> unit
type MyViewController(viewInitialized:UIView -> IInitializedView) =
inherit UIViewController()
let mutable initializedView = None
override this.ViewDidLoad() =
base.ViewDidLoad()
initializedView := Some(viewInitialized this.View)
override this.OtherMethod() =
viewInitialized |> Option.iter (fun vi ->
vi.OtherMethod() )
The idea here is that MyViewController calls your function when it has view and your function then creates a new interface that handles the other method - but your interface is created only after everything is properly initialized!
let vc = MyViewController(fun view ->
// Now we have valid 'view' so we construct animator!
let animator = UIDynamicAnimator(view)
{ new IInitializedView with
member x.OtherMethod() =
// no problem here, because we have animator...
animator.Whatever() })
But I don't know enough about Xamarin to say whether this would work OK in a full more complex system.
I think what #Carsten gets at is that you shouldn't introduce null values unless you are absolutely forced to by interop with other CLI languages. Types declared in F# wouldn't allow them anyway, unless decorated with an AllowNullLiteralAttribute.
The value wrapped in the Option<'a> type would be a somewhat direct translation, but still has mutability. I'm assuming that you do not really need the property setter, replacing the automatic property with a let-bound value.
type MyViewController() =
inherit UIViewController()
let mutable animator = Option<UIDynamicAnimator>.None
member x.Animator = animator.Value
override this.ViewDidLoad() =
base.ViewDidLoad()
animator <- Some <| new UIDynamicAnimator(this.View)
On the other hand, wrapping in Lazy<'a> is a little bit more in the functional spirit.
type MyViewController() as this =
inherit UIViewController()
let animator = lazy(new UIDynamicAnimator(this.View))
member x.Animator = animator.Value
override this.ViewDidLoad() =
base.ViewDidLoad()
// Optional; only if you need the object creation right now
animator.Force() |> ignore
The rust by example guide shows the following code here for a fibonacci series with iterators:
fn next(&mut self) -> Option<u32> {
let new_next = self.curr + self.next;
let new_curr = mem::replace(&mut self.next, new_next);
// 'Some' is always returned, this is an infinite value generator
Some(mem::replace(&mut self.curr, new_curr))
}
I would like to understand what is the advantage of this, over the most intuitive (if you come from other languages):
fn next(&mut self) -> Option<u32> {
let tmp = self.next;
self.next = self.curr + self.next;
self.curr = tmp;
Some(self.curr)
}
It's not always possible to write the direct code, due to Rust's ownership. If self.next is storing a non-Copy type (e.g. Vec<T> for any type T) then let tmp = self.next; is taking that value out of self by-value, that is, moving ownership, so the source should not be usable. But the source is behind a reference and references must always point to valid data, so the compiler cannot allow moving out of &mut: you get errors like cannot move out of dereference of `&mut`-pointer.
replace gets around these issues via unsafe code, by internally making the guarantee that any invalidation is entirely made valid by the time replace returns.
You can see this answer for more info about moves in general, and this question for a related issue about a swap function (replace is implemented using the standard library's swap internally).
I'm struggling to understand why I'm getting this compiler error in an iOS project using Swift. If I create the following class:
class InitTest {
let a: Int
let b: Int
let c: Int
init () {
self.a = 3
self.b = 4
self.c = self.runCalculation()
}
func runCalculation () -> Int {
return self.a * self.b
}
}
I get a compiler error on the line self.c = self.runCalculation() saying "Variable 'self.c' used before being initialized".
At first I thought this was because the compiler could not verify that the runCalculation() method did not access self.c, but then I tried mixing the init method up a bit:
init () {
self.a = 3
self.c = self.runCalculation()
self.b = 4
}
and this time the error is "Variable 'self.b' used before being initialized" (on the same self.runCalculation() line). This indicates that the compiler is capable of checking which properties the method accesses, and so as far as I can see should have no issue with the initial case.
Of course this is a trivial example and I could easily refactor to avoid calling the calculation method, but in a real project there could be several calculations each of which could be quite involved. I'd like to be able to separate out the logic to keep things readable.
Fortunately there's a simple workaround:
init () {
self.a = 3
self.b = 4
self.c = 0
self.c = self.runCalculation()
}
(or using a property initialiser let c = 0) but I'd like to understand why the compiler has a problem with the first example. Am I missing something or is it an unnecessary restriction?
Swift has this behaviour because of two phase initialisation. From Apple's Swift book:
Class initialization in Swift is a two-phase process. In the first
phase, each stored property is assigned an initial value by the class
that introduced it. Once the initial state for every stored property
has been determined, the second phase begins, and each class is given
the opportunity to customize its stored properties further before the
new instance is considered ready for use.
Classes need some kind of default value before the first phase ends. Customising values is part of the second phase.
Objective-C didn't have this behaviour because it could always give 0 as default for primitives and nil for objects, but in Swift there is no mechanism to give such a default value.