[PROPOSAL] "use" keyword

# Michaël Rouges (10 years ago)

There is any plan around un functionnality like the "use" keyword, in PHP.

Why something like that? Because, in JS, there is no way to inject some variables, without touch the this object known in a function.

The lone possible way is with ownmade functions, in the same context, by :

`var test, fn;

fn = new Function('value', 'return function (){console.log(value);}');

fn('hello');`

Really boring to share some private variables...

Michaël Rouges - Lcfvs - @Lcfvs

# David Bruant (10 years ago)

Le 25/07/2014 20:52, Michaël Rouges a écrit :

Hi all,

There is any plan around un functionnality like the "use" keyword, in PHP.

Why something like that? Because, in JS, there is no way to inject some variables, without touch the this object known in a function.

Can you give an example of what you call "injecting some variables"? More generally, can you give a concrete example of what you're trying to achieve?

Thanks,

# Andrea Giammarchi (10 years ago)

I am not sure I understand your problem but AFAIK php introduced "use" to simulate JavaScript implicit outer scope access instead of the explicit global context php is (in)famous for, it comes quite as a surprise you are asking JS to simulate PHP here :-)

`var test, fn;

fn = new Function('value', 'return function (){console.log(value);}');

fn('hello');`

I don't see why would you pass through Function instead of just wrapping that function.

var fn = (function(floatNum, genericString){
  return function (anotherArg) {
    console.log(floatNum, genericString, anotherArg);
  };
}(
  // here the equivalent of your "use"
  Math.random(),
  'whatever'
));

fn('yo'.sup());

will produce something like:

0.3651656119618565, whatever, <sup>yo</sup>

Best

# Tab Atkins Jr. (10 years ago)

On Fri, Jul 25, 2014 at 11:52 AM, Michaël Rouges <michael.rouges at gmail.com> wrote:

Hi all,

There is any plan around un functionnality like the "use" keyword, in PHP.

PHP's use() syntax is because PHP doesn't have actual lexical closures; it's a hack around the lack.

Why something like that? Because, in JS, there is no way to inject some variables, without touch the this object known in a function.

"Injecting variables into a function" is typically done by passing arguments.

The lone possible way is with ownmade functions, in the same context, by :

`var test, fn;

fn = new Function('value', 'return function (){console.log(value);}');

fn('hello');`

This is functionally identical to:

