Skip to content
This repository

export keyword #121

Closed
ghost opened this Issue April 07, 2012 · 24 comments

2 participants

Satoshi Murakami Nadav Ivgi
Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

I was wondering if it'd be possible to add an export keyword. The reason is that in some JavaScript environments (hint hint, QtScript) people tend to require certain variable on the global scope. However, with the QtScript transition to V8, adding them to the "this" property will become a strict mode error if you don't use .call on a method, furthermore, many implementations don't posses a window-like object for the global scope.

The solution is to use the bare mode, but this isn't desirable. Instead I would propose the use of a special keyword, export.

a = 1
function randomNumber
 ...
export function eventAttacked victim, attacker
 ...

Might compile to:

var eventAttacked;
(function(){
 var a;
 eventAttacked = function (victim, attacker) { ... }
 function randomNumber () { ... }
 a = 1;
})();
Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 07, 2012

adding them to the "this" property will become a strict mode error

You mean, the global object is frozen by default in that environment or something? Then you shouldn't be able to add global variables at all.

Running

<script>
"use strict"
var a
Object.freeze(this)
a = 1
</script>

on Firefox 11 gives Error: a is read-only.

Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

"use strict"

function f () {
 this.q = 3;
}
f()
console.log(q);
ryan@R26695g /tmp $ node file

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
TypeError: Cannot set property 'q' of undefined
    at f (/tmp/file:4:9)
    at Object.<anonymous> (/tmp/file:6:1)
    at Module._compile (module.js:432:26)
    at Object..js (module.js:450:10)
    at Module.load (module.js:351:31)
    at Function._load (module.js:310:12)
    at Array.0 (module.js:470:10)
    at EventEmitter._tickCallback (node.js:192:40)

In strict mode, you can't use this inside a function that's not a property of an object or called with the call method. The compiler wraps all your code in a function. Using the bare option defeats the safeguards.

Edit: Fixed

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 07, 2012

That's why we use .call(this) rather than just ().

Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

@satyr
Sorry, maybe this(coco example) better shows my point:

"use strict"

this.x = 0
x := 3 # error
x = 4 # wrong
function e
 x := 2 # error
 this.x = 3 # error

Yes, it can be gotten around, but there are times when your environment does stupid things...

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 07, 2012

x := 2 # error

How?

this.x = 3 # error

Depends on how e is called.

Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

Well, you have to remove the line marked #wrong to get the error. It's an "undeclared variable" error.

And I don't want to call e with funny calls every time, or bind every function in my code. I think an export would be a better solution, it's much less coding.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 07, 2012

Assuming your intention at this.x = 3 is to change global x,

global = this
function e
  global.x = 3

is what you want.

Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

Isn't that rather verbose?

And the issue is when I want to do that with a function.
do f
export function f

I would have to opt for the much less readable global.f = function ... for every function in my code which needs to be put on the global object.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 07, 2012

less readable global.f = function

On top level that's merely @f = ->.

Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

I'm not always going to be on the top level, if I want to reference it, I have to make the global object a variable, or call all my functions using .call @

global = this
@a = !(b, c) ->
 d
function e
 global.a 3, 6

I think export would be easier, it hurts my eyes to see functions assigned, especially with all that extra stuff...

Edit: Fixed.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 07, 2012

@a = (b, c) !->

Try @a = !(b, c) ->.

Deleted user ghost closed this April 07, 2012
Deleted user ghost reopened this April 07, 2012
Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

The @a syntax does NOT hoist the functions. I have multiple files, and if I run code in part of it, a function may be in another file. It might end up below code that requires it. A good example is a util file: The functions have to be hoisted, if they aren't, they wont be available to most files. (those that start with anything which comes before u.)

I'm aware you don't like using multiple files and joining them. But we don't all live in a node.js environment where we can require the other files.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 07, 2012

Ah, hoisting. In that case you do need export function I guess. See #116 and the mockup I wrote there.

Deleted user
ghost commented April 07, 2012

The content you are editing has changed. Reload the page and try again.

Looks good. Though I would make export work with regular variables as well.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Nadav Ivgi

