- Computers aren't bad or good, they're just machines.
- Programs aren't bad or good, they just do what the programmer typed.
- Programmers are bad.
- Def Leppard is finally available in digital! Hysteria's my favorite of their albums ("Armageddon It" in particular), but all the pre-'90s albums are fantastic, a good mix of NWOBHM blues-metal and pop, and the later ones are fine, just different without Clark. If anything, Rick Allen gets better without one arm slowing him down.
- "Humans from Earth", by T-Bone Burnett
- Hatful of Hollow, by the Smiths "I am Human and I need to be loved", claims Morrissey
- Crash, by the Human League "I was Human, too"
- Felt Mountain, by Goldfrapp "Are you Human, or do you make it up?"
- Replicas Redux, by Gary Numan "I Nearly Married a Human"
- Rock 'n Roll, by the New York Dolls "Human Being"
- Astro-Creep 2000, by White Zombie "More Human Than Human"
- Wizard Bloody Wizard, by Electric Wizard: New last year, I missed this coming out!
- Electric Wizard
- What Happens Next, by Joe Satriani: New album!
- Black Swans and Wormhole Wizards, by Joe Satriani
- Wrong Creatures, by Black Rebel Motorcycle Club: New album! Much more mellow, blues/distortion rock than the last few. I still largely listen to BRMC because I miss Michael Been's band The Call, and his son sometimes does a cover or a little Call-out.
- No Cross No Crown, by Corrosion of Conformity: NEW ALBUM by original lineup!
I go through phases of playing with Scheme for utility code, maybe even portable dev; while FreePascal is a better language for this, I'm frustrated by the lack of library support and the useless iOS situation.
Scheme's always been an emergency backup language; it was fun to learn back in the '80s and early '90s, and both SICP and TSPL are good books, but nobody wanted to pay for Scheme dev, and anyway the language is very annoying to write. I often treat it as a logic puzzle to get anything done, not a useful tool. But it does have good library support, and it can compile to very fast binaries, despite having GC pauses and consuming 2x as much memory as a C program. Maybe I can get better at solving problems in it, build up some libraries, and make it useful?
So the current landscape is:
- Chez Scheme:
- Very fast to compile and at runtime, competitive with C compilers.
- Great interactive REPL, not just a half-broken readline history like pretty much every other Scheme.
- Debugger is reasonably good, and integrated in the REPL. All I really use myself is (trace FOO) and (inspect BAR), but non-caveman coders will make better use of it.
- Current R6RS implementation plus extensive chezscheme library.
- By R. Kent Dybvig, author of TSPL, and Cisco currently employs him to maintain Chez Scheme.
- REPL environment is called a café, which I find charming. Yes, I also liked all the coffee puns and iconography from early Java programming.
- Not as widely supported by tools & documentation as Racket.
- Very nice GUI.
- Current R6RS implementation plus extensive racket library.
- Built around making multiple languages; I don't really care about this. I loathe "Typed Racket", one of the worst combinations of ideas in history.
- Tons of documentation.
- Mediocre performance. There's a project to rehost Racket on Chez Scheme, which would fix this, but then why use Racket?
- Doing anything in the GUI destroys your environment, all the objects you've made, unlike any LISP or Scheme ever. So it's utterly fucking useless as an interactive REPL. I can't say enough bad things about this. ★☆☆☆☆ Kill On Sight.
- Compiles to C and thence to native binaries, with nice FFI to C libraries.
- Mostly old R5RS, with a few extension libraries.
- Terrible REPL, only really usable as a compiled language.
- Scheme R7RS benchmarks
Chez Scheme is the clear winner for me; if I was a novice, I might choose Racket and not realize that the REPL is a broken abomination for a while. If I was only doing C interop, Chicken would be better.
Editing in BBEdit works OK, but it doesn't know how to find function definitions. I guess Vim has current syntax, but I'm kinda over that habit unless I have to sysadmin. I have never been emacsulated and never will.
Atom's symbols list doesn't do any better. But if you do want to use it, install package language-racket (all other language-schemes are R5RS at best), and then add some file types to config.cson:
"*": core: customFileTypes: "source.racket": [ "scm" "ss" ]
In any editor, any language, I use hard tabs (1 char = 1 logical indentation level, obviously), and normally tabstop at 8 chars which discourages very long nesting and encourages me to extract functions. Scheme is indentation hell, so set the tabstop to 4 spaces. (The code blocks below won't show that.)
Do not criticize my C-like paren/brace placement; I prefer clear readability of code structure to some obsolete Emacs dogma.
So, let's see it work, with hello.ss:
#!/usr/bin/env scheme-script (import (chezscheme)) (format #t "Cheers 🍻 , ~a!~%" (car (command-line-arguments))) (exit)
% chmod 755 hello.ss % ./hello.ss Mark Cheers 🍻 , Mark!
Now for something more serious:
;; stdlib.ss ;; Copyright © 2015,2018 by Mark Damon Hughes. All Rights Reserved. (library (stdlib) (export inc! dec! currentTimeMillis randomize input atoi) (import (chezscheme)) ;; Variables (define-syntax inc! (syntax-rules () ((_ x) (begin (set! x (+ x 1)) x)) ((_ x n) (begin (set! x (+ x n)) x)) ) ) (define-syntax dec! (syntax-rules () ((_ x) (inc! x -1)) ((_ x n) (inc! x (- n))) ) ) ;; Date-Time (define (currentTimeMillis) (let [(now (current-time))] (+ (* (time-second now) 1000) (div0 (time-nanosecond now) 1000000)) ) ) ;; Random Numbers ;; "Anyone who attempts to generate random numbers by deterministic means is, of course, living in a state of sin." —John von Neumann (define (randomize) (random-seed (bitwise-and (currentTimeMillis) #xffffffff) ) ) ;; Input/Output ;; Reads a line from stdin, ends program on EOF (define (input) (let [(s (get-line (current-input-port)) )] (if (eof-object? s) [begin (display "Bye!\n") (exit) ] s ) ) ) ;; Strings ;; Converts a string to an integer, 0 if invalid (define (atoi s) (let [(n (string->number s))] (if (eqv? n #f) 0 (inexact->exact (truncate n)) ) ) ) )
#!/usr/bin/env scheme-script ;; guess.ss ;; Copyright © 2015,2018 by Mark Damon Hughes. All Rights Reserved. (import (chezscheme)) (import (stdlib)) (define (guess) (display "I'm thinking of a number from 1 to 100, try to guess it!\n") (let [(theNumber (+ (random 100) 1))] (define guesses 1) (do [(break #f)] (break) (format #t "Guess #~a? " guesses) (let [(g (atoi (input)))] (cond [(or (<= g 0) (>= g 100)) (display "Try a number from 1 to 100.\n") ] [(< g theNumber) (display "Too low!\n") (inc! guesses) ] [(> g theNumber) (display "Too high!\n") (inc! guesses) ] [else (display "You got it!\n") (set! break #t) ] ) ) ) ) (display "***GAME OVER***\n") ) (randomize) (guess) (exit)
chez-compile.zsh, with my thanks to Graham Watt for explaining wpo and libraries:
#!/bin/zsh if [ $# -ne 1 ]; then echo "Usage: chez-compile.zsh MAINNAME" exit 1 fi rm -f *.so rm -f *.wpo mkdir -p bin cat <<ENDTEXT |scheme -q --optimize-level 3 (compile-imported-libraries #t) (generate-wpo-files #t) (compile-program "$1.ss") (compile-whole-program "$1.wpo" "bin/$1") ENDTEXT rm -f *.so rm -f *.wpo if [ -f "bin/$1" ]; then chmod 755 "bin/$1" fi
Now I just:
% chez-compile.zsh guess compiling guess.ss with output to guess.so compiling stdlib.ss with output to stdlib.so ((stdlib)) () % bin/guess I'm thinking of a number from 1 to 100, try to guess it! Guess #1? 50 Too low! Guess #2? ^DBye!
1 REM GUESS. COPYRIGHT (C) 1980,2018 BY MARK DAMON HUGHES. ALL RIGHTS RESERVED. 5 RANDOMIZE INT(TIMER()):FOR I=1 TO 10:A=RND(1):NEXT I:REM CHIPMUNK'S RANDOMIZE SUCKS 10 N=INT(100*RND(1))+1:T=1 20 PRINT "I'M THINKING OF A NUMBER FROM 1 TO 100, TRY TO GUESS IT!" 100 PRINT "GUESS #";T;"? ";:INPUT "",G 110 IF G<=0 OR G>=100 OR G<>INT(G) THEN 200 120 IF G<N THEN 210 130 IF G>N THEN 220 140 GOTO 230 200 PRINT "TRY A NUMBER FROM 1 TO 100.":GOTO 100 210 PRINT "TOO LOW!":T=T+1:GOTO 100 220 PRINT "TOO HIGH!":T=T+1:GOTO 100 230 PRINT "YOU GOT IT!":PRINT "*** GAME OVER ***" 240 EXIT:REM CHIPMUNK
But now I can think about more complex problems in Chez Scheme!
Here's the tiniest piece of what I've been thinking about next:
My first infinite loop was summer, age 10, only because I hadn't seen a computer until the year before. My pre-college computing skills were 90% self-taught; LOGO class at ~12 and a year of "comp sci" at 14 were minimal. ⌨️🖥
WordPress does a lot of things, not always well, but better than other blog platforms. But occasionally it runs amok like a toddler on espresso scribbling over your stuff with crayons and shitting in corners before falling down in a huff.
Today, it decided to replace my emoji with terrible little pictures again despite using the Disable Emojis plugin, so I gave up and edited
functions.php (Appearance, Editor). And took this opportunity to uneducate my quotes so you can actually use code I paste without having to run it thru BBEdit's "straighten quotes" text menu. I didn't invent any of this, but it's all buried in obsolete version advice.
// Fake Emoji & "Smart" Quotes Fuck Off remove_action('wp_head', 'print_emoji_detection_script', 7); remove_action('wp_print_styles', 'print_emoji_styles'); remove_action('admin_print_scripts', 'print_emoji_detection_script'); remove_action('admin_print_styles', 'print_emoji_styles'); remove_filter('wp_mail', 'wp_staticize_emoji_for_email'); remove_filter('the_content_feed', 'wp_staticize_emoji'); remove_filter('comment_text_rss', 'wp_staticize_emoji'); add_filter('emoji_svg_url', '__return_false'); add_filter('run_wptexturize', '__return_false');