Skip to content

Instantly share code, notes, and snippets.

@jsoriano
Last active December 14, 2015 20:39
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsoriano/5145457 to your computer and use it in GitHub Desktop.
Save jsoriano/5145457 to your computer and use it in GitHub Desktop.
Closures that modify a variable of these scopes in different languages
module Main (main) where
import Debug.Trace
import Control.DeepSeq
import Control.Monad.State
type Counter = State Int ()
log' :: Counter -> Counter
log' f = do f
modify (\c -> traceShow c c)
foo :: Counter
foo = modify (+1)
main :: IO ()
main = do deepseq (runState (log' foo >> log' foo) 0) (return ())
function foo() {
var a = 0;
var bar = function() {
a = a + 1;
return a;
}
return bar;
}
f = foo();
console.log(f());
console.log(f());
<?php
function foo() {
$a = 0;
return function() use (&$a) {
$a = $a + 1;
return $a;
};
};
$f = foo();
echo $f();
echo $f();
# Tricky thing: variable to modify cannot be a simple variable, it can if it's only read and not modified
def foo():
a = [0]
def bar():
a[0] = a[0] + 1
return a[0]
return bar
f = foo()
print f()
print f()
# Tricky thing: in ruby you cannot return named functions, but you can
# return lambdas (that need to be called with .call method)
def foo
a = 0
return lambda { a = a + 1 }
end
f = foo
print f.call
print f.call
@ditman
Copy link

ditman commented Mar 12, 2013

I'd rewrite the JS example as this:

var foo = function() {
    var a = 0, 
        bar = function() {
            a = a + 1;
            return a;
        };
    return bar;
};

var f = foo();

console.log(f());
console.log(f());

@ditman
Copy link

ditman commented Mar 12, 2013

And here's closure.php (requires PHP > 5.3.0)!

function foo() {
        $a = 0;
        return function() use (&$a) {
                $a = $a + 1;
                return $a;
        };
};

$f = foo();

echo $f();
echo $f();

Awesome :P

@jsoriano
Copy link
Author

Added!

@jimenezrick
Copy link

Plz, if I don't see monads I get bored:

module Main (main) where

import Debug.Trace
import Control.DeepSeq
import Control.Monad.State

type Counter = State Int ()

log' :: Counter -> Counter
log' f = do f
            modify (\c -> traceShow c c)

foo :: Counter
foo = modify (+1)

main :: IO ()
main = do deepseq (runState (log' foo >> log' foo) 0) (return ())

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment