Picking property by attribute
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
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: 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
(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
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
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]);
On Aug 18, 2008, at 9:28 AM, Yuh-Ruey Chen wrote:
OK, with the advent of ES-Harmony, I have no clue whether the language will support iterators (and maybe generators)
We talked about these in Oslo. My notes say generators received
favorable comments, with the thought from Mark Miller that the
introductory keyword might better be 'generator' than 'function'.
These were never a bone of contention between factions, AFAIK.
or catch-all methods.
These required the meta namespace in ES4 as proposed.
I know that namespaces are out.
Then you do have a clue about catchalls as proposed :-/.
I think this would be useful:
Get an enumerable property:
Call the non-enumerable .toString():
Distinguish between owned and inherited properties:
Loop through a subset:
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: