Pass arguments from an array to an Actionscript method with ...(rest) argument - actionscript

my question is the Flex transposition of this question :
Can I pass an array as arguments to a method with variable arguments in Java?
That is, I have an Array in some Actionscript code and i need to pass every object indexed in the array into a method method(...arguments).
Some code to make it clear:
private function mainMethod():void{
var myArray:Array = new Array("1", "2", "3");
// Call calledMethod and give it "1", "2" and "3" as arguments
}
private function calledMethod(...arguments):void{
for each (argument:Object in arguments)
trace(argument);
}
Is there some way to do what the comment suggests?

It's possible by going through the Function object itself. Calling apply() on it will work:
private function mainMethod():void
{
var myArray:Array = new Array("1", "2", "3");
// call calledMethod() and pass each object in myArray individually
// and not as an array
calledMethod.apply( this, myArray );
}
private function calledMethod( ... args ):void
{
trace( args.length ); // traces 3
}
For more info, check out http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Function.html#apply()

It is kind of hard for the compiler to guess what you want, do you want to pass one argument of type Array or do you want to pass the elements of that array. The compiler goes for assumption one.

The ...args is one Object the method awaits for. You can pass multiple elements or (in this case) one array with the parameters.
Example:
function mainMethod():void
{
//Passing parameters as one object
calledMethod([1, 2, 3]);
//Passing parameters separately
calledMethod(1, 2, 3);
}
function calledMethod(...args):void
{
for each (var argument in args)
{
trace(argument);
}
}
mainMethod();
Hope it helps,
Rob

Related

Create a const array with values at certain indices

I need to provide a const array to a property in my class. I need certain indices to have a value in the array. How would I create such an array ... it's important that the array is a const because I'm assigning a value to a non null property in my class.
Assigning to non-nullable properties is possible (once) at run time if you mark them with the late keyword. Optionally, your property may be final, too.
class C {
late final List<int> myList;
C() {
myList = [1, 2, 4];
}
You could also use an unmodifiable list.

Why can I ref return an item of an array that only exists inside the method?

I was trying out the new ref returns of C#7.
I am able to compile and build this:
public ref string MisUseRefReturn(int index)
{
string[] array = { "a", "b", "c", "d" };
return ref array[index]; //array[2] gets out of scope when this method returns!
}
According to MSDN: The return value cannot be a local variable in the method that returns it; it must have a scope that is outside the method that returns it. It can be an instance or static field of a class, or it can be an argument passed to the method. Attempting to return a local variable generates compiler error CS8168, "Cannot return local 'obj' by reference because it is not a ref local."
So why does this compile? When I execute this method, the returned reference shows the correct string.
Think of the array element as if it were an instance field of the array. Imagine your array were:
public class FourElementStringArray
{
public string element0;
public string element1;
public string element2;
public string element3;
}
Then your code is equivalent to:
public ref string MisUseRefReturn(int index)
{
var array = new FourElementStringArray
{
element0 = "a",
element1 = "b",
element2 = "c",
element3 = "d"
};
// TODO: do this dynamically based on index
return ref array.element2;
}
That abides by the piece of documentation you quoted:
It can be an instance or static field of a class, or it can be an argument passed to the method.
Is this useful? Not particularly. Is it dangerous? No.
The latter part is the important point. Using the regular array, if the caller assigns a new value, that's fine - it's replacing an element of an array, on the heap. The array can't be garbage collected while the array element reference exists; all is basically okay.
What the compiler rule is trying to prevent is the use of a returned reference to somewhere on the stack which has then been popped by the method returning. The array itself isn't on the stack, so there's no problem here.
See the description here:
Returning a local int variable instead of an array is not possible.
int is a value type, and thus the variable gets out of scope at the
end of the method, and thus a reference to it cannot be returned.
That’s different with an array. An array is a reference type, and the
array is allocated on the heap. An int within the array can be
returned with the ref keyword.
You could not return an integer value directly as it is a value type. An array element can be returned because it is a reference type. The MSDN statement is correct.
... of an array that only exists inside the method
The returned reference persists the array beyond the method call.

What is a difference in lifecycle between 'entity' object and function object in javascript?

Why does this code snippet outputs 5 (as expected due to scope chain) ?
let arr = []
var firstFunc;
for(var i = 0; i < 5; i++) {
var iterFunc = function () {
return function() {
return i
}
}
arr.push(iterFunc())
}
console.log(arr[0]())
but this outputs {a: 0}:
let arr = []
var firstFunc;
for(var i = 0; i < 5; i++) {
var iterFunc = function () {
return {
a: i
}
}
arr.push(iterFunc())
}
console.log(arr[0])
what memory allocation logic occurs under the hood ? Why 'entity' object persists current value in contrast to closure ?
Returning i or {a: i} here doesn't matter.
The important thing is that in first example, iterFunc() returns a function and is inside that (not yet invoked) function where i or {a: i} is evaluated.
Having i is always holding a scalar (immutable) value, that value is what you get in place. (If i would have been an object, a reference to that object would be returned and if, its contents mutated, you could see that mutations).
Being immutable value, you will get that value. But, as you know, i value changes in time, so the key thing here is WHEN that value is read.
If you see at your first example, in console.log(...) statement, you are intentionally invoking it as the function you know it is (the unnamed function returned by iterFunc()) and, that time, i is holding a value of 5.
If, in your first example, you just change following line:
arr.push(iterFunc())
by
arr.push(iterFunc()())
...and, of course:
console.log(arr[0]())
by
console.log(arr[0]) // Same of your second example.
You will realize that output will be the same in both cases (0).

Swift: Dictionary passed as parameter is always empty

I want to fill Dictionary via a method of which dictionary is one of the parameter. When I add a value to key, say 15, it always return 0 count when I try to access it second time with same key i.e. 15. Here's the code.
private static var showWidgetMap = Dictionary<Int, [BaseWidget]>()
private static var hideWidgetMap = Dictionary<Int, [BaseWidget]>()
static func initHandler()
{
let cloudWidget = CloudWidget()
cloudWidget.setType(CreatorConstants.CLOUD)
let property1 = [CreatorConstants.IMG_SRC: "cloud1", CreatorConstants.X_COORD: "100", CreatorConstants.Y_COORD: "450"]
cloudWidget.setPropery(property1)
addWidgetInLocalTimeList(15, widget: cloudWidget, delete: false)
let emojiWidget = CloudWidget()
emojiWidget.setType(CreatorConstants.EMOTICON)
let property2 = [CreatorConstants.IMG_SRC: "1", CreatorConstants.X_COORD: "100", CreatorConstants.Y_COORD: "550"]
emojiWidget.setPropery(property2)
addWidgetInLocalTimeList(15, widget: emojiWidget, delete: false)}
static func addWidgetInLocalTimeList(time_milisec: Int, widget: BaseWidget, delete: Bool)
{
if(delete)
{
checkAndAdd(hideWidgetMap, key: time_milisec, widget: widget);
}
else
{
checkAndAdd(showWidgetMap, key: time_milisec, widget: widget);
}
}
private static func checkAndAdd(var map: Dictionary<Int, [BaseWidget]>, key: Int, widget: BaseWidget)
{
print("map count is")
print(map.count)
if var val = map[key]
{
val.append(widget);
}
else
{
var temp: [BaseWidget] = [];
temp.append(widget);
map[key] = temp
print(map.count)
}
}
print(map.count) always returns 0.
You need to understand the difference between value types and reference types.
Value type variables are just values. For example, an array is a value type. It is just a value of "a bunch of stuff" *. On the other hand, reference types are references to values. For example, when you create a UIViewController, that variable actually stores a reference to the actual UIviewController *.
Don't really understand? Then it's analogy time! The variables and constants you create are children. The things you put in variables and constants are balloons.
There are two types of children, one type (value types) likes to hold balloons directly in their hands. The other type (reference types) likes to hold balloons using a string **.
When you pass a child to a method, depending on what type of child he is, different things will happen:
A value type child holds the balloon in his hands, so tightly that the method parameter can't take it away from him. So what can it do? It creates a copy of it! It then takes the copy to the method implementation let it do its thing.
A reference type, however, holds balloons using a string. The method parameter will tie another string to the balloon so the implementation can access it using the string. As a result, no copies of the balloon are created.
So what are you doing wrong here?
Since swift dictionaries are value types, when you pass a dictionary to a method, as I said above, it creates a copy! In the implementation, you are actually editing a copy of the dictionary, not the original one. That's why the original dictionary still has a count of 0.
What can you do?
Instead of marking the parameter with var, which is a very bad practice btw, you mark it with inout!
private static func checkAndAdd(inout map: Dictionary<Int, [BaseWidget]>, key: Int, widget: BaseWidget)
The inout modifier basically says
Hey parameter, next time you see a value type, just get a string and tie it to the balloon that the child is holding.
There is also another thing that you should do. That is you should change the way you call your method.
Instead of
checkAndAdd(showWidgetMap, key: time_milisec, widget: widget)
You write
checkAndAdd(&showWidgetMap, key: time_milisec, widget: widget)
And magically, it works!
Conclusion: Parameters are dumb. They aren't even smart enough to know when to tie a string. Be careful when you work with value types.
Footnotes * Assume it is not nil
** Not the String type, but an actual string.

Access Rhino's native JSON.Stringify from Java

Is there a cleaner way to get the JSON representation of a Javascript object than with the following kludge?
System.out.println(((ScriptableObject) scope).callMethod(
cx, (Scriptable) scope.get("JSON", scope),
"stringify", new Object[]{jsObject}));
Where jsObject is the ScriptableObject I want to stringify.
Note that Hannes has now addressed this in Rhino. So the usage simplifies to this:
import org.mozilla.javascript.NativeJSON;
// ...
Object json = NativeJSON.stringify(cx, scope, jsObject, null, null);
The org.mozilla.javascript.NativeJSON class should be public in the Rhino 1.7R4 release.
I was able to get this working within an Apache Ant target using the NativeJSON class.
importPackage(org.mozilla.javascript);
var context = Context.enter();
var json = '{}';
// The call to parse required a reviver function that should return the
// state of a key/value pair.
var reviver = function(key, value) { return value; };
var scope = context.initStandardObjects();
var object = NativeJSON.parse(context, scope, json, reviver);
// The call to stringify does not require the replacer or space parameters.
// The replacer is a function that takes a key/value pair and returns the
// new value or an array of keys from the input JSON to stringify. The space
// parameter is the indentation characters or length.
json = NativeJSON.stringify(context, scope, config, null, 4);
http://mozilla.github.io/rhino/javadoc/org/mozilla/javascript/NativeJSON.html
https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/NativeJSON.java

Resources