I am in the process of creating a new web site. It will replace this blog soon. Here it is in draft form: https://resonant-bienenstitch-1ab75c.netlify.app/services/
I am in the process of creating a new web site. It will replace this blog soon. Here it is in draft form: https://resonant-bienenstitch-1ab75c.netlify.app/services/
Posted at 05:34 PM | Permalink | Comments (0)
Here's something I thought might be worth sharing. I've stored reference information on my personal computer since the 1980s and have seen the rise of software like mind-mapping and zettelkaste. I've tried them, but always found them more time-consuming than this technique with no real advantage for me. So here it is in case it's of interest to anyone.
Since the 1980s I have used an outliner for storing notes, links, etc. and some word processor for actually writing using that info. (Starting with WordStar; then various Mac word processors and lately MS Word.)
An outliner is fantastic for hierarchical information storage, of course. And there is an outline-native format called OPML so that you can switch outliners by exporting to OPML and importing it in your new software.
But the key to making it work really well for me is to also have "keywords" which involve starting an important word with a couple of underscores. For instance, I have __python. And I use an asterisk to represent sub-keywords. So my outlines have the outliner's natural structure, but I don't have to spend energy getting it perfect or navigating through it, because I can have an outline that is megabytes in size and still instantaneously find "python" and then if I'm looking for python databases, I can immediately search *database and I have my hierarchical list of python databases from which I can pick one for the project I'm currently working on.
Each of those has information about it stored in a hierarchical manner, so they are organized and have no need for keywords.
I have different outlines for different projects I'm working on, and a multi-megabyte one called "Instructions" for... uh... instructions for different technologies and non-technologies such as "_Learning" strategies. (The _python keyword is a top-level outline heading in that. I have hundreds or perhaps thousands of top-level items in that topic, accumulated since the 1980s. I COULD organize so that there were 5 to 10 top level items, trying to make it so that each of those would have 5 to 10 under it, etc., etc., but I have absolutely no need to do so, and no need to navigate through such a structure. This is for my convenience, not to be a lesson in the Platonic ideal of outlining.)
So I get the best of both worlds. Hierarchy where that's convenient, and instantaneous searching when that's convenient, in one seamless file, where I don't have to spend nontrivial effort on organization but can find whatever I want instantaneously –– and at any point where it's convenient, I can have the advantages of hierarchical information storage for that group of information items.
And then when I need to write something for someone else to read, I use a regular word processor. This way I can pick the best outliner I can find for my information organization (now OmniOutliner, previously More, and back in the CP/M days, Kamas), and the best word processor I can find for writing. (As I mentioned, that's currently Word, but for a long time I used Markdown word processors.)
I mention all the above in case my experience happens to be useful to anyone else.
I like the Rye project manager better than virtualenvwrapper, but missed workon
. So I made a bash shell script that, for my purpose, does the same thing as workon
. It's called Bourbon.
When you're in a Rye-based project (for example, project_x), do bourbon add
, and then in another terminal session you can do bourbon list
to show the projects Bourbon knows about, and bourbon project_x
to go to the project. Just type bourbon
alone to get help.
To be able to invoke it from anywhere, I put it in my source directory and made it executable with chmod +x bourbon.sh
. Then in my .zshrc, I put:
source /Users/garyrob/source/bourbon.sh
If bourbon
is too much to type, you can add:
alias bbn=bourbon
The script is at https://github.com/garyrob/bourbon/blob/main/bourbon.sh.
Posted at 12:54 PM | Permalink | Comments (0)
I wrote a terminal-based utility in Python that I'm thinking of releasing publicly (I've been using it myself for years). But the footprint seems very big for a terminal utility. So I've been looking at converting it to a compiled language. One with memory management. I like F#, but its executable footprint is surprisingly large.
I played with OCaml, and I basically like the language, but its tooling is not great and I'm finding that ChatGPT isn't good at writing OCaml code particularly when using libraries, because there just isn't much code out there using most OCaml ecosystem libraries.
Which finally led me to look at Rust. It has features I want like match statements, and even has macros that do pipelining. Obviously, it's usually considered a systems programming language, although there are things like web frameworks.
One might ask, however: For applications where efficiency isn't a major issue, why would you use a language where you have to manually deal with things like memory management, meaning that it will take significantly more code to accomplish the same thing as you could in a non-systems language?
An answer I'm considering: There is a lot of Rust code out there for training LLMs. My guess is that to the degree that a developer is willing to invoke an LLM to write Rust code, it can handle the memory management pretty much painlessly.
I'm not advocating turning programming tasks entirely over to LLMs. We should still read and understand any LLM-generated code we use, carefully consider the structure and tools it uses, etc..
But what I'm suspecting is that a language like Rust may get more use in the future. The time expenditure that goes with its programming overhead is greatly reduced when LLMs are used to generate code. Maybe there will be less traction going to languages whose main advantage is that they require fewer lines of code for the same results when those lines are often written by an LLM.
So I make a tentative prediction: LLM use will cause the Rust community to grow even more quickly than has already been the case.
Anyway, I'm going to be moving from Python to Rust, making substantial use of LLMs, and see how it feels.
Posted at 01:56 PM in Python, Rust | Permalink | Comments (1)
In the last few days there have been more than 2,600 visits to this blog from China. If anyone could enlighten me about why that is, by posting a comment, I'd appreciate it!
在过去的几天里,来自中国的博客访问量已超过 2,600 次。 如果有人能通过发表评论告诉我为什么会这样,我将不胜感激!
Zài guòqù de jǐ tiān lǐ, láizì zhōngguó de bókè fǎngwèn liàng yǐ chāoguò 2,600 cì. Rúguǒ yǒurén néng tōngguò fābiǎo pínglùn gàosù wǒ wèishéme huì zhèyàng, wǒ jiāng bù shēng gǎnjī!
Posted at 03:25 PM | Permalink | Comments (1)
Right now, the vast majority of people have little-to-no idea what distinguishes Ethereum from something like Dogecoin, and so their prices go up and down for the same reasons. But, behind the scenes, they are vastly different. This is the ultimate inefficient market: the relevant information isn't really penetrating yet to unlink Ethereum's and Dogecoin's price paths.
I have zero interest in investing in memecoins like Dogecoin. But I am bullish on Ethereum in the long term, say, 5-10 years, for reasons I'll describe below.
The people working on Ethereum are brilliant and fully engaged with doing all the grit work necessary to create a new kind of money. Unlike Bitcoin, which uses an incredible amount of energy because it's based on "proof of work," as is today's Ethereum, later this year (assuming things go as planned) Ethereum will be based on "proof of stake," which uses a very tiny fraction of the energy. But there are many difficult challenges involved in making proof-of-stake money as secure from malicious actors as it needs to be. Those challenges are the subject of much of the current engineering work in the Ethereum world.
Other work is involved in bringing down transaction fees to almost nothing. That will happen over the next few years, and involves something called "zero-knowledge proofs." ZKPs have been in development for a couple of decades, but only now is that technology being completed to the point that this type of practical application is possible. While there are efforts such as the "lightning network" to do something analogous in the Bitcoin world, the possible approaches just don't intrinsically work as well as what is possible with Ethereum as their basis.
That's because of the other major difference between Ethereum and Bitcoin. Ethereum includes a Turing-complete virtual machine so that software can be developed that runs on it, and that interacts with publicly-available data storage, not owned or controlled by any company, which will exist as long as Ethereum does, that anyone can access. That, too, is something new that will have a lot of ramifications. The twist being developed now is that zero-knowledge proofs will be built into the virtual machines.
Ethereum will not replace the credit card industry, which has layers to handle disputes, etc. Dispute resolution must be done by some centralized entity, and if you have that, you (arguably) might as well back it up with a centralized database. (However, that being said, it is also true that businesses will almost certainly arise to provide such dispute resolution services for blockchain-based transactions.) But there are use-cases for which dispute resolution is simply unnecessary, most notably, "micropayments.
I have been monitoring the ongoing engineering work closely, and my impression is that they are doing a great job at anticipating the problems that will emerge and spending the time (and money) to do the necessary engineering. It's a bit like building an airplane. There are a lot of pieces that have to be done right. Before they were, there was no airplane. Before they are done right for the blockchain world, there will be no real blockchain-based money.
But I think Ethereum has a nontrivial chance of being the breakthrough, creating what truly is a new kind of money with new, advantageous properties, and affecting the world of finance in a major way.
I am practicing what I'm preaching... one manifestation is that I'm writing software that runs on it... I'll say something here if/when I have something you can interact with.
I will be buying more Ethereum soon. I think there's a nontrivial chance that a lot of the world's finances will run on Ethereum in 10-20 years. To be part of it, you'll have to have Ethereum. And the amount of Ethereum will not be growing forever. So market forces will, if all this comes to pass, put a lot of upward pressure on the price of each coin. Even if it goes down from its current price of $1000 to $100 in the next months or the next couple of years, the upside possibility is still there unaltered. To see what will happen, there's no option but to wait until the airplane is built and see whether it works better, for its purposes, than earlier means of transportation.
With all the above as background, here's a brief outline of why I think Ethereum is a good, but highly speculative investment today:
1) 10 years from now, there will be about the same amount of Ethereum as there is now.
2) Ethereum may provide a significantly better basis for a significant portion of the world's financial transactions than exists now.
3) Ethereum's market cap is now on the order of $100 billion. The world's economy is on the order of $100 trillion. Therefore, if 10% of the world's economy runs on Ethereum 10 years from now, Ethereum's market cap will be $10 trillion, or 100X its price today. So Ethereum coins would be worth something on the order of $100K at that point. I think that outcome is very possible. Which would make it a good idea to invest in Ethereum today.
4) The reasons I think that is possible are twofold: a) I think this type of technology will probably have that level of importance in the future; and b) I think Ethereum is well-positioned to be the version that gets there. My reasons for being bullish on Ethereum, in particular for being the one are, again, twofold: a) in proof-of-stake systems with a design that works properly, security is based on the amount of money devoted to staking, and that is highly related to market cap, and Ethereum will soon be the proof-of-stake system with the greatest market cap, and b) as far as I can see, there is more engineering momentum and smarts being invested in the Ethereum ecosystem than in any of its competitors.
1) I may be fundamentally wrong: this type of technology may just not play a significant role in the future.
2) While I think Ethereum is the currently-existing technology that is most likely to fill the niche, because, when it converts to proof-of-stake later this year, it will have both the highest market cap for a proof-of-stake blockchain and the most engineering momentum, I may be wrong. Something else, such as competitor Polkadot, may do so. Or, Bitcoin may unexpectedly change course in a huge way. (Market cap is highly relevant because, in a well-designed proof-of-stake system, the security of the system is ultimately based pretty much purely on the combination of a) its market cap and b) the decentralization of the entities owning the coins.)
3) Something wholly unexpected and unforeseeable (at least by me) may come out of nowhere to better fill the niche.
4) There are some complications I'm not addressing in the above. Most notably: most of the transactions will take place in "layer 2", which, at least today, often uses coins that are not Ethereum. However, the security of those coins will be based on Ethereum itself. So, there will be natural pressure for Ethereum to have a high market cap relative to these other coins.
[Update: I recently heard from someone who says he conceived the idea of using a browser cookie to track people across web sites before me, but who said that he thinks I can still "safely" assume I actually worked out how to do it first. The USPTO doesn't count you as the inventor of a patentable idea until you actually know how to do it. As I mention in the piece below, the "how" was non-obvious at the time; I was told "you could, in theory, if you had source for your server, hack in someway for it to send the cookie somewhere. There is no existing protocol for doing so." But using a hack was unacceptable and the actual solution required none. My take on it is that it was just one of those ideas whose time had come. And that it therefore would certainly have have happened with or without me; nevertheless, for whatever it may or may not be worth, I appears highly likely that I am first to have actually have done both, together, of: a) independently conceiving of why one should be made, and b) figuring out how to do it. There are reasons that in a 2021 jointly-filed legal brief, Google and Twitter called it "Robinson's Cookie". More on all of that below.]
My patent, number 5,918,014,[1] describes how to track user activity using browser cookies and has a priority date of Dec 27, 1995. The patent doesn't claim anything about tracking cookies separately from a specific technique for choosing ads to present—my main focus in the days I spent on the patent was on a collaborative filtering technique, and advertising using a tracking cookie was a particular potential application of it. I developed the technique between Nov 2 of that year and the priority date. While the patent is focused on collaborative filtering in web advertising, soon after that, I became more focused on the tracking-based advertising opportunity in general.
The patent changed hands several times through the years, and Google is the current owner. As far as I know, it has never been used offensively. But it has been used defensively, most recently (as far as I know) in the case Twitter, Inc., et al. v. B.E. Technology, L.L.C (IPR2021-00485, filed Feb 24, 2021), in which Twitter and Google are using it to defend themselves in a patent lawsuit. In their petition[2] in that case, Twitter and Google repeatedly refer to the cookie tracking mechanism as "Robinson's Cookie."
My patent makes no attempt to claim the cookie-based tracking mechanism by itself, even though it describes it in enough detail that a programmer could implement it. Rather, at the time, I was looking for uses for a collaborative filtering technology I'd designed, and web advertising was an exciting one: collaborative filtering could potentially be used to recommend ads based on user-tracking data.
From the very beginning, people I talked to were sensitive to the potentially Orwellian nature of this technology. Because of that, much of the patent (filed a year after the provisional application that contained the original idea) is devoted to describing mechanisms to give users control over their data. (Again, none of that is claimed outside of the context of being used with my particular collaborative filtering approach.)
The reason I'm bringing this up now is that I've been noticing the wild happenings in the world of NFTs, where, for example, a NY Times column about NFTs sold for hundreds of thousands of dollars, and more recently, source code for the original World Wide Web was sold for millions. It occurred to me: I wonder if I could sell an NFT for the conception of cookie-based user tracking for web advertising, along with its written background story?
So, if anyone knows of proof of an earlier conception, please let me know, so that I don't waste people's time by presenting such an NFT.
Here's the background story. Of course, I'd be happy to answer any questions.
In the '80s, I created a voice-based dating service that served New York City. Its name and phone number was 212-ROMANCE. It was basically personals ads available by phone. There were recorded ads, and users could leave voice mail messages on the system for people they were interested in, engaging in a two-way voice-mail conversion before phone numbers were given out. This was fairly unique because there were very few interactive phone systems of any kind at that time. I advertised it in NYC publications that ran personals ads, such as New York Magazine.
With printed personals ads, it's easy to quickly scan them to find the ones most likely to be of interest. But listening to ads took real time, and the service charged by the minute. So I needed a way to make the ones most likely relevant to a particular user come out first.
I figured that if I kept track of which ads people responded to by skipping over, saving, or replying, I could order ads as follows: if person A generally likes the same ads as people B, C, and D, and if the latter users have responded positively to some ads person A hasn't heard yet, those ads should be played first when person A phones in again.
So I built that into the system, and it seemed to work very well. Then I thought: why couldn't I do the same thing for music or other things? So I spent a good deal of time working on a better way of making such recommendations than was used in 212-ROMANCE, which was very primitive although it worked well enough for that context. (I still have the 8086 assembly code and would be happy to share it if anyone is interested!)
In 1995, I was becoming quite interested in the internet and attended the 1995 Internet World conference in Boston. It ran from Oct 30 to Nov 2. In one workshop, the speaker was in charge of selling advertising for a Web site, and he discussed having to hire staff to act as "space salesmen." It was expensive. The cost of obtaining advertising to run on a Web site was a significant barrier to doing business on the Web.
At the time, I lived in Bangor, Maine, a 4-5 hour drive from Boston. I always liked using that drive to think. On the drive home, which I believe was on Nov 2, I went over things I'd heard at the conference, trying to see if there was anything in my background that could be useful for solving any problems that were discussed there. After an hour or two, I thought about the advertising presentation and had the sudden "Aha!": the recommendation algorithms I'd been developing could be used to recommend ads to people on Web sites! People's activities on the Web could be tracked for data to feed into those algorithms! There could be a hub through which ads were distributed, which would eliminate the need for space salespeople!
This idea really seemed like it had a lot of potential. I hadn't heard anything like it before. I don't think you'll be surprised to learn that I was extremely excited during the rest of that drive home. But, I also had some uncertainty because I had never done any internet-related programming and had no idea how user activity could be tracked across different Web sites. I didn't know if it was possible. I'm not sure whether I'd even heard of Netscape's "cookies" at that point—I don't think so—and I certainly didn't understand how they worked well enough to know that they could form part of the solution.
That drive was at night, and the next day I started researching how the idea could be implemented. Over the next weeks, I investigated various aspects of Web programming, and the thing that seemed to have the most potential was Netscape's cookie mechanism.
At first blush, cookies didn't appear like they could help, because they could only be written or read from the internet domain from which they were written. So, if a cookie was written by, for example, a CGI at golfing.com, it couldn't be accessed by a CGI at boating.com. It followed that the idea of having the servers for golfing.com and boating.com both accessing a central server at some other location to track user activity wouldn't work; there was no way to know that the same user had visited both sites because any cookies written at one site would be inaccessible to the other.
But as I looked further into the general topic of Web programming, I noticed that a Web site running on one domain could invoke a CGI running on another domain. And there seemed to be no reason why that CGI, running on that other domain, couldn't write its own cookie to the local computer. So, if Web pages running on golfing.com and boating.com each invoked a CGI running at adserver.com, then that CGI could know that the user had visited both sites. The cookie might be inaccessible to gofling.com and boating.com servers, but that didn't matter because it would be accessible to adserver.com.
I asked about this idea in Netscape-related forums, to confirm whether I was right. One response said: "You could, in theory, if you had source for your server, hack in someway for it to send the cookie somewhere. There is no existing protocol for doing so."
However, despite the apparent lack of understanding of this potential by at least some members of the Netscape programming community, when I had some tests run, it turned out that Netscape's cookie functioned in exactly the way I hoped it would and thought it might! Again, I was quite excited. Since Netscape's browser had 70%-80% of the browser market at that time, it would be very effective. And it seemed that, since Web developers were targeting the Netscape browser, more and more browsers would incorporate compatible cookie mechanisms in time so that Web sites incorporating cookies would be able to run in their browsers as well.
I figured that it wouldn't be too long before other people came up with the same idea, and I believed that it would be possible to build a successful company around it, so I rushed to create a patent that would make it safe to talk openly about it. I was hoping I could get venture capital funding and wanted a provisional patent application filed that would protect the idea, at least as it related to my particular algorithm for recommending ads.
The result was that on Dec 27, 1995, I filed a provisional patent application, although my records show I had figured out how to do the piece of the patent embodied in the tracking cookie concept by mid-October of that year. As I mentioned earlier, the patent was written in such a way that the cookie tracking mechanism couldn't be claimed separately from my collaborative filtering approach. While it disclosed how to track user activity across different Web sites by means of Netscape's cookies, it was not a general patent on that. I don't know whether it would have been possible to create such a patent, but I didn't try.
In any case, I subsequently, and as quickly as I could, made contact with various east coast VCs. The responses I got are, I think, quite interesting in retrospect.
The first VC I met with was Ted Dintersmith of Charles River Ventures. I'd met with him a couple of times previously relative to my collaborative filtering technology. (And my relationship with Ted, and his with Jeff Bezos, eventually led to Jeff calling me out of the blue about that technology before Amazon had recommendation functionality. But that's another story!) And I'd always felt like Ted was a truly good guy, and as generous and supportive as he could reasonably be—given that I was a lone programmer living in Bangor, ME, with no industry connections. (Everyone in the tech industry knows that VCs tend to invest in teams, not ideas, and there was no way I'd be able to present a proven team, or even myself as an entrepreneur to invest in. But Ted was still generous enough to meet with me a number of times.)
For a little more perspective before I present Ted's reaction to the idea of a hub from which ads would be distributed to many Web sites in a targeted manner, I'll mention that Ted was eventually ranked by Business 2.0 as the best-performing U.S. Venture Capitalist for 1995-1999. He was obviously competent.
While my patent only claimed the technology with respect to my collaborative filtering technology, I had written a white paper that discussed the far broader concept of hubs from which ads would be sent to many Web sites, targeting individual users based on the interests they'd displayed in the course of their Web browsing activities. Of course, today, that describes an industry worth many billions of dollars. Ted read it, and I met with him about it at Charles River.
I will never forget his response, which was startling enough to me that, 25 years later, I recall it pretty much word-for-word: "I don't see how a lot of money could be made from this."
And, with a major exception I'll come to soon, people I talked to about the concept generally responded the same way. The main reason seemed to be a mindset where they assumed that advertising on the internet would always be the same way it was at the time I was pitching the idea, and the same way advertising had worked from time immemorial. For instance, in the world of magazines, people subscribed to particular magazines because of their interests, and advertisers placed ads in the magazines that seemed to have some alignment between the demographics of the magazine. A golf magazine was the place for ads for golf clubs and for non-golf items that would appeal to the golfer demographic.
Imagining that ads would be targeted at the individual's interests, without necessarily paying attention to the demographics of the Web page he was currently visiting, seemed to be a leap that many people just couldn't make at the time. I doubt that anyone reading this will even be able to relate to that as a possible hesitation. But I heard it over and over. And it's a phenomenon I've witnessed over and over with respect to many things, especially in the very early days of the internet, when people were told about possible implications of the technology: They just couldn't see that the internet could lead to fundamental changes in the workings of well-established industries.
One VC, Ollie Curme of Battery Ventures, was the only one I spoke with who immediately saw the potential. It's undoubtedly not a coincidence that he had also been a speaker at that same Boston Web conference (he didn't attend the advertising session). He was far more attuned to the possibilities of the internet than most people were at the time.
During my meeting with him, he kept on saying: "What a great idea!" He seemed to absolutely love it. He couldn't have possibly given a response I would have experienced more positively. Of course, since a lone guy from Bangor without an entrepreneurial success story behind me, he wasn't going to invest millions of dollars in me. But he did the next best thing. He introduced me to someone who had been a CEO of a major CAD/CAM company. It seemed very clear that if this CEO wanted to run a company based on this concept, Ollie would be inclined to be the lead investor.
I met with this CEO several times. In the end, he told me something that would echo a lot of people's feeling, at the time as well as years later, about this kind of advertising mechanism: He said that he thought it was an idea with potential, but he didn't want to devote the rest of his career to spying on people. So he turned down the opportunity.
His response was prescient, but he wasn't the only person who responded that way. At some point in 1996, I went to a conference where I informally talked to other attendees about the concept, one of whom was the president of a direct-mail marketing company. We were standing in the crowded main atrium of the conference venue. Suddenly, he got down on his knees in front of me, raised his hands into the air, and repeatedly bowed all the way to the ground, chanting, "You are Big Brother! You are Big Brother!"
Meanwhile, as I expected, other people did independently come up with the same basic concept. Some of them involved entrepreneurial teams with far better track records than mine. Battery Ventures eventually funded at least one of those teams.
Ted Dintersmith did end up helping me out in a different way, by introducing me to someone who invited me onto the founding team of a company that did fairly well, giving me my first substantial entrepreneurial experience.
DoubleClick eventually bought my patent, and then they were purchased by Google, which is why Google owns it now.
I’m sure some readers may be wondering how I feel about the way tracking on the internet has played out. Has the prediction “You are Big Brother!” been fulfilled?
When the idea occurred to me, I naively saw a future in which people would be presented with ads they’d be interested in, instead of ads they are not interested in. I saw that as a good thing. After people like the Big Brother chanter responded as they did, I became aware of the privacy issues. That was between the time I filed a provisional patent application, which discussed using the tracking cookie to get data to recommend ads based on interest, and the time I filed the regular patent application. The regular application, therefore, had a ton of ideas relating to privacy. It had means for people to have control over their information, only giving advertisers as much information as they happened to want to give in order to improve the correspondence of ads to their actual interests.
Now, features very reminiscent of the ones I described in my patent appear on practically every web site when you are given the choice to accept all cookies or modify cookie preferences. This is definitely a very good thing!
One thing I didn’t foresee at all back in the ’90s was the degree to which web pages would be bloated and made intolerably slow by advertising and tracking mechanisms. It just didn’t seem like it would require a ton of code to be running locally; I envisioned the heavy lifting being done on the servers.
In the end, I believe that the downsides to the tracking cookie, as they have played out in the real world, are much worse than the upsides. But, if companies had put in privacy-protecting features from the beginning, and kept the computational load on the servers, and protected those servers adequately from hackers who would want access to the data, then things would have been different. But human nature being what it is, that was almost certainly an impossible dream.
[Update: an earlier version of this post requested any evidence that anyone could find of someone inventing the tracking cookie before me. I deleted that request because no one came forth with anything, I can't find anything, and in the legal brief I mentioned, Google and Twitter called it "Robinson's Cookie". If they couldn't find anything earlier with their legal resources, I think that's enough due diligence.]
[1] https://patentimages.storage.googleapis.com/c3/d4/40/239073914fa7fc/US5918014.pdf
[2] https://s3-us-west-1.amazonaws.com/ptab-filings/IPR2021-00485/3 See, for example, the top of page 40.
[3] https://www.w3.org/Conferences/WWW4/BOF.html
Posted at 05:52 PM | Permalink | Comments (0)
A student raised his hand and said "In that case, given that 1 = 0, prove that you are the Pope."
Russell immediately replied,'Add 1 to both sides of the equation: then we have 2 = 1. The set containing just me and the Pope has 2 members. But 2 = 1, so it has only 1 member; therefore, I am the Pope.'"
Posted at 11:51 AM | Permalink | Comments (2)
You may have heard about an artist named Beeple selling an "NFT" for $69 million a few weeks ago. NFT's are "non-fungible tokens," a definition that may not explain much! In this piece, I will try and provide a birds-eye view introduction to this wild new world.
If you read some of the recent articles about the NFTs, you'll see mention of "blockchains." Skipping all technicalities, the important thing about blockchains—the thing that makes them so useful—is that many, many computers are involved, working together, to store information. There are vast numbers of copies of that information. The fact that there are so many computers involved means that if the owner of one of them, or even a sizable group of them, wants to cheat by changing the stored information, he (or they) can't. This is because a larger number of computers still have the correct information and will refuse to accept the change.[0]
For instance, if the information that you own a particular amount of digital money is stored in a blockchain, nobody can change that information. You own it and can trust that you will continue to own it.
Now, digital money is "fungible." One digital coin is equivalent to another, the same way any particular dollar bill is equivalent to any other. So digital money can serve the same role as dollar bills in online transactions. If a merchant accepts one person's Bitcoin, every other person's Bitcoin is identical, and the merchant will accept it.
But "non-fungible" pieces of information can also be stored in the blockchain, such that there is only one and no other one is equivalent. Or there could be a set of such pieces of information with a limited number. If the piece of information is a "non-fungible token" representing a work of art, then it's helpful that information can be stored in it specifying one person as the owner.[3] And nothing can change that because it would mean messing with more computers than it's possible to mess with.
So, provenance is established. The record of provenance is stored in the blockchain. In the ordinary world, the provenance of the Mona Lisa is well-established. There's probably paperwork stored somewhere in the Louvre going back to da Vinci. But everybody agrees that the one in the Louvre is the original. Now, suppose somebody makes a copy that is so exact that even the best experts can't distinguish it from the original. The copy would nevertheless have little value. It's the provenance that matters for value.
Everybody trusts the provenance of the Mona Lisa that's in the Louvre. But everybody can also trust the provenance of an artwork represented by a non-fungible token in a blockchain.
Now, some people are using NFTs to represent the provenance of physical works of art; that information is just as secure there as it would be in a vault in the Louvre. So there's a reason to do that. But I don't personally think that, for most works of art on the marketplace, there is serious question about their provenance such that that's the most important use for NFT's.
My personal opinion is that the primary art-related value is for digital artworks, where every copy is absolutely identical to the original and there is no hope of telling them apart except for information stored somewhere that says who owns it. And there's no better place to store that information than on a blockchain. And there are services out there such that it is trivially easy to store that information there.
Why would anybody want to buy digital art? With traditional art, you can hang it on a wall or put it on a table and see it whenever you want. But with digital art, you can see it whenever you want to; it's just in your computer. For instance, it could come up whenever you're not working and take over your computer screen through "screensaver" functionality.
But I think their value is also analogous to things like baseball cards. For reasons having nothing to do with the physical characteristics of a cardboard card, certain rare ones, such as early Mickey Mantle cards, become very valuable over time. People don't hang them on a wall for their aesthetic virtues. They just want to own them because they're both rare and significant, and have value due to how rare and significant they are.
That's what happened with the Beeple NFT that sold for $69 million a few weeks ago.[1] It's a digital image. But because the artist had notoriety by the time Christie's auctioned it, and because the auctioned image contained images of earlier works of his for each day from an early point in his career, it was unique. In that way, it was analogous to a rookie season Mickey Mantle card. So it sold for a tremendous amount of money.
But another way I think NFT artworks will be valuable in the future is with "digital canvases" such as the Meural[2]. You hang them on the wall as if they're paintings. Such canvases can be beautifully colorful and can display any work of art. You see a Van Gogh in the frame at the page linked at [2]. But of course, Van Goghs lose something in that kind of representation. The translation to digital form can't retain every nuance of a physical work.
Still, a frame like that has the advantage that beautiful artworks can rotate through it... so you can have Van Gogh during the day and a Picasso at night if you want. Or a different great painting every 5 minutes.
But now consider artworks that are created specifically for a digital context. I visited a museum recently which was showing the works of an artist who has been well-known for many years but had started working on an iPad. There were many works of his being displayed in digital frames on the walls, all of which were created on that iPad. They looked great. I felt that they were real art, and worth displaying on one's wall in a digital frame. And provenance would matter: for a given work, you could own the only NFT for that work.[4] If other people showed the same image on their walls, it would be analogous to you having an original physical work by that artist, from the period when he still used a canvas and brushes, and others showing extremely well-done copies. Only yours would have the value associated with that artist's work.
The result of all this is that the world of NFTs provides a new avenue for artists to create and sell their work. It has different characteristics from the traditional art world, such as eliminating the need for artists to convince gallery owners to display their works. (However, other means will then be necessary to develop the awareness of potential buyers, and those means are being developed now by entrepreneurs.)
[0] In reality, nothing is perfect. People have had digital money stolen. Also, there are nuances such as "Proof of Work" vs. "Proof of Stake" that affect what roles all those different computers have. I am trying to be as high-level here as possible to communicate only the absolute basics.
[1] https://www.nytimes.com/2021/03/11/arts/design/nft-auction-christies-beeple.html
[2] https://www.bloomingdales.com/shop/product/meural-winslow-digital-canvas
[3] Actually, the information is stored at an "address" on the blockchain; and the owner of a coin knows the address and keeps it secret. The fact that someone could discover the secret is one of the vulnerabilities by which one can steal digital money or NFTs. For instance, you might print out the address and keep it in a safety deposit box; somebody might break into the bank vault and get the information.
[4] An artist can also create the equivalent of limited edition prints by creating a fixed number of NFTs that are identical except for ownership information.
Posted at 02:56 PM in Current Affairs, Web/Tech | Permalink | Comments (7)
Posted at 02:33 PM | Permalink | Comments (0)
[Update: This blog contained a series of posts showing the results of my Stupid Simple Model for predicting the number of covid fatalities. I deleted most of them because they're irrelevant now. But the upshot is that the SSM was more accurate than the IHME. The philosophy of the SSM was that the IHME was trying to make predictions based on a number of factors that we just didn't know enough about to be meaningful. From the SSM's perspective, they were therefore just noise, more likely to cause distortions than be helpful, and a better prediction could be made by simply extending overall statistical trends. That is, we assume that, while there is a broad range of potential outcomes, the trends have already seen are at the center of those possibilities. That turned out to be more reliable basis for predicting than assuming that we could make use of truckloads of factors we didn't actually understand. In the end, up to the date for which the SSM had made predictions, it was more accurate than the IHME. ]
As of April 17, the Institute for Health Metrics and Evaluation is predicting 60,308 US COVID-19 deaths by August 4, 2020.[1] (Down from their prediction of 68,841 yesterday, and from a prediction 61,545 for that date made on April 12.)
Essentially, this is a contest between the Stupid-Simple Model (SSM) and the IHME. On April 12, the IHME predicted 61,545 deaths by Aug 4. And on that same day, the SSM predicted more fatalities than that by April 22. And it’s still predicting that. That’s 4 days from now! Who will turn out to be closer to correct?
Below is the recent growth in fatality rates:
2020-04-01: 1.24
2020-04-02: 1.26
2020-04-03: 1.18
2020-04-04: 1.13
2020-04-05: 1.13
2020-04-06: 1.14
2020-04-07: 1.18
2020-04-08: 1.16
2020-04-09: 1.12
2020-04-10: 1.13
2020-04-11: 1.1
2020-04-12: 1.08
2020-04-13: 1.07
2020-04-14: 1.1
2020-04-15: 1.1
2020-04-16: 1.16
2020-04-17: 1.12
For the SSM, I average the last 8 days’ exponential growth and get 1.1059. We then take yesterday’s numbers:
2020-04-17: Deaths: 3,857; Accumulated deaths: 36,773
Finally, we project forward using the SSM, seeing that the SSM anticipates more fatalities by 4 days from now (Apr 22) than the IHME predicts for Aug 4.
2020-04-18: Increase: 4,265 Total: 41,038
2020-04-19: Increase: 4,717 Total: 45,755
2020-04-20: Increase: 5,217 Total: 50,972
2020-04-21: Increase: 5,769 Total: 56,742
2020-04-22: Increase: 6,380 Total: 63,123
2020-04-23: Increase: 7,056 Total: 70,179
2020-04-24: Increase: 7,804 Total: 77,984
2020-04-25: Increase: 8,630 Total: 86,614
2020-04-26: Increase: 9,544 Total: 96,159
2020-04-27: Increase: 10,555 Total: 106,715
2020-04-28: Increase: 11,674 Total: 118,389
2020-04-29: Increase: 12,910 Total: 131,300
2020-04-30: Increase: 14,278 Total: 145,578
2020-05-01: Increase: 15,790 Total: 161,368
[1] https://covid19.healthdata.org/united-states-of-america
Posted at 03:11 PM | Permalink | Comments (0)
[I will be updating this daily for the foreseeable future.]
A very simple, two-week-ahead COVID-19 fatalities predictor. The main purpose of this predictor is to give a better sense of the implications of exponential growth to viewers who may not have a strong intuitive sense of that. Also, it’s for people like me who simply want to know: “If conditions stay as they are, where will we be in two weeks?” Finally, if it spurs discussion about the causes for changes in the exponential growth factors, that would be great too.
Daily change in exponential growth factors:
2020-03-27: 1.31
2020-03-28: 1.28
2020-03-29: 1.22
2020-03-30: 1.21
2020-03-31: 1.3
2020-04-01: 1.23
2020-04-02: 1.25
2020-04-03: 1.2
2020-04-04: 1.19
2020-04-05: 1.14
COMMENTARY:
The most recent exponential growth rate is the lowest yet. This may indicate a temporary slowdown, or a long-term one. Perhaps it’s driven by the slowdown in NYC. Deaths in NYC for Saturday, Sunday, and Monday were 630, 599, and 594, respectively. That slowdown is probably because of the high level of social distancing occurring there. Without it, the rates would have been much higher even if there were an infinite supply of hospital beds on ventilators, but there aren’t, so the death rates would have been even higher.
Yesterday’s US fatalities: 9,616
Predicted total fatalities for the US based on the average growth rate for the most recent 3 days:
2020-04-06: 11,303
2020-04-07: 13,287
2020-04-08: 15,620
2020-04-09: 18,361
2020-04-10: 21,584
2020-04-11: 25,373
2020-04-12: 29,827
2020-04-13: 35,062
2020-04-14: 41,216
2020-04-15: 48,451
2020-04-16: 56,955
2020-04-17: 66,952
2020-04-18: 78,704
2020-04-19: 92,518
COMMENTARY: Yesterday’s model predicted a total of 120,378 on 4/18. So today’s 78,704 is quite a change for that date, showing the power of relatively small changes to an exponential growth rate. Let’s hope the growth rate continues getting smaller.
If you've been exploring ReasonML, you might have run into a problem where the Pipe First operator doesn't seem to work in rtop. You get the error message:
Error: Unbound value |.
Well, it turns out that that's just the way it is. Pipe First doesn't work in rtop. rtop uses regular, native OCaml's utop, which doesn't have Pipe First. Your compiled Reason programs can use it, because they rely on Bucklescript rather than native OCaml.
This behavior may change in the future, but it's as it is right now.
Posted at 11:37 AM in ReasonML | Permalink | Comments (0)
From the Unix & Linux StackExchange:
Q: We've noticed that some of our automatic tests fail when they run at 00:30 but work fine the rest of the day. They fail with the message "gimme gimme gimme" in stderr, which wasn't expected. Why are we getting this output?
A: er, that was my fault, I suggested it. Sorry. Pretty much the whole story is in the commit. The maintainer of man is a good friend of mine, and one day six years ago I jokingly said to him that if you invoke man after midnight it should print "gimme gimme gimme", because of the Abba song called "Gimme gimme gimme a man after midnight”… Well, he did actually put it in, a few people were amused to discover it, and we mostly forgot about it until today...
Posted at 08:07 AM | Permalink | Comments (0)
I can't let this go unremarked. This may be one of the greatest milestones in the history not only of technology, but of humanity, and it is not being noticed at all by the vast majority of people. A machine has created honest-to-God, deep beauty for the first time I am aware of. "At first, Fan Hui thought the move was rather odd. But then he saw its beauty. 'It’s not a human move. I’ve never seen a human play this move,' he says. 'So beautiful.' It’s a word he keeps repeating. Beautiful. Beautiful. Beautiful.” [http://www.wired.com/2016/03/sadness-beauty-watching-googles-ai-play-go/]
It’s referring to a move in the game Go. People didn’t think a machine would be able to beat a top human player for a long time to come. But it’s happening now.
This isn’t poetry or music or a painting, but to say that means it isn’t real beauty would be merely to not recognize that real beauty can occur in other contexts, such as the game of Go. What will the world be like when machines start creating beauty in the contexts most of us are more familiar with? There is already software that analyzes recorded music to determine what tracks are most likely to be hits, and it works fairly well. It “understands” the characteristics that make people want to listen to music enough to be able to tell whether those characteristics are present, to at least a degree that makes that software commercially worthwhile. If you combine that with the smarts it’s taking to beat the best mankind has to offer at Go, and create beauty in doing so, you have to wonder what will come next.
An important factor is the extreme rate at which artificial intelligence is getting better and better. People are projecting that it won’t be long until machines start designing new machines, using “ideas” that humans aren’t creating or, necessarily, fully comprehending… when that happens the rate of improvement will skyrocket, and it’s already quite extreme.
I await the future with excitement and trepidation.
Posted at 03:26 PM in Science | Permalink | Comments (0)
I assume everyone reading this has heard by now of the LIGO experiment detecting gravitational waves for the first time.
The discovery is encapsulated in this very short YouTube.
It is a little confusing without explanation. I saw the video at other links without the explanation and it didn’t make sense: Why were there two chirps? The answer is simply that they play the chirp twice, so that if you want to hear it more than once, you don’t have to keep restarting the video!
But in any case, the chirp is the sound of two black holes spiraling around each other faster and faster as they get closer together, and the sound stops when they’ve combined into one black hole. That is, the frequencies you hear in the chirp are determined by the speed of the spiraling. (The whole recording does get sped up a bit so that it is in a good range for human ears to hear.) Note that these black holes were approaching each other at nearly the speed of light!
From the exact measurements of the characteristics of the chirp, scientists can determine that the two black holes were 36 and 29 times the mass of the Sun, respectively. And the resulting black hole is 62 times the mass of the Sun. These objects are pulled in by the enormous gravity so that they are remarkably small. A black hole that is 30 times the mass of the Sun will have a radius of only 55 miles.[1] Keep in mind that the radius of the Sun is 432,474 miles!
But wait, 36 plus 29 is 65, so why did the resulting black hole only have 62 solar masses??
You might recall Einstein’s equation, E = MC^2 (pronounced E equals MC squared). Energy and mass are equivalent and can be converted from one to the other. And what happened is that 3 solar masses were converted into the energy of the gravitational waves that were detected in the experiment! How much energy is that? "For comparison, that’s about 10 trillion times the energy emitted by the sun over the course of an entire year.[2] Or: "8.5 billion trillion trillion Hiroshima atomic bombs.”[3]
Or to put it yet another way, "Calculations show that the peak gravitational wave energy radiated was more than the combined light energy released by all the stars in the observable universe.”[4] !!!!!!!!!!
Note that black holes are objects we can’t see with we can’t see with electromagnetic radiation.[5] That’s the point of black holes… their gravitational force is so strong that light waves can’t escape it. We are “seeing” these black holes with gravitational waves instead of light waves. We have never directly observed a black hole before… up until now, we’ve only been able to indirectly infer their presence. But now we can “see” and “hear” them directly. Now we have far more reason to believe they actually exist than we had before.
The next part of this write-up attempts to give some background about why this actually proves something and has pushed science forward in a significant way. If you dont care about that, or if you already know why, there’s no reason to read further!
The scientific method is to generate a theory that has implications that can be tested. Then you run the test. If the test fails, then there is no reason to give further weight to that particular theory, and you move on. But if the test succeeds, then it is extremely likely that there is something to the theory worth further exploration.
Consider Einstein’s completely theoretical ideas about general relativity. That theory generated a hypothesis: that the light of a distant star which must travel close to the Sun before reaching our eyes would be bent. If you looked at the star with a telescope at night, so that the Sun was not a factor, the star would appear to be at one location; but when you looked at that same star during the day, when its light had to brush by the Sun on its way to us, the star would appear to be at a different location. The time of a total eclipse was chosen to make the measurement because that way the starlight would be visible during the day.
Einstein’s theories enabled him to compute the exact angle by which the apparent location of the star would shift during the eclipse. That was the hypothesis: If General Relativity was a correct theory, that shift would be detectable; if it wasn’t, no shift would occur.
And lo and behold, the predicted shift did occur. The news made newspapers around the world. It’s considered to be the first experimental proof of General Relativity, and one of the greatest scientific discoveries of all time.
With regard to the LIGO experiment, there was a predicted shape of the waveform that would occur as two black holes spiraled into each other. This was exactly equivalent, from the standpoint of the scientific method, to Einstein’s prediction of the exact angle that the starlight would be deflected by the Sun’s presence. If we could detect that waveform in nature, the theory would be vindicated.
And LIGO did detect a waveform having exactly the predicted characteristics (at least within the limits of experimental error, as was also true with Einstein’s starlight prediction), and which has no other explanation that scientists can conceive of. You can see it and hear it. Its really quite amazing. It’s not like they detected all sorts of waveforms that were slightly similar to the theory, and picked one that happened to match it more exactly. They didn’t.
They detected THIS one, and it just happened to completely conform with the theory. It is simply far too unlikely to have happened by chance alone. Just as Einstein didn’t detect lots of starlight deflections, and pick one that happened to correspond to the theory. A deflection coinciding with the presence of the Sun had never been looked for before, and when it was, its angle conformed to the theory. Out of all the possibilities that could have happened, starting with the overwhelmingly great possibility that no deflection at all would be detected, just happening to conform to the predicted angle would be extremely unlikely. So much so that that possibility can be dismissed as being too unreasonable to take seriously. Same thing with LIGO.
Note that all this doesn/\'t mean that the theory is 100% complete and perfect. In the history of science, there are always further nuances to discover, or new contexts that make us understand old theories in a new way. But it DOES mean that there is something about the theory that is highly revealing of an aspect of nature; and thus is something that will provide a basis from which further discoveries can be made.
[1] http://physics.stackexchange.com/questions/92990/finding-the-schwarzchild-radius-of-a-star-of-solar-mass-30
[2] http://www.vice.com/en_au/read/we-asked-an-astrophysicist-about-the-biggest-discovery-in-the-universe
[3] https://cosmosmagazine.com/space/got-them-gravitational-waves-detected-at-last
[4] http://spaceflight101.com/gravitational-wave-discovery-opens-new-window-on-the-universe/
[5] https://physics.aps.org/articles/v9/17
Posted at 09:47 AM | Permalink | Comments (0)
Inspired by “Git in 5 Minutes”, I decided to take things a step further, and create guide for git that takes even less time to get through. Of course, this is very minimalistic git! But it’s enough be useful for beginning solo developers, and provides a start from which you can grow. As far as I know, this post is the absolute record for minimalistic git guides on the web!
In two minutes, there isn’t time to worry about a remote server, so this manner of using git is only appropriate for a solo developer who has a regular backup strategy in place for their hard drive. With 2-minute git, plus a backup strategy, you can confidently commit files and know that you can see changes or restore an earlier version if you need to.
Why does this even matter? Well, one of the most annoying and time-consuming experiences a developer can have is to realize that something that used to work no longer does. In such situations, simply being able to see changes and go back to an earlier version can be a huge help. Also, being able to go back gives you freedom to experiment with a new approach — there’s no problem experimenting because you can always go back.
When you have a chance, you should definitely learn about such features as staging and branching, and pushing and pulling to/from remote repositories. But what you’ll learn here will still be useful!
Note: When a filename is mentioned below, you can just as easily use a file path.
We’re assuming you’re working in a directory. The first thing you should do is:
git init
which initializes the directory for git use.
Now you have to tell git which files it should care about. If you have N files, you can do
git add <file1> <file2> … <fileN>
to add them. Or if you want to add every file in the directory, you can do
git add .
Next, we need to commit changes. Any time you want to commit changes to one or more files, do
git commit <file1> <file2> … <fileN> -m "This is your commit message"
Or, to commit all files that have changed since the last commit:
git commit -a -m "This is your commit message for all changed files"
Be sure to make your commit message contain enough of a description that you can figure out what version you want to go back to.
Now we need a way to see old versions are available. To see your commit messages along with each version’s “hash” (a number that refers to the version), you can use the following command to show them in a one-version-per-line output.
git log --pretty=oneline
That will give you output that looks like the following, showing each commit’s hash together with its commit message
dbe28a0a1eba45d823d309cc3659069fc16297e3 4th version I wanted to commit 13bbf385e6d1f94c7f11a4cdfa2a7688dfdd84f8 3rd a1696f671fb90dc8ea34645a6f851d0ab0152fc2 2nd version 179e59467039c7a7b81f676297415c8e018542a0 first version
Note, you can also use
git log
for a much more verbose output, with multiple lines per version, and you can use
git log --pretty=oneline -- <filename>
to view only the changes for a particular file. (Note the space after the second pair of dashes!)
To restore a file to an earlier version, you need to identify the version you want to restore. To restore the most recently committed version, just do:
git checkout HEAD -- <filename>
To get back an earlier version, just use the first few characters of the hash (enough to uniquely distinguish it):
git checkout <hash> -- <filename>
For example,
git checkout 179e59467039 -- myfile
will revert my file to the contents of the file called myfile that are associated with the 179e59467039c7a7b81f676297415c8e018542a0 hash (in this case, the first committed version of the file).
You usually won’t want to retrieve an old version of a file without first examining the changes it contains! To see a list of the changes between the current file and the most recently committed one, you use the fact that HEAD represents the most recent commit:
git diff HEAD -- <filename>
Alternatively, see a list of differences between the current version of a file and a historical one, you refer to the historical version’s hash:
git diff <hash> -- <filename>
You can also compare two historical versions:
git diff <hash1> <hash2> -- <filename>
Finally, to see a list of the changes you’ve made since your last commit across all files, simply do:
git diff
Note: all the diff variants shown above put the results into a pager. You can page through using the space bar, and quit with q. If you don’t want to use the pager, add -P, like:
git -P diff HEAD -- <filename>
git reset HEAD^If the only problem is in the commit message itself, you can replace it with:
git commit --amend -m "Replacement commit message"
While you can get a lot of benefit using just the features above, here's one more thing you'll find to be useful. If you don't want to bother with it now, don't – try it another time.
Sometimes, you're not sure what files have changed. To find out, you can do:
git status
That'll generate a list of files and their statuses. For example, a file that hasn't been "git add"-ed will be listed as untracked; if it's a file you care about, you should add it.
The reason I consider this command "optional" in a two-minute guide is that it can be a little unwieldy. It can list a lot of files you don't care about. For instance, if you're programming in Python, it'll show the compiled .pyc files that Python generates. And you'll probably want to do something about that.
To fix it, you need to create a file called .gitignore in your project directory. For instance, if you're working on a project in Python 2.x, you'll probably want it to contain (at least):
.pyc
Notice that .gitignore understands the * wildcard. And if you want to hide an entire directory, you append the folder name with a slash. For instance you're working in Python 3.x, the compiled files go in a directory called __pycache__, so you'll want the following in your .gitignore:
__pycache__/
That’s all you need to know to get started with git, as long as you have a regular backup strategy for your hard drive. If you don’t want to memorize anything, just keep this guide bookmarked and you’ll be able to commit, compare versions, and get back old versions without any trouble!
Remember, this guide is literally as minimalistic as you can possibly get in order to do something useful with git. For powerful features like branching, staging, and sharing with others via a remote server, be sure to move on to Git In Five Minutes and even (?!) longer git guides when you have a chance!
[Update Aug 6, 2022: added the entry for undoing a commit.
Update Jan 2, 2017: added the use of HEAD in restoring file versions.
Update September 7, 2015: added two more ways of seeing changes.
Update September 20, 2015: for some reason the optional section on git status and .gitignore disappeared at some point. So I put it back! Also rewrote the diff section to put the HEAD version first.]
Posted at 05:07 PM in Web/Tech | Permalink | Comments (7)
An observation found on a t-shirt my son owns, and which I also noticed today on Hacker News:
There are 10 people in this world, those who understand binary and those who don't.
The first reply on Hacker News:
There are 10 kinds of people in this world: Those who understand ternary, those who don't, and those who mistake it for the binary system.
Posted at 09:56 AM | Permalink | Comments (0)
Durandal provides the Durandal Test Framework for unit testing. This test framework uses PhantomJS and Jasmine.
As shipped with Durandal, it's focused on testing Durandal's own internal components. But it can easily be adapted for your own unit testing needs.
You can obtain the test framework by downloading the entire Durandal project with
git clone https://github.com/BlueSpire/Durandal.git
(assuming, of course, you have git installed).
Note that if you're not on Windows, you'll also need to install PhantomJS on your system, since the PhantomJS that comes with the Test Framework is a .exe.
In your own work, you're probably not going to want to use the entire Durandal project -- you may start with a starter kit such as the HTML Starter Kit, or even with your own custom setup. The first challenge is that the Starter Kits don't include the Test Framework. Beyond that, since the Test Framework is configured out-of-the-box for Durandal's internal testing needs, its hardcoded paths don't work for the directory hierarchies you'll have as a developer.
But configuring the Test Framework for your own needs is very easy. Edit spec.html in the test directory. In that file, you'll see that require is configured with some paths:
paths: {
'specs': '../test/specs/',
'text': '../lib/require/text',
'durandal': 'durandal/js',
'plugins' : 'plugins/js',
'transitions' : 'transitions/js',
'knockout': '../lib/knockout/knockout-2.3.0',
'jquery': '../lib/jquery/jquery-1.9.1'
}
For the HTML Starter Kit, with the test directory copied into the top-level directory at the same level as lib, css, and app, you only have to change three of them:
'durandal': '../lib/durandal/js',
'plugins' : '../lib/durandal/js/plugins',
'transitions' : '/lib/durandal/js/transitions',
In general, you just need to find the durandal, plugins, and transitions directories and set the paths appropriately.
It's also helpful to add a path to the app directory where your code will live:
'app': '../app',
You can test your paths by removing the existing test modules from test/specs (which will no longer work, since they are for Durandal's internal testing) and replacing them with a new, dummy test module such as:
define(['viewmodels/flickr'], function (flickr) {
describe('', function(){
it('returns true', function () {
expect(true).toBe(true);
});
});
});
This sets up testing for the flickr module that ships with the HTML Starter Kit. If you're using some other setup, you'll need a different test. But this shows how it's done. It doesn't test every path, but since the flickr module uses the durandal and plugin paths, it tells you whether you're on the right track.
To run the test:
$ phantomjs spec.js
You'll know that you don't have the paths set correctly if you get a error like the fullowing, which leads to a hang of PhantomJS:
Running spec files: specs/mytest.spec
Error: Script error
http://requirejs.org/docs/errors.html#scripterror
file:///Users/garyrob/Source/Durandal%20Projects/HTML%20StarterKit%20(Durandal%202.0)%20Exp%202/lib/require/require.js:32
file:///Users/garyrob/Source/Durandal%20Projects/HTML%20StarterKit%20(Durandal%202.0)%20Exp%202/lib/require/require.js:12 in C
file:///Users/garyrob/Source/Durandal%20Projects/HTML%20StarterKit%20(Durandal%202.0)%20Exp%202/lib/require/require.js:29
If all is well, you should see something like:
Running spec files: specs/mytest.spec
Starting...
Finished
-----------------
1 spec, 0 failures in 0.002s.
And you'll be ready to unit test your new Durandal project!
Posted at 12:19 PM in Durandal | Permalink | Comments (0)
I love Python and have posted a number of Python tips on this blog. And I've been involved in the creation of sizable web sites using Django.
But I've come to feel that for many types of web sites, doing all the rendering on the server and shipping the rendered page to the browser is probably not be the best way to go. Certainly, I'm not the first to come to that conclusion. Google Docs is a phenomenal example of what can be done in a "single page app" (SPA) rendered in the browser. There are many others.
In the course of investigating the various technologies for creating SPA's, one thing I've come to appreciate about that strategy is that you may not need much of a server at all. If you use something like Firebase for your database, you may need nothing more than a means of serving static html and JavaScript files on your server. And then you can use a CDN like CloudFlare to keep you online even if that server is temporarily down. All these factors together can eliminate an enormous amount of overhead in server administration.
Eliminating such overhead seems like it could be very helpful for my goal of creating my next project entirely by myself.
Unfortunately, JavaScript is (IMO) not nearly as nice a language as Python. But if used according to certain patterns, such as described in the famous JavaScript: The Good Parts, a lot of its deficiencies are mitigated, and then it's really not so bad. And most modern JavaScript libraries use the language in that way, so the ecosystem as a whole supports you in that.
Javascript even has Python-like constructions such as list comprehensions. And there are other languages that compile to JavaScript and can be fairly easily integrated into JavaScript projects, such as CoffeeScript -- which itself is Python-like in a number of ways, including semantic indentation.
You can put together tools such as Firebase, Knockout and KnockoutFire to cause changes in your database to automatically and near-instantaneously show up on-screen in your SPA with trivially little code through data-binding. Of course, there are ways of doing that with a framework like Django as well, but data-binding is integral to the way some SPA frameworks operate.
Lately I've been experimenting with Durandal as my SPA framework. It incorporates Knockout, and I'm using KnockoutFire to connect it to a Firebase database. Using a framework like Durandal provides organization for your code, and provides facilities like routing.
So far, I'm very impressed. The main drawback (other than already-noted inherent weaknesses in Javascript itself) is that the documentation and ecosystems of long-existing, high-profile projects like Django are much more evolved. But those things will get better in time, and I'm looking forward to continuing my explorations with Durandal and Firebase.
Posted at 05:04 PM in Python | Permalink | Comments (0)
Recent Comments