I want to return from a configbody but cannot do so explicitly without causing the variable not to be set.
I'd like help understanding the behavior I'm seeing. Please consider the following code (using Itcl 3.4):
package require Itcl
catch {itcl::delete class Model}
itcl::class Model {
public variable filename "orig"
}
itcl::configbody Model::filename {
if 1 {
return ""
} else {
}
}
Model my_model
my_model configure -filename "newbie"
puts "I expect the result to be 'newbie:' [my_model cget -filename]"
When I return empty string, filename is not set to the new value. If I do not return but just allow the proc to fall through, filename does change. You can see this by changing the 1 to a 0 in the above code.
I suspect its related to the following statement:
When there is no return in a script, its value is the value of the last command evaluated in the script.
If someone would explain this behavior and how I should be returning, I'd appreciate the help.
Tcl handles return by throwing an exception (of type TCL_RETURN). Normally, the outer part of a procedure or method handler intercepts that exception and converts it into a normal result of the procedure/method, but you can intercept things with catch and see beneath the covers a bit.
However, configbody does not use that mechanism. It just runs the script in some context (not sure what!) and that context treats TCL_RETURN as an indication to fail the update.
Workaround:
itcl::configbody Model::filename {
catch {
if 1 {
return ""
} else {
}
} msg; set msg
# Yes, that's the single argument form of [set], which READS the variable...
}
Or call a real method in the configbody, passing in any information that's required.
Related
I have in the .ts file the following code:
set query(query: string) {
this.form.get('query').setValue(query);
}
get query() {
return this.form.controls.query;
}
I am trying to call the getter method in .html file as:
<div *ngIf="!query.valid && (query?.dirty || query?.touched)">
<div [hidden]="!query.errors.required">Query is required</div>
</div>
However, an error is thrown. The code works perfectly if I remove the setter from the .ts file.
Why does this happen?
You can do it via two ways,
Way 1:
set query(query: any) {
this.form.get('query').setValue(query);
}
get query() {
return this.form.controls.query;
}
Way 2:
set query(query: string) {
this.form.get('query').setValue(query);
}
get query(): AbstractControl {
return this.form.controls.query;
}
when you assign a value to query you are assigning it as a string see the incoming argument type in your setter. So by default angular understands it as string type. Then in your HTML, you try to access it as an object which creates a problem for angular as it expects it to be a string but used as an object.
try form.getControls['query'].setValue(myValue)
form.get('fieldName') will get value of that field ...
form.controls['fieldName'] would get the field itself .. Field control will expose get or set value methods
Although the accepted answer works and the thinking behind it make sense, I would completely avoid using any as a return type, when you know exactly what you're returning.
That just goes against the purpose of using Typescript as a language. Using any is the same as saying "accept everything and don't just interpret it as a string".
set query(query: string) {
this.form.get('query').setValue(query);
}
get query(): AbstractControl {
return this.form.controls.query;
}
Since you know you're returning an AbstractControl, I would set the return type to either AbstractControl or, if you want to be more specific, to FormControl.
In Python, I would do this:
try:
some_func()
except Exception:
handle_error()
else:
print("some_func was successful")
do_something_else() # exceptions not handled here, deliberately
finally:
print("this will be printed in any case")
I find this very elegant to read; the else block will only be reached if no exception was thrown.
How does one do this in Kotlin? Am I supposed to declare a local variable and check that below the block?
try {
some_func()
// do_something_else() cannot be put here, because I don't want exceptions
// to be handled the same as for the statement above.
} catch (e: Exception) {
handle_error()
} finally {
// reached in any case
}
// how to handle 'else' elegantly?
I found Kotlin docs | Migrating from Python | Exceptions, but this does not cover the else block functionality as found in Python.
Another way to use runCatching is to use the Result's extension functions
runCatching {
someFunc()
}.onFailure { error ->
handleError(error)
}.onSuccess { someFuncReturnValue ->
handleSuccess(someFuncReturnValue)
}.getOrDefault(defaultValue)
.also { finalValue ->
doFinalStuff(finalValue)
}
Take a look at the docs for Result: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/index.html
If you do not care about the default value, for example, you want just to hide the loading you could use this:
runCatching {
show_loading(true) //show loading indicator
some_func() //this could throw an exception
}.onFailure {
handle_error(it.message)
}.getOrNull().run {
show_loading(false) //hide loading indicator regardless error or success
}
if ($condition)
$foo = 'bar';
else
throw_exception();
echo $foo;
For this of code, PhpStorm thinks that $foo might not be defined and shows a warning. I have to add /** #noinspection PhpUndefinedVariableInspection */ to eliminate the warning that I hope there is a better solution.
ATM -- nope.
https://youtrack.jetbrains.com/issue/WI-10673 might be a solution (once it will be implemented).
Right now even declaring throw_function() with #throws Exception does not help (as throwing an exception is just one of the possible scenarios and not an obligation).
Watch that and the following related tickets (star/vote/comment) to get notified on any progress:
https://youtrack.jetbrains.com/issue/WI-7462
https://youtrack.jetbrains.com/issue/WI-6562
Right now I simply suggest to rewrite the code in a following more straightforward and easier-to-read fashion:
if (!$condition) {
throw_exception();
}
$foo = 'bar';
echo $foo;
If condition is not met then exit happens sooner (due to the thrown exception) and the code below will simply not be executed. It's much easier to read and understand this way (to follow the code execution flow).
I think PhpStorm is right, because if you don't meet the $condition then $foo is undefined.
You could declare $foo with a null value (or false, or ' ' ...) before the if block to avoid the warning (IMHO this is a better solution):
$foo = '';
if ($condition)
$foo = 'bar';
else
throw_exception();
echo $foo;
(See this more as a comment than an answer please)
As atx stated it's because $foo is not definied when it's read. This is called an undefinied read data flow anomaly. That's not a "problem" of PHPStorm or any other IDE but of your code or in more general of the PHP syntax. The static code analysis in the else-case only see a method call of a method calles throw_exception, not the end of the script. Therefore your code looks like this in this case:
throw_exception();
echo $foo
And then you read an unfedinied variable.
Let's compare this to to a JAVA example
public void test(boolean condition) throws Exception {
if (condition) {
String foo = "this";
} else {
throw new Exception("");
}
// Doesn't compile: foo can not be resolved to a variable
System.out.println(foo);
}
This does not compile at all, because in the line of printing foo "foo can not be resolved to a variable". Same when this method doesn't throws an exception but exits the method with a return value:
public boolean test(boolean condition) {
if (condition) {
String foo = "this";
} else {
return false;
}
// Doesn't compile: foo can not be resolved to a variable
System.out.println(foo);
return true;
}
Let's extend the example:
public void test(boolean condition, String foo) {
if (condition) {
foo = "this";
} else {
System.out.println("else");
}
System.out.println(foo);
}
This compiles and you don't get a warning of the static code analysis because the static code analysis doesn't see an ur-anomaly: foo ist definied in the method header, even if it's definied as null.
Hope this helps to understand why you get the warning and should always definie your variables.
I was just wondered which is better way for returning some result of function or instance of Class?
1)
FN() {
var result = callSomeFN();
return result;
}
InitClass(int typeId): MyClass {
MyClass class = new MyClass(typeId);
return class;
}
2)
FN() {
return callSomeFN();
}
InitClass(int typeId): MyClass {
return new MyClass(typeId);
}
The only difference I see here is the declaration of a variable. I wouldn't say one is better than the other. If the variable is never going to be used why bother defining it? Just return.
I suppose if you really wanted to nitpick it would depend on if you're returning a value or reference type. If it's a reference it doesn't matter since you're going to store something in memory and return a pointer (both the variable and the return value are just pointers to the same memory space). If it's a value type it will end up copying the value and disposing of the version within the function scope. If the variable is never used why create something just to destroy it? The default behavior would be highly language dependent, which you didn't specify.
I have a problem with Spock Mock() object.
I have a java class I'm trying to test. This class does some ftp stuff I want to mock.
My sample code
class ReceiveDataTest extends Specification{
String downloadPath = 'downloadPath';
String downloadRegex = 'downloadRegex';
SftpUtils sftpUtils = Mock();
ReceiveData receiveData;
def setup(){
sftpUtils.getFileNames(downloadPath,downloadRegex) >> ['file1', 'file2']
receiveData= new ReceiveData()
receiveData.setDownloadPath(downloadPath)
receiveData.setDownloadRegex(downloadRegex)
receiveData.setSftpUtils(sftpUtils);
}
def "test execute"() {
given:
def files = sftpUtils.getFileNames(downloadPath,downloadRegex)
files.each{println it}
when:
receiveData.execute();
then:
1*sftpUtils.getFileNames(downloadPath,downloadRegex)
}
}
public class ReceiveData(){
//fields, setters etc
public void execute() {
List<String> fileNames = sftpUtils.getFileNames(downloadPath, downloadRegex);
for (String name : fileNames) {
//dowload and process logic
}
}
}
Now, inside "test execute" the files.each{} prints what is expected. But when receiveData.execute() is called my sftpUtils are returning null..
Any ideas why?
EDIT
Maybe i didnt state my problem well - that I dont want to just check if getFileNames was called. I need the result to proper check the for loop. If I comment the loop inside execute, the test passes. But since I use the result of the getFilenames() method, I get a NPE execute method reaches the for loop. With mockito I would do something like this
Mockito.when(sftpUtils.getFilenames(downloadPath, downloadRegex)).thenReturn(filenamesList);
receiveData.execute();
Mockito.verify(sftpUtils).getFilenames(downloadPath, downloadRegex);
//this is what I want to test and resides inside for loop
Mockito.verify(sftpUtils).download(downloadPath, filenamesList.get(0));
Mockito.verify(sftpUtils).delete(downloadPath, filenamesList.get(0));
but I cannot use Mockito.verify() inside Spock then block
The main problem is that you did not include the response generator (the >> part) in the expectation (i.e. the "1 * ..." part inside the then: block).
This is explained well in the spock documentation.
http://spockframework.org/spock/docs/1.0/interaction_based_testing.html#_combining_mocking_and_stubbing
https://spock-framework.readthedocs.org/en/latest/interaction_based_testing.html#wheretodeclareinteractions
You shouldn't have to declare your stub in the setup: block. You can just specifiy it once in the then: block -- even though that follows the call to receiveData.execute(). That's part of the magic of spock thanks to Groovy AST transformations. And since (non-shared) fields are reinitialized before each test (more AST based magic), you don't even need setup() in this case.
Another odd thing is that you are both stubbing out sftpUtils.getFilenames() and also calling it from the test code. Mocks and stubs are intended to replace collaborators that are called from the system under test. There's no reason to call the stub from the test driver. So delete the call to getFilenames() from your given block and let the code under test call it instead (as it does).
Groovy lets you simplify calls to Java set and get methods. Look at the initialization of receiveData below. Its okay to use def in Groovy. Let the compiler figure out the data types for you.
Leading to something like:
class ReceiveDataTest extends Specification {
// only use static for constants with spock
static String PATH = 'downloadPath'
static String REGEX = 'downloadRegex'
def mockSftpUtils = Mock(SftpUtils)
def receiveData = new ReceiveData(downloadPath : PATH,
downloadRegex : REGEX,
sftpUtils : mockSftpUtils)
def "execute() calls getFileNames() exactly once"() {
when:
receiveData.execute()
then:
1 * mockSftpUtils.getFileNames(PATH, REGEX) >> ['file1', 'file2']
0 * mockSftpUtils.getFileNames(_,_)
// The second line asserts that getFileNames() is never called
// with any arguments other than PATH and REGEX, aka strict mocking
// Order matters! If you swap the lines, the more specific rule would never match
}
}