not meta-programming
class Object
alias :orig_method_missing :method_missing
def method_missing name, *args
pred = name.to_s[/^not_(\w+\?)/, 1]
orig_method_missing name, *args unless pred
not self.__send__ pred.intern, *args
end
end
Example
irb(main):013:0> nil.not_nil?
=> false
irb(main):014:0> [].not_empty?
=> false
irb(main):015:0> [1,2,3].not_empty?
=> true
irb(main):016:0> [].not_not_empty?
=> true
Sets as predicates
Being inspired by the SICP, Sets can be represented as predicates to decide whether element is a member of the set. Translating to scheme,
(define (make-set pred?) pred?)
(define (element-of-set? x set) (set x))
So we can define sets of multiples.
(define (multiples n)
(make-set (lambda (x) (= 0 (remainder n x)))))
(define multiples-of-2 (multiples 2))
(define multiples-of-3 (multiples 3))
Some operations can be also defined.
(define (union-set set1 set2)
(lambda (el) (or (set1 el) (set2 el))))
(define (intersection-set set1 set2)
(lambda (el) (and (set1 el) (set2 el))))
(define (complement-set set)
(lambda (el) (not (set el))))
And we can get
(define multiples-of-6 (intersection-set multiples-of-2 multiples-of-3))
(define evens (multiples 2))
(define odds (complement-set evens))
(define integers (union-set evens odds))
(define empty-set (lambda (_) #f))
(define whole-set (complement-set empty-set))
In this way, self-containing set can be defined.
(define s
(let1 p (lambda (a) (eq? 'quux a))
(union-set (make-set p) (make-set (lambda (e) (element-of-set? 'quux e))))))
(element-set? s s) will be evaluated to #t. So let’s make set of self-containing set.
Encode the Russell’s paradox into S-expression!
(define russell-set
(make-set (lambda (s) (element-of-set? s s))))
Of course, (element-of-set? s russell-set) is #t. But when trying to evaluate (element-of-set? russell-set russell-set), we encounter infinite loop or stack overflow.
Overwriting quote
Breaks everything silently.
(define 'boom (list boom boom boom))
;; so '1 is evluated to (1 1 1)
Last night, I’ve finished reading Slaughter House 5 by Kurt Vonnegut Jr. It is translated into Japanese by Norio Ito.
Strange behavior
Today I worked with ShowS to construct String efficiently. When I use these ShowS as Monoid, They behaves strangely for me.
Prelude Data.Monoid> mconcat (map showString ["foo","bar","baz"]) . showString "!" $ ""
"foo!bar!baz!"
Here I expected the expression would return “foobarbaz!”, with analogy of String.
This is because of the instance of Monoid b => Monoid (a -> b) in Data.Monoid, the instance is defined as:
instance Monoid b => Monoid (a -> b) where
mempty _ = mempty
mappend f g x = f x `mappend` g x
Fine. But here it makes unexpected behavior (to me) for ShowS’ mappend.
So what I wanted is, just composing ShowS
Prelude Data.Monoid> foldr (.) id (map showString ["foo","bar","baz"]) . showString "!" $ ""
"foobarbaz!"
or Endo Monoid
Prelude Data.Monoid> (appEndo $ mconcat (map (Endo . showString) ["foo","bar","baz"])) . showString "!" $ ""
"foobarbaz!"
Despair
findDataBy :: (Data -> Bool) -> Seed -> [Data]
findDataBy pred seed = filter pred . generateDataFrom $ seed
generateDataFrom :: Seed -> [Data]
generateDataFrom = findDataBy (const True)
HTTP Server in 3 Lines
But I prefer recursion rather than iteration.
if nc -lp 4567 -e "printf \"HTTP/1.0 200 OK\\r\\n\\r\\nHello, World\\r\\n\""; then
exec sh $0
fi
Random Mizutama Background

Source:
<body>
<script>
var cvs = document.createElement('canvas');
cvs.width = 150; cvs.height = 150;
function rand (n) {
return Math.floor(Math.random() * n);
}
function randBetween (min, max) {
return rand(max - min) + min;
}
function randomColor () {
var colors = 'indigo lavender fuchsia khaki honeydew olive deeppink'.split(/\s+/);
return colors[rand(colors.length)];
}
function randomBGColor () {
var colors = 'lightblue lightgreen'.split(/\s+/);
return colors[rand(colors.length)];
}
with(cvs.getContext('2d')) {
fillStyle = randomBGColor();
fillRect(0, 0, cvs.width, cvs.height);
var span = 4, rad = 10
for (var i = 0; i < span; i++) for (var j = 0; j < span; j++) {
beginPath();
fillStyle = randomColor();
arc( randBetween( cvs.width * i / span + rad, cvs.width * (i + 1) / span - rad ),
randBetween( cvs.height * j / span + rad, cvs.height * (j + 1) / span - rad),
rad, 0, Math.PI * 2, true );
fill();
}
}
document.body.style.backgroundImage = 'url(' + cvs.toDataURL() + ')'
</script>
<div style="background-color: white; font-size: 12px; position: absolute">
Mizutama!
</div>
</body>
Each reload, different background image!