<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description> 
 
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-1136525-6']);
  _gaq.push(['_trackPageview']);
 
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga);
  })();
 

My name is Ram Rachum, and I’m a Python software developer based in Israel.

This is my personal blog. I write about technology, Python, programming and a bunch of other things.</description><title>Ram Rachum's blog</title><generator>Tumblr (3.0; @ramrachum)</generator><link>http://blog.ram.rachum.com/</link><item><title>Can someone break my weak home-brew encryption?</title><description>&lt;p&gt;There is a wide consensus among security experts that when choosing an encryption algorithm, it&amp;#8217;s much better to choose a well-known public algorithm rather than a home-brew one. I completely agree with this approach.&lt;/p&gt;
&lt;p&gt;However, I am curious about how easy it is to break a weak, home-brew encryption. When you&amp;#8217;re faced with seemingly-random piece of data, and only told that it is encrypted with no clue as to how the encryption algorithm works, how would you even know where to start at decrypting it?&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;To shed some light on this mystery, I&amp;#8217;ve decided to do a little experiment here on my blog.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve encrypted a piece of information using a home-brew algorithm that I came up with and implemented in a few minutes. I won&amp;#8217;t say much about the algorithm (since the point of this exercise is breaking the algorithm without knowing what it does) but I will say that it&amp;#8217;s the result of several steps, each of which is easily breakable.&lt;/p&gt;
&lt;p&gt;The data is posted below in hex. I&amp;#8217;m very curious to see whether anyone would be successful at decrypting it, and even more curious as to how that was done.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit: &lt;/strong&gt;Just to make it 100% clear: I will &lt;em&gt;never&lt;/em&gt; use something like this for any real encryption need. This is just a puzzle. Never use anything like this to encrypt something even remotely valuable. I do not condone using home-brew encryption algorithms.&lt;/p&gt;
&lt;p&gt;Without further ado, the encrypted data:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;5A9E938B9A9BA0A0D5B9DB42EDD9A0F4
AFAF2780C9D941ED0BE6C8E6DD0DD082
05845029B203AE4A2C4169BFAEB6FDD9
AD461C685A700427C0E440EDE287FD31
7710ACA70B5C059D3B3EA6F58880EB70
4132D80D9F596BB1DC5922D3331BEFED
7D4C9146091F8093109EF21DE22B387C
10ADA38DF91FFBE4305B68B87A563447
AA97364600CC682F2328E8733BBA252E
3C7F93A1805B6593834F647B5BB34356
061B30DBE73734A62426816D49BB185D
C8C6D5D5FF87D5C6FFDD7DE4651FAB43
1F61AD0D4E5E5AD211FEB1D255E6D2BF
906D963C04DCC7BF2914263EF4866BFB
2A99CB704A568C0E23D66215C922F581
8CC31947C57B9F519161C3DBBA19C4AE
F18EE25281999E4C867B69838870811F
307BB3368D884E959EABC97092DD6975
232B8642424B66B67A326F6277231D98
18CBB796693D28BD92BE26956241589B
BC28C98C903D9D6AB976FB55D57B0711
681232107038820F0AA96BD7B11ED190
1897FA07905304EA128355A3BE409379
C2484D40DB45F3A5C535AF736F492B92
63E46B078D3B74092656E3D1BEC2FCC4
46895AAE93FE7CA6D281C84E7AEAEDE4
98F707F9829324AD9C3E7C9A4017B710
CC6DDBB048699E1346AADD538853F037
7B1E139212A1055F331CAF1027ED4955
3F0C2DA2CF2C1D72173B77287893146D
93BEA605DD46B6A3BD77A95F1FF66A56
2B8A2D11804907DAFA6F64DAFB1F81A1
D70187301CE1DA816C11D5E87FBED853
9788333E1426FCF6926236B42C72A6E0
39FBB728C37633A2AD4088D42E13E005
F544D0ACE4ED0AF8EDC82D0F0D5CBE07
93096E3AB1484A2E1622077E458CE9B0
D3BB4E128DB3112706E1E55EC85D41DC
164C8177D296BCCB87FF18295E54F0A7
3A09ED54D9DC0406D97B4E2529BFB3A4
22484AE361AC1970818219409B464A9B
2BD4269F4B5901A389DF30CF7A1D6CF5
8BB39C6BA76B0B0EAEF64F516C15E166
D9BE6A256985601FBD1B2FC7FA0DDFF6
7D4989B264DE32A13B6A9385E0581D90
DB10B0C71FE99C9121B0AEC58303C61B
B4F74F0E35FB4D1AE38836630C368A92
C1C4E5ACBB4B1B390246503A174ACFEA
08674C50BA7347558BC4F967BF154EDE
67ECEABEF97CE930F2539906F8A97B8C
3DEBE7C0AC8EFEDC9AC25AE1FDA9C941
3B16DECC5EDB562CE7AC386AB25D9662
275FE07DC8F59468C3C918FEC8BC6830
A3DE122885D834104F71707458D91917
6105614B1156884C5CD9D1BBCC1F25D2
6EE91F048FB9F9D3B9504B85D25CB317
36A5030C8EFD2EDA90C06FFA0AA44966
1B6259678FADFE8C27820398E867A8BA
45438A4802828ACFA8C0B6A89C32ED60
8286FD1125E99DD4B40AFFC3306E9BB9
242D7F4E026FA448A00D8D3F2E948D09&lt;/code&gt;&lt;/pre&gt;</description><link>http://blog.ram.rachum.com/post/45762666705</link><guid>http://blog.ram.rachum.com/post/45762666705</guid><pubDate>Tue, 19 Mar 2013 18:50:00 +0200</pubDate></item><item><title>Concise explanation of why programming is fun</title><description>&lt;p&gt;I&amp;#8217;ve been asked many times by friends, acquaintances, family members and potential romantic interests the question: &lt;strong&gt;Why do you like programming so much? What&amp;#8217;s so fun about programming?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Naturally, the people who usually ask this are those who do not have a technical background, and that makes it a bit difficult to answer without giving them a crash course in programming.&lt;/p&gt;
&lt;p&gt;Here is my attempt at a concise answer that expresses the joy of computer programming without assuming any kind of technical background.&lt;!-- more --&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Imagine you&amp;#8217;re building a house with brick and mortar. You lay down one brick. You lay another next to it. You lay yet another next to the second one. You keep laying more and more bricks, until you fill up the entire length of the wall. Now you start on the second line. You lay the first brick. You lay the second one. And on and on until you complete the second line. Then the third line and the fourth and the fifth, all the way up to the top. You finished building a wall! Now to build the next wall in your house. You lay down a brick. You lay another next to it&amp;#8230;&lt;/p&gt;
&lt;p&gt;Now, imagine the same exercise, except this time we&amp;#8217;ll do it similar to how a software developer writes a program. You lay down one brick. You lay another one. You keep laying bricks until you finish the line. Achievement unlocked: You now have unlimited brick lines. You lay those brick lines on top of each other until the wall is complete. Achievement unlocked: You now have unlimited walls. You lay down 4 walls next to each other. Achievement unlocked: You now have unlimited houses. You build 100 houses in the same area. Achievement unlocked&amp;#8230; Ad infinitum.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Of course, the metaphor is not perfect, and not all is happy-fun-time in programming-land. But I think this hits pretty close to what gives me the thrill about programming.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/44451925470</link><guid>http://blog.ram.rachum.com/post/44451925470</guid><pubDate>Sun, 03 Mar 2013 15:39:00 +0200</pubDate></item><item><title>On changing the world</title><description>&lt;p&gt;I’d like to share a story from my high-school days with you, and then a few thoughts that followed from it.&lt;/p&gt;
&lt;h2&gt;Tuning the telescope&lt;/h2&gt;
&lt;p&gt;When I was in high-school, we had a fantastic teacher of Physics named Bernd. I loved that guy. Bernd would routinely organize extra-curricular activities to learn about science outside of the classroom. One evening Bernd took the entire class to the rooftop of the school building to use the school telescope. (It was a boarding school so it was legitimate for there to be school activities in the evening.)&lt;/p&gt;
&lt;!-- more --&gt;
&lt;p&gt;&lt;img align="right" alt="image" src="http://media.tumblr.com/3567980f9ddd9280fd97daf37be28e31/tumblr_inline_mhk00x5vc01qz4rgp.png" title="Photo by Ryan Wick, http://www.flickr.com/photos/ryanwick/3461850112/"/&gt;&lt;/p&gt;
&lt;p&gt;He took us to use the telescope to look at the moon. (There might have been some kind of notable astronomical phenomenon happening at that time, I forget.) Since it was a wealthy private school, we had a high-end telescope with a myriad of dials to fine-tune the focus, zoom, and God knows what else. Bernd tuned the telescope carefully, and then we all lined up to look at the moon through the eyepiece. There were a few dozen kids on one telescope so we all had to wait for our turn to have 10 seconds to look at the moon before the next student would take his turn.&lt;/p&gt;
&lt;p&gt;The funny thing, what I remember the most from the story is not seeing the moon, but what Bernd said before he let us use the telescope. This was not Bernd’s first time taking a class up to use the telescope, and experience taught him to give the following warning: “When you get your turn with the telescope, please &lt;em&gt;do not&lt;/em&gt; touch the dials. There’s no need to fiddle with them. I already fine-tuned it &lt;em&gt;perfectly.&lt;/em&gt; Every change you make will only worsen the picture and the students after you will suffer for it. I’m sorry that I have to give you this warning but for some reason people always feel the need to fiddle with the dials themselves regardless of the fact that the picture is perfect.”&lt;/p&gt;
&lt;p&gt;That warning made me think. I think that there’s a lesson to be learned here that’s bigger than dials and telescopes.&lt;/p&gt;
&lt;h2&gt;Making a difference&lt;/h2&gt;
&lt;p&gt;People have an urge to change and to control, even if the change that they’re making is for the worse. They don’t care. The urge to feel that their actions have an impact on the world around them is bigger than the desire for the world to be in a good state. Not unlike a teenager spray-painting a tasteless piece of graffiti on a wall, people want to leave their mark, even if the world ends up uglier because of it.&lt;/p&gt;
&lt;p&gt;&lt;img align="left" alt="image" src="http://media.tumblr.com/2a4a0ece10c7d2d58dda973a38d4658e/tumblr_inline_mhk26uNdUe1qz4rgp.png" title="Picture by VigBrastle, http://vigbrastle.deviantart.com/art/fuk-yea-graffiti-truck-173398990"/&gt;&lt;/p&gt;
&lt;p&gt;It makes me think about all those people out there trying to change the world and make a difference. I live in a big, fashionable city in a first-world country, surrounded by people who belong to the wealthiest 10% of the world population. It seems that you can’t find a single person who doesn’t want to change the world and make a difference in some way or another. Everybody has their own pet causes. One guy wants to save the environment, one girl wants to stop government corruption, another guy wants everyone in the world to learn how to meditate and achieve enlightenment. Then there’s world peace, universal healthcare, helping people in third world countries…&lt;/p&gt;
&lt;p&gt;Given that practically every person I meet wants to make the world a better place, and those are relatively wealthy people by world standards, you kind of have to wonder why the world didn’t become that better place already. In fact there seem to be more people who have a strong opinion on how the world should work then there are people who know how to live their own lives happily and be content with themselves.&lt;/p&gt;
&lt;p&gt;Is there somewhere out there an evil, chubby, mustache-wielding cigar-smoking businessman who is sociopathically apathetic to all the bad things in the world around us and who cunningly sabotages our efforts to fix the world? I don’t think so. It’s all us.&lt;/p&gt;
&lt;p&gt;I used to want to change the world too. I cared about education. I wanted to make a worldwide revolution in education, in effect doing something similar to what Khan Academy is currently doing, except it was back around 2006, when Khan Academy was just Salman Khan posting video lectures for his cousin. My partners and I made &lt;a href="http://bintos.com"&gt;a nice pilot in Israel&lt;/a&gt; but failed to get funding and the project was abandoned.&lt;/p&gt;
&lt;p&gt;Now I don’t care anymore. I don’t want to change the world or make a difference anymore. I still like helping people, but only the people who are close to me. I care intensely about my own life and the lives of my loved ones, but I don’t try to have an impact on the world outside of that tiny circle.&lt;/p&gt;
&lt;p&gt;Now, this is the part of the essay that I’m not sure how to write. I know that by this point, many readers are going to be angry with me for suggesting that people who try to make the world a better place are in fact a selfish bunch who are just looking to get their own personal satisfaction. I can feel the angry comments coming my way.&lt;/p&gt;
&lt;p&gt;But yes, that’s indeed what I’m saying: Almost all the people who are trying to change the world are in it for their own satisfaction, and they don’t care if the world ends up a worse place.&lt;/p&gt;
&lt;p&gt;That one guy who meticulously collects plastic bottles to recycle to help the environment, bought a smartphone that was manufactured by children working in terrible conditions in a third-world country. That one guy who wants everyone to meditate and become enlightened went to a strip club and fed money into an organization that degrades women and turns them into slaves. That one girl who wants to stop government corruption has her money in a savings account that’s invested in companies that abuse the environment to make a profit.&lt;/p&gt;
&lt;p&gt;People help the world in one way and then abuse it in 99 different ways. In fact the western man is a genius; he managed to rape the world while still maintaining that he’s the one trying to save it.&lt;/p&gt;
&lt;h2&gt;What’s a perfect world?&lt;/h2&gt;
&lt;p&gt;I know that some people are going to say, “Your story about the telescope is not a good metaphor, because while the telescope in the story was tuned perfectly, our world is not even remotely perfect.” To which I answer, why not? Why don’t you think our world is perfect? Because of all the suffering and ignorance around us?&lt;/p&gt;
&lt;p&gt;What would a perfect world be then? If a genie offered you to change the world exactly as you want it to the smallest detail, what kind of world would you ask him to create?&lt;/p&gt;
&lt;p&gt;&lt;img align="right" alt="image" src="http://media.tumblr.com/709ce8abfc16925cafe32c6fb8d0f42e/tumblr_inline_mhk2gqWooX1qz4rgp.jpg" title="Picture by V Smoothe, http://www.flickr.com/photos/vsmoothe/2081906537/"/&gt; Perhaps a world with no suffering at all? A world in which people of all countries can make a decent living, get free education, be always kind and supportive to one another, and never hurt or be hurt by another person? Did you ever watch a movie in which nothing bad ever happens? I never have. It’s notable that even in cinema, where humans can literally create whichever fantastic world they want, nobody wants to see a world in which there’s no suffering. Even movies intended for little children always have the character go through some kind of conflict or danger. The only thing closest to a movie with no suffering that I can think of is Teletubbies, and even that one has &lt;a href="http://en.wikipedia.org/wiki/List_of_Teletubbies_episodes_and_videos"&gt;episodes&lt;/a&gt; in which the characters have to deal with some kind of mishap.&lt;/p&gt;
&lt;p&gt;Without suffering there’s no point to life. Without a possibility of failure there is no excitement.&lt;/p&gt;
&lt;p&gt;Then you might say, “well, we don’t want a world where there is absolutely zero suffering. We just want there to be less suffering than there is today.”&lt;/p&gt;
&lt;p&gt;So clearly, there is such a thing as too much suffering. And as I elaborated above, there is such a thing as &lt;em&gt;not enough&lt;/em&gt; suffering. So that implies that somewhere in between there’s an optimal amount of suffering that’s &lt;em&gt;just right&lt;/em&gt;. Why do you think that the current amount of suffering in the world is higher than the optimal amount? The current amount of suffering in the world is lower than it’s ever been in the history of civilization. Why do you think that the optimal level is still lower than this? Are you such an expert on the workings of our world that you think that you know what the optimal amount of suffering is? Sounds like a monumentally arrogant thought to me.&lt;/p&gt;
&lt;p&gt;So the argument that the world isn’t perfect is invalid.&lt;/p&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;What I take away from this is: Don’t try to change the world. Live your life. Be happy. If you’re reading this you’re probably one of the lucky few who are well-off enough to have an Internet connection, not to mention the fact that you can read, which already makes you more privileged than 85% of people on the planet. Have fun with the precious few decades that you have to live.&lt;/p&gt;
&lt;p&gt;If you enjoy being an activist, if it’s fun and satisfying for you, that’s great, keep it up then. But don’t try to pretend you’re doing it for the world. You’re doing it &lt;em&gt;for yourself&lt;/em&gt;, and &lt;em&gt;regardless&lt;/em&gt; of whether it’s making the world better or not. It’s just how you like to live.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/42662606206</link><guid>http://blog.ram.rachum.com/post/42662606206</guid><pubDate>Sat, 09 Feb 2013 15:53:00 +0200</pubDate></item><item><title>First phishing attempt that targets Israeli bank</title><description>&lt;p&gt;Over the years I&amp;#8217;ve gotten thousands of phishing attempts to my mailbox, but now for the first time I get one that&amp;#8217;s masquerading as an Israeli bank, Bank Leumi:&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/e147cbb2f7263b88cabe1ab12fd2356e/tumblr_inline_mhuv62uFbl1qz4rgp.png"/&gt;&lt;/p&gt;

