The title is incorrect; you need "!" and the only reason why I clicked on the article was that doing it without "!" would be a BIG deal. The title of the original article is "A Javascript journey with only six characters" and the topic has been posted/reposted and explained more times than I can count on HN
This is an extreme demonstration of the validity of a delightfully snarky blog post by Robert Harper on how dynamic typing is actually static typing using a unitype:
A string is a Boolean is a number is a function, and braindead conversions can happen without anyone noticing. How does one keep their sanity using a language like that?
Keep it straight in your head, and use strict comparison.
Hey, at least when JS implicitly converts your types, it actually does type conversion, rather than merely casting them, so you often get what you want (looking at you, C).
As for C, I have to contradict you. Implicit (numeric) type conversions do actual conversions (like char to int, or int to double; even pathological cases like pointer to what-counts-as-Boolean-in-C). The casts you are talking about must be explicit, and thereby are squarely the programmer's responsibility.
Of course, a language that forces all conversions to be explicit is preferable.
Yes, but the char still has to be extended to int. Or the int truncated to char. Except on systems where they happen to be the same size.
EDIT: Supplement:
The notion of “type” in C is best translated as “memory layout plan”. Languages of the ML family (including Haskell), e.g., have a notion of “type” closer to mathematical concepts.
What the OP takes to the extreme is a property of weak typing, not dynamic typing.
These properties are separate issues. A language is either statically typed or dynamically typed, and it is also either strongly typed or weakly typed.
In a statically typed language, types are attached to variables. In a dynamically typed language, types are attached to values. Do note that many languages don't fit 100% into either category. (Note that the blog post you linked to calls types attached to values classes, but that distinction often isn't made so clearly.)
A weakly typed language performs implicit type conversions as it deems necessary, while a strongly typed language does no implicit type conversions. Most languages don't fit 100% into either category. Usually languages that are considered to be strongly typed still allow you to add integers to floating point numbers, for example.
It is possible for a dynamically typed language to be so strongly typed that it won't do any implicit type conversion, ever. Such a language would not allow you to, say, add an integer and a floating point number without explicitly converting one to the other.
It is also possible for a statically typed language to be so weakly typed that it implicitly converts types everywhere. Such a language might do the exact same things the OP uses, like converting a function to a string of its source code when adding it to a string.
Ah, this was extremely well explained, thank you; I've encountered the strong / static (and weak / dynamic) dichotomy before but I didn't grok the difference until now.
> In a statically typed language, types are attached to variables.
More precisely, expressions may be typed. Of course, free variables are one particular of expression.
> In a dynamically typed language, types are attached to values.
More precisely, tags are attached to objects. An object is a “physical” entity that exists in space (computer memory) and time (from its construction to its destruction or garbage collection). A value is an abstract and atemporal entity that only exists in the language's semantics.
> Such a language would not allow you to, say, add an integer and a floating point number without explicitly converting one to the other.
But it does allow you to add integers and floating points! The result just happens to be an exception, which is a very well defined operation in the semantics of most high-level languages.
In a dynamic language, you have to wait until runtime to decide whether an operation is valid or not. Only then can you check an object's tag to see if it proclaims the right type. If it doesn't, non-local exit (of which the exception is the most popular form), is still the best you can do. So, cum grano salis, throwing an exception is a dynamic language's way of disallowing invalid operations.
Any memory-safe language? Say, Python. `[] / []` is a perfectly valid operation: its result is a raised exception misleadingly called `TypeError`. OTOH, in most typed languages, this is a genuinely invalid operation, and it can't happen at all.
I'm a fan of Javascript. It has proper lambdas, true lexical scope, will soon have TCO, and is a really flexable language.
But it's not without its warts, and this is one of the worst. Although it's sometimes fun to mess with, nonetheless.
To see this taken to one of its logical extremes, check out If Hemmingway Wrote Javascript's entry for Douglas Adams:
// Here I am, brain the size of a planet, and they ask me to write JavaScript...
function kevinTheNumberMentioner(_){
l=[]
/* mostly harmless --> */ with(l) {
// sorry about all this, my babel fish has a headache today...
for (ll=!+[]+!![];ll<_+(+!![]);ll++) {
lll=+!![];
while(ll%++lll);
// I've got this terrible pain in all the semicolons down my right hand side
(ll==lll)&&push(ll);
}
forEach(alert);
}
// you're really not going to like this...
return [!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]];
}
Lexical scope with async closures makes it very easy to write async code for example events in a gui or handling multiple clients in a server. Its a big deal.
I knew about these languages but I've never understood how they were made. This is a fun, fantastic article! These articles make me excited about technology. Even bad ones.
It's hardly the new McCarthyism when there's no government force that leads the charge against private citizens, driving them to be unable to find any work in their field in the US.
The public deciding that it doesn't want to support someone is an entirely different phenomenon. The public can still be wrong, of course, but there's no need to conflate the two situations.
They're both the phenomenon of policing thought and coercing others to publicly profess, or at least acquiesce to, only blessed opinions. It hardly matters, to this point, whether the behavior is centralized or emergent.
Brendan has his own startup in SV and appears in JS community podcasts, conferences, and meetups. The community is always talking to him on Twitter in a positive way. He may have had to leave Mozilla, but he's anything but ostracized.
It's too bad that people are willing to use their money and influence to negatively affect specific groups of people. Both Eich and Luckey made personal choices that negatively affected users of their products. As a response, these users, and people who support them, have decided to reject them.
This feels like basically the reverse of the ad hominem, where if you agree with the things someone is saying in a particular context, you also have to praise them as a person. And it's a fallacy for the same reason the ad hominem is a fallacy. I can respect Brendan Eich's technical views without having to respect his political / social ones, and I can believe that he's amazingly qualified to be CTO of Mozilla, a technical role, and yet amazingly unsuited to be CEO, a political/social role. And this isn't just me - none of the controversy started until he moved from CTO to CEO.
If we can't do that, then we ostracize people who aren't a cookie-cutter $political_view.
oh man totally. neither brendan eich nor palmer luckey have gotten any work ever since they were blackballed by silicon valley.
oh wait. they weren't was blackballed. and one has his own startup, the other is basically set for life.
oh wait. has either one of them appeared in from the a senate committee to defend themselves for false accusations of subverting the u.s. gov, or committing treason? without any evidence?
This doesn't make me want to use JS. The power of JS is in two things, it's in every major browser and it doesn't completely suck. JS syntax kind of sucks. The power in JS is that it's dynamic and lets you send functions around, but defining functions is much uglier than defining a lambda in Ruby:
-> {anything goes here}
or
->(a,b,c) {anything goes here}
The problem with Ruby is that you then have to .() the lambda vs. (), so that is more verbose than just calling the function.
If browsers were to embrace a language that was more Ruby-like and less clunky than JS, I'm sure I'd use it more.
That's succinct, but less clear than the Ruby version, imo, as you don't have any scope indicators required for the function body.
JS:
let f = (a,b,c) => a * b ^ c;
f(2,3,4);
vs. Ruby:
f = ->(a,b,c) { a * b ^ c }
f.(2,3,4)
Ruby's shorter and clearer. But, when you use the Ruby lambda more than once in the code, you lose the brevity advantage, because of the "extra" dot. But, in Ruby I use methods more than lambdas, which would be:
I would say the different is negligible here and claiming one is more clear than the other is purely preferential. Coming from a JS background the JS is more clear but not substantially enough for me to claim it is outright more clear a language syntax. Someone coming from a ruby background may argue the other direction.
Some languages are quite different but you are splitting hairs here and trying to be conclusive about it.
Good catch. It seems that the "Object" string doesn't provide any crucial characters for further steps; in this case the literal curly brackets aren't needed.
Does anyone know a good sandboxing technology to execute user written javascript in a safe way? (like, on other user machines or on the server)? I have some ideas like "learn programming" that would benefit from this immensely.
Note that caja doesn't protect against local denial-of-service attacks: user-written javascript executed with it could allocate tons of memory or run forever (`while(true){}`). This may or may not be a problem depending on your use-case. (If you're using caja for code written by mostly-trusted 3rd parties, or for one user's code only on their own machine, then it's not much of an issue. If you're serving code written by one user to another, then it could be a problem.)
thanks, I didn't actually know about that. it looks like a perfect (and simple) solution for running on nodejs. wish there was something like that for browsers too!
Note that the vm module doesn't protect against local denial-of-service attacks: user-written javascript executed with it could allocate tons of memory or run forever (despite any configured timeouts: https://github.com/nodejs/node/issues/3020).
I've hacked on this interpreter some, it's pretty nice to read! It implements a very limited subset of JavaScript, something like ES3.
I'd be really interested to hear about other similar implementations of JavaScript in JavaScript. I stopped working on https://github.com/thomasballinger/hotswapping-js-interp#js-... partially because copying the state of the interpreter was relatively slow. I'd be interested in implementations that would handle this better by using a more bytecode-like VM or immutable data structures.
If you don't like JavaScript's type coercion rules, fair enough. But if you're criticizing the fact that you can write JavaScript programs with nothing but punctuation characters, remember that no-one ever does so except as a joke, and that you can do ridiculous stuff in most languages. (Try Googling "obfuscated $YOUR_FAVORITE_LANGUAGE".)
reply