Strange behavior during variables assignment in Scala - scala

How can I define variables inside if-block ?
if ( 2 > 1 ){
val t = 6
}
print(t)
This simple code returns error : not found: value t

Your code's t variable is only defined within if block. So you can use it only inside this block. One reason for this behavior is a question: Which value has t when the condition of the if statement is false.
If you want to use the t variable outside this scope you can do the following:
Put if block in the assigning like this:
val t = if (2 > 1) 0 else 1
Use var keyword to make the t mutable and define it before if block with the default value:
var t = 1
if (2 > 1) {
t = 0
}
In any case, you need a value for else case to be able to define the t variable.

Related

Call a script with definitions in a function

We have a script that defines values to names similar to #define in c. For example:
script.m:
ERR_NOERROR = 0;
ERR_FATAL = 1;
This script already exists and is used for value replacement when reading data from files.
Now we have a function (or more) that does some analysis and we would like to use the same definition in this function to avoid magic numbers. But when the script is called from the function we get an error.
Attempt to add "ERR_NOERROR" to a static workspace.
See MATLAB Programming, Restrictions on Assigning to Variables for details.
And this does not help much in the understanding of the problem.
The question is how can we make these definitions visible/usable in the functions with having to copying it every time.
Example:
function foo = bar(a)
run(script.m) %also tried running it without the run command
if a == ERR_NOERROR
foo = 5;
else
foo = 6;
end
end
edit:
There was a nested function,below in the function which I was not aware of. This explains the problem.
This kind of scoping error happens when you use nested or anonymous function within a function. The solution is well documented.
To your case, you can avoid nested function, or "Convert the script to a function and pass the variable using arguments", as the documentation suggests.
EDIT: I should have made it clear that the error occurs even if the script is not called within the nested function. Similar scenario is that, in debug mode (by setting up a break point), it will be an error if one tries to create a temporal variable to test something.
This is not a direct answer, rather a recommendation to switch to another method, which will not be mixing scope and workspace.
Instead of defining your constant in a script, you could make a class containing only constant properties. ex: code for error_codes.m:
classdef error_codes
% ---------------------------------------------------------------------
% Constant error code definition
% ---------------------------------------------------------------------
properties (Constant = true)
noerror = 0 ;
fatal = 1 ;
errorlvl2 = 2 ;
errorlvl3 = 3 ;
warning = -1 ;
% etc ...
end
end
I use this style for many different type of constants. For tidiness, I groups them all in a Matlab package directory (The directories which starts with a + character.
The added benefit of using constant class properties is the safety that the values cannot be changed in the middle of the code (your variables defined in a script could easily be overwritten by a careless user).
So assuming my file error_codes.m is placed in a folder:
\...somepath...\+Constants\error_codes.m
and of course the folder +Constants is on the MATLAB path, then to use it as in your example, instead of calling the script, just initialise an instance of the class, then use the constant values when you need them:
function foo = bar(a)
ERR = Constants.error_codes ;
if a == ERR.noerror
foo = 5;
else
foo = 6;
end
or it can works in switch statement too:
switch a
case ERR.noerror
foo = 5 ;
case ERR.warning
foo = 42 ;
case ERR.fatal
foo = [] ;
end

Redeclaring variables in functions

Why does redeclaring output inside this if-statement not generate an error?
let output = 0
if counter < message.count {
let output = counter //This should throw an error, right?
counter += 1
} ...
The scope inside the if-statement knows about output as proven here, when trying to change the value of output instead of re-declaring it:
let output = 0
if counter < message.count {
output = counter //ERROR: Cannot assign to value: 'output' is a 'let' constant
counter += 1
} ...
There is no error because it is perfectly legal to declare a variable inside a closure with the same name of a variable which has been declared outside of the closure. It shadows the "outside declared variable".
In case your sample code is inside a class you could still access the "outside declared variable" using self:
class Foo {
let output = 0
func baa() {
let output = 1
print(output)
print(self.output)
}
}
Using this:
let foo = Foo()
foo.baa()
prints:
1
0
let output = counter is declaring a new variable (output) in the scope of the if statement, which has nothing to do with the output variable declared outside.
Edit
The code extract below illustrates that the output variables are not the same, despite their name. The value that gets changed is the one of the local output variable, not the one outside.
var message = [String]()
let output = 2
var counter = -1
if counter < message.count {
let output = counter //This should throw an error, right?
print("local output value is:\(output)") // here the local output value is -1 not 2.
counter += 1
}
The first example is a case of variable shadowing. This occurs when the code has multiple scope blocks. In the first example:
let output = 0 //outer scope block
if counter < message.count {
let output = counter //inner scope block
counter += 1
} ...
In the inner scope block, a new 'output' constant has been declared with the 'let' keyword. That output constant is only valid within that 'if' block. It happens to use the same name as the one declared above the "if" statement. This is variable shadowing.
For the second example:
let output = 0
if counter < message.count {
output = counter //ERROR: Cannot assign to value: 'output' is a 'let' constant
counter += 1
} ...
The error is occurring because defining something with 'let' makes it a constant. It cannot be changed. In this case there is only one 'output' constant. It was declared above the if statement and it is a constant. So, it cannot be changed once it has been assigned a value.
So, in the first example, there are 2 "output" constants, one of which is only valid within the "if" statement. In the second example, there is only 1 "output" constant.
Curly braces constitute a scope. In an inner scope, it is always legal to overshadow a variable name from an outer scope.
let output = // ... [A]
[class, func, if, for, do, etc.] {
let output = // ... [B, overshadows A]
// *
}
You've done a self-limiting thing, in one sense, in that code at the * point may now be unable to refer to output A; it is overshadowed by output B. But it isn't illegal. On the contrary, this is an important thing to be able to do, and to disallow it would be silly.

TestComplete/JScript- Using a variable in an object path

I am using TestComplete with JScript testing a webpage that has elements that I declare as a variable to make it easier to test the element later. They all have a path like:
var check1 = Window.Panel(1).Panel(2).Panel(0).Panel(0).Panel(0).Panel(0).Panel(1).Panel(0).Label(0).Checkbox(0)
The elements are dynamic, so there is no telling how many there are when the test is run. I was hoping there was some way to loop through and declare the elements, but it would involve declaring the element like this:
var check1 = Window.Panel(1).Panel(2).Panel(0).Panel(0).Panel(0).Panel(0).Panel(1).Panel(0).Label(x).Checkbox(0)
where x is the counter variable. The problem is that TestComplete sees this as a literal path and does not recognize x as a variable.
Is there any way to do this with TestComplete using JScript? Or convert a string to an object? I think I can work with that, too.
My guess is that since you store the reference in variable check1, the variable x is updated but the x in variable check1 still holds it's original value (1).
Workaround
Keep the first part of the path static in the variable, then update x and assign it to the label.
var path = Window.Panel(1).Panel(2).Panel(0).Panel(0).Panel(0).Panel(0).Panel(1).Panel(0);
// path to the Checkbox
path.Label(x).Checkbox(0);
// or if you want to loop over it
for (var x = 0, len = 8; i < len; x += 1) {
if (path.Label(x).Checkbox(0).value === 'something') {
console.log('hooray!');
}
}

Scala return does not return

There is some misunderstanding between me and Scala
0 or 1?
object Fun extends App {
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) { // when this is true
return 1 // and we are about to return 1, the code goes to the next line
}
foo(list.tail, count + 1) // I know I do not use "return here" ...
count
}
val result = foo( List(1,2,3) )
println ( result ) // 0
}
Why does it print 0?
Why does recursion work even without "return"
(when it is in the middle of function, but not in the end)?
Why doesn't it return 1? when I use "return" explicitly?
--- EDIT:
It will work if I use return here "return foo(list.tail, count + 1)'.
Bu it does NOT explain (for me) why "return 1" does not work above.
If you read my full explanation below then the answers to your three questions should all be clear, but here's a short, explicit summary for everyone's convenience:
Why does it print 0? This is because the method call was returning count, which had a default value of 0—so it returns 0 and you print 0. If you called it with count=5 then it would print 5 instead. (See the example using println below.)
Why does recursion work even without "return" (when it is in the middle of function, but not in the end)? You're making a recursive call, so the recursion happens, but you weren't returning the result of the recursive call.
Why doesn't it return 1? when I use "return" explicitly? It does, but only in the case when list is empty. If list is non-empty then it returns count instead. (Again, see the example using println below.)
Here's a quote from Programming in Scala by Odersky (the first edition is available online):
The recommended style for methods is in fact to avoid having explicit, and especially multiple, return statements. Instead, think of each method as an expression that yields one value, which is returned. This philosophy will encourage you to make methods quite small, to factor larger methods into multiple smaller ones. On the other hand, design choices depend on the design context, and Scala makes it easy to write methods that have multiple, explicit returns if that's what you desire. [link]
In Scala you very rarely use the return keyword, but instead take advantage that everything in an expression to propagate the return value back up to the top-level expression of the method, and that result is then used as the return value. You can think of return as something more like break or goto, which disrupts the normal control flow and might make your code harder to reason about.
Scala doesn't have statements like Java, but instead everything is an expression, meaning that everything returns a value. That's one of the reasons why Scala has Unit instead of void—because even things that would have been void in Java need to return a value in Scala. Here are a few examples about how expressions work that are relevant to your code:
Things that are expressions in Java act the same in Scala. That means the result of 1+1 is 2, and the result of x.y() is the return value of the method call.
Java has if statements, but Scala has if expressions. This means that the Scala if/else construct acts more like the Java ternary operator. Therefore, if (x) y else z is equivalent to x ? y : z in Java. A lone if like you used is the same as if (x) y else Unit.
A code block in Java is a statement made up of a group of statements, but in Scala it's an expression made up of a group of expressions. A code block's result is the result of the last expression in the block. Therefore, the result of { o.a(); o.b(); o.c() } is whatever o.c() returned. You can make similar constructs with the comma operator in C/C++: (o.a(), o.b(), o.c()). Java doesn't really have anything like this.
The return keyword breaks the normal control flow in an expression, causing the current method to immediately return the given value. You can think of it kind of like throwing an exception, both because it's an exception to the normal control flow, and because (like the throw keyword) the resulting expression has type Nothing. The Nothing type is used to indicate an expression that never returns a value, and thus can essentially be ignored during type inference. Here's simple example showing that return has the result type of Nothing:
def f(x: Int): Int = {
val nothing: Nothing = { return x }
throw new RuntimeException("Can't reach here.")
}
Based on all that, we can look at your method and see what's going on:
def foo(list:List[Int], count:Int = 0): Int = {
// This block (started by the curly brace on the previous line
// is the top-level expression of this method, therefore its result
// will be used as the result/return value of this method.
if (list.isEmpty) {
return 1 // explicit return (yuck)
}
foo(list.tail, count + 1) // recursive call
count // last statement in block is the result
}
Now you should be able to see that count is being used as the result of your method, except in the case when you break the normal control flow by using return. You can see that the return is working because foo(List(), 5) returns 1. In contrast, foo(List(0), 5) returns 5 because it's using the result of the block, count, as the return value. You can see this clearly if you try it:
println(foo(List())) // prints 1 because list is empty
println(foo(List(), 5)) // prints 1 because list is empty
println(foo(List(0))) // prints 0 because count is 0 (default)
println(foo(List(0), 5)) // prints 5 because count is 5
You should restructure your method so that the value that the body is an expression, and the return value is just the result of that expression. It looks like you're trying to write a method that returns the number of items in the list. If that's the case, this is how I'd change it:
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) count
else foo(list.tail, count + 1)
}
When written this way, in the base case (list is empty) it returns the current item count, otherwise it returns the result of the recursive call on the list's tail with count+1.
If you really want it to always return 1 you can change it to if (list.isEmpty) 1 instead, and it will always return 1 because the base case will always return 1.
You're returning the value of count from the first call (that is, 0), not the value from the recursive call of foo.
To be more precise, in you code, you don't use the returned value of the recursive call to foo.
Here is how you can fix it:
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) {
1
} else {
foo(list.tail, count + 1)
}
}
This way, you get 1.
By the way, don't use return. It doesn't do always what you would expect.
In Scala, a function return implicitly the last value. You don't need to explicitly write return.
Your return works, just not the way you expect because you're ignoring its value. If you were to pass an empty list, you'd get 1 as you expect.
Because you're not passing an empty list, your original code works like this:
foo called with List of 3 elements and count 0 (call this recursion 1)
list is not empty, so we don't get into the block with return
we recursively enter foo, now with 2 elements and count 1 (recursion level 2)
list is not empty, so we don't get into the block with return
we recursively enter foo, now with 1 element and count 2 (recursion level 3)
list is not empty, so we don't get into the block with return
we now enter foo with no elements and count 3 (recursion level 4)
we enter the block with return and return 1
we're back to recursion level 3. The result of the call to foo from which we just came back in neither assigned nor returned, so it's ignored. We proceed to the next line and return count, which is the same value that was passed in, 2
the same thing happens on recursion levels 2 and 1 - we ignore the return value of foo and instead return the original count
the value of count on the recursion level 1 was 0, which is the end result
The fact that you do not have a return in front of foo(list.tail, count + 1) means that, after you return from the recursion, execution is falling through and returning count. Since 0 is passed as a default value for count, once you return from all of the recursed calls, your function is returning the original value of count.
You can see this happening if you add the following println to your code:
def foo(list:List[Int], count:Int = 0): Int = {
if (list.isEmpty) { // when this is true
return 1 // and we are about to return 1, the code goes to the next line
}
foo(list.tail, count + 1) // I know I do not use "return here" ...
println ("returned from foo " + count)
count
}
To fix this you should add a return in front of foo(list.tail.....).
you return count in your program which is a constant and is initialized with 0, so that is what you are returning at the top level of your recursion.

CoffeeScript variable scope

Is there any way to declare a variable at "file" scope (which will be closured by CS), without initializing it? A contrived example:
init = ->
counter = 0
inc = ->
counter += 1
This won't work, because you need to declare "counter". Adding "counter = 0" to the top would make it work, but the "= 0" is unnecessary. (A more realistic example would involve something that accesses the DOM on page load - there's no way to correctly initialize it in "file" scope.)
You'll have to define it on the outer scope, as you mentioned.
counter = null
init = ->
counter = 0
inc = ->
counter += 1
If your functions where part of an object you could use #counter, like this:
obj =
init: ->
#counter = 0
inc: ->
#counter += 1
You can say `var counter;` with backticks and that is passed literally through to the generated javascript.
When you have a problem like this, look at the generated javascript. It will be extremely clear that the variable scope is lexically limited to the function.
Looking at the generated javascript is often a good way to understand what the behavior of coffeescript constructs is.