Speaking of Lisp...

# P T Withington (19 years ago)

One of our developers wondered why no scripting language has adopted
symbols. I replied:

Objects have most of the features of symbols: they are unique, you
can compare them for identity, you can store properties on them.
An object by itself is like an uninterned symbol -- you have to
keep a handle on it. If you want to intern an object, you can just
assign it to a global variable. So, I think what you are mostly
missing is the shorthand where in lisp you can write  'foo

and if the symbol already exists, you get the symbol, and if it
doesn't it will be created for you.

It wouldn't take much to mimic that in Javascript. Something like:

class Symbol { static var allSymbols = {};

function Symbol(name) { if (name in Symbol.allSymbols) return Symbol.allSymbols[name]; this._name = name; return Symbol.allSymbols[name] = this; }

function toString() { return this._name; } }

var _ = Symbol;

Then you can write a symbol as:

_('mySymbol')

Clearly, IWBNI there were a shorter hand for writing symbol
literals, 1 character rather than 5, but this isn't too bad is it?

Were symbols ever discussed as a possible addition? Is there a handy
non-symbol punctuation mark that could be co-opted?

@mySymbol

Dylan uses:

#"mySymbol"

(3 characters rather than 5). Yet another use for #.

# Bob Ippolito (19 years ago)

On 1/5/07, P T Withington <ptw at pobox.com> wrote:

One of our developers wondered why no scripting language has adopted symbols. I replied:

Objects have most of the features of symbols: they are unique, you can compare them for identity, you can store properties on them. An object by itself is like an uninterned symbol -- you have to keep a handle on it. If you want to intern an object, you can just assign it to a global variable. So, I think what you are mostly missing is the shorthand where in lisp you can write  'foo

and if the symbol already exists, you get the symbol, and if it doesn't it will be created for you.

It wouldn't take much to mimic that in Javascript. Something like:

class Symbol { static var allSymbols = {};

function Symbol(name) { if (name in Symbol.allSymbols) return Symbol.allSymbols[name]; this._name = name; return Symbol.allSymbols[name] = this; }

function toString() { return this._name; } }

var _ = Symbol;

Then you can write a symbol as:

_('mySymbol')

Clearly, IWBNI there were a shorter hand for writing symbol literals, 1 character rather than 5, but this isn't too bad is it?

Were symbols ever discussed as a possible addition? Is there a handy non-symbol punctuation mark that could be co-opted?

@mySymbol

Dylan uses:

#"mySymbol"

(3 characters rather than 5). Yet another use for #.

Do you think that encouraging global variables would be a good thing? I thought ES4 was trying to make them less popular.

# John Cowan (19 years ago)

P T Withington scripsit:

One of our developers wondered why no scripting language has adopted
symbols. I replied:

In Java, symbols are there under the covers, in the form of interned strings. The trouble is that there is no way to examine a string to see if it is interned, so people engage in a lot of String.equals where == would suffice.

# Jeff Thompson (19 years ago)

P T Withington wrote:

If you want to intern an object, you can just assign it

to a global variable. So, I think what you are mostly missing is the shorthand where in lisp you can write  'foo

and if the symbol already exists, you get the symbol, and if it doesn't it will be created for you.

For Yield Prolog, I wrote my own internalize function. (In Prolog, they call it an "atom".):

var _internalizedStrings = new Object(); // Return the unique string object that equals name. If you always internalize the strings you use, // then when you compare two strings, they will be the same string object and compare instantly. function internalize(name) { var atomName = _internalizedStrings[name]; if (atomName == undefined) { _internalizedStrings[name] = name; return name; } else return atomName; }

This way, a string object itself is like a Lisp symbol, if you call internalize on it first. Since Firefox 2.0, they fixed the following bug, so that == on two strings instantly checks for two identical string objects. bugzilla.mozilla.org/show_bug.cgi?id=314890

# Brendan Eich (19 years ago)

On Jan 5, 2007, at 5:01 PM, Jeff Thompson wrote:

