Almost identical recursive functions - language-agnostic

I have a function called myFunction1 whose definition is the following:
function myFunction1()
{
if condition1 then
doSomething1();
myFunction1();
else if condition2 then
doSomething2();
myFunction1();
else if condition3 then
doSomething3();
myFunction1();
else throw Exception;
}
Now I want to write a second function myFunction2 which is almost identical to myFunction1 except for a single case, i.e.,
function myFunction2()
{
if condition1 then
doSomething4();
myFunction2();
else if condition2 then
doSomething2();
myFunction2();
else if condition3 then
doSomething3();
myFunction2();
else throw Exception;
}
Note that it is only the first if which differs from myFuction1. How could I write myFuction2 so as to avoid duplicating code?

If it is easy to read and maintenance, have some duplicates is good!

If it's a functional language then refactoring this is easy. Just take out the difference and pass it in as an argument:
function myGenericFunction1(theThingToDo)
{
if condition1 then
theThingToDo();
myFunction1();
else if condition2 then
doSomething2();
myFunction1();
else if condition3 then
doSomething3();
myFunction1();
else throw Exception;
}
Now you can either use it directly:
myGenericFunction1(doSomething1);
myGenericFunction1(doSomething4);
Or use it to create your two functions:
function myFunction1 () {
myGenericFunction1(doSomething1);
}
function myFunction2 () {
myGenericFunction1(doSomething4);
}
myFunction1();
myFunction2();

If it's not a functional language, you can add a parameter to a single method:
function myFunction(case)
{
if condition1 then
if case == 1 then
doSomething1();
else
doSomething4();
myFunction(case);
else if condition2 then
doSomething2();
myFunction(case);
else if condition3 then
doSomething3();
myFunction(case);
else throw Exception;
}
Or, depending on your actual case, it might make sense to pass doSomething1/4 as a function parameter, to avoid the if. That makes the code simpler when there are more possibilities.

Related

How to write a test case for multiple if else statement in angular 9

I am trying to write test case for below method but i don't know how to write the test case to cover the code:
getSectionName(sectionId: string) {
if (sectionId === sectionIds.Homepage) {
return Section.Homepage;
} else Iif (sectionId === sectionIds.ProductList) {
return Section.aboutUs;
} else {
return Section.Homepage
}
}
How to achieve the test case for this method?
It could be a test case by calling directly the component function and checking the function result. Acutaly I simplify your function too.
getSectionName(sectionId: string) {
if (sectionId === sectionIds.ProductList) {
return Section.aboutUs;
}
return Section.Homepage
}
it(
"Verify ProductList result",
waitForAsync(() => {
const result = component.getSectionName(sectionIds.ProductList);
expect(result).toBe(Section.aboutUs);
})
);

Using exceptions as default arguments in Kotlin

I'm writing a function in Kotlin to retrieve items of type T from a database.
The user can specify an action to be invoked if no matching results are found, otherwise an IllegalArgumentException is thrown:
fun get(
...,
onNoneFound: () -> T = throw IllegalStateException("No matching results found")
): T {
...
return when (results.size) -> {
0 -> onNoneFound.invoke()
1 -> ...
else -> chooseResult(...)
}
}
The issue I'm having is that whenever the function is invoked, it seems that the IllegalStateException is thrown before the function body is executed.
In a way, that makes sense, and I suppose a workaround could be:
fun get(
...,
onNoneFound: (() -> T)? = null
): T {
...
return when (results.size) -> {
0 -> if (onNoneFound == null) {
throw IllegalArgumentException("No matching results found")
} else {
onNoneFound.invoke()
}
1 -> ...
else -> chooseResult(...)
}
}
I was wondering if there is a more elegant/preferable solution to this problem - ideally where I do not have to make the function nullable and do a null check later. Is there a way of doing this with Kotlin's default argument syntax?
Edit:
It occurred to me that I can use the elvis operator for the null check which does make the code more elegant:
onNoneFound?.invoke() ?: throw IllegalArgumentException("No matching results found")
But I'm still curious if Kotlin has a built-in way of doing this without the null check.
You shouldn't build the exception directly. Try:
fun get(
...,
onNoneFound: () -> T = { throw IllegalStateException("No matching results found") }
): T {
...
return when (results.size) -> {
0 -> onNoneFound.invoke()
1 -> ...
else -> chooseResult(...)
}
}
The problem is that throw IllegalStateException(...) is a perfectly fine expression of type () -> T, just as it is an expression of any other type; but it throws the exception immediately, what you want is a lambda which will throw the exception when invoked. And that's { throw IllegalStateException(...) } in Kotlin, as
Roger Lindsjö's answer says.

Using a switch case can you put expressions in the case?

Is it valid to put expressions in a case statement? I have this switch case statement.
var switchValue:String = StatusUpdateErrorEvent.UPDATE_ERROR;
switch (switchValue) {
case caseValue: { // it's implied here that (switchValue==caseValue)
}
case StatusUpdateErrorEvent.UPDATE_ERROR: {
}
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR: {
}
// is this what I should do if I add my own expression?
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR==type: {
}
}
It doesn't throw any errors when I add an expression is the switchValue==caseValue expression thrown out?
switch (switchValue) {
case caseValue:
//1
break;
case StatusUpdateErrorEvent.UPDATE_ERROR:
//2
break;
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR:
//3
break;
case event is StatusUpdateErrorEvent && StatusUpdateErrorEvent.UPDATE_ERROR == type:
//4
break;
}
You need to use "break;" after every case. If not, all other breaks after will be executed. It can e also "return;" if you just want to exit function after break.
Other thing is that you use "case" in a very weird way, just like they are if's. Don't put boolean comparison there like that. It's place for values.

Can you override functions in AS3?

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...
}

In as3 can an if statement run an event tracker or call a function?

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);
}
}