fn = function(value) { return function() { console.log(value); }; fn("hello")

Using the Function constructor here doesn't seem to offer anything at all over just writing a normal function. Am I missing something?

# Michaël Rouges (10 years ago)

Sure... I make a library that that needs to share a private variable with all methods of an instance passed by arguments on my lib' method.

var lib;

(function () {
    var shared;

    shared = 'a shared value';

    lib = {
        method: function method(foreignObject) {
            var property;

            for (property in foreignObject) {
                if (foreignObject.hasOwnProperty('property') {
                    if (typeof foreignObject === 'function') {
                        // how to pass the "shared" variable
                        // preserving the inside this in foreignObject
methods
                        // and without to touch the methods args?
                    }
                }
            }
        }
    };
}());```

The nearest way is something like this :

var foreignObject;

foreignObject = { method: function method(shared) { console.log(shared); } };

lib.method(foreignObject);


And, in place of the lib.method comments :

foreignObject[property] = foreignObject[property].bind(foreignObject, shared);


It's really boring, because :
- it don't works with non-writable methods,
- it risks to loose the inside this of the methods (if not equal to
foreignObject),
- it forces to have a 'shared' arguments on each foreignObject method


Better? :)


Michaël Rouges - https://github.com/Lcfvs - @Lcfvs
# Andrea Giammarchi (10 years ago)

function wrap(method) { return function () { var args = [].slice.call(arguments); args[0] = shared; return method.aply(this, args); }; }

foreignObject[property] = wrap(foreignObject[property]);

?

you still have the problem with the non writable methods ... but hey, that's exactly the reason people make methods non writable .. you know, if you don't own objects don't be that obtrusive ;-)

# Michaël Rouges (10 years ago)

@Andrea :

Yeah, I don't really want to rewrite the methods, I only want to share my "shared" variable with these methods.

Furthermore, your code don't works because "method" don't knows "shared".

Michaël Rouges - Lcfvs - @Lcfvs

# Tab Atkins Jr. (10 years ago)

On Fri, Jul 25, 2014 at 12:56 PM, Michaël Rouges <michael.rouges at gmail.com> wrote:

Hi David.

Sure... I make a library that that needs to share a private variable with all methods of an instance passed by arguments on my lib' method.

var lib;

(function () {
    var shared;

    shared = 'a shared value';

    lib = {
        method: function method(foreignObject) {
            var property;

            for (property in foreignObject) {
                if (foreignObject.hasOwnProperty('property') {
                    if (typeof foreignObject === 'function') {
                        // how to pass the "shared" variable
                        // preserving the inside this in foreignObject
methods
                        // and without to touch the methods args?
                    }
                }
            }
        }
    };
}());```

Ah, so you've got a "private" variable (declared in a closure) that you want to share with other objects which aren't created in the same closure.

This is what Symbols/WeakMaps were made for. Precisely how to use them depends on exactly what you're going for and what your constraints are, but I'm confident you could bodge something together with a WeakMap without too much trouble.

# Rick Waldron (10 years ago)

On Fri, Jul 25, 2014 at 4:25 PM, Michaël Rouges <michael.rouges at gmail.com>

wrote:

@Andrea :

Yeah, I don't really want to rewrite the methods, I only want to share my "shared" variable with these methods.

Furthermore, your code don't works because "method" don't knows "shared".

You could temporarily (or not) share the data as a property of the foreign object's method itself.

gist.github.com/rwaldron/7a3fe8bd49831978846e

# Andrea Giammarchi (10 years ago)

the method knows shared as soon as you define it inside your closure ...

var lib;

(function () {
    var shared;

    shared = 'a shared value';

    function wrap(method) {
      return function () {
        var args = [].slice.call(arguments);
        args[0] = shared;
        return method.aply(this, args);
      };
    }

    lib = {
        method: function method(foreignObject) {
            var property;

            for (property in foreignObject) {
                if (foreignObject.hasOwnProperty('property')) {
                    if (typeof foreignObject[property] === 'function') {
                        foreignObject[property]
= wrap(foreignObject[property]);
                    }
                }
            }
        }
    };
}());

... take care ...

# Andrea Giammarchi (10 years ago)

forgot to fix one of many typos in your initial example too ... if (foreignObject.hasOwnProperty(property)) { ...

# Rick Waldron (10 years ago)

On Fri, Jul 25, 2014 at 4:29 PM, Tab Atkins Jr. <jackalmage at gmail.com>

wrote:

On Fri, Jul 25, 2014 at 12:56 PM, Michaël Rouges <michael.rouges at gmail.com> wrote:

Hi David.

Sure... I make a library that that needs to share a private variable with all methods of an instance passed by arguments on my lib' method.

var lib;

(function () {
    var shared;

    shared = 'a shared value';

    lib = {
        method: function method(foreignObject) {
            var property;

            for (property in foreignObject) {
                if (foreignObject.hasOwnProperty('property') {
                    if (typeof foreignObject === 'function') {
                        // how to pass the "shared" variable
                        // preserving the inside this in foreignObject
methods
                        // and without to touch the methods args?
                    }
                }
            }
        }
    };
}());```

Ah, so you've got a "private" variable (declared in a closure) that you want to share with other objects which aren't created in the same closure.

This is what Symbols/WeakMaps were made for.

I'd be interested to see what your approach would be—afaict, this would require exposing the Symbol or WeakMap to whatever scope the foreign object is defined in and then there's no point in using either.

# Michaël Rouges (10 years ago)

@ TJ, Rick :

I'm really interested too!

On an another side, my next idea, for the same goal, is a thing like :

Function.prototype.attachContext()

Where an "attachContext" call can share the context of the current scope with the related function.

Michaël Rouges - Lcfvs - @Lcfvs

# Rick Waldron (10 years ago)

On Fri, Jul 25, 2014 at 4:39 PM, Michaël Rouges <michael.rouges at gmail.com>

wrote:

@ TJ, Rick :

I'm really interested too!

On an another side, my next idea, for the same goal, is a thing like :

Function.prototype.attachContext()

Where an "attachContext" call can share the context of the current scope with the related function.

var attachContext = Function.prototype.attachContext; Function.prototype.attachContext = function(context) { malice(context); attachContext.call(this, context); };

# Tab Atkins Jr. (10 years ago)

On Fri, Jul 25, 2014 at 1:35 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Fri, Jul 25, 2014 at 4:29 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

Ah, so you've got a "private" variable (declared in a closure) that you want to share with other objects which aren't created in the same closure.

This is what Symbols/WeakMaps were made for.

I'd be interested to see what your approach would be—afaict, this would require exposing the Symbol or WeakMap to whatever scope the foreign object is defined in and then there's no point in using either.

Yeah, upon actually walking through my desired example, I found that the Symbol/Weakmap is irrelevant. Here's what I was thinking, using only existing stuff:

(function(){
var shared1;

function ForeignObject() { /* Uses shared1 somehow */ }

ForeignObject.setSharedSecret(val) {
  shared1 = val;
}
})();

(function(){
var shared2 = "the real secret";

function MyObject() { /*...*/ }

MyObject.exposeSharedSecret(cb) {
  cb(shared2);
}
})();

MyObject.exposeSharedSecret(ForeignObject.setSharedSecret);
# Michaël Rouges (10 years ago)

Um, no, I was thinking something like :

var fn;

fn = function fn() {
    // After the context is attached fn scope already knows "shared"
};

(function () {
    var shared;

    shared = 'message';

    fn.attachContext();
}());```


Michaël Rouges - https://github.com/Lcfvs - @Lcfvs
# Andrea Giammarchi (10 years ago)

as a knonw convention in your code that would work but I have no idea what was anymore the first request at this point.

Best

# Andrea Giammarchi (10 years ago)
  1. I don't understand what you are trying to do and why
  2. I don't think any of this woul dhave been solved anyway with "use" , neither in PHP

Hope others can help more.

Best

# Rick Waldron (10 years ago)

On Fri, Jul 25, 2014 at 4:53 PM, Tab Atkins Jr. <jackalmage at gmail.com>

wrote:

On Fri, Jul 25, 2014 at 1:35 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

On Fri, Jul 25, 2014 at 4:29 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

Ah, so you've got a "private" variable (declared in a closure) that you want to share with other objects which aren't created in the same closure.

This is what Symbols/WeakMaps were made for.

I'd be interested to see what your approach would be—afaict, this would require exposing the Symbol or WeakMap to whatever scope the foreign object is defined in and then there's no point in using either.

Yeah, upon actually walking through my desired example, I found that the Symbol/Weakmap is irrelevant. Here's what I was thinking, using only existing stuff:

(function(){
var shared1;

function ForeignObject() { /* Uses shared1 somehow */ }

ForeignObject.setSharedSecret(val) {
  shared1 = val;
}
})();

(function(){
var shared2 = "the real secret";

function MyObject() { /*...*/ }

MyObject.exposeSharedSecret(cb) {
  cb(shared2);
}
})();

MyObject.exposeSharedSecret(ForeignObject.setSharedSecret);

Neither of these objects is in scope here.

# Michaël Rouges (10 years ago)

@ Andrea :

The why comes from an another question : why to reserve the variables sharing (across the scopes) for the parenst/childs relations.

Imho, some things should be shared with objects out of this of relationship type, no? :)

Michaël Rouges - Lcfvs - @Lcfvs

# Andrea Giammarchi (10 years ago)

let's do this way: you write down in some working PHP what you are trying to achieve and I'll give you back the equivalent JS, if possible ... otherwise I think I cannot help much here.

Best

P.S. Rick ... lol, true that, but if you imagine those functions returned and used outside that IFI the sharing technique would work somehow, although I still cannot think of any concrete or useful application

# Michaël Rouges (10 years ago)

@Andrea :

There is no real equivalent in PHP.

I only used the "use" keyword as example to suggest, in your mind, an ability to share vars with a foreign function without to touch the foreign function arguments. ;)

Michaël Rouges - Lcfvs - @Lcfvs

# Rick Waldron (10 years ago)

On Fri, Jul 25, 2014 at 5:13 PM, Michaël Rouges <michael.rouges at gmail.com>

wrote:

@Andrea :

There is no real equivalent in PHP.

I only used the "use" keyword as example to suggest, in your mind, an ability to share vars with a foreign function without to touch the foreign function arguments. ;)

Perhaps you missed it, but I demonstrated exactly this: gist.github.com/rwaldron/7a3fe8bd49831978846e

# Rick Waldron (10 years ago)

On Fri, Jul 25, 2014 at 4:57 PM, Michaël Rouges <michael.rouges at gmail.com>

wrote:

Um, no, I was thinking something like :

var fn;

fn = function fn() {
    // After the context is attached fn scope already knows "shared"
};

(function () {
    var shared;

    shared = 'message';

    fn.attachContext();
}());```


It's as if attachContext creates pointers to all bindings in the Lexical and Variable Environment? If any of those bindings are for references, this creates an object capabilities leak.

# Michaël Rouges (10 years ago)

@ Rick :

I don't missed but thanks :)

Your example works but not in an private channel between the 2 scopes.

And on your next post, yeah, it's exactly that sharing the pointers... but in single way (A to B) or (B to A)

And I think to an another Function.prototype method to prevent this effect, a few like a Object.preventExtensions().

Michaël Rouges - Lcfvs - @Lcfvs

# Andrea Giammarchi (10 years ago)

that's the nonsense I am talking about. In php "use" is defined at function definition time, it's not something you can attach later on.

In JS you can use .call and .apply passing any context to any different function, unless already bound to another context, so you have already way more power than PHP methods or generic callbacks, with or without "use"

If you talk about variables as outer scope variables, then I don't udnerstand how you create functions that rely on abstract values around them without knowing what are these values about ... what does it mean sharing variables?

There's a lot of mixed and in my opinion unclear content that has not much to do with "use" or PHP and rather what you are trying to achieve concretely which is still a mystery to me.

Then, trying to understand what brought you here, I've realized here ( Lcfvs/XEncoder.js/blob/master/XEncoder.js#L49 ) you might want to clear-up a little bit, and a part of this thread, how context and scope work in JavaScript, maybe you have all answers already, you just don't see them ;-)

Best

# Michaël Rouges (10 years ago)

@ Andrea :

.call, .apply and .bind change the this in the function, then it can't catch the goal and it doesn't work with non-writable methods again.

It's why my detailled example ( esdiscuss.org/topic/proposal-use-keyword#content-4) is written with object methods (to etablish all constraints).

And don't worry... dont make a fixation on the PHP use, read the last Rick's post. ;)

Michaël Rouges - Lcfvs - @Lcfvs

# Andrea Giammarchi (10 years ago)

.call, .apply works with every non-writable method you want ... Rick answered, I've fixed your broken example (parens missing, checks on the method instead of the object itself, etc ...) and finally Tab wrote what's the closest thing you can think of between two closures, once you export outside those two functions.

I'd done here, good luck with your task.

Best

# Michaël Rouges (10 years ago)

@ Andrea :

Thanks for the fixes, I tried but got "Internal server error", on edit.

The Tab's solution works but not on a secure channel between the closures.

Michaël Rouges - Lcfvs - @Lcfvs

# Michaël Rouges (10 years ago)

@ Rick :

Or a more controlled solution might be to create a method able to only attach one pointer at a time.

What do You think about it?

# Frankie Bagnardi (10 years ago)

I see where this might be convenient, but the down sides are much larger, similar to with, eval, or arbitrary global variables. It essentially destroys the ability of compilers, tools, and people to statically analyze the code.

I'm all for laziness in code (e.g. destructuring), but not when it causes significant problems.

Michaël, sorry, but I think this is a lost cause.

# Michaël Rouges (10 years ago)

Ok, ok, it's a bit that I dreaded opening this topic but the idea of ​​a shared private channel between two foreign scopes seemed interesting enough to suggest, at least to discuss it.

Thanks to all. :)

Michaël Rouges - Lcfvs - @Lcfvs