Since Firefox 2.0, they fixed the following bug, so that == on two
strings instantly checks for two identical string objects. bugzilla.mozilla.org/show_bug.cgi?id=314890

That's just an optimization, since == is defined to compute true for
any two strings with the same ordered list of characters.

ECMA TG1 has not considered symbols. Macros and property quotation
facilities have been mentioned for post-ES4 work, so who knows?

Another item falling out of the ES4 spec: hashes mapping string to
value where the mapping is not polluted by Object.prototype. A late
"save" may be possible, if anyone can suggest syntax. E.g., var hash
= #{'foo':1, 'bar':2, 'baz':3}; alert('toString' in hash) => false.

Eek, yet another attempt to use #.

(Should these map value to value, rather than string to value? E4X
(ECMA 357) already introduced QName objects as identifiers, so one
can't pretend all properties are named by strings, if one believes in
E4X.)

# Peter Hall (19 years ago)

While identifiers can be QNames, does that automatically mean that it's useful to use QNames for hash keys? Probably not.

But, even so, I don't see a big barrier if qualified keys were required. For QNames with non-empty namespace URI, there would be no pollution problem and for unqualified keys you could add a prefix to prevent collision with Object.prototype.

Something like AS3's Proxy object would mean you could encanpsulate that implementation quite cleanly too. I'd prefer to see AS3's Proxy and Dictionary classes added to ES4 before more strange syntax - ES4 is already filling up with a lot of new notations and concepts, that would be unfamiliar and difficult to many existing JS/AS developers.

Peter

# Brendan Eich (19 years ago)

On Jan 5, 2007, at 6:33 PM, Peter Hall wrote:

While identifiers can be QNames, does that automatically mean that it's useful to use QNames for hash keys? Probably not.

It's not clear to me whether E4X requires QNames as hash keys. One
way of reading it (when I implemented it) says "yes".

But, even so, I don't see a big barrier if qualified keys were required. For QNames with non-empty namespace URI, there would be no pollution problem and for unqualified keys you could add a prefix to prevent collision with Object.prototype.

One often wants a hash from string to value, no QNames or namespaces
involved.

Something like AS3's Proxy object would mean you could encanpsulate that implementation quite cleanly too. I'd prefer to see AS3's Proxy and Dictionary classes added to ES4 before more strange syntax - ES4 is already filling up with a lot of new notations and concepts, that would be unfamiliar and difficult to many existing JS/AS developers.

