I just started using Dart, and I haven't been able to find answers to these issues.
How do these three AS3 lines translate into Dart?
1) static var asset:*;
<<-- basically how do I handle * type
2) static function getAsset():* {
<<-- same issue, how do I handle * type?
3) static function loadImages(... images):void {
<< -- how do I handle ... argument?
I don't know ActionScript, but some quick Googling suggests that the asterisk means "can be any type". Since Dart is optionally typed, this means you can just leave the type off. I believe static works about the same in both languages.
So:
1) static var asset:*; becomes static var asset;
2) static function getAsset():* { becomes static getAsset() {
3) Dart doesn't support varargs, but this answer has a workaround.
Related
I was looking at a javascript code here:
https://www.w3schools.com/js/js_object_accessors.asp
Where they have shown using object accessors in javascript.
Being a superset of JS, I tried to use it in AS3 but I am getting compiler error
var p = {
get a() {
return 1;
}
};
trace(p.a);
I hope there must be some way to use it in AS3? Any ideas?
I already know about the longer syntax though which of course works:
var p = {
a:function() {
return 1;
}
};
trace(p.a());
AS3 syntax is very different from JavaScript. Variables have type (even if it's just Object). The AS3 reference shows an example of creating a dynamic object, which is really more of an associative array:
var obj:Object = {a:"foo", b:"bar"};
While AS3 does allow for some of the idiosyncracies of JavaScript, I strongly suggest that you treat it like a proper strongly-types programming language (more like C# or Java, than JavaScript) because this leads to cleaner code and better performance (in some cases).
If you know the properties of the object at design time, you should create classes with get/set properties and methods, because these will have much better performance than a dynamic object.
Adding dynamic functions to objects relies on using the Function type.
Yes there are getters and setters in AS3, but they are available in classes only.
Implementation:
package
{
public class ExampleGS
{
public function get a():int
{
return 1;
}
}
}
Usage:
var p:* = new ExampleGS;
trace(p.a); // 1
More info about getters and setters.
Is it possible to do something similar to this in Haxe?
private var _bindingsFiltered:Vector<String>;
_bindingsFiltered = new Vector<String>();
_controller_touched_binding.action = "meta_start";
What I would like to be able to do:
_bindingsFiltered[_controller_touched_binding.action] = "BUTTON_13";
trace(_bindingsFiltered["meta_start"]); //result: "BUTTON_13"
I want to be able to override a specific index too (still accessed via a string), with a new value, rather than keep pushing new content to the end of the vector. I have been using 'openfl.utils.Object' to cheat for now but I am looking for a more reliable approach for the long run.
Is there a way to do this in Haxe?
If not, what are my options?
I would also be interested in a solution for this in AS3, if there is one (avoiding the Array class).
My goal is to find a method that I can use in both languages seamlessly (next-to-none, differences).
Vector's cannot be indexed by string in Haxe. A vector is an array with a fixed size. This is the Haxe manual on that subject.
Instead of vectors, you can use a Map.
class Test {
private var vector:Map<String, String> = new Map<String, String>();
public function new() {
var str = 'haxe';
vector[str] = "is great";
trace(vector[str]);
}
static function main() {
new Test();
}
}
https://try.haxe.org/#F74Ba
I think you could do this using flash.utils.Dictionary:
ActionScript
import flash.utils.Dictionary;
...
var _bindingsFiltered:Dictionary = new Dictionary ();
_bindingsFiltered[_controller_touched_binding.action] = "BUTTON_13";
trace(_bindingsFiltered["meta_start"]); //result: "BUTTON_13"
Haxe
import openfl.utils.Dictionary;
...
var _bindingsFiltered = new Dictionary<String, String> ();
_bindingsFiltered[_controller_touched_binding.action] = "BUTTON_13";
trace(_bindingsFiltered["meta_start"]); //result: "BUTTON_13"
First, do you really want an array / vector / list, or do you really want a hashmap of key / value pairs? How are you using the collection? Why do you want String keys? And related, is this mostly about access symantics (you want to type it this way), or are the runtime reasons you'd want to use strings (serialization / etc)?
From what you've described, it sounds like what you really want is an Object like the ones in AS3/JS/ECMAScript, with square-bracket access symantics -- obj[key]
Yes, you can do that in Haxe. The openfl.utils.Object class is a helper to do exactly this, using Dynamic objects and reflection. It should compile to exactly what you want on all Haxe targets.
In any case, if you'd like to feel like you're not bound to OpenFL, no problem. Copy the openfl/utils/Object.hx file and place it anywhere you like in your project's class path (and update the package statement).
There's nothing particularly OpenFL-ish about that code. It's pure Haxe code with no dependencies. It provides array access with String keys, as well as toString, toLocaleString, propertyIsEnumerable, iterator, isPrototypeOf, and hasOwnProperty functions (which ECMA-folk are used to.)
The transition from AS3/JS to Haxe is a little weird, especially when it comes to dynamic objects, and I've been meaning to blog more about it. ;) Good luck!
ETA: In truth, you probably want to get away from Dynamic/Reflection, and embrace a more type-strict approach. AS3/JS devs don't understand this at first, but it is where the benefits of Haxe come from. If you don't then your Haxe experience is likely to be unplesant.
Short answer: yes, you can.
abstract MyVector<T>(Vector<T>) {
public function new(l:Int) this = new Vector<T>(l);
#:op([]) public function set<K:T>(s:String, v:K) {
switch (s) {
case "FIRST": this[0] = v;
case "SECOND": this[1] = v;
default: return;
}
}
#:op([]) public function get(s:String) {
switch (s) {
case "FIRST": return this[0];
case "SECOND": return this[1];
default: return cast 0;
}
}
}
var mv = new MyVector<String>(2);
mv["SECOND"] = "Second";
trace(mv["SECOND"]); // outputs Second
You can inline get and set methods if you want.
I am porting a library from AS3 to Haxe and I need to make a method accepting variable number of arguments. Target is a *.swc library.
My question relates to this one but none of the suggested solutions outputs a method with the required signature: someMethod(...params)
Instead, the produced method is: someMethod(params:*=null)
This won't compile in AS3 projects using the library and the used code is beyond my reach. Is there a way to do this, perhaps macros?
Well, that's a great question. And, it turns out there is a way to do it!
Basically, __arguments__ is a special identifier on the Flash target, mostly used to access the special local variable arguments. But it can also be used in the method signature, in which case it changes the output from test(args: *) to test(...__arguments__).
A quick example (live on Try Haxe):
class Test {
static function test(__arguments__:Array<Int>)
{
return 'arguments were: ${__arguments__.join(", ")}';
}
static function main():Void
{
// the haxe typed way
trace(test([1]));
trace(test([1,2]));
trace(test([1,2,3]));
// using varargs within haxe code as well
// actually, just `var testm:Dynamic = test` would have worked, but let's not add more hacks here
var testm = Reflect.makeVarArgs(cast test); // cast needed because Array<Int> != Array<Dynamic>
trace(testm([1]));
trace(testm([1,2]));
trace(testm([1,2,3]));
}
}
Most importantly, this generates the following:
static protected function test(...__arguments__) : String {
return "arguments were: " + __arguments__.join(", ");
}
I am registering listeners from JS to NPAPI plugin.
In order not to register same listener multiple times I need a way to compare passed NPVariant object to those already in the list.
This is how I'm registering listeners from JS :
PluginObject.registerListener("event", listener);
and then in plugin source :
for (l=head; l!=NULL; l=l->next) {
// somehow compare the listeners
// l->listener holds NPVariant object
if (l->listener-> ??? == new_lle->listener-> ???)
{
found = 1;
DBG("listener is a duplicate, not adding.");
NPN_MemFree(new_lle->listener);
free(new_lle);
break;
}
}
when you're talking about a javascript function the NPVariant is just an NPObject.
typedef struct _NPVariant {
NPVariantType type;
union {
bool boolValue;
int32_t intValue;
double_t doubleValue;
NPString stringValue;
NPObject *objectValue;
} value;
} NPVariant;
compare the val.type and val.objectValue. This will usually work, but if it doesn't there isn't another way so you're still better off trying it. I guess one other possibility would be to create a javascript function to compare them, inject it with NPN_Evaluate and call it with the two objects.
I don't think you can rely on objectValue. For instance if you do the following:
foo={};
bar=foo;
x={};
x.f=foo; x.b=bar;
Now, if you call NPN_Enumerate and pass x as the NPObject, you get two identifiers. Calling GetProperty for each of these returns NPVariants, but the value of variant->value.objectValue will be different for each, and different again in subsequent calls to NPN_Enumerate.
taxilian: is there significant overhead in calling NPN_Invoke with the two NPObjects, just to test for equality? This also involves some calls to GetProperty and the creation of identifiers and calling the NPVARIANT macros to test the results, etc.. I am wondering just how much logic I should be injecting and evaluating in Javascript.. this code injection seems to come up as a solution again and again. Is it costly?
Actionscript 3.0 (and I assume Javascript and ECMAScript in general) lacks pass-by-reference for native types like ints. As a result I'm finding getting values back from a function really clunky. What's the normal pattern to work around this?
For example, is there a clean way to implement swap( intA, intB ) in Actionscript?
I Believe the best you can do is pass a container object as an argument to a function and change the values of some properties in that object:
function swapAB(aValuesContainer:Object):void
{
if (!(aValuesContainer.hasOwnProperty("a") && aValuesContainer.hasOwnProperty("b")))
throw new ArgumentError("aValuesContainer must have properties a and b");
var tempValue:int = aValuesContainer["a"];
aValuesContainer["a"] = aValuesContainer["b"];
aValuesContainer["b"] = tempValue;
}
var ints:Object = {a:13, b:25};
swapAB(ints);
I suppose an alternative would be somewhere defining this sort of thing ...
public class Reference {
public var value:*;
}
Then use functions that take some number of Reference arguments to act as "pointers" if you're really just looking for "out" parameters and either initialize them on the way in or not and your swap would become:
function swap(Reference a, Reference b) {
var tmp:* = a.value;
a.value = b.value;
b.value = tmp;
}
And you could always go nuts and define specific IntReference, StringReference, etc.
This is nitpicking, but int, String, Number and the others are passed by reference, it's just that they are immutable. Of course, the effect is the same as if they were passed by value.
You could also use a wrapper instead of int:
public class Integer
{
public var value:int;
public function Integer(value:int)
{
this.value = value;
}
}
Of course, this would be more useful if you could use operator overloading...
Just look at some Java code. Java has had the convention that reference types are passed by reference and primitive types are passed by value since it's inception. It's a very good model in many ways.
But talking about swap, the best and easiest way to do a swap in Java/AS3 is with the following three lines:
var temp:int = array[i];
array[j] = array[i];
array[i] = temp;
Theres not really any reason to use a function to do a simple swap, when you can do it faster with just 3 lines.
It is annoying. But if you use different idioms than in e.g. C#, you can get reasonable-quality results. If you need to pass a lot of parameters back and forth, pass in an object filled with the needed data, and change the object's parameters when you return. The Object class is for just this sort of thing.
If you just need to return a bunch of data, return an Object. This is more in keeping with the ECMAScript style than pass-by-ref semantics.
Destructuring assignment (e.g. [a,b] = [b,a]) isn't defined in the ECMA-262 3 specification, and it's not implemented in JavaScript 1.5, which is the version equivalent to the JScript implementation in IE. I've seen this syntax in the AS4 specifications preview though, and I believe it's part of JavaScript 1.7.
If ActionScript works like Javascript,
[a,b] = [b,a]