Extremely minor potential nitpick: correct me if I'm wrong, but I think this sentence implies that Javascript is not type-safe, when it is indeed type-safe; it's just dynamically typed, and its type system gives meaning to all expressions (where that meaning is to signal an error in some cases).
"But wait a minute, Assembly is not type safe!" But yes it is, just every type is a binary number. It's not Assembly's fault that you're trying to use binary numbers to print characters to the screen or point to regions of memory and somehow get the two mixed up.
Aggressive type coercion is not type safety. It does not prevent type errors. It just sweeps them under the rug.
5 - 'foo'
That's a type error. It's not a convenient shortcut for `NaN`. var a = 1;
a = "foo";
is not type safe.(I really like Rust's take on this with the semicolons—just leave off the semicolon to return—it makes the semicolon actually useful.)
The reasons I switched away from LLVM are:
- the LLVM API is huge, not very well documented, and changes radically from version to version. - LLVM library consumers are not well supported by the project. Frequently what you get when install it is a set of static libraries, which take forever to link against and lead to 150MB binaries. - LLVM's supported architectures set isn't great yet. C provides a portable, vendor-neutral intermediate language which works everywhere and is easy to read and therefore debug. - targeting C makes library integration trivial (as your output program can use the library's own headers, which means ABI issues become nonexistent).
I did contemplate a partial switch, where my compiler didn't link against LLVM at all but instead just spat out LLVM bitcode assembly --- but emitting C was the same amount of work and so much more flexible. The only downsides is that C can't do tail calls, and getting the debug information to match up is more work, but that's about it.
(For the interested: Cowbel is an experiment at producing a minimal static duck-typed language --- all types are anonymous; you refer to objects only by their interfaces. The compiler than uses type inference to determine the actual concrete type of the object. This allows it to, e.g. use a single machine word to represent a number if you're never going to do dynamic dispatch on it, which means you don't end up with the weird schizophrenia of C++ and Java where some types are scalars and some are objects and they have different semantics.
It's also an attempt at minimalism; I wanted to remove as many features as possible and still end up with a expressive language with Javascript-ish syntax. I'm really proud of the way I managed to unify scope blocks and objects...
It works beautifully, and produces tight, fast code, but the compiler became unmaintainably complex and needs to be rewritten from scratch, which I haven't done yet.)
Can you please tell me which GC is that ?
I don't. Thanks to all those that do though. Interesting thought experiment, even as a spectator.
> setIdThenSave(newid Num, Bool recursively) { ... }
i like the idea of letting a type do double duty as a variable name if it's obvious in context, and being aliased by an explicit name if wanted/needed, but letting the order be irrelevant sounds like unnecessary flexibility to me - it makes writing no easier, and reading harder.
Of course, I do see where the complaints come from, and a part of me fears the day that someone releases a wake linter which requires aliases to follow the type. If that were to happen I think I'd nix the idea in favor of unity in the community.
that(expected Bool, expected Int)Equals(actual Bool, actual Int)
to match on two values, for instance. on the other hand, constraining the adjective to come before the noun is an english-based convention, so you're probably right about seeing which way the community leans before doing anything.
But what I really like is the presentation: I like how all features are summarized, pointing out what is novel, and then everything is just discussed using examples and comparisons to other languages. This is something I'll have to try when I finally get my own language off the ground :).
I wonder if the author is interested in engaging with researchy PL designers. E.g. the testability orientation of the language would make for a good Onward paper, or maybe a Future of Programming workshop presentation.
I haven't written a technical paper before, but tried to make one on the testability here: https://docs.google.com/document/d/1hT761Cl2-r7cSJV4zR69PGAD...
Other discussion here: https://news.ycombinator.com/item?id=9040029
Yeah, I had posted that to Reddit, where it didn't do too well, but someone posted it here where (for some reason!) it did much better.
Figured in addition to the story of creating Wake, I'd post the home page so people could look into it more!
I've typically found PL related articles do much better on Hacker News than Reddit, I think perhaps because of differing (but overlapping) target audiences. Always found it interesting what articles work here but not on Reddit (the converse isn't as interesting...)
function RecordValidator(sessionHolder) {
function validateRecords(records) {
return records.every(validate);
}
function validateRecord(record) {
if (record.lastRevision !== undefined
&& record.lastRevision.user !== undefined) {
return record.lastRevision.user.getAccounts().every(function(account) {
return sessionHolder.hasAccount(account);
});
}
return record.revisions.map(usesLimits);
}
function usesLimits(revision) {
return sessionHolder.hasUser(revision.user);
}
return {
validateRecords: validateRecords,
validateRecord: validateRecord,
usesLimits: usesLimits,
};
}
The language looks like it has much to like. return Record[].any({
r -> return !validate(r);
});
shouldn't this be return Record[].all({
r -> return validate(r);
});
?And the inequality seems to be strict in Wake's case but weak in Java's. Finally, Java won't always return from `validate`.
The Java would really benefit from the newest version. I'm no Java expert, but I think it would look a bit like:
public class RecordValidator {
public RecordValidator(SessionHolder mySessionHolder) {
sessionHolder = mySessionHolder;
}
protected SessionHolder sessionHolder;
public boolean validate(List<Record> records) {
return records.stream().allMatch(this::validate);
}
public boolean validate(Record record) {
if(record.lastRevision != null && record.lastRevision.user != null) {
List<Account> accounts = record.lastRevision.user.getAccounts();
return accounts.stream().allMatch(sessionHolder::hasAccount);
}
record.revisions.stream().filter(this::usesLimits).count() < 3;
}
public boolean usesLimits(Revision revision) {
return sessionHolder.hasUser(revision.user);
}
}What ideas are new? I'm not sure about provisions because the examples aren't really clear, but all the other features I've seen in other languages before.
> 3. Shadowing (concise, safe)
It doesn't seem like shadowing is the feature here, rather the use of '$' to prevent shadowing.
> Lists (called Arrays in many other languages)
There's a very good reason for this. Lists and arrays are very different data structures. Why create confusion by calling them lists?
> Since Wake blurs the line between variables and types, we can boast the smallest foreach loop of any language.
Really, the smallest foreach loop of any language? Come on.
> Self Executing
Why is this called 'self executing'? Also, I'd expect any language with lambdas to support calling a lambda right after it's created.
Same in the "What Wake did without" section. Yes, you do not have those features, or bugs, but have you really "FIXED" a bug? There is no bugs you have fixed, just different design decisions.
edit: The language may or may not be actually worth something, but those things make it look like they try to hard to me.