On Mar 15, 2009, at 23:30 , Brendan Eich wrote:
But here is the uneval/toSource equivalent, inline, using the same
notation (single quotes around string results, although all results
are string results, in a one-line comment starting //-> after the
repr call):
Thank you. Added it here http://gist.github.com/81118 for easy
comparison (and syntax coloring :P).
Also, removed the single quotes on the Python examples[1] and cleaned
up the Ruby examples[2] to use p(obj) instead of obj.inspect.
Since undefined was added as a global property after ES1, when there
was too much risk of a web page defining a same-named global, it's
read/write and deletable, so uneval(undefined) produces '(void 0)'.
Note also that unlike toString, the function toSource results squish
code onto one line. This can get ugly, but it was considered
convenient for short functions. Perhaps it was a mistake to do this,
though.
Sharp variables handle cycles and join points but they are overkill
for an inspect-like utility, and they require aggressive memoization
to avoid divergence calling non-idempotent getters or otherwise
dealing with object graphs that modify themselves (via
SpiderMonkey's internal metaprogramming hooks) as they are crawled
to find the join points.
Comments welcome.
From an end-user's perspective, the main difference between
SpiderMonkey's uneval and Python's repr or Ruby's Object#inspect [3]
is that the former looks like a meta-programming tool while both
Python's and Ruby's implementation are just debugging helpers.
I would argue that fulfilling both needs with the same API is not a
good thing. For debugging, the most useful representation of an object
is often domain- or even context-specific and that is not necessarily
it's source code.
I have little knowledge of Python's repr implementation but can
explain briefly how ruby's Object#inspect [4] works.
In Ruby, every object (and in Ruby, nil is an object too) has an
inspect method, which is either defined in the object's class or
inherited from Object#inspect. When not overridden Object#inspect
delegates to the object's to_s [5] method.
Object#to_s returns the object‘s class and an encoding of the object's
id and is overridden for most common types (String, Number, Array,
etc.).
Printing the object's debug representation to the program's standard
output is then as simple as calling Kernel#p [6] with the object
passed as it's first argument:
p(123) # or p 123, brackets are optional
> 123
Since inspect is an instance method, it allows classes to define their
own debugging representation. Thus:
class Foo
def inspect
return 'I am an instance of Foo'
end
end
p(Foo.new)
> I am an instance of Foo
Here's a pseudo-implementation in ES 3 (please bear with the obvious
issues such as breaking for...in loops, etc.). Obviously, naming the
EcmaScript counterpart of Ruby's Object#inspect
Object.prototype.inspect wouldn't fit with the rest of the EcmaScript
API, I would suggest something like Object.prototype.toDebugString().
Object.prototype.toDebugString = function() {
return this.toString();
};
function p(obj) {
if (typeof obj === 'undefined') {
return 'undefined';
}
if (obj === null) {
return 'null';
}
return obj.toDebugString();
}
A program could then specify custom debugging representations like so:
function Foo() {}
Foo.prototype.toDebugString = function() {
return 'I am an instance of Foo';
}
p(new Foo());
//-> I am an instance of Foo
Native objects would need to define their own prototype.toDebugString
methods.
We've been using something similar in Prototype for a long time to
great effect (although we do not extend Object.prototype).
In summary:
- uneval and toDebugString serve two different purposes and should be
treated separately, and
- Object.prototype.toDebugString could be roughly mapped to Ruby's
Object#inspect implementation.
This would allow for easy customization of debugging output (which
answers concerns expressed about domain-specificity of serialization)
and avoids complex implementation and specification issues related to
returning an "evaluatable" source representation.
Best,
Tobie
--
[1] Python example: http://gist.github.com/78424
[2] Ruby example: http://gist.github.com/78355
[3] in Ruby, the notation Foo#bar means the instance method 'bar' of
class 'Foo'.
[4] Object#inspect doc: http://www.ruby-doc.org/core/classes/Object.html#M000358
[5] Object#to_s doc: http://www.ruby-doc.org/core/classes/Object.html#M000357
[6] Kernel#p doc: http://www.ruby-doc.org/core/classes/Kernel.html#M006002
_______________________________________________
Es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss