//reverse a string with recursion and a closure
function r(str){
var i = str.length-1,results=[],j=0;
function _r(str){
if(i===0){
return results.join('') + str[0];
}
console.log('i = ' + i);
results[j] = str[i];
i--,j++;
console.log('j = ' + j);
return _r(str);
}
return _r(str);
}
I have two questions about the above code:
does the above code break the (my ignorance is showing) stateless nature of function programming?
what if str was a large string, is this implementation slower/more memory intensive than a solution that did not use a closure?
Yes, you're not using the functional paradigm.
In your case you're using the recursion just to loop and the processing is done using variables that are outside of the function. It's really not much different than using global variables (except that they're not global but locals of the outside function).
To reverse a string using the functional approach you should consider that the reverse of a string is composed by last_char + (reverse of middle part) + first_char.
This definition expands naturally into a recursive function... for example:
function rev(str) {
if (str.length < 2) {
// Empty string or a single char... reverse = input
return str;
} else {
return str[str.length-1] + rev(str.slice(1, -1)) + str[0];
}
}
this uses no explicit state (as you may notice there are no assignments at all).
If you're looking for a tail-call optimizable version instead consider:
function rev(todo, done) {
if (todo === "") {
return done;
} else {
return rev(todo.slice(1), todo[0] + (done||""));
}
}
the idea in this case is that the processing case must be return <recursive-call> (in the previous example this is not happening because the result of recursion is added one char to each end before returning).
If your code ends up returning the unprocessed result of a recursive call then the function can be tail-call optimized as no stack space is needed. In other words the recursive call becomes a simple loop.
Finally this is another version, not purely functional but that seems similar to what you're attempting:
function rev(str) {
function rev1(v, i, j) {
if (i >= j) {
return v.join("");
} else {
var t=v[i]; v[i]=v[j]; v[j]=t;
return rev1(v, i+1, j-1);
}
}
return rev1(str.split(""), 0, str.length-1);
}
This is not purely functional because the vector elements are swapped (and you can see there are assignments) but uses a tail-call optimizable recursion to do the loop. Note that rev1 is not a closure but a function (captures no state and you can also put it outside of rev).
Related
I'm trying to simplify the introduction of loops to children in JS and p5.js with writing some helper functions to ease difficult things. What I'm aiming for is something like repeat(5){ //code to be executed 5 times }
something similar can be achieved with a higher order function, but it's not quite as simple/transparent as I hope it could be.
for example:
function repeat(n = 1) {
let i = 0;
return fn => {
while(n--) {
i++;
fn(i)
}
}
}
// example usage:
repeat(10)(i => {
console.log('floop boop', i)
})
but the usage and curly/parens will confuse children. I'm aware that a while loop is one direction to go, but It's sort of goes in an inverse direction of what a repeat loop might do. It's the direction to push them, but maybe not ideal for day 1 of coding.
ultimately We could eventually use it something like:
let i = 0;
repeat(10){
i++
console.log('we are repeating and we're on iteration number ', i)
}
If you are teaching JavaScript you won't be able to avoid first class functions. I would start by creating a method called repeat, it takes in a number of times to repeat and the function with the behaviour you want repeated.
function repeat(times, fn) {
var i = 0;
while(times--) {
i++;
fn(i);
}
}
repeat(10, function(i) {
console.log('we are repeating and we\'re on iteration number ', i);
});
I agree that a higher order function may be confusing. In both cases you don't need functions to teach loops.
I'm using Coffescript and p5.
for i in range 10
rect 20*i,20,10,10
Range has same defintion as in underscore.
Python indentation without colon
P5dojo.com is my site.
Why/when would one use .concat() in place of assignment operators?
i.e. if I am trying to combine the following:
var p1 = "My name is ";
var p2 = "Joe";
var sen = p1+p2;
//Or you could use concat to do the same
var sen2 = p1.concat(p2);
//My question is, why would you ever use the latter?
Sometimes its best to consult the documentation: Array.concat, and String.concat.
Simply, Array.concat() is used to create a new array equivalent to the flat merging of all passed in objects (arrays or otherwise). String.concat() is used to create a new string, which is equivalent to the merging of all passed in strings.
However, as MDN hints at, String.concat() should not be used as the assignment +, += operators are much faster. Why then would you use String.concat()? You wouldn't. Why have it then? It's part of the spec: See Page 111 - 112 (Section: 15.5.4.6).
So on to the question of Why is String.Concat so slow?. I did some digging through Chrome's V8 Engine. To start with, behind the scenes, this is what a call to String.prototype.concat is doing:
// ECMA-262, section 15.5.4.6
// https://github.com/v8/v8/blob/master/src/string.js#L64
function StringConcat(other /* and more */) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "String.prototype.concat");
var len = %_ArgumentsLength();
var this_as_string = TO_STRING_INLINE(this);
if (len === 1) {
return this_as_string + other;
}
var parts = new InternalArray(len + 1);
parts[0] = this_as_string;
for (var i = 0; i < len; i++) {
var part = %_Arguments(i);
parts[i + 1] = TO_STRING_INLINE(part);
}
return %StringBuilderConcat(parts, len + 1, "");
}
As you can see all of the real work happens in StringBuilderConcat, which then calls a StringBuilderConcatHelper which then finally calls String::WriteToFlat to build a string. These are each extremely long functions and I've cut most of it out for brevity. But if you'd like to look for your self have a look in github:
StringBuilderConcat
// https://github.com/v8/v8/blob/master/src/runtime.cc#L7163
RUNTIME_FUNCTION(Runtime_StringBuilderConcat) {
// ...
StringBuilderConcatHelper(*special,
answer->GetChars(),
FixedArray::cast(array->elements()),
array_length);
// ...
}
StringBuilderConcatHelper
template <typename sinkchar>
static inline void StringBuilderConcatHelper(String* special,
sinkchar* sink,
FixedArray* fixed_array,
int array_length) {
// ...
String::WriteToFlat(string, sink + position, 0, element_length);
// ...
}
String::WriteToFlat
// https://github.com/v8/v8/blob/master/src/objects.cc#L8373
template <typename sinkchar>
void String::WriteToFlat(String* src,
sinkchar* sink,
int f,
int t) {
String* source = src;
int from = f;
int to = t;
while (true) {
// ...
// Do a whole bunch of work to flatten the string
// ...
}
}
}
Now what's different about the assignment pathway? Lets start with the JavaScript addition function:
// ECMA-262, section 11.6.1, page 50.
// https://github.com/v8/v8/blob/master/src/runtime.js#L146
function ADD(x) {
// Fast case: Check for number operands and do the addition.
if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x);
if (IS_STRING(this) && IS_STRING(x)) return %_StringAdd(this, x);
// Default implementation.
var a = %ToPrimitive(this, NO_HINT);
var b = %ToPrimitive(x, NO_HINT);
if (IS_STRING(a)) {
return %_StringAdd(a, %ToString(b));
} else if (IS_STRING(b)) {
return %_StringAdd(%NonStringToString(a), b);
} else {
return %NumberAdd(%ToNumber(a), %ToNumber(b));
}
}
First thing to note, there's no loops and its quite a bit shorter compared to StringConcat up above. But most of the work we're interested in happens in the %_StringAdd function:
// https://github.com/v8/v8/blob/master/src/runtime.cc#L7056
RUNTIME_FUNCTION(Runtime_StringAdd) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
isolate->counters()->string_add_runtime()->Increment();
Handle<String> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result, isolate->factory()->NewConsString(str1, str2));
return *result;
}
This is pretty simple actually, some counters and a call to something called NewConsString with the left and right operands. NewConsString is also pretty simple:
// https://github.com/v8/v8/blob/master/src/ast-value-factory.cc#L260
const AstConsString* AstValueFactory::NewConsString(
const AstString* left, const AstString* right) {
// This Vector will be valid as long as the Collector is alive (meaning that
// the AstRawString will not be moved).
AstConsString* new_string = new (zone_) AstConsString(left, right);
strings_.Add(new_string);
if (isolate_) {
new_string->Internalize(isolate_);
}
return new_string;
}
So this just returns a new AstConsString, what's that:
// https://github.com/v8/v8/blob/master/src/ast-value-factory.h#L117
class AstConsString : public AstString {
public:
AstConsString(const AstString* left, const AstString* right)
: left_(left),
right_(right) {}
virtual int length() const OVERRIDE {
return left_->length() + right_->length();
}
virtual void Internalize(Isolate* isolate) OVERRIDE;
private:
friend class AstValueFactory;
const AstString* left_;
const AstString* right_;
};
Well this doesn't look like a string at all. Its actually an 'Abstract Syntax Tree', this structure forms a 'Rope' which is efficient for modifying strings. It turns out most of the other browsers now use this type or rope structure when doing string addition.
The take away from this, is that the addition pathway uses a more efficient data structure, where as StringConcat does significantly more work with a different data structure.
According to Javascript: The Good Parts by Douglas Crockford:
The concat method makes a new string by concatenating other strings
together. It is rarely used because the + operator is more convenient
Concat is not only less convenient, it is also slower: Benchmark
On the documentation page from MDN:
It is strongly recommended that assignment operators (+, +=) are used
instead of the concat method.
Javascript has some less than ideal parts. Every language has at least some bad parts. Don't think you have to use every part of any language.
Can anyone see a problem with a recursive function written like this:
var recurse = 100;
var recursed = 0;
(function (callback){
callback(callback);
})(function(callback){
recursed++;
console.log('recursed ' + recursed + ' times');
if(recursed < recurse){
callback(callback);
}
});
Is there any reason why this might execute slower? Or might be considered bad practise?
Is this functional programming gone AWOL?
The core principles of functional programming are data immutability and functions being functions in mathematical sense (i.e. take value and return value without any side-effects). Those principles form referential transparency, i.e. given the same arguments a function will always return the same result.
Your function does not satisfy any of those criteria to be referred to as "functional".
The following is an example of how recursion is done in functional style:
var recursiveFunction = function( count, max ) {
if( count < max ){
return recursiveFunction( count + 1, max )
} else {
return count
}
}
var result = recursiveFunction(0, 100) // result == 99
Is there any reason why this might execute slower?
Yes. JavaScript is hardly tail-call-optimized. A loop would be faster.
Or might be considered bad practise?
Yes. Your example code is unreadable, it's hard to grasp what all these callbacks do.
If you want to use recursion for something like this, an IENFE (Named & Immediately Executed Function Expression) would be a better choice:
(function callback(recursed) {
console.log('recursed ' + recursed + ' times');
if (recursed < 100)
callback(recursed + 1);
})(0);
See the following pseudocode snippet that approximates my situation:
function foo () {
for ( velocity=0; velocity<100; velocity++ ) {
root1 = computeRoot1();
root2 = computeRoot2();
// do a bunch of computation with root1
// if result of computation is undesirable, do computations again with root2
}
So, basically I want to do the computations in the body of the for loop with root1, and then root2 if root1's computation result is invalid.
My first instinct was the obvious approach, to wrap the computation in a help function, but I'm not sure this is the most clear approach. I'm trying for good collocation of information in my code, and a function call for code that will be executed at most twice (per iteration) defeats that goal without providing a great deal of conciseness to my code.
I was thinking perhaps a for loop like:
for ( root=root1; root1IsInvalid==true || bothRootsInvalid==true; root=root2 )
or a while with similar functionality. But I'm certainly open to other suggestions
As someone reading this code, which approach would make it the most readable and concise to you?
As an aside, I'm writing this particular function in JavaScript, but language-agnostic solutions would be awesome.
EDIT: clarified code snippet
You have several basic approaches:
Put the values in an array and use a for loop to run the same code on each item in the array, perhaps stopping the iterations when some condition is met.
Create a function that does the computation and then just write code that calls the function on the first one, then the second one and so on.
Create a while loop and repeat your code until some condition is met.
The first option is easier to extend to N items. The second option is perhaps simpler for just two items.
You can make the computation function be a local function (declared and used inside the function you are currently executing) so it doesn't add to the global namespace and your code remains more encapsulated.
I'm also not sure what you intend to be doing with this line:
root1, root2 = computeRoots();
But, it is only assigning the value to root2 and it looks like you probably want var in front of these to define them as local variables.
If eager evaluation is OK, you can collect your roots into an array and use roots.filter(isinvalid) to take out the invalid ones; then just use the first item in the resulting array.
If you need lazy evaluation, you can generalize this into a function that lazily evaluates a function over an array until a non-null result is found:
// call fn on items in arr until fn returns non-null
// returns [item, result]
// if result===false, no true value was returned
function firstNotNull(fn, arr) {
var i, length, item, result=null;
for (i = 0, length=arr.length; i < length; i++) {
item = arr[i];
result = fn(item);
if (result!==null) {
break;
}
}
return [item, result];
}
function rootComputations(root) {
var computationResult = null;
if (root==1) {
computationResult = 1;
}
return computationResult;
}
function computeRoots() {
return [0,1];
}
function foo() {
var velocity, roots, root, result, computations;
for (velocity = 0; velocity < 100; velocity++) {
roots = computeRoots();
computations = firstNotNull(rootComputations, roots);
console.log(computations);
root = computations[0];
result = computations[1];
}
}
foo();
You can generalize firstNotNull() even further:
// call fn on items in arr until cond(fn(item)) returns true
// returns [item, fn(item)], or null if unsatisfied
function firstSatisfying(cond, fn, arr) {
var i, length, item, fnitem, result=null;
for (i = 0, length=arr.length; i < length; i++) {
item = arr[i];
fnitem = fn(item);
if (cond(fnitem)) {
result = [item, fnitem];
break;
}
}
return result;
}
var firstNotNull = firstSatisfying.bind(null, function(item){return item!==null;});
You now have a generic function for taking the first of a list of things that satisfies any condition you want.
ECMAScript 5 added many methods which make eager functional application over arrays much easier, but Javascript doesn't have any native facilities for lazy evaluation. If this is something you think you'll be needing often, consider using stream.js, which provides a "stream" datatype with methods for partial application. Using stream.js, your logic would look like this:
// rootStream should be a function which returns a Stream
// It should construct a stream with the first root produced
// and a function that returns the remaining roots.
// Since I don't know how you get your roots, I'll use a stupid example:
function rootStream() {
return new Stream(0, function(){
return new Stream(1);
});
}
function isvalid(root) {
return root===1;
}
Stream.range(0,100)
.walk(function(v){
//v doesn't seem to be used?
var firstvalid = rootStream().filter(isvalid).head();
console.log(firstvalid);
});
I am trying to recursively print out the contents of jQuery. I'm planning on using this to analyze an existing instance of jQuery (loaded in a page) against a small database of known "jQuery signatures", to determine what changes have been made (i.e. what plugins have been loaded, functions modified, etc.).
To do this, I have this small function:
function recurse(obj, iter){
var padding = (new Array(iter + 1)).join(" ") + ">";
for (var i in obj){
document.writeln(padding + i + "<br/>");
if (iter < 5)
recurse(obj[i], iter + 1);
}
}
When I execute this:
recurse(jQuery, 1);
I get something like this:
>prototype
>init
>prototype
>init
>prototype
>selector
>jquery
>0
.... On and on and on .....
My problem is, at the very beginning, you can see that prototype and then init repeat over and over again. The only reason it stopped at 5 deep is because of the if (iter < 5) check. If the limit wasn't there, it would have recurred [sic?] forever. The iteration limit helps, but what if there is a critical function 6 deep? Essentially, I have no idea what I should make this iteration limit, or if there should be one at all.
Instead, I'm thinking there must be some kind of algorithm that can prevent never-ending recursion. Does such an algorithm exist? Or should I change how I go about traversing jQuery? Thanks,
You could keep track of what values you've already seen, and just bail out when you see one again.
function recurse(obj) {
var marker = '__' + new Date().getTime() + '__';
function r(obj, iter) {
if (marker in obj) return;
var padding = (new Array(iter + 1)).join(" ") + ">";
obj[marker] = true;
for (var i in obj) {
if (!obj.hasOwnProperty(i) || i === marker) continue;
document.writeln(padding + i + "<br/>");
recurse(obj[i], iter + 1);
}
}
r(obj, 0);
}
Now this of course has the disadvantage of leaving your traversed object graph littered with extra properties, but for some applications that wouldn't be a problem. Also using the clock to make a "unique" marker is really lame; you might want to just use a counter, or maybe just a fixed nonsense string.
edit — Also, another issue (present in the original code too) is that this really should be checking to see if the "obj" values are really objects. If they're scalars, then there's no point doing anything, really. You'd just need to do a "typeof" check right after checking for the marker, and if you see null, a number, a string, or a boolean, just return.
Your recursion is missing a base case. See the definition of Recursion. You introduced an arbitrary base case of (depth < 5). Maybe instead use the length of the array, or as Pointy pointed out, the hasOwnProperty check to skip the recursive call.
Unless i am missing something, all you need to do is to skip strings (if you use a modern browser that allows indexing of strings, otherwise it doesn't matter) and the init function which is the jQuery self reference that gives you the infinite recursion
function recurse(obj, iter){
var padding = (new Array(iter + 1)).join(" ") + ">";
for (var i in obj){
document.writeln(padding + i + "<br/>");
if (i != 'init' && typeof obj[i] != 'string')
recurse(obj[i], iter + 1);
}
}
As several answers said: You algorithm must contain a proper break case to prevent infinite recursion.
But what happen if you cannot control the input of your algorithm?
For that case, or just for development purposes, you could use this:
function acmeRecursion(){
var count = localStorage.getItem("count");
if(count>50){
throw new Error("recursion limit exceeded");
}
count++;
//put your logic here
}
Building off of Pointy's answer (ideally this would be a comment, but alas, code doesn't work great in those), a better solution might be to just pass along an object to the the recurse function that will keep track of objects you've already seen. Something like this:
var recurse = function(obj)
{
var seen = {};
var inner = function(obj, padding)
{
for (var i in obj)
{
if (!(obj[i] in seen))
{
document.writeln(padding + i + '<br />');
seen[obj[i]] = true;
inner(obj[i], padding + ' ');
}
}
};
return inner(obj, '');
};
Which uses a closure rather than an argument to pass along the seen object, for the sake of simplicity, but the basic concept is the same.
This approach has the advantage of not adding extra attributes to the objects you're traversing.
Edit: I meant to explain this, but forgot. I'm not using hasOwnProperty here because in the case of printing an object graph, you probably do want to see inherited attributes.