What is the exact definition of the strategy design pattern? - oop

I had a geek fight with someone over what the strategy pattern really is and I need a expert to settle the matter.
We both agree that the strategy pattern allows for the guts of a class (e.g., the behavior) to be swapped out at runtime while maintaining the same interface. However, her contention is that "For [the algorithms] to be a strategy, You would have to get the same results". My contention is that swapping an "algorithm" or logic of a class could mean that the results of the overridden operation are different, but that it still meets the purpose, intent (and classification) of the strategy pattern.
Her code example with comments:
By your definition, any subclasses of a class would be a strategy. They have the same method definitions (signatures), and are therefore interchangeable.
Interface Strategy
{
DoArithmatic(int[] a)
}
Class A : Strategy
public int DoArithmatic(int[]a)
{
int temp = 0;
for(int i =0; i< a.length; i++)
temp += a[i]
}
Class B : Strategy
public int DoArithmaticB(int[]a)
{
int temp = 0;
for(int i =a.length -1; i>-1; i--)
temp += a[i]
}
Class C : Strategy
public int DoArithmatic(int[]a)
{
int temp = 0;
for(int i =0; i< a.length; i++)
temp -= a;
}
int[] a = { 1,2,3 }
ClassA.DoArithmatic(a) = 6
ClassB.DoArithmatic(a) = 6
ClassC.DoArithmatic(a) = -6//This one is not interchangeable
The first two are strategies. Because for any input they will give you the EXACT same answer. the last one is not. Just because it gives you an int does not make it a strategy. They have to "DO" the same thing.
You can't use a "higher" abstraction term just to make them a strategy.
These all do "MATH" but they are not all doing the "same" thing in a different way. That is the essence of a strategy.
So, who's right?

You sir are correct and your coworker needs to read the GoF.
"The strategy pattern lets the algorithms vary independently from clients that use them."
See:
http://www.dofactory.com/Patterns/PatternStrategy.aspx

Technically, strategies can do whatever they want.
It is only when the "outer context" dictates some fixed and repeatable behaviour that cannot be captured in the programmatical interface (call them "desirable properties"), that you need to take care that your strategies are truly substitutable à la Liskov with respect to these desirable properties.

I support your opinion. Different strategies can do very different things as long as they can be used in the same context.
For example, if you want to visit each node in a tree, valid strategies could be:
Depths-first search pre-order
DFS post-order
BFS
randomized
...
All strategies would visit the nodes in a different order, yet the objective (visiting each node) would be the same. So if the order does not matter, either strategy fits your needs.

FWIW, the Wikipedia article agrees with you and has never heard of her position.

The first two are strategies. Becuase for any input they will give you the EXACT same answer. the last one is not. Just becuase it gives you an int does not make it a strategy. They have to "DO" the same thing.
They have to do the same thing, but that doesn't mean they give the exact same result. The motivating example from the GoF is one of different layout algorithms, or different register allocation algorithms. The strategies have the same goal - layout blocks of text and images on a page, or assigning virtual registers to hardware registers - but they don't have to create exactly the same result.
So if the goal of the Strategy in your example is to do any arithmetic with the input, then each example is a strategy for that goal. If the goal was to sum the array it is passed, DoArithmatic would have been called CalculateSum, and the final example would fail to conform to the contract of the strategy, and so violate LSP.

According to "Head first Design Patterns" (see here) page 24
"The Strategy Pattern defines a family of algorithms,
encapsulates each one, and makes them interchangeable.
Strategy lets the algorithm vary independently from
clients that use it. "
so sir you are correct, at least according to the people who defined the pattern, but what do they know.

You are. The point of the strategy is to substitute the algorithm. Whether they deliver the same result is a by-product of the desired behavior.

I think it would be more correct to say that the question of whether the strategies must be deterministically identical is outside the scope of the definition of the strategy pattern.
If a function always returns the same result for given inputs, it is deterministic. If two functions are deterministic and they always return the same value for the same inputs then they are deterministically equivalent. They may or may not have the same side effects; if they do then they are just plain equivalent.
Typically this is not the case. Let us consider an example that appears to require deterministic equivalence: sorting. You might think that if two comparer implementations fail to return the same result for the same inputs then at least one of them must be faulty, but this is not necessarily the case.
Sort orders vary between countries. Some places sort accent-insensitively. Some put McDuck with MacDuck, and so forth. These are strategies, this is a perfect application of strategy pattern, and the strategies are most certainly not deterministically equivalent.
You win.

I also have to agree. A good example would be a pricing calculator strategy. You could have different strategies for calculating the final amount of an invoice depending on several variables like quantity of items, type of customer, shipping destination, etc. Each of those strategies would definitely be expected to return a different result and it would still be considered a Strategy pattern.

Related

Where does the KeY verification tool shine?

What are some code examples demonstrating KeY’s strength?
Details
With so many Formal Method tools available, I was wondering where KeY is better than its competition, and how? Some readable code examples would be quite helpful for comparison and understanding.
Updates
Searching through the KeY website, I found code examples from the book — is there a suitable code example in there somewhere?
Furthermore, I found a paper about the bug that KeY found in Java 8’s mergeCollapse in TimSort. What is a minimal code from TimSort that demonstrates KeY’s strength? I do not understand, however, why model checking supposedly cannot find the bug — a bit array with 64 elements should not be too large to handle. Are other deductive verification tools just as capable of finding the bug?
Is there an established verification competition with suitable code examples?
This is a very hard question, which is why it hasn't yet been answered after having already been asked more than one year ago (and although we from the KeY community are well aware of it...).
The Power of Interaction
First, I'd like to point out that KeY is basically the only tool out there allowing for interactive proofs of Java programs. Although many proofs work automatically and we have quite powerful automatic strategies at hand, sometimes interaction is required to understand why a proof fails (too weak or even wrong specifications, wrong code or "just" a prover incapacity) and to add suitable corrections or strengthenings.
Feedback from Proof Inspection
Especially in the case of a prover incapacity (specification and program are OK, but the problem is too hard for the prover to succeed automatically), interaction is a powerful feature. Many program provers (like OpenJML, Dafny, Frama-C etc.) rely on SMT solvers in the backend which they feed with many more or less small verification conditions. The verification status for these conditions is then reported back to the user, basically as pass or fail -- or timeout. When an assertion failed, a user can change the program or refine the specifications, but cannot inspect the state of the proof to deduct information about why something went wrong; this style is sometimes called "auto-active" as opposed to interactive. While this can be quite convenient in many cases (especially when proofs pass, since the SMT solvers can be really quick in proving something), it can be hard to mine SMT solver output for information. Not even the SMT solvers themselves know why something went wrong (although they can produce a counterexample), as they just are fed a set of formulas for which they attempt to find a contradiction.
TimSort: A Complicated Algorithmic Problem
For the TimSort proof which you mentioned, we had to use a lot of interaction to make them pass. Take, for instance, the mergeHi method of the sorting algorithm which has been proven by one of the most experienced KeY power users known to me. In this proof of 460K proof nodes, 3K user interactions were necessary, consisting of quite a lot of simple ones like the hiding of distracting formulas, but also of 478 quantifier instantiations and about 300 cuts (on-line lemma introduction). The code of that method features many difficult Java features like nested loops with labeled breaks, integer overflows, bit arithmetic and so on; especially, there are a lot of potential exceptions and other reasons for branching in the proof tree (which is why in addition, also five manual state merging rule applications have been used in the proof). The workflow for proving this method basically was to give the strategies a try for some time, check the proof state afterward, prune back the proof and introduce a helpful lemma to reduce the overall proof work and to start again; occasionally, quantifiers were instantiated manually if the strategies failed to find the right instantiation directly by themselves, and proof tree branches were merged to tackle state explosion. I would just claim here that proving this code is (at least currently) not possible with auto-active tools, where you cannot guide the prover in that way, and also cannot obtain the right feedback for knowing how to guide it.
Strength of KeY
Concluding, I'd say that KeY's strong in proving hard algorithmic problems (like sorting etc.) where you have complicated quantified invariants and integer arithmetic with overflows, and where you need to find quantifier instantiations and small lemmas on the fly by inspecting and interacting with the proof state. The KeY approach of semi-interactive verification also excels in general for cases where SMT solvers time out, such that a user cannot tell whether something is wrong or an additional lemma is required.
KeY can of course also proof "simple" problems, however there you need to take care that your program does not contain an unsupported Java feature like floating point numbers or multithreading; also, library methods can be quite a problem if they're not yet specified in JML (but this problem applies to other approaches as well).
Ongoing Developments
As a side remark, I also would like to point out that KeY is now more and more being transformed to a platform for static analysis of different kinds of program properties (not only functional correctness of Java programs). On the one hand, we have developed tools such as the Symbolic Execution Debugger which can be used also by non-experts to examine the behavior of a sequential Java program. On the other hand, we are currently busy in refactoring the architecture of the system for making it possible to add frontends for languages different than Java (in our internal project "KeY-RED"); furthermore, there are ongoing efforts to modernize the Java frontend such that also newer language features like Lambdas and so on are supported. We are also looking into relational properties like compiler correctness. And while we already support the integration of third-party SMT solvers, our integrated logic core will still be there to support understanding proof situations and manual interactions for cases where SMT and automation fails.
TimSort Code Example
Since you asked for a code example... I cannot right know think of "the" code example showing KeY's strength, but maybe for giving you a flavor of the complexity of mergeHi in the TimSort algorithm, here a shortened excerpt with some comments (the full method has about 100 lines of code):
private void mergeHi(int base1, int len1, int base2, int len2) {
// ...
T[] tmp = ensureCapacity(len2); // Method call by contract
System.arraycopy(a, base2, tmp, 0, len2); // Manually specified library method
// ...
a[dest--] = a[cursor1--]; // potential overflow, NullPointerException, ArrayIndexOutOfBoundsException
if (--len1 == 0) {
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
return; // Proof branching
}
if (len2 == 1) {
// ...
return; // Proof branching
}
// ...
outer: // Loop labels...
while (true) {
// ...
do { // Nested loop
if (c.compare(tmp[cursor2], a[cursor1]) < 0) {
// ...
if (--len1 == 0)
break outer; // Labeled break
} else {
// ...
if (--len2 == 1)
break outer; // Labeled break
}
} while ((count1 | count2) < minGallop); // Bit arithmetic
do { // 2nd nested loop
// That's one complex statement below...
count1 = len1 - gallopRight(tmp[cursor2], a, base1, len1, len1 - 1, c);
if (count1 != 0) {
// ...
if (len1 == 0)
break outer;
}
// ...
if (--len2 == 1)
break outer;
count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
if (count2 != 0) {
// ...
if (len2 <= 1)
break outer;
}
a[dest--] = a[cursor1--];
if (--len1 == 0)
break outer;
// ...
} while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
// ...
} // End of "outer" loop
this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field
if (len2 == 1) {
// ...
} else if (len2 == 0) {
throw new IllegalArgumentException(
"Comparison method violates its general contract!");
} else {
System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
}
}
Verification Competition
VerifyThis is an established competition for logic-based verification tools which will have its 7th iteration in 2019. The concrete challenges for past events can be downloaded from the "archive" section of the website I linked. Two KeY teams participated there in 2017. The overall winner that year was Why3. An interesting observation is that there was one problem, Pair Insertion Sort, which came as a simplified and as an optimized Java version, for which no team succeeded in verifying the real-world optimized version on site. However, a KeY team finished that proof in the weeks after the event. I think that highlights my point: KeY proofs of difficult algorithmic problems take their time and require expertise, but they're likely to succeed due to the combined power of strategies and interaction.

