Weird callback call syntax (need explanation) - callback

The following example is a minimal example that I found that explains the problem I am having:
use std::borrow::BorrowMut;
use std::ops::DerefMut;
#[derive(Debug, Clone)]
enum ConnectionState {
NotStarted,
}
type StateChangedCallback = Box<FnMut(ConnectionState) + Send + Sync>;
fn thread_func(mut on_state_changed: StateChangedCallback) {
let new_state = ConnectionState::NotStarted;
let f: &mut BorrowMut<StateChangedCallback> = &mut on_state_changed;
f.borrow_mut().deref_mut()(new_state);
}
fn main() {
let on_state_changed = Box::new(|new_state| {
println!("New state: {:?}", new_state);
});
let join_handle = std::thread::spawn(|| thread_func(on_state_changed));
join_handle.join().unwrap();
}
I have a simple thread that needs to call a callback passed from main. The callback is the signature Box<FnMut(ConnectionState) + Send + Sync>, since I want to call it multiple times. The only way I managed to call the callback was with this weird syntax:
let f: &mut BorrowMut<StateChangedCallback> = &mut on_state_changed;
f.borrow_mut().deref_mut()(new_state);
I searched and did not find a reasonable explanation for this. I am doing something wrong? Or is this the way Rust works?
If it is so, could someone explain the reason for this syntax?

You are overcomplicating things.
You might explain, why you think, that you have to do borrow_mut(), since there is no borrowing involved in your signature.
Your function thread_func can be simplified to this:
fn thread_func(mut on_state_changed: StateChangedCallback) {
let new_state = ConnectionState::NotStarted;
on_state_changed(new_state);
}
Please note, that in contrast to your sentence "I want to call it (the callback) multiple times" you can't, because you move your closure into the function.

Related

Why does my code work on Playgrounds but not CoderPad?

I have a very simple func in Xcode playgrounds which works when I run it. But when i try to run the same code in CoderPad it gives me the following error Solution.swift:18:1: warning: result of call to 'isPalindrome(word:)' is unused
isPalindrome(word:"racecar")
Here is the code
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
isPalindrome(word:"racecar")
I really do not understand why this is happening.
Try this:
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
print(isPalindrome(word:"racecar"))
all you had to do was print it, hope this helped
That means, that the "left-hand-side" result of the call to your function isPalindrome(word: "racecar") is unused ("wasted").
It seems that for a debugging, testing, try-out environment like a Playground it's just okay to find out the result of this call (true) without storing it inside a variable. However, when doing that in other development environments, the compiler will be complaining about that. I can give you four options that would prevent the error from being thrown, just to give you a better idea of why the compiler is complaining:
If you want to use it in your further code below, just store the result and change your calling line to let isPalindrome = isPalindrome(word: "racecar"). But if you don't use it, the compiler will give you a warning again saying that you're never using your isPalindrome variable... --> Option 2
If you don't need the result, you can also just say: _ = isPalindrome(word: "racecar"). That will explicitly tell the compiler "bro, it's okay if the result is just ignored". It wouldn't make much sense for this function, though.
You can add the #discardableResult keyword prior to your function declaration, so it would say: #discardableResult func isPalindrome(word: String) -> Bool { ... That would kinda just silence your thrown error and like option 2 just tell the compiler that it's okay to just ignore the result of this function.
Just use the result in any way like:
if isPalindrome(word: "racecar") {
// do something
} else {
// do something else
}
// or
print("racecar is a palindrome: \(isPalindrome(word: "racecar")")
and everything will just be fine. I hope that helps you!

