Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

do does not retain scope #106

Open
kballenegger opened this issue Jun 17, 2014 · 4 comments
Open

do does not retain scope #106

kballenegger opened this issue Jun 17, 2014 · 4 comments

Comments

@kballenegger
Copy link

The do form does not retain its parent scope, the way e.g. let does.

(do () ()) generates (function () { void 0; return (void 0); })(), instead of (function () { void 0; return (void 0); }).call(this)

@Gozala
Copy link
Collaborator

Gozala commented Jul 11, 2014

I think you're right, wanna try to tackle this issue ? I can give some tips how to approach it.

@kballenegger
Copy link
Author

I can try to give it a try when I get a chance. Gonna have to find some time though, might take a few weeks (months?).

@robjens
Copy link

robjens commented Nov 22, 2015

So for me this (transpile) returns

(function () {
    list();
    return list();
})();

Also trying (do (def foo 1) (do (print foo) ())) seems to me it actually does retain scope. Or are we talking macro's here? Also there, in my book, the output is sane. Trying

(defmacro foo [a]
  (do
    (def b 1)
    (do
      (print a)
      (print b)
      (print *ns*)
  ())))
;=> void(0);
(print (foo :bar)) ;=> compiles to console.log(list());
(foo :bar) ;=> compiles to list();

Both print :foo and 1 on executing. Note, the keyword printing out literal, e.g. expansion (*ns* will resolve to wisp.backend.escodegen.generator) is taking place and here a keyword is just a wisp keyword, not a string. Added the *ns* print to illustrate.

Imho, this makes perfect sense. Although there is no way to view the expression (the defmacro 'vaporizes' as a figure of speech) I can't show the expression (isn't there a macro-expand macro usually to serve this end?) but as a function I would assume it is just the same output only outside runtime context, during compile-time.

Taking my macro as function to transpile, I get:

var foo = exports.foo = function foo(a) {
        return (function () {
            var b = 1;
            return (function () {
                var b = 1;
                console.log(a);
                console.log(b);
                console.log(_ns_);
                return list();
            })();
        })();
    };

Note the duplication of the var b = 1 while I only defined it once. This way the value is carried over without touching the calling context of the function expression. Heh, I didn't expect that but yea, it makes sense. So this makes me think Gozala actually fixed this issue since then, and this can be closed??

@riatzukiza
Copy link

If you used an arrow function from ES6, the problem would be solved.

(do
  (def foobar "foo")
  (console.log foobar))

generates

(() => {
  var foobar = "foo";
  return console.log(foobar);
})();

Of course this would end up meaning that the programs generated are then only compatible with environments that use ES6, so a fall-back mechanism should be supported if you wish to generate ES5 compliant code and get similar behavior.

Arrow functions are more efficient than binding/calling a normal function for multiple reasons if they are available.

  1. there is no binding/rebinding going on,
    they execute in the same context.
  2. Arrow functions do not have an arguments object, since
    the do macro does not need to have any
    arguments passed to it, it is not needed,
    and not having it would result in faster execution.

@robjens They aren't talking about lexical scopeing of variables here, they are talking about the context of this. Using a self executing function expression with out binding/calling/applying it results in the content of that function useing the head object as its this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants