I'm new to Dart, so maybe I'm missing something here:
This works:
In my main(), I have this:
var a = _someFunction;
var b = _someFunction;
print("${a == b}"); // true. correct!
Where _someFunction is another top-level function.
This does NOT work: (at least not how I'm expecting it to)
Given this class...
class Dummy {
void start() {
var a = _onEvent;
var b = _onEvent;
print(a == b); // false. ???????
}
void _onEvent() {
}
}
Instantiating it from main() and calling its start() method results in false. Apparently a new instance of some function or closure object is created and returned whenever my code obtains a reference to _onEvent.
Is this intentional behaviour?
I would expect that obtaining multiple references to the same method of the same instance returns the same object each time. Perhaps this is intended for some reason. If so; what reason? Or is this a bug/oversight/limitation of VM perhaps?
Thanks for any insights!
Currently, the behaviour seems to be intentional, but the following defect is open since May 2012: https://code.google.com/p/dart/issues/detail?id=144
If I were to guess, I'd say that setting "var a = _onEvent;" creates a bound method, which is some sort of object that contains both the function as well as this. You are asking for bound methods to be canonicalized. However, that would require the team to create a map of them, which could lead to worries about memory leaks.
I think they made "var a = _someFunction;" work early on because they needed static functions to be constants so that they could be assigned to consts. This was so that they could write things like:
const logger = someStaticLoggingFunction;
This was in the days before statics were lazily evaluated.
In any case, I would say that comparing closures for equality is a edge case for most languages. Take all of the above with a grain of salt. It's just my best guess based on my knowledge of the system. As far as I can tell, the language spec doesn't say anything about this.
Actually, now that I've read (https://code.google.com/p/dart/issues/detail?id=144), the discussion is actually pretty good. What I wrote above roughly matches it.
Related
Disclaimer: I have seen many similar questions posted already. However in all those questions, they were not aware of the update parameter to AndroidView. I am aware of the update parameter.
The problem
I have a legacy CustomView that has two methods to set its data. Let's call them setDataSlow() and setDataFast().
The setDataSlow() method is expected to be called only once in the lifetime of the view, and it is relatively slow.
The setDataFast() method needs to be called frequently, and is very fast.
So, the natural code in Compose would be something like this:
var data1 by remember {mutableStateOf(0)}
var data2 by remember {mutableStateOf(0)}
AndroidView(factory = {
val v = CustomView(it)
v.setDataSlow(data1)
v
}, update = {
it.setDataFast(data2)
}
)
The problem is, the factory lambda gets only called once, even when data1 changes. I understand this is by design.
Question
How do I solve this? If I call setDataSlow() inside update, it will slow down the UI tremendously.
I need to somehow force the factory method to update, and the only way I can do that is to force recompose of AndroidView somehow.
I'm trying to do something that would be a basic feature in any other Object Oriented Language but for some reasons in Dart, I can't manage to do it. I'm new to Dart so this question might be dumb, but I couldn't find any answer online.
I have a property that need to be calculated once and on the constructor. This is my code so far :
class Game {
String _wordChosen;
Game() {
final _random = Random();
_wordChosen = WORDS[_random.nextInt(WORDS.length)];
}
}
WORDS is a list defined outside the class. My error is on the Game constructor :
not_initialized_non_nullable_instance_field.
I don't want to set the _wordChosen variable to a default value as that would make no sense (it would be overwritten right when the constructor is run).
I also don't want to set the property as nullable as again, it would make no sense.
i think the answer is using the keyword late to make compiler know that you will initialize the variable before using it but not now like below
late String _wordChosen;
i think this is your solution and it in null safety documents here
i hope this answer helps you
I have a situation where I defined a couple of module-level instance variables using the 'private' scope identifier. I require to do this because these variables will be used in several functions within the module. Also, some of these variables are 'lists' or 'sets'. I realized that values of these variables persist between repeated calls to a certain function within the module. This is as expected.
I am also creating a test where I call one of the functions repeatedly. I would prefer to have a fresh copy of the instance variables (just like with instance members in Java). I can't seem to do so. If I try to nullify the content of the list/set, I get into trouble as follows:
module foo::bar
private set[DataType_1] data1;
public void nullifyInstanceVars( )
{
//tried
data1={}
}
//method that gets called repeatedly:
public void repeatCallMe(..)
{
nullifyInstanceVars( );
...
..
//Throws an error like: trying to add an element of type 1 to set[void]
data1 += anElementOfType1
}
So, I modified the nullifyInstanceVars( ) method to have set[DataType1] data1={ }. It doesn't work because I believe that simply creates a new variable scoped only within the function and really doesn't clear the element!
Any help is appreciated...
This really looks like a bug in the Rascal interpreter. I will file a bug report for it.
The work around is to initialize data1 in the declaration as well:
private set[int] data1 = {};
Can you confirm that this solves your problem?
i want to build a small plugin-system for objects in objective-c.
Now i am stuck at the point where i want to dynamically (at runtime) add a line of code to every function available in an object.
I have played around with the runtime library but came to no solution, yet.
What i have tried so far is this:
id (^impyBlock)(id, id, ... ) = ^(id self_, id arguments, ...)
{
// My custom code for every function here
id (*func)(__strong id,SEL,...) = (id (*)(__strong id, SEL, ...))imp;
return func(obj, s, arguments);
};
id (*impyFunct)(id, SEL,...) = imp_implementationWithBlock(impyBlock);
method_setImplementation(mList[i], impyFunct);
My problem is, when there is more than one argument i got no chance to pass them to "func()". AFAIK this is not possible in C.
Another solution i have thought about is doing some magic with method swizzling.
In steps:
Create a "swizzle Method" which just calls my custom code and calls the original method afterwards (by a naming schema)
Change the IMP of every function with the one of the "swizzle Method"
Create a new method with the "old" implementation and change to name to a schema like "___name"
In this solution i am stuck at point 3. I haven't managed to dynamically create a complete new method.
Does anybody can help me with my problems above or has another solution for a "catch all method functionality".
The best would be something like forwardInvocation which also catches already defined functions.
Thanks for your help!
Lemme break this into two parts since I just can't get the connection between your two questions.
I. Create a new method with the "old" implementation and change to name to a schema like "___name"
That's fairly easy, although I don't understand how that would be able to solve your problem. You still can't pass down variadic function arguments to such a method (and you're right, that can't be done in C).
IMP swapImpForSelector(Class cls, SEL sel, IMP newImp)
{
Method m = class_getInstanceMethod(cls, sel);
IMP oldImp = method_setImplementation(m, newImp);
NSString *newSel = [NSString stringWithFormat:#"__prefixed_%#", NSStringFromSelector(sel)];
const char *type = method_getTypeEncoding(m);
class_addMethod(cls, NSSelectorFromString(newSel), oldImp, type);
return oldImp;
}
II. If you want to pass variadic arguments between functions, you may need to fall back to heavy assembly hackage. Fortunately, some smart people have already done that for you.
Either use the NSInvocation class, or if it isn't sufficient, then libffi is even lower-level.
Doing this for arbitrary objects will be quite hard. Take a look at AspectCocoa for something along these lines, but you'll see it doesn't work so great and isn't recommended for use in a production environment.
But for a plugin system, you'd be better off just defining something like a PluggableObject class that is designed with extension in mind. Forget about running arbitrary blocks in the middle of arbitrary methods — instead, define specific "sockets" where things can plug in and an interface that those things can follow to get the functionality you want to support. It'll be a lot more stable and easier to add and fix things.
I would like to cast instances of my custom class A to int. What is the syntax of the implicit cast operator? (I thought I remembered that there is such a feature but I can't find it on the web)
int a = (new A());
You can also use as to help tell the tools "no, really, treat this object as this type".
A good example of this is when you have to deal with dart:html's querySelector() function.
FormElement form = querySelector('#sign-up') as FormElement;
In the above, the object returned by querySelector('#sign-up') is checked that it is really an instance of FormElement.
Learn more at https://www.dartlang.org/docs/dart-up-and-running/ch02.html#operators
Type annotations are not allowed to affect behavior in Dart. If you're not running in checked mode, then this:
int a = new A();
will work the same as this:
var a = new A();
at run-time. In other words, when not in checked mode, you're welcome to store your A in a variable annotated as an int, but no actual conversion takes place.
If you are running in checked mode, the first form will give you a runtime exception.
I'm not sure, but I think what you're asking for is a way to define a conversion between your class A and int that will happen automatically when "cast" to an int. No such thing exists, to my knowledge. You should simply define a method to do so. For example:
int a = new A().to_i();