&lt;p&gt;The copy looks surprisingly good. To those of you who don&amp;#8217;t read Hebrew, it&amp;#8217;s pretty standard stuff: Due to some unspecified security problems, we need you to give us all of your secret banking information, kthxbye.&lt;/p&gt;
&lt;p&gt;But of course, if the lack of punctuation marks didn&amp;#8217;t give this away as a phishing attempt, the link to http://adf.ly/IjI32 surely does.&lt;/p&gt;
&lt;p&gt;That webpage, intended to collect the victim&amp;#8217;s personal banking information, also looks surprisingly legit:&lt;/p&gt;
&lt;p&gt;&lt;img alt="image" src="http://media.tumblr.com/561103400a2181ae8559515dd06ff695/tumblr_inline_mhuvgqlPmO1qz4rgp.png"/&gt;&lt;/p&gt;
&lt;p&gt;Of course, the domain mpibullion.com doesn&amp;#8217;t belong to Bank Leumi, so there&amp;#8217;s no doubt that this is a scam. &lt;span&gt;The link to Verisign simply links to the certificate for Leumi&amp;#8217;s actual website.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;All in all, a well executed scam.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/42505722161</link><guid>http://blog.ram.rachum.com/post/42505722161</guid><pubDate>Thu, 07 Feb 2013 17:11:00 +0200</pubDate></item><item><title>Phone companies: Please send me my voice messages via email</title><description>&lt;p&gt;I really hate checking my voice mail. It&amp;#8217;s fucking retarded. I get a text that someone left me a voice message, and then I have to call the special voice mail number, navigate the painfully slow menu, until I finally get to hear the guy&amp;#8217;s message, which is most often to the tune of &amp;#8220;Uh, hi&amp;#8230; Uh&amp;#8230; I guess&amp;#8230; You&amp;#8217;re not there. It&amp;#8217;s Jeff&amp;#8230; I wanted to talk to you about something. It&amp;#8217;s about&amp;#8230; Uh&amp;#8230; Never mind, just call me back.&amp;#8221; &lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what I want: I want to have a system where every time someone leaves me a voice message, I automatically get an email with an audio file of the message, the silent parts automatically removed from it, and the whole thing playing x1.2 faster than normal speed. (Speech recognition is an option but only as an extra because it&amp;#8217;s not reliable.)&lt;/p&gt;
&lt;p&gt;Asides from making the message-listening experience faster, and not making me call the special number, it&amp;#8217;ll have the advantage that the voice messages will be easier to manage. One thing is read/unread: Email programs already have an excellent concept of read-vs-unread messages, which works much better than the phone companies&amp;#8217; system. Also, there&amp;#8217;s metadata like the time the call was made and the caller, which in the current system are read to you &lt;em&gt;before&lt;/em&gt; hearing the message, which is really frustrating. These belong as text in the email message, where they do not interfere with listening to the message.&lt;/p&gt;
&lt;p&gt;Now, of course, I&amp;#8217;m sure that some phone companies (like Google Voice maybe?) have implemented some of this. The problem is that (a) switching providers for something like that is annoying because the provider you&amp;#8217;re switching to may have its own host of problems and (b) I live in Israel and most likely I wouldn&amp;#8217;t be able to find an Israeli phone provider that does this.&lt;/p&gt;
&lt;p&gt;Maybe if a startup would create a product that&amp;#8217;s able to interface with any provider&amp;#8217;s voice message system, and then email you the voice files&amp;#8230; The problem though is that at any moment the phone companies could implement that feature and leave your startup dead in the water.&lt;/p&gt;
&lt;p&gt;So my only hope seems to be waiting for the phone companies to pull their heads out of their asses and implement this feature themselves.&lt;/p&gt;
&lt;p&gt;Goddamnit, I really want this feature&amp;#8230;&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/35130163346</link><guid>http://blog.ram.rachum.com/post/35130163346</guid><pubDate>Tue, 06 Nov 2012 17:55:00 +0200</pubDate></item><item><title>Cute riddle: Four kids holding one toy balloon</title><description>&lt;p&gt;This morning I was lying in bed for a while before getting up, and an idea for a cute logical riddle came to me.&lt;/p&gt;
&lt;p&gt;Four kids are standing in an amusement park holding a helium toy balloon. Each kid holds his own end of a thread, but there&amp;#8217;s only one single toy balloon for the entire group. If any of the four kids let go of their own thread, the toy balloon will fly up to the sky and be lost, &lt;em&gt;even if the remaining three kids keep holding to their respective threads.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;How are the threads arranged? Post your answers in the comments!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Many people solved the riddle in different ways that I didn&amp;#8217;t think of in the comments. Congrats! Now your next task: Generalize the problem to N kids and M balloons, find the function that gives the number of threads needed for each combination, and then send a link to an interactive 3D plot of it :)&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/34561608024</link><guid>http://blog.ram.rachum.com/post/34561608024</guid><pubDate>Mon, 29 Oct 2012 14:57:00 +0200</pubDate></item><item><title>Developers: When using Frecency, please consider the context</title><description>&lt;p&gt;Nowadays there are many applications that use the wonderful concept of Frecency.&lt;/p&gt;
&lt;p&gt;&amp;#8220;Frecency&amp;#8221; is a combination of &amp;#8220;frequency&amp;#8221; and &amp;#8220;recency&amp;#8221;. For example, say that I have a dear friend named Bob Jones to whom I write emails every day. I may have many Bobs in my address book, but when I start a new message in GMail and start typing &amp;#8220;Bob&amp;#8221;, GMail is smart enough to offer me Bob Jones as the first choice, because that&amp;#8217;s the Bob to whom I&amp;#8217;ve written the most often to recently.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;This is a really awesome feature! It saves a lot of time sifting between non-popular choices. I &amp;lt;3 Frecency.&lt;/p&gt;
&lt;p&gt;Many applications use this concept of frecency. When you start typing anything into Chrome&amp;#8217;s Omnibar, it uses frecency to guess which website you want to visit. I use a launcher for Windows called &lt;a href="http://www.launchy.net/"&gt;Launchy&lt;/a&gt;. When you press Start-Space, you can start typing the name of the program that you want to launch, and Launchy will usually guess that program after 1-3 keystrokes. That&amp;#8217;s a really fast and convenient feature, powered by frecency.&lt;/p&gt;
&lt;h2&gt;But&amp;#8230; There&amp;#8217;s room for improvement&lt;/h2&gt;
&lt;p&gt;There&amp;#8217;s one thing about most frecency-using programs that I find annoying. Let me explain it with an example.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve already mentioned my good friend Bob Jones to whom I write emails every day. I also have a business partner called John Schiller to whom I write frequently, though less than to Bob. Sometimes I mean to write an email to John, so I start typing &lt;strong&gt;jo&lt;/strong&gt; in the address field, but then instead of getting John Schiller as the first suggestion, I get Bob Jones.&lt;/p&gt;
&lt;p&gt;GMail is offering me Bob Jones because I write to Bob Jones more frequently than to John Schiller, and &lt;strong&gt;jo&lt;/strong&gt; happens to be the first 2 letters in Bob Jones&amp;#8217; name.&lt;/p&gt;
&lt;p&gt;But, if GMail had a better algorithm, than it would realize that I &lt;em&gt;never&lt;/em&gt; start an email to Bob Jones by typing his last name. Ever. Therefore if I&amp;#8217;m writing &lt;strong&gt;jo&lt;/strong&gt;, the odds are slim that I&amp;#8217;m writing an email to Bob.&lt;/p&gt;
&lt;h2&gt;How to fix it?&lt;/h2&gt;
&lt;p&gt;The way to fix this problem is to always check how certain selections are made. If I always start an email to Bob Jones by typing Bob, don&amp;#8217;t offer that selection in a high position when I start typing Jones. Every time I make a selection, save the original piece of text that I typed in to make that selection, and then consult that data next time the program is trying to guess my selection.&lt;/p&gt;
&lt;p&gt;I have a similar problem with Launchy. Sometimes I want to launch Rosetta Stone, so I start typing &lt;strong&gt;ro&lt;/strong&gt;, but then Launch offers to launch Ch&lt;strong&gt;ro&lt;/strong&gt;me, because I launch Chrome much more often than Rosetta Stone, and &amp;#8220;Chrome&amp;#8221; has &amp;#8220;ro&amp;#8221; in it. Again, a mistake. I &lt;em&gt;never&lt;/em&gt; type &lt;strong&gt;ro&lt;/strong&gt; when I&amp;#8217;m launching Chrome. &lt;em&gt;Never.&lt;/em&gt; So the smart thing for Launchy to do is to notice that so it could guess better at what I mean.&lt;/p&gt;
&lt;p&gt;I hope that developers writing frecency algorithms would listen to this advice so we could all have smarter programs!&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/33095461928</link><guid>http://blog.ram.rachum.com/post/33095461928</guid><pubDate>Sun, 07 Oct 2012 19:45:00 +0200</pubDate></item><item><title>AeroFS is x87 faster than Dropbox in LAN syncing [Video]</title><description>&lt;p&gt;I&amp;#8217;m a long-time paying user of &lt;a href="http://www.dropbox.com/"&gt;Dropbox&lt;/a&gt;, and for a few months now I&amp;#8217;m also a beta user of the competing &lt;a href="http://www.aerofs.com/"&gt;AeroFS&lt;/a&gt; service. Both services are excellent and revolutionary. But I&amp;#8217;m frustrated with how slow Dropbox&amp;#8217;s LAN sync is. When I put a file on my Dropbox on my desktop computer, I expect it to appear in my Dropbox on my laptop very quickly. But Dropbox takes a really long time to transfer the file, probably because it&amp;#8217;s trying to first transfer it to the Dropbox servers instead of directly to my laptop. AeroFS, on the other hand, does it much faster, probably because the transfer is done directly.&lt;/p&gt;
&lt;p&gt;In this video I&amp;#8217;ve measured and compared the time it takes Dropbox and AeroFS to transfer an 8.5 Megabyte file from my desktop to my laptop. Dropbox took &lt;strong&gt;12:28&lt;/strong&gt; minutes, while AeroFS took only &lt;strong&gt;00:08&lt;/strong&gt; seconds. &lt;em&gt;&lt;strong&gt;AeroFS is x87 faster than Dropbox in moving a file over the LAN.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;&lt;!-- more --&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Watch the video (and pardon my accent):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=SjY0DaT-snE"&gt;&lt;img src="http://media.tumblr.com/tumblr_mbiqnjf0ZU1qzywlj.png"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Why am I posting this?&lt;/h2&gt;
&lt;p&gt;Dropbox is one of the best cloud services out there, and I really hope that they understand just how frustrating their LAN Sync feature is. I&amp;#8217;m sure that they can figure out a way to do LAN transfers as fast as AeroFS does them. (Or at least not x87 slower!)&lt;/p&gt;
&lt;p&gt;I am not affiliated with AeroFS in any way&amp;#8212; I&amp;#8217;m just a fan of their service, and of course, there are many aspects in which Dropbox is better than AeroFS.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/33073905775</link><guid>http://blog.ram.rachum.com/post/33073905775</guid><pubDate>Sun, 07 Oct 2012 12:35:00 +0200</pubDate></item><item><title>GarlicSim is dead, long live Python Toolbox!</title><description>&lt;p&gt;I&amp;#8217;ve got some bad news and I&amp;#8217;ve got some good news.&lt;/p&gt;
&lt;p&gt;The bad news:&lt;/p&gt;
&lt;h2&gt;GarlicSim is dead!&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;ve tried, and I&amp;#8217;ve failed.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;I wanted to make an awesome simulation framework. I had amazing ideas that I&amp;#8217;ve never seen before in any other piece of simulation software. In the 2.5 years in which I&amp;#8217;ve worked my ass off on GarlicSim I managed to make some of these ideas into working software. I was so proud of them&amp;#8212; Especially the tree-related features, that allowed you to make a change in the world, see how that change affects the future, and then come back to the parallel timeline in which the change never happened. Those kinds of features have great research applications, but beyond that they are just so damn cool and it was very satisfying to work on them and to play with them.&lt;/p&gt;
&lt;p&gt;But&amp;#8230;&lt;/p&gt;
&lt;p&gt;GarlicSim is an open-source project. And I am a human being who requires such things as food, water and a roof above my head to survive. Therefore I need to spend my time working a job that pays me money, since working on GarlicSim, as satisfying as it is, does not pay me anything.&lt;/p&gt;
&lt;p&gt;I spend most of time working on the paying job, doing Python web development, and then there&amp;#8217;s this thing called &amp;#8220;personal life&amp;#8221; that takes up what&amp;#8217;s left of my time :)&lt;/p&gt;
&lt;p&gt;I have to prioritize the things that I spend my time on, and I find that I care more about my job, my financial security and my personal life than the GarlicSim project.&lt;/p&gt;
&lt;p&gt;I have therefore decided: &lt;strong&gt;I&amp;#8217;m abandoning the GarlicSim project.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Unlike most open-source Python projects, GarlicSim is not a tool but a framework, and a big one at that. A big framework like that is something that is either executed with a lot of attention to detail, or better not executed at all. Nobody wants to use Big Framework version 0.6.3 alpha. A framework needs to be stable and feature-rich before people start migrating to it. And I don&amp;#8217;t want to put in the huge amount of time needed to get GarlicSim to that stage, so there is no point in me spending any time on it at all.&lt;/p&gt;
&lt;p&gt;That is why I decided to abandon GarlicSim.&lt;/p&gt;
&lt;p&gt;The GarlicSim code will still be available online under an open source license for whoever finds it useful (or wishes to pick up the torch), but it&amp;#8217;ll be marked as abandoned, as will the official website.&lt;/p&gt;
&lt;p&gt;The GarlicSim blog, which has long ago served more like my own personal blog, has been appropriately renamed to Ram Rachum&amp;#8217;s blog and now lives at &lt;a href="http://blog.ram.rachum.com"&gt;&lt;a href="http://blog.ram.rachum.com"&gt;http://blog.ram.rachum.com&lt;/a&gt;.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now it&amp;#8217;s time for the good news.&lt;/p&gt;
&lt;h2&gt;Long live Python Toolbox!&lt;/h2&gt;
&lt;p&gt;Out of the ruins of GarlicSim, a fresh new open source project was born. An open source project that, while less ambitious, has proven to be very helpful in my job as a Django web developer, and moreover I&amp;#8217;m having a lot of fun hacking on it. I&amp;#8217;m hoping that it will be as useful to other people as it was to me.&lt;/p&gt;
&lt;p&gt;The project is called the &lt;a href="http://pypi.python.org/pypi/python_toolbox/"&gt;Python Toolbox&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What is the Python Toolbox?&lt;/p&gt;
&lt;p&gt;When developing GarlicSim, I often had a need for various general-purpose Python tools. One example, out of many, was the &lt;code&gt;cache&lt;/code&gt; decorator. One of the things I needed while developing GarlicSim was a &lt;code&gt;cache&lt;/code&gt; decorator that you can put in front of a function to have its results cached. So I did what every programmer does: I Googled around for an open-source caching package that I could download from PyPI and get it over with. I imagined there would be a nice implementation available, since a &lt;code&gt;cache&lt;/code&gt; decorator, or &lt;code&gt;memoize&lt;/code&gt; as it&amp;#8217;s sometimes called, is so common that it&amp;#8217;s often used as a case study when talking about decorators.&lt;/p&gt;
&lt;p&gt;But&amp;#8230; I couldn&amp;#8217;t find one that I really liked! I&amp;#8217;m very picky when it comes to the tools I use. For example, I remember I couldn&amp;#8217;t find any caching module whose &lt;code&gt;cache&lt;/code&gt; decorator actually understands the arguments passed to functions, and is able to understand that &lt;code&gt;f(5)&lt;/code&gt; is the same as &lt;code&gt;f(x=5)&lt;/code&gt; and thus they should be cached together.&lt;/p&gt;
&lt;p&gt;So I wrote my own, and it became known as the &lt;code&gt;garlicsim.general_misc.caching&lt;/code&gt; module. It was included with GarlicSim, despite the fact that it had nothing to do with simulations. It was there just because I needed that tool for GarlicSim.&lt;/p&gt;
&lt;p&gt;And then I had more needs for more general-purpose tools. And again I was surprised with how difficult it is to find good general-purpose Python tools. So then came &lt;code&gt;queue_tools&lt;/code&gt;, and &lt;code&gt;binary_search&lt;/code&gt;, and &lt;code&gt;context_managers&lt;/code&gt; and &lt;code&gt;cute_iter_tools&lt;/code&gt;&amp;#8230; All of them general-purpose Python tools that I&amp;#8217;ve written and that I am very proud of, but which have nothing to do with computer simulations.&lt;/p&gt;
&lt;p&gt;The Python Toolbox is this entire collection of tools, taken out of GarlicSim. It contains about 50 such modules, not counting the sub-modules that some of these modules have.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve made the Python Toolbox 0.1 release today! &lt;a href="http://pypi.python.org/pypi/python_toolbox/"&gt;Download it on PyPI&lt;/a&gt;, &lt;a href="https://github.com/cool-RR/python_toolbox"&gt;fork it on GitHub&lt;/a&gt;, use it in your Python project, and tell me what you think!&lt;/p&gt;
&lt;p&gt;Have fun!&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/24682447796</link><guid>http://blog.ram.rachum.com/post/24682447796</guid><pubDate>Fri, 08 Jun 2012 18:42:00 +0300</pubDate></item><item><title>Silly Python riddle</title><description>&lt;p&gt;Here&amp;#8217;s a silly Python riddle for you.&lt;/p&gt;
&lt;p&gt;Today I opened up a Python 2.7 shell, and ran two commands in it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; f = lambda: g(&lt;strong&gt;???&lt;/strong&gt;)
&amp;gt;&amp;gt;&amp;gt; f()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt; &lt;/code&gt;&lt;/p&gt;
&lt;p&gt;(Note that these are the only commands that I ran. You&amp;#8217;re not allowed to run any other commands before them.)&lt;/p&gt;
&lt;p&gt;The riddle: What&amp;#8217;s the &lt;em&gt;shortest&lt;/em&gt; thing you can put instead of &lt;strong&gt;???&lt;/strong&gt; so my second command would not raise an exception?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit:&lt;/strong&gt; I just posted it and people are already coming up with creative solutions! So now it&amp;#8217;s time to say: The winning solution is &lt;strong&gt;7 characters&lt;/strong&gt; long. Try to match that!&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; An anonymous commenter on Hacker News &lt;a href="http://news.ycombinator.com/item?id=3373280"&gt;solved it&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;The solution:&lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;(Scroll down&amp;#8230;) &lt;/p&gt;
&lt;p&gt;The solution:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; f = lambda: g(&lt;strong&gt;(yield)&lt;/strong&gt;)
&amp;gt;&amp;gt;&amp;gt; f()&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Funny, isn&amp;#8217;t it? I was surprised to see that the &lt;code&gt;yield&lt;/code&gt; keyword can be used in a lambda function. &lt;/p&gt;
&lt;p&gt;So when you type &lt;code&gt;f()&lt;/code&gt;, it just returns a generator. If you&amp;#8217;ll try to exhaust it, an exception will be raised because &lt;code&gt;g&lt;/code&gt; doesn&amp;#8217;t exist, but that&amp;#8217;s a new line :)&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s funny that in this case, Python seems to throw away the value of the lambda function! As we know, the &lt;code&gt;yield&lt;/code&gt; keyword actually forms an expression whose value is &lt;code&gt;None&lt;/code&gt;, unless you used the generator&amp;#8217;s &lt;code&gt;.send&lt;/code&gt; instead of &lt;code&gt;.next&lt;/code&gt;. So you could also use &lt;code&gt;.send&lt;/code&gt; to send in whatever value you want into the lambda function, and Python will just throw it away. Unless I&amp;#8217;m missing something.&lt;/p&gt;
&lt;p&gt;So that&amp;#8217;s the only case I can think of where Python completely throws away the value of a lambda function.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/14506657016</link><guid>http://blog.ram.rachum.com/post/14506657016</guid><pubDate>Tue, 20 Dec 2011 14:16:00 +0200</pubDate></item><item><title>The `coverage` module celebrates 10 years today!</title><description>&lt;p&gt;Today, December 4&lt;sup&gt;th&lt;/sup&gt; 2011, marks the tenth birthday of &lt;a href="http://pypi.python.org/pypi/coverage"&gt;the excellent &lt;code&gt;coverage&lt;/code&gt; module&lt;/a&gt;! Here is the &lt;a href="https://bitbucket.org/ned/coveragepy/src/740b68eb8fc5/CHANGES.txt#cl-580"&gt;changelog entry&lt;/a&gt; showing it was created exactly ten years ago, on December 4&lt;sup&gt;th&lt;/sup&gt;, 2001 by &lt;a href="http://garethrees.org/"&gt;Gareth Rees&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;coverage&lt;/code&gt; module is one of the most sturdy and reliable pillars of my development toolset. It&amp;#8217;s a hallmark of a great tool that you never have to spend too much with it&amp;#8212; When I want to check the statement-coverage of my tests, I just use &lt;code&gt;coverage&lt;/code&gt; (invoked via its Nose plugin), it just works, and then I can go back to writing my tests and ensuring they cover a big part of my code. You don&amp;#8217;t have to spend too much time with it for the simple reason that it very rarely breaks&amp;#8212; Which is not a trivial accomplishment for a tool that acts on every, single, line of code in your project.&lt;/p&gt;
&lt;p&gt;Kudos to &lt;a href="http://nedbatchelder.com/"&gt;Ned Batchelder&lt;/a&gt; for his excellent maintenance of the &lt;code&gt;coverage&lt;/code&gt; module! I&amp;#8217;m a relatively new user of &lt;code&gt;coverage&lt;/code&gt;, having used it only for about 2 years, if I remember correctly. So long-time users of &lt;code&gt;coverage&lt;/code&gt; may have a bigger perspective on this module than I do. But in the relatively short time that I&amp;#8217;ve been using it, Ned has been an exemplary maintainer, and the few tickets that I created on the bug tracker received his attention. Ned also made sure that &lt;code&gt;coverage&lt;/code&gt; supported Python 3.x &lt;em&gt;before it was cool&lt;/em&gt;, and on every release he takes the time to create Windows binaries of &lt;code&gt;coverage&lt;/code&gt; to help Windows users avoid having to compile it themselves.&lt;/p&gt;
&lt;p&gt;If every maintainer was as dedicated as Ned, the Python community would be in a better place today, and we would have probably already seen Python 3.x going into mainstream.&lt;/p&gt;
&lt;p&gt;Thank you, Gareth and Ned, for this wonderful module!&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/13739362516</link><guid>http://blog.ram.rachum.com/post/13739362516</guid><pubDate>Sun, 04 Dec 2011 21:28:00 +0200</pubDate></item><item><title>Deadline for GarlicSim 0.7 cancelled</title><description>&lt;p&gt;Just when I finished one contract job and thought that I finally had time for some serious work on GarlicSim, I got a new contract job.&lt;/p&gt;
&lt;p&gt;Since the deadline for the GarlicSim 0.7 release has been postponed so many times, I&amp;#8217;m just going to cancel the deadline altogether. Sorry for the disappointment.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m angry at myself for not making the deadlines, but on the other hand I&amp;#8217;m happy about having a bunch of contract jobs. This will allow me to spend a lot of time on GarlicSim later on. My contract jobs have already allowed me to do a bunch of upgrades and improvements of my work environment (from hardware upgrades, through time-saving AutoHotKey scripts, to ergonomic upgrades), and that really helps me be more productive, both in my contract work and my open-source work.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/11269744385</link><guid>http://blog.ram.rachum.com/post/11269744385</guid><pubDate>Mon, 10 Oct 2011 13:30:35 +0200</pubDate></item><item><title>GUIs kick CLIs' asses</title><description>&lt;p&gt;Or, &lt;strong&gt;&amp;#8220;Hey programmers, did you know you can use a GUI with the keyboard?&amp;#8221;&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;This post is &lt;strong&gt;part 1&lt;/strong&gt; of the &lt;strong&gt;Unpopular Opinions&lt;/strong&gt; series. In this series I will present a few opinions of mine that go against what most other software developers think. If you disagree any of these posts, you know they&amp;#8217;re working. Please stay civil in the comments&amp;#8212; Criticizing my opinions is encouraged, as long as it&amp;#8217;s done in a &lt;a href="http://www.paulgraham.com/disagree.html"&gt;constructive and respectful manner&lt;/a&gt;.&lt;/blockquote&gt;
&lt;p&gt;One of the big things that have been bugging me ever since I became a professional developer is that &lt;strong&gt;most developers shun GUIs.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As a developer, I often get to hang out with other developers and see their tools and work processes— Sometimes in person, and sometimes online. I quickly found that almost all of them hate GUIs (&lt;a href="http://en.wikipedia.org/wiki/Graphical_user_interface"&gt;Graphical User Interfaces&lt;/a&gt;, i.e. visual programs with windows, buttons, menus, dialogs, etc.) Most programmers much prefer working with CLIs (&lt;a href="http://en.wikipedia.org/wiki/Command-line_interface"&gt;Command Line Interfaces&lt;/a&gt;, i.e. a textual shell.)&lt;a href="#note1"&gt;[1]&lt;!-- more --&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img align="right" src="http://ram.rachum.com/images/complex_gui.png"/&gt;I found this baffling. Why would anyone enjoy working in front of a command-line interface, where you can&amp;#8217;t see shit and have to remember a ton of commands and flags by heart? Surely the programmer community is intelligent and passionate enough to pick the very best possible tools, so perhaps they have good reasons for preferring CLIs?&lt;/p&gt;
&lt;p&gt;After thinking about it for a while, my conclusion is that there are two main reasons that most programmers prefer CLIs to GUIs:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;
&lt;p&gt;Most GUIs suck. And when it comes to proper keyboard support, most GUIs suck &lt;em&gt;terribly&lt;/em&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Most programmers are ignorant about good GUIs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;But before we get to that:&lt;/p&gt;
&lt;h2&gt;Let&amp;#8217;s compare GUIs and CLIs&lt;/h2&gt;
&lt;p&gt;There are a bunch of parameters that we can measure GUIs against CLIs on. The two parameters that are the most important for heavy computer users are &lt;strong&gt;Visibility&lt;/strong&gt; and &lt;strong&gt;Speed&lt;/strong&gt;.&lt;a href="#note2"&gt;[2]&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Visibility&lt;/h2&gt;
&lt;p&gt;The first parameter we&amp;#8217;re going to look at is &lt;strong&gt;visibility&lt;/strong&gt;. This is the 800-pound gorilla that most programmers seem to ignore.&lt;/p&gt;
&lt;p&gt;For the sake of an example, let&amp;#8217;s take a simple everyday task: Say you want to copy a bunch of files from one folder on your computer to another.&lt;/p&gt;
&lt;p&gt;If you were to do this with a CLI, you would do something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; cd ~/source_dir cp file_1 file_2 file_3 ~/target_dir&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the other side of the ring, if you were to do this with a GUI, you would navigate to the source folder in your explorer/nautilus/whatever, select the three files, copy them to the clipboard, navigate to the the target folder and hit paste.&lt;/p&gt;
&lt;p&gt;&lt;img align="right" alt="Alex E. Proimos on flickr.com" height="266" src="http://ram.rachum.com/images/horse_blinders.png" title="Alex E. Proimos on flickr.com" width="400"/&gt;When you take the GUI route to copying files, you get to see a lot of stuff. Some of it may not be relevant to your current needs, but some of it might be. You will get to see all the other files in the source and target folders. You will get to see how much disk space all these files take. You will get to see any sibling folders that the source/target folder might have. You will get to see the file size of each of the files you&amp;#8217;re copying.&lt;/p&gt;
&lt;p&gt;When you take the CLI route to copying files, you&amp;#8217;re not seeing anything except the next shell prompt waiting for your next command. Sure, if you got everything right, you wouldn&amp;#8217;t really &lt;em&gt;need&lt;/em&gt; to see anything, because your 3 files just got copied and you completed the task. So what do you care about seeing all the data you would have seen in the GUI route?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Because keeping your eyes open is important.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Maybe when looking around the source folder, you&amp;#8217;d see that there was another file that you forgot to copy? Maybe you&amp;#8217;ll see that for some reason the target folder has more files that it should, which might indicate a problem with your system? Maybe you&amp;#8217;ll see that some impolite package-management tool that you previously ran left a bunch of &lt;code&gt;build&lt;/code&gt; folders that you should delete?&lt;/p&gt;
&lt;p&gt;When you take the GUI route, you&amp;#8217;re exposed to all of that stuff. You&amp;#8217;re more likely to catch possible problems, or have ideas about how to improve the system.&lt;/p&gt;
&lt;p&gt;So the scoreboard for &lt;strong&gt;Visibility&lt;/strong&gt; is:&lt;/p&gt;
&lt;blockquote&gt;&lt;strong&gt;GUI - Medium to High&lt;/strong&gt; (depending on GUI quality)&lt;br/&gt;&lt;strong&gt;CLI - Low to Medium&lt;/strong&gt; (depending on CLI quality)&lt;/blockquote&gt;
&lt;p&gt;And when our task isn&amp;#8217;t to copy files, but to write or debug a computer program, this point becomes &lt;em&gt;crucial&lt;/em&gt;. There&amp;#8217;s so much shit that&amp;#8217;s helpful to see when you&amp;#8217;re developing! If you just got an exception, you should see the running code, the entire stack, the values of all variables, documentation for the currently selected function, system I/O, and on and on. Each of these pieces of data might help you solve your problem in seconds instead of hours.&lt;/p&gt;
&lt;p&gt;&lt;img align="right" src="http://ram.rachum.com/images/zork.gif"/&gt;Now sure, you can obtain all of that data on the shell too. But having to explicitly ask for it by running a command is such a chore! And what more, every time you ask for more data, it pushes the previous data up and away, as if that data wasn&amp;#8217;t important anymore!&lt;/p&gt;
&lt;p&gt;Do you know what this reminds me of? It reminds me of old text-based games, where you would tell the computer &amp;#8220;Go west&amp;#8221;, &amp;#8220;Look around&amp;#8221;, &amp;#8220;Fight monster&amp;#8221; etc., and it would tell you things like &amp;#8220;You have killed the monster&amp;#8221; or &amp;#8220;You are in a room with exits to the north and east.&amp;#8221; Aside from the nostalgic feelings, playing a game like this totally sucks! You want to &lt;em&gt;see&lt;/em&gt; how many exits the room has! You want to &lt;em&gt;see&lt;/em&gt; the monster you&amp;#8217;re killing, in all its gory detail! And this is true whether that monster is a grue or a segfault.&lt;/p&gt;
&lt;h2&gt;Speed&lt;/h2&gt;
&lt;p&gt;Now we&amp;#8217;re getting to our second parameter: &lt;strong&gt;Speed&lt;/strong&gt;. The opposite of speed, when it comes to computing tasks, can be called &lt;strong&gt;friction&lt;/strong&gt;. If you have to click in seven different places to finish a task, then that&amp;#8217;s a lot of friction, and that makes for a slow process and a sad user.&lt;/p&gt;
&lt;p&gt;Speed is obviously a crucially important parameter. When you spend 8 hours a day doing tasks on the computer, the speed with which you do the tasks makes for a night-and-day difference. Sometimes you manage to shorten a 10-second task to a 2-second task, which is nothing short of an orgasm for a productivity-minded developer. But even cutting a task down from 3 seconds to 2 seconds is a considerable improvement. Remember— We&amp;#8217;re sitting in front of that freaking computer &lt;em&gt;all day long.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s important to note that speed is important &lt;em&gt;not only&lt;/em&gt; because of the time you save, but because computer tasks are usually done in order to achieve some greater goal. That greater goal often requires a bunch of subtasks, and as each of these subtasks becomes more complicated and slow, you lose sight of your original goal. Doing tasks fast allows your train of thought to go faster.&lt;/p&gt;
&lt;p&gt;Okay, so how do CLIs fare against GUIs in the parameter of speed?&lt;/p&gt;
&lt;p&gt;Speed is the old standby of CLI-loving programmers. &amp;#8220;CLIs are so must faster than GUIs! A GUI is so cumbersome, you have to click here and click there, navigate through menus&amp;#8230; With a CLI, you just press a few keys, hit enter, and presto, it&amp;#8217;s done!&amp;#8221;&lt;/p&gt;
&lt;p&gt;I beg to differ.&lt;/p&gt;
&lt;p&gt;The scoreboard for &lt;strong&gt;Speed&lt;/strong&gt;, which I will promptly explain, is:&lt;/p&gt;
&lt;blockquote&gt;&lt;strong&gt;GUI - Low to High&lt;/strong&gt; (depending on GUI quality)&lt;br/&gt;&lt;strong&gt;CLI - Medium to High&lt;/strong&gt; (depending on CLI quality)&lt;/blockquote&gt;
&lt;p&gt;The CLIs&amp;#8217; score of &amp;#8220;Medium to High&amp;#8221; is, on average, better than the GUIs&amp;#8217; score of &amp;#8220;Low to High&amp;#8221;; but when it comes to software, where copying costs are minimal, the best program tends to make all the other alternatives extinct. So in the long run we care more about the best program rather than the average program, so GUIs and CLIs end up pretty close to each other on the all-important &lt;strong&gt;speed&lt;/strong&gt; parameter.&lt;/p&gt;
&lt;p&gt;&amp;#8220;But wait,&amp;#8221; the Vim fanboy cries, &amp;#8220;how the hell could a GUI have anything close to a &amp;#8220;high&amp;#8221; speed rating?&amp;#8221;&lt;/p&gt;
&lt;p&gt;If you don&amp;#8217;t know the answer to that question, I want you to really listen to what I&amp;#8217;m about to say next, and try hard to remember it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Because GUIs can be controlled with the keyboard!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Phew, that felt good! Now let&amp;#8217;s explain.&lt;/p&gt;
&lt;p&gt;The reason that programmers see GUIs as so much slower and more cumbersome than CLIs is that they try to operate them with the mouse. Working with the mouse is terribly, terribly slow. When you&amp;#8217;re working with the mouse, you don&amp;#8217;t have muscle memory. You always have to look at the screen for the next button or next menu item that you want to click. Not to mention that the mouse is more conducive to RSI than the keyboard, and this can be a serious health problem for heavy computer users.&lt;/p&gt;
&lt;p&gt;To take a simple example: After you&amp;#8217;ve learned to copy-paste by pressing &lt;code&gt;Ctrl-C&lt;/code&gt; and &lt;code&gt;Ctrl-V&lt;/code&gt;, you don&amp;#8217;t need to think about them anymore; those movements become second nature. Your body and mind are good at memorizing these kinds of tasks, and before you know it you&amp;#8217;ll be &lt;code&gt;Ctrl-C&lt;/code&gt;&amp;#8216;ing and &lt;code&gt;Ctrl-V&lt;/code&gt;&amp;#8216;ing without even thinking about it, like a pianist doesn&amp;#8217;t even think about which piano keys he&amp;#8217;s hitting. But if you were to try this with the mouse, it won&amp;#8217;t work: You&amp;#8217;ll always have to be on the lookout for the context menu after right-clicking, and then visually search for the &amp;#8220;copy&amp;#8221; item and click it&amp;#8230; &lt;em&gt;Friction friction friction.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Not to mention that when you&amp;#8217;re using the mouse, you constantly have to move your right hand from the mouse to the keyboard and back, and that sucks.&lt;/p&gt;
&lt;p&gt;And programmers often do tasks much more complicated than copy-pasting, making this point so much stronger.&lt;/p&gt;
&lt;p&gt;So we all agree: Mice suck, keyboards rock!&lt;/p&gt;
&lt;p&gt;But, but, but&amp;#8230; A good GUI can be controlled with the keyboard! A good GUI can be operated completely with the keyboard, and has good keyboard shortcuts for the most common tasks.&lt;/p&gt;
&lt;p&gt;&lt;img align="right" height="422" src="http://ram.rachum.com/images/git_checkout.jpg" width="326"/&gt;For example, let&amp;#8217;s look at a program I use everyday and has both a GUI and CLI interface: &lt;a href="http://en.wikipedia.org/wiki/Git_(software)"&gt;Git&lt;/a&gt;. Say I want to check-out a branch, something I do dozens of times a day. If I&amp;#8217;d want to do that with the CLI, I&amp;#8217;d type &lt;code&gt;git checkout master&lt;/code&gt;. With autocompletion in place, I will have to make exactly 12 keypresses (namely, &lt;code&gt;git chec{TAB}m{Tab}{Enter}&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;What about the GUI? Sure, if I&amp;#8217;ll try using a mouse it will be an epic fail, but with the keyboard I can do &lt;code&gt;{Ctrl-O}ma{Enter}{Enter}&lt;/code&gt;, which makes for exactly 6 keypresses. &lt;strong&gt;It&amp;#8217;s twice as fast at the CLI version, i.e. half of the friction!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now sure, some tasks can turn out to be faster on a GUI and others can be faster on a CLI, but when you pit the best GUIs against the best CLIs, they&amp;#8217;re in the same league.&lt;/p&gt;
&lt;h2&gt;So why do programmers still prefer CLIs?&lt;/h2&gt;
&lt;p&gt;Now we can get back to the two items I mentioned at the beginning of the article, and expand on them. Those are the two main reasons that programmers prefer CLIs to GUIs:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Most GUIs suck. And when it comes to proper keyboard support, most GUIs suck &lt;em&gt;terribly&lt;/em&gt;.&lt;/strong&gt; It seems that most developers of GUI apps don&amp;#8217;t care so much about keyboard-accessibility. It&amp;#8217;s all too common to see desktop apps that simply cannot be controlled with the keyboard. Buttons that cannot be pressed, menus that cannot be opened, scrollbars that cannot be moved with the arrow keys.&lt;/p&gt;
&lt;p&gt;This is annoying enough in mainstream software that&amp;#8217;s mostly intended for non-technical people, but the astounding thing is that &lt;strong&gt;many open-source programs that are made &lt;em&gt;for&lt;/em&gt; developers &lt;em&gt;by&lt;/em&gt; developers are not keyboard-usable!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I find this completely shocking. The same programmers that preach about how Vim is so much more productive than an IDE because you get to use the keyboard, suddenly put on a different face when it&amp;#8217;s time for them to make GUIs, for other programmers no less!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Most programmers are ignorant about good GUIs.&lt;/strong&gt; Because some GUIs are good. Some GUIs have great keyboard support. Microsoft is one company that really shines in this regard. I challenge you to find one action in Windows, or in any other Microsoft product, that can be done with the mouse but not with the keyboard.&lt;/p&gt;
&lt;p&gt;So good GUIs exist. They can be hard to find, but hey, a lot of good software is. Google Chrome has good keyboard support. Mac and Ubuntu have okay keyboard support. Wing IDE has good keyboard support. PuTTY has great keyboard support.&lt;/p&gt;
&lt;p&gt;And of course, these GUI programs usually have much better visibility than their CLI counterparts, making them more productive programs overall.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;h2&gt;Final words&lt;/h2&gt;
&lt;p&gt;I want to stress out that what I did here is a comparison between the &lt;em&gt;very best&lt;/em&gt; GUIs and the &lt;em&gt;very best&lt;/em&gt; CLIs. It takes time to find good GUI programs that can be operated with the keyboard. That&amp;#8217;s tough. It takes time before you can surround yourself in excellent GUI tools to help you do your job. But it&amp;#8217;s possible, and eventually, it&amp;#8217;s the optimal way to work.&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;&lt;a id="note1" name="note1"&gt;&lt;/a&gt;[1] - Actually there are some communities of programmers where most of the members like GUIs, but these are usually communities of developers that work in environments like Dot-Net and Java.&lt;/p&gt;
&lt;p&gt;&lt;a id="note2" name="note2"&gt;&lt;/a&gt;[2] - One parameter that is very important for non-hardcore users, and still somewhat important even for hardcore users, is &lt;strong&gt;Discoverability&lt;/strong&gt;, i.e. being able to easily see all the different options and commands that a program gives you. GUIs obviously beat CLIs big-time in this parameter.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/9875143930</link><guid>http://blog.ram.rachum.com/post/9875143930</guid><pubDate>Tue, 06 Sep 2011 15:17:00 +0300</pubDate></item><item><title>Quick riddle</title><description>&lt;p&gt;Here&amp;#8217;s a quick riddle:&lt;/p&gt;
&lt;p&gt;You owe your friend two Dollars. You have a $5 bill, but your friend has only a $1 coin for change.&lt;/p&gt;
&lt;p&gt;What would be a fair way to settle your debt that would not require you to get more change?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Answer:&lt;/strong&gt; You toss the coin. If you win, you don&amp;#8217;t give your friend anything. If your friend wins, you give him the $5 and he gives you back $1, so he gets $4. His expectation is $4 * 1/2 = $2, which is exactly fair.&lt;/p&gt;
&lt;p&gt;Thanks for all the people who posted their answers in the comments!&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/9799355938</link><guid>http://blog.ram.rachum.com/post/9799355938</guid><pubDate>Sun, 04 Sep 2011 22:12:00 +0300</pubDate></item><item><title>A Git user's first (and hopefully last) foray into SVN-land</title><description>&lt;p&gt;&lt;img align="right" alt="By Asthma Helper at flickr.com" height="237" src="http://ram.rachum.com/images/jump_fail.jpg" width="213"/&gt;I belong to a rare breed of programmers: I was born and raised on Git. It&amp;#8217;s the only version-control system that I&amp;#8217;ve ever used. This is my personal story of how I had to use SVN temporarily for a contract project.&lt;/p&gt;
&lt;p&gt;Now, I know there are a million of blog posts out there saying &amp;#8220;Ooh, look how much better Git is than SVN!&amp;#8221; I&amp;#8217;m not trying to tell people something they don&amp;#8217;t already know about Git, SVN, and the difference between them&amp;#8212; I&amp;#8217;ll just be telling my own personal story and my own impressions of SVN.&lt;!-- more --&gt;&lt;/p&gt;
&lt;h2&gt;Beginnings&lt;/h2&gt;
&lt;p&gt;I started my programming comeback about 3 years ago. When I was a child, I programmed a lot&amp;#8212; I was taught Basic in third grade, and I spent a lot of time of my elementary school and junior high making various little programs in C and Pascal. But I took a long hiatus from programming starting at about 10th grade, because I was frustrated with how many stupid technical details were involved in programming.&lt;/p&gt;
&lt;p&gt;That hiatus ended about 3 years ago as I started learning Python, programming computer simulations for my Physics research, and about a year after that became a professional programmer. By the way, the main reason I chose Python is because &lt;a href="http://paulgraham.com"&gt;Paul Graham&lt;/a&gt; mentioned it favorably in one of his essays.&lt;/p&gt;
&lt;h2&gt;Starting out with Git&lt;/h2&gt;
&lt;p&gt;How did I start out with version control? I saw the term &amp;#8220;GitHub&amp;#8221; being thrown around a lot on &lt;a href="http://news.ycombinator.com/"&gt;Hacker News&lt;/a&gt;. It seemed to be something everyone liked, so I figured I&amp;#8217;ll try putting my project &lt;a href="http://garlicsim.org"&gt;GarlicSim&lt;/a&gt; there. I learned Git. It took a while, because I was still not very technical, but eventually I got the hang of it enough to work in a single branch.&lt;/p&gt;
&lt;p&gt;After a while, I understood what branches meant. I understood that I was able to create alternate versions of my code, work on them as much as I want, and decide at my leisure whether they should be merged into &lt;code&gt;master&lt;/code&gt; and become an official part of my project.&lt;/p&gt;
&lt;p&gt;I was happy. Branches are awesome.&lt;/p&gt;
&lt;h2&gt;I heard about SVN&amp;#8230;&lt;/h2&gt;
&lt;p&gt;At some point I heard about SVN. I heard that it was something like a predecessor to Git.&lt;/p&gt;
&lt;p&gt;What I imagined in my mind was that SVN was to Git what Windows 98 was to Windows XP. I imagined that SVN was just a crappier version of Git. Like, same idea, same workflow, just with more annoyances and less polish.&lt;/p&gt;
&lt;p&gt;That perception changed when I got my first programming job.&lt;/p&gt;
&lt;h2&gt;First contact with SVN&lt;/h2&gt;
&lt;p&gt;Then I started programming professionally. I was hired by an Israeli startup to work on a Django project. I was kinda surprised to learn that they were using SVN. I figured that a technology startup would, you know, &lt;em&gt;care about technology&lt;/em&gt;. But I said, &amp;#8220;Meh, so I&amp;#8217;ll just have to use Windows 98 for a while instead of XP, I could live with that.&amp;#8221;&lt;/p&gt;
&lt;p&gt;Oh boy.&lt;/p&gt;
&lt;p&gt;So I was just about to learn SVN. This is a dramatization of the conversation I had with that company&amp;#8217;s chief developer: (I ask you to read the text in &lt;em&gt;italics&lt;/em&gt; in John Cleese&amp;#8217;s famous &lt;a href="http://youtu.be/sFBOQzSk14c?t=59s"&gt;surprised voice&lt;/a&gt;.)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Me: Hey man, I wanna make a small change to the code to add [Feature X], I&amp;#8217;ll just make a little branch, alright?&lt;/p&gt;
&lt;p&gt;Chief developer: &lt;em&gt;What?!&lt;/em&gt; You&amp;#8217;re gonna make a &lt;em&gt;branch&lt;/em&gt;?!&lt;/p&gt;
&lt;p&gt;Me (taken back): Eh, yeah, a branch. So, you know, I could make changes in it without affecting our &lt;code&gt;master&lt;/code&gt;, or &lt;code&gt;trunk&lt;/code&gt;, or whatever?&lt;/p&gt;
&lt;p&gt;Chief developer: And how are we supposed to put the changes back into our &lt;code&gt;trunk&lt;/code&gt;?!&lt;/p&gt;
&lt;p&gt;Me (totally freaked out at this point): Eh, merge them back?&lt;/p&gt;
&lt;p&gt;Chief developer: &lt;em&gt;Merge? MERGE?!&lt;/em&gt; That&amp;#8217;s a mighty big word for someone your size!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And then followed a conversation in which he explained to me that branching-n-merging in SVN is really fucking complicated. I don&amp;#8217;t remember exactly what he said was required, but it changed my perception of SVN from:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;SVN is a slightly crappier version of Git.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;SVN is a version of Git in which every time you want to start a branch or merge it back, you have to sacrifice a young virgin to the source-control gods.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I was not happy.&lt;/p&gt;
&lt;p&gt;Luckily, the chief developer was considerate of me, and the company was small enough (only a handful of people), so he agreed that we&amp;#8217;ll just move our entire product to Git.&lt;/p&gt;
&lt;p&gt;I was saved at last moment from the atrocities of SVN.&lt;/p&gt;
&lt;p&gt;Until now.&lt;/p&gt;
&lt;h2&gt;SVN strikes back&lt;/h2&gt;
&lt;p&gt;Recently I got a nice contract job. And, like any other contract job after my initial trauma with SVN, I made sure to ask that the job was in Git &lt;em&gt;before&lt;/em&gt; I started the job. Unfortunately, despite being told that the job was in Git, it turned out that the job was in SVN, and that we&amp;#8217;d move to Git &amp;#8220;after the deadline.&amp;#8221;&lt;/p&gt;
&lt;p&gt;I was not happy. It turned out that I had to learn SVN after all.&lt;/p&gt;
&lt;p&gt;I had my brother give me a crash course on SVN via phone. My brother&amp;#8217;s a C++/Java programmer, and he had to use SVN for a while, so he agreed to help me with it. He has experience with Git so he was in a good position to explain the differences between the two. I primarily remember him explaining to me about branches.&lt;/p&gt;
&lt;p&gt;Now, I remember seeing the &amp;#8220;branches&amp;#8221; folder in the SVN repo. I thought it was pretty weird to keep branches in a folder, but whatever. I assumed that the stuff in the &amp;#8220;branches&amp;#8221; folder was like the stuff in the &amp;#8220;.git&amp;#8221; folder in Git: Magic data that contains all your branches and allows you to switch to them at will.&lt;/p&gt;
&lt;p&gt;Then my brother explained to me that this is not the case. I remember this part of our phone conversation pretty well, because at that point I was sitting on my knees on the carpet, with my head in my hands, looking down into the seat of my office chair. He explained that SVN doesn&amp;#8217;t &lt;em&gt;really&lt;/em&gt; have branches, it&amp;#8217;s just a folder called &amp;#8220;branches&amp;#8221; that you manually copy your code into.&lt;/p&gt;
&lt;p&gt;I was not happy.&lt;/p&gt;
&lt;p&gt;Though, on the other hand, it was kind of a relief; it was relieving to know that SVN doesn&amp;#8217;t even &lt;em&gt;try&lt;/em&gt; to do branches. Because God knows how badly they would fuck it up if they would have tried to. Copy-pasting folders is major bullshit, but at the very least it&amp;#8217;s predictable; when you use &lt;code&gt;mv&lt;/code&gt; or &lt;code&gt;cp&lt;/code&gt;, you know exactly what you&amp;#8217;re getting, which is something you can&amp;#8217;t say about &lt;code&gt;svn&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That partial relief nonwithstanding, the whole &amp;#8220;branches&amp;#8221; thing in SVN is utterly ridiculous. In the past when people told me &amp;#8220;SVN has branches too!&amp;#8221; I knew that something wasn&amp;#8217;t right and I just assumed that SVN branches suck, but now with this new knowledge I can answer in confidence, &amp;#8220;No, SVN does &lt;em&gt;not&lt;/em&gt; have branches, it merely has a folder called &amp;#8220;branches&amp;#8221;, which is a far cry from having actual branches.&amp;#8221;&lt;/p&gt;
&lt;p&gt;You know what SVN&amp;#8217;s &amp;#8220;branches&amp;#8221; folder is like? It&amp;#8217;s like taking an A4 paper from your printer, drawing a &lt;a href="http://en.wikipedia.org/wiki/DeLorean_time_machine#Flux_capacitor"&gt;Flux Capacitor&lt;/a&gt; on it, hanging it in your car and declaring with a satisfied grin, &amp;#8220;My car&amp;#8217;s a DeLorean time machine! I can go back in time!&amp;#8221;&lt;/p&gt;
&lt;h2&gt;SVN Ignore&lt;/h2&gt;
&lt;p&gt;One other thing I had to deal with in SVN was doing &amp;#8220;SVN ignore&amp;#8221; (I don&amp;#8217;t know the SVN jargon for it.) Basically I was looking for the SVN equivalent of &lt;code&gt;.gitignore&lt;/code&gt;: A list of file patterns that do not get source-controlled, ever. This is very useful for build products, files containing passwords, user-uploaded static content, etc.&lt;/p&gt;
&lt;p&gt;Now in Git, you just have a file called &lt;code&gt;.gitignore&lt;/code&gt; in the root of your repo, and in that file you write the file patterns that should be git-ignored, like &lt;code&gt;*.pyc&lt;/code&gt; or &lt;code&gt;build&lt;/code&gt;. You save the file, and that&amp;#8217;s it. I assumed that there would be a similar mechanism in SVN.&lt;/p&gt;
&lt;p&gt;You can probably guess where this is going by now.&lt;/p&gt;
&lt;p&gt;It turned out that SVN&amp;#8217;s ignoring mechanism is far more complicated than that. It basically holds a list of SVN-ignored file for &lt;em&gt;every&lt;/em&gt;, &lt;em&gt;single&lt;/em&gt;, &lt;em&gt;folder&lt;/em&gt; in your repo, and there is no convenient way to edit all these rules for the enitre repo, or even just view them. You have to run &lt;a href="http://stackoverflow.com/questions/1252270/how-do-i-view-all-ignored-patterns-set-with-svnignore-recursively-in-an-svn-repo/1252303#1252303"&gt;this baffling command&lt;/a&gt; in order to even &lt;em&gt;view&lt;/em&gt; the ignore rules. Also, when you edit the ignore rules for a folder, you&amp;#8217;re not just editing a text file like in Git, you have to actually set the rules using &lt;code&gt;svn&lt;/code&gt;. I tried actually going into the dreaded &lt;code&gt;.svn&lt;/code&gt; folder and edit the text file that holds the ignore rules myself, but it was encoded in a really stupid encoding, and in order to write rules there manually I would have had to count the number of characters in my ruleset and type it as part of the text file.&lt;/p&gt;
&lt;h2&gt;Back to Git&lt;/h2&gt;
&lt;p&gt;Eventually my new client saw how bad of an effect SVN was having on me, and he let me move us to Git. So over the weekend I used &lt;a href="https://github.com/nirvdrum/svn2git"&gt;svn2git&lt;/a&gt; to convert our repo to Git and now we manage all our code in Git. Uninstalling TortoiseSVN from my machine was quite a happy moment.&lt;/p&gt;
&lt;p&gt;Goodbye SVN, may we never meet again.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/9583964892</link><guid>http://blog.ram.rachum.com/post/9583964892</guid><pubDate>Tue, 30 Aug 2011 14:36:00 +0300</pubDate></item><item><title>Postponing GarlicSim 0.7 yet again</title><description>&lt;p&gt;Yeah, the deadline for GarlicSim 0.7 has been an epic fail. &lt;a href="http://blog.garlicsim.org/post/7849706187/postponing-garlicsim-0-7-again"&gt;A couple of weeks ago&lt;/a&gt; I thought I had it under control, but then I got a contract job that&amp;#8217;s been taking all my time. Good news for mah bank account, bad news for mah open-source project.&lt;/p&gt;
&lt;p&gt;So I&amp;#8217;m postponing the 0.7 release to &lt;strong&gt;November 1st, 2011&lt;/strong&gt;. See you then.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/8656451924</link><guid>http://blog.ram.rachum.com/post/8656451924</guid><pubDate>Mon, 08 Aug 2011 23:23:31 +0300</pubDate></item><item><title>Postponing GarlicSim 0.7 again</title><description>&lt;p&gt;I&amp;#8217;m postponing the deadline of GarlicSim 0.7 again, this time to &lt;strong&gt;August 20th&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;This is fucked up and I feel really bad about this. I should have been more realistic about my deadlines, but I&amp;#8217;ve let my optimism have the better of me. I&amp;#8217;ll try to be more accurate in future deadlines.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/7849706187</link><guid>http://blog.ram.rachum.com/post/7849706187</guid><pubDate>Wed, 20 Jul 2011 20:43:57 +0300</pubDate></item><item><title>Why making a cool project is a good idea for an aspiring software developer</title><description>&lt;p&gt;As a software developer, I get to know a lot of other software developers. Many of the software developers I know are either running a startup, working as an early employee for a startup, doing contract jobs for a startup, or dreaming of one day starting a startup. My point is that software developers are very interested in startups, either starting them or working for them.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.flickr.com/photos/jmpk/3420499644"&gt;&lt;img align="right" height="487" src="http://ram.rachum.com/images/man_juggling.png" width="323"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My advice to anyone who&amp;#8217;s interested in startups: &lt;strong&gt;Before you ever start a startup, try to make at least one cool and useful project.&lt;/strong&gt; It doesn&amp;#8217;t have to make money; in fact, it&amp;#8217;s better if your project doesn&amp;#8217;t even try to make any kind of profit.&lt;/p&gt;
&lt;h2&gt;Why is making a cool project important?&lt;/h2&gt;
&lt;p&gt;When you&amp;#8217;re doing a startup, you essentially have to do two things at once:&lt;/p&gt;
&lt;ol&gt;&lt;li&gt;Create some kind of &lt;strong&gt;product&lt;/strong&gt; or solution that answers your users&amp;#8217; needs; this is usually the software ingredient of your startup; and&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;business&lt;/strong&gt; around that product that brings in money for your company.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;Both of these things are difficult. Really difficult. It&amp;#8217;s easy to mess either of these up. And you have to do them both &lt;em&gt;at the same time&lt;/em&gt;. Get one right but mess the other one up, and you still failed.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a metaphor: &lt;strong&gt;Starting a startup is like juggling while riding a unicycle.&lt;/strong&gt; Riding a unicycle is &lt;em&gt;hard&lt;/em&gt;. Juggling is &lt;em&gt;hard&lt;/em&gt;. Doing them both at the same time? &lt;em&gt;Really freaking hard.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If your goal in life was to juggle while riding a unicycle, would you get on the unicycle while holding a few juggling clubs and try to juggle while riding the unicycle? Not if you have any common sense. You would first try to ride the unicycle. You&amp;#8217;d take your time until you&amp;#8217;re sufficiently skilled with that. Ditto for juggling. Then you&amp;#8217;d carefully try to do both of them at once.&lt;/p&gt;
&lt;p&gt;The same applies to startups. Making a successful product is hard enough; it&amp;#8217;s all too common for companies to invest a lot of resources in making an ambitious product, and when it&amp;#8217;s launched it&amp;#8217;s just &amp;#8220;meh&amp;#8221;. &lt;/p&gt;
&lt;p&gt;Building a business on top of a product is hard as well. There are many places where you can screw it up, both by making technical mistakes or strategic ones.&lt;/p&gt;
&lt;p&gt;As you can guess, the chance of you messing &lt;em&gt;either&lt;/em&gt; the software side &lt;em&gt;or&lt;/em&gt; the business side is very big.&lt;/p&gt;
&lt;h2&gt;Start a project, don&amp;#8217;t try to make money.&lt;/h2&gt;
&lt;p&gt;That&amp;#8217;s the essence of my advice. Start a project which is free of the burden of profit. Sure, you won&amp;#8217;t get rich off of it, and you&amp;#8217;re gonna have to support yourself financially while you work on it, but it&amp;#8217;s your best chance at learning how to make a successful product&amp;#8212; It definitely has a much better ROI than going to college.&lt;/p&gt;
&lt;p&gt;Not being burdened with having to make a profit will make it easier for you to build a successful product. &lt;strong&gt;You&amp;#8217;d never have to think about limiting or exploiting your users&lt;/strong&gt;, which is something that many software businesses have to do. Think about those crippled &amp;#8220;starter&amp;#8221; versions of Windows that sell for cheap, or DRM, or annoying ads on websites, or desktop software that installs annoying toolbars and spyware. These are all attempts to make money by limiting or exploiting users. &lt;a href="http://blog.ram.rachum.com/post/1388741380/thinking-of-your-software-as-a-butler-is-difficult-but"&gt;Software needs to act like a butler&lt;/a&gt;, which is difficult enough; imagine how hard it is to have a good butler who also tries to upsell you some crap as he serves you.&lt;/p&gt;
&lt;p&gt;As a person who&amp;#8217;s making a project that doesn&amp;#8217;t aim to make money, you&amp;#8217;ll be free from all of those dangerous practices.&lt;/p&gt;
&lt;p&gt;Making a useful product is still hard, mind you, and you still have a good chance of failing; but at least when you crash from the unicycle and try to pick yourself up, you won&amp;#8217;t have juggling clubs falling on your head.&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/7699968171</link><guid>http://blog.ram.rachum.com/post/7699968171</guid><pubDate>Sun, 17 Jul 2011 00:34:00 +0300</pubDate></item><item><title>`SimpackSelectionDialog` almost done</title><description>&lt;p&gt;Hey, only a few weeks remain until the release of GarlicSim 0.7. I just wanted to give you a sneak peak of the new &lt;code&gt;SimpackSelectionDialog&lt;/code&gt;, incidentally on a Mac:&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ram.rachum.com/images/simpack_selection_widget_teaser.png"&gt;&lt;img align="middle" alt="Teaser of `SimpackSelectionDialog`" height="384" src="http://ram.rachum.com/images/simpack_selection_widget_teaser_thumbnail.png" width="512"/&gt;&lt;br/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ram.rachum.com/images/simpack_selection_widget_teaser.png"&gt;(Click to enlarge.)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m quite pleased with this widget. It&amp;#8217;s almost finished, I might put in a few more touches before the release. The above screenshot shows it on a Mac, but as always, it&amp;#8217;s completely cross-platform and works on Windows XP, Windows 7 and Linux as well.&lt;/p&gt;
&lt;p&gt;This time I put in more emphasis on keyboard-accessibility, including accelerators for as many buttons as possible. The widget is not 100% keyboard accessible, but I&amp;#8217;d say around 90%, and it will get to 100% in a couple of years as the underlying &lt;a href="http://wxpython.org"&gt;wxPython framework&lt;/a&gt; evolves. I also went through all the other dialogs in GarlicSim and gave them as many accelerators as possible.&lt;/p&gt;
&lt;p&gt;Going back to work on 0.7!&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/7508116562</link><guid>http://blog.ram.rachum.com/post/7508116562</guid><pubDate>Tue, 12 Jul 2011 01:13:00 +0300</pubDate></item><item><title>DreamPie: My favorite Python shell</title><description>&lt;p&gt;If you&amp;#8217;re not familiar with it, you should really check out &lt;a href="http://dreampie.sourceforge.net/"&gt;DreamPie&lt;/a&gt;, which is a graphical Python shell.&lt;!-- more --&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s a really well-done GUI shell, with great keyboard support to boot. Its most unique feature is the separation of the &amp;#8220;history area&amp;#8221; from the &amp;#8220;current command area&amp;#8221;. I think this design makes more sense than the traditional approach of having them together. It&amp;#8217;s also notable that the &amp;#8221;current command area&amp;#8221; can be used to enter multi-line Python commands (like defining a function or a class) and it&amp;#8217;s very easy to move between lines to edit them. (This sounds obvious but many other shells make this kind of editing cumbersome.) The autocompletion is also well done; for example, DreamPie is able to autocomplete modules even if they haven&amp;#8217;t been imported yet.&lt;/p&gt;
&lt;p&gt;On top of that, I was delighted to find that it works on PyPy out of the box! Check it out:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lmn8op5dMS1qzywlj.png"/&gt;&lt;/p&gt;</description><link>http://blog.ram.rachum.com/post/6429754567</link><guid>http://blog.ram.rachum.com/post/6429754567</guid><pubDate>Sat, 11 Jun 2011 23:56:00 +0300</pubDate></item></channel></rss>
