Yep! That was my inspiration. I'd love to be able to do this in Rust. Soon, hopefully!
HN user
jarrettc
Will the Rust compiler ever understand numbers in types? I.e. will the numbers ever be more than just part of the string that is the type name? If not, then I don't know how possible powers will be. Maybe the solution would be to define some types for commonly-used powers, e.g. PowN4, PowN3, PowN2, PowN1, Pow2, Pow3, Pow4. Users who needed higher powers could define those types themselves, I guess.
Great question. I believe each unit struct would need to implement PartialEq or something similar. That would define the canonical nesting order. Alphabetical would make sense.
We would to resolve the nesting during multiplication and division. For example:
let a: Scalar<Times<A, B>> = Scalar::new(10.0);
let b: Scalar<Times<A, Times<B, C>>> = Scalar::new(5.0);
let c: Scalar<Times<A, Times<A, Times<B, Times<C>>>> = a * b;
Another challenge is that the type of c is ugly. But this could be mitigated by generous use of type synonyms.Lately I've been playing around with static dimensional analysis in Rust. The overall idea is similar: Use PhantomData to add a type parameter and define an empty struct for each unit. So you might end up with, say, Scalar<Newtons> or Vec3<Meters>.
Dividing and multiplying units statically is where I've had trouble so far. I think I've found a way, but it would depend on negative trait bounds, as discussed here:
https://github.com/rust-lang/rfcs/issues/1053
Ideally, I'd like to be able to do something like this:
let a: Scalar<Joules> = Scalar::new(2.0);
let b: Scalar<Seconds> = Scalar::new(3.0);
let c: Scalar<Watts> = a / b;
// Watts is a type synonym for Over<Joules, Seconds>.
// Other derived units would use Times<U, V>. E.g.:
type Pascals = Times<Newton, Times<Meter, Meter>>.Hasn't every template language in the world has come to a similar conclusion?
No, not even every mainstream template language. For example, I still use ERB and EJS extensively, and so do many other engineers. ERB and EJS use the control flow constructs of the underlying languages (Ruby and JS, respectively).
There is of course debate about whether templates should expose the full power of a programming language. I have tried templating languages that do and ones that don't. For now, I'm sticking with templates that let me mix in arbitrary code as I see fit. Could I abuse that power and make a mess? Absolutely. But I try not to, and my code stays pretty maintainable.
I'm skeptical that 3d printed objects could replace very much of what we now obtain from factories. In industrial design, the materials and fabrication process are (supposed to be) selected very carefully with an eye towards cost, physical properties, chemical properties, etc. Even my phone case, which might be the simplest product I own, was made not just from any old plastic, but from a very particular plastic that's optimized for phone cases.
Whereas with 3d printing, we're currently stuck with a kind of plastic that's optimized for compatibility with a 3d printer. It's unclear whether we'll ever be able to print from other, better plastics. And that's saying nothing of other materials like steel, glass, and ceramic, which are often necessary in useful consumer products.
This isn't security through obscurity
I don't necessarily disagree. But how, other than through obscurity, does HTML5 DRM inhibit copying, given that the client possesses the decryption key? (Let's assume the would-be attackers aren't dissuaded by any laws that might apply.)
Or does it truly rely on blackbox obfuscation?
The client ultimately has to decrypt the data somehow. So the key is there on the client. I take it obfuscation is the only thing standing between the user and that key. Am I correct about that?
Which makes me wonder: How much security does HTML5 DRM really provide? Security through obscurity is a very weak defense, and one that is almost invariable defeated sooner or later. Will this really prove a hindrance to piracy in the long run?
Thanks so much for working on the grammar docs! This is much needed and very helpful, considering how quickly Rust's grammar has been evolving.
Ah, my mistake. So would I be correct in saying that a trait is a type, but it does not necessarily implement the Sized trait, and if it does not, then it cannot be allocated directly on the stack?
Also, I've been wondering something about dereferencing a Box where the inner type is just a trait. If I dereference a Box<CanineTrait> and call "bark," how is the correct implementation found at runtime? Is there a vtable or something analogous?
Rust has algebraic data types. They're one of Rust's most important features.
But algebraic data types do not in themselves provide a way to express the notion of a type with variants or sub-types.
I'm hoping the next post will talk about this use case: Suppose I have an enum called "Canine" and I want each of its variants to implement a different "bark" method. Currently, as far as I know, I have to write a match statement dispatching "bark" to each "Canine" variant. If I have "bark" and "growl," I have to write two match statements, and so on for each method that needs to be dispatched to different variants.
So it's a lot of boilerplate. I think it can be slimmed down with a macro, but still.
You might think traits rather than enums are the way to go here. Sometimes that may be true. But often, an enum is far preferable because in Rust, a trait is not a type, but an enum is. That means you cannot, for example, have a "Vec<CanineTrait>," but you can have a "Vec<CanineEnum>."
I guess it just seems overly ambitious to me.. finding the right abstraction for the server is difficult enough without polluting it with the front-end.
Certainly. That's why I'm skeptical that this will ever happen.
why spend time solving problems are are more incidental than essential?
I wouldn't characterize these kinds of errors as incidental, inasmuch as they account for a very high percentage of the web app bugs I've encountered.
Designers of languages like Rust and Haskell noted that null pointer dereferences were the single largest class of errors in other languages. Thus, the designers chose to make null pointer dereferences impossible at the language level. With that choice, they turned a huge number of run-time errors, which developers often miss, into compile-time errors, which developers cannot ignore. This has proven itself beneficial to productivity and software quality.
So too here: If I'm correct that client-side type and name errors constitute a large fraction of all web app errors, then catching them at compile time will be a big win.
But again, I don't know how feasible this is. Nor do I know whether it would involve compiling from a type-safe language to HTML/CSS/JS or just static analysis of raw HTML/CSS/JS.
The examples you give don't seem to be typing problems, they seem to be wrong-value problems.
They're like type or name errors because the "apple" and "orange" here are like identifiers, not data. Sure, to the browser, they're data. But in terms of the structure of the web application, they're identifiers like variables, function names, or types.
For example, the HTTP endpoint "/apples?count=5" is like a function "apples(int count)."
Actually building such a beast would seem to be a non-trivial engineering challenge.
It certainly would. That's why I'm wondering if you consider it possible.
Strong typing on the web has been an intractable problem for me so far. Sure, I can have strong typing in my server-side code. But so many errors result from the interaction between the server, CSS, HTML, and JS. For example, you define a route at the path `/apples` but send an AJAX request to `/oranges` instead. Or you write `<div class="apples">` but query it with `div.oranges` instead. These are very much like type errors or name errors, except they occur at the boundaries of languages and processes.
Have you worked out a way to catch these sorts of things at compile time? If not, do you think it's possible in the framework of the future?
True, but the parent commenter is getting at something important. The article suggests that researchers have found a new, much more concise way to express the solutions to difficult problems. That's different from a library, which merely packages pre-built solutions to a finite set of problems.
It's like the difference between a complete kitchen that fits in your pocket and an iPhone app that lets you order a burrito. The article suggests something like the former. A library which encapsulates 1000 lines of code into a single function call is like the latter.
Good to know. Thanks! So I guess the moral is, if you have a big, expensive struct, make sure the expensive part is in a sub-structure you know is heap allocated, such as a Vec. E.g.:
struct Expensive {
cheap_value: u32,
expensive_value: Vec<u32>
}
Does that seem like a good maxim?Oh, agreed. But how about this:
let x = BigExpensiveStruct::new();
some_function(x);
That won't trigger a big, expensive memcpy of the BigExpensiveStruct, will it? I'd thought that its memory was on the heap.Yes, I had understood the struct's memory to be on the heap. My thinking was, keeping the memory on the heap allows for inexpensive moves. Whereas, the pointer to the heap space may indeed be on the stack, as far as I know.
But I could be mistaken. This is all based on hearsay--just stuff I've read about the Rust compiler. I don't actually work on the compiler myself.
Semantically speaking, the only difference between a move and a copy is that you're allowed to use a copy type afterwards
Are you speaking about Rust specifically, or move in general? I had always understood that move was no more expensive than passing by reference. That is, I had thought the memory was on the heap and didn't need to be copied each time someone new took ownership of that heap space.
It seems to me like the value would be memcpyed, when you pass by value.
As far as I know, the compiler should not copy in that instance. Rather, it should move.
There is not one unit of memory that is "taken over," or if there was, then Rust would have a serious problem.
Could you elaborate on that? Rust does have an ownership model, and ownership can be transferred as in the example. What sort of problems would you expect that to cause? If you're worried that it will invalidate existing pointers, the compiler checks that for you. Unless you deliberately circumvent the check, the compiler guarantees that your pointers are valid.
The author mentions that Rust's "Box type is an owning type" and compares Box to C++'s std::unique_ptr. Worth noting: Rust's most basic variable syntax provides unique_ptr-like behavior, so you usually don't need the Box type for this behavior. For example:
The relative impact of your money vs your time depends in part on your income, you skill-set, and the causes you would choose.
A person with a high income but few relevant skills would probably have the greatest impact by donating money. For example, a trader interested in preventing disease might not have any skills in developing or delivering vaccines. But that trader might have a substantial amount of money to donate to organizations that do have those skills.
On the other hand, a software engineer with a modest income might find a very effective nonprofit that could do much more if only it had access to software development talent. For that engineer, donating time might achieve much more than donating money.
I've always been uneasy about the fact that Stack Overflow users can edit each other's posts more or less arbitrarily. User A can edit user B's post to say something embarrassing, and most readers will attribute it to User B.
I've had this happen with my posts. It's never been egregious, like a user inserting something inflammatory into my otherwise mundane programming question. Most often, the offending edits give the appearance that the original poster doesn't know how to write or doesn't know basic programming concepts. It's not unheard-of for potential employers to look at a programmer's accounts on Stack Overflow, Github, etc., so an unflattering edit could be problematic.
Granted, one can use a pseudonymous account. But it would be better not to have to.
Even though 1.0 isn't out yet, today you can use Rust for many real projects. I'm unsure whether I'd bet my business on it yet, but I'd be open to the idea. And I'm usually a very late adopter.
I've been building a 3d game with Rust and OpenGL, ported from a C++ codebase. So far, my experience has been very positive. Despite Rust's supposed immaturity, it feels more polished than C++ in many ways. Forward progress has been much faster than it was with C++.
Does anyone else have a story (positive or negative) about using Rust in real projects?
The article suggests that solar panels could be an "existential threat" to power companies. For those of you who are familiar with the math of solar panels, how realistic is that prediction? How much of a normal home's energy needs could be supplied by solar panels, assuming the panels covered the entire surface area of the roof? How much is the ROI on solar panels likely to improve in the foreseeable future? (I've heard estimates of 5-8% annual return for 2014.)
I agree that HTML needn't be strictly semantic in the way that the OP suggests. But for the foreseeable future, it does need to encode basic structural data for CSS-less presentation. That includes links, headings, inter-page and intra-page navigation, and the like. Who needs that data? Screen readers, text-only browsers, and scrapers, to name a few.
Someday, it may be possible to do away with the concept of a web "page" or "document." Desktop and mobile apps aren't (generally) built in that paradigm. But if we move away from the document concept, we'll have a new set of problems. How do we represent things like blog posts, which really are more like documents than applications? How do we enable a variety of clients with varying capabilities to consume textual content? How do we maintain the useful concept of a URI, if at all? These may not be unsolvable problems, but they are challenging for sure.