Is this a bug?
I have the following block in the middle of my action method wrapped in the if statement:
withFormat {
json{
render returnMap as JSON
return
}
}
The returnMap is rendered to the client just fine, but the method continues to execute as if return was never processed. What's up?
I am using grails 1.3.7.
To answer my own question:
I found it has something to do with the withFormat block. If I remove it the return statement works just fine. When the withFormat is in place it seems that the return statement exits that block and continues the execution of the remaining method.
Edit:
Burt clarified below that it's the json{} closure that gets exited with the return statement (or without it I guess). If there are statements following that closure they will be executed.
The return exits the 'json' Closure, but not the whole method. It's like having methods with methods - you can only pop up one level. You'd need to set a flag inside the block and check it outside, something like
boolean renderedJson = false
...
withFormat {
json{
render returnMap as JSON
renderedJson = true
}
}
...
if (renderedJson) {
return
}
Related
I noticed that forEach and for in to produce different behavior. I have a list of RegExp and want to run hasMatch on each one. When iterating through the list using forEach, hasMatch never returns true. However, if I use for in, hasMatch returns true.
Sample code:
class Foo {
final str = "Hello";
final regexes = [new RegExp(r"(\w+)")];
String a() {
regexes.forEach((RegExp reg) {
if (reg.hasMatch(str)) {
return 'match';
}
});
return 'no match';
}
String b() {
for (RegExp reg in regexes) {
if (reg.hasMatch(str)) {
return 'match';
}
}
return 'no match';
}
}
void main() {
Foo foo = new Foo();
print(foo.a()); // prints "no match"
print(foo.b()); // prints "match"
}
(DartPad with the above sample code)
The only difference between the methods a and b is that a uses forEach and b uses for in, yet they produce different results. Why is this?
Although there is a prefer_foreach lint, that recommendation is specifically for cases where you can use it with a tear-off (a reference to an existing function). Effective Dart recommends against using Iterable.forEach with anything else, and there is a corresponding avoid_function_literals_in_foreach_calls lint to enforce it.
Except for those simple cases where the callback is a tear-off, Iterable.forEach is not any simpler than using a basic and more general for loop. There are more pitfalls using Iterable.forEach, and this is one of them.
Iterable.forEach is a function that takes a callback as an argument. Iterable.forEach is not a control structure, and the callback is an ordinary function. You therefore cannot use break to stop iterating early or use continue to skip to the next iteration.
A return statement in the callback returns from the callback, and the return value is ignored. The caller of Iterable.forEach will never receive the returned value and will never have an opportunity to propagate it. For example, in:
bool f(List<int> list) {
for (var i in list) {
if (i == 42) {
return true;
}
}
return false;
}
the return true statement returns from the function f and stops iteration. In contrast, with forEach:
bool g(List<int> list) {
list.forEach((i) {
if (i == 42) {
return true;
}
});
return false;
}
the return true statement returns from only the callback. The function g will not return until it completes all iterations and reaches the return false statement at the end. This perhaps is clearer as:
bool callback(int i) {
if (i == 42) {
return true;
}
}
bool g(List<int> list) {
list.forEach(callback);
return false;
}
which makes it more obvious that:
There is no way for callback to cause g to return true.
callback does not return a value along all paths.
(That's the problem you encountered.)
Iterable.forEach must not be used with asynchronous callbacks. Because any value returned by the callback is ignored, asynchronous callbacks can never be waited upon.
I should also point out that if you enable Dart's new null-safety features, which enable stricter type-checking, your forEach code will generate an error because it returns a value in a callback that is expected to have a void return value.
A notable case where Iterable.forEach can be simpler than a regular for loop is if the object you're iterating over might be null:
List<int>? nullableList;
nullableList?.forEach((e) => ...);
whereas a regular for loop would require an additional if check or doing:
List<int>? nullableList;
for (var e in nullableList ?? []) {
...
}
(In JavaScript, for-in has unintuitive pitfalls, so Array.forEach often is recommended instead. Perhaps that's why a lot of people seem to be conditioned to use a .forEach method over a built-in language construct. However, Dart does not share those pitfalls with JavaScript.)
👋 jamesdin! Everything you have shared about the limitations of forEach is correct however there's one part where you are wrong. In the code snippet showing the example of how you the return value from forEach is ignored, you have return true; inside the callback function for forEach which is not allowed as the callback has a return type of void and returning any other value from the callback is not allowed.
Although you have mentioned that returning a value from within the callback will result in an error, I'm just pointing at the code snippet.
Here's the signature for forEach
Also, some more pitfalls of forEach are:
One can't use break or continue statements.
One can't get access to the index of the item as opposed to using the regular for loop
I am using a redux pattern in my dart application. Inside the reducer the if statement that has the "is" keyword to figure out which action(in the form of a class) is being passed is not working at all.
DictionaryState dictionaryReducer(DictionaryState state, dynamic action){
if(action is RequestingDictionaryEntryAction){
// This if statement should be executed but it is not.
return _requestingDictionaryEntry(state);
}
if(action is ReceivedDictionaryEntryAction){
return _receivedDictionaryEntry(state, action);
}
return state;
}
When calling dictionaryReducer I am passing an action called RequestingDictionaryEntryAction and it is not being recognized as RequestingDictionaryEntryAction, instead the code continues to execute and the function does not return as it is supposed to.
Just off the top of my head, so don't put in too much faith, but your problem might lie in the "dynamic" type of the parameter causing the is operator to fail at compile-time. I would think it could be solved using:
DictionaryState dictionaryReducer(DictionaryState state, dynamic action){
if(action.runtimeType == RequestingDictionaryEntryAction){
return _requestingDictionaryEntry(state);
}
if(action.runtimeType == ReceivedDictionaryEntryAction){
return _receivedDictionaryEntry(state, action);
}
return state;
}
The problem was in the argument I was passing as action. I was not instantiating the class properly. I was passing the class declaration itself instead of an instant of it.
final action = RequestingDictionaryEntryAction instead of
final action = RequestingDictionaryEntryAction();
:D :D
I have code on logout button, where I'm using defer statement.
I'm wondering when changing position of defer statement code inside action method scope.
I have added defer statement at the end of method, it's show me warning.
'defer' statement before end of scope always executes immediately;
replace with 'do' statement to silence this warning
Code:
override func sendButtonTapped(sender: Any) {
self.deleteCoreData()
self.clearUserDefaults()
// Clear view context
AppDelegate.shared.persistentContainer.viewContext.reset()
....
....
// Call after all code execution completed in this block's Scope
defer {
// Set isUserLoggedIn and change root view controller.
UserDefaults.Account.set(false, forKey: .isUserLoggedIn)
AppDelegate.shared.setRootViewController()
}
}
Then, I have added defer statement at start of method, it's show nothing.
Code:
override func sendButtonTapped(sender: Any) {
// Call after all code execution completed in this block's Scope
defer {
// Set isUserLoggedIn and change root view controller.
UserDefaults.Account.set(false, forKey: .isUserLoggedIn)
AppDelegate.shared.setRootViewController()
}
self.deleteCoreData()
self.clearUserDefaults()
// Clear view context
AppDelegate.shared.persistentContainer.viewContext.reset()
....
....
}
Can anyone explain what exactly happening with defer statement?
To sum it up, the defer statement will be executed at the end of the scope you are in. ( .apple doc : https://docs.swift.org/swift-book/ReferenceManual/Statements.html#grammar_defer-statement )
from apple doc
func f() {
defer { print("First defer") }
defer { print("Second defer") }
print("End of function")
}
f()
// Prints "End of function"
// Prints "Second defer"
// Prints "First defer"
The defer statement allow you to define an action that will be executed after the rest of the operation you want to be done, i.e. at the end of the scope.
The warning is pretty explicit too, considering you place the defer statement just at the end of the scope, it doesnt serve any purpose :
func f() {
print("TIC")
defer { print("TAC") } // will be print at the end of the function
}
f()
// Prints "TIC"
// Prints "TAC""
which is the very same as :
func f() {
print("TIC")
print("TAC") // no defer, same result
}
f()
// Prints "TIC"
// Prints "TAC""
To go further
Then why do the warning propose you a do block ?
Actually, the two previous example are not 100% the same, when you use the defer statement, it creates its own scope
func f() {
// here you are in the scope of the `f()` function
print("TIC")
defer {
// here you are the scope of the `defer` statement
print("First defer")
}
}
And the closest way to manually create a scope is the do statement
func f() {
// here you are in the scope of the `f()` function
print("TIC")
do {
// here you are the scope of the `do` statement
print("First defer")
}
}
From apple docs
The do statement is used to introduce a new scope and can optionally contain one or more catch clauses, which contain patterns that match against defined error conditions. Variables and constants declared in the scope of a do statement can be accessed only within that scope.
if you want to learn more about scopes, here is some lecture: https://andybargh.com/lifetime-scope-and-namespaces-in-swift/
Essentially, an objects scope defines the areas of our program from which the item can be accessed.
According to Swift documentation:
A defer statement is used for executing code just before transferring program control outside of the scope that the defer statement appears in. This means that a defer statement can be used, for example, to perform manual resource management such as closing file descriptors, and to perform actions that need to happen even if an error is thrown.
In your example, using a defer at the end of the code is useless because the code will be executed exactly in the same way as if it was outside the defer, as a defer executes the code just before exiting the current scope (method).
I'd like to implement method chaining in my swift code, likely to Alamofire methods. For example, if I have to use my function like below
getListForID(12).Success {
// Success block
}. Failure {
// Failure block
}
How would I create the function getListForID?
To expand on the great points #dasblinkenlight and #Sulthan have made – here's a small example of how you could achieve your request function to take a success and failure closure, in the convenient syntax that you want.
First, you'll have to define a new class to represent the 'result handler'. This is what your success and failure functions will pass around, allowing you to add multiple trailing closures to make up your completion block logic. You'll want it to look something like this:
class ResultHandler {
typealias SuccessClosure = RequestHandler.Output->Void
typealias FailureClosure = Void->Void
// the success and failure callback arrays
private var _successes = [SuccessClosure]()
private var _failures = [FailureClosure]()
/// Invoke all the stored callbacks with a given callback result
func invokeCallbacks(result:RequestHandler.Result) {
switch result {
case .Success(let output): _successes.forEach{$0(output)}
case .Failure: _failures.forEach{$0()}
}
}
// remove all callbacks – could call this from within invokeCallbacks
// depending on the re-usability of the class
func removeAllCallbacks() {
_successes.removeAll()
_failures.removeAll()
}
/// appends a new success callback to the result handler's successes array
func success(closure:SuccessClosure) -> Self {
_successes.append(closure)
return self
}
/// appends a new failure callback to the result handler's failures array
func failure(closure:FailureClosure) -> Self {
_failures.append(closure)
return self
}
}
This will allow you to define multiple success or failure closures to be executed on completion. If you don't actually need the capacity for multiple closures, then you can simplify the class down by stripping out the arrays – and just keeping track of the last added success and failure completion blocks instead.
Now all you have to do is define a function that generates a new ResultHandler instance and then does a given asynchronous request, with the invokeCallbacks method being invoked upon completion:
func doRequest(input:Input) -> ResultHandler {
let resultHandler = ResultHandler()
doSomethingAsynchronous(resultHandler.invokeCallbacks)
return resultHandler
}
Now you can call it like this:
doRequest(input).success {result in
print("success, with:", result)
}.failure {
print("fail :(")
}
The only thing to note is your doSomethingAsynchronous function will have to dispatch its completion block back to the main thread, to ensure thread safety.
Full project (with added example on usage): https://github.com/hamishknight/Callback-Closure-Chaining
In order to understand what is going on, it would help to rewrite your code without the "convenience" syntax, which lets you omit parentheses when a closure is the last parameter of a function:
getListForID(12)
.Success( { /* Success block */ } )
.Failure( { /* Failure block */ } )
This makes the structure of the code behind this API more clear:
The return value of getListForID must be an object
The object must have two function called Success and Failure*
Both Success and Failure need to take a single parameter of closure type
Both Success and Failure need to return self
* The object could have only Success function, and return a different object with a single Failure function, but then you wouldn't be able to re-order the Success and Failure handlers, or drop Success handler altogether.
In Grails (at least up to the current version 2.2), taglibs are closures. For certain taglib closures, I'd like to use some "around" type advice / wrap the closure in an interceptor.
To put it another way, let's say there is this taglib straight from the Grails doc:
class SimpleTagLib {
def emoticon = { attrs, body ->
out << body() << (attrs.happy == 'true' ? " :-)" : " :-(")
}
}
Now, without modifying the taglib code, I'd like to time how long "emoticon" takes to execute.
Spring AOP (and all other AOP I can find) only seems to work on Java methods - and taglibs are always based on closures. An "around" pointcut would be perfect for this, but I can't figure out how to make it work.
I've written something similar which I put as a public closure in a category I then mixin to services:
// TimingCategory.groovy
/**
* Provides common AOP timing functionality to Services which mixin this category.
*/
class TimingCategory {
static Closure timer = { String label = "The call", Closure closure ->
Long start = System.currentTimeMillis()
def result = closure.call()
Long end = System.currentTimeMillis()
Long duration = end - start
log.warn "${label} took ${duration} ms"
return result
}
}
In other classes, you just reference the timer closure as such:
#Mixin(TimingCategory)
public class WhateverService {
public String doSomeWork() {
timer "Doing a lot of work", {
1000.times { doSomething() }
someMethodWithAStringReturnValue()
}
}
}
That will give you log output of "WARN: Doing a lot of work took nn ms" and return the value of the inner closure as the return value of the doSomeWork method.
For your taglib instance, just wrap the out << ... in the
timer "Writing an emoticon", {
// your code
}
code.
If you don't care about passing through the internal return value, you could instead return the duration as the result of the closure invocation.
Update:
I might have misread -- you're asking how to wrap the taglib execution without modifying the taglib code at all? What about creating a custom taglib which accepts the body and passes it to the other taglibs for execution?
I haven't tried this, but something like:
class TimedTagLib {
static namespace = "timer"
def timedTag = { attrs, body ->
timer "Executing the timed tag", {
out << body()
}
}
}
And invoking it like
<timer:timedTag><g:emoticon whatever="something">Text</g:emoticon></timer:timedTag>
Update 2:
Ok, so I tried it. Works fine. My final code (I added a second timer closure which returns the duration):
// TimedTagLib.groovy
#Mixin(TimingCategory)
class TimedTagLib {
static namespace = "timer"
def timedTag = { attrs, body ->
def duration = returnTimer "Printing the timed tag", {
out << body()
}
out << "Took ${duration} ms to print"
}
}
And the view:
// someView.gsp
<timer:timedTag>
<g:formatLocalDate date="${LocalDate.now()}" />
</timer:timedTag>
The resulting HTML is:
03/19/2013
Took 6 ms to print
And it also wrote to the log.