Normalize legacy code blocks and remove typocode

This commit is contained in:
Sami Samhuri 2026-02-07 16:47:58 -08:00
parent c8b75cdd83
commit 5ef44a5ccb
No known key found for this signature in database
30 changed files with 543 additions and 1102 deletions

View file

@ -8,7 +8,6 @@ module Pressa
PLACEHOLDER_PREFIX = '%%PRESSA_PRESERVE_'
PRESERVE_PATTERNS = [
/<div class="typocode">.*?<\/div>/m,
/<div class="pressa">.*?<\/div>/m,
/<div class="language-[^"]*?highlighter-rouge">.*?<\/div>\s*<\/div>/m
].freeze

View file

@ -4,7 +4,6 @@ Author: Sami Samhuri
Date: "20th February, 2006"
Timestamp: 2006-02-20T00:31:00-08:00
Tags: [rails, coding, hacking, migration, rails, testing]
Styles: typocode.css
---
<p><em>I'm a Rails newbie and eager to learn. I welcome any suggestions or criticism you have. You can direct them to <a href="mailto:sjs@uvic.ca">my inbox</a> or leave me a comment below.</em></p>
@ -17,52 +16,36 @@ Styles: typocode.css
<p>It's unlikely that he was surprised at my lengthy response, but I was. I have been known to write him long messages on topics that interest me. However, I've only been learning Rails for two weeks or so. Could I possibly have so much to say about it already? Apparently I do.</p><h2>Ruby on Rails background</h2>
<p>I assume a pretty basic knowledge of what Rails is, so if you're not familiar with it now's a good time to read something on the official <a href="http://www.rubyonrails.com/">Rails website</a> and watch the infamous <a href="http://www.rubyonrails.com/screencasts">15-minute screencast</a>, where Rails creator, <a href="http://www.loudthinking.com/">David Heinemeier Hansson</a>, creates a simple blog application.</p>
<p>The screencasts are what sparked my curiosity, but they hardly scratch the surface of Rails. After that I spent hours reading whatever I could find about Rails before deciding to take the time to learn it well. As a result, a lot of what you read here will sound familiar if you've read other blogs and articles about Rails. This post wasn't planned so there's no list of references yet. I hope to add some links though so please contact me if any ideas or paraphrasing here is from your site, or if you know who I should give credit to.</p>
<h2>Rails through my eyes</h2>
<p>Rails is like my Black &amp; Decker toolkit. I have a hammer, power screwdriver, tape measure, needle-nose pliers, wire cutters, a level, etc. This is exactly what I need—no more, no less. It helps me get things done quickly and easily that would otherwise be painful and somewhat difficult. I can pick up the tools and use them without much training. Therefore I am instantly productive with them.</p>
<p>The kit is suitable for many people who need these things at home, such as myself. Companies build skyscrapers and huge malls and apartments, and they clearly need more powerful tools than I. There are others that just need to drive in a nail to hang a picture, in which case the kit I have is overkill. They're better off just buying and using a single hammer. I happen to fall in the big grey middle <a href="http://web.archive.org/web/20070316171839/http://poignantguide.net/ruby/chapter-3.html#section2">chunk</a>, not the other two.</p>
<p>I'm a university student. I code because it's satisfying and fun to create software. I do plan on coding for a living when I graduate. I don't work with ancient databases, or create monster sites like Amazon, Google, or Ebay. The last time I started coding a website from scratch I was using <a href="http://www.php.net/">PHP</a>, that was around the turn of the millennium. [It was a fan site for a <a href="http://www.nofx.org/">favourite band</a> of mine.]</p>
<p>After a year or so I realized I didn't have the time to do it properly (ie. securely and cleanly) if I wanted it to be done relatively soon. A slightly customized <a href="http://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a> promptly took it's place. It did all that I needed quite well, just in a less specific way.</p>
<p>The wiki is serving my site extremely well, but there's still that itch to create my <strong>own</strong> site. I feel if Rails was around back then I may have been able to complete the project in a timely manner. I was also frustrated with PHP. Part of that is likely due to a lack of experience and of formal programming education at that time, but it was still not fun for me. It wasn't until I started learning Rails that I thought "<em>hey, I could create that site pretty quickly using this!</em>"</p>
<p>Rails fits my needs like a glove, and this is where it shines. Many professionals are making money creating sites in Rails, so I'm not trying to say it's for amateurs only or something equally silly.</p>
<h2>Web Frameworks and iPods?</h2>
<p>Some might say I have merely been swept up in hype and am following the herd. You may be right, and that's okay. I'm going to tell you a story. There was a guy who didn't get one of the oh-so-shiny iPods for a long time, though they looked neat. His discman plays mp3 CDs, and that was good enough for him. The latest iPod, which plays video, was sufficiently cool enough for him to forget that <strong>everyone</strong> at his school has an iPod and he would be trendy just like them now.</p>
<p>Shocker ending: he is I, and I am him. Now I know why everyone has one of those shiny devices. iPods and web frameworks have little in common except that many believe both the iPod and Rails are all hype and flash. I've realized that something creating this kind of buzz may actually just be a good product. I feel that this is the only other thing the iPod and Rails have in common: they are both <strong>damn good</strong>. Enough about the iPod, everyone hates hearing about it. My goal is to write about the other thing everyone is tired of hearing about.</p>
<h2>Why is Rails special?</h2>
<p><strong>Rails is not magic.</strong> There are no exclusive JavaScript libraries or HTML tags. We all have to produce pages that render in the same web browsers. My dad was correct, there <em>is</em> nothing special about my website either. It's more or less a stock Typo website.</p>
<p>So what makes developing with Rails different? For me there are four big things that set Rails apart from the alternatives:</p>
<ol>
<li>Separating data, function, and design</li>
<li>Readability (which is underrated) </li>
@ -70,148 +53,120 @@ Styles: typocode.css
<li>Testing is so easy it hurts</li>
</ol>
<h3>MVC 101 <em>(or, Separating data, function, and design)</em></h3>
<p>Now I'm sure you've heard about separating content from design. Rails takes that one step further from just using CSS to style your website. It uses what's known as the MVC paradigm: <strong>Model-View-Controller</strong>. This is a tried and tested development method. I'd used MVC before in Cocoa programming on Mac OS X, so I was already sold on this point.</p>
<ul>
<li>The model deals with your data. If you're creating an online store you have a product model, a shopping cart model, a customer model, etc. The model takes care of storing this data in the database (persistence), and presenting it to you as an object you can manipulate at runtime.</li>
</ul>
<ul>
<li>The view deals <em>only</em> with presentation. That's it, honestly. An interface to your app.</li>
</ul>
<ul>
<li>The controller binds the model to the view, so that when the user clicks on the <strong>Add to cart</strong> link the controller is wired to call the <code>add_product</code> method of the cart model and tell it which product to add. Then the controller takes the appropriate action such as redirecting the user to the shopping cart view.</li>
</ul>
<p>Of course this is not exclusive to Rails, but it's an integral part of it's design.</p>
<h3>Readability</h3>
<p>Rails, and <a href="http://www.ruby-lang.org/">Ruby</a>, both read amazingly like spoken English. This code is more or less straight out of Typo. You define relationships between objects like this:</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">Article</span> <span class="punct">&lt;</span> <span class="constant">Content</span>
<span class="ident">has_many</span> <span class="symbol">:comments</span><span class="punct">,</span> <span class="symbol">:dependent</span> <span class="punct">=&gt;</span> <span class="constant">true</span><span class="punct">,</span> <span class="symbol">:order</span> <span class="punct">=&gt;</span> <span class="punct">"</span><span class="string">created_at ASC</span><span class="punct">"</span>
<span class="ident">has_many</span> <span class="symbol">:trackbacks</span><span class="punct">,</span> <span class="symbol">:dependent</span> <span class="punct">=&gt;</span> <span class="constant">true</span><span class="punct">,</span> <span class="symbol">:order</span> <span class="punct">=&gt;</span> <span class="punct">"</span><span class="string">created_at ASC</span><span class="punct">"</span>
<span class="ident">has_and_belongs_to_many</span> <span class="symbol">:categories</span><span class="punct">,</span> <span class="symbol">:foreign_key</span> <span class="punct">=&gt;</span> <span class="punct">'</span><span class="string">article_id</span><span class="punct">'</span>
<span class="ident">has_and_belongs_to_many</span> <span class="symbol">:tags</span><span class="punct">,</span> <span class="symbol">:foreign_key</span> <span class="punct">=&gt;</span> <span class="punct">'</span><span class="string">article_id</span><span class="punct">'</span>
<span class="ident">belongs_to</span> <span class="symbol">:user</span>
<span class="punct">...</span></code></pre></div>
```ruby
class Article < Content
has_many :comments, :dependent => true, :order => "created_at ASC"
has_many :trackbacks, :dependent => true, :order => "created_at ASC"
has_and_belongs_to_many :categories, :foreign_key => 'article_id'
has_and_belongs_to_many :tags, :foreign_key => 'article_id'
belongs_to :user
...
```
<p><code>dependent =&gt; true</code> means <em>if an article is deleted, it's comments go with it</em>. Don't worry if you don't understand it all, this is just for you to see some actual Rails code.</p>
<p>In the Comment model you have:</p>
```ruby
class Comment < Content
belongs_to :article
belongs_to :user
<div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">Comment</span> <span class="punct">&lt;</span> <span class="constant">Content</span>
<span class="ident">belongs_to</span> <span class="symbol">:article</span>
<span class="ident">belongs_to</span> <span class="symbol">:user</span>
<span class="ident">validates_presence_of</span> <span class="symbol">:author</span><span class="punct">,</span> <span class="symbol">:body</span>
<span class="ident">validates_against_spamdb</span> <span class="symbol">:body</span><span class="punct">,</span> <span class="symbol">:url</span><span class="punct">,</span> <span class="symbol">:ip</span>
<span class="ident">validates_age_of</span> <span class="symbol">:article_id</span>
<span class="punct">...</span></code></pre></div>
validates_presence_of :author, :body
validates_against_spamdb :body, :url, :ip
validates_age_of :article_id
...
```
<p>(I snuck in some validations as well)</p>
<p>But look how it reads! Read it out loud. I'd bet that my mom would more or less follow this, and she's anything but a programmer. That's not to say programming should be easy for grandma, <strong>but code should be easily understood by humans</strong>. Let the computer understand things that are natural for me to type, since we're making it understand a common language anyways.</p>
<p>Ruby and Ruby on Rails allow and encourage you to write beautiful code. That is so much more important than you may realize, because it leads to many other virtues. Readability is obvious, and hence maintainability. You must read code to understand and modify it. Oh, and happy programmers will be more productive than frustrated programmers.</p>
<h3 id="migrations">Database Migrations</h3>
<p>Here's one more life-saver: migrations. Migrations are a way to version your database schema from within Rails. So you have a table, call it <code>albums</code>, and you want to add the date the album was released. You could modify the database directly, but that's not fun. Even if you only have one server, all your configuration will be in one central place, the app. And Rails doesn't care if you have PostgreSQL, MySQL, or SQLite behind it. You can develop and test on SQLite and deploy on MySQL and the migrations will just work in both environments.</p>
```ruby
class AddDateReleased < ActiveRecord::Migration
def self.up
add_column "albums", "date_released", :datetime
Albums.update_all "date_released = now()"
end
<div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">AddDateReleased</span> <span class="punct">&lt;</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Migration</span>
<span class="keyword">def </span><span class="method">self.up</span>
<span class="ident">add_column</span> <span class="punct">"</span><span class="string">albums</span><span class="punct">",</span> <span class="punct">"</span><span class="string">date_released</span><span class="punct">",</span> <span class="symbol">:datetime</span>
<span class="constant">Albums</span><span class="punct">.</span><span class="ident">update_all</span> <span class="punct">"</span><span class="string">date_released = now()</span><span class="punct">"</span>
<span class="keyword">end</span>
<span class="keyword">def </span><span class="method">self.down</span>
<span class="ident">remove_column</span> <span class="punct">"</span><span class="string">albums</span><span class="punct">",</span> <span class="punct">"</span><span class="string">date_released</span><span class="punct">"</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
def self.down
remove_column "albums", "date_released"
end
end
```
<p>Then you run the migration (<code>rake migrate</code> does that) and boom, your up to date. If you're wondering, the <code>self.down</code> method indeed implies that you can take this the other direction as well. Think <code>rake migrate VERSION=X</code>.</p>
<p><em>Along with the other screencasts is one on <a href="http://www.rubyonrails.org/screencasts">migrations</a> featuring none other than David Hansson. You should take a look, it's the third video.</em></p>
<h3>Testing so easy it hurts</h3>
<p>To start a rails project you type <code>rails project_name</code> and it creates a directory structure with a fresh project in it. This includes a directory appropriately called <em>test</em> which houses unit tests for the project. When you generate models and controllers it creates test stubs for you in that directory. Basically, it makes it so easy to test that you're a fool not to do it. As someone wrote on their site: <em>It means never having to say "<strong>I introduced a new bug while fixing another.</strong>"</em></p>
<p>Rails builds on the unit testing that comes with Ruby. On a larger scale, that means that Rails is unlikely to flop on you because it is regularly tested using the same method. Ruby is unlikely to flop for the same reason. That makes me look good as a programmer. If you code for a living then it's of even more value to you.</p>
<p><em>I don't know why it hurts. Maybe it hurts developers working with other frameworks or languages to see us have it so nice and easy.</em></p>
<h2>Wrapping up</h2>
<p>Rails means I have fun doing web development instead of being frustrated (CSS hacks aside). David Hansson may be right when he said you have to have been soured by Java or PHP to fully appreciate Rails, but that doesn't mean you won't enjoy it if you <em>do</em> like Java or PHP.</p>
<p><a href="http://www.relevancellc.com/blogs/wp-trackback.php?p=31">Justin Gehtland</a> rewrote a Java app using Rails and the number of lines of code of the Rails version was very close to that of the XML configuration for the Java version. Java has strengths, libraries available <strong>now</strong> seems to be a big one, but it's too big for my needs. If you're like me then maybe you'll enjoy Rails as much as I do.</p>
<h2>You're not done, you lied to me!</h2>
<p>Sort of... there are a few things that it seems standard to include when someone writes about how Rails saved their life and gave them hope again. For completeness sake, I feel compelled to mention some principles common amongst those who develop Rails, and those who develop on Rails. It's entirely likely that there's nothing new for you here unless you're new to Rails or to programming, in which case I encourage you to read on.</p>
<h3>DRY</h3>
<p>Rails follows the DRY principle religiously. That is, <strong>Don't Repeat Yourself</strong>. Like MVC, I was already sold on this. I had previously encountered it in <a href="http://www.pragmaticprogrammer.com/ppbook/index.shtml">The Pragmatic Programmer</a>. Apart from telling <em>some_model</em> it <code>belongs_to :other_model</code> and <em>other_model</em> that it <code>has_many :some_models</code> nothing has jumped out at me which violates this principle. However, I feel that reading a model's code and seeing it's relationships to other models right there is a Good Thing™.</p>
<h3>Convention over configuration <em>(or, Perceived intelligence)</em></h3>
<p>Rails' developers also have the mantra "<em>convention over configuration</em>", which you can see from the video there. (you did watch it, didn't you? ;) Basically that just means Rails has sane defaults, but is still flexible if you don't like the defaults. You don't have to write even one line of SQL with Rails, but if you need greater control then you <em>can</em> write your own SQL. A standard cliché: <em>it makes the simple things easy and the hard possible</em>.</p>
<p>Rails seems to have a level of intelligence which contributes to the wow-factor. After <a href="#migrations">these relationships</a> are defined I can now filter certain negative comments like so:</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="ident">article</span> <span class="punct">=</span> <span class="constant">Article</span><span class="punct">.</span><span class="ident">find</span> <span class="symbol">:first</span>
<span class="keyword">for</span> <span class="ident">comment</span> <span class="keyword">in</span> <span class="ident">article</span><span class="punct">.</span><span class="ident">comments</span> <span class="keyword">do</span>
<span class="ident">print</span> <span class="ident">comment</span> <span class="keyword">unless</span> <span class="ident">comment</span><span class="punct">.</span><span class="ident">downcase</span> <span class="punct">==</span> <span class="punct">'</span><span class="string">you suck!</span><span class="punct">'</span>
<span class="keyword">end</span></code></pre></div>
```ruby
article = Article.find :first
for comment in article.comments do
print comment unless comment.downcase == 'you suck!'
end
```
<p>Rails knows to look for the field <strong>article_id</strong> in the <strong>comments</strong> table of the database. This is just a convention. You can call it something else but then you have to tell Rails what you like to call it.</p>
<p>Rails understands pluralization, which is a detail but it makes everything feel more natural. If you have a <strong>Person</strong> model then it will know to look for the table named <strong>people</strong>.</p>
<h3>Code as you learn</h3>
<p>I love how I've only been coding in Rails for a week or two and I can do so much already. It's natural, concise and takes care of the inane details. I love how I <em>know</em> that I don't even have to explain that migration example. It's plainly clear what it does to the database. It doesn't take long to get the basics down and once you do it goes <strong>fast</strong>.</p>

View file

@ -4,7 +4,6 @@ Author: Sami Samhuri
Date: "23rd February, 2006"
Timestamp: 2006-02-23T17:18:00-08:00
Tags: [textmate, rails, coding, bundle, macros, rails, snippets, textmate]
Styles: typocode.css
---
Everything that you've seen posted on my blog is now available in one bundle. Snippets for Rails database migrations and assertions are all included in this bundle.
@ -13,15 +12,17 @@ There are 2 macros for class-end and def-end blocks, bound to <strong>⌃C</stro
I use an underscore to denote the position of the cursor in the following example:
<div class="typocode"><pre><code class="typocode_ruby "><span class="ident">method</span><span class="punct">(</span><span class="ident">arg1</span><span class="punct">,</span> <span class="ident">arg2_</span><span class="punct">)</span></code></pre></div>
```ruby
method(arg1, arg2_)
```
Typing <strong>⌃D</strong> at this point results in this code:
<div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">def </span><span class="method">method</span><span class="punct">(</span><span class="ident">arg1</span><span class="punct">,</span> <span class="ident">arg2</span><span class="punct">)</span>
<span class="ident">_</span>
<span class="keyword">end</span></code></pre></div>
```ruby
def method(arg1, arg2)
_
end
```
There is a list of the snippets in Features.rtf, which is included in the disk image. Of course you can also browse them in the Snippets Editor built into TextMate.

View file

@ -16,39 +16,53 @@ Scope should be *source.ruby.rails* and the triggers I use are above the snippet
mcdt: **M**igration **C**reate and **D**rop **T**able
create_table "${1:table}" do |t|
$0
end
${2:drop_table "$1"}
```ruby
create_table "${1:table}" do |t|
$0
end
${2:drop_table "$1"}
```
mcc: **M**igration **C**reate **C**olumn
t.column "${1:title}", :${2:string}
```ruby
t.column "${1:title}", :${2:string}
```
marc: **M**igration **A**dd and **R**emove **C**olumn
add_column "${1:table}", "${2:column}", :${3:string}
${4:remove_column "$1", "$2"}
```ruby
add_column "${1:table}", "${2:column}", :${3:string}
${4:remove_column "$1", "$2"}
```
I realize this might not be for everyone, so here are my original 4 snippets that do the work of *marc* and *mcdt*.
mct: **M**igration **C**reate **T**able
create_table "${1:table}" do |t|
$0
end
```ruby
create_table "${1:table}" do |t|
$0
end
```
mdt: **M**igration **D**rop **T**able
drop_table "${1:table}"
```ruby
drop_table "${1:table}"
```
mac: **M**igration **A**dd **C**olumn
add_column "${1:table}", "${2:column}", :${3:string}
```ruby
add_column "${1:table}", "${2:column}", :${3:string}
```
mrc: **M**igration **R**remove **C**olumn
remove_column "${1:table}", "${2:column}"
```ruby
remove_column "${1:table}", "${2:column}"
```
I'll be adding more snippets and macros. There should be a central place where the rails bundle can be improved and extended. Maybe there is...
@ -91,4 +105,3 @@ I'll be adding more snippets and macros. There should be a central place where t
<p>P.S. I tried several ways to get the combo-snippets to put the pieces inside the right functions but failed. We'll see tomorrow if Allan (creator of TextMate) has any ideas.</p>
</div>
</div>

View file

