I have some problems with the scope of the # keyword in an anonymous function
(this is not what's happening but I need it for my example)
createArray = (fun) -> fun()
this is the example class
class Example
stuff: []
otherStuff: createArray ->
#stuff
the # points to window (I presume). So I looked into this and remembered the fat arrow to create a generator function.
I tried this
class Example
stuff: []
otherStuff: createArray =>
#stuff
but it didn't even compile to a function(_this) { ...}(this). So I started trying to wrap in generators everything
class Example
stuff: []
otherStuff: =>
createArray ->
#stuff
...
otherStuff: =>
stuff = #stuff
createArray ->
stuff
...
otherStuff: ((stuff) ->
createArray ->
stuff
)(#stuff) #this is the one that upsets me the most because it compiles to Example.stuff and not to Example.prototype.stuff
but none of these are working.
Before switching to a simple function instead of class, is there a way to achieve what I want?
otherStuff: createArray ->
#stuff
This is run at class definition time, not when you execute otherStuff(). At that time there is no this (#), because no object has yet been instantiated. Essentially this is doing:
Example.prototype.otherStuff = (function () { return this.stuff; })();
// which boils down to:
Example.prototype.otherStuff = this.stuff;
Obviously, this has nothing to do with an instance of Example at this point.
If you want # to refer to the current instance of Example, you need to defer your function execution until you have an instance and call otherStuff:
otherStuff: ->
createArray ->
#stuff
Here now the inner function will lose its context, and you need to fat-arrow bind it:
otherStuff: ->
createArray =>
#stuff
Related
I need a macro that will call functions with different numbers of arguments or a macro that will generate a valid argument list from its (repeating) parameters.
I am fine with explicitly giving the information about the number of arguments to the macro, but I can't figure out how to generate the argument list for the function - I always stumble on the macros returning expressions rather than token tree.
I made the following playground example:
macro_rules! call (
($f: expr, $($params:tt)*) => {
$f(make_params!($($params:tt)*))
};
);
macro_rules! make_params {
() => {};
(I $($params: tt)*) => {
1, make_params!($($params:tt)*)
};
}
fn foo(a: i32, b: i32, c: i32) {
println!("foo: {} {} {}", a, b, c);
}
fn bar(a: i32, b: i32) {
println!("bar: {} {}", a, b);
}
fn main() {
call!(foo, I I I);
call!(bar, I I);
}
The compiler complains with the following:
error: macro expansion ignores token `,` and any following
--> src/main.rs:10:10
|
10 | 1, make_params!($($params:tt)*)
| ^
|
note: caused by the macro expansion here; the usage of `make_params!` is likely invalid in expression context
--> src/main.rs:3:12
|
3 | $f(make_params!($($params:tt)*))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
How can I treat the return of make_params! as a token stream (or such) rather than expression?
My real use case is a bit more involved than this toy example. My functions have multiple parameter types which are constructed in different ways. In my case, just making macros call1, call2!, ... does not seem like a good solution, as I would need the likes of call_IIOOI, call_IIIO, etc.
You need to build the function call progressively as you go and only emit it at once in the end:
macro_rules! call (
($f: expr, $($params:tt)*) => {
make_call!($f, () $($params)*)
};
);
macro_rules! make_call {
($f: expr, ($($args:tt)*)) => { $f($($args)*) };
($f: expr, () I $($params:tt)*) => {
make_call!($f, (1) $($params)*)
};
($f: expr, ($($args:tt)*) I $($params:tt)*) => {
make_call!($f, ($($args)*, 1) $($params)*)
};
}
playground
I'm trying to implement a JavaScript-style callback. I have an application that uses a library (both are mine) and I need the application to be able to pass a closure or function to a method in the library, which then spawns a thread and inside the thread when a condition is met it will call the callback.
main.rs
fn main(){
welcome_message();
mylib::connect(|| println!("Connected to service! Please enter a command. (hint: help)\n\n"));
loop {
match prompt_input() {
true => {},
false => break,
}
}
}
lib.rs
pub fn connect<F>(resolve: F) -> (mpsc::Sender<Message>, mpsc::Receiver<Message>)
where F: Fn()
{
...
let receive_loop = Thread::scoped(move || {
for response in receiver.incoming_messages::<Message>(){
let json_string = match response.unwrap() {
Message::Text(txt) => txt,
_ => "".to_string(),
};
let message = json::Json::from_str(json_string.as_slice());
let message_json = message.unwrap();
if message_json.is_object() {
let ref something = receiver_tx;
let obj = message_json.as_object().unwrap();
let something_json = obj.get("lsri").unwrap();
let something = something_json.to_string().replace("\"", "");
match something.as_slice() {
"service#connected" => resolve(),
_ => println!("{}", type),
}
} else {
println!("Invalid service response");
}
}
});
...
}
Error
src/lib.rs:54:24: 54:38 error: the trait `core::marker::Send` is not implemented for the type `F` [E0277]
src/lib.rs:54 let receive_loop = Thread::scoped(move || {
^~~~~~~~~~~~~~
src/lib.rs:54:24: 54:38 note: `F` cannot be sent between threads safely
src/lib.rs:54 let receive_loop = Thread::scoped(move || {
^~~~~~~~~~~~~~
It doesn't need to be a closure that I pass, I could pass a function too. It doesn't need any arguments or return types, but I could add some dummy ones if that helps. I am VERY open to suggestions of other methods or ways to accomplish the same goal.
I have tried using:
Thread::spawn
FnMut()
Arc::new(resolve) (with implementation of .clone())
Arc::new(Mutex::new(resolve)) (with implementation of .lock())
Searching Google for examples
Reading the Rust book in it's entirety
Searching the error message for examples
All of the above in various configurations
Is this possible with Rust? Is there a better way?
Thank you for your time in advance.
Solution:
For anyone finding this in the future, per the instructions of the answer below I changed the signature of connect to the following, which allowed the callback to be passed into the thread.
pub fn connect<'a, T, F>(resolve: F) -> (mpsc::Sender<Message>, mpsc::Receiver<Message>)
where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
Try marking your F with the same restrictions as Thread::scoped:
fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T>
where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
specifically, bounding the type with the Send trait should clear the immediate error of
the trait core::marker::Send is not implemented for the type F
How can I call a callback function in xtend?
I am looking for something similar to the one in C.
Example:
struct callbacks
{
char name[10];
boolean (*pfState)();
};
static const struct callbacks call[] = {
{"YOURS", &isOwner},
{"OURS", &our_owner}
};
So, I will just call it like this: call[0].pfState().
I have created a similar ArrayList in xtend.
val you = new youModule()
val our = new ourModule()
val callbacks = newArrayList('YOURS' -> you.isOwner, 'OURS' -> our.isOwnder);
Am I doing this correctly? How can I execute the function call in the pair?
Currently you create a list of Pairs which map strings to the result of the method invocation, e.g. assuming #isOwner returns a boolean, your list callbacks is currently a List<Pair<String, Boolean>>.
Instead, you have to wrap the invocation of #isOwner in a lambda expression:
val callbacks = newArrayList(
'YOURS' -> [| you.isOwner ],
'OURS' -> [| our.isOwnder ]
);
Now, callbacks has the type List<Pair<String, ()=>boolean>>, or in other words: List<Pair<String, Functions.Function0<Boolean>>>.
If you have a "callback" stored in a variable, you need to invoke the function by calling apply on it.
Here is a simple example showing a hash map that contains two callbacks stored under 'YOURS' and 'OURS' key. When called, each callback function prints a different message and returns a boolean value.
val callbacks = newHashMap(
'YOURS' -> [| println("calling the first callback"); true ],
'OURS' -> [| println("calling the second callback"); false ]
)
val result = callbacks.get("YOURS").apply
// result is: true
// console output is: calling the first callback
In Coffeescript, can I call the constructor for an object after it has already been created? Like this:
class Snake
constructor: (#name) ->
obj = new Snake()
// do stuff
obj.constructor("Python")
Yes, you can. CoffeeScript class syntax is just syntax sugar for JavaScript constructor functions, which are just normal functions that you can call:
class Example
count: 0
constructor: (#name) ->
#count += 1
e = new Example 'foo'
console.log e.count # -> 1
console.log e.name # -> foo
# Call contructor again over the same instance:
Example.call e, 'bar'
console.log e.count # -> 2
console.log e.name # -> bar
# If you don't have the constructor in a variable:
e.constructor.call e, 'baz'
console.log e.count # -> 3
console.log e.name # -> baz
This code is compiled to:
var Snake, obj;
Snake = (function() {
function Snake(name) {
this.name = name;
}
return Snake;
})();
obj = new Snake();
So there is no constructor() method, coffeescript is just using it to generate the Snake() function.
So no you can't. But why would you want to do that if your code is object oriented?
I have not understood the following code snippet why afterDelay(0) {...}, a locally defined function can be stored into agenda? Can someone help me understand the afterDelay(0) {...} in the run function?
abstract class Simulation {
type Action = () => Unit
case class WorkItem(time: Int, action: Action)
private var curtime = 0
def currentTime: Int = curtime
private var agenda: List[WorkItem] = List()
private def insert(ag: List[WorkItem], item: WorkItem): List[WorkItem] = {
if (ag.isEmpty || item.time < ag.head.time) item :: ag
else ag.head :: insert(ag.tail, item)
}
def afterDelay(delay: Int)(block: => Unit) {
val item = WorkItem(currentTime + delay, () => block)
agenda = insert(agenda, item)
}
private def next() {
(agenda: #unchecked) match {
case item :: rest =>
agenda = rest
curtime = item.time
item.action()
}
}
def run() {
afterDelay(0) {
println("*** simulation started, time = "+
currentTime +" ***")
}
while (!agenda.isEmpty) next()
}
}
afterDelay(0) {
println(...)
}
Is equivalent to the following:
afterDelay(0)({
println(...)
})
The function afterDelay is invoked a new WorkItem (item) is added to the list, not the function itself. The parameter block: => Unit is a "By-Name Parameter" (see the Scala Language Specification section 4.6.1): the expression used as the argument is implicitly converted into a "parameterless method" (without being evaluated first) that will be invoked whenever the variable inside the method is accessed (no () required).
In this case that is when the function resulting from () => block is invoked: it is invoked at item.action() which occurs at some point after the new WorkItem is added to the list (and afterDelay returns).
If it was written as (taking in a function paramater, not a by-name/thunk):
def afterDelay(delay: Int)(block: () => Unit) { // take a function
// new function will invoke function named by "block" when invoked ...
val item = WorkItem(..., () => block())
// or skip wrapping the function in a function ...
// val item = WorkItem(..., block)
...
}
Then it would need to be invoked passing in a function:
afterDelay(0)(() => { // need a function
println(...)
})
Or, alternative syntax, still a function of () => Unit, but the outside parenthesis can be avoided:
afterDelay(0) { () => // need a function
println(...)
}
Extract from the SLS, 4.6.1 By-Name Parameters:
The type of a value parameter may be prefixed by =>, e.g. x: => T. The type of such a parameter is then the parameterless method type => T. This indicates that the corresponding argument is not evaluated at the point of function application, but instead is evaluated at each use within the function. That is, the argument is evaluated using call-by-name.
You defined afterDelay as a curried function. This means it has two parameter lists. In scala you can replace the brackets surounding the parameterlist (...) with {...}. In the second parameterlist you are using a "call-by-name" parameter. Those parameters are evaluated everytime again you use them in your function. A good Example is here.
"Call-by-name" parameters are often used to define your own controlling structure.
def do(until: Int)(body: => Unit) {
body
if (until > 1) do(until - 1)(body)
}
do(0)(println("test"))
do(5)(println("test2"))
This is an example for a do until. It will print once test and five times test2.