Is CallCC an improved version of goto? - javascript

My background is Javascript, Python & a bit of Haskell. I am trying to understand callCC, there are many explanations but I can't find them trivial & I came across this https://www.cs.bham.ac.uk/~hxt/research/Logiccolumn8.pdf and I felt like I almost got it but I need some help to understand C code.
Below is the Code for Jumping back into a function in GNU C.
void *label_as_result() {
return &&L;
L: printf("Jumped back into the function. \n");
}
main () {
void *p;
p = label_as_result();
printf("The function returned; now jump back into it.\n");
goto *p;
}
What does return statement do in label_as_result function?
Does p in main store the stack frame in heap & the instruction line where it is stopped?
Jump back to function means create a stack frame again and continue from where we left?
Below this code there is paragraph
But in a language with first-class functions and callCC, no such implementation restrictions apply. Just as with the label as a result in C, we can return a continuation introduced by callCC from a function so as to jump back into the function. When we did this with goto, the stack was smashed, but with callCC the function just returns again. Consider the following function
λ(). callCC(λk. λx. throw k (λy. x))
The continuation k is returned as part of the result, roughly analogous to returning a label as the result in C.
What does stack was smashed, he meant stackoverflow can happen if you use goto? How callCC is getting around this problem using trampolining?
As many say callCC gives Early return semantics that means is it like yield in python or Javascript?
Is it possible to write callCC in Javascript using yield?
How I conceive the above code in Javascript
function* label_as_result() {
yield () => console.log("Jumped back into the function.");
}
p = label_as_result().next().value;
console.log("The function returned; now jump back into it.");
p();
It can even simple be written without any generators concept as
function label_as_result() {
return () => console.log("Jumped back into the function.");
}
p = label_as_result();
console.log("The function returned; now jump back into it.");
p();
That means callCC is a function that returns a continuation but all other functions take continuations.
Continuations are like Undecided code that need to be performed in future but callCC is like predefined code that needs to be performed in Future? (I am talking in perspective of a framework and the user's code)

What does return statement do in label_as_result function?
It returns the address of the instruction labelled L. That is, it returns the address of where the code the compiler generated for printf("Jumped back into the function. \n"); is stored in memory.
Does p in main store the stack frame in heap & the instruction line where it is stopped?
No, it stores the instruction line where the L label is. That's all it stores.
Jump back to function means create a stack frame again and continue from where we left?
No, it means a single jump and nothing else - no stack manipulation. The control flow jumps to the line labelled L, but nothing else changes. The stack remains unchanged.
What does stack was smashed, he meant stackoverflow can happen if you use goto?
Underflow, actually. When label_as_result is called, a frame is pushed to the stack. When it returns, that frame is popped. Then we jump to L, execute printf and then reach the end of the function, which will pop the stack again. So in the end the stack was popped more often than it was pushed.
How callCC is getting around this problem
By actually doing what you assumed the C code was doing: Saving and restoring the stack instead of just jumping to a code line while keeping the stack the same.
As many say callCC gives Early return semantics that means is it like yield in python or Javascript?
They're alike in the sense that they both give you a type of early return and they can be used for some of the same things. You can think of yield as a more specialized tool meant to provide a simpler way to achieve some of the use cases of callCC.
Is it possible to write callCC in Javascript using yield?
No, but it's possible to write yield in Scheme using callCC. callCC is strictly the more powerful of the two.
How I conceive the above code in Javascript
The actual C code isn't something that you can replicate in JavaScript (other than by building a mini-VM with its own stack) because JavaScript doesn't allow you to destroy the stack like that.
A non-broken version that doesn't destroy the stack could be accomplished by returning a function from label_as_result as you do in your second code sample.
That means callCC is a function that returns a continuation
callCC is a function that calls another function with the current continuation. That can be used to return the continuation.
Continuations are like Undecided code that need to be performed in future
Sure, except I wouldn't say "need" here. You don't have to invoke the continuation (or you could invoke it more than once even).
but callCC is like predefined code that needs to be performed in Future?
Not quite sure what you mean here, but that doesn't sound right. callCC is a function that gives you access to the current continuation.

try, throw, catch
callcc can be implemented in direct style using try-catch. The important bit is that the continuation must "box" the return value and "unbox" it in catch to avoid swallowing real errors. Here is a straightforward implementation in JavaScript -
const callcc = f => {
class Box { constructor(v) { this.unbox = v } }
try { return f(value => { throw new Box(value) }) }
catch (e) { if (e instanceof Box) return e.unbox; throw e }
}
console.log(5 + callcc(exit => 10 * 3))
console.log(5 + callcc(exit => 10 * exit(3)))
console.log(5 + callcc(exit => { exit(10); return 3 }))
console.log(5 + callcc(exit => { exit(10); throw Error("test failed") }))
try {
console.log(5 + callcc(exit => { throw Error("test passed!") }))
}
catch (e) {
console.error(e)
}
.as-console-wrapper { min-height: 100%; top: 0; }
35 ✅ 5 + 10 * 3
8 ✅ 5 + 3
15 ✅ 5 + 10
15 ✅ 5 + 10
Error: test passed! ✅ Errors are not swallowed
early return
Given a list of numbers, let's multiply all of them. As humans we know if a single 0 is present, the product must be 0. callcc allows us to encode that same short-circuiting behavior. In the demo below mult(a,b) is used so we can see when actual work is happening. In a real program it could be replaced with a * b -
const callcc = f => {
class Box { constructor(v) { this.unbox = v } }
try { return f(value => { throw new Box(value) }) }
catch (e) { if (e instanceof Box) return e.unbox; throw e }
}
const apply = (x, f) => f(x)
const mult = (a, b) => {
console.log("multiplying", a, b)
return a * b
}
console.log("== without callcc ==")
console.log(
apply([1,2,3,0,4], function recur(a) {
if (a.length == 0) return 1
return mult(a[0], recur(a.slice(1)))
})
)
console.log("== with callcc ==")
console.log(
callcc(exit =>
apply([1,2,3,0,4], function recur(a) {
if (a.length == 0) return 1
if (a[0] == 0) exit(0) // 🔍
return mult(a[0], recur(a.slice(1)))
})
)
)
.as-console-wrapper { min-height: 100%; top: 0; }
== without callcc ==
multiplying 4 1
multiplying 0 4 🔍 here we know the answer must be zero but recursion continues
multiplying 3 0
multiplying 2 0
multiplying 1 0
0
== with callcc ==
0 🔍 the answer is calculated without performing any unnecessary work
cursory benchmark
In a one-off metric, callcc performs at least 50-500 times faster on a list of 20,000 numbers ranging from 0-100 -
const callcc = f => {
class Box { constructor(v) { this.unbox = v } }
try { return f(value => { throw new Box(value) }) }
catch (e) { if (e instanceof Box) return e.unbox; throw e }
}
const apply = (x, f) => f(x)
const A = Array.from(Array(20000), _ => 0 | Math.random() * 100)
console.time("== without callcc ==")
console.log(
apply(A, function recur(a) {
if (a.length == 0) return 1n
return BigInt(a[0]) * recur(a.slice(1))
}).toString()
)
console.timeEnd("== without callcc ==")
console.time("== with callcc ==")
console.log(
callcc(exit =>
apply(A, function recur(a) {
if (a.length == 0) return 1n
if (a[0] == 0) exit(0) // 🔍
return BigInt(a[0]) * recur(a.slice(1))
})
).toString()
)
console.timeEnd("== with callcc ==")
.as-console-wrapper { min-height: 100%; top: 0; }
0
== without callcc ==: 466.000ms
0
== with callcc ==: 1.000ms
read on
callcc was originally implemented in this Q&A. Read on for additional info and examples.

Related

async function does update iterator correctly at the begining but not at the end

In the code bellow I work with CSS DOM, which may be computation heavy. This is apparently necessary to access the :after selector. renderItem method will add a new item to the DOM (including it's after element) and this is the reason why I have used the async function and await for it's return in each iteration inside of loadFromStorage.
However, the await seems to not work correctly, or something weird happens inside of renderItem function. The n iterator is updated correctly at the beginning of the function (items are correctly rendered to the screen and the first console.debug prints a correct value in a correct order), but at the bottom, the second printed value, is always the last iteration value (which is 4 in my case, as I am trying to render 4 items from the local storage) and getCSSRule method is getting a wrong number.
let books = []
let n = 0
const renderItem = async (entry, direction = 1) => {
const li = document.createElement('li')
const ul = document.querySelector('ul')
li.classList.add('item')
n += 1
console.debug(`iter: ${n}`)
li.id = (`item${n}`)
await addCSSRule(`#item${n}:after`)
li.innerText = entry.slice(0, entry.length - 13)
if (direction === 1)
ul.appendChild(li)
else
ul.insertBefore(li, ul.firstChild)
console.debug(`iter: ${n}`)
const s = await getCSSRule(`#item${n}::after`).catch(() => {
console.debug(`Failed to find ':after' selector of 'item${n}'`)
return false
})
s.style.content = "\""+ entry.slice(entry.length - 13, entry.length) +"\""
return true
}
const loadFromStorage = () => {
books = localStorage.getItem('books').split('//')
books.forEach(async (entry) => {
await renderItem(entry)
})
}
...
Console result (considering localStorage.getItem('books').split('//') returns 4 items):
iter: 1
iter: 2
iter: 3
iter: 4
iter: 4 // Printed x4
I been also trying to pass this renderItem method to await inside of a Promise object, which give me the same result. Also when I update the n iterator at the end of function the same thing happens, but at the beginning of it.
I am sorry if some terminology I have used is not correct in the context of JavaScript, I been not using this language for many years and currently I am trying to catch on.
The key problem here is that you're passing an async function to forEach, so even though you're awaiting inside the body of it, forEach will not wait for the function itself. To illustrate the order of events here, say you have 4 books A, B, C, D. Your execution will look something like this.
renderItem(A)
n += 1 (n is now 1)
console.log(n) (logs 1)
await addCSSRule(`#item${1}:after`) (This is a truly asynchronous event, and so this frees up the event loop to work on other things, namely the next elements in the forEach)
renderItem(B)
n += 1 (2)
console.log(n) (logs 2)
...
renderItem(C) ... n += 1 (3) ... await addCSSRule
renderItem(D) ... n += 1 (4) ... await addCSSRule
And then whenever the addCSSRule calls resolve n will always be 4 no matter which call you're in.
Solution
Use a for await...of loop instead of Array.prototype.forEach.
for await (const entry of books) {
await renderItem(entry);
}
Or a traditional for loop, and modify renderItem to take n as an argument
for (let i = 0; i < books.length; i++) {
renderItem(books[i], i+1);
// we don't need to await in this case, and we add 1 to i so that the 'n' value is 1-indexed to match your current behaviour.
}
I would prefer the latter option as it's best practice to avoid mutable global state (your n variable) - as it can lead to confusing control flow and issues just like the one you're having.
One other option is to set a local variable to the value of n after incrementing it inside renderItem, so that for the duration of that function the value won't change, but that seems like a very hacky workaround to me.

Creating an Arithmetic Task Runner

I have been tasked to create an Arithmetic Task Runner as part of my assignment.
Up until today I've never used NodeJS or even the terminal to execute a script.
I have been working on this for the past 5 hours and still no luck. I have avoided coming here and asking as I'd like to figure it out for myself, however, I have succumbed to desperately needing help.
This is the code I have so far:
class ArithmeticTaskRunner {
static set taskCount(counter) {
throw new('This is a readOnly accessor, the value is ${value}');
}
add(y) {
this.y = y || 0
console.log(y)
}
minus(x) {
this.x = Math.abs(this.y) * -1;
console.log(this.x);
};
multiply(z) {
this.z = z * this.x;
console.log(this.z)
}
execute(startValue) {
this.startValue = startValue + this.y
this.y = this.startValue
console.log(this.startValue)
this.startValue = this.minus
console.log(this.startValue)
this.startValue = this.multiply(this.startValue)
console.log(this.startValue)
}
}
tasks = [
function() { minus()},
function() { multiply(z)},
function() { add(x)},
function() { execute(x)}
]
This is nowhere near perfect, but it's 80%-90% near completion.
This is the task I have been given:
You should implement a class called ArithmeticTaskRunner with the following:
- An instance variable named tasks which is initialised to an empty array upon
creation.
- A method named addNegationTask which adds an anonymous function to the
tasks array. This anonymous function should take one argument, x, and return the
negation, -x.
- A method named addAdditionTask which takes a single argument y, and adds
an anonymous function to the tasks array. This anonymous function should take
one argument, x, and return the result x + y.
- A method named addMultiplicationTask which takes a single argument y,
and adds an anonymous function to the tasks array. This anonymous function
should take one argument, x, and return the result x * y.
- A read-only accessor named taskCount which returns the number of queued tasks.
- A method named execute, which takes a single argument named startValue.
If omitted, startValue defaults to zero. Starting at startValue, this method should iterate over the tasks array executing each function on the current value. It then returns the resulting number after all arithmetic operations have been executed.
I'd be grateful for any help I could get.
The issues I have are the following: The execute method (trying to make the startValue, after the addition, a negative), the multiplication method and the fact I cannot call the addition method twice without overriding the value. The examples of the program fully working have shown I should allow for a method to be called multiple times without overriding the previous value.
I know there's a rule where it's one question per issue, I concede that. But if anyone can help me out with any of the issues I will truly be grateful and I will compensate people for their efforts.
Thank you.
Edit - This is an example of both the expected inputs/outputs
> let taskRunner = new ArithmeticTaskRunner()
undefined
> taskRunner.addAdditionTask(2)
undefined
> taskRunner.addMultiplicationTask(4)
undefined
> taskRunner.addAdditionTask(10)
undefined
> taskRunner.execute(2)
26
> taskRunner.execute(-2)
10
I don't want to provide the whole answer because this is an assignment for you, but here's some code that might help you out. This starts with 5 then calls doubleIt and then calls addOne to arrive at 11.
It does this by creating an array of functions, each one performs a simple task and returns the result of its input modified in some way.
Then it creates a function called execute that uses Array.reduce to call the first function in the array with a given initial value, then repeatedly calls each function in the array on the result. Check the documentation for Array.reduce if you're confused about how it works.
doubleIt = x => x * 2;
addOne = x => x + 1;
tasks = [doubleIt, addOne];
execute = (initial) => tasks.reduce((x,fn) => fn(x), initial)
document.write(execute(5))
Hint #2
class ArithmeticTaskRunner {
constructor() {
this.tasks = [];
}
addAdditionTask(arg) {
this.tasks.push(x => x + arg);
}
addMultiplicationTask(arg) {
this.tasks.push(x => x * arg);
}
execute(startValue) {
return this.tasks.reduce((x, fn) => fn(x), startValue);
}
}
let taskRunner = new ArithmeticTaskRunner()
taskRunner.addAdditionTask(2)
taskRunner.addMultiplicationTask(4)
taskRunner.addAdditionTask(10)
document.write(taskRunner.execute(2));
document.write(', ');
document.write(taskRunner.execute(-2));

Closures with recursion JavaScript

//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).

Javascript anonymous function error

I have been trying to use recursion to find the sum of a number using an anonymous function in javascript but I am getting the following error:
Uncaught SyntaxError: Unexpected token +
I want to use an anonymous function for this. Can anyone help me in finding what I am doing wrong here?
<script type="text/javascript">
console.log(function (n) {
if (n == 0) {
return 1;
}
else {
return function(n+function(n-1));
}
}(8));
</script>
There are several problems with what you're doing.
For starters, attempting to call the function recursively (function(n+function(n-1))) will result in a call stack size exceeded error because you're adding the sum to each argument passed to the recursive call. You probably want something closer to (n + function(n-1)).
However, this is still problematic, because you can't call an anonymous function recursively (except by using arguments.callee, which is disallowed in strict mode).
To do what it appears you're trying to do without giving a name to your function expression, you could do something like:
console.log(function(n) {
if (n == 0) {
return 1;
}
else {
return n + arguments.callee(n-1);
}
}(8))
However, you could also provide a name for your function expression to refer to in recursive calls, which will work in strict mode as well:
console.log(function foo(n) {
if (n == 0) {
return 1;
}
else {
return n + foo(n-1);
}
}(8))
edited: In the base case (n == 0) you probably want to return 0 instead of 1 if your goal is to get the sum of all whole numbers from 0 to n.
console.log(function fn(n) {
if (n == 0) {
return 1;
} else {
return (n + fn(n - 1));
}
}(8));
Error in this line function(n+function(n-1)), because this is syntax error, you can not call function like you do. In our case you should add for self-Invoking function - name, and use it for recursion call stack
When I revised the anonymous function to use the correct recursion, namely return n + f(n-1), I discovered that oddly enough the following code works without resorting to arguments.callee as long as the script resides on an HTML page. Note: it still does not work with console.log.
One more thing, if the code in this instance is attempting to get the sum of numbers ranging from eight to one, then when n equals zero, the return value should be zero and not one for the sum to be mathematically correct.
var f = function (n) {
if (n == 0) {
return 0;
}
else {
return n + f(n-1);
}
};
var res = f(8); // 36
See live example at http://jsfiddle.net/d5k4ag8w/11/
Also, this article provides an easy way to figure out the math using just pencil and paper :)

Expressing Y in term of SKI-Combinators in JavaScript

I was fiddling with combinators in JavaScript and was being proud of (hopefully) getting S to work when I stumbled upon Wikipedia saying: "The Y combinator can be expressed in the SKI-calculus as: Y = S (K (S I I)) (S (S (K S) K) (K (S I I)))", so I had to try that:
var I = function (x) {
return x;
};
var K = function (x) {
return function(){
return x;}
};
var S = function (x) {
return function (y) {
return function (z) {
return x(z)(y(z));
}
}
};
var Y = S (K(S(I)(I))) (S(S(K(S))(K)) (K(S(I)(I))));
Y; //evals to:
//function (z) {return x(z)(y(z));}
//And this (lifted from Crockford's Site):
var factorial = Y(function (fac) {
return function (n) {
return n <= 2 ? n : n * fac(n - 1);
};
}); //fails:
//RangeError: Maximum call stack size exceeded
What am I doing wrong? Am I not translating that expression correctly? Is there something wrong with how I'm going about this? Does it even make sense? Most of what's to be read about stuff like this just makes my brain want to explode, so the point of this exercise for me was mainly to see if I understood the notation (and would thus be able to translate it to JavaScript).
Oh, and, by the way: what got me reading & fiddling again was that what prototype.js implements as Prototype.K is actually the I combinator. Has anyone noticed?
The problem here is that you are using a strictly evaluated programming language. The Y-combinator, pretty much like any other fixed point combinator, will only work properly when your functions are called by need, or 'lazily evaluated'.
I know of a way to work around this (one of my professors looked into it a while ago), but it will make your code completely unreadable.
Below I've shown what's going on exactly, hoping you can see why JavaScript can't handle a straightforward implementation of SKI-calculus.
This is what Y looks like after JavaScript evaluated your SKI-expression:
var Y = function (q) {
return (function(p){return q(p(p))})(function(p){return q(p(p))});
};
Now let's see what happens if you feed it your function function (fac) { ... }. Let's call that function f:
var factorial = (function(p){return f(p(p))})(function(p){return f(p(p))});
Since the first anonymous function is applied to an argument, it will be evaluated into this:
var factorial = f(
(function(p){return f(p(p))})(function(p){return f(p(p))})
);
In a lazily evaluated language, the argument to f would now be left alone, and f itself would be evaluated. However, because JavaScript is a strictly evaluated language (or 'call-by-value'), it wants to know what argument it needs to pass to function f before actually running that function. So let's evaluate that argument, shall we?
var factorial = f(f(
(function(p){return f(p(p))})(function(p){return f(p(p))})
)
);
I guess now you're starting to see now where things go wrong, and how the Y-combinator actually works. In any case, your JavaScript machine will run out of stack space, because it's trying to build an infinite stack of calls to f.

Categories