@ -4,43 +4,41 @@ Author: Sami Samhuri
Date: "21st February, 2006"
Timestamp: 2006-02-21T14:55:00-08:00
Tags: [textmate, rails, hacking, commands, macro, rails, snippets, textmate]
Styles: typocode.css
---
<p><em><strong>UPDATE:</strong> I got everything working and it's all packaged up <a href="/posts/2006/02/intelligent-migration-snippets-0_1-for-textmate">here</a>. There's an installation script this time as well.</em></p>
<p>Thanks to <a href="http://thread.gmane.org/gmane.editors.textmate.general/8520">a helpful thread</a> on the TextMate mailing list I have the beginning of a solution to insert text at 2 (or more) locations in a file.</p>
<p>I implemented this for a new snippet I was working on for migrations, <code>rename_column</code>. Since the command is the same in self.up and self.down simply doing a reverse search for <code>rename_column</code> in my <a href="/posts/2006/02/textmate-move-selection-to-self-down">hackish macro</a> didn't return the cursor the desired location.</p><p>That's enough introduction, here's the program to do the insertion:</p>
```ruby
#!/usr/bin/env ruby
def indent(s)
s =~ /^(\s*)/
' ' * $1.length
end
<div class="typocode"><pre><code class="typocode_ruby "><span class="comment">#!/usr/bin/env ruby</span>
<span class="keyword">def </span><span class="method">indent</span><span class="punct">(</span><span class="ident">s</span><span class="punct">)</span>
<span class="ident">s</span> <span class="punct">=~</span> <span class="punct">/</span><span class="regex">^(<span class="escape">\s</span>*)</span><span class="punct">/</span>
<span class="punct">'</span><span class="string"> </span><span class="punct">'</span> <span class="punct">*</span> <span class="global">$1</span><span class="punct">.</span><span class="ident">length</span>
<span class="keyword">end</span>
up_line = 'rename_column "${1:table}", "${2:column}", "${3:new_name}"$0'
down_line = "rename_column \"$$1\", \"$$3\", \"$$2\"\n"
<span class="ident">up_line</span> <span class="punct">=</span> <span class="punct">'</span><span class="string">rename_column "${1:table}", "${2:column}", "${3:new_name}"$0</span><span class="punct">'</span>
<span class="ident">down_line</span> <span class="punct">=</span> <span class="punct">"</span><span class="string">rename_column <span class="escape">\"</span>$$1<span class="escape">\"</span>, <span class="escape">\"</span>$$3<span class="escape">\"</span>, <span class="escape">\"</span>$$2<span class="escape">\"\n</span></span><span class="punct">"</span>
# find the end of self.down and insert 2nd line
lines = STDIN.read.to_a.reverse
ends_seen = 0
lines.each_with_index do |line, i|
ends_seen += 1 if line =~ /^\s*end\b/
if ends_seen == 2
lines[i..i] = [lines[i], indent(lines[i]) * 2 + down_line]
break
end
end
<span class="comment"># find the end of self.down and insert 2nd line</span>
<span class="ident">lines</span> <span class="punct">=</span> <span class="constant">STDIN</span><span class="punct">.</span><span class="ident">read</span><span class="punct">.</span><span class="ident">to_a</span><span class="punct">.</span><span class="ident">reverse</span>
<span class="ident">ends_seen</span> <span class="punct">=</span> <span class="number">0</span>
<span class="ident">lines</span><span class="punct">.</span><span class="ident">each_with_index</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">line</span><span class="punct">,</span> <span class="ident">i</span><span class="punct">|</span>
<span class="ident">ends_seen</span> <span class="punct">+=</span> <span class="number">1</span> <span class="keyword">if</span> <span class="ident">line</span> <span class="punct">=~</span> <span class="punct">/</span><span class="regex">^<span class="escape">\s</span>*end<span class="escape">\b</span></span><span class="punct">/</span>
<span class="keyword">if</span> <span class="ident">ends_seen</span> <span class="punct">==</span> <span class="number">2</span>
<span class="ident">lines</span><span class="punct">[</span><span class="ident">i</span><span class="punct">..</span><span class="ident">i</span><span class="punct">]</span> <span class="punct">=</span> <span class="punct">[</span><span class="ident">lines</span><span class="punct">[</span><span class="ident">i</span><span class="punct">],</span> <span class="ident">indent</span><span class="punct">(</span><span class="ident">lines</span><span class="punct">[</span><span class="ident">i</span><span class="punct">])</span> <span class="punct">*</span> <span class="number">2</span> <span class="punct">+</span> <span class="ident">down_line</span><span class="punct">]</span>
<span class="keyword">break</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="comment"># return the new text, escaping special chars</span>
<span class="ident">print</span> <span class="ident">up_line</span> <span class="punct">+</span> <span class="ident">lines</span><span class="punct">.</span><span class="ident">reverse</span><span class="punct">.</span><span class="ident">to_s</span><span class="punct">.</span><span class="ident">gsub</span><span class="punct">('</span><span class="string">[$`<span class="escape">\\</span>]</span><span class="punct">',</span> <span class="punct">'</span><span class="string"><span class="escape">\\\\</span>\1</span><span class="punct">').</span><span class="ident">gsub</span><span class="punct">('</span><span class="string"><span class="escape">\\</span>$<span class="escape">\\</span>$</span><span class="punct">',</span> <span class="punct">'</span><span class="string">$</span><span class="punct">')</span></code></pre></div>
# return the new text, escaping special chars
print up_line + lines.reverse.to_s.gsub('[$`\\]', '\\\\\1').gsub('\\$\\$', '$')
```
<p>Save this as a command in your Rails, or <a href="http://blog.inquirylabs.com/">syncPeople on Rails</a>, bundle. The command options should be as follows:</p>
<ul>
<li><strong>Save:</strong> Nothing</li>
<li><strong>Input:</strong> Selected Text or Nothing</li>
@ -49,10 +47,8 @@ Styles: typocode.css
<li><strong>Scope Selector:</strong> source.ruby.rails</li>
</ul>
<p>The first modification it needs is to get the lines to insert as command line arguments so we can use it for other snippets. Secondly, regardless of the <strong>Re-indent pasted text</strong> setting the text returned is indented incorrectly.</p>
The macro I'm thinking of to invoke this is tab-triggered and will simply:
<ul>
<li>Select word (<code><strong>⌃W</strong></code>)</li>
@ -61,4 +57,3 @@ The macro I'm thinking of to invoke this is tab-triggered and will simply:
<li>Run command "Put in self.down"</li>
</ul>

View file

@ -4,29 +4,26 @@ Author: Sami Samhuri
Date: "21st February, 2006"
Timestamp: 2006-02-21T00:26:00-08:00
Tags: [textmate, rails, hacking, hack, macro, rails, textmate]
Styles: typocode.css
---
<p><strong>UPDATE:</strong> <em>This is obsolete, see <a href="/posts/2006/02/textmate-insert-text-into-self-down">this post</a> for a better solution.</em></p>
<p><a href="/posts/2006/02/some-textmate-snippets-for-rails-migrations.html#comment-3">Duane's comment</a> prompted me to think about how to get the <code>drop_table</code> and <code>remove_column</code> lines inserted in the right place. I don't think TextMate's snippets are built to do this sort of text manipulation. It would be nicer, but a quick hack will suffice for now.</p><p>Use <acronym title="Migration Create and Drop Table">MCDT</acronym> to insert:</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="ident">create_table</span> <span class="punct">"</span><span class="string">table</span><span class="punct">"</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">t</span><span class="punct">|</span>
```ruby
create_table "table" do |t|
<span class="keyword">end</span>
<span class="ident">drop_table</span> <span class="punct">"</span><span class="string">table</span><span class="punct">"</span></code></pre></div>
end
drop_table "table"
```
<p>Then press tab once more after typing the table name to select the code <code>drop_table "table"</code>. I created a macro that cuts the selected text, finds <code>def self.down</code> and pastes the line there. Then it searches for the previous occurence of <code>create_table</code> and moves the cursor to the next line, ready for you to add some columns.</p>
<p>I have this bound to <strong>⌃⌥⌘M</strong> because it wasn't in use. If your Control key is to the left the A key it's quite comfortable to hit this combo. Copy the following file into <strong>~/Library/Application Support/TextMate/Bundles/Rails.tmbundle/Macros</strong>.</p>
<p style="text-align: center;"><a href="http://sami.samhuri.net/files/move-to-self.down.plist">Move selection to self.down</a></p>
<p>This works for the <acronym title="Migration Add and Remove Column">MARC</acronym> snippet as well. I didn't tell you the whole truth, the macro actually finds the previous occurence of <code>(create_table|add_column)</code>.</p>
<p>The caveat here is that if there is a <code>create_table</code> or <code>add_column</code> between <code>self.down</code> and the table you just added, it will jump back to the wrong spot. It's still faster than doing it all manually, but should be improved. If you use these exclusively, the order they occur in <code>self.down</code> will be opposite of that in <code>self.up</code>. That means either leaving things backwards or doing the re-ordering manually. =/</p>

View file

@ -16,8 +16,9 @@ It requires more thinking than the last 2 computer books I read, *Programming Ru
QOTD, p. 329, about matching nested pairs of parens:
\(([^()]|\(([^()]|\(([^()]|\(([^()])*\))*\))*\))*\)
Wow, that's ugly.
```conf
\(([^()]|\(([^()]|\(([^()]|\(([^()])*\))*\))*\))*\)
Wow, that's ugly.
```
(Don't worry, there's a much better solution on the next 2 pages after that quote.)

View file

@ -16,7 +16,7 @@ I would fully expect the PHP parser to give me an error like "No class method [f
This code:
<pre><code>
```php
class Foo {
public static function static_fun()
{
@ -29,7 +29,7 @@ class Foo {
}
}
echo '&lt;pre&gt;';
echo '<pre>';
echo "From Foo:\n";
echo Foo::static_fun();
echo Foo::not_static();
@ -37,14 +37,14 @@ echo "\n";
echo "From \$foo = new Foo():\n";
$foo = new Foo();
echo $foo-&gt;static_fun();
echo $foo-&gt;not_static();
echo '&lt;/pre&gt;';
</code></pre>
echo $foo->static_fun();
echo $foo->not_static();
echo '</pre>';
```
Produces:
<pre><code>
```php
From Foo:
This is a class method!
This is an instance method!
@ -52,7 +52,7 @@ This is an instance method!
From $foo = new Foo():
This is a class method!
This is an instance method!
</code></pre>
```
What the fuck?! <a href="http://www.php.net/manual/en/language.oop5.static.php">http://www.php.net/manual/en/language.oop5.static.php</a> is lying to everyone.

View file

@ -10,8 +10,7 @@ Tags: [php, coding, coding, php]
As colder on ##php (freenode) told me today, class methods in PHP don't have what they call late static binding. What's that? It means that this code:
<pre>
<code>
```php
class Foo
{
public static function my_method()
@ -24,15 +23,13 @@ class Bar extends Foo
{}
Bar::my_method();
</code>
</pre>
```
outputs "I'm a Foo!", instead of "I'm a Bar!". That's not fun.
Using <code>__CLASS__</code> in place of <code>get_class()</code> makes zero difference. You end up with proxy methods in each subclass of Foo that pass in the real name of the calling class, which sucks.
<pre>
<code>
```php
class Bar extends Foo
{
public static function my_method()
@ -40,8 +37,7 @@ class Bar extends Foo
return parent::my_method( get_class() );
}
}
</code>
</pre>
```
I was told that they had a discussion about this on the internal PHP list, so at least they're thinking about this stuff. Too bad PHP5 doesn't have it. I guess I should just be glad I won't be maintaining this code.

View file

@ -28,7 +28,9 @@ If anyone actually knows how to write batch files I'd like to hear any suggestio
You will probably just want to test my method of testing for Parallels and Boot Camp first. The easiest way is to just open a command window and run this command:
ipconfig /all | find "Parallels"
```bat
ipconfig /all | find "Parallels"
```
If you see a line of output like **"Description . . . . : Parallels Network Adapter"** and you are in Parallels then the test works. If you see no output and you are in Boot Camp then the test works.
@ -46,8 +48,10 @@ If you're lazy then you can download <a href="http://sami.samhuri.net/files/para
Run Windows in Parallels, activate it, then open a command window and run:
mkdir C:\Windows\System32\Parallels
copy C:\Windows\System32\wpa.* C:\Windows\System32\Parallels
```bat
mkdir C:\Windows\System32\Parallels
copy C:\Windows\System32\wpa.* C:\Windows\System32\Parallels
```
Download <a href="http://sami.samhuri.net/files/parallels/backup-parallels-wpa.bat">backup-parallels-wpa.bat</a>
@ -57,8 +61,10 @@ Download <a href="http://sami.samhuri.net/files/parallels/backup-parallels-wpa.b
Run Windows using Boot Camp, activate it, then run:
mkdir C:\Windows\System32\BootCamp
copy C:\Windows\System32\wpa.* C:\Windows\System32\BootCamp
```bat
mkdir C:\Windows\System32\BootCamp
copy C:\Windows\System32\wpa.* C:\Windows\System32\BootCamp
```
Download <a href="http://sami.samhuri.net/files/parallels/backup-bootcamp-wpa.bat">backup-bootcamp-wpa.bat</a>
@ -72,19 +78,21 @@ If you have XP Pro then you can get it to run using the Group Policy editor. Sav
<p>If you have XP Home then the best you can do is run this script from your Startup folder (Start -> All Programs -> Startup), but that is not really going to work because eventually Windows will not even let you log in until you activate it. What a P.O.S.</p>
@echo off
```bat
@echo off
ipconfig /all | find "Parallels" > network.tmp
for /F "tokens=14" %%x in (network.tmp) do set parallels=%x
del network.tmp
ipconfig /all | find "Parallels" > network.tmp
for /F "tokens=14" %%x in (network.tmp) do set parallels=%x
del network.tmp
if defined parallels (
echo Parallels
copy C:\Windows\System32\Parallels\wpa.* C:\Windows\System32
) else (
echo Boot Camp
copy C:\Windows\System32\BootCamp\wpa.* C:\Windows\System32
)
if defined parallels (
echo Parallels
copy C:\Windows\System32\Parallels\wpa.* C:\Windows\System32
) else (
echo Boot Camp
copy C:\Windows\System32\BootCamp\wpa.* C:\Windows\System32
)
```
Download <a href="http://sami.samhuri.net/files/parallels/activate.bat">activate.bat</a>
@ -105,4 +113,3 @@ This method worked for me and hopefully it will work for you as well. I'm intere
I finally bought Windows XP this week and I'm starting to regret it because of all the hoops they make you jump through to use it. I only use it to fix sites in IE because it can't render a web page properly and I didn't want to buy it just for that. I thought that it would be good to finally get a legit copy since I was using a pirated version and was sick of working around validation bullshit for updates. Now I have to work around MS's activation bullshit and it's just as bad! Screw Microsoft for putting their customers through this sort of thing. Things like this and the annoying balloons near the system tray just fuel my contempt for Windows and reinforce my love of Linux and Mac OS X.
I don't make money off any of my sites, which is why I didn't want to have to buy stupid Windows. I hate MS so much for making shitty IE the standard browser.

View file

@ -12,98 +12,54 @@ They work exactly as you'd expect them to work with possibly one gotcha. If you
Enough chat, here's the self-explanatory code:
<pre class="line-numbers">1
2
3
4
</pre>
<pre><code><span class="c"># extend ActiveRecord::Base with find_or_create and find_or_initialize.</span>
<span class="co">ActiveRecord</span>::<span class="co">Base</span>.class_eval <span class="r">do</span>
include <span class="co">ActiveRecordExtensions</span>
<span class="r">end</span></code></pre>
```ruby
# extend ActiveRecord::Base with find_or_create and find_or_initialize.
ActiveRecord::Base.class_eval do
include ActiveRecordExtensions
end
```
```ruby
module ActiveRecordExtensions
def self.included(base)
base.extend(ClassMethods)
end
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
16
17
18
19
<strong>20</strong>
21
22
23
24
25
26
27
28
29
<strong>30</strong>
31
32
33
34
35
36
37
38
39
<strong>40</strong>
41
</pre>
<pre><code><span class="r">module</span> <span class="cl">ActiveRecordExtensions</span>
<span class="r">def</span> <span class="pc">self</span>.included(base)
base.extend(<span class="co">ClassMethods</span>)
<span class="r">end</span>
module ClassMethods
def find_or_initialize(params)
find_or_do('initialize', params)
end
<span class="r">module</span> <span class="cl">ClassMethods</span>
<span class="r">def</span> <span class="fu">find_or_initialize</span>(params)
find_or_do(<span class="s"><span class="dl">'</span><span class="k">initialize</span><span class="dl">'</span></span>, params)
<span class="r">end</span>
<span class="r">def</span> <span class="fu">find_or_create</span>(params)
find_or_do(<span class="s"><span class="dl">'</span><span class="k">create</span><span class="dl">'</span></span>, params)
<span class="r">end</span>
def find_or_create(params)
find_or_do('create', params)
end
private
<span class="c"># Find a record that matches the attributes given in the +params+ hash, or do +action+</span>
<span class="c"># to retrieve a new object with the given parameters and return that.</span>
<span class="r">def</span> <span class="fu">find_or_do</span>(action, params)
<span class="c"># if an id is given just find the record directly</span>
<span class="pc">self</span>.find(params[<span class="sy">:id</span>])
# Find a record that matches the attributes given in the +params+ hash, or do +action+
# to retrieve a new object with the given parameters and return that.
def find_or_do(action, params)
# if an id is given just find the record directly
self.find(params[:id])
<span class="r">rescue</span> <span class="co">ActiveRecord</span>::<span class="co">RecordNotFound</span> =&gt; e
attrs = {} <span class="c"># hash of attributes passed in params</span>
rescue ActiveRecord::RecordNotFound => e
attrs = {} # hash of attributes passed in params
<span class="c"># search for valid attributes in params</span>
<span class="pc">self</span>.column_names.map(&amp;<span class="sy">:to_sym</span>).each <span class="r">do</span> |attrib|
<span class="c"># skip unknown columns, and the id field</span>
<span class="r">next</span> <span class="r">if</span> params[attrib].nil? || attrib == <span class="sy">:id</span>
# search for valid attributes in params
self.column_names.map(&:to_sym).each do |attrib|
# skip unknown columns, and the id field
next if params[attrib].nil? || attrib == :id
attrs[attrib] = params[attrib]
<span class="r">end</span>
end
<span class="c"># no valid params given, return nil</span>
<span class="r">return</span> <span class="pc">nil</span> <span class="r">if</span> attrs.empty?
# no valid params given, return nil
return nil if attrs.empty?
<span class="c"># call the appropriate ActiveRecord finder method</span>
<span class="pc">self</span>.send(<span class="s"><span class="dl">"</span><span class="k">find_or_</span><span class="il"><span class="dl">#{</span>action<span class="dl">}</span></span><span class="k">_by_</span><span class="il"><span class="dl">#{</span>attrs.keys.join(<span class="s"><span class="dl">'</span><span class="k">_and_</span><span class="dl">'</span></span>)<span class="dl">}</span></span><span class="dl">"</span></span>, *attrs.values)
<span class="r">end</span>
<span class="r">end</span>
<span class="r">end</span></code></pre>
# call the appropriate ActiveRecord finder method
self.send("find_or_#{action}_by_#{attrs.keys.join('_and_')}", *attrs.values)
end
end
end
```

View file

@ -8,7 +8,9 @@ Tags: [haskell]
While reading a <a href="http://www.haskell.org/tutorial/index.html">Haskell tutorial</a> I came across the following code for defining the <a href="http://en.wikipedia.org/wiki/Fibonacci_number">Fibonacci numbers</a>:
fib = 1 : 1 : [ a + b | (a, b) <- zip fib (tail fib) ]
```haskell
fib = 1 : 1 : [ a + b | (a, b) <- zip fib (tail fib) ]
```
After reading it a few times and understanding how it works I couldnt help but think how <strong>beautiful</strong> it is. I dont mean that its aesthetically pleasing to me; the beautiful part is the meaning and simplicity. Lazy evaluation is sweet.
@ -24,4 +26,3 @@ Going deeper down the functional rabbit-hole youll find things like <a href="
* <a href="http://web.cecs.pdx.edu/~antoy/Courses/TPFLP/lectures/MONADS/Noel/research/monads.html">What the hell are Monads?</a>
* <a href="http://en.wikibooks.org/wiki/Programming:Haskell_monads">Monads on WikiBooks</a>
* <a href="http://www.engr.mun.ca/~theo/Misc/haskell_and_monads.htm">Monads for the Working Haskell Programmer</a>

View file

@ -18,9 +18,10 @@ I'm going to explain one of the exercises because converting between the various
Last night I rewrote <code>parseNumber</code> using <code>do</code> and <code>&gt;&gt;=</code> (bind) notations (ex. 3.3.1). Here's <code>parseNumber</code> using the <code>liftM</code> method given in the tutorial:
<pre><code>parseNumber :: Parser LispVal
```haskell
parseNumber :: Parser LispVal
parseNumber :: liftM (Number . read) $ many1 digit
</code></pre>
```
Okay that's pretty simple right? Let's break it down, first looking at the right-hand side of the <code>$</code> operator, then the left.
* <code>many1 digit</code> reads as many decimal digits as it can.
@ -41,24 +42,25 @@ The <code>$</code> acts similar to a pipe in <code>$FAVOURITE_SHELL</code>, and
So how does a Haskell newbie go about re-writing that using other notations which haven't even been explained in the tutorial? Clearly one must search the web and read as much as they can until they understand enough to figure it out (which is one thing I like about the tutorial). If you're lazy like me, here are 3 equivalent pieces of code for you to chew on. <code>parseNumber</code>'s type is <code>Parser LispVal</code> (Parser is a monad).
Familiar <code>liftM</code> method:
<pre><code>parseNumber -&gt; liftM (Number . read) $ many1 digit
</code></pre>
```haskell
parseNumber -> liftM (Number . read) $ many1 digit
```
Using <code>do</code> notation:
<pre><code>parseNumber -&gt; do digits &lt;- many1 digit
```haskell
parseNumber -> do digits <- many1 digit
return $ (Number . read) digits
</code></pre>
```
If you're thinking "Hey a <code>return</code>, I know that one!" then the devious masterminds behind Haskell are certainly laughing evilly right now. <code>return</code> simply wraps up it's argument in a monad of some sort. In this case it's the <code>Parser</code> monad. The <code>return</code> part may seem strange at first. Since <code>many1 digit</code> yields a monad why do we need to wrap anything? The answer is that using <code>&lt;-</code> causes <code>digits</code> to contain a <code>String</code>, stripped out of the monad which resulted from <code>many1 digit</code>. Hence we no longer use <code>liftM</code> to make <code>(Number . read)</code> monads, and instead need to use <code>return</code> to properly wrap it back up in a monad.
In other words <code>liftM</code> eliminates the need to explicitly re-monadize the contents as is necessary using <code>do</code>.
Finally, using <code>&gt;&gt;=</code> (bind) notation:
<pre><code>parseNumber -&gt; many1 digit &gt;&gt;= \digits -&gt;
```haskell
parseNumber -> many1 digit >>= \digits ->
return $ (Number . read) digits
</code></pre>
```
At this point I don't think this warrants much of an explanation. The syntactic sugar provided by <code>do</code> should be pretty obvious. Just in case it's not, <code>&gt;&gt;=</code> passes the contents of its left argument (a monad) to the <em>function</em> on its right. Once again <code>return</code> is needed to wrap up the result and send it on its way.
When I first read about Haskell I was overwhelmed by not knowing anything, and not being able to apply my previous knowledge of programming to <em>anything</em> in Haskell. One piece of syntax at a time I am slowly able to understand more of the Haskell found <a href="http://www.google.com/url?sa=t&amp;ct=res&amp;cd=2&amp;url=http%3A%2F%2Fblog.moertel.com%2Farticles%2F2005%2F03%2F25%2Fwriting-a-simple-ruby-evaluator-in-haskell&amp;ei=Q1A6RtWPLZvYigGZsMjxAQ&amp;usg=AFrqEzdrRepwsuNaQqe1gHYjHvqdCDKfoA&amp;sig2=0qNTIOB9XxeZRqKR7J61Iw">in the wild</a>.

View file

@ -4,32 +4,35 @@ Author: Sami Samhuri
Date: "15th May, 2007"
Timestamp: 2007-05-15T13:38:00-07:00
Tags: [rails]
Styles: typocode.css
---
Here's an easy way to solve a problem that may have nagged you as it did me. Simply using <code>foo.inspect</code> to dump out some object to the browser dumps one long string which is barely useful except for short strings and the like. The ideal output is already available using the <a href="http://www.ruby-doc.org/stdlib/libdoc/prettyprint/rdoc/index.html"><code>PrettyPrint</code></a> module so we just need to use it.
Unfortunately typing <code><pre><%= PP.pp(@something, '') %></pre></code> to quickly debug some possibly large object (or collection) can get old fast so we need a shortcut.
Unfortunately typing <code>&lt;pre&gt;&lt;%= PP.pp(@something, '') %&gt;&lt;/pre&gt;</code> to quickly debug some possibly large object (or collection) can get old fast so we need a shortcut.
Taking the definition of <a href="http://extensions.rubyforge.org/rdoc/classes/Object.html#M000020"><code>Object#pp_s</code></a> from the <a href="http://extensions.rubyforge.org/rdoc/">extensions project</a> it's trivial to create a helper method to just dump out an object in a reasonable manner.
**/app/helpers/application_helper.rb**
<div class="typocode"><div class="codetitle">/app/helpers/application_helper.rb</div><pre><code class="typocode_ruby "><span class="keyword">def </span><span class="method">dump</span><span class="punct">(</span><span class="ident">thing</span><span class="punct">)</span>
<span class="ident">s</span> <span class="punct">=</span> <span class="constant">StringIO</span><span class="punct">.</span><span class="ident">new</span>
<span class="constant">PP</span><span class="punct">.</span><span class="ident">pp</span><span class="punct">(</span><span class="ident">thing</span><span class="punct">,</span> <span class="ident">s</span><span class="punct">)</span>
<span class="ident">s</span><span class="punct">.</span><span class="ident">string</span>
<span class="keyword">end</span></code></pre></div>
```ruby
def dump(thing)
s = StringIO.new
PP.pp(thing, s)
s.string
end
```
Alternatively you could do as the extensions folks do and actually define <code>Object#pp_s</code> so you can use it in your logs or anywhere else you may want to inspect an object. If you do this you probably want to change the <code>dump</code> helper method accordingly in case you decide to change <code>pp_s</code> in the future.
**lib/local_support/core_ext/object.rb**
<div class="typocode"><div class="codetitle">lib/local_support/core_ext/object.rb</div><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">Object</span>
<span class="keyword">def </span><span class="method">pp_s</span>
<span class="ident">pps</span> <span class="punct">=</span> <span class="constant">StringIO</span><span class="punct">.</span><span class="ident">new</span>
<span class="constant">PP</span><span class="punct">.</span><span class="ident">pp</span><span class="punct">(</span><span class="constant">self</span><span class="punct">,</span> <span class="ident">pps</span><span class="punct">)</span>
<span class="ident">pps</span><span class="punct">.</span><span class="ident">string</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
```ruby
class Object
def pp_s
pps = StringIO.new
PP.pp(self, pps)
pps.string
end
end
```

View file

@ -4,7 +4,6 @@ Author: Sami Samhuri
Date: "10th May, 2007"
Timestamp: 2007-05-10T16:14:00-07:00
Tags: [ruby, extensions]
Styles: typocode.css
---
I wanted a method analogous to Prototype's <a href="http://prototypejs.org/api/enumerable/pluck">pluck</a> and <a href="http://prototypejs.org/api/enumerable/invoke">invoke</a> in Rails for building lists for <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#M000510">options_for_select</a>. Yes, I know about <a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#M000511">options_from_collection_for_select</a>.
@ -13,114 +12,130 @@ I wanted something more general that I can use anywhere - not just in Rails - so
First you need <a href="http://pragdave.pragprog.com/pragdave/2005/11/symbolto_proc.html"><code>Symbol#to_proc</code></a>, which shouldn't need an introduction. If you're using Rails you have this already.
<div class="typocode"><div class="codetitle">Symbol#to_proc</div><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">Symbol</span>
<span class="comment"># Turns a symbol into a proc.</span>
<span class="comment">#</span>
<span class="comment"># Example:</span>
<span class="comment"># # The same as people.map { |p| p.birthdate }</span>
<span class="comment"># people.map(&amp;:birthdate)</span>
<span class="comment">#</span>
<span class="keyword">def </span><span class="method">to_proc</span>
<span class="constant">Proc</span><span class="punct">.</span><span class="ident">new</span> <span class="punct">{|</span><span class="ident">thing</span><span class="punct">,</span> <span class="punct">*</span><span class="ident">args</span><span class="punct">|</span> <span class="ident">thing</span><span class="punct">.</span><span class="ident">send</span><span class="punct">(</span><span class="constant">self</span><span class="punct">,</span> <span class="punct">*</span><span class="ident">args</span><span class="punct">)}</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
</code></pre></div>
**Symbol#to_proc**
```ruby
class Symbol
# Turns a symbol into a proc.
#
# Example:
# # The same as people.map { |p| p.birthdate }
# people.map(&:birthdate)
#
def to_proc
Proc.new {|thing, *args| thing.send(self, *args)}
end
end
```
Next we define <code>String#to_proc</code>, which is nearly identical to the <code>Array#to_proc</code> method I previously wrote about.
<div class="typocode"><div class="codetitle">String#to_proc</div><pre><code class="typocode_ruby "><span class="keyword">class </span><span class="class">String</span>
<span class="comment"># Turns a string into a proc.</span>
<span class="comment">#</span>
<span class="comment"># Example:</span>
<span class="comment"># # The same as people.map { |p| p.birthdate.year }</span>
<span class="comment"># people.map(&amp;'birthdate.year')</span>
<span class="comment">#</span>
<span class="keyword">def </span><span class="method">to_proc</span>
<span class="constant">Proc</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span> <span class="punct">|*</span><span class="ident">args</span><span class="punct">|</span>
<span class="ident">split</span><span class="punct">('</span><span class="string">.</span><span class="punct">').</span><span class="ident">inject</span><span class="punct">(</span><span class="ident">args</span><span class="punct">.</span><span class="ident">shift</span><span class="punct">)</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">thing</span><span class="punct">,</span> <span class="ident">msg</span><span class="punct">|</span>
<span class="ident">thing</span> <span class="punct">=</span> <span class="ident">thing</span><span class="punct">.</span><span class="ident">send</span><span class="punct">(</span><span class="ident">msg</span><span class="punct">.</span><span class="ident">to_sym</span><span class="punct">,</span> <span class="punct">*</span><span class="ident">args</span><span class="punct">)</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
</code></pre></div>
**String#to_proc**
```ruby
class String
# Turns a string into a proc.
#
# Example:
# # The same as people.map { |p| p.birthdate.year }
# people.map(&'birthdate.year')
#
def to_proc
Proc.new do |*args|
split('.').inject(args.shift) do |thing, msg|
thing = thing.send(msg.to_sym, *args)
end
end
end
end
```
Finally there's <code>Enumerable#to_proc</code> which returns a proc that passes its parameter through each of its members and collects their results. It's easier to explain by example.
<div class="typocode"><div class="codetitle">Enumerable#to_proc</div><pre><code class="typocode_ruby "><span class="keyword">module </span><span class="module">Enumerable</span>
<span class="comment"># Effectively treats itself as a list of transformations, and returns a proc</span>
<span class="comment"># which maps values to a list of the results of applying each transformation</span>
<span class="comment"># in that list to the value.</span>
<span class="comment">#</span>
<span class="comment"># Example:</span>
<span class="comment"># # The same as people.map { |p| [p.birthdate, p.email] }</span>
<span class="comment"># people.map(&amp;[:birthdate, :email])</span>
<span class="comment">#</span>
<span class="keyword">def </span><span class="method">to_proc</span>
<span class="attribute">@procs</span> <span class="punct">||=</span> <span class="ident">map</span><span class="punct">(&amp;</span><span class="symbol">:to_proc</span><span class="punct">)</span>
<span class="constant">Proc</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">thing</span><span class="punct">,</span> <span class="punct">*</span><span class="ident">args</span><span class="punct">|</span>
<span class="attribute">@procs</span><span class="punct">.</span><span class="ident">map</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">proc</span><span class="punct">|</span>
<span class="ident">proc</span><span class="punct">.</span><span class="ident">call</span><span class="punct">(</span><span class="ident">thing</span><span class="punct">,</span> <span class="punct">*</span><span class="ident">args</span><span class="punct">)</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
**Enumerable#to_proc**
```ruby
module Enumerable
# Effectively treats itself as a list of transformations, and returns a proc
# which maps values to a list of the results of applying each transformation
# in that list to the value.
#
# Example:
# # The same as people.map { |p| [p.birthdate, p.email] }
# people.map(&[:birthdate, :email])
#
def to_proc
@procs ||= map(&:to_proc)
Proc.new do |thing, *args|
@procs.map do |proc|
proc.call(thing, *args)
end
end
end
end
```
Here's the cool part, <code>Enumerable#pluck</code> for Ruby in all its glory.
<div class="typocode"><div class="codetitle">Enumerable#pluck</div><pre><code class="typocode_ruby "><span class="keyword">module </span><span class="module">Enumerable</span>
<span class="comment"># Use this to pluck values from objects, especially useful for ActiveRecord models.</span>
<span class="comment"># This is analogous to Prototype's Enumerable.pluck method but more powerful.</span>
<span class="comment">#</span>
<span class="comment"># You can pluck values simply, like so:</span>
<span class="comment"># &gt;&gt; people.pluck(:last_name) #=&gt; ['Samhuri', 'Jones', ...]</span>
<span class="comment">#</span>
<span class="comment"># But with Symbol#to_proc defined this is effectively the same as:</span>
<span class="comment"># &gt;&gt; people.map(&amp;:last_name) #=&gt; ['Samhuri', 'Jones', ...]</span>
<span class="comment">#</span>
<span class="comment"># Where pluck's power becomes evident is when you want to do something like:</span>
<span class="comment"># &gt;&gt; people.pluck(:name, :address, :phone)</span>
<span class="comment"># #=&gt; [['Johnny Canuck', '123 Maple Lane', '416-555-124'], ...]</span>
<span class="comment">#</span>
<span class="comment"># Instead of:</span>
<span class="comment"># &gt;&gt; people.map { |p| [p.name, p.address, p.phone] }</span>
<span class="comment">#</span>
<span class="comment"># # map each person to: [person.country.code, person.id]</span>
<span class="comment"># &gt;&gt; people.pluck('country.code', :id)</span>
<span class="comment"># #=&gt; [['US', 1], ['CA', 2], ...]</span>
<span class="comment">#</span>
<span class="keyword">def </span><span class="method">pluck</span><span class="punct">(*</span><span class="ident">args</span><span class="punct">)</span>
<span class="comment"># Thanks to Symbol#to_proc, Enumerable#to_proc and String#to_proc this Just Works(tm)</span>
<span class="ident">map</span><span class="punct">(&amp;</span><span class="ident">args</span><span class="punct">)</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
**Enumerable#pluck**
```ruby
module Enumerable
# Use this to pluck values from objects, especially useful for ActiveRecord models.
# This is analogous to Prototype's Enumerable.pluck method but more powerful.
#
# You can pluck values simply, like so:
# >> people.pluck(:last_name) #=> ['Samhuri', 'Jones', ...]
#
# But with Symbol#to_proc defined this is effectively the same as:
# >> people.map(&:last_name) #=> ['Samhuri', 'Jones', ...]
#
# Where pluck's power becomes evident is when you want to do something like:
# >> people.pluck(:name, :address, :phone)
# #=> [['Johnny Canuck', '123 Maple Lane', '416-555-124'], ...]
#
# Instead of:
# >> people.map { |p| [p.name, p.address, p.phone] }
#
# # map each person to: [person.country.code, person.id]
# >> people.pluck('country.code', :id)
# #=> [['US', 1], ['CA', 2], ...]
#
def pluck(*args)
# Thanks to Symbol#to_proc, Enumerable#to_proc and String#to_proc this Just Works(tm)
map(&args)
end
end
```
I wrote another version without using the various <code>#to_proc</code> methods so as to work with a standard Ruby while only patching 1 module.
<div class="typocode"><pre><code class="typocode_ruby "><span class="keyword">module </span><span class="module">Enumerable</span>
<span class="comment"># A version of pluck which doesn't require any to_proc methods.</span>
<span class="keyword">def </span><span class="method">pluck</span><span class="punct">(*</span><span class="ident">args</span><span class="punct">)</span>
<span class="ident">procs</span> <span class="punct">=</span> <span class="ident">args</span><span class="punct">.</span><span class="ident">map</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">msgs</span><span class="punct">|</span>
<span class="comment"># always operate on lists of messages</span>
<span class="keyword">if</span> <span class="constant">String</span> <span class="punct">===</span> <span class="ident">msgs</span>
<span class="ident">msgs</span> <span class="punct">=</span> <span class="ident">msgs</span><span class="punct">.</span><span class="ident">split</span><span class="punct">('</span><span class="string">.</span><span class="punct">').</span><span class="ident">map</span> <span class="punct">{|</span><span class="ident">a</span><span class="punct">|</span> <span class="ident">a</span><span class="punct">.</span><span class="ident">to_sym</span><span class="punct">}</span> <span class="comment"># allow 'country.code'</span>
<span class="keyword">elsif</span> <span class="punct">!(</span><span class="constant">Enumerable</span> <span class="punct">===</span> <span class="ident">msgs</span><span class="punct">)</span>
<span class="ident">msgs</span> <span class="punct">=</span> <span class="punct">[</span><span class="ident">msgs</span><span class="punct">]</span>
<span class="keyword">end</span>
<span class="constant">Proc</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">orig</span><span class="punct">|</span>
<span class="ident">msgs</span><span class="punct">.</span><span class="ident">inject</span><span class="punct">(</span><span class="ident">orig</span><span class="punct">)</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">thing</span><span class="punct">,</span> <span class="ident">msg</span><span class="punct">|</span> <span class="ident">thing</span> <span class="punct">=</span> <span class="ident">thing</span><span class="punct">.</span><span class="ident">send</span><span class="punct">(</span><span class="ident">msg</span><span class="punct">)</span> <span class="punct">}</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
```ruby
module Enumerable
# A version of pluck which doesn't require any to_proc methods.
def pluck(*args)
procs = args.map do |msgs|
# always operate on lists of messages
if String === msgs
msgs = msgs.split('.').map {|a| a.to_sym} # allow 'country.code'
elsif !(Enumerable === msgs)
msgs = [msgs]
end
Proc.new do |orig|
msgs.inject(orig) { |thing, msg| thing = thing.send(msg) }
end
end
<span class="keyword">if</span> <span class="ident">procs</span><span class="punct">.</span><span class="ident">size</span> <span class="punct">==</span> <span class="number">1</span>
<span class="ident">map</span><span class="punct">(&amp;</span><span class="ident">procs</span><span class="punct">.</span><span class="ident">first</span><span class="punct">)</span>
<span class="keyword">else</span>
<span class="ident">map</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">thing</span><span class="punct">|</span>
<span class="ident">procs</span><span class="punct">.</span><span class="ident">map</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">proc</span><span class="punct">|</span> <span class="ident">proc</span><span class="punct">.</span><span class="ident">call</span><span class="punct">(</span><span class="ident">thing</span><span class="punct">)</span> <span class="punct">}</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
if procs.size == 1
map(&procs.first)
else
map do |thing|
procs.map { |proc| proc.call(thing) }
end
end
end
end
```
It's just icing on the cake considering Ruby's convenient block syntax, but there it is. Do with it what you will. You can change or extend any of these to support drilling down into hashes quite easily too.

View file

@ -14,9 +14,11 @@ Anyway I was very pleased to see the only correct usage of the phrase "begs the
This describes a perfectly legitimate mathematical function. We could use it to recognize whether one number is the square root of another, or to derive facts about square roots in general. On the other hand, the definition does not describe a procedure. Indeed, it tells us almost nothing about how to actually find the square root of a given number. It will not help matters to rephrase this definition in pseudo-Lisp:
<pre><code>(define (sqrt x)
```scheme
(define (sqrt x)
(the y (and (= y 0)
(= (square y) x))))</code></pre>
(= (square y) x))))
```
<strong>This only begs the question.</strong>
</blockquote>

View file

@ -14,76 +14,20 @@ Tags: [emacs, textmate]
Despite my current infatuation with Emacs there are many reasons I started using TextMate, especially little time-savers that are very addictive. I'll talk about one of those features tonight. When you have text selected in TextMate and you hit say the <code>'</code> (single quote) then TextMate will surround the selected text with single quotes. The same goes for double quotes, parentheses, brackets, and braces. This little trick is one of my favourites so I had to come up with something similar in Emacs. It was easy since a <a href="http://osdir.com/ml/emacs.nxml.general/2005-08/msg00002.html">mailing list post</a> has a solution for surrounding the current region with tags, which served as a great starting point.
<pre class="line-numbers">1
2
3
4
5
6
7
</pre>
<pre><code>(defun surround-region-with-tag (tag-name beg end)
```lisp
(defun surround-region-with-tag (tag-name beg end)
(interactive "sTag name: \nr")
(save-excursion
(goto-char beg)
(insert "&lt;" tag-name "&gt;")
(insert "<" tag-name ">")
(goto-char (+ end 2 (length tag-name)))
(insert "&lt;/" tag-name "&gt;")))</code></pre>
(insert "</" tag-name ">")))
```
With a little modification I now have the following in my ~/.emacs file:
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
16
17
18
19
<strong>20</strong>
21
22
23
24
25
26
27
28
29
<strong>30</strong>
31
32
33
34
35
36
37
38
39
<strong>40</strong>
41
42
43
44
45
46
47
</pre>
<pre><code>;; help out a TextMate junkie
```lisp
;; help out a TextMate junkie
(defun wrap-region (left right beg end)
"Wrap the region in arbitrary text, LEFT goes to the left and RIGHT goes to the right."
@ -103,7 +47,7 @@ With a little modification I now have the following in my ~/.emacs file:
(interactive)
(if (and mark-active transient-mark-mode)
(call-interactively 'wrap-region-with-tag)
(insert "&lt;")))
(insert "<")))
(defun wrap-region-with-tag (tag beg end)
"Wrap the region in the given HTML/XML tag using `wrap-region'. If any
@ -111,10 +55,10 @@ attributes are specified then they are only included in the opening tag."
(interactive "*sTag (including attributes): \nr")
(let* ((elems (split-string tag " "))
(tag-name (car elems))
(right (concat "&lt;/" tag-name "&gt;")))
(right (concat "</" tag-name ">")))
(if (= 1 (length elems))
(wrap-region (concat "&lt;" tag-name "&gt;") right beg end)
(wrap-region (concat "&lt;" tag "&gt;") right beg end))))
(wrap-region (concat "<" tag-name ">") right beg end)
(wrap-region (concat "<" tag ">") right beg end))))
(defun wrap-region-or-insert (left right)
"Wrap the region with `wrap-region' if an active region is marked, otherwise insert LEFT at point."
@ -129,7 +73,8 @@ attributes are specified then they are only included in the opening tag."
(global-set-key "(" (wrap-region-with-function "(" ")"))
(global-set-key "[" (wrap-region-with-function "[" "]"))
(global-set-key "{" (wrap-region-with-function "{" "}"))
(global-set-key "&lt;" 'wrap-region-with-tag-or-insert) ;; I opted not to have a wrap-with-angle-brackets</code></pre>
(global-set-key "<" 'wrap-region-with-tag-or-insert) ;; I opted not to have a wrap-with-angle-brackets
```
&darr; <a href="/f/wrap-region.el" alt="wrap-region.el">Download wrap-region.el</a>

View file

@ -10,24 +10,8 @@ Tags: [elschemo, haskell, scheme]
The first task is extending the <code>LispVal</code> type to grok floats.
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
</pre>
<pre><code>type LispInt = Integer
```haskell
type LispInt = Integer
type LispFloat = Float
-- numeric data types
@ -41,30 +25,22 @@ data LispVal = Atom String
| Number LispNum
| Char Char
| String String
| ...</code></pre>
| ...
```
The reason for using the new <code>LispNum</code> type and not just throwing a new <code>Float Float</code> constructor in there is so that functions can accept and operate on parameters of any supported numeric type. First the floating point numbers need to be parsed. For now I only parse floating point numbers in decimal because the effort to parse other bases is too great for the benefits gained (none, for me).
ElSchemo now parses negative numbers so I'll start with 2 helper functions that are used when parsing both integers and floats:
<pre class="line-numbers">1
2
3
4
5
6
7
</pre>
<pre><code>parseSign :: Parser Char
```haskell
parseSign :: Parser Char
parseSign = do try (char '-')
&lt;|&gt; do optional (char '+')
<|> do optional (char '+')
return '+'
applySign :: Char -&gt; LispNum -&gt; LispNum
applySign sign n = if sign == '-' then negate n else n</code></pre>
applySign :: Char -> LispNum -> LispNum
applySign sign n = if sign == '-' then negate n else n
```
<code>parseSign</code> is straightforward as it follows the convention that a literal number is positive unless explicitly marked as negative with a leading minus sign. A leading plus sign is allowed but not required.
@ -72,94 +48,64 @@ applySign sign n = if sign == '-' then negate n else n</code></pre>
Armed with these 2 functions we can now parse floating point numbers in decimal. Conforming to R5RS an optional <code>#d</code> prefix is allowed.
<pre class="line-numbers">1
2
3
4
5
6
7
8
</pre>
<pre><code>parseFloat :: Parser LispVal
```haskell
parseFloat :: Parser LispVal
parseFloat = do optional (string "#d")
sign &lt;- parseSign
whole &lt;- many1 digit
sign <- parseSign
whole <- many1 digit
char '.'
fract &lt;- many1 digit
fract <- many1 digit
return . Number $ applySign sign (makeFloat whole fract)
where makeFloat whole fract = Float . fst . head . readFloat $ whole ++ "." ++ fract</code></pre>
where makeFloat whole fract = Float . fst . head . readFloat $ whole ++ "." ++ fract
```
The first 6 lines should be clear. Line 7 simply applies the parsed sign to the parsed number and returns it, delegating most of the work to <code>makeFloat</code>. <code>makeFloat</code> in turn delegates the work to the <code>readFloat</code> library function, extracts the result and constructs a <code>LispNum</code> for it.
The last step for parsing is to modify <code>parseExpr</code> to try and parse floats.
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
</pre>
<pre><code>-- Integers, floats, characters and atoms can all start with a # so wrap those with try.
```haskell
-- Integers, floats, characters and atoms can all start with a # so wrap those with try.
-- (Left factor the grammar in the future)
parseExpr :: Parser LispVal
parseExpr = (try parseFloat)
&lt;|&gt; (try parseInteger)
&lt;|&gt; (try parseChar)
&lt;|&gt; parseAtom
&lt;|&gt; parseString
&lt;|&gt; parseQuoted
&lt;|&gt; do char '('
x &lt;- (try parseList) &lt;|&gt; parseDottedList
<|> (try parseInteger)
<|> (try parseChar)
<|> parseAtom
<|> parseString
<|> parseQuoted
<|> do char '('
x <- (try parseList) <|> parseDottedList
char ')'
return x
&lt;|&gt; parseComment</code></pre>
<|> parseComment
```
### Displaying the floats ###
That's it for parsing, now let's provide a way to display these suckers. <code>LispVal</code> is an instance of show, where <code>show</code> = <code>showVal</code> so <code>showVal</code> is our first stop. Remembering that <code>LispVal</code> now has a single <code>Number</code> constructor we modify it accordingly:
```haskell
showVal (Number n) = showNum n
<pre class="line-numbers">1
2
3
4
5
6
7
</pre>
<pre><code>showVal (Number n) = showNum n
showNum :: LispNum -&gt; String
showNum :: LispNum -> String
showNum (Integer contents) = show contents
showNum (Float contents) = show contents
instance Show LispNum where show = showNum</code></pre>
instance Show LispNum where show = showNum
```
One last, and certainly not least, step is to modify <code>eval</code> so that numbers evaluate to themselves.
eval env val@(Number _) = return val
```haskell
eval env val@(Number _) = return val
```
There's a little more housekeeping to be done such as fixing <code>integer?</code>, <code>number?</code>, implementing <code>float?</code> but I will leave those as an exercise to the reader, or just wait until I share the full code. As it stands now floating point numbers can be parsed and displayed. If you fire up the interpreter and type <code>2.5</code> or <code>-10.88</code> they will be understood. Now try adding them:
(+ 2.5 1.1)
Invalid type: expected integer, found 2.5
```scheme
(+ 2.5 1.1)
Invalid type: expected integer, found 2.5
```
Oops, we don't know how to operate on floats yet!
@ -167,79 +113,8 @@ Oops, we don't know how to operate on floats yet!
Parsing was the easy part. Operating on the new floats is not necessarily difficult, but it was more work than I realized it would be. I don't claim that this is the best or the only way to operate on any <code>LispNum</code>, it's just the way I did it and it seems to work. There's a bunch of boilerplate necessary to make <code>LispNum</code> an instance of the required classes, Eq, Num, Real, and Ord. I don't think I have done this properly but for now it works. What is clearly necessary is the code that operates on different types of numbers. I think I've specified sane semantics for coercion. This will be very handy shortly.
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
16
17
18
19
<strong>20</strong>
21
22
23
24
25
26
27
28
29
<strong>30</strong>
31
32
33
34
35
36
37
38
39
<strong>40</strong>
41
42
43
44
45
46
47
48
49
<strong>50</strong>
51
52
53
54
55
56
57
58
59
<strong>60</strong>
61
62
63
64
65
66
67
68
69
<strong>70 </strong>
</pre>
<pre><code>lispNumEq :: LispNum -&gt; LispNum -&gt; Bool
```haskell
lispNumEq :: LispNum -> LispNum -> Bool
lispNumEq (Integer arg1) (Integer arg2) = arg1 == arg2
lispNumEq (Integer arg1) (Float arg2) = (fromInteger arg1) == arg2
lispNumEq (Float arg1) (Float arg2) = arg1 == arg2
@ -247,35 +122,35 @@ lispNumEq (Float arg1) (Integer arg2) = arg1 == (fromInteger arg2)
instance Eq LispNum where (==) = lispNumEq
lispNumPlus :: LispNum -&gt; LispNum -&gt; LispNum
lispNumPlus :: LispNum -> LispNum -> LispNum
lispNumPlus (Integer x) (Integer y) = Integer $ x + y
lispNumPlus (Integer x) (Float y) = Float $ (fromInteger x) + y
lispNumPlus (Float x) (Float y) = Float $ x + y
lispNumPlus (Float x) (Integer y) = Float $ x + (fromInteger y)
lispNumMinus :: LispNum -&gt; LispNum -&gt; LispNum
lispNumMinus :: LispNum -> LispNum -> LispNum
lispNumMinus (Integer x) (Integer y) = Integer $ x - y
lispNumMinus (Integer x) (Float y) = Float $ (fromInteger x) - y
lispNumMinus (Float x) (Float y) = Float $ x - y
lispNumMinus (Float x) (Integer y) = Float $ x - (fromInteger y)
lispNumMult :: LispNum -&gt; LispNum -&gt; LispNum
lispNumMult :: LispNum -> LispNum -> LispNum
lispNumMult (Integer x) (Integer y) = Integer $ x * y
lispNumMult (Integer x) (Float y) = Float $ (fromInteger x) * y
lispNumMult (Float x) (Float y) = Float $ x * y
lispNumMult (Float x) (Integer y) = Float $ x * (fromInteger y)
lispNumDiv :: LispNum -&gt; LispNum -&gt; LispNum
lispNumDiv :: LispNum -> LispNum -> LispNum
lispNumDiv (Integer x) (Integer y) = Integer $ x `div` y
lispNumDiv (Integer x) (Float y) = Float $ (fromInteger x) / y
lispNumDiv (Float x) (Float y) = Float $ x / y
lispNumDiv (Float x) (Integer y) = Float $ x / (fromInteger y)
lispNumAbs :: LispNum -&gt; LispNum
lispNumAbs :: LispNum -> LispNum
lispNumAbs (Integer x) = Integer (abs x)
lispNumAbs (Float x) = Float (abs x)
lispNumSignum :: LispNum -&gt; LispNum
lispNumSignum :: LispNum -> LispNum
lispNumSignum (Integer x) = Integer (signum x)
lispNumSignum (Float x) = Float (signum x)
@ -287,50 +162,32 @@ instance Num LispNum where
signum = lispNumSignum
fromInteger x = Integer x
lispNumToRational :: LispNum -&gt; Rational
lispNumToRational :: LispNum -> Rational
lispNumToRational (Integer x) = toRational x
lispNumToRational (Float x) = toRational x
instance Real LispNum where
toRational = lispNumToRational
lispIntQuotRem :: LispInt -&gt; LispInt -&gt; (LispInt, LispInt)
lispIntQuotRem :: LispInt -> LispInt -> (LispInt, LispInt)
lispIntQuotRem n d = quotRem n d
lispIntToInteger :: LispInt -&gt; Integer
lispIntToInteger :: LispInt -> Integer
lispIntToInteger x = x
lispNumLessThanEq :: LispNum -&gt; LispNum -&gt; Bool
lispNumLessThanEq (Integer x) (Integer y) = x &lt;= y
lispNumLessThanEq (Integer x) (Float y) = (fromInteger x) &lt;= y
lispNumLessThanEq (Float x) (Integer y) = x &lt;= (fromInteger y)
lispNumLessThanEq (Float x) (Float y) = x &lt;= y
instance Ord LispNum where (&lt;=) = lispNumLessThanEq</code></pre>
lispNumLessThanEq :: LispNum -> LispNum -> Bool
lispNumLessThanEq (Integer x) (Integer y) = x <= y
lispNumLessThanEq (Integer x) (Float y) = (fromInteger x) <= y
lispNumLessThanEq (Float x) (Integer y) = x <= (fromInteger y)
lispNumLessThanEq (Float x) (Float y) = x <= y
instance Ord LispNum where (<=) = lispNumLessThanEq
```
Phew, ok with that out of the way now we can actually extend our operators to work with any type of <code>LispNum</code>. Our Scheme operators are defined using the functions <code>numericBinop</code> and <code>numBoolBinop</code>. First we'll slightly modify our definition of <code>primitives</code>:
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
</pre>
<pre><code>primitives :: [(String, [LispVal] -&gt; ThrowsError LispVal)]
```haskell
primitives :: [(String, [LispVal] -> ThrowsError LispVal)]
primitives = [("+", numericBinop (+)),
("-", subtractOp),
("*", numericBinop (*)),
@ -339,94 +196,57 @@ primitives = [("+", numericBinop (+)),
("quotient", integralBinop quot),
("remainder", integralBinop rem),
("=", numBoolBinop (==)),
("&lt;", numBoolBinop (&lt;)),
("&gt;", numBoolBinop (&gt;)),
("<", numBoolBinop (<)),
(">", numBoolBinop (>)),
("/=", numBoolBinop (/=)),
("&gt;=", numBoolBinop (&gt;=)),
("&lt;=", numBoolBinop (&lt;=)),
...]</code></pre>
(">=", numBoolBinop (>=)),
("<=", numBoolBinop (<=)),
...]
```
Note that <code>mod</code>, <code>quotient</code>, and <code>remainder</code> are only defined for integers and as such use <code>integralBinop</code>, while division (/) is only defined for floating point numbers using <code>floatBinop</code>. <code>subtractOp</code> is different to support unary usage, e.g. <code>(- 4) =&gt; -4</code>, but it uses <code>numericBinop</code> internally when more than 1 argument is given. On to the implementation! First extend <code>unpackNum</code> to work with any <code>LispNum</code>, and provide separate <code>unpackInt</code> and <code>unpackFloat</code> functions to handle both kinds of <code>LispNum</code>.
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
</pre>
<pre><code>unpackNum :: LispVal -&gt; ThrowsError LispNum
```haskell
unpackNum :: LispVal -> ThrowsError LispNum
unpackNum (Number (Integer n)) = return $ Integer n
unpackNum (Number (Float n)) = return $ Float n
unpackNum notNum = throwError $ TypeMismatch "number" notNum
unpackInt :: LispVal -&gt; ThrowsError Integer
unpackInt :: LispVal -> ThrowsError Integer
unpackInt (Number (Integer n)) = return n
unpackInt (List [n]) = unpackInt n
unpackInt notInt = throwError $ TypeMismatch "integer" notInt
unpackFloat :: LispVal -&gt; ThrowsError Float
unpackFloat :: LispVal -> ThrowsError Float
unpackFloat (Number (Float f)) = return f
unpackFloat (Number (Integer f)) = return $ fromInteger f
unpackFloat (List [f]) = unpackFloat f
unpackFloat notFloat = throwError $ TypeMismatch "float" notFloat</code></pre>
unpackFloat notFloat = throwError $ TypeMismatch "float" notFloat
```
The initial work of separating integers and floats into the <code>LispNum</code> abstraction, and the code I said would be handy shortly, are going to be really handy here. There's relatively no change in <code>numericBinop</code> except for the type signature. <code>integralBinop</code> and <code>floatBinop</code> are just specific versions of the same function. I'm sure there's a nice Haskelly way of doing this with less repetition, and I welcome such corrections.
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
16
17
18
</pre>
<pre><code>numericBinop :: (LispNum -&gt; LispNum -&gt; LispNum) -&gt; [LispVal] -&gt; ThrowsError LispVal
```haskell
numericBinop :: (LispNum -> LispNum -> LispNum) -> [LispVal] -> ThrowsError LispVal
numericBinop op singleVal@[_] = throwError $ NumArgs 2 singleVal
numericBinop op params = mapM unpackNum params &gt;&gt;= return . Number . foldl1 op
numericBinop op params = mapM unpackNum params >>= return . Number . foldl1 op
integralBinop :: (LispInt -&gt; LispInt -&gt; LispInt) -&gt; [LispVal] -&gt; ThrowsError LispVal
integralBinop :: (LispInt -> LispInt -> LispInt) -> [LispVal] -> ThrowsError LispVal
integralBinop op singleVal@[_] = throwError $ NumArgs 2 singleVal
integralBinop op params = mapM unpackInt params &gt;&gt;= return . Number . Integer . foldl1 op
integralBinop op params = mapM unpackInt params >>= return . Number . Integer . foldl1 op
floatBinop :: (LispFloat -&gt; LispFloat -&gt; LispFloat) -&gt; [LispVal] -&gt; ThrowsError LispVal
floatBinop :: (LispFloat -> LispFloat -> LispFloat) -> [LispVal] -> ThrowsError LispVal
floatBinop op singleVal@[_] = throwError $ NumArgs 2 singleVal
floatBinop op params = mapM unpackFloat params &gt;&gt;= return . Number . Float . foldl1 op
floatBinop op params = mapM unpackFloat params >>= return . Number . Float . foldl1 op
subtractOp :: [LispVal] -&gt; ThrowsError LispVal
subtractOp num@[_] = unpackNum (head num) &gt;&gt;= return . Number . negate
subtractOp :: [LispVal] -> ThrowsError LispVal
subtractOp num@[_] = unpackNum (head num) >>= return . Number . negate
subtractOp params = numericBinop (-) params
numBoolBinop :: (LispNum -&gt; LispNum -&gt; Bool) -&gt; [LispVal] -&gt; ThrowsError LispVal
numBoolBinop op params = boolBinop unpackNum op params</code></pre>
numBoolBinop :: (LispNum -> LispNum -> Bool) -> [LispVal] -> ThrowsError LispVal
numBoolBinop op params = boolBinop unpackNum op params
```
That was a bit of work but now ElSchemo supports floating point numbers, and if you're following along then your Scheme might too if I haven't missed any important details!
Next time I'll go over some of the special forms I have added, including short-circuiting <code>and</code> and <code>or</code> forms and the full repetoire of <code>let</code>, <code>let*</code>, and <code>letrec</code>. Stay tuned!

View file

@ -14,11 +14,14 @@ It's been a little while since I wrote about Haskell and the <a href="/posts/200
Last time I left off at parsing <a href="http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_sec_6.3.5">R5RS compliant numbers</a>, which is exercise 3.3.4 if you're following along the tutorial. Only integers in binary, octal, decimal, and hexadecimal are parsed right now. The syntaxes for those are <code>#b101010</code>, <code>#o52</code>, <code>42</code> (or <code>#d42</code>), and <code>#x2a</code>, respectively. To parse these we use the <code>readOct</code>, <code>readDec</code>, <code>readHex</code>, and <code>readInt</code> functions provided by the Numeric module, and import them thusly:
import Numeric (readOct, readDec, readHex, readInt)
```haskell
import Numeric (readOct, readDec, readHex, readInt)
```
In order to parse binary digits we need to write a few short functions to help us out. For some reason I couldn't find <code>binDigit</code>, <code>isBinDigit</code> and <code>readBin</code> in their respective modules but luckily they're trivial to implement. The first two are self-explanatory, as is the third if you look at the <a href="http://www.cse.ogi.edu/~diatchki/MonadTransformers/pfe.cgi?Numeric">implementation</a> of its relatives for larger bases. In a nutshell <code>readBin</code> says to: "read an integer in base 2, validating digits with <code>isBinDigit</code>."
<pre><code>-- parse a binary digit, analagous to decDigit, octDigit, hexDigit
```haskell
-- parse a binary digit, analagous to decDigit, octDigit, hexDigit
binDigit :: Parser Char
binDigit = oneOf "01"
@ -28,24 +31,30 @@ isBinDigit c = (c == '0' || c == '1')
-- analogous to readDec, readOct, readHex
readBin :: (Integral a) = ReadS a
readBin = readInt 2 isBinDigit digitToInt</code></pre>
readBin = readInt 2 isBinDigit digitToInt
```
The next step is to augment <code>parseNumber</code> so that it can handle R5RS numbers in addition to regular decimal numbers. To refresh, the tutorial's <code>parseNumber</code> function looks like this:
parseNumber :: Parser LispVal
parseNumber = liftM (Number . read) $ many1 digit
```haskell
parseNumber :: Parser LispVal
parseNumber = liftM (Number . read) $ many1 digit
```
Three more lines in this function will give us a decent starting point:
parseNumber = do char '#'
base <- oneOf "bdox"
parseDigits base
```haskell
parseNumber = do char '#'
base <- oneOf "bdox"
parseDigits base
```
Translation: First look for an R5RS style base, and if found call <code>parseDigits</code> with the given base to do the dirty work. If that fails then fall back to parsing a boring old string of decimal digits.
That brings us to actually parsing the numbers. <code>parseDigits</code> is simple, but there might be a more Haskell-y way of doing this.
<pre><code>-- Parse a string of digits in the given base.
```haskell
-- Parse a string of digits in the given base.
parseDigits :: Char - Parser LispVal
parseDigits base = many1 d >>= return
where d = case base of
@ -53,7 +62,7 @@ parseDigits base = many1 d >>= return
'd' -> digit
'o' -> octDigit
'x' -> hexDigit
</code></pre>
```
The trickiest part of all this was figuring out how to use the various <code>readFoo</code> functions properly. They return a list of pairs so <code>head</code> grabs the first pair and <code>fst</code> grabs the first element of the pair. Once I had that straight it was smooth sailing. Having done this, parsing R5RS characters (#\a, #\Z, #\?, ...) is a breeze so I won't bore you with that.
@ -61,27 +70,17 @@ The trickiest part of all this was figuring out how to use the various <code>rea
It still takes me some time to knit together meaningful Haskell statements. Tonight I spent said time cobbling together an implementation of <a href="http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-7.html#%_sec_4.1.5">cond</a> as a new special form. Have a look at the code. The explanation follows.
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
</pre>
<pre><code>eval env (List (Atom "cond" : List (Atom "else" : exprs) : [])) =
```haskell
eval env (List (Atom "cond" : List (Atom "else" : exprs) : [])) =
liftM last $ mapM (eval env) exprs
eval env (List (Atom "cond" : List (pred : conseq) : rest)) =
do result &lt;- eval env $ pred
do result <- eval env $ pred
case result of
Bool False -&gt; case rest of
[] -&gt; return $ List []
_ -&gt; eval env $ List (Atom "cond" : rest)
_ -&gt; liftM last $ mapM (eval env) conseq</code></pre>
Bool False -> case rest of
[] -> return $ List []
_ -> eval env $ List (Atom "cond" : rest)
_ -> liftM last $ mapM (eval env) conseq
```
* __Lines 1-2:__ Handle <code>else</code> clauses by evaluating the given expression(s), returning the last result. It must come first or it's overlapped by the next pattern.
* __Line 3:__ Evaluate a <code>cond</code> by splitting the first condition into <strong>predicate</strong> and <strong>consequence</strong>, tuck the remaining conditions into <code>rest</code> for later.
@ -93,4 +92,3 @@ eval env (List (Atom "cond" : List (pred : conseq) : rest)) =
* __Line 9:__ Anything other than <code>#f</code> is considered true and causes <code>conseq</code> to be evaluated and returned. Like <code>else</code>, <code>conseq</code> can be a sequence of expressions.
So far my Scheme weighs in at 621 lines, 200 more than the tutorial's final code listing. Hopefully I'll keep adding things on my TODO list and it will grow a little bit more. Now that I have <code>cond</code> it will be more fun to expand my stdlib.scm as well.

View file

@ -12,22 +12,15 @@ Recently I had looked at converting Typo to Mephisto and it seemed pretty painle
After running that code snippet to fix my tags, I decided to completely ditch categories in favour of tags. I tagged each new Mephisto article with a tag for each Typo category it had previously belonged to. I fired up <code>RAILS_ENV=production script/console</code> and typed something similar to the following:
<pre class="line-numbers">1
2
3
4
5
6
7
</pre>
<pre><code>require <span class="s"><span class="dl">'</span><span class="k">converters/base</span><span class="dl">'</span></span>
require <span class="s"><span class="dl">'</span><span class="k">converters/typo</span><span class="dl">'</span></span>
articles = <span class="co">Typo</span>::<span class="co">Article</span>.find(<span class="sy">:all</span>).map {|a| [a, <span class="co">Article</span>.find_by_permalink(a.permalink)] }
articles.each <span class="r">do</span> |ta, ma|
<span class="r">next</span> <span class="r">if</span> ma.nil?
ma.tags &lt;&lt; <span class="co">Tag</span>.find_or_create(ta.categories.map(&amp;<span class="sy">:name</span>))
<span class="r">end</span></code></pre>
```ruby
require 'converters/base'
require 'converters/typo'
articles = Typo::Article.find(:all).map {|a| [a, Article.find_by_permalink(a.permalink)] }
articles.each do |ta, ma|
next if ma.nil?
ma.tags << Tag.find_or_create(ta.categories.map(&:name))
end
```
When I say something similar I mean exactly that. I just typed that from memory so it may not work, or even be syntactically correct. If any permalinks changed then you'll have to manually add new tags corresponding to old Typo categories. The only case where this bit me was when I had edited the title of an article, in which case the new Mephisto permalink matched the new title while the Typo permalink matched the initial title, whatever it was.

View file

@ -10,79 +10,47 @@ This last week I've been getting to know <a href="http://chneukirchen.org/blog/a
I did hit a little snag with functional testing though. The method of declaring which controller to use takes the form:
<pre class="line-numbers">
</pre>
<pre><code>use_controller <span class="sy">:foo</span></code></pre>
```ruby
use_controller :foo
```
and can be placed in the <code>setup</code> method, like so:
```ruby
# in test/functional/sessions_controller_test.rb
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
14
15
</pre>
<pre><code><span class="c"># in test/functional/sessions_controller_test.rb</span>
context "A guest" do
fixtures :users
context <span class="s"><span class="dl">"</span><span class="k">A guest</span><span class="dl">"</span></span> <span class="r">do</span>
fixtures <span class="sy">:users</span>
setup do
use_controller :sessions
end
setup <span class="r">do</span>
use_controller <span class="sy">:sessions</span>
<span class="r">end</span>
specify <span class="s"><span class="dl">"</span><span class="k">can login</span><span class="dl">"</span></span> <span class="r">do</span>
post <span class="sy">:create</span>, <span class="sy">:username</span> =&gt; <span class="s"><span class="dl">'</span><span class="k">sjs</span><span class="dl">'</span></span>, <span class="sy">:password</span> =&gt; <span class="s"><span class="dl">'</span><span class="k">blah</span><span class="dl">'</span></span>
response.should.redirect_to user_url(users(<span class="sy">:sjs</span>))
specify "can login" do
post :create, :username => 'sjs', :password => 'blah'
response.should.redirect_to user_url(users(:sjs))
...
<span class="r">end</span>
<span class="r">end</span></code></pre>
end
end
```
This is great and the test will work. But let's say that I have another controller that guests can access:
```ruby
# in test/functional/foo_controller_test.rb
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
<strong>10</strong>
11
12
13
</pre>
<pre><code><span class="c"># in test/functional/foo_controller_test.rb</span>
context "A guest" do
setup do
use_controller :foo
end
context <span class="s"><span class="dl">"</span><span class="k">A guest</span><span class="dl">"</span></span> <span class="r">do</span>
setup <span class="r">do</span>
use_controller <span class="sy">:foo</span>
<span class="r">end</span>
specify <span class="s"><span class="dl">"</span><span class="k">can do foo stuff</span><span class="dl">"</span></span> <span class="r">do</span>
get <span class="sy">:fooriffic</span>
status.should.be <span class="sy">:success</span>
specify "can do foo stuff" do
get :fooriffic
status.should.be :success
...
<span class="r">end</span>
<span class="r">end</span></code></pre>
end
end
```
This test will pass on its own as well, which is what really tripped me up. When I ran my tests individually as I wrote them, they passed. When I ran <code>rake test:functionals</code> this morning and saw over a dozen failures and errors I was pretty alarmed. Then I looked at the errors and was thoroughly confused. Of course the action <strong>fooriffic</strong> can't be found in <strong>SessionsController</strong>, it lives in <strong>FooController</strong> and that's the controller I said to use! What gives?!

View file

@ -16,7 +16,6 @@ that means the code here is for me to get some feedback as much
as to show others how to do this kind of stuff. This may not be too
interesting if you haven't at least browsed the tutorial.
I'm going to cover 3 new special forms: <code>and</code>, <code>or</code>, and <code>cond</code>. I
promised to cover the <code>let</code> family of special forms this time around
but methinks this is long enough as it is. My sincere apologies if
@ -45,25 +44,16 @@ concise language. My explanations may be redundant because of this.
### lispAnd ###
<pre class="line-numbers">1
2
3
4
5
6
7
8
</pre>
<pre><code>lispAnd :: Env -&gt; [LispVal] -&gt; IOThrowsError LispVal
```haskell
lispAnd :: Env -> [LispVal] -> IOThrowsError LispVal
lispAnd env [] = return $ Bool True
lispAnd env [pred] = eval env pred
lispAnd env (pred:rest) = do
result &lt;- eval env pred
result <- eval env pred
case result of
Bool False -&gt; return result
_ -&gt; lispAnd env rest</code></pre>
Bool False -> return result
_ -> lispAnd env rest
```
Starting with the trivial case, <code>and</code> returns <code>#t</code> with zero
arguments.
@ -84,25 +74,16 @@ just complicates things but it's a viable solution.
Predictably this is quite similar to <code>lispAnd</code>.
<pre class="line-numbers">1
2
3
4
5
6
7
8
</pre>
<pre><code>lispOr :: Env -&gt; [LispVal] -&gt; IOThrowsError LispVal
```haskell
lispOr :: Env -> [LispVal] -> IOThrowsError LispVal
lispOr env [] = return $ Bool False
lispOr env [pred] = eval env pred
lispOr env (pred:rest) = do
result &lt;- eval env pred
result <- eval env pred
case result of
Bool False -&gt; lispOr env rest
_ -&gt; return result</code></pre>
Bool False -> lispOr env rest
_ -> return result
```
With no arguments <code>lispOr</code> returns <code>#f</code>, and with one argument it
evaluates and returns the result.
@ -117,33 +98,23 @@ First let me define a convenience function that I have added to
ElSchemo. It maps a list of expressions to their values by evaluating
each one in the given environment.
<pre class="line-numbers">1
2
</pre>
<pre><code>evalExprs :: Env -&gt; [LispVal] -&gt; IOThrowsError [LispVal]
evalExprs env exprs = mapM (eval env) exprs</code></pre>
```haskell
evalExprs :: Env -> [LispVal] -> IOThrowsError [LispVal]
evalExprs env exprs = mapM (eval env) exprs
```
### lispCond ###
Again, <code>lispCond</code> has the same type as <code>eval</code>.
<pre class="line-numbers">1
2
3
4
5
6
</pre>
<pre><code>lispCond :: Env -&gt; [LispVal] -&gt; IOThrowsError LispVal
```haskell
lispCond :: Env -> [LispVal] -> IOThrowsError LispVal
lispCond env (List (pred:conseq) : rest) = do
result &lt;- eval env pred
result <- eval env pred
case result of
Bool False -&gt; if null rest then return result else lispCond env rest
_ -&gt; liftM last $ evalExprs env conseq</code></pre>
Bool False -> if null rest then return result else lispCond env rest
_ -> liftM last $ evalExprs env conseq
```
Unlike Lisp which uses a predicate of <code>T</code> (true) Scheme uses a
predicate of <code>else</code> to trigger the default branch. When the pattern
@ -164,15 +135,11 @@ expressions and return the value of the last one.
Now all that's left is to hook up the new functions in <code>eval</code>.
<pre class="line-numbers">1
2
3
</pre>
<pre><code>eval env (List (Atom "and" : params)) = lispAnd env params
```haskell
eval env (List (Atom "and" : params)) = lispAnd env params
eval env (List (Atom "or" : params)) = lispOr env params
eval env (List (Atom "cond" : params)) = lispCond env params</code></pre>
eval env (List (Atom "cond" : params)) = lispCond env params
```
You could, of course, throw the entire definitions in <code>eval</code> itself but <code>eval</code> is big
enough for me as it is. YMMV.

View file

@ -21,21 +21,8 @@ Now that you know what to do I'll give you what you probably wanted at the begin
&darr; <a href="/f/gtkpod-aac-fix.sh">gtkpod-aac-fix.sh</a>
<pre class="line-numbers">1
2
3
4
5
6
7
8
9
10
11
12
</pre>
<pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><code>mkdir /tmp/gtkpod-fix
```shell
mkdir /tmp/gtkpod-fix
cd /tmp/gtkpod-fix
wget http://ftp.uni-kl.de/debian-multimedia/pool/main/libm/libmpeg4ip/libmp4v2-0_1.5.0.1-0.3_amd64.deb
wget http://ftp.uni-kl.de/debian-multimedia/pool/main/libm/libmpeg4ip/libmp4v2-dev_1.5.0.1-0.3_amd64.deb
@ -44,6 +31,7 @@ wget http://ftp.uni-kl.de/debian-multimedia/pool/main/libm/libmpeg4ip/libmpeg4ip
for f in *.deb; do sudo gdebi -n "$f"; done
svn co https://gtkpod.svn.sourceforge.net/svnroot/gtkpod/gtkpod/trunk gtkpod
cd gtkpod
./autogen.sh --with-mp4v2 &amp;&amp; make &amp;&amp; sudo make install
./autogen.sh --with-mp4v2 && make && sudo make install
cd
rm -rf /tmp/gtkpod-fix</code></pre>
rm -rf /tmp/gtkpod-fix
```

View file

@ -8,10 +8,10 @@ Tags: [arc, project euler]
Release early and often. This is a code repo web app for solutions to <a href="http://projecteuler.net/">Project Euler</a> problems. You can only see your own solutions so it's not that exciting yet (but it scratches my itch... once it highlights syntax). You can <a href="http://nofxwiki.net:3141/euler">try it out</a> or <a href="https://samhuri.net/euler.tgz">download the source</a>. You'll need an up-to-date copy of <a href="http://arcfn.com/2008/02/git-and-anarki-arc-repository-brief.html">Anarki</a> to untar the source in. Just run <strong>arc.sh</strong> then enter this at the REPL:
<pre><code>arc&gt; (load "euler.arc")
arc&gt; (esv)
</code></pre>
```lisp
arc> (load "euler.arc")
arc> (esv)
```
That will setup the web server on port 3141. If you want a different port then run <code>(esv 25)</code> (just to mess with 'em).

View file

@ -45,17 +45,15 @@ blob of machine code. That blob could be described by a single
section named \_\_text, inside a single nameless segment. Here's a
diagram showing the layout of such a file:</p>
<pre>
```markdown
,---------------------------,
Header | Mach header |
| Segment 1 |
| Section 1 (__text) | --,
|---------------------------| |
Data | blob | &lt;-'
Data | blob | <-'
'---------------------------'
</pre>
```
<h2>The Mach Header</h2>
@ -71,7 +69,6 @@ CStruct</a> we define the Mach header like so:</p>
<script src="https://gist.github.com/280635.js" integrity="mDxjhIjSzfTrTGCoJEal7X5EowTQWcPyyE9xuDaRH4Al5wWVemvfjJr3WT0QCOGA" crossorigin="anonymous"></script>
<h2>Segments</h2>
<p>Segments, or <b>segment commands</b>, specify where in memory the
@ -92,7 +89,6 @@ be easy enough to follow.</p>
<script src="https://gist.github.com/280642.js" integrity="eY3t12vnVg5AdETSbfxWASVlAMXw8Ti7m7V2siEe9AmPncn5rckLDlh5jWBGYBbJ" crossorigin="anonymous"></script>
<h2>Sections</h2>
<p>All sections within a segment are described one after the other
@ -115,7 +111,6 @@ two underscores, e.g. \_\_bss or \_\_text</p>
<script src="https://gist.github.com/280643.js" integrity="TTawOAzAxNuDvbcDU7DXvkoK6vBygkHd1Web2mk2sKx9iCK1ZOnWUPU9tZUDFzig" crossorigin="anonymous"></script>
<h2>macho.rb</h2>
<p>As much of the Mach-O format as we need is defined in
@ -126,7 +121,6 @@ constants as well.</p>
<p>I'll cover symbol tables and relocation tables in my next post.</p>
<h2>Looking at real Mach-O files</h2>
<p>To see the segments and sections of an object file, run
@ -145,7 +139,6 @@ also disassemble the \_\_text section with
<p>You'll get to know otool quite well if you work with Mach-O.</p>
<h2>Take a break</h2>
<p>That was probably a lot to digest, and to make real sense of it you

View file

@ -14,7 +14,8 @@ Tags: [37signals, chalk, ipad, javascript, web, html, css, zepto.js]
<p>The manifest is a nice summary of the contents, and allows browsers to cache the app for offline use. Combine this with mobile Safari's "Add to Home Screen" button and you have yourself a free chalkboard app that works offline.</p>
<pre><code>CACHE MANIFEST
```conf
CACHE MANIFEST
/
/zepto.min.js
@ -26,7 +27,7 @@ Tags: [37signals, chalk, ipad, javascript, web, html, css, zepto.js]
/images/chalk-tile-red.png
/images/chalk-tile-white.png
/stylesheets/chalk.css
</code></pre>
```
<p>Not much there, just 10 requests to fetch the whole thing. 11 including the manifest. In we go.</p>
@ -170,7 +171,6 @@ chalk-sprites.png </div>
<p>&nbsp;</p>
<script src="https://gist.github.com/664260.js?file=chalk-shade.js" integrity="mJqbDt7at8NZ71dB7ItvDOdAKnEzyfVHTRcz0l10vbA0ts1noJ7p9vms8nY4XmZ1" crossorigin="anonymous"></script>
<p>When the light switch is touched (or clicked) the shade class on the body element is toggled. Nothing to it.</p>
<p>&nbsp;</p>

View file

@ -35,17 +35,23 @@ Yup, that is a lot of moving parts. It is rather elegant in a [Unixy way](http:/
For example, the following lines would be created in a file at `~/Dropbox/Linky/Ruxton/<generated filename>.txt` for my machine named [Ruxton](http://en.wikipedia.org/wiki/Ruxton_Island).
Callbacks as our Generations' Go To Statement
http://tirania.org/blog/archive/2013/Aug-15.html
```markdown
Callbacks as our Generations' Go To Statement
http://tirania.org/blog/archive/2013/Aug-15.html
```
The filename field is defined as:
{FromAddress}-{ReceivedAt}
```conf
{FromAddress}-{ReceivedAt}
```
And the content is:
{Subject}<br/>
{BodyPlain}<br/>
```conf
{Subject}<br/>
{BodyPlain}<br/>
```
That means that when you email links, the subject should contain the title and the body should contain the link on the first line. It's ok if there's stuff after the body (like your signature), they will be ignored later.
@ -63,7 +69,9 @@ This is a quick and dirty thing I whipped up a couple of years ago, and now it's
It has a text configuration file kind of like [cron](http://en.wikipedia.org/wiki/Cron). Here's mine from Ruxton:
+ Dropbox/Linky/Ruxton ruby /Users/sjs/bin/linky-notify
```shell
+ Dropbox/Linky/Ruxton ruby /Users/sjs/bin/linky-notify
```
That tells NorthWatcher to run `ruby /Users/sjs/bin/linky-notify` when files are added to the directory `~/Dropbox/Linky/Ruxton`.
@ -80,4 +88,3 @@ You can get `terminal-notifier` with [homebrew](http://brew.sh) in a few seconds
## Cool story, bro
It may not be exciting, but as someone who typically suffers from [NIH syndrome](http://en.wikipedia.org/wiki/Not_invented_here) and writes too much from scratch, I found it pretty rewarding to cobble something seemingly complicated together with a bunch of existing components. It didn't take very long and only involved about 10 lines of code. It's not exactly what I wanted but it's surprisingly close. Success!

View file

@ -10,7 +10,7 @@ It's not hard to hide a whole lot of complexity behind a function call, so you h
Here's some example code illustrating a big performance problem I found in a codebase I've inherited. We have a dictionary keyed by a string representing a date, e.g. "2016-08-10", and where the values are arrays of videos for that given date. Due to some unimportant product details videos can actually appear in more than one of the array values. The goal is to get an array of all videos, sorted by date, and with no duplicates. So we need to discard duplicates when building the sorted array.
```Swift
```swift
func allVideosSortedByDate(allVideos: [String:[Video]]) -> [Video] {
var sortedVideos: [Video] = []
// sort keys newest first
@ -32,7 +32,7 @@ Because this is being called from within a loop that's already looping over all
In this particular case my first instinct is to reach for a set. We want a collection of all the videos and want to ensure that they're unique, and that's what sets are for. So what about sorting? Well we can build up the set of all videos, then sort that set, converting it to an array in the process. Sounds like a lot of work right? Is it really faster? Let's see what it looks like.
```Swift
```swift
func allVideosSortedByDate(allVideos: [String:[Video]]) -> [Video] {
var uniqueVideos: Set<Video> = []
for key in allVideos.allKeys {

View file

@ -8,7 +8,7 @@ Tags: [iOS, Swift]
Swift compile times leave something to be desired and a common culprit is the affectionately-named [nil-coalescing operator][nilop]. A small extension to `Optional` can improve this without sacrificing a lot of readability.
```Swift
```swift
extension Optional {
func or(_ defaultValue: Wrapped) -> Wrapped {
switch self {
@ -21,7 +21,7 @@ extension Optional {
And you use it like so:
```Swift
```swift
let dict: [String : String] = [:]
let maybeString = dict["not here"]
print("the string is: \(maybeString.or("default"))")

View file

@ -1,181 +0,0 @@
/* Syntax highlighting */
.typocode_ruby .normal {}
.typocode_ruby .comment {
color: #005;
font-style: italic;
}
.typocode_ruby .keyword {
color: #A00;
font-weight: bold;
}
.typocode_ruby .method {
color: #077;
}
.typocode_ruby .class {
color: #074;
}
.typocode_ruby .module {
color: #050;
}
.typocode_ruby .punct {
color: #447;
font-weight: bold;
}
.typocode_ruby .symbol {
color: #099;
}
.typocode_ruby .string {
color: #944;
background: #FFE;
}
.typocode_ruby .char {
color: #F07;
}
.typocode_ruby .ident {
color: #004;
}
.typocode_ruby .constant {
color: #07F;
}
.typocode_ruby .regex {
color: #B66;
background: #FEF;
}
.typocode_ruby .number {
color: #F99;
}
.typocode_ruby .attribute {
color: #7BB;
}
.typocode_ruby .global {
color: #7FB;
}
.typocode_ruby .expr {
color: #227;
}
.typocode_ruby .escape {
color: #277;
}
.typocode_xml .normal {}
.typocode_xml .namespace {
color: #B66;
font-weight: bold;
}
.typocode_xml .tag {
color: #F88;
}
.typocode_xml .comment {
color: #005;
font-style: italic;
}
.typocode_xml .punct {
color: #447;
font-weight: bold;
}
.typocode_xml .string {
color: #944;
}
.typocode_xml .number {
color: #F99;
}
.typocode_xml .attribute {
color: #BB7;
}
.typocode_yaml .normal {}
.typocode_yaml .document {
font-weight: bold;
color: #07F;
}
.typocode_yaml .type {
font-weight: bold;
color: #05C;
}
.typocode_yaml .key {
color: #F88;
}
.typocode_yaml .comment {
color: #005;
font-style: italic;
}
.typocode_yaml .punct {
color: #447;
font-weight: bold;
}
.typocode_yaml .string {
color: #944;
}
.typocode_yaml .number {
color: #F99;
}
.typocode_yaml .time {
color: #F99;
}
.typocode_yaml .date {
color: #F99;
}
.typocode_yaml .ref {
color: #944;
}
.typocode_yaml .anchor {
color: #944;
}
.typocode {
background-color: #eee;
padding: 2px;
margin: 5px;
}
.typocode pre {
padding: 0.2rem 0.5rem;
margin: 0;
border: none;
background: transparent;
font-family: 'Fira Code', 'JetBrains Mono', 'Meslo LG M', 'Inconsolata', 'Menlo', 'Courier New', monospace;
overflow: auto;
}
.typocode .lineno {
text-align: right;
color: #B00;
font-family: 'Fira Code', 'JetBrains Mono', 'Meslo LG M', 'Inconsolata', 'Menlo', 'Courier New', monospace;
padding-right: 1rem;
}