OK, with the advent of ES-Harmony, I have no clue whether the language
will support iterators (and maybe generators) or catch-all methods. I
know that namespaces are out.
But assuming a pre-ES-Harmony mindset:
My solution does have bugs: I forgot to filter the results of
iter.next() in the next() method, and I forgot to handle the non-method
case in the get catch-all. So it's supposed to only enumerate over
properties that the object really owns. So it should replicate exactly
what you want. The fixed (pseudo) code:
// Defined in some library (possibly builtin)
class OwnPropertiesEnumerator {
val obj;
val iter;
OwnPropertiesEnumerator(obj) {
this.obj = obj;
this.iter = obj.iterator::get();
}
public function next() {
var x = meta::get(iter.next());
while (x == undefined) {
x = meta::get(iter.next());
}
return x;
}
meta function get(name) {
if (obj.hasOwnProperty(name)) {
if (obj[name] is Function) {
// make sure |this| in a method doesn't refer to an
instance of this class
return function(...args) {
if (this is OwnPropertiesEnumerator)
return obj[name].apply(obj, args);
return obj[name].apply(this, args);
}
} else {
return obj[name];
}
}
}
meta function set(name, value) {
obj[name] = value;
}
meta function has(name) {
return obj.hasOwnProperty(name);
}
meta function delete(name) {
if (obj.hasOwnProperty(name))
delete obj[name];
}
}
Object.prototype.own = function() {
return new OwnPropertiesEnumerator(this);
}
Object.prototype.propertyIsEnumerable("own", false);
...
// User code
print(foo.own().bar);
print(foo.own().toString); // prints undefined
for (var prop in foo.own()) // does not enumerate toString and co.
print(prop + ": " + foo[prop]);
Ingvar von Schoultz wrote:
> YR Chen wrote:
> > But the syntax you propose is redundant, since you can define a own()
> > method returning an iterator (for for...in) and a getOwn() method to do
> > the same thing.
>
> What people wanted so hotly was an object completely unpolluted
> by inheritance from Object. It should have no .toString() etc.
> Your solution does inherit material from Object (and Function).
>
> Therefore the important thing is that obj[*own] is unpolluted.
> And yet it can inherit anything you want, and this inherited
> material is accessible unambiguously through obj[*!own].
>
> Ingvar
>
>
>
> YR Chen wrote:
> > (Oops, forgot to reply all, so repost)
> >
> > But the syntax you propose is redundant, since you can define a own()
> > method returning an iterator (for for...in) and a getOwn() method to do
> > the same thing. Or, if you think getOwn() is ugly, you can customize the
> > own() method to also return a "view" object:
> >
> > // Defined in some library (possibly builtin)
> > class OwnPropertiesEnumerator {
> > val obj;
> > val iter;
> > OwnPropertiesEnumerator(obj) {
> > this.obj = obj;
> > this.iter = obj.iterator::get();
> > }
> > function next() {
> > return iter.next();
> > }
> > meta function get(name) {
> > if (obj.hasOwnProperty(name))
> > if (obj[name] is Function) {
> > // make sure |this| in a method doesn't refer to an
> > instance of this class
> > return function(...args) {
> > if (this is OwnPropertiesEnumerator)
> > return obj[name].apply(this.obj, args);
> > return obj[name].apply(this, args);
> > }
> > }
> > return obj[name];
> > }
> > meta function set(name, value) {
> > obj[name] = value;
> > }
> > meta function has(name) {
> > return obj.hasOwnProperty(name);
> > }
> > meta function delete(name) {
> > if (obj.hasOwnProperty(name))
> > delete obj[name];
> > }
> > }
> > Object.prototype.own = function() {
> > return new OwnPropertiesEnumerator(this);
> > }
> > Object.prototype.
> > propertyIsEnumerable("own", false);
> >
> > ...
> >
> > // User code
> > print(foo.own().bar);
> > for (var prop in foo.own())
> > print(prop + ": " + foo[prop]);
> >
> > Or something like that. I'm not completely familiar with ES4 syntax and
> > what has changed in the past months (using the Oct 07 overview pdf as a
> > reference), so the above may not be strictly correct, but you should get
> > the intent :)
> >
> > -Yuh-Ruey Chen
> >
> >
> > On Sun, Aug 10, 2008 at 5:52 PM, Ingvar von Schoultz
> > <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>> wrote:
> >
> > YR Chen wrote:
> >
> > There's no separate "namespace" for enumerable properties.
> >
> >
> > This is about something else, something that's come up several
> > times in the discussion archives. See for example this post:
> > https://mail.mozilla.org/pipermail/es4-discuss/2007-March/000578.html
> >
> >
> > Also, let's not add syntax for things that can easily be done
> > with functions.
> >
> >
> > Several syntaxes have been discussed. It seems to me that this
> > syntax would solve several problems that were discussed, and is
> > simple in implementation, very flexible and nicely readable.
> >
> > Whether people still feel a need for a syntax, I don't know.
> >
> > Ingvar
> >
> >
> >
> > YR Chen wrote:
> >
> > There's no separate "namespace" for enumerable properties. They
> > are properties with a hidden enumerable flag set. With that
> > said, in ES4, only non-fixed properties in the public namespace
> > will be enumerable by default. That means that properties
> > defined in classes will not be enumerable unless prefixed with
> > |prototype|, and only "custom" properties defined in the public
> > namespace (which is the default namespace) are enumerable. So if
> > you don't want a property to be enumerable, just define it in
> > another namespace and also open that namespace (via |use
> > namespace|). Or you can toggle the enumerable flag off via some
> > new method whose name escapes me.
> >
> > Also, let's not add syntax for things that can easily be done
> > with functions. You can create your own iterator functions and
> > use them, e.g.:
> >
> > // assuming pythonic generators are in ES4 (there's an
> > equivalent, albeit uglier, non-generator way)
> > myDictClass.prototype.own = function() {
> > for (var x in this.iterator::get()) {
> > if (this.hasOwnProperty(x))
> > yield x;
> > }
> > }
> >
> > for (var x in myDict.own()) ...
> >
> > -Yuh-Ruey Chen
> >
> > On Fri, Aug 8, 2008 at 1:07 PM, Ingvar von Schoultz
> > <[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>
> > <mailto:[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>>> wrote:
> >
> > I think this would be useful:
> >
> > Get an enumerable property:
> >
> > var x = myDict [*enumerable] .someName;
> >
> > var x = myDict [*enumerable] [someVariable];
> >
> > Call the non-enumerable .toString():
> >
> > var x = myDict [*!enumerable] .toString();
> >
> > Distinguish between owned and inherited properties:
> >
> > var x = myDict [*own] .someName;
> >
> > var x = myDict [*!own] .toString();
> >
> > Loop through a subset:
> >
> > for (var x in myDict [*own]) {...}
> >
> > The syntax is meant to suggest that we pick a subset, such as
> > all the enumerable properties, and then pick a property from
> > this subset.
> >
> > Here's an alternate syntax, more logical but less readable
> > in my opinion:
> >
> > var x = myDict .:enumerable .someName;
> >
> > var x = myDict .!enumerable .toString();
> >
> > --
> > Ingvar von Schoultz
> >
> > _______________________________________________
> > Es4-discuss mailing list
> > [EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>
> > <mailto:[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]>>
> >
> > https://mail.mozilla.org/listinfo/es4-discuss
> >
> >
> >
> >
> > --
> > Ingvar von Schoultz
> >
> > ------- (My unusual use of capitals in code comes from my opinion that
> > reserved and predefined words should all start with lowercase, and
> > user-defined should all start with uppercase, because this will easily
> > and elegantly prevent a host of name-collision problems when things
> > like programming languages are upgraded with new labels.)
>
>
_______________________________________________
Es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss