tag:blogger.com,1999:blog-41502322953973686572024-03-05T07:10:38.748-04:00/random/thoughtsnicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-4150232295397368657.post-10441729032807638162009-11-08T17:42:00.006-04:302010-07-27T11:56:11.883-04:30BooksBooks are great! Some say the internet holds all the answers. I'd say it holds most of the answers and it will hold them all as soon as publishers, authors and hardware companies get off their own way and create serious mechanisms to manage (publish, buy, sell, read, own, share) digital books. If they're as stubborn as the music industry, this will not happen soon; but I think that, with the lessons learned from music, we're moving in the right direction. Let's see what the future holds (or let's ourselves make the future happen). For now, here's a list of technical books I've read lately and I'd like to recommend:<br /><br /><ul><br /><li><br /><a href="http://oreilly.com/catalog/9780596510046">Beautiful Code</a><br /><br />This book is a must read. It is also a very easy read. It's comprised of series of write-ups by different authors of the likes of Brian Kernighan and Simon Peyton Jones where the authors have chosen a problem they've faced and solved "Beautifully". Each author has their own definition of beautiful code (great design, speed and reliability, testability, versatility and more), but all of them teach you valuable ways to think about problem solving, design and development. With languages from Haskell to C (through Python, Ruby, Perl Lisp and others) and topics from quicksort to software transactional memory (through Python's dictionaries, testing, debugging, mapreduce and the original implementation of Paint among others) I can assure you that this book will be of interest to any good computer scientist or software engineer. My recommendation: go buy this book and put it on your night stand; it is very easy to just read a chapter every day.<br /></li><br /><li><br /><a href="http://www.realworldhaskell.org/blog/">Real World Haskell</a><br /><br />This book is just amazing. It covers Haskell from zero-knowledge to advanced and has something to offer to programmers of most backgrounds. Those who have never programmed in Haskell (or even functionally) will definitely benefit from the paradigm switch and seeing the problems from another perspective. Those that already know Haskell will probably find it a little bit slow as it explores a lot of the basics, but there are, for certain, hidden pearls to be found on every section; plus, you can skim fast through the "Haskell" parts and get to the "Real World" parts to get great examples of the uses of this powerful, different, language.<br /></li><br /><br /><li><br /><a href="http://www.amazon.com/Programming-Pearls-2nd-Jon-Bentley/dp/0201657880">Programming pearls</a><br /><br />This is a book of the like of Beautiful Code but written by only one author (Jon Bentley, who also writes a great article in Beautiful Code) and slightly older. It showcases a series of problems and different ways to approach and solve them. It is not so much focused on the solutions themselves but the way of thinking for arriving to those solutions. The problems in themselves are not overly complex, but the detail in which the different options are explored and the trade-offs and solutions presented is very appealing. All the problems are accompanied with the C code used for solving it but avoiding any unnecessary boilerplate. It's simply a great book to keep you sharp on your computer-problem solving abilities. <br /></li><br /><li><br /><a href="http://www.amazon.com/Algorithm-Design-Manual-Steve-Skiena/dp/0387948600">The algorithm design manual</a><br /><br />While I think this book is a little hard to read at some points it provides an amazingly complete set of algorithms, their implementations and example problems. One thing I liked a lot about this book is that it's not solely based in simple explanatory examples but also shows how the different techniques showcased in the book can be used to solve real life problems (that actually happened). But the really amazing thing of this book is that it contains a chapter with a comprehensive catalogue of algorithms categorized by the type of problem they solve. It is literally half of the book, they all have an illustration to represent what the algorithm does and it serves as a great reference for any future algorithmic problems you might encounter.<br /><br /></li><br /></ul><br /><br />Honorable mentions go to: <br /><ul><br /><li><br /><a href="">Coders at work</a>: a series of interviews with great programmers in which they expose their thoughts on programming along with their personal experience. As of today I've only read a few chapters, but I go so far as to recommend the whole book as it has left a very good impression. <br /></li><br /><li><br /><a href="http://www.amazon.com/Introduction-Theory-Computation-Michael-Sipser/dp/053494728X">Introduction to the theory of computation</a>: a great introduction, from regular expressions, finite and push-down automatons to reductions and computability. Very well explained from an expert in the field. It is also well written and very short. Loved it.<br /></li><br /><li><br /><a href="http://aima.cs.berkeley.edu/">Artificial Intelligence</a>: a modern approach, this book contains at least introductory material to most fields in artificial intelligence. It has in-depth material about a lot of topics and instead of trying to deeply explore all of the areas of AI in one book (which would be impossible) it focuses on the most important areas and gives you a great introduction on the rest for you to go and read the papers or a more specific book.<br /></li><br /></ul><br /><br />Later this month I'll make a list of non-technical books I have read or am reading and I'd like to recommend.<br /><br />Any technical books you can recommend me?<br />I am particularly interested in advanced data structures, modern concurrency (Programming Erlang is in my to-read list), compilers (Compilers by Aho et. al. is in my to-read list), optimization and computational geometry. But that's just a list of stuff that popped in my head this instant, so if you have any recommendations on another subject please be sure to let me know!nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com1tag:blogger.com,1999:blog-4150232295397368657.post-67615401619163192282009-11-07T09:35:00.008-04:302009-11-13T10:30:53.643-04:30Emacs mark-stackThere's no worst feeling than being lost in your code. You know, when you need to look at a bunch of code fragments buried in other files or in the same, very large, file; or having to trace back a bunch of function calls spanning multiple emacs buffers and not knowing where the previous stuff was.<br />Okey, there are probably a lot of feelings that are worst. But you gotta give me it's annoying.<br /><br />If only there was a way to push positions to a stack and then come back to them later on! I know about C-@ and C-U C-@, but if you use delete-selection-mode or anything else in which you do a lot of marks that's not an option. Plus, the default key bindings suck and it's only buffer local. So I decided to write my own mark system in emacs lisp.<br /><br />Before people come rushing down to the comments to tell me there's already a better solution for this problem, take into account that I didn't look much into it. I did this not only to solve the problem but to practice my elisp. Nevertheless, if there are alternatives I would love to hear about them; so comment on, just don't troll =)<br /><br />If you don't know emacs-lisp there's a <a href="http://xahlee.org/emacs/elisp.html">guide</a> by <a href="http://xahlee.org/">Xah Lee</a> I can't recommend enough.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Design</span></span><br /><br />So I want two things: (i) To be able to push and pop marks locally to a buffer and (ii) to be able to pop marks globally. The later means that if I push marks in two different buffers and I do a global pop, the current buffer will change to the one with the latest mark.<br /><br />To do this, I used two datastructures: A hash table that maps a buffer name to its stack, and a global stack that keeps all the pushed positions.<br /><br />The first one looks like this:<br /><br /><pre name="code" class="lisp"><br />"marks.el" -> (1622 1042 1283)<br /></pre><br /><br /><pre name="code" class="lisp"><br />((1622 "marks.el") (1042 "marks.el") (194 "*Messages*") (1283 "marks.el"))<br /></pre><br /><br />In the global stack we keep the name of the buffer so we can move to it and remove the mark from the right stack.<br /><br />So, onto the code.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Code</span></span><br /><br />First we need a helper function to add the list to the hash if it doesn't exist already or push to the stack on an existing list<br /><br /><pre name="code" class="lisp"><br />(defun add-or-push (key value hash)<br />(if (gethash key hash)<br /> (progn<br /> (puthash key (cons value (gethash key hash)) hash))<br /> (progn<br /> (puthash key (list value) hash))))<br /></pre><br /><br />And some functions to clear the local and global stack should things go wrong.<br /><br /><pre name="code" class="Lisp"><br />(defun clear-push-mark-for-buffer ()<br />"Resets the buffer's stack"<br />(interactive)<br />(puthash (buffer-name) () local-mark-stack))<br /><br />(defun clear-global-push-mark ()<br />"Resets the buffer's stack"<br />(interactive)<br />(setq global-mark-stack '())<br />(maphash (lambda (kk vv) (puthash kk () local-mark-stack)) local-mark-stack)<br />)<br /></pre><br /><br />Now, the real code:<br /><br />For pushing, we just need one function that adds the current possition to both datastructures:<br /><br /><pre name="code" class="lisp"><br />(defun local-push-mark ()<br />"Pushes a the current point to a stack"<br />(interactive)<br />(if (boundp 'local-mark-stack)<br /> (progn<br /> (let (buffer point)<br /> (setq buffer (buffer-name))<br /> (setq point (point))<br /> (add-or-push buffer point local-mark-stack)<br /> (message "Pushed %d on %s" point buffer)<br /> (if (boundp 'global-mark-stack)<br /> (setq global-mark-stack (cons (list point buffer) global-mark-stack))<br /> (setq global-mark-stack (list point buffer)))))<br /> (progn<br /> (setq local-mark-stack (make-hash-table))<br /> (local-push-mark))))<br /></pre><br /><br />For popping, however, we need a function for the local stack and another for the global stack<br /><br /><pre name="code" class="lisp"><br />(defun local-pop-mark ()<br />"Pops the a mark from the current buffer's stack"<br />(interactive)<br />(let (stack)<br /> (setq stack (gethash (buffer-name) local-mark-stack))<br /> (if (and (boundp 'local-mark-stack) stack)<br /> (progn<br /> (goto-char (pop stack))<br /> (puthash (buffer-name) stack local-mark-stack)<br /> (setq global-mark-stack<br /> (remove (list (point) (buffer-name)) global-mark-stack)))<br /> (message "No marks to pop"))))<br /><br />(defun global-pop-mark ()<br />"Pops a mark from any buffer"<br />(interactive)<br />(let (pos buffer)<br /> (setq pos (car global-mark-stack))<br /> (setq buffer (nth 1 (car global-mark-stack)))<br /> (setq stack (gethash buffer local-mark-stack))<br /> (if (and (boundp 'global-mark-stack) stack)<br /> (progn<br /> (switch-to-buffer buffer)<br /> (goto-char (pop stack))<br /> (puthash buffer stack local-mark-stack)<br /> (setq global-mark-stack (remove (list pos buffer) global-mark-stack)))<br /> (message "No marks to pop"))))<br /></pre><br /><br />the only important detail to notice is that the global pop removes both from the local and global stacks. The rest should be self-explanatory.<br /><br />And we add a statement to provide the marks module<br /><br /><pre name="code" class="lisp"><br />(provide 'marks)<br /></pre><br /><br />So now, we just need to load the module and add some key bindings:<br /><br /><pre name="code" class="lisp"><br />(require 'marks)<br />(global-set-key (kbd "C-x <next>") 'local-push-mark)<br />(global-set-key (kbd "C-x <prior>") 'local-pop-mark)<br />(global-set-key (kbd "C-x S-<prior>") 'global-pop-mark)<br /></prior></prior></next></pre><br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Using it.</span></span><br /><br />If your using <a href="http://nicolas-lara.blogspot.com/2009/02/my-emacs.html">my .emacs</a> you just need to ckeck out the <a href="http://github.com/nicolaslara/emacs">code</a> and compile it.<br /><br />If not just copy everything up to " (provide "marks") " into a file called marks.el and load it in your .emacs.<br /><br />Enjoy.<br /><br /><span style="font-weight: bold;">Edit</span>: Apparently there's no lisp syntax support for the highlighter I'm using. sorry for that.nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-32710972997487452342009-11-04T23:56:00.008-04:302009-11-05T13:00:58.679-04:30My Pycon talk (Python Metaprogramming)If you followed the link on my previous post and looked at #64 you might have noticed I'll be giving a talk on Python Metaprogramming. Here's a sneak peak at what the talk will be like along with some comments.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Outline</span></span><br /><ul><br /><li> Metaprogramming:<br />A short explanation of what metaprogramming is, why it is needed and how it can save you time and effort.</li><br /><li>Metaprogramming Languages:<br /><br /> What languages are considered "metaprogramming languages" and what constructs do they provide to be considered as such. A 30000 ft view exploration of the metaprogramming features of languages like Lisp, Ruby, Perl, Javascript, Haskell and OCaml.</li><br /><li>Cool uses/examples of metaprogramming in other languages:<br /><br /> Some interesting examples of metaprogramming regardless of the language. These examples will be ported to Python at the end of the talk. I will go through this very fast just to show what we want to achieve in each example and what techniques are used by other programming languages to achieve this effects. A more detailed explanation will be done at the end of the talk by porting the examples to Python.<br /></li><br /><br /><li>Tools for metaprogramming in Python:<br /><br /> Each of the subsections of "Tools for metaprogramming in Python" should contain the following information:<br /><ul><br /><li>Explaination: short explaination</li><br /><li> Short example in Python</li><br /><li> An example of using the technique to port some othe language metaprogramming features</li><br /><li>Patterns: Common or useful patterns to incorporate that metaprogramming tool into your code</li><br /><li> Advantages, disadvantages and perils.</li></ul></li> </ul>The subsections I'll be covering are the following:<br /><ol><li>Code generation: eval() and exec():<br />The basics. Code Generation as strings and getting them to execute.<br /></li><br /><li>Python (A.K.A.: Python's data model):<br /> Exploring the flexibility of Python's data model: Duck-typing, special methods, attribute access, callable emulation, behaviour on operators.<br /></li><br /><li> Decorators:<br /> An introduction to decoratos and what can be achieved with them. Emphasis on decorator patterns.<br /></li><br /><li> Metaclasses:<br /> A basic introduction to metaclasses: What they are and when are they needed. Includes an idea of when can metaclasses be replaced by decorators.<br /></li><br /><li> types. Specially types.FunctionType:<br /> Exploring type objcts. Specially function objects, code attributes, locals, globals defaults and closures<br /></li><br /><li> Others: import hooks, ByteCode, etc:<br /> A seccion on other useful metaprogramming tools that might fit into the time frame of the talk. (this seccion might be included depending on the time or if there are in depth talks in pycon about somme of the above techniques that suggest cutting down on them in favour of other options)<br /></li><br /></ol><br /><li> Putting it all together:<br /> Just a pointer to a resourse that shows example code using most of the techniques shown throughout the talk. The example will probably be creating a DSL: possibly language generation (HTML, CSS, SQL or other), a generic problem solver or a small framework for distributed computation. I might take a lightning talk to go through this example in more detail.<br /></li><br /><br /><li>The Good, the Bad and the Ugly:<br /> A short conclusion about metaprogramming in Python. Why use it, when to use it, when to avoid it and what is python missing regarding metaprogramming that other languages have.<br /></li><br /><br /><span style="font-weight: bold;font-size:130%;" ><br />Alternative titles</span><br /><br />There are some alternative titles I'm considering for the talk. Any favourites?<br /><ul><li>Baddass Metaprogramming with Python (Thanks, Ahsanul)<br /></li><li> The swiss army knife for metaprogramming in Python</li><li>Metaprogramming tricks for Python programmers<br /></li><li> A zoo of Python metaprogramming tools</li><li> Tools and techniques for Python metaprogramming</li><li> Enhancing your code through metaprogramming</li><li> Python metaprogramming tricks for your toolbox</li></ul>nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com2tag:blogger.com,1999:blog-4150232295397368657.post-13944375679426561102009-11-04T23:28:00.005-04:302009-11-07T15:12:40.294-04:30Pycon 2010The list of <a href="http://us.pycon.org/2010/conference/talks/">scheduled talks for Pycon 2010</a> is out and they are looking very good. Thanks to all the <a href="http://us.pycon.org/2010/helping/">people</a> involved in making Pycon happen!<br /><br />I am specially fond of <a href="http://nicolas-lara.blogspot.com/2009/11/if-you-followed-link-on-my-previous.html">#64</a>. Go check it out!<br /><br />If you missed Pycon 2009 (I did), you can take a look at what went on <a href="http://us.pycon.org/2009/conference/talks/">here</a>.<br /><br />As for the <a href="http://nicolas-lara.blogspot.com/2009/11/blog-posting-month.html">Blog Posting Month</a> not all of my posts during the month will be like this. A real one is on the way. Promise!nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-82232228665551005842009-11-03T03:25:00.003-04:302009-11-07T15:12:32.540-04:30Blog posting monthNovember is said to be the <a href="http://www.nablopomo.com/">(Inter)National Blog Posting Month</a>. The idea is simple: 30 days - 30 posts. <br /><br />People that read this blog regularly would know that it hasn't been very active lately (More than 6 months without posting). That's just wrong. Let's change it. <br /><br />Keeping up with the Blog Posting Month should be a good motivator to start writing again. I give you that I am already a bit late as today is November 3rd, so I have some catching up to do. From the technical perspective expect stuff in the lines of: concurrency, new-ish programming languages, emacs, linux, comet, python, algorithms and optimization. However, technical posts take some time to prepare and though I have some half-cooked posts already that should be coming out this month do expect to read some lighter content during this month.<br /><br />That's it for now. Till tomorrow.nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-76347578210606898982009-04-20T17:48:00.003-04:302009-04-20T18:48:27.586-04:30GSoC projects I'm excited aboutToday the <a href="http://socghop.appspot.com/program/accepted_orgs/google/gsoc2009">list</a> of accepted projects for Google Summer of Code was made public. Here's the list of the top 25 projects that I'm personally excited about. Im adding an asterisk to those that either I'm really looking forward to use or that really blew my mind.<br /><br /><span style="font-weight: bold;">Boost</span><br /><ul><li> Graph Partitioning in The Boost Graph Library</li></ul><ul><li> Relations data type *</li></ul><ul><li> Boost.Python py3k support </li></ul><span style="font-weight: bold;">Django</span><br /><ul><li> Multiple Database Support in Django *</li></ul><ul><li> Model aware validation</li></ul><ul><li> UI improvements for the admin interface </li></ul><span style="font-weight: bold;">Debian</span><br /><ul><li> Large dataset manager </li></ul><span style="font-weight: bold;">GCC</span><br /><ul><li> Automatic parallelization in Graphite *</li></ul><span style="font-weight: bold;">Gentoo</span><br /><ul><li> Portage backend for PackageKit </li></ul><ul><li> Universal Select Tool *</li></ul><ul><li> Tree-wide collision checking and provided files database</li></ul><span style="font-weight: bold;">GIMP</span><br /><ul><li> Advanced GUI for brush dynamics (GIMP) </li></ul><span style="font-weight: bold;">Google open source programs</span><br /><ul><li> Build a distributed object-capability system on the Caja platform.</li></ul><span style="font-weight: bold;">Haskell</span><br /><ul><li> Improving space profiling experience </li></ul><span style="font-weight: bold;">GNU Project</span><br /><ul><li> Improve "sort" on multi-core systems</li></ul><ul><li> GDB - Python Scripting API Enhancements </li></ul><ul><li> Emacs GDB/MI migration </li></ul><span style="font-weight: bold;">KDE</span><br /><ul><li> Improving Search and Virtual Folders in KDE4 *</li></ul><ul><li> Plasma Media Center Components </li></ul><ul><li> New Widget Explorer </li></ul><ul><li> PlasMate Editor - An editor for Plasmoids, DataEngines and Themes </li></ul><span style="font-weight: bold;">Mozilla </span><br /><ul><li> Web pages over rsync **</li></ul><span style="font-weight: bold;">OpenCog</span><br /><ul><li> Python Interfaces For OpenCog Framework API</li></ul><ul><li> Natural Language Generation using RelEx and the Link Parser</li></ul><span style="font-weight: bold;">Python Software Foundation</span><br /><ul><li> Apache Axis2 extension for Jython</li></ul><br /><br />I know that there are a lot more great projects but I had to settle for 25. Which projects are you excited about and why?nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-49189095722521452832009-04-20T00:37:00.004-04:302009-04-20T01:38:32.830-04:30Spiral matrixToday I found a very interesting <a href="http://www.ocf.berkeley.edu/~wwu/riddles/cs.shtml">set of 'simple' problems</a>. It is a list of Berkeley University's "hardcore tech-interview style riddles and mathematical puzzles". I was specially interested in the Computer Science section (as you might have guessed) and, in particular, one problem caught my attention (probably because of the large matrix).<br /><br /><span style="font-weight: bold;font-size:130%;" >The problem</span><br /><br />The problem reads as follows:<br /><blockquote><br />Write a program that will display a "spiral" of NxN numbers, using constant space (no arrays allowed). For example, here's what the spiral looks like for N=10:<br /><pre><br /> 99 98 97 96 95 94 93 92 91 90<br /> 64 63 62 61 60 59 58 57 56 89<br /> 65 36 35 34 33 32 31 30 55 88<br /> 66 37 16 15 14 13 12 29 54 87<br /> 67 38 17 4 3 2 11 28 53 86<br /> 68 39 18 5 0 1 10 27 52 85<br /> 69 40 19 6 7 8 9 26 51 84<br /> 70 41 20 21 22 23 24 25 50 83<br /> 71 42 43 44 45 46 47 48 49 82<br /> 72 73 74 75 76 77 78 79 80 81<br /></pre><br /></blockquote><br /><br />Sounds simple enough.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">The solution</span></span><br /><br />As I've been reading a lot of "Real World Haskell" lately (and considering the language is great for the task at hand) I decided to code this program in Haskell. If you don't already know Haskell I recommend you to go and learn it on your free time. It is an excellent language with a very unorthodox view of programming (not only functional, but pure!) that will open your mind to a very new and interesting programming style. A good resource for learning Haskell (besides the book, which I highly recommend and will do so with further details in a future post about books) is the classical <a href="http://haskell.org/tutorial/">Gentle introduction to Haskell</a>. But if you prefer a nice colourful website with cool drawings and good info to match the cool design (I know I do!) you can check <a href="http://learnyouahaskell.com/introduction">Learn you a Haskell for great good</a>.<br /><br />Enough with the language. Into the problem.<br /><br />To analyse the solution I enumerated some of the matrices, from which matrices of size 4 and 5 were the most useful<br /><pre><br />15, 14, 13, 12,<br />4, 3, 2, 11,<br />5, 0, 1, 10,<br />6, 7, 8, 9<br /></pre><br /><pre><br />24, 23, 22, 21, 20,<br />9, 8, 7, 6, 19,<br />10, 1, 0, 5, 18,<br />11, 2, 3, 4, 17,<br />12, 13, 14, 15, 16<br /></pre><br /><br />A matrix of size n contains the numbers from n*n-1 to 0. So the next matrix will contain 2n-1 new elements and the rest will be the same elements in a different order. This gives us the idea that the algorithm can be solved recursively.<br />If we look with more detail into the two matrices outlined above, we can notice that the top row and rightmost column contains all the new elements and that, due to the spiral ordering described in the problem, they will always be located in these positions (there are 2n-1 slots there).<br /><br />What's left is to figure out how the elements in the previous matrix map to those in the next one and we'll have ourselves a recursive algorithm. We can notice that the first element in the matrix of size 4 is the last element in the sub-matrix formed by removing the new elements from the matrix of size 5. Because of the spiral order the next element to the right in the old matrix becomes the next to the left in the new one and the element that was beneath a number is transposed above it. <b>We can see it as a 90 degree rotation on the old matrix</b>.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">The code</span></span><br /><br />Knowing this all that's left is to write the code.<br />We will need a function that given the position in the n-sized matrix will return the element<br />that belongs to that position.<br /><br /><pre name="code" class="haskell"><br />spiral :: Int -> Int -> Int -> Int<br />spiral 0 j n = n*n - 1 - j<br />spiral i j n<br /> | j == (n-1) = n*n - n - i<br /> |otherwise = spiral (n-1-i) (n-j-2) (n-1)<br /></pre><br /><br />The first line of this function (after the signature) is one of our base cases: The top row of the matrix is formed by the numbers from (n*n)-1 to n*(n-1). The second definition our second base case: the rightmost column. In this case each element descends from the element in the top right corner (i.e.: n*(n-1) ) one number by row. The rest of the function (the otherwise clause) is our recursive case. On the matrix of size n-1, we are interested in the element that occupies the row n2-i where n2 is the size of the smaller matrix (i.e.: n-1) and the column n2-j-1. Note that the difference between the row and the column is that in the column case we need to substract an extra 1 which refers to the extra columns that appears in the larger matrix. If we don't do this, the transformation would be transposed to the right.<br /><br />Extra<br /><br />This code is enough to solve the problem. But to better calculate the results (without having to calculate each index at a time) I provided some extra functions.<br /><br /><pre name="code" class="haskell"><br />-- claculates an index based on the previous matrix<br />spiral :: Int -> Int -> Int -> Int<br />spiral 0 j n = n*n - 1 - j<br />spiral i j n<br /> | j == (n-1) = n*n - n - i<br /> |otherwise = spiral (n-1-i) (n-j-2) (n-1)<br /><br />-- returns the numbers from 0 to n-1<br />range :: Int -> [Int]<br />range n = take n (iterate (1+) 0)<br /><br />-- returns every possible index of an NxN matrix<br />matrix :: Int -> [(Int,Int)]<br />matrix n = [(i,j) | i<-range n, j<-range n] -- a helper function for the map in printSpiral revSp :: Int -> (Int, Int) -> Int<br />revSp n (i,j) = spiral i j n<br /><br />-- returns the result for each index<br />printSpiral :: Int -> [Int]<br />printSpiral n = map (revSp n) (matrix n)<br /><br />-- calculates all spiral matrices from 0 to n<br />through :: Int -> [[Int]]<br />through n = map printSpiral (range (n+1))<br /></pre><br /><br />Does anyone have a better (or different) solution?nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com5tag:blogger.com,1999:blog-4150232295397368657.post-49518102196402220962009-02-28T19:10:00.006-04:302009-02-28T19:50:22.781-04:30Publishing an emacs bufferYes, another emacs post, in row, but I found this so amazingly cool that I couldn't just keep quiet.<br /><br />I told myself today: "It would be cool if I could convert what is rendered in an emacs buffer to html so I can show it to others". Of course, some people had already beaten me to it.<br /><br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Making it happen</span></span><br />I used an emacs add-on by <a htef="http://www.xemacs.org/People/hrvoje.niksic/">Hrvoje Niksic</a> called <a href="http://www.emacswiki.org/emacs/Htmlize">htmlize</a>. It does all the hard work, and it does it very well.<br /><br />Still, I wanted a one key solution to publish it. So I just coded these small emacs-lisp functions:<br /><br /><pre style="color: #bebebe; background-color: #262626; font-size: 8pt"><br />(<span style="color: #afeeee; font-weight: bold;">defun</span> <span style="color: #7fffd4; font-weight: bold;">publish-buffer-to</span> (file)<br /> <span style="color: #87cefa;">"Converts buffer to html and writes it to file"</span><br /> (interactive <span style="color: #87cefa;">"Ffile: "</span>)<br /> (<span style="color: #afeeee; font-weight: bold;">require</span> '<span style="color: #98fb98;">htmlize</span>)<br /> (<span style="color: #afeeee; font-weight: bold;">save-excursion</span><br /> (<span style="color: #afeeee; font-weight: bold;">with-current-buffer</span> (htmlize-buffer (current-buffer))<br /> (write-file file)<br /> (kill-buffer (current-buffer))))<br /> (message (concat <span style="color: #87cefa;">"current buffer contents published to "</span> file)))<br /><br />(<span style="color: #afeeee; font-weight: bold;">defun</span> <span style="color: #7fffd4; font-weight: bold;">publish-buffer</span> ()<br /> <span style="color: #87cefa;">"Converts buffer to html and writes it to ~/public_html/emacs.html"</span><br /> (interactive)<br /> (publish-buffer-to <span style="color: #87cefa;">"~/public_html/emacs.html"</span>))<br /></pre><br />(snnipets provided by htmlize! =) )<br /><br />Now all that was left was to provide a simple key shortcut. <br /><br /><pre style="color: #bebebe; background-color: #262626; font-size: 8pt"><br />(global-set-key [f7] 'publish-buffer)<br /></pre><br /><br />And thanks to Ruslan Spivak's <a href="http://ruslanspivak.com/2007/08/18/htmlize-your-erlang-code-buffer/">code</a> I could also add an easy way to create code snippets out of regions.<br /><br />So now I can easily share my emacs buffers not only on my local server but on my blog =).<br /><br />Apparently there's <a href="http://rtfm.etla.org/emacs/htmlfontify/">another module</a> to do this that might be added to emacs soon, but for now I'm very happy with this solution.<br /><br />In the future, I'd like to integrate this with tramp and add better file management support so I can seamlessly post to a remote server. I would also like to make it autoreload so it can track live changes, but we'll see.<br /><br /><span style="font-style:italic;">If you liked this, you can check out <a href="http://nicolas-lara.blogspot.com/2009/02/my-emacs.html">my .emacs</a></span>nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com2tag:blogger.com,1999:blog-4150232295397368657.post-7452275191566958772009-02-22T12:55:00.005-04:302009-02-28T17:19:07.186-04:30My .emacsI have been delaying this post for quite a while. I've been waiting until my .emacs file is "complete". Today, I realised it is never going to be complete. So here's a few notes regarding my emacs configuration and how you can use it.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Order</span></span><br /><br />I must confess, a few weeks back my emacs configuration consisted of one HUGE file and a few emacs lisp files scattered in a directory. Also, half of the tools and modes I used were installed in a system wide manner via the OS's packaging system. ...A mess.<br />I decided to put some order (beauty?) to it. So now my .emacs file is 9 non-comment non-whitespace lines and the rest of the configuration is well distributed several different in appropriately named files and directories. With all tools included it is 535149 LOC.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Mobility (sort of)</span></span><br /><br />I love working in emacs so much that I consider most other editing options a pain. I've even considered implementing emacs-lisp in javascript so I can turn every textarea into a fully functional emacs buffer (this is way down in my list of personal-projects-i-will-do-someday due to its complexity and my lack of free time)<span style="font-style: italic;">[1]</span>.<br /><br />Being a little more realistic, I decided just to put my .emacs in a git repo that I could access everywhere and which included all the things I normally use when developing (or writting in general). This way I could have all my tools everywhere customized the way I want them.<br />With this approach installing new tools (like JDEE) becomes a little more complicated because they are commonly packaged to be installed in a system wide manner. Also, I cannot use my OS packaging system. But the upside of having everything in one places pays off.<br /><br />So, why does it say "sort of" in the title? Well, some of the tools (the ones that need non-emacs-lisp components) are compiled for my system (A 64-bit Arch Linux box). So you might have problems with them if you just clone my emacs repo in a different system.<br />What can go wrong? Mostly there might be problems with JDEE and AucTex. But besides that I don't see much that could go wrong in a unix system.<br /><br /><span style="font-size:130%;"><span style="font-weight: bold;">Goodies</span></span><br /><br />There are not many new and amazing things. So here's a non-exhaustive list of stuff I use every day:<br />* Color themes<br />* git support<br />* JDEE<br />* Auctex<br />* ECB<br />* word-to-emacs (open .doc files in emacs)<br />* some modes: (java, haskell, erlang, javascript, etc)<br />* some key-bindings:<br /> * C-x p: go to matching paren<br /> * f9: cross highlight (line and column)<br /> * f11: fullscreen<br /> * f10: remove scrollbar (combined with f11 it makes a great fullscreen experience =) )<br /> * M-<up>/ M-<down>: move line up/down<br /> * f8: make frame on display<br /> * f5: go-to-line<br />* enhanced clipboard interaction<br />* in place annotations (I'd like to make this one better)<br />* automatic backups<br />* tramp<br />* everything else that I forgot<br /><span style="font-weight: bold;font-size:130%;" ><br />What's missing</span><br /><br />Currently I am missing:<br />* Slime (I haven't used Lisp in quite a while, but I'd like to start using it again. Wait for my Clojure exploration)<br />* Better Python support. The default mode is very good. But I'd love to have more advanced stuff like Ropemacs.<br />* Bookmarks. A personal project I might add soon.<br />* Probably some stuff I'm forgetting<br /><span style="font-weight: bold;font-size:130%;" ><br />Sharing</span><br /><br />I very often get asked by firends for my .emacs file (or updates from older ones). So here's a way anyone can go and use my emacs configuration:<br />Go to github and get a copy of my emacs repo:<br /><pre name="code" class="bash"><br />> git clone git://github.com/nicolaslara/emacs.git ~/elisp<br />> ln -s ~/elisp/.emacs ~/.emacs<br /></pre><br /><br />It doesn't go without a disclaimer: This is, and will always be, an incomplete project. Though it probably is portable, it is made for my personal use and there is no guarantee it will work in different non-linux setups.<br /><br />Now, I'd love to make this even more portable and add different tools to it. So if anyone have a problem or suggestion I'd love to hear it. I would, of course, like it better if the suggestions come with a link to a fork of the project where the problems are fixed and I can just pull it ;)<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">Comments</span></span><br /><br />So, Whats the emacs feature you like the most? Which one amazes you the most? anything you couldn't live without? What do you miss from other text editors when working in emacs?<br /><br /><span style="font-weight: bold; font-style: italic;">Notes</span><br /><br /><span style="font-style: italic;">[1]</span> The folks at Mozilla labs have done a very nice contribution to the online editing world with Bespin. I hope they keep on the good work and turn to project into something emacs-like for the web.nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com3tag:blogger.com,1999:blog-4150232295397368657.post-28453605383481761642009-02-19T13:14:00.005-04:302009-11-13T10:29:34.192-04:30AcronymsIn the last post I mentioned the book Programming Pearls. In the second chapter, Jon Bentley presents a simple, but interesting problem: Given a list of words, group those that are acronyms together.<br /><br />If you don't know what acronyms are, it is simply a words formed from the initial letters of others. For instance, the words "pot" and "top" are acronyms; so are the words "slow" and "owls".<br /><br />When I read it, I thought "This could be done with unix tools and pipes". Actually, I didn't find a way of doing it efficiently with native unix tools. The reason being that there's no horizontal sort implementation in unix. You could write something like this:<br /><br /><pre class="bash" name="code"><br />for i in `cat dict | sed 'p' | sed 'N;s/\n/*-/g'`; do echo $i | <br />cut -d "*" -f 2 | sed "s/\(.\)/\1-/g" | tr "-" "\n" | sort | <br />tr -d "\n"; echo "$i" | cut -d "*" -f 2 ; done | sort<br /></pre><br /><br />But it won't be very efficient and it's very ugly. I didn't spend too much time thinking of a better way to do it unix-style. If you have one, please post it on the comments =)<br /><br />Instead, I wrote a small python script<br /><br /><pre class="python" name="code"><br />#!/usr/bin/env python<br />import sys<br /><br />if __name__ == '__main__':<br /> f = open(sys.argv[1])<br /> for line in f.xreadlines():<br /> line = line.strip()<br /> print '%s-%s' % (''.join(sorted(line)), line)<br /></pre><br /><br />and I executed:<br /><br /><pre class="bash" name="code"><br />./expand.py dict2 | sort<br /></pre><br /><br />which runs in about 0.47 seconds. Then, we could add another step to pretty print the acronyms, but I wasn't interested in that. <br /><br />Unfortunately, the only thing that remains 'unix' about this solution is the use of sort and one pipe. This post is not so much to show my findings but to look for a better solution. Does anyone have a suggestion?nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-40002251949032991372009-01-31T16:57:00.003-04:302009-02-01T11:42:38.727-04:30PermutationsThis last week I happened to have the necessity of generating all the possible permutations of an array. This seems to be a fairly easy task but many programmers won't come up with a simple solution to this problem very fast. There is at least one intuitive, recursive, solution to this problem, many more complex but *slightly* more efficient, iterative, solutions and no really time-efficient solution. After all, the problem is to generate n! orderings of an array so we, at least, have to visit each one once.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">The well-known solution</span></span><br /><br />The most widely spread solution to this problem is the Dijkstra algorithm for generating the next permutation. It is based on the assumption that there is a total order between the elements of the array and the elements of the array are unique (there are no repetitions). If these conditions are met, the algorithm always generates the next permutation in lexicographical order.<br /><br />The algorithm is very straight forward and goes as follow:<br /><pre name="code" class="python"><br />def get_next(a):<br /> N = len(a)<br /> i = len(a)-1<br /><br /> while a[i-1] >= a[i]:<br /> i -= 1<br /><br /> j = N<br /><br /> while a[j-1] <= a[i-1]:<br /> j -= 1<br /><br /> a[i-1], a[j-1] = a[j-1], a[i-1]<br /><br /> i += 1<br /> j = N<br /><br /> while i < j:<br /> a[i-1], a[j-1] = a[j-1], a[i-1]<br /> i+=1<br /> j-=1<br /><br /> return a<br /><br /></pre><br /><br />To use this algorithm to generate every possible permutation we just call it n! times:<br /><pre name="code" class="python"><br />def dijkstra(a):<br /> import operator<br /> fact = reduce(operator.mul, range(1,len(a)+1))<br /> the_list = [copy(a)]<br /> for i in range(fact-1):<br /> a = get_next(a)<br /> the_list.append(copy(a))<br /><br /> return the_list<br /></pre><br /><br />the only possibly uncommon thing here is line 3 which is a functional-style factorial function.<br /><br />This works very well for generating the permutations of n (the permutations of the array [0..n-1]) but it won't work for arrays of arbitrary elements. So we explore other options.<br /><span style="font-size:130%;"><br /><span style="font-weight: bold;">The known recursive solution</span></span><br /><br />There's a (not-so-well-)known recursive solution to solving the permutation problem. It is known as the HeapPermute algorithm or Heap's algorithm for permuting an array.<br />My python implementation of the algorithm goes as follow:<br /><pre name="code" class="python"><br />def heap_aux(a, n, the_list):<br /> if n == 1:<br /> the_list.append(copy(a))<br /> else:<br /> for i in range(n):<br /> heap_aux(a, n-1, the_list);<br /><br /> if n % 2 == 1:<br /> a[0], a[n-1] = a[n-1], a[0]<br /> else:<br /> a[i], a[n-1] = a[n-1], a[i]<br /><br /><br />def heap(a):<br /> the_list = []<br /> heap_aux(a, len(a), the_list)<br /> return the_list<br /></pre><br />This algorithm works very well and it is very efficient too but it generates the permutations in an order that I find particularly disturbing.<br />Also it is not as easy to understand as I would like.<br /><br />Enter my recursive solution<br />This is probably the most straight forward solution I could come up with. It is a clasical recursive design.<br />Want to permute an array of n elements? How would you do it if you already had a function to solve the problem for a smaller array?<br />Simple. Select each possible element of the array to be "the first element of the permutation" and then permute the rest of the array:<br />A permutation of 1,2,3,4 would be:<br />1 + permutation_of(2,3,4)<br />2 + permutation_of(1,3,4)<br />3 + permutation_of(2,1,4)<br />4 + permutation_of(2,3,1)<br /><br />Simple, right?<br /><br />Let's code it:<br /><pre name="code" class="python"><br /> for j in range(i, len(a)):<br /> a[i], a[j] = a[j], a[i]<br /> permutation(a, i+1, the_list)<br /> a[i], a[j] = a[j], a[i]<br /></pre><br />This loop captures the essence of the procedure described above. We have to remember to put the elements back where they were after the recursive call to allow next iteration to work. Not doing so would result in swapping the wrong element in the next iteration.<br /><br />Puting it all together (and adding a small optimization):<br /><pre name="code" class="python"><br />def perm_aux(a, i, the_list):<br /> if i == len(a):<br /> the_list.append(copy(a))<br /> else:<br /> perm_aux(a, i+1, the_list)<br /> for j in range(i+1, len(a)):<br /> a[i], a[j] = a[j], a[i]<br /> perm_aux(a, i+1, the_list)<br /> a[i], a[j] = a[j], a[i]<br /><br /><br />def permutate(a):<br /> the_list = []<br /> perm_aux(a, 0, the_list)<br /> return the_list<br /></pre><br />This algorithm generates the list in a nicer order (though it's not lexicographical). And as its predecessor is quite efficient (taking into account the complexity of the problem).<br /><span style="font-weight: bold;font-size:130%;" ><br />Performance</span><br />Normally recursive algorithms are put down for performance reasons: They keep all local variables stored in the stack while the other recursive calls are made and have to incur in function calling overhead. In the case of these two algorithms the good thing is that the recurtion depth is not proportional to the size of the problem solution but to the size of the array (actually it is exactly as deep as the array's length). Also, if the list variables are passed by reference (this is programming language specific), only the reference to the variable needs to be stored in the stack and there is no overhead of coping the variables on every call.<br />It will probably never be as efficient as their iterative counterparts but for me readability (with small performance penalties) definitely pays off.<br /><br />To measure the times I used the following python decorator:<br /><pre name="code" class="python"><br />def timing(func):<br /> def inside(*args):<br /> t1 = time.time()<br /> res = func(*args)<br /> t2 = time.time()<br /> print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)<br /> return res<br /> return inside<br /></pre><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv8LA3-wgMvbyFk4-UjC5GQ24mD0SmYMuJATMXvn_ngoNGaiNtGqCT-CfBi-ruTzQpPG7DY4lR3p0ZiwSfeqMuzQWJzW3zZYyxnKrLciQ_zPg7sypi3nTiPpiTYjesnY1Oh7GwfiBnFLzG/s1600-h/norm.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 214px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiv8LA3-wgMvbyFk4-UjC5GQ24mD0SmYMuJATMXvn_ngoNGaiNtGqCT-CfBi-ruTzQpPG7DY4lR3p0ZiwSfeqMuzQWJzW3zZYyxnKrLciQ_zPg7sypi3nTiPpiTYjesnY1Oh7GwfiBnFLzG/s320/norm.png" alt="" id="BLOGGER_PHOTO_ID_5297570902174957346" border="0" /></a><br /><br />Given the complexity of the problem, the graph grows rapidly out of scale. So a graph in logarithmic scale is in order<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC6zVnAjYX-0de3kjBNSRdjxPl7KBULfnp4U0bJsh4Q6fB6WJaFfW1q-gpR3ch8L8ww6U689xssE4oL3Qk9CtgbOkrd79JEu9zf6LpWAY1HLg7ZEqPKqtc6iDZLEHXO1JQwRQlx04UxuOL/s1600-h/log.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 212px;" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiC6zVnAjYX-0de3kjBNSRdjxPl7KBULfnp4U0bJsh4Q6fB6WJaFfW1q-gpR3ch8L8ww6U689xssE4oL3Qk9CtgbOkrd79JEu9zf6LpWAY1HLg7ZEqPKqtc6iDZLEHXO1JQwRQlx04UxuOL/s320/log.png" alt="" id="BLOGGER_PHOTO_ID_5297571279821384258" border="0" /></a><br /><br />As you can see the algorithms behave very similarly. The largest difference (for an array of size 9) between the fastest (heap) and the slowest (permute) is 0.6 seconds. This of course will grow with the array size, but in a linear instead of exponential manner.<br /><br /><br />Have another solution to this problem? comment on! =)nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com8tag:blogger.com,1999:blog-4150232295397368657.post-24259892033137134232009-01-30T18:55:00.005-04:302009-01-30T19:03:06.147-04:30sed one-linersSed never ceases to amaze me. But I was specially amazed by the fact that "sed is turing complete". Check out <a href="http://www.catonmat.net/blog/sed-one-liners-explained-part-one">this</a> useful sed commands that'll make your life a lot easier!.nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-21649449769992947862009-01-16T12:28:00.003-04:302009-01-24T12:33:47.008-04:30Django gets aggregation support!As for <a href="http://code.djangoproject.com/changeset/9742">Changeset 9742</a> Django gets aggregation support. For those of you that don't know, I worked in this project as part of Google Summer of Code and I'm very glad to see this finally coming true!. <br /><br />I also wanted to thank Russell Keith-Magee for mentoring me throughout the project and working in the code after GSoC was finished, Malcolm Tredinnick for giving amazing code reviews during the whole SoC and the many others that worked in getting this done.<br /><br />I encourage you to check it out. The <a href="http://docs.djangoproject.com/en/dev/topics/db/aggregation/#topics-db-aggregation">documentation</a> is a great start! =)nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-6191254685239770632009-01-05T01:58:00.017-04:302009-01-06T12:36:22.981-04:30Emulating Ruby blocks in PythonThere are some Ruby features I like a lot. A handful of them are borrowed from other languages (like lisp or perl), but the <a href="http://www.ruby-lang.org/en/about/">Matz</a> found a way of making the language a very nice and powerful combination of them. I've been using Ruby lately and got thinking on how could I implement one of Ruby's most beloved features, blocks, in Python (remember, "imitation is the sincerest form of flattery"). As it turns out, it is not all that hard. Here's what I came up with:<br /><br />But before that...<br /><span style="font-weight: bold;font-size:130%;" ><br />On Ruby blocks</span><br /><br />Blocks in ruby provide a way of creating functions that act on a code block defined later on.<br />An example of blocks in ruby is the following:<br /><pre name="code" class="ruby"><br />array = [1, 2, 3, 4]<br />array.each { |n| puts n ** 2 }<br />1<br />4<br />9<br />16<br /></pre><br />According to their site: "A block is like an anonymous function or lambda [and] the variable between pipe characters is the parameter for this block". What's missing from this description is that ruby also provides the syntactic sugar to create functions that receive blocks using the "yield" statement. In other words, it is a way of creating closures and attaching them to other methods. Using closures in ruby comes very easily even for people that donsn't know what a closure is. If we were to implement the previous behaviour ourselves we would do something like this:<br /><br /><pre name="code" class="ruby"><br />class Array<br /> def each2<br /> for i in self<br /> yield(i)<br /> end<br /> end<br />end<br /><br />array = [1, 2, 3, 4]<br />array.each2 { |n| puts n ** 2 }<br />1<br />4<br />9<br />16<br /></pre><br /><br />I won't go into details because there is a lot of documentation on ruby blocks out there.<br /><br />So, onto Python...<br /><br /><span style="font-weight: bold;font-size:130%;" >Design</span><br />The Python "builtin" that resembles the most to blocks is that of <a href="http://www.python.org/dev/peps/pep-0343/">PEP343</a>, the with statement; but I wanted something that immitetad the ruby syntax as much as possible. The with statement is nice, but it doesn't cover all the cases.<br /><br />So I decided to use a decorator to convert the function that uses the "block" into something that receives the block, inserts it into the namespace, and execute the original function with the block as a corutine.<br /><br />The idea was something like this:<br /><pre name="code" class="python"><br />@receive_block<br />def simple_iterate():<br /> for i in [1,2,3]:<br /> print block()<br /><br />@simple_iterate<br />def _():<br /> return "a"<br /></pre><br />This copies the Ruby syntax except for the receive_block decorator, but I considered it a reasonable sacrifice.<br />Using "def _()" leaves the function as anonymous and allows you to specify parametrs for the block.<br /><span style="font-weight: bold;font-size:130%;" ><br />Implementing blocks in Python</span><br />So, to implement the syntax I just need to write the <span style="font-style: italic;">receive_block</span> decorator.<br />The objective of this decorator is to convert the block receiving function, A, into another decorator that receives a function, B, introduces B into A's scope and subsequently calls A.<br />The key step is to add the block function to the scope. To do this we use Python's builtin <span style="font-style: italic;">types</span> module. It includes the FunctionType method which creates a function object.<br /><pre name="code" class="python"><br />types.FunctionType(func.__code__, scope)<br /></pre><br />There is more to this method than what we use here, but I won't go into details about the method since we only need the simplest use of it.<br />Once we know this, the decorator is pretty simple:<br /><pre name="code" class="python"><br />import types<br /><br />def receive_block(func):<br /> def decorator(block):<br /><br /> # Add block to globals<br /> scope = func.func_globals #globals()<br /> scope.update({'block':block})<br /><br /> #create the function with the new scope<br /> new_func = types.FunctionType(func.__code__, scope)<br /><br /> return new_func()<br /><br /> return decorator<br /></pre><br /><br />Lets see how it works:<br /><pre name="code" class="python"><br />@receive_block<br />def external():<br /> for i in [1,2,3]:<br /> print block()<br /><br />print "External"<br />@external<br />def _():<br /> return "a"<br /></pre><br />This will print<br /><pre name="code" class="python"><br />External<br />a<br />a<br />a<br /></pre><br />And if we add a parameter:<br /><pre name="code" class="python"><br />@receive_block<br />def param_external():<br /> for i in [1,2,3]:<br /> print block(i)<br /><br />print "External with param"<br />@param_external<br />def _(i):<br /> return "a " + unicode(i)<br /></pre><br />It, as expected, prints:<br /><pre name="code" class="python"><br />External with param<br />a 1<br />a 2<br />a 3<br /></pre><br />But what if we wanted to implement something like ruby's Array class? Lets create an Array class that extends the builtin list type and see what happens.<br /><pre name="code" class="python"><br />class Array(list):<br /> @receive_block<br /> def each(self):<br /> for i in self:<br /> print block(i)<br /></pre><br />When calling<br /><pre name="code" class="python"><br />a = Array([1,2,3,4])<br /><br />print "Each Square"<br />@a.each<br />def _(x):<br /> return x**2<br /></pre><br />we get the exception:<br /><pre name="code"><br />decorator() takes exactly 1 argument (2 given)<br /></pre><br />because the instance method takes <span style="font-style: italic;">self</span> as the first argument.<br />So we modify our initial decorator to work with instance methods:<br /><pre name="code" class="python"><br />def receive_block(func):<br /> def decorator(*args):<br /> if len(args) == 1:<br /> block, = args<br /> instance = None<br /> elif len(args) == 2:<br /> instance, block = args<br /><br /> # Add block to globals<br /> scope = func.func_globals #globals()<br /> scope.update({'block':block})<br /><br /> #create the function with the new scope<br /> new_func = types.FunctionType(func.__code__, scope)<br /><br /> if instance:<br /> return new_func(instance)<br /> else:<br /> return new_func()<br /><br /> return decorator<br /></pre><br />This modification is pretty straight forward. So I won't explain it because it speaks for itself.<br /><br />Lets write some functions:<br /><pre name="code" class="python"><br />class Array(list):<br />@receive_block<br />def each(self):<br /> for i in self:<br /> print block(i)<br /><br />@receive_block<br />def collect(self):<br /> for (i, value) in enumerate(self):<br /> self[i] = block(value)<br /><br />@receive_block<br />def handled(self):<br /> for i in self:<br /> try:<br /> block(i)<br /> except:<br /> print "This raised an exception"<br /></pre><br />and pass them some blocks:<br /><pre name="code" class="python"><br />a = Array([1,2,3,4])<br /><br />print "Each Square"<br />@a.each<br />def _(x):<br /> return x**2<br /><br />print "Each"<br />@a.each<br />def _(x):<br /> return x<br /><br />print "Collect"<br />@a.collect<br />def _(x):<br /> return x**2<br /><br />print a # a is changed<br /><br />print "Handled"<br />@a.handled<br />def _(x):<br /> if x != 9:<br /> raise Exception("this won't work")<br /> else:<br /> print "this works"<br /></pre><br />We, then, obtain the desired output:<br /><pre name="code"><br />Each Square<br />1<br />4<br />9<br />16<br />Each<br />1<br />2<br />3<br />4<br />Collect<br />[1, 4, 9, 16]<br />Handled<br />This raised an exception<br />This raised an exception<br />this works<br />This raised an exception<br /></pre><br /><br />It works. =)<br /><br />Another interesting way to do this would have been to add the block variable as a free variable of the function and have the code object reference it. In Python, when a closure is created the free variables are stored in an attribute of the function's code object and it's values are stored in the function itself using the cell type. Take this closure as example:<br /><pre name="code" class="python"><br />def test():<br /> a = 10<br /> b = lambda x: x+2<br /> def inner():<br /> print a, b(a)<br /> return inner<br /></pre><br /><br /><pre name="code" class="python"><br />>>> i = test()<br />>>> i.func_code.co_freevars<br />('a', 'b')<br />>>> i.func_closure<br />(< cell int object at 0x802400 >,<br />< cell function object at 0xf68848 >)<br /></pre><br />Adding the closure to the new function should be easy, since FunctionType accepts a closure keyword argument to do so. Unfortunately, the code's co_freevars attribute is read only:<br /><pre name="code" class="python"><br />>>> i.func_code.co_freevars += ('block',)<br />TypeError: readonly attribute<br /></pre><br />If anyone, who knows better than I do, cares to provide an implementation using closures I'd love to hear your solutions.<br /><br />So this is how we implement Ruby-style blocks in Python using decorators. Hope you enjoyed it.<br /><br /><span style="font-weight: bold;font-size:130%;" ><br />Disclaimer</span><br />This is by no means meant to be used in a production environment. Not even in a semi-serious environment. It is just a hack to demonstrate the how this could be done and it hasn't been tested.<br /><br /><span style="font-weight: bold;font-size:130%;" ><br />Other notes</span><br />* The code for this project is hosted in <a href="http://github.com/nicolaslara/blocks/tree/master">http://github.com/nicolaslara/blocks/tree/master</a><br />* I wanted to implement some of the builtin Ruby functions that use blocks but I didn't have the time. If somebody is up to the task I'd love to see what interesting things could be done with this.<br />* Also, if somebody is willing to improve the code you are more than welcome.<br />* Some of the problems of this code:<br />-It clutters the global namespace.<br />-The word "block" is introduced as a global reserved word.<br />* For some reason blogger doesn't let me edit this site's template in 2009, so I couldn't add code syntax highlighting.nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com8tag:blogger.com,1999:blog-4150232295397368657.post-85826351536906605532008-12-30T12:08:00.001-04:302008-12-30T12:42:19.569-04:30Doing it right!(or "my primer on studying computer science the right way")<br /><br />For those of you how don't know it, I'm a CS major and am currently finishing the last three months of my career. I've been looking back at the whole five years of cs curriculum and noticing what I did right, what I should have done right and, specially, what I started to do right late and wish someone would have told me to do right from the beginning. So here is my advice to those staring to study for a computer science degree. I will not categorize all of these ideas according to how I did or didn't do them. Instead, I'll elaborate on what they actually mean, why I think they're important and how to do them effectively.<br /><br /><span style="font-weight: bold;font-size:130%;" >Motivation</span><br />One would expect that after completing a degree in computer science people would be very well acquainted with the different aspects of the discipline. Moreover, they should be fluent in many programming language, understand the inner workings of a computer and of operating systems, know the advantages and disadvantages of different implementation decisions in programing language design, understand (and apply) algorithm complexity analysis, know several data structures and abstract data types along with their uses and implementations, understand networks and network software, just to name a few. This list could go forever, but besides knowing subjects related to the CS curriculum one would expect a computer science newly grad to be aware of different tools to improve productivity (i.e. not to code in notepad), to be able to work their way through unix, to strive for software quality, to be curious about different/new approaches to problem solving (like alternatives to sockets that make distributed programming suck less), do testing, be able to design correct and efficient algorithms, use version control; again, just to name a few.<br />Unfortunately, many people can get through their career without actually knowing more than shallow information on all of those subjects (and I mean those explicitly in the career program, many people have probably never even heard of subversion or grep or emacs). Some might claim the problem is in the education system. I personally believe that, even if the education system do have many problems, the causes are lack of curiosity, lack of motivation or lack of information.<br />"The information is out there!" you might say, and you would be right, but it is very hard to actually find it if you don't know what you're looking for. This is the case of the freshmen which, with curiosity of motivation, could actually find the information to start doing computer science "right" but who might also just need to discover this information first to start building their curiosity and getting motivated. I could very well be a problem in the education system in general but I will not address that issue here (at least not in this post). Today I'll focus in what I believe could help you obtain the right information to start doing it right.<br /><br /><span style="font-weight: bold;font-size:130%;" >But I just want to learn to program, do I also need to do/learn all this stuff?</span><br />Short answer: yes.<br />Long answer: yes, but go get a CS degree. I am not saying that you *need* a CS degree to be a programmer. I'm not even saying you need the degree to excel at it. But certainly most people do. What you *do* need to be a programmer is training in discreet mathematics, algorithms, data structures, group theory, machine architecture, probabilities, set theory, logic, amongst many others which, again, I will not list. Sure, some people could teach themselves all these things, but most people can't. And even if you can, why not get the degree while you're at it?<br />Anyway, I phrase this article talking about computer science majors but it is as valid for anyone wanting to take programming, technology or computation, in general, seriously.<br /><br /><span style="font-weight: bold;font-size:130%;" >For whom is this intended</span><br />These tips are not necessarily for you. This article is intended for those interested in tackling the art of programming or designing programs. If you want to work as a manager, a company spokesman or at selling software (not making it), you probably won't need any of this. If you, on the other hand, are interested in creating good software, whether your are a cs major or not, then read on for a list of what, to my understanding, is a good set of advices to becoming better at it.<br /><span style="font-weight: bold;font-size:130%;" ><br />Advices</span><br /><span style="font-weight: bold;">* Learn (many) different languages</span><br />This is probably one of the most important items in this list. If I hear somebody telling me "I only know C and Java", I read between the lines "You don't actually have any real interest in programing. You probably were never interested in learning things deeper than what they showed you in your courses". If they add "And, well, I once used Scheeme (or Haskell) for my programming languages course, but nobody uses that kind of languages in the real world, so I never really learned how to use it" I read: "You probably care more about getting some job than actually doing great software" and "You probably can think of new, different, solutions to the problems besides the straight forward procedural or OO solutions that come in a cereal box".<br />Learning new programming languages is not only about using them to solve problems in your job (though they might comehttp://www.dabeaz.com/generators/genfind.py in very handy. If you don't believe me check out <a href="http://www.dabeaz.com/generators/genfind.py">this</a> implementation of unix find command; it is not only very short but a different way of thinking to what you would do in Java or C). Even if you might not use some programming language in your job (though you might), learning to program in a different paradigm and with a different set of constructs and restrictions will definitely make you a better programmer. Learning Erlang, for example, will give you a new way to think of network programming. Learning Haskell, or functional programming in general, will help you better understand recursion, its advantages, its disadvantages and how to overcome them (not to mention pattern matching, the importance of side effects and the usefulness of first-classs functions). Python or Ruby will help you understand the importance of writing beautiful code (and will become great addictive tools to solve problems very elegantly and fast). Languages from the lisp family will make you question why C or Fortran became so popular back when there where not many other programing languages. Lisp will also make you understand the usefulness of building domain specific languages and the possibilities of expanding the language that many others neglect. I just named a few languages I know, but there is something to learn from every possible languages since each has its own way of solving problems.<br />Even learning a "worst" programming language will be of great use. It provides constrains that were not there before and you need to think of a way to overcome them.<br /><br /><span style="font-weight: bold;">* Hold maths in high esteem</span><br />Edsger Dijkstra once said: "Computer science is no more about computers than astronomy is about telescopes."<span style="font-style: italic;"></span><cite></cite><br />Computer science is about computation. Whether we use a Von Neuman machine or not, the way to reason about computation is with mathematics. If you just want to program very simple websites you will probably not need much complex math, but for any slightly more interesting task you should learn (and love if possibly) math or you might end up doing things like solving a problem by iteration when you might just calculate a closed form (resulting in bad efficiency) . <a href="www.math.nus.edu.sg/%7Emattyc/CS.Maths.pdf">This article</a> talks about some interesting problems and how math is used, along with computing, to solve them.<br /><br /><span style="font-weight: bold;">* Learn English</span><br />Knowing english is essential for this field of study. If you don't know english (or not enough english) just go and learn it. Seriously, go now!. English is not my first language and I am always trying to improve my english (writting this blog in english is a part of it). I also often see people complaining about having to use english for programming; I even saw once somebody claiming that programming language constructs (like IF-THEN-ELSE, FOR, etc) should be translated into multiple language. Excel does this for its macro system and I consider it plain STUPID. Many professors in my university even _force_ you to code using variable names and code comments in spanish. This is not necessarily wrong. I personally prefer to do all the coding and documentation in english since it gives my code more reach but if I _know_ the code and documentation will only be read by X-speaking people, I believe it is ok to write it in X.<br />I also consider it is easier to read code that has variable names in english because you could read some code expressions out loud and they would make perfectly well formed english expressions. This is especially true for languages like python or ruby; C, java, Haskell or others with a more obscure syntax probably don't have this advantage.<br /><br /><span style="font-weight: bold;">* Read</span><br />A few days back, reading about public speaking, I found this tips:<br /><blockquote><br />- Listen to great speakers: Attend as many programs of great speakers as possible. Subject spoken is immaterial here, what you are learning is the “Master's” way of doing it.<br />- Read about doing presentations: There are now plenty of books on doing effective presentations and Internet has numerous pages on this. Read them.<br /></blockquote><br />It seams very obvious that doing this stuff will make you a better public speaker. The analogous of this for coding could be:<br /><br />- Read code written by great coders<br />- Read about writing code<br /><br />I should be very obvious that doing these two will also make you a better programmer, but lets expand a little bit on why (and how to do it).<br />The first one, read code written by great coders, might seem hard (at least it seems a little harder than listening to a great speaker). You can start by reading small chunks of code, the kind of snippets you find in a book, and move into larger projects as you get the hang of it. You could of course just jump directly to reading sections of a project and then the whole project (and while you're at it, why not contribute a bit!). It is very easy to find great code, written by great coders, to read: just go and download the source of your favorite open source project (some suggestions: django, emacs, git, your favorite linux distro, kde, mootools/jquery, blender; they go from operating systems to 3D tools, there's something for everyone).<br />The second one is a lot easier to do, and maybe even more educative. There's a lot of material on the internet that aims to teach you how to program well, and then there's books!. Many authors will contradict each other because the "right way" of programming is not the same for everyone. There are many different thoughts on how to do it right but most of them share some basic grounds so you'll have to decide whether what they suggest makes sense or not. It is here where you'll start having your own opinions on programming forged from the thoughts of many.<br />So, pick your a language or an area of interest (for example: "OCaml" or "Image generation/manipulation" or "artificial intelligence" or, simpler, "sorting algorithms") and go find information on how they're done. Read, read, read, read. And then, if possible, implement.<br /><br />There is another type of reading that I believe might be useful but with which you should be careful:<br />- Read bad code<br />Read bad code and try to understand why it is bad code and what are the "anti-patterns" that are present in that code that makes it suck. If possible try and make it not-suck anymore.<br /><br />Note: If you're trying to tell somebody that their code sucks: don't be an ass, be constructive and helpful.<br /><br /><span style="font-weight: bold;">* Read blogs</span><br />There's a lot of smart people out there. Many of them have blogs and they blog about interesting cool stuff. It doesn't need to be about technology or science. I would avoid things like "the paris hilton blog"; but, besides that, anything that promotes your intellect creativity or recreation is fine. I am not going to tell you which blogs to read (but read mine! ;) ), you'll build your own list as you start finding people that write interesting articles. There are a lot of sites like digg, reddit and swik where you can find tons of articles every day. They are also classified by subject. Just read the ones you like, and if someone writes interesting stuff add their feed to your aggregator. (If you don't know what an aggregator is, just check google reader out)<br /><br /><span style="font-weight: bold;">* Read books</span><br />The internet is nice but it sure doesn't have all the answers. There are a few problems with obtaining all of your knowledge from the internet: The information doesn't have an explicit order, you need to decide in which order you learn stuff and doing so can sometimes make it harder to learn; The internet is "Breadth first", finding topics in depth can be hard and, even if the information is there, it is not as comprehensive as it would be in a book; There is no formal review process, though some sites, like wikipedia and some blogs, have a very good process for socially reviewing information, not all of the information gets reviewed or, if it does get reviewed, it might not be updated to reflect the improvements of the review. Books are very good at treating complex (or simple) topics in depth, their narrative is designed to be appealing and to ensure a good learning path and they're reviewed many times by different people to ensure their quality. Not all books are great, but certainly there are a lot that are.<br />It's simple. Search for books on what interests you: learning a language (or better, theory of programming languages), learning algorithms, learning a specific topic (AI, Operating Systems, Testing, Graphics, Security...), what ever you fancy the most. Read reviews of the books, choose one, buy it, read it. I might come up with a list of book recommendations sometime in the future, but for the time being you're on your own (but with a little help from amazon and the internet).<br /><br /><span style="font-weight: bold;">* Use Open Source</span><br />There are a lot of open source tools available out there. You should always try to look them up and see for yourself what they're all about. Sometimes they're better than their closed counterparts, some other times they're not. It pretty much depends on what you're trying to do. I am not telling you to use openoffice here. I am talking about development or deployment tools or frameworks that can help you make a better job. You need a web server? why not check apache out? you need a database management system? there's more than oracle out there (try postgres or mysql). Need a mapreduce framework, let's try out hadoop and see how it goes. compilers? gcc, gcj, etc. There are also great open source programs you can use as a final user, Amarok, Inkscape, GIMP, blender (really check this out, blender is amazing!)..., but it is more importante that you know which tools are available to make you do a better job.<br />As I said before, the opensource programs many times are better than the closed source ones, but this is not always the case. In such cases where there are good closed alternatives it is important that you know in which ways the open source options are better and if they are suitable for the task you wish to accomplish. In the near future there is probably going to be an open source alternative to every closed tool out there and, if things continue to be as they are now, this tools will be better than the closed alternatives (or at least _very_ competitive).<br /><br /><span style="font-weight: bold;">* Do Open Source</span><br />I had never worked on open source until I participated in Google's summer of code project earlier this year. I had the opportunity to work with the Django community which is just great. Lately I haven't had the time to continue working on opensource projects but I definitely wish to continue doing so as soon as possible.<br />Doing opensource teaches you many things. Technologically, it gives you the possibility to work with many great programmers and learn a lot from them, by reading their code, by having them review your code, by finding and fixing their errors, by discussing the best approaches to solving a problem. Humanly, it allows you to work with a fairly large number of people scattered around the globe with different mindsets, different cultures, different languages, different interests; having to work with so many different people encourages you to take your work seriously and have a good work and communication methodology.<br />Open source development requires dedication, but it is very well rewarded when you know you've done something good and other people are actually using and improving your code. It is also rewarded with the amount of knowledge and expertise that you earn. You could practice programming by doing toy programs at home. But you could also practice programing by contributing to real world programs and state of the art technologies. It is better for both you and the world.<br /><br /><span style="font-weight: bold;">* Learn Unix</span><br />("unix" in this section refers to any *nix, especially linux)<br />Unix is great. Once you learn it you probably won't be able to live without it. It is pretty much like Firefox for an IE user. Most IE users will tell you it has everything they need. They are just unable to imagine anything better. They might even resist using it because they don't see the advantages and they just don't want to change their browser. You, then, convince them to change to FF just for a month or two. Some time later they will probably come thanking you for showing them FF and rant about how they could never use IE anymore. It is one of those things you don't actually get until you've taste them.<br />Unix is probably the same for most people: "the thing geeks use that seems to be pretty much the same but looks kind of odd". Just taste it for a while...<br />But I am not saying you should use Unix on a daily basis. I'm not even saying you should ever use it as *your* operating system. I am just saying you should "know" it. Why? Many reasons: First, the shallow reasons, it looks nice on your resume; Second you'll probably need to use it some time during your professional life and you don't want to look stupid asking how to read a file; Third, It will help you solve problems really easily ("get me the number of html files that contain the word X", done: "find -iname "*html" -exec grep X {} + | wc -l"); Forth, just learn it! ok?. This article is not for preaching about unix, there are enough of those on the net, this is for recommending you to learn how to use it.<br />If you can also learn how the internals work I also recommend you do so. It is not hard. Just set yourself the goal of learning a different part of the OS every week (month?). Ask yourself a question like: What (exactly) happens when I turn the computer on, from pushing the button to browsing the web? (this question might take a while but it is very educative, you could consider breaking it up into pieces) what are services? daemons? what are kernel modules? how do I compile a kernel? how do I load "drivers"? how does authentication work in my system? how do I make packages for my distro? what (exactly) happens when I install a package? how does the networking work? and, of course, what cool tricks can I do with my OS?<br />These questions should strike you quite interesting if you don't know the answer and they will probably provide you with tons of new things to learn. You could go nd install some distro that doesn't try to do everything for you (ubuntu). This will also give you more freedom to do anything with your system. I am currently using Arch and loving it (except for a few issues that I'll blog about later). Before, I was a strong Gentoo user (and I still have a place for gentoo in my heart, I'm just tired of compiling everything for my personal computer).<br /><br /><span style="font-weight: bold;">* Use Unix</span><br />I lied. I *am* going to tell you to use it on a daily basis. If you really want to learn it, what better way to practice than by using it every day as your primary OS? And, as I said, once you get the hang of it you won't be able to understand why would somebody use anything else.<br /><br /><span style="font-weight: bold;">* Text Editors</span><br />This is probably the most important point in the series. Mastering a good text editor will make you tens of times more productive, so learn a good text editor and learn it well.<br />There are a handful of text editors out there. I use emacs, and consider it to be the best, but if you use vi/vim it is probably ok. If you own a mac, I've heard that TextMate is also very good.<br />Now, it is not enough just to learn how to get in and out of your editor and maybe some copy/paste shortcuts. Remember that the idea is to make you more productive. These text editors have an very large number of cool features that will never cease to amaze you, so learn it well. It will not only make you more productive but will give you bragging rights: "you built a program to convert that huge data file into a different format (re-ordering columns, removing irrelevant information, substituting expressions, etc)? I can do that with emacs in less than a minute". And it will be true!<br />Some (inevitably incomplete list of) cool features in emacs that will help you very often (at least they help me almost every day): cut and paste a rectangle, move a line up or down, highlight a line or a column, search and replace regular expressions, define macros, repeat an action several times, split the screen, open a shell and copy/paste from/to it, match parens, move to a specific line, display the name of the function you're in, display the line and column number, display code syntax errors, swap two words/characters, move by word... These are just examples. Start learning new tricks every day and put them to practice.<br />Some editors also provide the possibility of extending it. Use an editor that does so. By doing this you can change any behaviour you want and adapt the editor to your way of working. You could, then, share it with the world.<br />So, is a good text editor better than an IDE? For me: yes. Some text editors even behave like IDEs for some languages. But even if they didn't, I believe that having good editing capabilities makes you a lot more productive than giving you language hints and compile/debug buttons. If you still prefer the IDEs sometimes, you can always use them for some specific programming languages or tasks. Eventually, you'll find some simple but tedious task that your IDE just can't perform and go back to emacs (sorry, your text editor of choice). Even if this never happens, have some text editor knowledge handy just in case you would need it (while on ssh, for instance).<br /><br /><span style="font-weight: bold;">* Get trendy</span><br />Read about the latest trends, if possible try them out and see what they're all about. Trends are not necessarily good, but they're getting a lot of attention for a reason, and many people will know about these trends and love/hate them. You should decide for yourself whether they are good or bad and why. I personally don't like the whole J2EE and Design Patterns buzzwords. Instead I'd go for TDD, functional-style programming and dynamic typing. I am not saying these are all the latest trends or that you should follow them, it is just an example of my likes and dislikes. I am not saying either that you should abandon your path and go chasing buzzwords as they appear. I like dynamic typing, but I still understand the advantages of static types and won't abandon C/C++ style of programming. I believe J2EE is bullshit, but I don't consider Java should be completely knocked out of the way. I, also, in no way believe design patterns are useless, I just think they get way to much more attention than they should. Staying on top of the trends helps you absorb the good stuff about each one of them and understand their limitations. You will be able to tell people what paradigms you love or hate and why they are good or bad. You can also understand other programmers points of view and consider in which cases different approaches should be used.<br />How do you stay on top of the trends? Read blogs.<br /><br /><span style="font-weight: bold;">* Use Version Control</span><br />I am amazed at how many people, with a computer science or computer engineering degree, don't know or use version control systems. There are many advantages of using version control: recovering previous work, seamlessly integrating your work with other's, undoing undesired changes, keeping different "copies" (branches) of your project for experimental development, viewing the history of changes for your project along with who did each change, and many others you'll find when you start using version control on your projects.<br />I am currently using git as version control system and loving it. If you're using another version control system I highly recommend you give git a try (check <a href="http://whygitisbetterthanx.com/">this</a> out for reasons) . If you are new to version control many people would recommend you to go for something like mercurial or bazaar (because they are apparently simpler, I haven't use them) but If you are fierce I would also tell you to check git out. It is not _that_ hard and there are a lot of resources to learn it.<br /><br /><span style="font-weight: bold;">* Test</span><br />This is not a must, but it would be good if you got used to testing your software. It will help you build better programs and know many testing tools in the future.<br />If you use Java the most common testing tools is <a href="http://www.junit.org/">JUnit</a>; for C++ I recommend <a href="http://code.google.com/p/googletest/">googletest</a> and <a href="http://cxxtest.tigris.org/">cxxtest</a>, but for a more detailed comparison you can check <a href="http://gamesfromwithin.com/?p=29">this</a> article; for Python I'd recommend <a href="http://codespeak.net/py/dist/test.html">py.test</a>, or the standard python testing modules: <a href="http://docs.python.org/library/doctest.html">doctests</a> and <a href="http://docs.python.org/library/unittest.html">unittests</a>.<br />Testing might be a little time consuming, but it will certainly make you think about your software design and create better code.<br /><br /><span style="font-weight: bold;">* Try and make your courses better</span><br />This is a short one. Think about what you would like to learn in every course and compare it with what you'll actually learn in it. If there are things missing try and learn them yourself. If you think of a better way to work for a course (specially in software development courses) propose it or try to do it by yourself.<br /><br /><span style="font-weight: bold;">* A note on grades</span><br />Grades don't necessarily represent how much you know a given subject. Instead they represent how much dedication have you put to the course and to achieving the grade. Personally, I have always taken learning to be more important than achieving a grade. In courses where you choose a project to develop you could choose a simple project that will be easier to complete but will provide little to no knowledge (for example choosing a problem that is isomorphic to the class examples, or just using a library to solve the problems instead of implementing the algorithms), or you could choose a more complex project that will provide more learning but that is, also, more error prone (besides you might not be able to finish it in time). My recommendation is to always take learning as your primary objective and leave the grades to be a consequence of your good learning, but take this one with a grain of salt and don't go blaming me for your bad grades (though I believe if you follow this advice you'll probably thank me instead for the amount of learning you got for not fearing the grades)nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com15tag:blogger.com,1999:blog-4150232295397368657.post-14579270642107148282008-12-17T16:41:00.002-04:302008-12-30T14:58:13.061-04:30If programming Languages were religionsVery funny/interesting article =)nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com0tag:blogger.com,1999:blog-4150232295397368657.post-48251003679034228492008-12-16T12:56:00.011-04:302008-12-17T14:30:43.957-04:30Blogging<span style=";font-family:verdana;font-size:100%;" >I finally decided to start a blog!. It had actually been decided for quite a while, but I hadn't had time to start writing. That, and I was waiting to build my own (perfect) blog website. Anyway, I gave up and decided give blogger a try at least for the time being.<br /></span><span style=";font-family:verdana;font-size:100%;" ><br /><span style="font-weight: bold;font-size:130%;" >why blogging?</span><br />Well, there are many reasons. In the first place there is an awful lot of (smart) people telling you "</span><span style=";font-family:verdana;font-size:100%;" ><a href="http://steve.yegge.googlepages.com/you-should-write-blogs">you should write blogs</a></span><span style=";font-family:verdana;font-size:100%;" >" (the link is just one example, check google for more) and their reasons seem to quite convincing. But thinking about it, I didn't need them to tell me to write a blog. There's a much more compeling reason to do so: iThink.<br />No, I'ts not a new apple product. I just tend to think (and imagine) stuff all the time (seriously, *all* the time). But the problem with being thinking all the time is that thought is ephemeral. I've always wanted to carry around one of these old style recording devices that journalists used to carry with them and use it to record the interesting ideas I had. But even if I did, I wouldn't get much value of it cuz the recorded ideas have two main problems:<br />First, they are messy. Even if I could have them organized it would be just endless rants that wont make much sense (I'm not claiming my blog wont be like that, it probably will =p ).<br />And second, they would only reach me. I am not expecting to have much readers, none actually. But who knows.<br />I could also do a vlog (video log) using something like <a href="http://www.seesmic.com/">seesmic</a> but, seriously, who wants to spend their time looking at somebody's face while he talks?. Also to make a good video I'd have to write it first. I wouldn't be able to fix my mistakes and it would be hard to skip to a specific part of the post.<br />Writting, on the other hand, has many advantages. Sure, it's not as dynamic as talking and it's a lot slower, but it helps you (forces you to) organize your ideas to create a (semi) readable text. It is also persistent and can evolve over time. I would love it if blogs could have version control almost as much as I would love it if textareas could have emacs bindings (these are some of the things that would exist in my perfect blogging website), but for now I'm happy with the ability to edit the things I wrote in the past.<br /><br />But the most important advantage of writing is, for me, that it helps me get things done (tm). One of the problems of this "iThink" property of mine that I mentioned earlier is that I think of so many different stuff every day, and add so many things to my in-brain to-do list, that I hardly ever have time to do any of them. So this blog is for me a way of organizing what I think and forcing myself to actually doing or expressing it. Think of it as a place for my finished projects, essays or ideas I'd like to get feedback on (plus any random stuff I come up with).<br /><br /><span style="font-weight: bold;font-size:130%;" >So, What will I write about?</span><br />Pretty much anything. I believe I'll mostly write about computer science related stuff, but you could expect anything from sorting algorithms trough compiler technics trough movies to politics.<br /><span style="font-size:130%;"><br /></span><span style="font-weight: bold;font-size:130%;" >Why in english?</span><br />English is a nice language. A great part of the world can speak it, or at least understand it to some extent. Also I could use some english writting skills. I might do a post in spanish every so often, but don't expect it to be the rule.<br /><span style="font-size:130%;"><br /></span><span style="font-weight: bold;font-size:130%;" >Why /random/thoughts ?</span><br />I know, it is probably the most un-original blog name out there. Google shows 28,100 pages with the phrase "random thoughts" and the world blog in the title. But as it turns out it is not that easy to pick a blog name. I thought of a few different names but this blog is basically about me writting down random thoughts. Also it has just the right amount of geekyness; it is easy enough for anyone to read and slightly interesting for those *nix minded. Plus, "cat /dev/c3po > /mnt/blog" was already taken. Just kidding, I'm not actually *that* geeky =)<br /></span><span style="font-family:verdana;"><span style="font-size:130%;"><span style="font-size:100%;"><br /><blockquote><span style="font-size:85%;"><span style="font-size:78%;">Oficial Comment:<br />After writting my first post I've decided that blogger's wysiwyg editor sucks-a-lot. From now on I'm posting from Emacs.</span><br /></span></blockquote><br /></span></span></span>nicolaslarahttp://www.blogger.com/profile/15167966852380794888noreply@blogger.com2