I think that that's the point of it being metrically identical.
You can work in Courier Prime any time you want, and then switch to Courier for submitting your screenplay without worrying about it changing the pagination.
So it can help out any time you are working on your screenplay or working on it with anyone you know won't care, both before and after submission.
Because of the uncertainty behind something new, you should have strong evidence that driverless cars are substantially safer than cars with drivers.
Additionally, if driverless cars are being tested on public roads, you need laws and practices that are robust enough to prevent the kind of accident that killed someone. They had only one operator in the car, who was responsible for monitoring the car and logging information about its performance. They had specifically disabled safety systems which would have caused it to brake sooner.
Even if its expected that driverless cars will reduce fatalities due to drunk or distracted driving, you need to have sufficient evidence of the improvement, safety systems in place for test systems, and public discussion of the tradeoffs and what situations driverless cars might perform worse in than human drivers, because lots of people have behavioral expectations based on human drivers; things like making eye contact with a driver before crossing the street.
So yes, it is good to be working on and testing driverless cars, but you need to have a serious sense of humility and safety about it, and not push it, because even if you are incredibly safe you can expect some backlash, but if you miss the mark at all and oversell the safety, you'll get a lot more backlash, with justification, much sooner, which could set the whole program back significantly.
> you should have strong evidence that driverless cars are substantially safer than cars with drivers.
No. Considering the other benefits of self-driving cars, such as increased mobility for the elderly, you can at most require that they are as safe as cars with drivers, not necessarily safer.
If the benefits were great enough (reduced pollution indirectly saving lives? saved life-years due to more efficient traffic?) one could even accept that they could be a little less safe as far as direct fatalities are concerned.
I understand your point but I doubt it would work well in reality when it comes to public opinion/backlash.
Humans are disproportionately swayed by proximate causes, so deaths directly attributed to self driving cars are going to be more heavily weighted in the court of public opinion.
decreased, in fact. A self-driving vehicle can't go anywhere a cab or rideshare can't, while the latters have drivers who can assist loading/unloading elderly and their mobility aids.
Somebody with poor eyesight and slow reaction speed is an unsafe driver but doesn't need any particular help loading/unloading from a car. A driver who can help unload is a fine thing, but having somebody drive just so they can help unload seems like a ridiculous waste of resources. A car is ready whenever you need it; a car-and-driver might not be. And yes, you could schedule a car-and-driver to be available at a particular time...but you could similarly schedule somebody to be available to load/unload at the destination.
> If the benefits were great enough (reduced pollution indirectly saving lives? saved life-years due to more efficient traffic?) one could even accept that they could be a little less safe as far as direct fatalities are concerned.
I disagree. I'm finding it hard to come up with an example that would make me think it's ok to have more people hit and killed by cars. I'm more than ready for self-driving cars to be a reality, but not if more people will die. "Saved life-years" is not good enough.
What does it mean to avoid a fatality other than saving that person's remaining life-years?
> I'm finding it hard to come up with an example that would make me think it's ok to have more people hit and killed by cars.
Entirely speculative: Heart failure is the leading cause of death in the US. If 100% self-driving traffic could let EMTs arrive faster at the scene that could save more lives than a slight increase from traffic accidents.
Thank you for checking this, and determining it didn't actually apply in this case.
We do a lot of I/O intensive Rust at work, and I have a list of things to double-check when benchmarking. The most common slowdowns: debug builds, unlocked stdio, line iterators, and anything else which allocates in an inner loop.
If I can hit 250 MB/s throughput per core on my laptop, with some light data processing, I'm usually quite happy.
I love that OSH Park (https://oshpark.com/) uses purple soldermask. It's a fairly unusual soldermask color, but they use only purple. It looks great with gold plating, and it gives a satisfying sense of branding to for open source hardware and prototyping.
Actually OSHpark boards I find are pretty crap. They have mouse bites left over, the mask is crap and the registration poor on some boards. Getting better boards from JLC but you lose HASL and purple.
Yeah, there are a lot more options for easy, small-batch prototyping PCBs these days. OSH Park was one of the first that was really easy and accessible to hobbyists, so even if it's not the best or the cheapest any more, the purple soldermask still has a place in my heart.
use std::time::SystemTime;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let t0 = SystemTime::now();
let triples = (1..).flat_map(|z|
(1..=z).flat_map(move |x|
(x..=z).filter_map(move |y|
if x * x + y * y == z * z {
Some((x, y, z))
} else {
None
}
)
)
);
for triple in triples.take(100) {
println!("{:?}", triple);
}
let elapsed = t0.elapsed()?;
println!(
"{}",
elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9
);
Ok(())
}
It takes about .376s to compile in debug mode, about 0.491s in release mode. This was after warming caches; the first run took about 2.071s, of which a large portion was probably loading the compiler and standard library.
In debug mode, it runs in 0.047586s, in release mode, 0.002304.
I was pleasantly surprised to see this is actually better on the build times and debug build performance, given that those are two often cited sore points in Rust.
I would also say that while this is a little bit noisy, it is more readable than the proposed C++20 version. "1.." looks more like a range starting at 1 than "iota(1)" does. There's an actual "if" statement in there.
In fact, while Rust doesn't officially have generator/coroutine support yet, it is available in nightly builds for the implementation of async/await. If you use the nightly compiler, enable the unstable features, and wrap an adapter type around Generator that implements Iterator, you can write:
let triples = IterGen(||
for z in 1.. {
for x in 1..=z {
for y in x..=z {
if x*x + y*y == z*z {
yield (x, y, z)
}
}
}
}
);
It's expected that at some point in the coming year or so async/await, and probably the underlying Generator feature, will be stabilized, and I presume the standard library will implement the Iterator trait for appropriate types of Generators (though there is some bikeshedding about the details of that).
Rust doesn't have generators yet, so this is only really fair to compare to the generator/co_yield example in C++ (which is also proposed but not yet standardized). I'd say Rust's syntax compares favorably to that example; the ranges are more clear than the traditional C-style "for" loops, there's native tuple syntax, and it's just be "yield" instead of "co_yield".
Rust sore points regarding compile times have to do with lack of support for binary libraries.
While on C++ I can take advantage of incremental compilation and linking, while using binary libraries for all dependencies, with cargo I have always to build the whole world from scratch minus standard library.
I'm not sure when the last time you've used Rust is, but that hasn't been true in quite a while (not sure how long exactly). Cargo now has incremental compilation, and it's turned on by default. It's great!
Binary libraries don't help so much -- many libraries use generic types and functions (those are instantiated and compiled for each specific instance) which can only be delivered as library "metadata", not codegen'ed, and the latter is the very slow part.
Wrong since C++11 introduced external templates for common instatiation types.
Additionally, it is not like every C++ library is full of meta-programming templates.
Finally, there are other languages with library "metadata" and generic data types, which can easily beat Rust compile times like Delphi, Eiffel and Ada.
> Fridge0 does not need a big battery bank, since it stores cold in its thermal mass and runs only when solar power is available.
> But, at least a mimimal battery is needed to run the computer control. Probably on the order of 5 watts for a computer like a raspberry pi; this could be reduced more with a more embedded computer like an arduino.
> Enough battery to run the fridge for a minute or two is also needed. Consider what happens when the fridge is running, and the sun goes behind a rain cloud. Suddenly, there's not enough power to run it, but it's still turned on. The inverter will try to run with whatever small solar power is still coming in, but it's not enough. Some inverters might manage a clean power off, probably accompanied with loud beeping. Other inverters might fail in more interesting ways.
> To deal with this situation, the computer needs to check the incoming solar power frequently, and power off the fridge if there's not enough. The battery is needed to keep the inverter and fridge running until that happens.
Basically, it sounds like the answer is because with a solar panel, there are states that are between "off" and "on," you rather just get an amount of power proportional to the amount of sunlight, and there's a concern that those states could cause problems if you don't provide a more constant power supply and active switching to fully shut off the power when your solar panel is not producing enough power for the "on" state.
Thanks for the references! I'm familiar with the concept of hysteresis, but hadn't been familiar with the idea of power sequencing for MOS devices, such as the VDD + 0.6V maximum ratings or latch-up. That's good to know!
I tried out SDF when I wanted to give someone some basic intros to how to use the shell and do shell scripting, and was looking around for something that provided some kind of free shell access.
The problem is, unless you donate or find someone to sponsor you, you don't actually get shell access; you get some very limited BBS functionality. And even once you do donate to get the basic access level, there are a number of basic programs (like Python and a C compiler) that aren't executable without getting a higher access level.
I wound up installing my own local version of pkgsrc in my home directory just to see if I could use that work around the issue, but that's not really a good option for the "teach someone how to use a Unix shell" use case.
It's easier to just spin up a free tier VM on one of the cloud providers than it is to use the "Public Access Unix" on SDF.
The SDF system was created at a time (1987) when accessing to a timesharing Unix system was a rarity for the majority of PC users who's outside of an institution, thus "Public Access Unix System".
At that time, the creation of a public minicomputer running Unix, which you can telnet into was groundbreaking. And in the late 90s when the WWW was taking off, it offered a wide ranges of community services, including a shell, access to newsgroups, Gopher, E-mail, IRC, and being an ISP with dial-up and DSL network connection, that served as a great platform to your online presence.
The time has changed and today it doesn't have the significance that it was. Running a system by yourself or renting a virtual server makes more sense.
Although SDF itself is still a good community, and now has a Minecraft server and a Mastodon server in addition to the technical BBS.
One other benefit of experiencing this system instead of a random cloud VM is that one can experience what a properly managed 'classic' unix system is like - e.g:
- multinode / shared nfs homedirs / multiuser
- CLI mail is wired up properly
- publish www via ~/public_html
- finger/whois
- system from source, 3rd party stuff in ports
the modern 'random ubuntu laptops + dhcp on wifi' network feels hugely impoverished by comparison as far as network cohesion
(but yes there are positives to this tradeoff too)
cli mail, finger and talk could be a great initiation to traditional tools!
As for the random ubuntu laptops, try to do the dhcp on wifi using a debootstrap of a minimal debian on a separate partition, then configure wpa_supplicant to start dhcp by systemd dependancy, and detect wifi card to start wpa_supplicant@wifi_card_device_name. This could give you a great introduction to modern tools! (bonus points if you setup a native wayland)
Understand the old and the new ways gives a better picture of the overall system, and will help you make education decisions.
(And it's not forbidden to setup CLI mail on your modern system, or a systemd-based classic unix! mix and match to your tastes!)
>
The problem is, unless you donate or find someone to sponsor you, you don't actually get shell access; you get some very limited BBS functionality. And even once you do donate to get the basic access level, there are a number of basic programs (like Python and a C compiler) that aren't executable without getting a higher access level.
Eh? It takes a minute of dropping in on com to get someone to verify you, and after that you have access to everything in the 'basic' user level -- which does indeed give you access to compilers and the like.
SDF appears to be down right now (maybe too much attention from this thread?), but according to the archive https://web.archive.org/web/20180503065444/http://sdf.org:80..., you need the ARPA membership level ($36) for "outbound telnet, ssh, sftp, ftp, ytalk, irc, snarf, wget" and "gcc, elisp, perl, php, python, ruby", and this matches what I recall from when I tried.
There are the "instructor" and "student" levels, but since this wasn't an official course I was running but just "I want to show someone the ropes of Bash scripting," I found it a lot easier to just spin up a free-tier VM on Google than try to find someone who could give me the appropriate membership level.
It's back up again, and I checked. Right now gcc and some versions of Python are usable for people in the "users" group, but others are not:
lrwxr-xr-x 1 root wheel 9 Jan 2 2018 /usr/pkg/bin/python -> python2.7
-rwx---r-x 1 root users 5952 Nov 12 17:13 /usr/pkg/bin/python2.7
-rwx---r-x 1 root users 1685 Nov 12 17:14 /usr/pkg/bin/python2.7-config
lrwxr-xr-x 1 root wheel 9 Jan 18 2018 /usr/pkg/bin/python3 -> python3.6
-rwx---r-x 1 root users 7728 Feb 9 2018 /usr/pkg/bin/python3.6
-rwx---r-x 1 root users 3132 Feb 9 2018 /usr/pkg/bin/python3.6-config
-rwxr-xr-x 1 root wheel 5984 Dec 24 01:27 /usr/pkg/bin/python3.7
-rwxr-xr-x 1 root wheel 3132 Dec 24 01:27 /usr/pkg/bin/python3.7-config
They seem to use the "users" group to deny execute access to members of that group, but they have some more recently installed/updated packages that they haven't applied such permissions to.
There is the additional membership level MetaARPA, at $9/month which you need to have to have access to tools like git:
The motd mentions that they're testing a NetBSD 8 upgrade right now, which may be why the permissions aren't set up correctly for some of the tools that are supposed to be restricted at the "user" level.
But anyhow, this kind of restriction of use of basic development tools for the free tier makes it kind of useless for what I wanted to use it for, even if the restriction isn't enforced all that well. I could understand if they restricted usage, like disk or CPU, or things like TLS for your home page, and I can understand restricting some outbound networking to prevent abuse, but not providing access to Python and Git in the free tier?
Definitely agree on just spinning up a free tier VM for very mild use cases or for a jump box or testing, or for troubleshooting network/provider/access issues. Google's always(?)-free tier 600M F1 Micro instance works nicely for this. Be aware only 1G transfer in the free tier though.
> If you follow the established best practices (and the compiler will warn you if you don't)
There are a lot of best practices that can be quite hard to follow without language support, and would generate too many false positives to warn about. For instance, use after free. There is no lifetime information available in the type system that the C compiler could use to tell you whether you are doing something that could result in a use-after-free. How do you propose the compiler could catch these, except in the most trivial cases?
Common practice would be to set the pointer to NULL after free and if you have multiple pointers to the same object - well, try to avoid doing that. If you must, you can use reference counting.
I think that's pretty terrible advice for something that affects memory safety, and it invalidates your entire "the compiler will warn you" argument. There's a reason Rust has ownership and lifetime annotations: there are many things that a compiler simply cannot infer.
I haven't looked into Rust very much yet, but doesn't the borrow checker effectively prohibit you from having multiple references to the same object?
I wouldn't say it's terrible advice though. If I see that something I do is potentially dangerous and would require special care to get it right, I'd first look if there is another way to do it.
The borrow checker allows for one mutable reference, or multiple immutable references. There are also primitives for allowing interior mutability through shared references, which enforce single access at a time by other means (mutexes, copying data in and out, etc).
References are always guaranteed to point to something that lives longer than them. What they refer to could either be on the stack, or it can be allocated and deallocated on the heap via smart pointers. Box<T> is similar to C++'s unique_ptr; there is a single owner, and when that owner is dropped, the referenced value is dropped. Arc<T> is similar to C++'s shared_ptr; it's an atomically reference counted pointer, so the value will be deallocated when the last clone is deleted.
These combine in ways that allow you to use most of those "best practice" patterns from C and C++, but with actual language guarantees that you will follow them and the compiler will catch it if you don't. In the internals of data structure implementation, you may need to go beyond what this allows with use of unsafe, but you can limit that just to a few small critical pieces of code that can be more thoroughly audited and tested.
In a large project "try to avoid doing that" doesn't really fly; in a large codebase, with dozens of developers, developed over multiple years, people are going to make mistakes. They will need to do some kind of refactoring, and one of the guarantees will get missed.
If you've done a decent amount of work in a large C or C++ codebase, you might appreciate this description of the process of storing a reference to a slice of a Vec in Rust, without having to manually reason about all of the places in which that slice could be invalidated: https://manishearth.github.io/blog/2015/05/03/where-rust-rea....
For vanilla references (&), Rust will prevent you from having multiple mutable references. Beyond that, there are several types in the stdlib[0] that progressively increase flexibility, but always safely.
I think it's bad advice because you need to know what is potentially dangerous. That alienates newcomers to systems programming (which is why one of Rust's goals is to be able to "hack without fear"). There are also some designs that I'd never try to build without safety checks, because they're notoriously hard to get right. Even knowing the fundamentals of memory safety, without a way of enforcing lifetimes and mutability, writing zero-allocation implementations that share immutably can be daunting.
Some things that are covered are a bit hard to find. For example, I didn't know if operator overloading was covered; it turns out, it's mentioned in https://doc.rust-lang.org/book/ch19-03-advanced-traits.html, but it's not in the outline and there's no table of contents on that page, and it's only actually mentioned as an example of how default generic type parameters work. The topic it is covered well by the `std::ops` docs (https://doc.rust-lang.org/std/ops/index.html), but since it's a language feature as well as a library feature, I'd expect it to be covered by the book as well.
#[path = "path/to/file.rs"] doesn't seem to be mentioned; there are probably a bunch of other obscure attributes like this that aren't mentioned.
repr? I didn't find any mention of #[repr(C)], #[repr(packed)], #[repr(align)] etc. I also didn't find union.
simd? Seems to only really be covered by the 2018 edition guide. Googling "rust simd" turns up references to the old, unstable std::simd.
The first two examples are a couple of things I've recently looked for and couldn't find; the others are ones that I noticed browsing around just now looking for other things that might have been missed.
Now, some of these are documented in the reference, in the nomicon, in the 2018 edition guide, or in the standard library docs. But that's one of the problems; that there's no one, or even two or three, places you can go to find everything you need.
The reference has large warnings at the top about being incomplete, although it's actually not as incomplete as I remember, it might be a good idea to remove the scary warning from it, or to do an audit of it and only put the warning on the sections that are found to be incomplete (like the memory model, which is clearly incomplete as it hasn't actually been formalized yet), but take it off of the sections that actually are up to date.
And Google doesn't always help. It still sometimes gives me first edition book links at the top. When I was trying to look up all of the `#[cfg(target_...)]` forms I could use, I tried to search for "rust cfg target", https://www.google.com/search?q=rust+cfg+target, but that gives me Rust By Example, a first edition link, and a link to a placeholder that refers to both the first edition and the reference. It took a lot of clicking through to actually find the reference page on it.
Thanks! So I think that some of this difference is that you're mostly describing library features, not language features. It's also true that some of these examples blur the lines. I'm going to make some notes.
> it might be a good idea to remove the scary warning from it, or to do an audit of it and only put the warning on the sections that are found to be incomplete
Completeness is hard, as you've seen with the book! This is what we'd like to do, but it's non-trivial.
I'd say that most of these are language features. The only that are mostly library features are operator overloading and simd, but they both have associated language features supporting them.
I agree that completeness is hard, but I feel like it could be a bit easier if there were some consolidation of the material.
At the very least, make sure that everything covered in the 2018 edition guide is also covered in the Book, in at least a similar level of detail. I'd also make sure that everything covered in the Reference is covered in the Book, or the Book provides at least an introduction to the topic and then a reference to the more detailed information in the Reference.
> I'd also make sure that everything covered in the Reference is covered in the Book,
They have very different goals, so this will never happen. The Book's job is to teach you how to program in Rust. The referece's goal is to (eventually) be a full specification. The former must be a sub-set of the latter.
I do agree that everything should be documented, but the book cannot cover every last possible thing.
Yes, that's why I included the second part, "or the Book provides at least an introduction to the topic and then a reference to the more detailed information in the Reference."
For example, I don't think that every last detail of #[repr(...)] needs to be covered in the Book; but as the entry point for most people, it's how they discover features, so it should at least provide an introduction, and link to the reference for more information.
Likewise, while I think that the std::ops documentation does a good job of covering all of the details of operator overloading, I think the Book could provide a slightly more discoverable introduction to operator overloading which isn't just being used as an example of another feature, default generic type parameters, and provide some links to std::ops which might help with the Googleability problem.
One thing that I think really needs to be focused on is some SEO for the docs. For some reason, the way the Rust docs have been organized over the years, with old versions of docs and the old book being replaced by the new one, means that a lot of times, when I search for something I find old, out of date docs.
For instance, with operator overloading, if I search for "rust operator overloading", I find Rust by Example, which is OK but has a lot of text in comments which is harder to read, followed by a first edition link which warns about being out of date and then provides a link to the new book but not where in it to look, as well as a link to the 1.30.0 version of the first edition book, then a link to std::ops (which if I were a newcomer, I might not realize was relevant), then a 1.5.0 edition of the book.
The first edition operator overloading chapter seems pretty reasonable, actually, and it's present in the table of contents so its more discoverable, and it contains a link to `std::ops`. But because of the new structure of the second edition book, the first page I see if I try to check the book tells me that it's outdated, and directs me to the new book in which this material is harder to find.
And in the new book, even once I find it, there's not much to direct me to where to learn more about the topic. There's no link to `std::ops` documentation; I have to separately look that up.
Part of the problem was that the first edition book was a bit more like a more accessible reference, while the second edition has a more narrative or tutorial structure. So there's no longer a place to go for an accessible reference to all of the language features. There's the Reference, but that's written for detail and precision and not accessibility, and as discussed, is incomplete. There's Rust by Example, but that's mostly just code examples with commentary in comments. The second edition book covers a lot of the same material as the first edition, but because of the different structure, some of the "reference information" on more advanced features is just buried in a couple of "Advanced X" chapters.
I'm not sure of the best way to address this; I admit that getting this right isn't easy.
One option might be to have the new book be in two halves; one of which was the narrative/tutorial portion; chapters 1 through 18, and 20, perhaps, though they might be able to be slimmed down a bit and some material moved to the second portion. The other half which is more of an "accessible reference" for advanced features; the material in chapter 19, but expanded a bit and with more discoverable per-topic chapters like the "Syntax and Semantics" section of the first book, plus the Nomicon material, and any of the topics which are missing.
Or, alternatively, just expanding on and integrating the "advanced X" material, Nomicon, and missing topics into the overall structure of the book.
Or another option would be to have the Book just be the Book focusing on the main narrative/tutorial introduction to the most common features, and have a Reference in two portions; one longer one which covers every major feature but in an accessible style with examples, followed by a more formal appendix covering each last little detail.
I guess ultimately what I'm saying (sorry for taking so long and so many diversions to say it, but as you point out, it is hard to get this right, and I've been thinking about what I'd be looking for as I write), is that there should be some place that has an "accessible reference" to all major features which is organized somewhat like the "syntax and semantics" section of the first edition book. The second edition book, chapters 1 through 18, is definitely a better organization as a book than the first edition, but that structure doesn't lend itself well to covering every feature, and as you point out, you wouldn't want it to.
But the Reference also isn't a friendly place to point people, both because of the "incomplete" warnings but also because it's written in a more formal style.
And the fragmentation into the Book, Nomicon, Rust by Example, stdlib docs, 2018 Edition Guide, Cookbook, Reference, Cargo Guide, Unstable Book, along with some of the reorgs along the way, can sometimes make it a bit hard to figure out the right place to look. I feel like there should be one document somewhere that has a reasonable accessible introduction, with examples, to every feature, in addition to the more formal and succinct Reference.
Maybe I should put my money where my mouth is and try to compile something like what I mean. It would help to have a little bit of buy in from docs team leadership, though, so that there would be a hope of it getting merged and maintained. Perhaps a docs RFC would be appropriate?
Compare with Go's language spec, which is written in a formal (but readable) style with little math. I wouldn't want it to have examples because it's good that it's concise.
One way to start might be to have an official extended cheat sheet. A cheat sheet needn't explain everything, but it should list every language feature available. The idea is to give you a definitive "inventory" of everything available so you can search for answers elsewhere if you see something you don't understand. It should also be brief enough for the language maintainers to commit to updating it when they enable new features.
It is actually fairly comparable to the Rust Reference (https://doc.rust-lang.org/reference/introduction.html), though the way the Rust Reference is divided into chapters makes it a bit hard to see everything at once or search.
They both do contain some examples, as well as things like the syntax in a BNF like format.
Perhaps what I'm looking for is just to have the Rust Reference made a bit more complete and a little more accessible in format (the division into chapters doesn't really seem to help much), as well as improving the SEO since it doesn't show up in Google searches often.
You can work in Courier Prime any time you want, and then switch to Courier for submitting your screenplay without worrying about it changing the pagination.
So it can help out any time you are working on your screenplay or working on it with anyone you know won't care, both before and after submission.