I have a code that has complex function calls stack. I would like to refactor it which avoids calling function too deep. Currently, the function call stack looks like this:
function A () {
a = 1
return B(a)
}
function B (b) {
return C(b+1)
}
function C (c) {
return D(c+1)
}
function D (d) {
return (d+1)
}
This is what I would like to re-write look like:
function A () {
a = 1
b = B(a) // b -> 2
c = C(b) // c -> 3
d = D(c) // d -> 4
}
I'm not sure which one is a better solution. I feel like that calling B, C, D at the same level could make the code flow easier to be traced and easier to understand when the implementation in B, C, D getting more complicated. Is there any opinion of both benefits or drawbacks?
Thanks!
Related
i have the following question:
var a = 1;
function b(){
a = 10;
return;
function a(){}
}
// console.log("a equals to ",a); -> 1
b();
// console.log("now a equals to ", a) -> 1
so in this function i get 1 in both cases. Can somebody explain me why?
if i use const a = function() and of course put it before the return, the global variable will change to 10. Though now it does not.
My assumption is that this is not happening, because inside the function b, the variable a is a function. So the attempt a=10 will not work. But when i console.log(a) inside the b function the a is 10 and not a function.. Arghh!
Thanks in advance.
xx
so in this function i get 1 in both cases. Can somebody explain me why?
Variable a in the global scope and a inside b() belong to different scopes. Execution of b() happens in 2 phases:
Memory allocation: All variables declarations and functions in b() are first allocated memory. This is called hoisting.
This is how the global scope and local scope of b() would look like at this point: Local refers to the scope of b()
Local: {
a: function a()
}
Global: {
a: 1
}
Code execution: The line a = 10 will override and assign 10 to a inside b(). Right after this line the function returns. Note that b's execution does not modify a in the global scope. Thus, your code would log a as 1 even after b() finishes execution.
This is how the scopes would look like right before b() returns:
Local: {
a: 10
}
Global: {
a: 1
}
if i use const a = function() and of course put it before the return, the global variable will change to 10. Though now it does not.
To modify global variable a from b() you can remove function a, like this:
var a = 1;
function b() {
a = 10;
return;
}
console.log('a equals to ', a);
b();
console.log('now a equals to ', a);
Output:
a equals to 1
now a equals to 10
Why? Undeclared variables are always global in Javascript. This means that a declared in the global scope and a used inside b both reference the same variable. a=10 will therefore modify the a that was declared in the global scope.
This is how the scopes would look like:
Local: {
// no a
}
Global: {
a: 10
}
My goal is to have function which merge N functions into one. Preferably with inlining.
I see it like:
inline fun merge(vararg functions:(N)->Unit):(N)->Unit{
//something that makes this vararg into one function which calls all functions from vararg is sequence
}
How can i do it? If I can.
Please try this one:
fun <N> merge(vararg functions: (N) -> Unit): (N) -> Unit = { n: N ->
functions.forEach { it(n) }
}
Example of usage:
val one: (Int) -> Unit = { it + 2 }
val two: (Int) -> Unit = { it + 5 }
merge(one, two)(5)
Is it possible, in Scala, to define a function that would receive any other function as a parameter?
It should be something like the following:
object Module extends SecureModule{
val bc = new MyBC()
def method(parameter: Type) = {
exec(bc.method(parameter))
}
def method2(parameter1: Type1, parameter2: Type2) = {
exec(bc.method2(parameter1,parameter2))
}
}
trait SecureModule {
def exec(f: ANY_PARAMETER => ANY_RESULT) = {
//some extra processing
f
}
}
is it possible? If so, how could I achieve this?
Thank you in advance.
The nice thing about scala is that you can create what seems to be your own syntax.
If what you want to do is wrap an operation so that you can do pre and post processing, as well as control the execution context, then you do this by using call-by-name parameters. For example, if we just wanted to time how long a block of code takes, then we could do something like this:
def timer[T](block: => T): (T,Long) = {
val startDate = new Date()
val result = block
val endDate = new Date()
(result, endDate.getTime()-startDate.getTime())
}
We can use it like this:
val (result,duration) = timer {
1+3
}
Or like this
val (result,duration) = timer {
"hello" + " world!"
}
And the result will have the correct type from the block that you pass in while also giving you the duration that you expect.
I am under the impression that your description is somewhat misleading.
The way I understand it, what you (might) want to do is delaying the execution of the bc.method calls until some other code has been performed.
If so, try this:
object Module extends SecureModule{
val bc = new MyBC()
def method(parameter: Type) = {
exec(() => bc.method(parameter))
}
def method2(parameter1: Type1, parameter2: Type2) = {
exec(() => bc.method2(parameter1,parameter2))
}
}
trait SecureModule {
def exec[Result](f: () => Result): Result = {
//some extra processing
f()
}
}
You can't take any function as a parameter. What would you even do it?
At best, you can take any function that has a specific number of parameters.
For example, here, f takes one argument and returns a value.
def exec[A,B](f: A => B)
And here, f takes two arguments:
def exec[A,B,C](f: (A, B) => C)
If you don't care about the return type of the function, you could always use Any instead of a type parameter, since functions are covariant in their return type:
def exec[A](f: A => Any)
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...
}