void main() {
doStuff("foo");
}
void doStuff(String myString) {
String myString = "bar";
print(myString); //prints "bar"
}
The above executed in the dartpad yields "bar", the local variable is used instead of the parameter in the last line. If instead of an argument myString were an instance variable of a class, we could access the original myString with this.myString to print "foo". Is there an analogous way to access an argument to a function after a homonymous local variable has been declared?
No.
For local variables, you are expected to be able to rename any local variable which shadows the variable you want to access, so there is no scope override.
For instance variables, you can use this.x, for static variables you can use ClassName.x, for an imported top-level name, you can import the library with a fresh prefix name and access it as prefix.x, and for public top-level variable of the current library, you can, if all else fails, import that library with a prefix too and use:
// library foo.dart
import "foo.dart" as toplevel; // <- this library!
// ...
int foo = 42;
// ...
int method(int foo) {
return toplevel.foo + foo; // Wohoo
For local variables, you just have to rename the one that's shadowing the variable you want. Since nobody can see local variables from outside the method, no-one will ever know.
Related
I'm trying to access the variable reference by its name given in a String type.
class A {
B b = B();
}
class B {
String c = "apple";
}
void main() {
A a = A();
print(a.b.c); // prints apple
/// now if I get this ref as a string eg:
final ref = "a.b.c";
/// want to access the same variable with its reference
print(<ref>); <------
}
Need this to create a dynamic functionality.
Already tried with the creation of the toJson() method. but we have to access more nested classes and update all the classes with toJson method.
please help if there is any other solution.
void main() {
List a = ["aa", "bbb", "ccccc"];
Iterable b = a.iterator;
while (b.moveNext()) {
/*The method 'moveNext' isn't defined for the type 'Iterable'.
Try correcting the name to the name of an existing method,
or defining a method named 'moveNext'.dartundefined_method
*/
print(b.current);
/* The getter 'current' isn't defined for the type 'Iterable<dynamic>'.
Try importing the library that defines 'current',
correcting the name to the name of an existing getter,
or defining a getter or field named 'current'.dartundefined_getter
*/
}
}
Multiple problems. E.g. a.iterator does not return a Iterable but instead Iterator. Also, you should not write List since that means List<dynamic> in Dart which means you are loosing type information.
The easiest way is to just use final or var and let Dart automatically use the most precise type (e.g. List<String>):
void main() {
final a = ["aa", "bbb", "ccccc"];
final b = a.iterator;
while (b.moveNext()) {
print(b.current);
}
}
Why is it an error in Dart to try to set a class's static variable in the global space?
Example:
class Name {
static String? firstName;
}
Name.firstName = 'Mike'; // Error
void main() {
Name.firstName = 'Mike'; // Ok
}
It's not a big deal. I just came across this and then couldn't find an explanation for why it is. Where in the documentation does it describe the nuance here?
[UPDATE]
The actual error thrown is, among others: "Variables must be declared using the keywords 'const', 'final', 'var', or a type name."
You actually can execute statements outside of a function, but they have to be statements that declare scoped variables. Maybe these aren't technically statements, but just variable instantiations.
class Name {
static String? staticName;
String? lastName;
}
final me = Name(); // Ok
me.lastName = 'Jones'; // Error
void main() {
Name.staticName = 'Mike'; // Ok
final you = Name(); // Ok
you.lastName = 'Smith'; // Ok
}
Without the variable scoping, the compiler thinks I must be defining a function and it gets confused when there is no parameter list or function body.
It makes sense that statements are restricted to variable instantiations of function definitions only, so that there won't be side effects related to execution order to other importers of the file, as per #jamesdlin answer.
Name.firstName = 'Mike'; is a statement. You can't execute arbitrary statements in the global namespace. In what order would they execute? Suppose you had:
name.dart:
class Name {
static String? firstName;
}
and mike.dart:
import 'name.dart';
Name.firstName = 'Mike';
and spike.dart:
import 'name.dart';
Name.firstName = 'Spike';
and finally:
import 'name.dart';
import 'mike.dart';
import 'spike.dart';
void main() {
print(Name.firstName);
}
What should happen? Should it be illegal for multiple libraries to assign to Name.firstName? Should the last one imported win? If so, then suddenly importing a library would have side-effects, and order would matter. What would happen if an imported library imports other libraries with side-effects?
It's a huge headache that is completely unnecessary since you could have just done:
class Name {
static String? firstName = 'Mike';
}
in the first place.
I have jenkinsfile with defined Globals varible for timeout
class Globals {
static String TEST_TIMEOUT = ""
}
I am using functions from shared library
I am using the global variable to set a timeout for function. Since the shared library used by other projects that doesn't define the Globals variable I defined environment variable in the function file to be used as default value for time out.
env.TESTS_TIME_OUT="10080"
Then in function I want to check if Globals variable exists, I want to use the value as time out, if not the to use the default value.
if(Globals.TEST_TIMEOUT){
env.TESTS_TIME_OUT= "${Globals.TEST_TIMEOUT}"
}
timeout(time: "${env.TESTS_TIME_OUT}", unit: 'MINUTES') {
.
.
.
}
I`ve done it before with success on env parameters, but this time I am getting an error
No such field found: field java.lang.Class TEST_TIMEOUT
Any ideas how to solve this ? Or Any other way to check if Globals variable exists ?
Thank you
You can catch groovy.lang.MissingPropertyException which will be thrown if either Globals or Globals.TEST_TIMEOUT does not exist:
try {
env.TESTS_TIME_OUT = Globals.TEST_TIMEOUT
}
catch( groovy.lang.MissingPropertyException e ) {
env.TESTS_TIME_OUT = "10080"
}
You could even move this pattern into a generic function...
def getPropOrDefault( Closure c, def defaultVal ) {
try {
return c()
}
catch( groovy.lang.MissingPropertyException e ) {
return defaultVal
}
}
... which could be called like this:
env.TESTS_TIME_OUT = getPropOrDefault({ Globals.TEST_TIMEOUT }, '10080')
This could be useful if there are many different globals that you want to treat similar. Safes you from writing many try/catch blocks.
The closure is required to make sure that the expression Globals.TEST_TIMEOUT will be evaluated inside of the try/catch block of getPropOrDefault instead of before the function call.
When I run this java code, i am able to get the values of variables define outside the function, but i am unable to get the values of variable define inside the function. how to access these variable values?
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Scriptable;
public class JSFunctionTest {
public static void main(String args[]) {
String code = "var name='nc',global_a = 'jill'; " + "\n"+
"function myfunc(b) { " + "\n"+
"var local_a = 1;" + "\n"+
"global_a = 'jack';" + "\n"+
" return b;" + "\n"+
"}";
Context context = Context.enter();
context.setGeneratingDebug(true);
context.setOptimizationLevel(-1);
Scriptable scope = context.initStandardObjects();
context.evaluateString(scope, code, "code", 1, null);
//getting values of varables
System.out.println("var name:"+scope.get("name", scope));
System.out.println("var global_a:"+scope.get("global_a", scope));
System.out.println("var local_a:"+scope.get("local_a", scope));//not found becase function wasnt run
//calling the function.
Object fObj = scope.get("myfunc", scope);
if (!(fObj instanceof Function)) {
System.out.println("myfunc is undefined or not a function.");
} else {
Object functionArgs[] = { "nc" };
Function f = (Function)fObj;
Object r = f.call(context, scope, scope, functionArgs);
String report = "myfunc('nc') = " + Context.toString(r);
//trying to access global and local a after calling function
System.out.println("var global_a:"+scope.get("global_a", scope));//values is changed, because this is defined out side the function.
System.out.println("var local_a:"+scope.get("local_a", scope));// still not found,after running the function.
System.out.println(report);
}
}
}
I was able to resolve this, by implementing a debugger using the debug API in Rhino.
Implement your own debugger and debugframe classes.
Hook them to your context using setDebugger() method
in the DebugFrame class, I have implemented. cache the scope object in the onEnter method.
in the onLineChange method, you can get the local variables using ScriptableObject.getProperty() passing the cache scope object and giving the names
In ECMAScript, functions create their own scope. Outside the global scope, it's the only way to create new ones. See Rhino Scopes and Contexts for an example similar to yours.
The thing is that ECMAScript is a dynamic language (especially when optimization level is set to interpreted mode). This means the interpreter does not know in advance what it will encounter. The function's scope is only created/evaluated when the code is actually executed. So you can't evaluate a piece of code and query for variables inside a scope that isn't executed.
The question is why would you want to do that in practice? For debugging, you can step into the code and inspect the scopes, you should be able to see it.