Say, I have:
var buffer = StringBuffer();
buffer.toString(); // works (understandable)
buffer.write('foo').toString(); // fails because `write` returns `void` (understandable)
buffer..write('bar').toString(); // but why does it fail?
You can see buffer..write('bar') returns a StringBuffer instance, and I should be able to call toString() on that instance. But why it doesn't work that way.
PS: I know I can use buffer..write('bar')..toString() to make it work but my question is not how to make that work rather I want to know the reason why it didn't work.
Because that is how the cascade operator is suppose to work.
buffer..write('bar').toString();
Is equal to do:
buffer.write('bar').toString();
Where:
buffer..write('bar')..toString();
Is equal to:
buffer.write('bar');
buffer.toString();
What you can do to make your example works is to add bracket like this so we changes the order of how each part is linked:
(buffer..write('bar')).toString();
Also found this answer which also gives some details about this behavior:
How do method cascades work exactly in dart?
Related
So I have added code into a Dart Application that runs a check to see if a response is authorized and I have set it up so there is a simple 3 line bit of code that is needed in the method to check. I'm worried though that if I am not the one programming it how can we ensure that those lines get added. The code looks like below
#Operation.get()
Future<Response> returnGroupFromRegistrationCode(
#Bind.query('code') String code,
) async {
final result = await getRegistrationCodeGroupResult(context, code);
final unauthorizedResponse = result.unauthorizedResponse;
if (unauthorizedResponse != null) {
return unauthorizedResponse;
}
The final unathorizedResponse are the 3 lines that need to be added. The logical way is to add this check in the getRegistrationCodeGroupResult but I can't return the method early without a null check. Is there an error I could throw if and API is being used correctly because I didn't see an applicable one on the list? Just looking for potential ways to improve the code and make it easier to use in the future, any ideas welcome!
A few things I could hope for.
an error that could work to be thrown if the API is being used incorrectly
a way to cut off a function early without the null check
a way to possible integrate a standard into Lint or some autoformat or a scripted way to check if the lines of code are included
The reason it took me forever to find out is that I don't know how it is called. But I hope if I describe the question here as thoroughly as possible, it will pop up in the search results anyways.
Possible other titles:
How can I pass a function without name as parameter to querySelector.onClick.listen?
How to use a function without a name in dart?
How to create a nameless function that you can use only exactly there where it is defined?
I know that the following works - also hosted on dartpad
void main(){ querySelector('#btn').onClick.listen((e)=>fnct()); }
void fnct(){ querySelector('#btn').text="hola"; print("test");}
This changes the text of the button to "hola" and prints "test".
But what if I don't want to define a new function just for this because I like to keep the flow when reading the code and don't like to jump from function to function needlessly?
After an hour of searching, I found this
For my own code example, it would be like this dartpad link:
void main(){
querySelector('#btn').onClick.listen((e){
querySelector('#btn').text="hello";
print("no hablo espanol");
});
}
So you can define a function on the flow by using
(param){command(); secondCommand(param);}
It is entirely possible that you can find this somewhere. But I did not with my search terms. So if any of you know what the correct search terms would have been, let me know :)
String string = "org.springframework.web.multipart.commons.CommonsMultipartFile#1c08114a";
// CommonsMultipartFile reference = string // Wrong
// Something like that.....
Short answer: you can't. And more important: you shouldn't. Don't call toString() on your object in the first place. And if someone else hands you this down, beat them with a stick.
Long answer: the default toString() you are seeing there is just to make you differentiate objects. the hashcode/address/pointer there would only allow reversing back to a object, if you either store them somewhere or you have the means to calculate it back (e.g. a Boolean could work (but don't even bother trying)). This is not C, where you could attempt to dash that number into an void* and hope the best.
Disclaimer: it might not be impossible to do, but if you have to do it, then there is something fundamental broken. This answer intentionally does not answer the question.
For reference see Why does the default Object.toString() include the hashcode?
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'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.