Category Archives: Software

Piumarta and Warth’s Open Objects in Scheme

A Scheme implementation of the object model as described in their paper:

http://piumarta.com/software/cola/objmodel2.pdf

An R6RS version with more examples is located here:

https://github.com/kstephens/open-object-lab

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#lang r5rs
;;; Piumarta and Warth's Open Objects in Scheme.
(define object:tag '(<object>))
(define <vtable>   #f)
(define <object>   #f)
 
(define (object:vt  self)
  (vector-ref  self 1))
(define (object:vt= self value)
  (vector-set! self 1 value))
 
(define (vtable:alloc self size)
  (let ((obj (make-vector (+ size 2))))
    (vector-set! obj 0 object:tag)
    (object:vt= obj self)
    obj))
 
(define (object? self)
  (and (vector? self)
       (>= (vector-length self) 2)
       (eq? (vector-ref self 0) object:tag)))
 
(define (vtable self)
  (cond
    ((object? self)   (object:vt self))
    (else             <object>)))
 
(define (vtable:parent  self)
  (vector-ref  self 2))
(define (vtable:parent= self value)
  (vector-set! self 2 value))
 
(define (vtable:methods  self)
  (vector-ref  self 3))
(define (vtable:methods= self value)
  (vector-set! self 3 value))
 
(define (vtable:with-parent self parent)
  (let ((child (vtable:alloc self 2)))
    (object:vt=      child (and self (vtable self)))
    (vtable:parent=  child parent)
    (vtable:methods= child '())
    child))
 
(define (vtable:delegated self)
  (vtable:with-parent self #f))
 
(define (vtable:add-method self key value)
  (let* ( (methods (vtable:methods self))
          (slot (assq key methods)))
    (if slot
      (set-cdr! slot value)
      (vtable:methods= self (cons (cons key value) methods)))))
 
(define (vtable:lookup self key)
  (let* ((slot (assq key (vtable:methods self))))
    (if slot (cdr slot)
      (if (vtable:parent self)
        (send 'lookup (vtable:parent self) key)))))
 
(define (bind op rcvr)
  (let ((vt (vtable rcvr)))
    (if (and (eq? op 'lookup) (eq? vt <vtable>))
      (vtable:lookup vt op)
      (send 'lookup vt op))))
 
(define (send op self . args)
  (apply (bind op self) self args))
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Bootstrap vtables:
 
(set! <vtable> (vtable:delegated #f))
(object:vt= <vtable> <vtable>)
 
(set! <object> (vtable:delegated #f))
(object:vt= <object> <vtable>)
 
(vtable:parent= <vtable> <object>)
 
(vtable:add-method <vtable> 'lookup      vtable:lookup)
(vtable:add-method <vtable> 'add-method  vtable:add-method)
 
(send 'add-method <vtable> 'alloc      vtable:alloc)
(send 'add-method <vtable> 'delegated  vtable:delegated)
 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Additional vtables for Scheme types:
 
(send 'add-method <vtable> 'with-parent vtable:with-parent)
 
(define <number>  (send 'with-parent <vtable> <object>))
(define <real>    (send 'with-parent <vtable> <number>))
(define <integer> (send 'with-parent <vtable> <real>))
(define <symbol>  (send 'with-parent <vtable> <object>))
 
;; Extend vtable determination into Scheme types:
(set! vtable (lambda (self)
  (cond
    ((integer? self)  <integer>)
    ((real?    self)  <real>)
    ((number?  self)  <number>)
    ((symbol?  self)  <symbol>)
    ((object?  self)  (object:vt self))
    (else             <object>))))
 
(send 'add-method <object>
      'print (lambda (self) (write `(object ,self)) (newline)))
(send 'add-method <vtable>
      'print (lambda (self) (write `(vtable ...)) (newline)))
(send 'add-method <number>
      'print (lambda (self) (write `(number ,self)) (newline)))
(send 'add-method <real>
      'print (lambda (self) (write `(real ,self)) (newline)))
(send 'add-method <integer>
      'print (lambda (self) (write `(integer ,self)) (newline)))
(send 'add-method <symbol>
      'print (lambda (self) (write `(symbol ,self)) (newline)))
 
(send 'print <vtable>)
(send 'print <object>)
(send 'print 'a-symbol)
(send 'print 123)
(send 'print 1234.56)
(send 'print 1/23)
(send 'print '(a cons))

Discrete Event Probablities

My colleague, David, had an interesting problem:

“I want to simulate exceptional events (e.g. I/O errors) at predictable rates.

For example, if an error should occur 33% of the time, it should be predictable like: ERROR, ok, ok, ERROR, ok, ok, ...

Or at 50% error rate: ERROR, ok, ERROR, ok, ...

devdriven:

“Pseudo-random function p(t) in range [0,1) at time t and P is the probability of the event (e.g. I/O error) then: event?(t) = p(t) < P.

Pseudo-random numbers are predictable if you know the seed."

David:

“Not really what I had in mind. There’s got to be a better way…”

Continue reading

Ruby: Thread stack leak patch accepted into REE.

This patch reduces the stack buffer memory footprint of dead Threads as early as possible, rather than waiting until the Thread can be GCed.

This is applicable only to the zero-copy context switch patch.

http://code.google.com/p/rubyenterpriseedition/issues/detail?id=57

http://blog.phusion.nl/2011/02/12/ruby-enterprise-edition-1-8-7-2011-01-released/

Alan Perlis – SICP Quotes

Quotes from preface of Abelson and Sussman’s “Structure and Interpretation of Computer Programs”:

“I think that it’s extraordinarily important that we in computer science keep fun in computing. When it started out, it was an awful lot of fun. Of course, the paying customers got shafted every now and then, and after a while we began to take their complaints seriously. We began to feel as if we really were responsible for the successful, error-free perfect use of these machines. I don’t think we are. I think we’re responsible for stretching them, setting them off in new directions, and keeping fun in the house. I hope the field of computer science never loses its sense of fun. Above all, I hope we don’t become missionaries. Don’t feel as if you’re Bible salesmen. The world has too many of those already. What you know about computing other people will learn. Don’t feel as if the key to successful computing is only in your hands. What’s in your hands, I think and hope, is intelligence: the ability to see the machine as more than when you were first led up to it, that you can make it more.”
—Alan J. Perlis (April 1, 1922 February 7, 1990)

“Is it possible that software is not like anything else, that it is meant to be
discarded: that the whole point is to always see it as a soap bubble?”

ChicagoRuby Ruby Code Tweaks slides, code and video

The slides from my ChicagoRuby 2010/05/04 presentation :

http://kurtstephens.com/pub/ruby/ruby_code_tweaks/

All the raw data used to generate the graph should be referenced in the slides.

The code used to generate the slides is here:

http://github.com/kstephens/ruby_code_tweaks

I’m looking to increase the set of code “Problems” to cover other tiny code idioms and platform issues, for example: regular expressions, numerics, etc. If you have ideas, take a look at the code and contact me.

Justin Love gave a fantastic presentation on lambda and closure.

Thanks to everyone who came — hope it was helpful.

Video from the talk:

Ruby Code Performance Tweaks by Kurt Stephens from ChicagoRuby on Vimeo.

Ruby: Fixnum#gcd accepted into MRI

Ruby rational.rb clean-up and the Fixnum#gcd primitive was refactored into a new MRI extension. Fixnum#gcd is now defined during require ‘rational’.

This dramatically improves performance of Ruby Date class.

http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/ChangeLog?…

http://redmine.ruby-lang.org/issues/show/2561

See http://devdriven.com/2007/03/ruby-date-rational-fixnumgcd-hack-increased-app-performance-by-15/ .

Ruby 1.8: Improved Rational performance by 15%

This should also speed up DateTime. This will not help 1.9 performance.

The attached file is based on MRI 1.8.6 rational.rb.

 > ruby rational_performance.rb 
                                              user     system      total        real
test_it                                  32.930000   3.030000  35.960000 ( 35.971832)
test_it                                  33.840000   2.910000  36.750000 ( 36.758585)
test_it ks_rational                      29.110000   2.460000  31.570000 ( 31.572762)

Overview:

  • case x; when Foo; ...; end is faster than if Foo.kind_of?(x).
  • Avoid recuring on ephemeral objects.
  • Avoid local variables, in-line expressions.
  • Avoid return in tail position.
  • String interpolation: "#{x}/#{y}" is faster than x.to_s + "/" + y.to_s.
  • Implement #-, #zero?, #nonzero? natively.
  • #abs returns self if > 0.

MRI 1.8.7 patch to follow shortly.