Does initialising an auxiliary array to 0 count as n time complexity already?

very new to big O complexity and I was wondering if an algorithm where you have a given array, and you initialise an auxilary array with the same amount of indexes count as n time already, or do you just assume this is O(1), or nothing at all?
TL;DR: Ignore it
Long answer: This will depend on the rest of your algorithm as well as what you want to achieve. Typically you will do something useful with the array afterwards which does have at least the same time complexity as filling the array, so that array-filling does not contribute to the time complexity. Furthermore filling an array with 0 feels like something you do to initialize the array, so your "real" algorithm can work properly. But nevertheless there are some cases you could consider.
Please note that I use pseudocode in the following examples, I hope it's clear what the algorithm should do. Also note that all the examples don't do anything useful with the array. It's just to show my point.
Lets say you have following code:
A = Array[n]
for(i=0, i<n, i++)
A[i] = 0
print "Hello World"
Then obviously the runtime of your algorithm is highly dependent on the value of n and thus should be counted as linear complexity O(n)
On the other hand, if you have a much more complicated function, say this one:
A = Array[n]
for(i=0, i<n, i++)
A[i] = 0
for(i=0, i<n, i++)
for(j=n-1, j>=0, j--)
print "Hello World"
Then even if you take the complexity of filling the array into account, you will end with complexity of O(n^2+2n) which is equal to the class O(n^2), so it does not matter in this case.
The most interesting case is surely when you have different options to use as basic operation. Say we have the following code (someFunction being an arbitrary function):
A = Array[n*n]
for(i=0, i<n*n, i++)
A[i] = 0
for(i=0, i*i<n, i++)
someFunction(i)
Now it depends on what you choose as basic operation. Which one you choose is highly dependent on what you want to achieve. Let's say someFunction is a very cheap function (regarding time complexity) and accessing the array A is more expensive. Then you would propably go with O(n^2), since accessing the array is done n^2 times. If on the other hand someFunction is expensive compared to filling the array, you would propably choose this as base operation and go with O(sqrt(n)).
Please be aware that one could also come to the conclusion that since the first part (array-filling) is executed more often than the other part (someFunction) it does not matter which one of the operations will take longer time to finish, since at some point the array-filling will need longer time. Thus you could argue that the complexity has to be quadratic O(n^2) This may be right from a theoretical view. But in real life you usually will have an operation you want to count and don't care about the other operations.
Actually you could consider ignoring the array filling as well as taking it into account in all the examples I provided above, depending whether print or accessing the array is more expensive. But I hope in the first two examples it is obvious which one will add more runtime and thus should be considered as the basic operation.

What is difference between functional and imperative programming languages?

