"What is it?" "It's a book. A non-volatile data storage mechanism. Everyone should have one." —Blank Reg
?
Author: mdhughes
Stop Whining About Musical Abundance Wednesday Music
- Om Malik asks: Has music lost that loving feeling?: Betteridge's Law gives the correct answer, as usual: No.
- MG Siegler whines a few random setlists aren't random, "it's not the same": Pseudo-random number generation is in fact very close to random with modern seeding & algorithms, MG.
If you want to listen to an album, it's right there, in Apple Music, or presumably Spotify or whatever, which is why I mostly link to albums in my semi-daily music posts. If you want things outside your usual tastes, go hit Browse and find something. Or listen to one of Apple's "radio" stations; Zane Lowe just plays intolerable disco crap for ADHD babies, but there are others.
Anyway. Here's some hostile mechanical music to replace your whiny sentimental humanity:
1984
- Apple Introduces Macintosh: "See why 1984 won't be like 1984."
- Apple Announces HomePod
- HomePod arrives Feb 9, 2018
- Information Purification Directives. Big Brother is Watching You. Freedom is Slavery.
-
See why 2018 will be like 1984.
Thunderstruck Tuesday Music
Computers Aren't Bad or Good
- 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.
Definitely Hysterical Saturday Music
- 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.
Almost Human Friday Music
- "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"
Coke Is It
Status: Coke Is It.
(why are there no Coke/Pepsi/Generic-Brand Soda emoji?; answer: Cup With Straw was added, but my obsolete Sierra and iOS 10 installs can't display it)
Bloody Wizard Tuesday Music
- 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!
A Little Scheme
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:
- Pros:
- 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.
- Cons:
- Not as widely supported by tools & documentation as Racket.
- Pros:
- Racket:
- Pros:
- 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.
- Cons:
- 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.
- Pros:
- Chicken:
- Pros:
- Compiles to C and thence to native binaries, with nice FFI to C libraries.
- Cons:
- Mostly old R5RS, with a few extension libraries.
- Terrible REPL, only really usable as a compiled language.
- Pros:
- 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:
;; 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))
)
)
)
)
guess.ss:
#!/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!
Well, that was an adventure to get the equivalent of my first BASIC program from 1980, which can be run in Chipmunk BASIC if you don't happen to have a TRS-80 Model I handy:
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: