Anarchaia
I’ve been starting another blog—complementary to chris blogs—,
Anarchaia. Maybe someday I’ll
join both, but for now I feel better if the “weird content” sticks on
a different site. Maybe I’ll mirror things that fit to both, I
haven’t decided that yet. Subscribe to both. :-)
Interesting is how Anarchaia’s blog entries work, I use
Vooly to augment the HTML (think of
augmented reality), to insert common patterns. A post on how that
works will follow.
As a side note, I’m in Munich till Saturday evening, so do not expect
me to read mail or update any blog.
NP: Suicide Commando—Acid Bath
The T Object-System (in Ruby)
The T programming
language is a
dialect of Scheme developed during the 1980’s at Yale university. In
it’s manual, it
says:
T is a dialect of Lisp derived from Scheme. It is comparable in
power and expressivness to other recent Lisp dialects such as Lisp
Machine Lisp, Common Lisp, and NIL, but fundamentally more similar
in spirit to Scheme than these other Lisp dialects.
T is an attempt to create a powerful and expressive language which
is portable, efficient, and suitable for a broad variety of
applications, including symbolic, numerical, and systems
programming.
T draws from many sources in its attempt to provide a complete yet
simple and unified system. For the most part, the language’s
designers are collators, not originators. Common Lisp, NIL, and
Scheme have been the strongest influences.
The manual contains a lot of interesting stuff, the one I found most
interesting however is T’s object-system. This object system is so
easy (one could say trivial), but still so powerful and flexible that
you just need to admire it.
Basically, there are two procedures to implement the T object-system,
OBJECT and OPERATION. OBJECT takes two parameters, a value proc
that gets called if the object itself gets called (I leave that out in
the Ruby version, since it only makes sense with Lisp-1s and rarely
has an use anyway), and a list of handlers, each element consisting
of an symbol and an lambda. OBJECT returns a new object that
responds to the handlers given.
In my Ruby re-implementation, we would write:
# An object responding to `op'
obj = TObject.new(:op => lambda { |s| 34 })
obj.op # => 34
The first parameter of the lambda is used to pass
self, but you
can pass several arguments, of course:
# An object responding to `op'
obj2 = TObject.new(:op => lambda { |s, x| x })
obj2.op(55) # => 55
As you can see, we already have polymorphism. So far, this is not
very spectacular, though. The really interesting things about the T
object-system are operations and joins.
T operations are like methods of Object in Ruby. They are used as a
default everywhere except you did override them (In my Ruby
reimplementation, operations are only defined for TObjects, not for
every datatype as in T):
# An operation to do `op'
TObject.operation(:op) { |s|
:zebu # By default, return :zebu
}
TObject.new(:op => lambda { |s| :quagga }).op # => :quagga
TObject.new({}).op # => :zebu
So far, the object-system is rather boring, there is no real
instantiation, no mixins, no singleton classes, all the cool stuff
from Ruby is lacking. :-) Enter JOIN, it takes an unlimited number
of objects and combines their behavior:
foo = TObject.new(:foo => lambda { |s| :foo })
bar = TObject.new(:bar => lambda { |s| :bar })
joined = TObject.join(foo, bar)
joined.foo # => :foo
joined.bar # => :bar
Now, I can’t think of anything (except method_missing, which easily
could be handled as a special-case) that’s possible in Ruby’s
object-system, but not T’s.
(You may argue that the T object-system lacks instance variables, but
those can easily be replaced with accessable closures, which both T
and Ruby have.)
Another nice thing about the T object-system is that it’s soo easy to
implement (20 lines of Ruby), that you could quickly write it in
low-level lanuages as C as a foundation for a future programming
language.
By the way, here is the T object-system in Ruby:
class TObject
attr_reader :handlers
@@operations = {}
def self.operation(name, &block)
@@operations[name] = block
end
def self.join(*args)
TObject.new(args.inject({}) { |a, e| a.merge e.handlers })
end
def initialize(handlers)
@handlers = handlers
end
def method_missing(name, *args)
(@handlers[name] or @@operations[name]).call self, *args
end
end
NP: Interpol—Next Exit
Best Of Quotes
Das Beste der besten Quotes von März 2004 bis März 2005:
Lehrer:
I want to fuck you! I want to
fuck you!
Wenigstens seid ihr witzig… es gibt auch dumme Leute, die nicht
witzig sind!
Man hat das ja gesehen, im 3. Reich mit der Zivilcourage — die
hatten ja alle den Schwanz im Arsch.
[meint: eingezogen.]
Ich war Ministrant, Oberministrant natürlich. Willkommen in der
Gosse!
do re mi fa so le mi o
[die italienische Tonleiter]
… und als das mit den KZs bekannt wurde, war natürlich der Ofen aus
mit der Freundlichkeit.
Kompetzen
(was haben wir gelacht…)
Wie heißt ihr Friseur?
— Du siehst aber auch nicht besser
aus, oder?
Glotzt nicht so romantisch!
Schüler:
Hat’s schon geklingelt?
— Keine Ahnung. In meinem Kopf
klingelt’s ständig!
Du warst doch nicht da, als der Jesus gekreuzigt wurde!
— Ja zum Glück! Sonst hätt’ ich noch drauf geschossen!
Und ich, hacke Zug aus’m dicht.
I love you.
[Zum Englischlehrer als Demonstration von Ironie.]
Ich bin genau um halb zehn geboren!
— Pünktlich zu
Knoppers!
Die ist schwanger!
— Toll!
— Nee, gar nicht! Was
meinsch’ wie die danach aussieht!
Guck mal! Bert hat ‘ne Gehhilfe mit Licht!
[Herr Körner schiebt einen Tageslichtprojektor vor sich…]
Ich bin ein Kamasutrababe, bums mich ins Koma!
He did studies in “black holes.”
He, Frau Riggenbach, schön braun sind sie geworden!
— Ond an mords Sonnabrand aufm Zinka!
Wer meint, das was fehlt, darf mir gern seine eigene Zusammenstellung
mailen.
NP: Pearl Jam—Elderly Woman Behind The Counter
One Year of "chris blogs"
Today, exactly one year ago, I started this
blog. Actually, I didn’t
expect I could keep it current for a that long time. (My former blog,
started in January 2003 died before March 2003). But, as you see,
somehow I managed it, though.
Maybe it’s time for a few interesting facts:
The 5 most played artists were:
41 Bob Dylan
26 Pearl Jam
20 Dan Bern
07 Die toten Hosen
06 Interpol
The raw entries are 1.1 megabytes in 264 files.
The blogging tool I used at the very beginning was 127 lines of Ruby
code. When I wanted monthly archives, the thing broke and had 166
lines of Ruby. Nukumi2 as of now ~2000 LoC and 400 lines of
templates. It worked better than everything before, but I still
have new ideas all the time. :-)
I posted about 471 quotes directly taken out of real-life. A
Best-Of will follow.
I wish you happy Easter or whatever you happen to celebrate on the
first sunday after the first fullmoon after the vernal equinox.
Now, on to the next year of blogging!
NP: Pearl Jam—State Of Love And Trust
Byrne's Euclid
Paul Graham’s
last second to last essay,
“Undergraduation”
contains as a footnote a link to Byrne’s
Euclid,
[a]n unusual and attractive edition of Euclid […] published in
1847 in England, edited by an otherwise unknown mathematician named
Oliver Byrne. It covers the first 6 books of Euclid’s Elements of
Geometry, which range through most of elementary plane geometry and
the theory of proportions. What distinguishes Byrne’s edition is
that he attempts to present Euclid’s proofs in terms of pictures,
using as little text - and in particular as few labels - as
possible. What makes the book especially striking is his use of
colour. […]
It really looks like an excellent book, especially if you are easily
confused by short identifiers (that is, one char), possibly indexed
by another char. (I get reminded of Knuth’s “The Art Of Computer
Programming”…)
Still, the use of no identifiers at all, but graphics everywhere
can get pretty confusing,
too.
NP: Dan Bern—Too Late To Die Young
Vooly
This is one of these ideas I wished I had about a century ago, because
the “world” would have been much better then. I’m talking about my
new metalanguage. “Oh, no!”, I hear you scream… “Not another
metalanguage! Isn’t it enough we already have XML and YAML and OGML
and RLML?”
Yes, you have. And they solve their job. XML is a ok format for
writing websites and manuals, but it sucks for RPC, for example. YAML
is a nice format for config files, but I don’t like indenting all my
text. Every metalanguage was made with a reason, and that (at least,
should) be the part where it’s really good at. For the other parts,
most languages suck.
Vooly surely is no difference here. It was made by me to allow for
expressing hierarchical, as free-form as possible data with low cost
of markup (almost no escaping), userfriendlyness (you can learn the
language in 2 minutes, I promise) and extremely (not to say trivial)
implementation. I already wrote two implementations of it in Ruby,
one Push-API and the same again for pulling. Both are about 30 lines
of pretty Ruby. :-)
Vooly is soo damn easy, everyone can pick it up in two minutes. A
Vooly document is a text file, for example, let’s markup an recipe:
Cuba Libre
- 2 ounces Rum (White)
- 3/4 ounce Lime Juice
- 5 ounces Cola
Put lime juice and a twist of lime into highball glass. Add
rum and fill with cola.
Now, let’s markup the different parts of the document, by surrounding
them with << and >>:
<<
<< Cuba Libre >>
<<
<< 2 ounces Rum (White) >>
<< 3/4 ounce Lime Juice >>
<< 5 ounces Cola >>
>>
<<
<< Put lime juice and a twist of lime into highball glass. >>
<< Add rum and fill with cola. >>
>>
>>
Now, add information about what’s between the tags by writing it
directly after the tags where this makes sense:
<<recipe
<<drink Cuba Libre >>
<<ingredients
<< 2 ounces Rum (White) >>
<< 3/4 ounce Lime Juice >>
<< 5 ounces Cola >>
>>
<<steps
<< Put lime juice and a twist of lime into highball glass. >>
<< Add rum and fill with cola. >>
>>
>>
That’s it, you’re done! See, Vooly is soo easy. :-)
With this knowledge, you can apply Vooly to just about everything.
Make your own Vooly-RSS, Vooly-RFC822, Vooly-DocBook today! (Don’t
forget converters to take over the world :-))
Heck, you can even embed XML or YAML if that makes sense to get your
job done. There shouldn’t be any escaping problems, simply stuff your
things in there. (I need to further specify what happens if you want
to insert <<, a rather rare sequence of chars in ordinary text.)
Ruby libraries to do cool stuff with Vooly are soon to come.
NP: Bob Dylan—Tomorrow Is A Long Time
Various hacking
I worked over the weekend on various things. First, I fixed
darcsum.el to strip/convert
ANSI character sequeces, since several people complained. Thanks to
Jose Antonio Ortega Ruiz and Matthieu Lemerre for reporting this.
Please darcs pull to grab the latest changes.
Then, I spent some more time on
Kashmir/Elusion and added a “Do What I
Mean” mode. For example, instead of
^entries.each{
^recent?.true?{NEW}
^body
^time.with{^day/^month/^year}
}
You can now write (assuming you use Elusion):
^entries{
^recent?{NEW}
^body
^time{^day/^month/^year}
}
Elusion will then figure out on it’s own what you want to do (If there
is an #each, iterate. If it’s true, just call the block. Else
yield self to the block.) Also, you can now pass a block to
Kashmir#expand to automatically create an Elusion.
Now, there is a restartable
exception library to be
coded…
NP: Bob Dylan—Knockin’ On Heaven’s Door
Waldsterben & Trockenperiode
Sprüche aus dem WG, wo die Schließzeiten an den Türen kürzer sind als
in der Jugendstrafvollzugsanstalt, Mathestunden verwechselt, Zillen
gebaut, Kurse gewählt werden und die Hälfte der Klasse in Amerika
ist. Trotzdem ist
einiges passiert:
I want to fuck you! I want to
fuck you!
Was ist ein Altersheimausflug ins Grüne?
—
Waldsterben.
Was ist ein Tropfen Blut in der Wüste?
—
Trockenperiode.
Die Frau wurde [früher] verheiratet. Wir kennen Gegenden, wo das
heute noch so ist…
— Kreuzberg!
Laber nicht!
verschlägern
Jesus wäre über einen Kreuzbandriss froh gewesen.
In einer gewissen Scheisse… äh, Weise.
Die Menschen mussten arbeiten bis sie starben. Nur um zu überleben.
Konjunktiv Futur 2½
Loch Ness ist ‘ne Schlampe.
Identitätsbildung in der Jugend: Ausweise fälschen.
Ausser Konkurrenz:
Ah, ich bin stolz darauf wenig gegessen zu haben.
Das hat mir jetzt aber garnicht geschmeckt.
NP: Dan Bern—Jail
Kashmir
Overview
Kashmir is an advanced templating
engine for Ruby featuring an easy, pragmatic syntax and efficient
generated code.
Kashmir tries to walk on the small path between the mess of raw
evaluated Ruby like ERB and the clinical sterileness of data-driven
templating like Amrita.
Kashmir encourages you to define a Model for your View and call its
methods, but allows you as well to evaluate any code you want (though
you never have to).
Kashmir can provide automatic escaping of generated output to lower
the possibility of cross-side scripting attacks.
Kashmir is output-format agnostic, it can be used to generate all kind
of text files.
Kashmir ships with Elusion, an easy to use helper-library to realize
Amrita2-like active templates.
Documentation can be found at
http://chneukirchen.org/repos/kashmir/README.
History
- March 18, 2005: First public release 0.2.
Getting it
You can download Kashmir at
http://chneukirchen.org/releases/kashmir-0.2.0.tar.gz.
Upstream source
You can get latest development releases using
darcs by executing:
darcs get http://chneukirchen.org/repos/kashmir
darcs send is the preferred way to send patches, but mailing diffs
is fine too.
Authors
Kashmir is written by Christian Neukirchen.
Please mail bugs, feature requests or patches to the mail addresses
above or use IRC to contact the
developers.
Copyright
Copyright © 2005 Christian Neukirchen
This work is licensed under the same terms as Ruby itself.
NP: Dan Bern—Five Nothing Lead
Restartable Exceptions
One thing I always liked about Common Lisp is its mighty condition
system. Conditions provide what Exceptions do in Ruby, and more.
Usually, when an Exception is raised in Ruby, it may be rescued by
providing an error handler (possibly even a generic one that displays
an error page in a web application, for example), or ignored, which
will end the program. One thing you cannot do in Ruby is to use
Exceptions to emit warnings, as there is no way to resume the
erroneous code when you are already in the handler.
Not till now, at least. :-) I quickly coded an Common Lispish system
to restart exceptions. It’s best shown by developing a simple
application, so I’ll port the piece of code that explains
Conditions
in Practical Common Lisp.
This is an interactive Ruby description. Fire up your irb and paste
the very last piece of code. Now, please copy and paste the code as
you are reading to try the examples live. Happy hacking.
First, here is the code without any error handling:
class LogAnalyzer
def initialize(logs)
@logs = logs
end
def analyze
@logs.each { |log|
analyze_log log
}
end
def analyze_log(log)
parse_log(log).each { |line|
p line
}
end
def parse_log(log, &block)
entries = []
log.split("\n").each { |line|
entries << parse_log_entry(line)
}
entries
end
def parse_log_entry(line)
line[/^\d+ (\w+)/, 1]
end
end
Let’s call it with three example logs:
def test
LogAnalyzer.new([<<LOGA, <<LOGB, <<LOGC]).analyze
1 foo
2 bar
3 quux
LOGA
"?$%
&)%$
-,$"&
4 good_but_to_late
LOGB
1 foo
bar
3 quux
LOGC
end
test
You now should see this output:
"foo"
"bar"
"quux"
nil
nil
nil
"good_but_to_late"
"foo"
nil
"quux"
All those nils are mistakes in our log files! Eww. We should raise
an error if there is an erroneous line in our logs, and then ignore it
so our program will not totally stop:
class LogAnalyzer
class MalformedLogEntryError < StandardError; end
def parse_log(log, &block)
entries = []
log.split("\n").each { |line|
begin
entries << parse_log_entry(line)
rescue MalformedLogEntryError
# Skip
end
}
entries
end
def parse_log_entry(line)
line[/^\d+ (\w+)/, 1] or raise MalformedLogEntryError
end
end
This will result in (rerun test):
"foo"
"bar"
"quux"
"good_but_to_late"
"foo"
"quux"
Now, this looks much better, but we obviously should tell the user we
had to skip some entries. Now, this is where the trouble starts.
Usually you would not want to put that notification code into
parse_log, because parse_log is really our backend… it should go
to analyze. Here, restartable expections become a need:
class LogAnalyzer
def analyze
@logs.each { |log|
begin
analyze_log log
rescue MalformedLogEntryError => e
warn "Skipped invalid line: #{e.data}"
e.restart :skip_line
end
}
end
def parse_log(log, &block)
entries = []
log.split("\n").each { |line|
begin
entries << parse_log_entry(line)
rescue MalformedLogEntryError => e
e.data = line
e.restart_case(:skip_line) {
# Skip
}
e.handle_restarts
end
}
entries
end
end
Now we get this output:
"foo"
"bar"
"quux"
Skipped invalid line: "?$%
Skipped invalid line: &)%$
Skipped invalid line: -,$"&
"good_but_to_late"
Skipped invalid line: bar
"foo"
"quux"
Ignoring invalid entries is obviously not the only way to handle
invalid logfiles (one could say it’s a rather bad way). We may want
to replace single lines with something different. Let’s implement
this approach, called use_value just like in Common Lisp:
class LogAnalyzer
def analyze
@logs.each { |log|
begin
analyze_log log
rescue MalformedLogEntryError => e
e.restart :use_value, "xyzzy"
end
}
end
def parse_log(log, &block)
entries = []
log.split("\n").each { |line|
begin
entries << parse_log_entry(line)
rescue MalformedLogEntryError => e
e.data = line
e.restart_case(:skip_line) {
# Skip
}
e.restart_case(:use_value) { |replacement|
entries << replacement
}
e.handle_restarts
end
}
entries
end
end
Works beautifully, now all invalid lines get xyzzy:
"foo"
"bar"
"quux"
"xyzzy"
"xyzzy"
"xyzzy"
"good_but_to_late"
"foo"
"xyzzy"
"quux"
To make you see what complex situations you can handle with this
simple code, have a look at this example. We silently ignore wrong
entries, but when the log has more than 2 errors, we skip the whole
thing. Also, lines with bar in it for some reason or another
unfortunately got broken, so let’s restore them on the fly:
class LogAnalyzer
def analyze
@logs.each { |log|
invalid_entries = 0
begin
analyze_log log
rescue MalformedLogEntryError => e
if invalid_entries >= 2
next
elsif e.data =~ /bar/
e.restart :use_value, "BAR"
else
invalid_entries += 1
e.restart :skip_line
end
end
}
end
def parse_log(log, &block)
entries = []
log.split("\n").each { |line|
begin
entries << parse_log_entry(line)
rescue MalformedLogEntryError => e
e.data = line
e.restart_case(:skip_line) {
# Skip
}
e.restart_case(:use_value) { |replacement|
entries << replacement
}
e.handle_restarts
end
}
entries
end
end
Now, look how the very wrong log totally got skipped:
"foo"
"bar"
"quux"
"foo"
"BAR"
"quux"
Finally, here are the extensions to Exception I did to make this
possible (I think I should make that a library):
class Exception
attr_accessor :data
def restart_case(strategy, &block)
@restarts ||= {}
@restarts[strategy] = block
self
end
def handle_restarts
callcc { |@continuation| raise self }
end
def restart(strategy, *params)
@continuation.call(@restarts[strategy].call(*params))
end
end
NP: Bob Dylan—Sara
darcsum.el polished
Since John Wiegley stopped using
darcs, there have been no changes to
darcsum.el, a
fairly good Emacs-mode for interfacing with darcs.
With the update to darcs 1.0.2 darcsum.el even broke, as the look of
the prompts darcs.el waits for has changed. Therefore, I have decided
to “fork” it, fix it for 1.0.2 and add features I always wanted in
darcsum.el.
You can get the latest darcsum.el by running:
darcs get http://chneukirchen.org/repos/darcsum/
Simply stuff the darcsum.el into your load-path and (require 'darcsum).
Run it with M-x darcsum-whatsnew.
Features added by me include a Edit/Update-Log cycle (think of Arch)
and having a look at the context of patches (think diff -u).
NP: Silbermond—1000 Fragen
UUCP revival?
I knew it! UUCP is not dead. Christophe
Prévotaux uses it to securely
fetch lots of
mail.
I think that’s a pretty interesting usecase, escpecially since he
tunnels the UUCP over SSH.
I actually thought about using UUCP for scalable peer-to-peer
networks, but other ideas like RSS over UUCP (even more useful for
podcasts) seem to be pretty good too.
Sean Reifschneider already wrote
about Mobile Mail with
UUCP back in
2004 already. He did not make use of SSH, though:
While SSH is a good system for doing remote, interactive command
execution, UUCP may be better for batched and non-interactive
jobs. It’s certainly worth adding to your toolbox of possible
network transport options.
Then, did anyone try mail over rsync?
NP: Dan Bern—Edmonton
101 Zen Stories
101 Zen Stories contains a
lot of interesting and really good zen stories. One however,
The Moon Cannot Be Stolen,
I like soo much I just gotta have to full-quote it here:
Ryokan, a Zen master, lived the simplest kind of life in a little
hut at the foot of a mountain. One evening a thief visited the hut
only to discover there was nothing in it to steal.
Ryokan returned and caught him. “You may have come a long way to
visit me,” he told the prowler, “and you shoud not return
emptyhanded. Please take my clothes as a gift.”
The thief was bewildered. He took the clothes and slunk away.
Ryokan sat naked, watching the moon. “Poor fellow,” he mused, “I
wish I could give him this beautiful moon.”
NP: Josh Ritter—You’ve Got The Moon
Pizza statt Musik
Und mal wieder Quotes aus dem zauberhaften Wieland-Gymnasium, wo
Silber in Paprika-Gläsern aufbewahrt wird…
…doch Kondome brauch ich nicht, denn ich spritz dir ins Gesicht!
Meine Nippel brennen!
Die Neurose von Jericho
Ich will mal wissen, wie Kreuzzüge überhaupt fahren können.
Sagen wir, du tötest meine Frau; heute sagt man “Prima!”…
Saufen, fressen und fischen
Wann könnt ihr kommen?
— So spät wie möglich.
Was ist eigentlich, wenn ein Ritter während der Schlacht scheissen
muss?
Die heutige Jugend hat von Wagner lieber Pizza als Musik.
Und für die Programmierer unter uns:
“Statische Sprache” ist ein Euphemismus für Stagnation.
NP: Bob Dylan—Licence To Kill
Vlerq, or: Thrive for Ruby
I think it’s always a good thing when you have a weird idea, but
someone implements it independently quite how you thought of it.
That proves your idea was not totally absurd (or you and the other
implementor both are… :-)).
Anyway, this happended to me in the case of
Vlerq. I have thought of the idea of
embedding a small, fast language (I had
retroforth in mind) to write quick inner
loops for data scanning before. Then, I get to know the people that
wrote MetaKit—an embedded
database, easy to use and fairly quick (which admittedly is a lot
easier to do with embedded databases)—are at writing a fast,
embedded Thrill (a dialect of Forth) implementation called
Thrive for querying databases. They
already have early bindings for Tcl and Python, and I’m right now at
coding one for Ruby. The Python binding is less than 250 LOC, so that
won’t take too long.
Unfortunately, noone ever did a Ruby binding for MetaKit, but who
knows, maybe Vlerq will obsolete it. :-)
The source of Thrive
is an excellent example of Huffmann encoding, by the way:
L S cString(P p, I i) { P w = Work(p); I n;
if (i < 0) i += Length(p);
n = lenAt(p[i]);
if (n >= Alloc(p[i].p) || strAt(p[i])[n] != 0) {
S q = strAt(p[i]);
p[i].p = newBuffer(w,0,n+1); Length(p[i].p) = n; p[i].i = -1;
memcpy((M)p[i].p,q,(size_t)n);
}
return strAt(p[i]);
}
Whole Thrive is a single ~630 LOC C header (plus some optional
extensions) and licensed under the MIT License. ;-)
NP: Dan Bern—Black Boys On Mopeds
REBOL and Bluemoon
I’ve been thinking of building a syntactically-easy (not to say:
trivial), but extremely flexible and extensible programming-language
for some months already. I even wrote a sample interpreter for this
language, Bluemoon.
Bluemoon is essentially a stack-based, concatenative language quite
like postscript, but with reversed words. Instead of the Postscript
to calculate, e.g. the BMI (weight / height^2, all code untested):
/weight 60 def % kg
/height 185 def % m
/square { dup mul }
weight height square div
you would write this in Bluemoon:
weight: 60 height: 185
square: { :n
* n n
}
/ * height height weight
This has some beautiful side-effects on thinking in that language, it
not only makes your brain unusable for ever doing Postscript (or
Forth, Joy or Factor) again, but is actually
quite intuitive.
Today, I somehow got the the REBOL page again,
and had another look at it. This way probably the first time I
looked at REBOL since 2001, or
something. I was amazed how similar it was to Bluemoon (rather, the
other way round):
weight: 60
height: 185
square: [n] [n * n]
weight / square height
The main difference is due to REBOL’s syntactic sugar for infix
operators. And it doesn’t open the stack to you. (Last but not
least, Bluemoon is much smaller in it’s design than REBOL, which has
13 core datatypes with unique syntax, even for stuff like “mail address”
and “money”.)
Even more interesting are the similarities related to OO: both use
prototypes and “contexts” (think of scope).
Unfortunately, REBOL never got popular. IMO, this is related to the
lack of a free (as in freedom) reference implementation. It is also
the reason why I won’t use it, and rather build my own stuff. Too
bad, REBOL really seems to have some nice points (small, extremely
portable, easy GUI AFAICS).
On the other hand, having now seen that lots of my ideas were already
implemented by others, maybe I should strive for another language
design… time will tell. :-)
NP: Dan Bern—Fly Away
Darcs repositories moved
I finally came around to moving my darcs to
chneukirchen.org. The old repositories are
still there, but the “Message of the day” will tell you the new location.
As a nice side effect, I also installed darcs.cgi, so you now can
browse my source history.
The new repositories reside at
http://chneukirchen.org/repos.
Happy hacking. Patches to any projects are welcome. :-)
NP: Bob Dylan—Forever Young