I never like the visual representation of the / cc call, as I can't reflect it back in the code (yes, bad imagination);)
In any case, I think it’s easier to start not with the / cc call, but with the / ec call (to continue), if you are already familiar with exceptions in other languages.
Here is some code that should evaluate the value:
(lambda (x) (/ 1 x))
What if x is equal to "0"? In other languages, we can exclude, what about the circuit? We can leave him too!
(lambda (x) (call/ec (cont) (if (= x 0) (cont "Oh noes!") (/ 1 x))))
call / ec (as well as call / cc) works like a "try" here. In imperative languages, you can easily jump out of a function by simply returning a value or excluding throwing. In functionality you cannot jump, you have to evaluate something. And the call / * comes to the rescue. What it does is an expression under "call / ec" as a function (this is called "cont" in my case) with one argument. When this function is called, it replaces the WHOLE / * argument with it.
So, when (cont "Oh noes!") Replaces the string (call/ec (cont) (if (= x 0) (cont "Oh noes!") (/ 1 x))) with "Oh noes!" .
call / cc and call / ec are almost equal to each other, except for a simpler implementation. This allows you to just jump up, while cc can be shot down from the outside.
paul
source share