I tried custom functions:
if(Input.GetMouseButtonUp(0)) {
AcceptInput = true;
targetScript.enabled = false;
changeSprite ();
}
function changeSprite () {
//other stuff
}
It had an error:
Assets/Scripts/Button.js(70,1): BCE0070: Definition of 'Button.changeSprite()'
depends on 'Button.changeSprite()' whose type could not be resolved because of
a cycle. Explicitly declare the type of either one to break the cycle.
I don't get what's wrong with the function. can any body help me?
As the error message tells us, you can try defining the return type of the function, in this case "void";
function changeSprite(): void {
//other stuff
}
Related
I might be trying to achieve the impossible but here goes.
I want to define a function ( function A ) which will return the same type as a new function passed into the parameter of function A.
e.g.
export function test<T> ( arg:Function ):T {
return arg;
}
function a():string {
return 'a';
}
function b():number {
return 0;
}
let aVal:string = test(a);
let bVal:number = test(b);
Obviously this will allow me to strongly type my responses for some compile time errors.
Does anyone have any ideas or know if I'm just dreaming.
** Note: Code slapped together for demo **
Cheers
How about this?
function test<T>(arg: () => T): T {
return arg();
}
function a(): string {
return 'a';
}
function b(): number {
return 0;
}
let aVal: string = test(a);
let bVal: number = test(b);
Instead of using the Function interface we defined arg as a function that takes no arguments and returns something of type T. The actual type T then can be defined by the function that's passed in.
Is there a way to declare a function such that I don't care about return value? For example I have this Array extension:
extension Array {
func forEach(function: (element: T) -> ()) {
for e in self {
function(element: e)
}
}
}
Now I want to do:
textFields.forEach{$0.resignFirstResponder()}
And I can't because the function is declared to return Void.
This would fix it:
textFields.forEach{$0.resignFirstResponder();return}
But is there a generic way to declare the function such that I can return any value or Void?
Thanks!
If you add a second generic parameter with no constraints, and type the function to return it, then any return value would be accepted:
extension Array {
func forEach<U>(function: (Element) -> U) {
for e in self {
function(e)
}
}
}
func f(i: Int)->Int {
return i * 2
}
func g(i: Int) -> Double {
return Double(0.0)
}
func h(i: Int) {
println("\(i)")
}
let a = [1,2,3]
a.forEach(g) // U will be an Int
a.forEach(f) // U will be a Double
a.forEach(h) // U will be a ()
However, I’d strongly suggest you not do this and use for…in instead.
The only purpose of running a function on an array but not using the return value is for side-effects. When writing in a more imperative style and using side-effects and external state (as opposed to a more declarative functional style) it’s much better to use for…in as a signal that this is what you’re doing.
There are also unpleasant gotchas involved in constructing your own pseudo-control structures. For example, think about this:
// function that does something side-effecty, but
// if it achieves some goal, exist early
func someFunc(a: [Int]) {
a.forEach { i -> () in
// goal achieved early,
// return from func
return
}
assert(false)
}
This is a common practice – cut out of a function early if some goal (or failure) is achieved. But with the forEach structure this is a bit misleading. It looks like a regular loop, but it’s actually a closure, and the return returns from that closure, ready for forEach to call the next one (essentially, it behaves like a continue in a regular loop).
Use map():
let textFields : [UITextField] = [] // or whatever
textFields.map{$0.resignFirstResponder()}
This way you don't have to specify the return type, and you don't need to reinvent map with your forEach extension.
I am new to ActionScripting but I have done some Java. I was told they are kinda similar. I am coding my swf file with some AS3 integrated.
function init():void{
// do something
}
function init(var string:String):String{
// do something else
}
is this not allowed in AS? If not, is there another way of handling it besides?
Thanks in advance.
Yes, you can override functions. But the example you gave is not overriding - it's overloading. For overriding a function, you basically just create a function with the same signature and everything in a subclass and add the word "override" right before it.
You can't directly overload a function though. If you want a variable number of parameters, you have to use optional parameters instead. Like this:
function init(str:String = null):String
{
if (str == null)
{
// do one thing
return null;
}
else
{
// do another thing
return "someString";
}
}
And that's about the best you're going to be able to do in AS3. The inability to overload functions, at least strictly speaking, is a fairly common complaint and obvious shortcoming of the language.
Do you mean method overloading? Actionscript, sadly, does not support this.
To get around it, you can use default parameters, or just make your parameters a bit less constraining. This answer has some details on that.
You could try this:
function init(var string:String = "Default value"):String{
// do something
}
Actionscript does not support method overloading. However, based on the answer to this question you have other options.
If you just want to be able to accept any type, you can use * to
allow any type:
function someFunction( xx:*, yy:*, flag:Boolean = true )
{
if (xx is Number) {
...do stuff...
} else if (xx is String) {
...do stuff...
} else {
...do stuff...
}
}
If you have a large number of various parameters where order is
unimportant, use an options object:
function someFunction( options:Object )
{
if (options.foo) doFoo();
if (options.bar) doBar();
baz = options.baz || 15;
...etc...
}
If you have a variable number of parameters, you can use the ...
(rest) parameter:
function someFunction( ... args)
{
switch (args.length)
{
case 2:
arr = args[0];
someBool = args[1];
xx = arr[0];
yy = arr[1];
break;
case 3:
xx = args[0];
yy = args[1];
someBool = args[2];
break;
default:
throw ...whatever...
}
...do more stuff...
}
For cases where you need to call a common function to a number of
classes, you should specify the interface common to each class:
function foo( bar:IBazable, flag:Boolean )
{
...do stuff...
baz = bar.baz()
...do more stuff...
}
I've come across some syntax I'm not familiar with and am unable to find any reference online.
In the below as3 function is the if statement calling the 'sendTrackingEvent' function? And in the 'sendTrackingEvent' function is the if statement sending the tracking event?
function trackingHandler(page: String)
{
if (! sendTrackingEvent(EID,"Document View",page))
{
fl_SavePreferences_5(EID + ",Document View," + page);
}
}
function sendTrackingEvent(category:String, action:String, label:String):Boolean
{
if (tracker.trackEvent(category,action,label))
{
return true;
}
else
{
return false;
}
}
Thanks in advance for any help. I'm still learning.
sendTrackingEvent is a function that returns true or false
the first if statement is evaluating the RESPONSE (return value) of that function. So if sendTrackingEvent(EID,"Document View",page) returns false, then your if statement will run (since the ! means NOT true).
Same for the second if statement inside of sendTrackingEvent.
It's evaluating the return value of tracker.trackEvent(category,action,label).
That function (sendTrackingEvent) could actually be simplified to this:
function sendTrackingEvent(category:String, action:String, label:String):Boolean
{
return tracker.trackEvent(category,action,label);
}
And for that matter you don't even need the sendTrackingEvent function, as you could just do this:
function trackingHandler(page: String)
{
if (! tracker.trackEvent(EID,"Document View",page))
{
fl_SavePreferences_5(EID + ",Document View," + page);
}
}
Why do you think the code below does not work?
What would you change/add to make it work?
Any help is appreciated..
function TraceIt(message:String, num:int)
{
trace(message, num);
}
function aa(f:Function, ...args):void
{
bb(f, args);
}
aa(TraceIt, "test", 1);
var func:Function = null;
var argum:Array = null;
function bb(f:Function, ...args):void
{
func = f;
argum = args;
exec();
}
function exec()
{
func.apply(null, argum);
}
I get an ArgumentError (Error #1063):
Argument count mismatch on test_fla::MainTimeline/TraceIt(). Expected 2, got 1.
..so, the passed parameter (argum) fails to provide all passed arguments..
..Please keep the function structure (traffic) intact.. I need a solution using the same functions in the same order.. I have to pass the args to a variable and use them in the exec() method above..
regards
Ok, here is the solution.. after breaking my head : )
function TraceIt(message:String, num:int)
{
trace(message, num);
}
function aa(f:Function=null, ...args):void
{
var newArgs:Array = args as Array;
newArgs.unshift(f);
bb.apply(null, newArgs);
}
aa(TraceIt, "test", 1);
var func:Function = null;
var argum:*;
function bb(f:Function=null, ...args):void
{
func = f;
argum = args as Array;
exec();
}
function exec():void
{
if (func == null) { return; }
func.apply(this, argum);
}
This way, you can pass arguments as variables to a different function and execute them..
Thanks to everyone taking the time to help...
When TraceIt() eventually gets called, it's being called with 1 Array parameter, not a String and int parameters.
You could change TraceIt() to:
function TraceIt(args:Array)
{
trace(args[0], args[1]);
}
Or you could change exec() to:
function exec()
{
func.apply(null, argum[0].toString().split(","));
}
...as it appears when you pass "test", 1, you end up with array whose first value is "test,1". This solution doesn't work beyond the trivial case, though.
Change your bb function to look like this:
function bb(f:Function, args:Array):void
{
func = f;
argum = args;
exec();
}
As you have it now, it accepts a variable number of arguments, but you are passing in an array(of the arguments) from aa.