Most of the mainstream languages, including object-oriented programming (OOP) languages such as C#, Visual Basic, C++, and Java were designed to primarily support imperative (procedural) programming, whereas Haskell/gofer like languages are purely functional. Can anybody elaborate on what is the difference between these two ways of programming?
I know it depends on user requirements to choose the way of programming but why is it recommended to learn functional programming languages?
Here is the difference:
Imperative:
Start
Turn on your shoes size 9 1/2.
Make room in your pocket to keep an array[7] of keys.
Put the keys in the room for the keys in the pocket.
Enter garage.
Open garage.
Enter Car.
... and so on and on ...
Put the milk in the refrigerator.
Stop.
Declarative, whereof functional is a subcategory:
Milk is a healthy drink, unless you have problems digesting lactose.
Usually, one stores milk in a refrigerator.
A refrigerator is a box that keeps the things in it cool.
A store is a place where items are sold.
By "selling" we mean the exchange of things for money.
Also, the exchange of money for things is called "buying".
... and so on and on ...
Make sure we have milk in the refrigerator (when we need it - for lazy functional languages).
Summary: In imperative languages you tell the computer how to change bits, bytes and words in it's memory and in what order. In functional ones, we tell the computer what things, actions etc. are. For example, we say that the factorial of 0 is 1, and the factorial of every other natural number is the product of that number and the factorial of its predecessor. We don't say: To compute the factorial of n, reserve a memory region and store 1 there, then multiply the number in that memory region with the numbers 2 to n and store the result at the same place, and at the end, the memory region will contain the factorial.
Definition:
An imperative language uses a sequence of statements to determine how to reach a certain goal. These statements are said to change the state of the program as each one is executed in turn.
Examples:
Java is an imperative language. For example, a program can be created to add a series of numbers:
int total = 0;
int number1 = 5;
int number2 = 10;
int number3 = 15;
total = number1 + number2 + number3;
Each statement changes the state of the program, from assigning values to each variable to the final addition of those values. Using a sequence of five statements the program is explicitly told how to add the numbers 5, 10 and 15 together.
Functional languages:
The functional programming paradigm was explicitly created to support a pure functional approach to problem solving. Functional programming is a form of declarative programming.
Advantages of Pure Functions:
The primary reason to implement functional transformations as pure functions is that pure functions are composable: that is, self-contained and stateless. These characteristics bring a number of benefits, including the following:
Increased readability and maintainability. This is because each function is designed to accomplish a specific task given its arguments. The function does not rely on any external state.
Easier reiterative development. Because the code is easier to refactor, changes to design are often easier to implement. For example, suppose you write a complicated transformation, and then realize that some code is repeated several times in the transformation. If you refactor through a pure method, you can call your pure method at will without worrying about side effects.
Easier testing and debugging. Because pure functions can more easily be tested in isolation, you can write test code that calls the pure function with typical values, valid edge cases, and invalid edge cases.
For OOP People or
Imperative languages:
Object-oriented languages are good when you have a fixed set of operations on things and as your code evolves, you primarily add new things. This can be accomplished by adding new classes which implement existing methods and the existing classes are left alone.
Functional languages are good when you have a fixed set of things and as your code evolves, you primarily add new operations on existing things. This can be accomplished by adding new functions which compute with existing data types and the existing functions are left alone.
Cons:
It depends on the user requirements to choose the way of programming, so there is harm only when users don’t choose the proper way.
When evolution goes the wrong way, you have problems:
Adding a new operation to an object-oriented program may require editing many class definitions to add a new method
Adding a new kind of thing to a functional program may require editing many function definitions to add a new case.
Most modern languages are in varying degree both imperative and functional but to better understand functional programming, it will be best to take an example of pure functional language like Haskell in contrast of imperative code in not so functional language like java/C#. I believe it is always easy to explain by example, so below is one.
Functional programming: calculate factorial of n i.e n! i.e n x (n-1) x (n-2) x ...x 2 X 1
-- | Haskell comment goes like
-- | below 2 lines is code to calculate factorial and 3rd is it's execution
factorial 0 = 1
factorial n = n * factorial (n - 1)
factorial 3
-- | for brevity let's call factorial as f; And x => y shows order execution left to right
-- | above executes as := f(3) as 3 x f(2) => f(2) as 2 x f(1) => f(1) as 1 x f(0) => f(0) as 1
-- | 3 x (2 x (1 x (1)) = 6
Notice that Haskel allows function overloading to the level of argument value. Now below is example of imperative code in increasing degree of imperativeness:
//somewhat functional way
function factorial(n) {
if(n < 1) {
return 1;
}
return n * factorial(n-1);
}
factorial(3);
//somewhat more imperative way
function imperativeFactor(n) {
int f = 1;
for(int i = 1; i <= n; i++) {
f = f * i;
}
return f;
}
This read can be a good reference to understand that how imperative code focus more on how part, state of machine (i in for loop), order of execution, flow control.
The later example can be seen as java/C# lang code roughly and first part as limitation of the language itself in contrast of Haskell to overload the function by value (zero) and hence can be said it is not purist functional language, on the other hand you can say it support functional prog. to some extent.
Disclosure: none of the above code is tested/executed but hopefully should be good enough to convey the concept; also I would appreciate comments for any such correction :)
Functional Programming is a form of declarative programming, which describe the logic of computation and the order of execution is completely de-emphasized.
Problem: I want to change this creature from a horse to a giraffe.
Lengthen neck
Lengthen legs
Apply spots
Give the creature a black tongue
Remove horse tail
Each item can be run in any order to produce the same result.
Imperative Programming is procedural. State and order is important.
Problem: I want to park my car.
Note the initial state of the garage door
Stop car in driveway
If the garage door is closed, open garage door, remember new state; otherwise continue
Pull car into garage
Close garage door
Each step must be done in order to arrive at desired result. Pulling into the garage while the garage door is closed would result in a broken garage door.
//The IMPERATIVE way
int a = ...
int b = ...
int c = 0; //1. there is mutable data
c = a+b;   //2. statements (our +, our =) are used to update existing data (variable c)
An imperative program = sequence of statements that change existing data.
Focus on WHAT = our mutating data (modifiable values aka variables).
To chain imperative statements = use procedures (and/or oop).
//The FUNCTIONAL way
const int a = ... //data is always immutable
const int b = ... //data is always immutable
//1. declare pure functions; we use statements to create "new" data (the result of our +), but nothing is ever "changed"
int add(x, y)
{
return x+y;
}
//2. usage = call functions to get new data
const int c = add(a,b); //c can only be assigned (=) once (const)
A functional program = a list of functions "explaining" how new data can be obtained.
Focus on HOW = our function add.
To chain functional "statements" = use function composition.
These fundamental distinctions have deep implications.
Serious software has a lot of data and a lot of code.
So same data (variable) is used in multiple parts of the code.
A. In an imperative program, the mutability of this (shared) data causes issues
code is hard to understand/maintain (since data can be modified in different locations/ways/moments)
parallelizing code is hard (only one thread can mutate a memory location at the time) which means mutating accesses to same variable have to be serialized = developer must write additional code to enforce this serialized access to shared resources, typically via locks/semaphores
As an advantage: data is really modified in place, less need to copy. (some performance gains)
B. On the other hand, functional code uses immutable data which does not have such issues. Data is readonly so there are no race conditions. Code can be easily parallelized. Results can be cached. Much easier to understand.
As a disadvantage: data is copied a lot in order to get "modifications".
See also: https://en.wikipedia.org/wiki/Referential_transparency
Imperative programming style was practiced in web development from 2005 all the way to 2013.
With imperative programming, we wrote out code that listed exactly what our application should do, step by step.
The functional programming style produces abstraction through clever ways of combining functions.
There is mention of declarative programming in the answers and regarding that I will say that declarative programming lists out some rules that we are to follow. We then provide what we refer to as some initial state to our application and we let those rules kind of define how the application behaves.
Now, these quick descriptions probably don’t make a lot of sense, so lets walk through the differences between imperative and declarative programming by walking through an analogy.
Imagine that we are not building software, but instead we bake pies for a living. Perhaps we are bad bakers and don’t know how to bake a delicious pie the way we should.
So our boss gives us a list of directions, what we know as a recipe.
The recipe will tell us how to make a pie. One recipe is written in an imperative style like so:
Mix 1 cup of flour
Add 1 egg
Add 1 cup of sugar
Pour the mixture into a pan
Put the pan in the oven for 30 minutes and 350 degrees F.
The declarative recipe would do the following:
1 cup of flour, 1 egg, 1 cup of sugar - initial State
Rules
If everything mixed, place in pan.
If everything unmixed, place in bowl.
If everything in pan, place in oven.
So imperative approaches are characterized by step by step approaches. You start with step one and go to step 2 and so on.
You eventually end up with some end product. So making this pie, we take these ingredients mix them, put it in a pan and in the oven and you got your end product.
In a declarative world, its different.In the declarative recipe we would separate our recipe into two separate parts, start with one part that lists the initial state of the recipe, like the variables. So our variables here are the quantities of our ingredients and their type.
We take the initial state or initial ingredients and apply some rules to them.
So we take the initial state and pass them through these rules over and over again until we get a ready to eat rhubarb strawberry pie or whatever.
So in a declarative approach, we have to know how to properly structure these rules.
So the rules we might want to examine our ingredients or state, if mixed, put them in a pan.
With our initial state, that doesn’t match because we haven’t yet mixed our ingredients.
So rule 2 says, if they not mixed then mix them in a bowl. Okay yeah this rule applies.
Now we have a bowl of mixed ingredients as our state.
Now we apply that new state to our rules again.
So rule 1 says if ingredients are mixed place them in a pan, okay yeah now rule 1 does apply, lets do it.
Now we have this new state where the ingredients are mixed and in a pan. Rule 1 is no longer relevant, rule 2 does not apply.
Rule 3 says if the ingredients are in a pan, place them in the oven, great that rule is what applies to this new state, lets do it.
And we end up with a delicious hot apple pie or whatever.
Now, if you are like me, you may be thinking, why are we not still doing imperative programming. This makes sense.
Well, for simple flows yes, but most web applications have more complex flows that cannot be properly captured by imperative programming design.
In a declarative approach, we may have some initial ingredients or initial state like textInput=“”, a single variable.
Maybe text input starts off as an empty string.
We take this initial state and apply it to a set of rules defined in your application.
If a user enters text, update text input. Well, right now that doesn’t apply.
If template is rendered, calculate the widget.
If textInput is updated, re render the template.
Well, none of this applies so the program will just wait around for an event to happen.
So at some point a user updates the text input and then we might apply rule number 1.
We may update that to “abcd”
So we just updated our text and textInput updates, rule number 2 does not apply, rule number 3 says if text input is update, which just occurred, then re render the template and then we go back to rule 2 thats says if template is rendered, calculate the widget, okay lets calculate the widget.
In general, as programmers, we want to strive for more declarative programming designs.
Imperative seems more clear and obvious, but a declarative approach scales very nicely for larger applications.
I think it's possible to express functional programming in an imperative fashion:
Using a lot of state check of objects and if... else/ switch statements
Some timeout/ wait mechanism to take care of asynchornousness
There are huge problems with such approach:
Rules/ procedures are repeated
Statefulness leaves chances for side-effects/ mistakes
Functional programming, treating functions/ methods like objects and embracing statelessness, was born to solve those problems I believe.
Example of usages: frontend applications like Android, iOS or web apps' logics incl. communication with backend.
Other challenges when simulating functional programming with imperative/ procedural code:
Race condition
Complex combination and sequence of events. For example, user tries to send money in a banking app. Step 1) Do all of the following in parallel, only proceed if all is good a) Check if user is still good (fraud, AML) b) check if user has enough balance c) Check if recipient is valid and good (fraud, AML) etc. Step 2) perform the transfer operation Step 3) Show update on user's balance and/ or some kind of tracking. With RxJava for example, the code is concise and sensible. Without it, I can imagine there'd be a lot of code, messy and error prone code
I also believe that at the end of the day, functional code will get translated into assembly or machine code which is imperative/ procedural by the compilers. However, unless you write assembly, as humans writing code with high level/ human-readable language, functional programming is the more appropriate way of expression for the listed scenarios
There seem to be many opinions about what functional programs and what imperative programs are.
I think functional programs can most easily be described as "lazy evaluation" oriented. Instead of having a program counter iterate through instructions, the language by design takes a recursive approach.
In a functional language, the evaluation of a function would start at the return statement and backtrack, until it eventually reaches a value. This has far reaching consequences with regards to the language syntax.
Imperative: Shipping the computer around
Below, I've tried to illustrate it by using a post office analogy. The imperative language would be mailing the computer around to different algorithms, and then have the computer returned with a result.
Functional: Shipping recipes around
The functional language would be sending recipes around, and when you need a result - the computer would start processing the recipes.
This way, you ensure that you don't waste too many CPU cycles doing work that is never used to calculate the result.
When you call a function in a functional language, the return value is a recipe that is built up of recipes which in turn is built of recipes. These recipes are actually what's known as closures.
// helper function, to illustrate the point
function unwrap(val) {
while (typeof val === "function") val = val();
return val;
}
function inc(val) {
return function() { unwrap(val) + 1 };
}
function dec(val) {
return function() { unwrap(val) - 1 };
}
function add(val1, val2) {
return function() { unwrap(val1) + unwrap(val2) }
}
// lets "calculate" something
let thirteen = inc(inc(inc(10)))
let twentyFive = dec(add(thirteen, thirteen))
// MAGIC! The computer still has not calculated anything.
// 'thirteen' is simply a recipe that will provide us with the value 13
// lets compose a new function
let doubler = function(val) {
return add(val, val);
}
// more modern syntax, but it's the same:
let alternativeDoubler = (val) => add(val, val)
// another function
let doublerMinusOne = (val) => dec(add(val, val));
// Will this be calculating anything?
let twentyFive = doubler(thirteen)
// no, nothing has been calculated. If we need the value, we have to unwrap it:
console.log(unwrap(thirteen)); // 26
The unwrap function will evaluate all the functions to the point of having a scalar value.
Language Design Consequences
Some nice features in imperative languages, are impossible in functional languages. For example the value++ expression, which in functional languages would be difficult to evaluate. Functional languages make constraints on how the syntax must be, because of the way they are evaluated.
On the other hand, with imperative languages can borrow great ideas from functional languages and become hybrids.
Functional languages have great difficulty with unary operators like for example ++ to increment a value. The reason for this difficulty is not obvious, unless you understand that functional languages are evaluated "in reverse".
Implementing a unary operator would have to be implemented something like this:
let value = 10;
function increment_operator(value) {
return function() {
unwrap(value) + 1;
}
}
value++ // would "under the hood" become value = increment_operator(value)
Note that the unwrap function I used above, is because javascript is not a functional language, so when needed we have to manually unwrap the value.
It is now apparent that applying increment a thousand times would cause us to wrap the value with 10000 closures, which is worthless.
The more obvious approach, is to actually directly change the value in place - but voila: you have introduced modifiable values a.k.a mutable values which makes the language imperative - or actually a hybrid.
Under the hood, it boils down to two different approaches to come up with an output when provided with an input.
Below, I'll try to make an illustration of a city with the following items:
The Computer
Your Home
The Fibonaccis
Imperative Languages
Task: Calculate the 3rd fibonacci number.
Steps:
Put The Computer into a box and mark it with a sticky note:
Field
Value
Mail Address
The Fibonaccis
Return Address
Your Home
Parameters
3
Return Value
undefined
and send off the computer.
The Fibonaccis will upon receiving the box do as they always do:
Is the parameter < 2?
Yes: Change the sticky note, and return the computer to the post office:
Field
Value
Mail Address
The Fibonaccis
Return Address
Your Home
Parameters
3
Return Value
0 or 1 (returning the parameter)
and return to sender.
Otherwise:
Put a new sticky note on top of the old one:
Field
Value
Mail Address
The Fibonaccis
Return Address
Otherwise, step 2, c/oThe Fibonaccis
Parameters
2 (passing parameter-1)
Return Value
undefined
and send it.
Take off the returned sticky note. Put a new sticky note on top of the initial one and send The Computer again:
Field
Value
Mail Address
The Fibonaccis
Return Address
Otherwise, done, c/o The Fibonaccis
Parameters
2 (passing parameter-2)
Return Value
undefined
By now, we should have the initial sticky note from the requester, and two used sticky notes, each having their Return Value field filled. We summarize the return values and put it in the Return Value field of the final sticky note.
Field
Value
Mail Address
The Fibonaccis
Return Address
Your Home
Parameters
3
Return Value
2 (returnValue1 + returnValue2)
and return to sender.
As you can imagine, quite a lot of work starts immediately after you send your computer off to the functions you call.
The entire programming logic is recursive, but in truth the algorithm happens sequentially as the computer moves from algorithm to algorithm with the help of a stack of sticky notes.
Functional Languages
Task: Calculate the 3rd fibonacci number. Steps:
Write the following down on a sticky note:
Field
Value
Instructions
The Fibonaccis
Parameters
3
That's essentially it. That sticky note now represents the computation result of fib(3).
We have attached the parameter 3 to the recipe named The Fibonaccis. The computer does not have to perform any calculations, unless somebody needs the scalar value.
Functional Javascript Example
I've been working on designing a programming language named Charm, and this is how fibonacci would look in that language.
fib: (n) => if (
n < 2 // test
n // when true
fib(n-1) + fib(n-2) // when false
)
print(fib(4));
This code can be compiled both into imperative and functional "bytecode".
The imperative javascript version would be:
let fib = (n) =>
n < 2 ?
n :
fib(n-1) + fib(n-2);
The HALF functional javascript version would be:
let fib = (n) => () =>
n < 2 ?
n :
fib(n-1) + fib(n-2);
The PURE functional javascript version would be much more involved, because javascript doesn't have functional equivalents.
let unwrap = ($) =>
typeof $ !== "function" ? $ : unwrap($());
let $if = ($test, $whenTrue, $whenFalse) => () =>
unwrap($test) ? $whenTrue : $whenFalse;
let $lessThen = (a, b) => () =>
unwrap(a) < unwrap(b);
let $add = ($value, $amount) => () =>
unwrap($value) + unwrap($amount);
let $sub = ($value, $amount) => () =>
unwrap($value) - unwrap($amount);
let $fib = ($n) => () =>
$if(
$lessThen($n, 2),
$n,
$add( $fib( $sub($n, 1) ), $fib( $sub($n, 2) ) )
);
I'll manually "compile" it into javascript code:
"use strict";
// Library of functions:
/**
* Function that resolves the output of a function.
*/
let $$ = (val) => {
while (typeof val === "function") {
val = val();
}
return val;
}
/**
* Functional if
*
* The $ suffix is a convention I use to show that it is "functional"
* style, and I need to use $$() to "unwrap" the value when I need it.
*/
let if$ = (test, whenTrue, otherwise) => () =>
$$(test) ? whenTrue : otherwise;
/**
* Functional lt (less then)
*/
let lt$ = (leftSide, rightSide) => () =>
$$(leftSide) < $$(rightSide)
/**
* Functional add (+)
*/
let add$ = (leftSide, rightSide) => () =>
$$(leftSide) + $$(rightSide)
// My hand compiled Charm script:
/**
* Functional fib compiled
*/
let fib$ = (n) => if$( // fib: (n) => if(
lt$(n, 2), // n < 2
() => n, // n
() => add$(fib$(n-2), fib$(n-1)) // fib(n-1) + fib(n-2)
) // )
// This takes a microsecond or so, because nothing is calculated
console.log(fib$(30));
// When you need the value, just unwrap it with $$( fib$(30) )
console.log( $$( fib$(5) ))
// The only problem that makes this not truly functional, is that
console.log(fib$(5) === fib$(5)) // is false, while it should be true
// but that should be solveable
https://jsfiddle.net/819Lgwtz/42/
I know this question is older and others already explained it well, I would like to give an example problem which explains the same in simple terms.
Problem: Writing the 1's table.
Solution: -
By Imperative style: =>
1*1=1
1*2=2
1*3=3
.
.
.
1*n=n
By Functional style: =>
1
2
3
.
.
.
n
Explanation in Imperative style we write the instructions more explicitly and which can be called as in more simplified manner.
Where as in Functional style, things which are self-explanatory will be ignored.

