On Fri 26 Jul 2013 12:29:10 PM PDT, Brendan Eich wrote:
> Steve Fink wrote:
>> (2) writing JS still feels clunky in comparison to writing
>> Python,
>
> What's missing in your experience?

That question deserves a proper response, but it's tough remembering 
the issues when I'm not actively hacking out code. I've attempted to 
make lists of stuff at various times that I can dig up, but for now 
I'll just list out some that I've noticed recently. These are things 
that are possible but seem a little indirect or unnatural:

* copying an array with copy = orig.slice(0). Compare with Python's 
copy=list(orig) or copy=dict(orig), or Perl's @copy = @orig or %copy = 
%orig.

* using an array for a tuple feels heavyweight. |return [a,b]|. Compare 
with Python's tuples or Perl's multiple return values.

* |if (!(item in collection))|. I miss Python's |if (item not in 
collection)|

* Related to the above, the whole sequence

  if (!(key in collection))
      collection[key] = []; // or {}
  collection[key].push(value);

Compare with Python's somewhat clunky collection.setdefault(key, 
[]).append(value) or Perl's autovivification push @{ $collection[$key] 
}, $value

* |a + " " + b + ";" + c|. I think interpolation is coming with some 
future ES version (whatever quasiliterals are called now?), but compare 
with Python's rich string formatting or Perl's "$a $b;$c" string 
interpolation.

* Extending an array via |combined = orig.concat(newstuff)| creates 
garbage, can't be used when updating the original is what you want, and 
concat behaves differently for arrays vs everything else. (I don't know 
the spec well enough to understand what "array" means in this case.) 
Compare with Python's orig.extend(newstuff) and Perl's push @orig, 
@newstuff.

* Not a language issue, but I really like the cleaner control flow and 
intermediate memory usage of generators. But I am avoiding them in hot 
code because neither ionmonkey nor baseline currently gets along with 
them. (As in, they don't compile them, so I've been advised to avoid 
them when I don't want a performance cliff.)

* |in| vs |of|. Beyond the usual, the most recent way this bugged me 
was when I found that |for (x in generator())| and |for (x of 
generator())| seem to do the same thing. Given that I mostly consider 
|in| to iterate over keys and |of| over values, having them do the same 
thing seems odd. I'm not sure how I'd *want* them to behave, but it 
would somehow feel cleaner to have one of them be an error or making 
|in| return numbers counting up from zero or something. Then again, 
|of| doesn't give me values, only elements, which suggests that I just 
have the wrong mental model. It seems like |in| wants me to think of 
Arrays as objects that happen to have numeric keys, and |of| and 
|concat| don't.

* undefined testing. It bothers me that |undefined| can be defined, so 
|x === undefined| isn't 100% guaranteed to mean what I want (and yet 
redefining undefined doesn't do anything useful.) And actually, I don't 
really like |x === undefined| in the first place, since I'm uneasy with 
treating undefined as a valid value. I prefer Python's |x is None| and 
Perl's |defined(x)|.

* |if (item in collection)| is fine for non-Arrays, but |if 
(collection.indexOf(item) != -1)| feels clunky.

I'm probably just wrong about some of these. I reserve the right to 
turn around and argue that it should have been more obvious to me that 
I was wrong. :-)

On a separate note, please don't think that I am arguing against 
dogfooding in general. I'm just not so sure I want it in the build 
system. I think the rooting analysis has shown the power of dogfooding. 
bhackett needed to spawn external commands, so he added system() to the 
shell. I really wanted to load scripts relative to other scripts so I 
could split them into multiple files, so I added loadRelativeToScript. 
When developing in JS "for real", I wanted a debugger, so I tweaked 
js/examples/jorendb.js to allow easy debugging of standalone scripts. 
(My latest work on the analysis led me to discover that it had 
bitrotted, and that I needed to add some more functionality.) Due to 
some changes I needed to make in the data flow for the analysis, I 
found I needed to write out multiple files from one script, so just 
print() and shell redirection was no longer enough. I first fixed up 
mfeeley's implementation for writing a string to a file, then 
immediately discovered that it was useless for me because I didn't want 
to materialize the whole string before writing anything. So I added the 
ability to redirect stdout and/or stderr to a named file. (It would be 
better to be able to specify a file object for each print, but I have 
no interest in reintroducing a whole File object to the shell.)

These are all cases where the dogfooding led to improving the shell, 
not improving JS itself, but I'd like to think of these sorts of things 
as necessary prerequisites to "true" dogfooding, that which would lead 
to improvements in the shipped JS engine. You need a decent development 
environment before you can get people to do proper dogfooding.

_______________________________________________
dev-tech-js-engine-internals mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals

Reply via email to