Looking at my Scheme code and the way I customize it, I’m starting to see the real reason evil megacorps (and wannabe evil startups) won’t hire even middle-aged programmers or use your favorite weirdo language, they just want young idiots who code Java or Go.
Then maybe 10 years of them being project managers and “architects”, running waterfall and GANTT charts; they’ll say they’re “agile” but then have a giant JIRA repo of “backlog” features which have to be implemented before shipping, weekly 4-hour
planning “backlog grooming” meetings, and unrealistic estimates. This is sufficient to build all kinds of horrible vertical prisons of the mind like Azkaban Facebook.
Then they either retire, or are “downsized”, and now what? So they work on their own code, do maintenance on old systems, or leave the industry entirely.
If they work on their own, freed of evil megacorp constraints, they’re going to end up in something idiosyncratic and expressive, like Scheme, LISP, Forth, or a custom language. Make their own weirdo environment that’s perfectly fit to themself, and unusable/unreadable by anyone else.
Case in point, I needed an object model. There’s one I like in Gerbil, and Gerbil’s blazing fast, but I can’t make a full SDL2 library for it yet (Gambit’s FFI is hard, I’ve hit some bugs, and there’s a LOT of library to interface to), and I’m using a bunch of other Chickenisms anyway, so I can’t really move to it yet. Instead I just made my own simple object libary, with a couple macros to hide the ugly reality behind it:
(test "Object" 'Object (class-name Object))
(let [ (obj (@new Object)) (bug #f) (cow #f) (duck #f) ]
(test "Object-to-string" "[Object]" (@call obj 'to-string))
(define-class Animal Object)
(define-field Animal 'legs 0)
(define-field Animal 'color #f)
(define-method Animal 'init (self legs color)
(set! (@field self 'legs) legs)
(set! (@field self 'color) color) )
(define-method Animal 'speak (self)
(sprintf "The ~A ~A with ~A legs says " (@field self 'color) (class-name (@class self)) (@field self 'legs)) )
(set! bug (@new Animal 6 "green"))
(test "bug-legs" 6 (@field bug 'legs))
(test "bug-color" "green" (@field bug 'color))
(test "Bug speak" "The green Animal with 6 legs says " (@call bug 'speak))
(define-class Cow Animal)
(define-method Cow 'init (self color)
(@super self 'init 4 color) )
(define-method Cow 'speak (self)
(string-append (@super self 'speak) "MOO!") )
(set! cow (@new Cow "brown"))
;; second class to make sure classes don't corrupt shared superclass
(define-class Duck Animal)
(define-method Duck 'init (self color)
(@super self 'init 2 color) )
(define-method Duck 'speak (self)
(string-append (@super self 'speak) "QUACK!") )
(set! duck (@new Duck "black"))
(test "Cow speak" "The brown Cow with 4 legs says MOO!" (@call cow 'speak))
(test "Cow to string" "[Cow color:brown;legs:4]" (@call cow 'to-string))
(test "Duck speak" "The black Duck with 2 legs says QUACK!" (@call duck 'speak))
(test "Duck to string" "[Duck color:black;legs:2]" (@call duck 'to-string))
(test "instance-of?" #t (instance-of? cow Cow))
(test "instance-of? parent" #t (instance-of? cow Animal))
(test "instance-of? grandparent" #t (instance-of? cow Object))
(test "instance-of? cousin-false" #f (instance-of? cow Duck))
(test "instance-of? not an obj-false" #f (instance-of? "wtf" Cow))
The implementation code’s not much longer than the tests, but it’s not quite done for me to show off; I need to switch my macros into non-hygeinic forms so I can get rid of the (self) in define-method, and introduce an Objective-C-like _cmd field for self-reflection, and message-not-understood handling. There’s always more tinkering to do.
Which is great for me, but makes my code an undocumented (mostly) new language, unusable by anyone normal. A giant pile of crap Java program, no matter how old, can be “worked on” (more crap piled on top) by any teenage Bro Coder.
All of which brought to mind The Mote in God’s Eye, where the Motie Engineers over-optimize everything into a tangled mess, and the Watchmaker vermin are even worse, wiring up everything to everything to make new devices. The threat posed by and solution to Scheme programmers, in your usual authoritarian megacorp scenario, is similar to Watchmakers.
^1 Swift is intended to fit this niche much more than weirdo expressive Smalltalk+C Objective-C was, BDSM ^2 to prevent one from writing “bad” code, but it’s not there yet; the reality of low-level software dev can’t be simplified as much as Apple wants, and their C++ developers weren’t up to the task anyway.
^2 Bondage-Domination-Sado-Masochism; aka strict type systems and code flow analysis, that prevent one from writing “bad” code at the cost of annotating everything with types instead of doing useful work. I’m not kink-shaming people who do that for sex, only those who do it to their own software.
^3 Rob Pike has openly said they can’t give a powerful language to newbie Googlers, they mostly just know Java, C, C++, which is why Go is so limited and generic.
^4 Oddly, JS is basically a LISP with really shitty syntax. It’s easy to make trivial, broken junk in it, but it’s also powerful and expressive if you’re an old maniac who understands the Self-based object system.
^5 Oh, fine, but only so I can demonstrate something:
(define (fizzbuzz-test i n s) (if (zero? (modulo i n)) (begin (display s) #t) #f) )
(define (fizzbuzz i)
(unless (any identity (list (fizzbuzz-test i 3 'Fizz) (fizzbuzz-test i 5 'Buzz))) (display i))
(for (i 1 100) (fizzbuzz i))
Totally different structure from the usual loop-if-else repetition and hardcoding of everything, because Scheme encourages coding in small pieces. Of course I wrote my own
for macro which expands to a named let loop; there’s many like it but this one is mine. More Motie engineering.