'withUnsafeMutableBytes' is deprecated: use `withUnsafeMutableBytes<R>

I am very green with Xcode (apologize in advance). Trying to bring some old code to life. Getting the following with trying to move to Swift 5.
withUnsafeMutableBytes' is deprecated: use withUnsafeMutableBytes<R>(_: (UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R instead
Goal: All I need to do is modify the code appropriately and be done.
I have looked at other Stack Overflow messages, searched various articles, experimented with different things, but can't quickly determine what needs to change. I am sure the solution is super simple for someone that knows more.
var responseData = Data(count: Int(responseDataLength))
_ = responseData.withUnsafeMutableBytes
{
mfError = MFMediaIDResponse_GetAsString(mfMediaIdResponsePtr.pointee, MFString($0), responseDataLength)
}
Here is my example, when refreshing old code of withUnsafeMutableBytes
hope it helps
The old one:
_ = data.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) in
memcpy((ioData.pointee.mBuffers.mData?.assumingMemoryBound(to: UInt8.self))!, bytes, dataCount)
}
The new one:
_ = data.withUnsafeMutableBytes { (rawMutableBufferPointer) in
let bufferPointer = rawMutableBufferPointer.bindMemory(to: UInt8.self)
if let address = bufferPointer.baseAddress{
memcpy((ioData.pointee.mBuffers.mData?.assumingMemoryBound(to: UInt8.self))!, address, dataCount)
}
}
Explains:
use UnsafeMutablePointer<ContentType>, you get an unsafeMutablePointer in its closure.
To access to its memory, so need to typed it with bindMemory,
more details on Apple Pointer Doc

Why this is not counted as a closure capture?

Global functions are closures that have name and do not capture any values.
In swift a function is a spatial form of closure. The different is the function has a name and if it is an global function it cannot capture constants and variables from the surrounding context.
However, I found that the global function can also capture the constants and variables from the surrounding context also (please see the sample code below)
let referenceInt = 10
func addOne () -> Int {
return referenceInt + 1 //captured the constant referenceInt
}
let fooA = addOne
let fooB = addOne
let fooC = addOne
print(fooA()) //prints 11
print(fooB()) //prints 11
print(fooC()) //prints 11, (func addOne captured referenceInt ?)
print(referenceInt) //prints 10
Problems:
I believe I didn't fully understand the following concepts:
Simply define a function in playground (like addOne() -> Int here) may not means it is a global function
Having the wrong understanding of the "Capture" for this cases, this is not a capture at all, (but why?)
Helps I'm looking for:
I would be very appreciate you could point out which part I understand wrongly and would be even great that you can give me some explanation.
Thanks
PS:
This question might be a duplication of this one, however, I still post it since there is no clean answer on it yet and my question pushed the question a bit further. However, if you still want to close it, I respect that and I willing to learn from you.
First, I would question your premise. A closure is a closure. All functions in Swift are closures, and they all capture in just the same way.
Second, I don't see what your code has to do with capturing or closures. You are not doing anything in your code that tests whether anything is being captured. The assignment of the type let fooA = addOne doesn't do anything interesting, and the code inside addOne doesn't do anything interesting either. You are merely adding two values at the time the code runs. Certainly the code inside addOne is permitted to refer to the global variable referenceInt, but that is merely because it is in scope. You aren't doing anything here that elicits the special powers of a closure.
Here's a modification of your code that does show capturing in action:
struct Test {
var referenceInt = 10
func addOne () -> Int {
return referenceInt + 1 // capture
}
mutating func test() {
let fooA = self.addOne
let fooB = self.addOne
let fooC = self.addOne
referenceInt = 100 // :)
print(fooA()) //prints 11
print(fooB()) //prints 11
print(fooC()) //prints 11
print(referenceInt) //prints 100
}
}
var t = Test()
t.test()
We change referenceInt before calling fooA and so on. Calling fooA still gives 11, because the value of self.referenceInt was captured before we changed referenceInt.

Possible in swift to do a recursive function call with javascriptcore?

I have a function that is called by javascript with JavascriptCore.
Now inside that function I have to evaluate a javascript again under a certain condition. This should call the same function.
let My_JS_Function: #convention(block) ( String, String, String ) -> ( ) = {
thing_1, thing_2, thing_3
in
let my_Condition = true
if my_Condition {
let c = JSContext()
// compiling error: "Variable used within its own initial value"
Context.setObject(unsafeBitCast(My_JS_Function, AnyObject.self), forKeyedSubscript: "My_JS_Function")
c.evaluateScript("My_JS_Function("value 1","value 2","value 3");")
}
}
Now XCode tells me:
Variable used within its own initial value
Does anybody know wheather there's a way how to solve this problem?
Maybe a way to write the My_JS_Function as a function and not like here as a variable?
I could fix the problem with avoiding having functions as properties.
Therefor I put the functionality in an extra class and used JSExport.
One example for how it can be done with JSExport can be found here.

Cannot borrow captured outer variable in an `Fn` closure as mutable

This is my first day with Rust, but I'm trying to do something trivial, and I'm stuck.
What I'm trying to do is to add an struct to a Vector, and return the result. What I'm trying is to create a very simple REST service which will store the data in memory when posting, and return all the data in JSON format when doing a GET.
This is my current code:
fn main() {
let mut server = Nickel::new();
let mut reservations = Vec::new();
server.post("/reservations/", middleware! { |request, response|
let reservation = request.json_as::<Reservation>().unwrap();
reservations.push(reservation); // <-- error occurs here
format!("Hello {} {}", reservation.name, reservation.email)
});
server.listen("127.0.0.1:3000");
}
I tried this solution with a RefCell, but then I get the error that the trait Sync is not implemented for Vec<reservation::Reservation>
This is a very good example of how Rust protects you from thread unsafety.
If you think about it, in your current code it would be possible that multiple threads try to concurrently mutate reservations without any kind of synchronization. This is a data race and Rust will complain about it.
A possible solution would be to wrap the reservations vector into a Mutex to get synchronization. You will also need an Arc (atomic reference counting), since Rust cannot prove that reservations will live longer than the threads.
With these changes, your code should be like the following:
use std::sync::{Arc, Mutex};
fn main() {
let mut server = Nickel::new();
let reservations = Arc::new(Mutex::new(Vec::new()));
server.post("/reservations/", middleware! { |request, response|
let reservation = request.json_as::<Reservation>().unwrap();
reservations.lock().unwrap().push(reservation); // <-- error occurs here
format!("Hello {} {}", reservation.name, reservation.email)
});
server.listen("127.0.0.1:3000");
}
You can check the documentation for additional info about Mutex and Arc.