Let's not get stuck on syntax -- I made up #{...} because I know of
use-cases for an object initialiser where Object.prototype does not
pollute the hash. Whether you have to use B&D-language class-ical
OOP, or lighter-weight JS object "literal" syntax, we can wave off
(ok, I'm baiting/teasing a little in this sentence ;-).

Sounds like one vote for a Dictionary class. Could you cite some
URLs documenting Proxy and Dictionary from the Flex SDK (I'm assuming
these are not "AS3" but "host" types).

# Peter Hall (19 years ago)

Yes, they are native to the Flash Player, not AS3 in general - though there is of course currently no practical separation...

livedocs.macromedia.com/flex/2/langref/flash/utils/Dictionary.html, livedocs.macromedia.com/flex/2/langref/flash/utils/Proxy.html

But Dictionary does not solve the pollution problem by itself, as it still inherits from Object. You'd need to extend Proxy and specifically handle identifiers that conflicted with members of Object.prototype.

Peter

# Chris Double (19 years ago)

On 1/6/07, Brendan Eich <brendan at mozilla.org> wrote:

Sounds like one vote for a Dictionary class. Could you cite some URLs documenting Proxy and Dictionary from the Flex SDK (I'm assuming these are not "AS3" but "host" types).

A Dictionary class would be useful I think. Looking around the web for 'javascript associative arrays' will show quite a few hits where people have hit the problem of objects in the prototype being picked up without them realising this would happen.

Although 'hasOwnProperty' can be used to avoid this it doesn't work in all cases. For example, in Firefox all objects return true for hasOwnProperty('proto'). So using an object as a Dictionary has to handle issues like this.

Chris.

# Brendan Eich (19 years ago)

On Jan 5, 2007, at 6:59 PM, Chris Double wrote:

Although 'hasOwnProperty' can be used to avoid this it doesn't work in all cases. For example, in Firefox all objects return true for hasOwnProperty('proto').

Indeed, proto appears to be a property of every object in
SpiderMonkey. It's "DontEnum" in ECMA terms, so it does not pollute
for-in loops, but it's still a hazard reduced in risk only by the __
bracketing.

So using an object as a Dictionary has to handle issues like this.

Suppose ES4 adds a Hash or Dict class. Would there be demand for
initialiser syntax, because a common use-case is a constant or pre- filled (whether mutated later or not) mapping?

Any thoughts on value vs. string key? Surveying real pages, even if
skimmed by a search such as 'javascript associative arrays', is a
good idea. More detail?

# P T Withington (19 years ago)

On 2007-01-05, at 20:14 EST, Brendan Eich wrote:

ECMA TG1 has not considered symbols. Macros and property quotation
facilities have been mentioned for post-ES4 work, so who knows?

That would suffice.

Another item falling out of the ES4 spec: hashes mapping string to
value where the mapping is not polluted by Object.prototype. A
late "save" may be possible, if anyone can suggest syntax. E.g.,
var hash = #{'foo':1, 'bar':2, 'baz':3}; alert('toString' in hash)
=> false. Eek, yet another attempt to use #.

Since you can't build a pure hash in Javascript, this would be a
highly desirable addition. Naive use of Object for hash has been
the source of a number of subtle bugs in our code. One might even be
so bold as to make Hash the primitive and Object inherit from it?

We would have many uses for Hash in our code base. I have defined a
dictionary class that I use for some cases, but often have had to
trade correctness for performance.

A literal syntax would not be that important if you could have a
constructor with named arguments. (Because the constructor's
arguments property would be a Hash?) It would also be useful to
have a constructor that constructed a new hash from an existing one.

(Should these map value to value, rather than string to value? E4X
(ECMA 357) already introduced QName objects as identifiers, so one
can't pretend all properties are named by strings, if one believes
in E4X.)

value -> value would be a bonus that I would greatly appreciate, but

then won't you need to define a protocol for extending hash-code
computation and ===?

# John Cowan (19 years ago)

Brendan Eich scripsit:

Suppose ES4 adds a Hash or Dict class. Would there be demand for
initialiser syntax, because a common use-case is a constant or pre- filled (whether mutated later or not) mapping?

That could be avoided by having Dictionaries which wrap Objects (literal or otherwise) and provide get, put, delete methods on the wrappee.

# Jeff Thompson (19 years ago)

Brendan Eich wrote:

Suppose ES4 adds a Hash or Dict class. Would there be demand for initialiser syntax, because a common use-case is a constant or pre-filled (whether mutated later or not) mapping?

Any thoughts on value vs. string key?

I'm not sure if this is what you're asking, but Python, Java, etc. let you override the hash function that is used for hash maps. And this of course lets you create hash keys other than a string. Does/will ES4 let you override the hash function and would that address the problem?

# Chris Hansen (19 years ago)

(thinking out loud)

One way to circumvent the syntax issue could be to allow maps as part of function calls -- like a combination of varargs and keyword arguments:

function foo(x, y, arg_map) { return x + y + arg_map.a + arg_map.b } foo(1, 2, a: 1, b: 2)

The compiler can recognize the map arguments and turn the method call into this at compile time:

foo(1, 2, #{'a': 1, 'b': 2})

Then you could make a Hash or Dict using a built-in method call or a constructor: "new Hash(foo: 1, bar: 2)" or "hash(foo: 1, bar: 2)". It's a bit heavy syntactically but one advantage of this over a dedicated syntax is that people can add their own map types: "new PrefixTree(wip: 1, wap: 2)".

Just a thought.

# Peter Hall (19 years ago)

On 1/6/07, Brendan Eich <brendan at mozilla.org> wrote:

On Jan 5, 2007, at 6:59 PM, Chris Double wrote:

Although 'hasOwnProperty' can be used to avoid this it doesn't work in all cases. For example, in Firefox all objects return true for hasOwnProperty('proto').

Indeed, proto appears to be a property of every object in SpiderMonkey. It's "DontEnum" in ECMA terms, so it does not pollute for-in loops, but it's still a hazard reduced in risk only by the __ bracketing.

It's also "DontDelete". It's not ReadOnly though, but setting it to null probably isn't enough.

Irrelevent, but I think interesting, in ActionScript 1 and 2 there is a bug which means you can create an object without a proto by using o=Object() instead of o=new Object(). But AS1+2 let you toggle the DontDelete flag anyway, with undocumented functions.

Peter

# zwetan (19 years ago)

On 1/6/07, Brendan Eich <brendan at mozilla.org> wrote: ...

Sounds like one vote for a Dictionary class. Could you cite some URLs documenting Proxy and Dictionary from the Flex SDK (I'm assuming these are not "AS3" but "host" types).

and another vote here :)

most wanted AS3 class I would want to see native in ES4 are: flash.utils.ByteArray flash.utils.Dictionary flash.utils.Proxy

and btw Tamarin already have these (in the shell, not the core language)

ByteArray \mozilla\js\tamarin\shell\ByteArray.as \mozilla\js\tamarin\shell\ByteArrayGlue.cpp \mozilla\js\tamarin\shell\ByteArrayGlue.h

and Dictionnary ..\mozilla\js\tamarin\extensions\Dictionary.as ..\mozilla\js\tamarin\extensions\DictionaryGlue.cpp ..\mozilla\js\tamarin\extensions\DictionaryGlue.h

Concerning flash.utils.Proxy its features should be combined imho with the intrinsic namespace developer.mozilla.org/es4/spec/chapter_5_names.html#intrinsic_namespace and the catchalls developer.mozilla.org/es4/proposals/catchalls.html

so concerning the hash and overriding of hash I would like to be able to do something like that in ES4

class Foobar { . . . public function hash():uint { var seed:uint ^= propA.hash(); seed ^= propB.hash(); return intrinsic::hash( seed ); } }

with that logic function intrinsic::hash( seedvalue ):uint, the non-overridable universal hash method call. function hash( seedvalue ):uint, the hash method call

hope that make sens ?

zwetan

# Robert Sayre (19 years ago)

On 1/5/07, Chris Double <chris.double at double.co.nz> wrote:

A Dictionary class would be useful I think. Looking around the web for 'javascript associative arrays' will show quite a few hits where people have hit the problem of objects in the prototype being picked up without them realising this would happen.

I also think a Dictionary or Record type would be useful, and a convenient literal initializer would be nice. Round-tripping creates further problems:

people.mozilla.com/~sayrer/2007/02/02/hasOwnProperty.html

Any application that uses untrusted input is at risk here.

# Yuh-Ruey Chen (19 years ago)

Another item falling out of the ES4 spec: hashes mapping string to
value where the mapping is not polluted by Object.prototype. A late
"save" may be possible, if anyone can suggest syntax. E.g., var hash
= #{'foo':1, 'bar':2, 'baz':3}; alert('toString' in hash) => false.
Eek, yet another attempt to use #.

Would this new hashtable class derive from Object? If not, then in strict mode, would the following work (using #{} as the hashtable syntax)?

var x: Object = #{'foo':1};

# Lars T Hansen (19 years ago)

On Feb 4, 2007, at 3:00 PM, Yuh-Ruey Chen wrote:

Another item falling out of the ES4 spec: hashes mapping string to value where the mapping is not polluted by Object.prototype. A late "save" may be possible, if anyone can suggest syntax. E.g., var hash = #{'foo':1, 'bar':2, 'baz':3}; alert('toString' in hash) => false. Eek, yet another attempt to use #.

Would this new hashtable class derive from Object?

I think it could in principle, though it would violate the Object
protocol the way we currently understand it (no toString / valueOf
properties on the prototype object). So we would have to finesse the
use of those methods in the spec.