Is it possible to compare two Objective-C blocks by content?

float pi = 3.14;
float (^piSquare)(void) = ^(void){ return pi * pi; };
float (^piSquare2)(void) = ^(void){ return pi * pi; };
[piSquare isEqualTo: piSquare2]; // -> want it to behave like -isEqualToString...
To expand on Laurent's answer.
A Block is a combination of implementation and data. For two blocks to be equal, they would need to have both the exact same implementation and have captured the exact same data. Comparison, thus, requires comparing both the implementation and the data.
One might think comparing the implementation would be easy. It actually isn't because of the way the compiler's optimizer works.
While comparing simple data is fairly straightforward, blocks can capture objects-- including C++ objects (which might actually work someday)-- and comparison may or may not need to take that into account. A naive implementation would simply do a byte level comparison of the captured contents. However, one might also desire to test equality of objects using the object level comparators.
Then there is the issue of __block variables. A block, itself, doesn't actually have any metadata related to __block captured variables as it doesn't need it to fulfill the requirements of said variables. Thus, comparison couldn't compare __block values without significantly changing compiler codegen.
All of this is to say that, no, it isn't currently possible to compare blocks and to outline some of the reasons why. If you feel that this would be useful, file a bug via http://bugreport.apple.com/ and provide a use case.
Putting aside issues of compiler implementation and language design, what you're asking for is provably undecidable (unless you only care about detecting 100% identical programs). Deciding if two programs compute the same function is equivalent to solving the halting problem. This is a classic consequence of Rice's Theorem: Any "interesting" property of Turing machines is undecidable, where "interesting" just means that it's true for some machines and false for others.
Just for fun, here's the proof. Assume we can create a function to decide if two blocks are equivalent, called EQ(b1, b2). Now we'll use that function to solve the halting problem. We create a new function HALT(M, I) that tells us if Turing machine M will halt on input I like so:
BOOL HALT(M,I) {
return EQ(
^(int) {return 0;},
^(int) {M(I); return 0;}
);
}
If M(I) halts then the blocks are equivalent, so HALT(M,I) returns YES. If M(I) doesn't halt then the blocks are not equivalent, so HALT(M,I) returns NO. Note that we don't have to execute the blocks -- our hypothetical EQ function can compute their equivalence just by looking at them.
We have now solved the halting problem, which we know is not possible. Therefore, EQ cannot exist.
I don't think this is possible. Blocks can be roughly seen as advanced functions (with access to global or local variables). The same way you cannot compare functions' content, you cannot compare blocks' content.
All you can do is to compare their low-level implementation, but I doubt that the compiler will guarantee that two blocks with the same content share their implementation.

What are you favorite low level code optimization tricks? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I know that you should only optimize things when it is deemed necessary. But, if it is deemed necessary, what are your favorite low level (as opposed to algorithmic level) optimization tricks.
For example: loop unrolling.
gcc -O2
Compilers do a lot better job of it than you can.
Picking a power of two for filters, circular buffers, etc.
So very, very convenient.
-Adam
Why, bit twiddling hacks, of course!
One of the most useful in scientific code is to replace pow(x,4) with x*x*x*x. Pow is almost always more expensive than multiplication. This is followed by
for(int i = 0; i < N; i++)
{
z += x/y;
}
to
double denom = 1/y;
for(int i = 0; i < N; i++)
{
z += x*denom;
}
But my favorite low level optimization is to figure out which calculations can be removed from a loop. Its always faster to do the calculation once rather than N times. Depending on your compiler, some of these may be automatically done for you.
Inspect the compiler's output, then try to coerce it to do something faster.
I wouldn't necessarily call it a low level optimization, but I have saved orders of magnitude more cycles through judicious application of caching than I have through all my applications of low level tricks combined. Many of these methods are applications specific.
Having an LRU cache of database queries (or any other IPC based request).
Remembering the last failed database query and returning a failure if re-requested within a certain time frame.
Remembering your location in a large data structure to ensure that if the next request is for the same node, the search is free.
Caching calculation results to prevent duplicate work. In addition to more complex scenarios, this is often found in if or for statements.
CPUs and compilers are constantly changing. Whatever low level code trick that made sense 3 CPU chips ago with a different compiler may actually be slower on the current architecture and there may be a good chance that this trick may confuse whoever is maintaining this code in the future.
++i can be faster than i++, because it avoids creating a temporary.
Whether this still holds for modern C/C++/Java/C# compilers, I don't know. It might well be different for user-defined types with overloaded operators, whereas in the case of simple integers it probably doesn't matter.
But I've come to like the syntax... it reads like "increment i" which is a sensible order.
Using template metaprogramming to calculate things at compile time instead of at run-time.
Years ago with a not-so-smart compilier, I got great mileage from function inlining, walking pointers instead of indexing arrays, and iterating down to zero instead of up to a maximum.
When in doubt, a little knowledge of assembly will let you look at what the compiler is producing and attack the inefficient parts (in your source language, using structures friendlier to your compiler.)
precalculating values.
For instance, instead of sin(a) or cos(a), if your application doesn't necessarily need angles to be very precise, maybe you represent angles in 1/256 of a circle, and create arrays of floats sine[] and cosine[] precalculating the sin and cos of those angles.
And, if you need a vector at some angle of a given length frequently, you might precalculate all those sines and cosines already multiplied by that length.
Or, to put it more generally, trade memory for speed.
Or, even more generally, "All programming is an exercise in caching" -- Terje Mathisen
Some things are less obvious. For instance traversing a two dimensional array, you might do something like
for (x=0;x<maxx;x++)
for (y=0;y<maxy;y++)
do_something(a[x,y]);
You might find the processor cache likes it better if you do:
for (y=0;y<maxy;y++)
for (x=0;x<maxx;x++)
do_something(a[x,y]);
or vice versa.
Don't do loop unrolling. Don't do Duff's device. Make your loops as small as possible, anything else inhibits x86 performance and gcc optimizer performance.
Getting rid of branches can be useful, though - so getting rid of loops completely is good, and those branchless math tricks really do work. Beyond that, try never to go out of the L2 cache - this means a lot of precalculation/caching should also be avoided if it wastes cache space.
And, especially for x86, try to keep the number of variables in use at any one time down. It's hard to tell what compilers will do with that kind of thing, but usually having less loop iteration variables/array indexes will end up with better asm output.
Of course, this is for desktop CPUs; a slow CPU with fast memory access can precalculate a lot more, but in these days that might be an embedded system with little total memory anyway…
I've found that changing from a pointer to indexed access may make a difference; the compiler has different instruction forms and register usages to choose from. Vice versa, too. This is extremely low-level and compiler dependent, though, and only good when you need that last few percent.
E.g.
for (i = 0; i < n; ++i)
*p++ = ...; // some complicated expression
vs.
for (i = 0; i < n; ++i)
p[i] = ...; // some complicated expression
Optimizing cache locality - for example when multiplying two matrices that don't fit into cache.
Allocating with new on a pre-allocated buffer using C++'s placement new.
Counting down a loop. It's cheaper to compare against 0 than N:
for (i = N; --i >= 0; ) ...
Shifting and masking by powers of two is cheaper than division and remainder, / and %
#define WORD_LOG 5
#define SIZE (1 << WORD_LOG)
#define MASK (SIZE - 1)
uint32_t bits[K]
void set_bit(unsigned i)
{
bits[i >> WORD_LOG] |= (1 << (i & MASK))
}
Edit
(i >> WORD_LOG) == (i / SIZE) and
(i & MASK) == (i % SIZE)
because SIZE is 32 or 2^5.
Jon Bentley's Writing Efficient Programs is a great source of low- and high-level techniques -- if you can find a copy.
Eliminating branches (if/elses) by using boolean math:
if(x == 0)
x = 5;
// becomes:
x += (x == 0) * 5;
// if '5' was a base 2 number, let's say 4:
x += (x == 0) << 2;
// divide by 2 if flag is set
sum >>= (blendMode == BLEND);
This REALLY speeds things out especially when those ifs are in a loop or somewhere that is being called a lot.
The one from Assembler:
xor ax, ax
instead of:
mov ax, 0
Classical optimization for program size and performance.
In SQL, if you only need to know whether any data exists or not, don't bother with COUNT(*):
SELECT 1 FROM table WHERE some_primary_key = some_value
If your WHERE clause is likely return multiple rows, add a LIMIT 1 too.
(Remember that databases can't see what your code's doing with their results, so they can't optimise these things away on their own!)
Recycling the frame-pointer all of a sudden
Pascal calling-convention
Rewrite stack-frame tail call optimizarion (although it sometimes messes with the above)
Using vfork() instead of fork() before exec()
And one I am still looking for, an excuse to use: data driven code-generation at runtime
Liberal use of __restrict to eliminate load-hit-store stalls.
Rolling up loops.
Seriously, the last time I needed to do anything like this was in a function that took 80% of the runtime, so it was worth trying to micro-optimize if I could get a noticeable performance increase.
The first thing I did was to roll up the loop. This gave me a very significant speed increase. I believe this was a matter of cache locality.
The next thing I did was add a layer of indirection, and put some more logic into the loop, which allowed me to only loop through the things I needed. This wasn't as much of a speed increase, but it was worth doing.
If you're going to micro-optimize, you need to have a reasonable idea of two things: the architecture you're actually using (which is vastly different from the systems I grew up with, at least for micro-optimization purposes), and what the compiler will do for you.
A lot of the traditional micro-optimizations trade space for time. Nowadays, using more space increases the chances of a cache miss, and there goes your performance. Moreover, a lot of them are now done by modern compilers, and typically better than you're likely to do them.
Currently, you should (a) profile to see if you need to micro-optimize, and then (b) try to trade computation for space, in the hope of keeping as much as possible in cache. Finally, run some tests, so you know if you've improved things or screwed them up. Modern compilers and chips are far too complex for you to keep a good mental model, and the only way you'll know if some optimization works or not is to test.
In addition to Joshua's comment about code generation (a big win), and other good suggestions, ...
I'm not sure if you would call it "low-level", but (and this is downvote-bait) 1) stay away from using any more levels of abstraction than absolutely necessary, and 2) stay away from event-driven notification-style programming, if possible.
If a computer executing a program is like a car running a race, a method call is like a detour. That's not necessarily bad except there's a strong temptation to nest those things, because once you're written a method call, you tend to forget what that call could cost you.
If your're relying on events and notifications, it's because you have multiple data structures that need to be kept in agreement. This is costly, and should only be done if you can't avoid it.
In my experience, the biggest performance killers are too much data structure and too much abstraction.
I was amazed at the speedup I got by replacing a for loop adding numbers together in structs:
const unsigned long SIZE = 100000000;
typedef struct {
int a;
int b;
int result;
} addition;
addition *sum;
void start() {
unsigned int byte_count = SIZE * sizeof(addition);
sum = malloc(byte_count);
unsigned int i = 0;
if (i < SIZE) {
do {
sum[i].a = i;
sum[i].b = i;
i++;
} while (i < SIZE);
}
}
void test_func() {
unsigned int i = 0;
if (i < SIZE) { // this is about 30% faster than the more obvious for loop, even with O3
do {
addition *s1 = &sum[i];
s1->result = s1->b + s1->a;
i++;
} while ( i<SIZE );
}
}
void finish() {
free(sum);
}
Why doesn't gcc optimise for loops into this? Or is there something I missed? Some cache effect?