I would personally rather have export exporting to exports if it exists (as in the #116 mockup, where __out is set to exports ? this).

Currently I'm using a modified version of CoffeeScript where export sets any expression that can have a name determined for on exports, which includes variables, classes and assignments. It looks like that:

macro func 'export', (expr) -> assign(
  objAccess (value 'exports'),
    if      expr instanceof Class  then expr.determineName()
    else if expr instanceof Assign then expr.variable
    else if expr instanceof Value  then expr
    else throw new Error 'Cannot determine export name'
  expr
)
$ bin/coffee -bep 'export foo = (a,b) -> c'
var foo;

exports.foo = foo = function(a, b) {
  return c;
};
$ bin/coffee -bep 'export bar'
exports.bar = bar;
$ bin/coffee -bep 'export class Baz'
var Baz;

exports.Baz = Baz = (function() {

  function Baz() {}

  return Baz;

})();

I've been using that for some time now and its been working out quite well for me.

Satoshi Murakami
Owner
satyr commented April 09, 2012

We can further define:

export x, y         #=> export x; export y
export {x: y}       #=> __out <<< {x: y}
export [x, @y] = z  #=> what should this do?

export class Bar

The top level this equals exports in Node though, so you'd rather write class @Bar.

Satoshi Murakami satyr closed this in 7194d43 April 11, 2012
Deleted user
ghost commented April 11, 2012

The content you are editing has changed. Reload the page and try again.

Is it possible to make the whole function return the exported variables? For when some environments use eval on your script...

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 11, 2012

Like how?

Deleted user
ghost commented April 11, 2012

The content you are editing has changed. Reload the page and try again.

export function f
 a()
(function(){
 var __returned = false, __result = {}, __out = typeof exports != 'undefined' && exports || this;
 function f () { 
  a();
 }
 __out.f = f;
 if (!__returned ) __result.f = f;
 __returned = true;
 return __result; 
}).call(this);

Faster way might be to make the code return the "this" object, but that might cause problems.

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 11, 2012

Too bombastic for a relatively narrow use case.

I guess you can just add return this at the end. Ideally your environment should provide meaningful exports or this.

Deleted user
ghost commented April 11, 2012

The content you are editing has changed. Reload the page and try again.

"use return_exports"
?
Then you don't even bother with the other code. (__out)

And for the record, one QtScript environment I script for DOES use eval on your script. It's stupid, I know. They all seem to be stupid somehow, seems to be a thing with programs which use QtScript.

Edit: Just realised this wont work, since there's no way to put the "use return_exports" at the top of the script for sure...

Sending Request…

Attach images by dragging & dropping or selecting them. Octocat-spinner-32 Uploading your images… Unfortunately, we don't support that file type. Try again with a PNG, GIF, or JPG. Yowza, that's a big file. Try again with an image file smaller than 10MB. This browser doesn't support image attachments. We recommend updating to the latest Internet Explorer, Google Chrome, or Firefox. Something went really wrong, and we can't process that image. Try again.

Satoshi Murakami
Owner
satyr commented April 11, 2012

It does sound like hard to make QtScript code reusable in browser/CommonJS.

Maybe you can abuse hoisting:

$ coco -sp
  eval Coco.compile """
    export a = 1
    return exports
    function exports then
  """

{ [Function: exports] a: 1 }
Nadav Ivgi
Satoshi Murakami
Owner
satyr commented April 12, 2012

Hm, this at-name linking is kinda annoying.

the constructor won't be accessible in scopes with different this

It will:

$ coco -bcs
  class @Bar then  # same as: @Bar = Bar = class then

var Bar;
this.Bar = Bar = (function(){
  Bar.displayName = 'Bar';
  var prototype = Bar.prototype, constructor = Bar;
  function Bar(){}
  return Bar;
}());
josher19 josher19 referenced this issue from a commit in josher19/LiveScript July 27, 2012
George Zahariev merge with coco, change cascade op to .., removed constructor shortha…
…nd, closes #121
1aa4ea5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.