The main limitation at the moment is that we only support a handful of Web APIs (e.g. `fetch`, `URL`, etc.) and NodeJS APIs (e.g. `readFile`), as well as QuickJS's built-in ES2020 APIs, so if you try to run an existing app you may find it needs a Web API we don't yet support. If so, please feel free to open an issue on the `spin-js-sdk` repo.
This resembles ascending a rope using prusiks, which is a lot of fun if you haven't tried it. Great to see a variation the helps people with limited mobility to get around unassisted.
You do the same thing with prusiks to ascend a rope. Here's an example of a practical application, getting out a crevasse when climbing glaciers: https://www.youtube.com/watch?v=px_m3qzHYTA
In an alpine scenario you'd descend by rappelling. I doubt folks in a home want to setup a munter hitch or similar though. :)
This is how it’s taught in intro mountaineering courses. In the real world experienced alpinists carry a lightweight ascender, like a Micro Traction or similar, that can also be used for other tasks like hauling or fall protection for simul-leading.
It is a bit more complex. Climbing means falling. The 'ratchet' needs to work under shock loads. And wet/ice ropes radically change the friction numbers. There is a reason why climbers, experienced ones, know and use a great many different tricks for accending and decending ropes. A "big wall" climber can make a belay device out of almost anything, or even nothing.
I see. I tried to watch one video but they spent most of the time explaining how to create the rope/knots. I had assumed you eventually resorted to your arm strength to ratchet up the line. It does look like standing to ascend.
> Descending is a bit challenging for my brain to understand.
You would typically descend by rappelling, but it is possible to descend using two prussiks:
1. weight prussik B / unweight prussik A
2. slide prussik A down
3. weight prussik A / unwieght prussik B
4. slide prussik B down
5. repeat
I've never seen this done with two prussiks, but a similar sort of thing is done with two ascenders when rope soloing (e.g., to practice a single move over and over without re-rigging each time).
Haha! I though the same thing. I remember watching a video of an amputee ascending up El Cap using a similar set up only with lots of pull-ups! That and less of a Danish modern design aesthetic!
You can also do this by wrapping the rope around your foot. As you hoist up, let the rope around your foot go loose, then stand on your foot to go up again.
I've been making my way through this book for the past few weeks; just started Chapter 20. I tried reading Harper's Practical Foundations for Programming Languages first, but it was too abstract for me, so I switched to TaPL.
What I like most about Pierce's book is that he introduces each concept with a formal, abstract definition, complete with proofs of correctness, but also follows that up with a concrete implementation in OCaml. The latter is very easy to follow if you've had some experience with the ML family of languages. I sometimes find myself skipping ahead to the OCaml version when I get lost in the math syntax, which for me is less familiar. I'm planning to come back to Harper's book later, but Pierce's book is the perfect fit for where I am now.
My only criticism is that some parts are very dated given it hasn't been updated in almost 20 years. In particular, the version of Java he discusses throughout the book (pre-generics, pre-type-inference) bears little resemblance to the modern one. And since 2002 we've seen affine types (e.g. Rust) start to have mainstream influence, among other things.
In case it's helpful, I'm compiling a list of resources as I learn type systems, logic, category theory, etc.:
There are somewhat more involved formal treatments like Welterweight Java [1], which adds some more features, but of course, nowhere near the full set of Java features.
Some of the citations in that paper are also interesting.
I don't think there is a core calculus that specifically incorporates generics as in Java, but I could be wrong. In any case, much of Java's generics flow from theories of parametric polymorphism [2], specifically I believe bounded parametric polymorphism [3].
re: "I don't think there is a core calculus that specifically incorporates generics as in Java": doesn't Featherweight Java [1] already include generics? (Though a simplified version.)
I've implemented a RDBMS that supports this [1]. It handles joins, views (which are automatically materialized and incrementally updated), etc. It's memory only, and it doesn't support exotic stuff like recursive CTEs, but it does exactly what you're asking for. We used it in production successfully for frequently-updated real time data at the company where I used to work.
Notably, it uses persistent search trees such that each revision shares structure with the previous one, which makes diffing two closely-related revisions extremely efficient (just skip over any shared structure). Subscribers just receive a stream of diffs, with backpressure handled automatically by skipping over intermediate revisions. See [2] for a more detailed summary.
It also exposes revisions as first-class objects, which allows you to tag, diff, and even three-way merge them. Specifically, you can run arbitrary queries on both revisions and diffs. See [3] for examples.
It's no longer maintained, unfortunately. Someday I may revive it, perhaps adding support for spilling data that won't fit in memory to log-structured merge trees. I'd also rewrite it in a language like Rust, which will help flatten some of the more pointer-heavy data structures and reduce tail latencies. If anyone is interested in seeing that happen or helping out, let me know.
I'm really surprised this still isn't supported in mainstream DBMSes. The MVCC model in PostgreSQL seems particularly well suited to it.
I've been biking year-round in Denver for decades. The winters here are relatively mild, but we do get blizzards now and then.
I tried studded tires, but found they didn't help much. Black ice is rare here compared to layers of snow and slush, which don't give studs much to bite into. For me, three inch tires with an open tread pattern at low pressure -- plus an upright riding position that distributes weight evenly between the wheels -- gives me the most confidence.
Regarding the cold, I'd say windproofing is most important, and expedition-style mittens are well worth the investment. You won't need much insulation (except maybe at the extremities) once you start generating body heat. Multiple top layers, each with their own full length zipper, will let you regulate your temperature without getting off the bike. That's especially helpful if you have long climbs and long descents.
Nice work! I spent about six months pursuing the exact same idea about five years ago with the hope of building a company around it. I got reasonably far with a prototype, but gave up on the business side of things after doing more extensive market research and interviews.
One of the people I talked to had been involved with a startup called Adrenaline Mobility which did something very similar, but ultimately ran out of runway and was acquired by Twitter. He told an interesting story about how they (over-)built a highly scalable service but had a really hard time selling it. Those who lack the training to know the difference between good security and hand waving didn't see the value, and those who did have the training and skills didn't trust a third party to do it right anyway.
Nonetheless, a lot has changed in the past five years, and end-to-end encryption is more widely appreciated now. I hope you have better luck with the commercial side of things; this looks like a very promising start.
Thanks a lot! Things have indeed changed, and I feel like the public is really starting to understand the dangers with having their data exposed. I've been running EteSync for years now, and it's still growing.
I'd love to have a chat with you to learn from your experience if you are willing! My email is tom at etebase, please drop me a line (or let me know how to best reach you).
This might be very good timing for your product - the European Data Protection Board has just out their first guidance after the Schrems II case. It seems to firmly point towards cloud services where the provider can access the data in plaintext as being "unable to have the risks mitigated" from the perspective of international transfers.
Perhaps a straightforward E2EE toolbox could help companies implement their products rapidly so they remain complaint. Clearly this won't help fix issues like Microsoft 365 or GSuite (which need access to the plaintext for email and similar), but it might help some types of SaaS to thicken up their client application and prevent the backend having access to unencrypted data, thus making the transfer permitted.
I just want to echo the above comment around how most customers don't have the knowledge to understand the benefit of this, but hopefully this is changing as we see more strict enforcement of penalties for data breaches. Data is fast becoming a liability you don't want to have the ability to see, and systems like yours offer usable solutions for those who don't understand all the technology, but need a solution.
On the topic of inactive continuation implementations for Java: I implemented native support for both delimited (shift/reset) and non-delimited (call/cc) continuations in the Avian JVM. See https://github.com/ReadyTalk/avian/blob/master/test/extra/Co... for some mind-bending examples.
I wrote most of the Avian VM, and I agree that the code generation is quite primitive compared to LLVM's. We've considered using LLVM as an alternative code generator, but hesitated partly because LLVM used to require a shadow stack to support accurate GC. I just checked they're latest docs[1], though, and it seems that there are other options now.
All in all, adding LLVM support to Avian would be challenging but doable. However, Avian's generated code is already fast enough for most purposes, and it's not too hard to fall back to a bit of native code when you need maximum performance. My impression is that Java-on-iOS developers are less concerned about performance and more concerned with ease-of-use (e.g. tool integration) and convenient access to native APIs (e.g. Bro[2]). The RoboVM devs have apparently done a great job on both of those things.
I sympathize with Zechner and the other RoboVM devs. Development on Avian was originally funded by the company I was working at since it neatly addressed a problem we had: extending the lifetime of a large body of client-side Java code in a world that was/is increasingly unfriendly to client-side Java. Once it was good enough for that purpose, there was no business reason to continue investing in it besides bug fixes and maintenance, so we had to move on to other things.
I'd love to keep working on Avian full time and do cool stuff like an LLVM port or trace-based JIT compilation, but it's hard to justify when there are bills to pay. In my case, that means focusing primarily on other, income-producing projects. In RoboVM's case, it means trying a new approach to licensing to make development sustainable. I wish them luck with it.