Finnish court rules CSS ineffective at protecting DVDs
∞It's nice to see people making sane calls on issues like this. Ars has a nice summary and there's also a press release.
It's nice to see people making sane calls on issues like this. Ars has a nice summary and there's also a press release.
is a Gentoo dev and I read his posts via the Gentoo planet (and again on the freedesktop.org planet).
He recently mentioned an idea to foster participation in Gentoo (or any other project) by aggregating personal project plans for people to browse. I thought it sounded cool so I started coding and came up with what I call inspirado.
It's fairly basic so far but it's only a week old. It is RESTful and you can get XML for most pages by appending .xml to the URL (or by using curl and setting the HTTP Accept header). Eventually Atom and/or RSS should be available as well.
Note that everything you see there is purely for testing purposes and any changes you make are most likely going to be blown away.
There are several features on my TODO list but I'd love to hear about any you might have. Write to sami.samhuri@gmail.com if you have suggestions or anything else to say.
(Inspirado is, of course, a Rails app.)
Love it or hate it - even though it's not even out yet - the iPhone has spawned at least 2 good jokes.
The other iPhone lawsuit (GeekCulture.com)
"I'm waiting for the iPhone-shuffle, no display, just a button to call a random person on your contacts list."
NB: My definition of life is slightly skewed by my being somewhat of a geek
Luckily no one in the real world cares if you cheat. Most of life is open-book, but for the times when you just need to find something quick the answer, of course, is to cheat profusely.
I've only checked out a few of the cheat sheets but they are of high quality and their wiki-like nature means if they suck and you have time you can help out. I was very pleased to find that there are a number of zsh cheats already.
They certainly know the way to my heart! Ruby, Rails, TextMate, vim, zsh, screen. That'll do snake. That'll do.
* There are cheats for emacs, jEdit, and e too if TextMate and/or vim don't tickle your fancy.
Here's an easy way to solve a problem that may have nagged you as it did me. Simply using foo.inspect
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 PrettyPrint
module so we just need to use it.
Unfortunately typing
to quickly debug some possibly large object (or collection) can get old fast so we need a shortcut.<%= PP.pp(@something, '') %>
Taking the definition of Object#pp_s
from the extensions project it's trivial to create a helper method to just dump out an object in a reasonable manner.
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 Object#pp_s
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 dump
helper method accordingly in case you decide to change pp_s
in the future.
class Object
def pp_s
pps = StringIO.new
PP.pp(self, pps)
pps.string
end
end
I wanted a method analogous to Prototype's pluck and invoke in Rails for building lists for options_for_select. Yes, I know about options_from_collection_for_select.
I wanted something more general that I can use anywhere - not just in Rails - so I wrote one. In a second I'll introduce Enumerable#pluck
, but first we need some other methods to help implement it nicely.
First you need Symbol#to_proc
, which shouldn't need an introduction. If you're using Rails you have this already.
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 String#to_proc
, which is nearly identical to the Array#to_proc
method I previously wrote about.
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 Enumerable#to_proc
which returns a proc that passes its parameter through each of its members and collects their results. It's easier to explain by example.
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, Enumerable#pluck
for Ruby in all its glory.
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 #to_proc
methods so as to work with a standard Ruby while only patching 1 module.
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
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.
Update #1: Fixed a potential performance issue in Enumerable#to_proc
by saving the results of to_proc
in @procs
.
Some Rails plugins I find useful:
I'd just like to say, bwa ha ha ha!
Summary: Paris Hilton drove with a suspended license and is facing 45 days in jail. Now she's reaching out to lord knows who on her MySpace page to petition The Governator to pardon her. I might cry if I weren't pissing myself laughing.
Paris Hilton is out of her mind, living in some fantasy world separate from Earth. Pathetic doesn't begin to describe this plea for help from her own stupidity. She knowingly and willingly disobeyed the law, got busted, and then proceeded to claim that:
"She provides hope for young people all over the U.S. and the world. She provides beauty and excitement to (most of) our otherwise mundane lives."
I take this as a learning experience. For example, I learned that the US is no longer part of the world.
Flat out crazy, insane, not of sound mind. She is not any sort of hope, inspiration or role model for anyone.
Suddenly I feel the urge to try out Solaris for i386 again. Last time I gave it a shot was when it was first released, and all I ever got out of the CD was a white screen. It's been 2-3 years since then and it should be well-tested. I'll try to install it into a VM first using the ISO and potentially save myself a CD. (I don't even think I have blank CDs lying around anymore, only DVDs.)
The culprit.
gave a Google Tech Talk on some of his ideas of how a modern, global network could work more effectively, and with more trust in the data which changes many hands on its journey to its final destination.
A New Way to Look at Networking
The man is very smart and his ideas are fascinating. He has the experience and knowledge to see the big picture and what can be done to solve some of the new problems we have. He starts with the beginning of the phone networks and then goes on to briefly explain the origins of the ARPAnet, which evolved into the modern Internet and TCP/IP and the many other protocols we use daily (often behind the scenes).
He explains the problems that were faced while using the phone networks for data, and how they were solved by realizing that a new problem had risen and needed a new, different solution. He then goes to explain how the Internet has changed significantly from the time it started off in research centres, schools, and government offices into what it is today (lots of identical bytes being redundantly pushed to many consumers, where broadcast would be more appropriate and efficient).
If you have some time I really suggest watching this talk. I would love to research some of the things he spoke about if I ever got the chance. I'm sure they'll be on my mind anyway and inevitably I'll end up playing around with layering crap onto IPV6 and what not. Deep down I love coding in C and I think developing a protocol would be pretty fun. I'd learn a lot in any case.
I lived in Victoria for over a year before I ever rode the ferry between Vancouver Island and Tsawwassen (ignoring the time I was in BC with my family about 16 years ago, that is). I always just flew in and out of Victoria directly. The ferry is awesome and the view is incredible, navigating through all those little islands. Last time I rode the ferry I snapped this shot. It's possibly the best picture I've taken on that trip.
From Write Yourself a Scheme in 48 hours:
Basically, a monad is a way of saying "there's some extra information attached to this value, which most functions don't need to worry about". In this example, the "extra information" is the fact that this action performs IO, and the basic value is nothing, represented as "()". Monadic values are often called "actions", because the easiest way to think about the IO monad is a sequencing of actions that each might affect the outside world.
I really like this tutorial. I'm only on part 3.3 of 12, parsing, but I'm new to Haskell so I'm learning left, right & centre. The exercises are taking me hours of reading and experimenting, and it's lots of fun! ghc's errors are usually quite helpful and of course ghci is a big help as well.
I'm going to explain one of the exercises because converting between the various syntax for dealing with monads wasn't plainly obvious to me. Perhaps I wasn't paying enough attention to the docs I read. In any case if you're interested in Haskell at all, I recommend the tutorial and if you're stuck on exercise 3.3.1 like I was then come on back here. Whether you're following the tutorial or not the point of this post should stand on its own with a basic knowledge of Haskell.
Last night I rewrote parseNumber
using do
and >>=
(bind) notations (ex. 3.3.1). Here's parseNumber
using the liftM
method given in the tutorial:
parseNumber :: Parser LispVal
parseNumber :: liftM (Number . read) $ many1 digit
Okay that's pretty simple right? Let's break it down, first looking at the right-hand side of the $
operator, then the left.
many1 digit
reads as many decimal digits as it can.Number . read
is a function composition just like we're used to using in math. It applies read
to its argument, then applies Number
to that result.liftM
is concisely and effectively defined elsewhere, and I'll borrow their description:
liftM f m
lets a non-monadic functionf
operate on the contents of monadm
liftM
's type is also quite telling: liftM :: (Monad m) => (a -> b) -> (m a -> m b)
In a nutshell liftM
turns a function from a
to b
to a function from a monad containing a
to a monad containing b
.
That results in a function on the left-hand side of $
, which operates on and outputs a monad. The content of the input monad is a String
. The content of the output monad is a LispVal
(defined earlier in the tutorial). Specifically it is a Number
.
The $
acts similar to a pipe in $FAVOURITE_SHELL
, and is right associative which means the expression on the right is passed to the expression (function) on the left. It's exactly the same as (liftM (Number . read)) (many1 digit)
except it looks cleaner. If you know LISP or Scheme (sadly I do not) then it's analogous to the apply
function.
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. parseNumber
's type is Parser LispVal
(Parser is a monad).
Familiar liftM
method:
parseNumber -> liftM (Number . read) $ many1 digit
Using do
notation:
parseNumber -> do digits <- many1 digit
return $ (Number . read) digits
If you're thinking "Hey a return
, I know that one!" then the devious masterminds behind Haskell are certainly laughing evilly right now. return
simply wraps up it's argument in a monad of some sort. In this case it's the Parser
monad. The return
part may seem strange at first. Since many1 digit
yields a monad why do we need to wrap anything? The answer is that using <-
causes digits
to contain a String
, stripped out of the monad which resulted from many1 digit
. Hence we no longer use liftM
to make (Number . read)
monads, and instead need to use return
to properly wrap it back up in a monad.
In other words liftM
eliminates the need to explicitly re-monadize the contents as is necessary using do
.
Finally, using >>=
(bind) notation:
parseNumber -> many1 digit >>= \digits ->
return $ (Number . read) digits
At this point I don't think this warrants much of an explanation. The syntactic sugar provided by do
should be pretty obvious. Just in case it's not, >>=
passes the contents of its left argument (a monad) to the function on its right. Once again return
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 anything in Haskell. One piece of syntax at a time I am slowly able to understand more of the Haskell found in the wild.
I'm currently working on ex. 3.3.4, which is parsing R5RS compliant numbers (e.g. #o12345670, #xff, #d987). I'll probably write something about that once I figure it out, but in the meantime if you have any hints I'm all ears.
Update #1: I should do more proof-reading if I'm going to try and explain things. I made some changes in wording.
I've been really frustrated with Typo recently. For some reason changing my last post would cause MySQL to timeout and I'd have to kill the rogue ruby process manually before any other changes to the DB would work, instead of hanging for a minute or two then timing out. Luckily I was able to disable the post using the command line client, the bug only manifested itself when issuing an UPDATE with all the fields present. Presumably the body was tripping things up because most other fields are simple booleans, numbers, or very short strings.
Add to that the random HTTP 500 errors which were very noticeable while I was trying to fix that post and I was about to write my own blog or switch to WordPress.
I don't love WP so I decided to just upgrade Typo instead. I was using Typo 2.6, and the current stable version is 4.1. They skipped version 3 to preclude any confusion that may have ensued between Typo v3 and the CMS Typo3. So it really isn't a big upgrade and it went perfectly. I checked out a new copy of the repo because I had some difficulty getting svn switch --relocate
to work, configured the database settings and issued a rake db:migrate
, copied my theme over and it all just worked. Bravo Typo team, that's how an upgrade should work.
No more random 500 errors, things seem faster (better caching perhaps), and that troublesome post is troublesome no more. I am happy with Typo again.