Ron Toland
About Canadian Adventures Keeping Score Archive Photos Replies Also on Micro.blog
  • Tracking the Books

    I need to find a replacement for Goodreads, because I hate using it.

    Its UI is terrible. It looks like something I would’ve designed back in high school, and I’m a color-blind back-end developer that wouldn’t know a good font choice if there was only one to pick.

    The performance of the site is terrible. Searching for books takes too long, and (and!) if you type too much of the book’s title into the search bar, the one you want will go whizzing by, replaced by books that are nothing like the one you’re looking for.

    Even when you finally do locate the exact book you want to add to one of your shelves, if you later want to, say, find a list of all the books you’ve read this past year (as I tried to do back in January), you’ll find that Goodreads does not fill in the date every time you mark a book as read. I think somewhere between a quarter and a third of all the books on my “read” shelf have no dates attached to them, so they end up in a jumble at the bottom of the list, no rhyme or reason to them.

    But what choice do I have? I have a few hundred books in hard copy in my house. Another two hundred or so scattered across various ebook formats: Kindle (follies of youth), Nook (ditto), Kobo (simply the best), and iBooks (don’t judge me). All of which I need to keep track of, if only to keep myself from buying a book I already own. Goodreads, for all its flaws, at least lets me do that.

    I suppose as a developer I’m supposed to build my own solution. And I’ve thought about it; I could write an importer to take the xml junk Goodreads' api barfs out, clean it up, and then shove it into a text search engine (probably Elasticsearch) for easy retrieval later.

    But that’s a fair-sized project, and if I can, I’d rather take advantage of someone else’s work (and pay them for it, gladly).

    So: Are there other, better, apps out there for tracking a personal library? If you use one, which one, and why?

    → 7:56 AM, Mar 18
  • If Doorknobs Were Software

    If we designed doorknobs the way we design software, each one would come with a user manual.

    They wouldn’t be guaranteed to work. You could spend hundreds of dollars on a new doorknob, only to find the handle doesn’t turn, and the manufacturer doesn’t offer a warranty.

    Your doorknob would have options for direction of turn, speed of opening, and click sound, but not shape or color.

    Most doorknobs would be sold without locks. You could get a knob with a lock, but it would be $10,000.

    Each door in your house would need a different doorknob, depending on what year it was built. Doors from 1994 would need completely different knobs than 1993 doors. Sometimes you’d be able to put a 1995 knob in a 1993 door, but not always.

    Modern doorknobs – made only for modern doors – would understand some voice commands, like “What time is it?” and “When did you last close?” But only from one person in the house, and the commands for opening and shutting would be different depending on which knob you bought and which door you installed it in. Most of these voice doorknobs wouldn’t have handles, at all.

    Some people would lay awake at night, wondering if our doorknobs were getting too smart, and would one day rise up and kill everyone.

    → 9:06 AM, Feb 12
  • Seven More Languages in Seven Weeks: Elm

    Between the move and the election and the holidays, took me a long time to finish this chapter.

    But I’m glad I did, because Elm is – dare I say – fun?

    The error messages are fantastic. The syntax feels like Haskell without being as obtuse.  Even the package management system just feels nice.

    A sign of how much I liked working in Elm: the examples for Day Two and Three of the book were written for Elm 0.14, using a concept called signals. Unfortunately, signals were completely removed in Elm 0.17 (!). So to get the book examples working in Elm 0.18, I had to basically rebuild them. Which meant spending a lot of time with the (admittedly great) Elm tutorial and trial-and-erroring things until they worked again.

    None of which I minded because, well, Elm is a great language to work in.

    Here’s the results of my efforts:

    • Day Two
    • Day Three
    And here's what I learned:

    Day One

    • haskell-inspired
    • elm-installer: damn, that was easy
    • it's got a repl!
    • emacs mode also
    • types come back with all the values (expression results)
    • holy sh*t: "Maybe you forgot some parentheses? Or a comma?"
    • omg: "Hint: All elements should be the same type of value so that we can iterate through the list without running into unexpected values."
    • type inferred: don't have to explicitly declare the type of every variable
    • polymorphism via type classes
    • single-assignment, but the repl is a little looser
    • pipe syntax for if statement in book is gone in elm 0.17
    • case statement allows pattern matching
    • case statement needs the newlines, even in the repl (use `\`)
    • can build own complex data types (but not type classes)
    • case also needs indentation to work (especially if using result for assignment in the repl)
    • records: abstract types for people without beards
    • changing records: use `=` instead of `<-`: { blackQueen | color = White }
    • records look like they're immutable now, when they weren't before? code altering them in day one doesn't work
    • parens around function calls are optional
    • infers types of function parameters
    • both left and right (!) function composition <| and |>
    • got map and filter based off the List type (?)
    • no special syntax for defining a function versus a regular variable, just set a name equal to the function body (with the function args before the equal sign)
    • head::tail pattern matching in function definition no longer works; elm is now stricter about requiring you to define all the possible inputs, including the empty list
    • elm is a curried language (!)
    • no reduce: foldr or foldl
    • have to paren the infix functions to use in foldr: List.foldr (*) 1 list
    • hard exercise seems to depend on elm being looser than it is; afaict, it won't let you pass in a list of records with differing fields (type volation), nor will it let you try to access a field that isn't there (another type violation)

    Day Two

    • section is built around signals, which were removed in Elm 0.17 (!)
    • elm has actually deliberately moved away from FRP as a paradigm
    • looks like will need to completely rewrite the sample code for each one as we go...thankfully, there's good examples in the elm docs (whew!)
    • [check gists for rewritten code]
    • module elm-lang/keyboard isn't imported in the elm online editor by default anymore

    Day Three

    • can fix the errors from loading Collage and Element into main by using toHtml method of the Collage object
    • elm-reactor will give you a hot-updated project listening on port 8000 (so, refresh web page of localhost:8000 and get updated view of what your project looks like)
    • error messages are very descriptive, can work through upgrading a project just by following along (and refreshing alot)
    • critical to getting game working: https://ohanhi.github.io/base-for-game-elm-017.html (multiple subscriptions)
    → 7:00 AM, Jan 30
  • The Problem with Programmer Interviews

    You’re a nurse. You go in to interview for a new job at a hospital. You’re nervous, but confident you’ll get the job: you’ve got ten years of experience, and a glowing recommendation from your last hospital.

    You get to the interview room. There must be a mistake, though. The room number they gave you is an operating room.

    You go in anyway. The interviewer greets you, clipboard in hand. He tells you to scrub up, join the operation in progress.

    “But I don’t know anything about this patient,” you say. “Or this hospital.”

    They wave away your worries. “You’re a nurse, aren’t you? Get in there and prove it.”

    ….

    You’re a therapist. You’ve spent years counseling couples, helping them come to grips with the flaws in their relationship.

    You arrive for your interview with a new practice. They shake your hand, then take you into a room where two men are screaming at each other. Without introducing you, the interviewer pushes you forward.

    “Fix them,” he whispers.

    …

    You’re a pilot, trying to get a better job at a rival airline. When you arrive at your interview, they whisk you onto a transatlantic flight and sit you in the captain’s chair.

    “Fly us there,” they say.

    …

    You’re a software engineer. You’ve been doing it for ten years. You’ve seen tech fads come and go. You’ve worked for tiny startups, big companies, and everything in-between. Your last gig got acquired, which is why you’re looking for a new challenge.

    The interviewers – there’s three of them, which makes you nervous – smile and shake your hand. After introducing themselves, they wave at the whiteboard behind you.

    “Code for us.”

     

    → 7:00 AM, Nov 23
  • Follow the Tweeting Bot

    I have a problem.

    No, not my fondness for singing 80s country in a bad twang during karaoke.

    I mean a real, nerd-world problem: I have too many books to read.

    I can’t leave any bookstore without buying at least one. For a good bookstore, I’ll walk out with half a dozen or more, balancing them in my arms, hoping none of them fall over.

    I get them home and try to squeeze them into my bookshelf of “books I have yet to read” (not to be confused with my “books I’ve read and need to donate” or “books I’ve read and will re-read someday when I have the time” shelves). That shelf is full, floor to ceiling.

    My list of books to read is already too long for me to remember them all. And that’s not counting the ones I have sitting in ebook format, waiting on my Kobo or iPhone for me to tap their cover art and dive in.

    Faced with so much reading material, so many good books waiting to be read, my question is this: What do I read next?

    I could pick based on mood. But that usually means me sitting in front of my physical books, picking out the one that grabs me. I could pick based on which ones I’ve bought most recently, which would probably narrow things down to just my ebooks.

    But I want to be able to choose from all of my books, physical and virtual, at any time.

    So I wrote a bot to help me.

    It listens to my twitter stream for instructions. When I give it the right command, it pulls down my to-read shelf from Goodreads (yes, I put all of my books, real and electronic, into Goodreads. yes, it took much longer than I thought it would), ranks them in order of which ones I should read first, and then tweets back to me the top 3.

    I’ve been following its recommendations for about a month now, and so far, it’s working. Footsteps in the Sky was great. Data and Goliath was eye-opening. The Aesthetic of Play changed the way I view art and games.

    Now, if only I could train it to order books for me automatically…

    → 6:00 AM, Apr 27
  • Notes from Strange Loop 2015: Day Two

    Pixie

    • lisp
    • own vm
    • compiled using RPython tool chain
    • RPython - reduced python
      • used in PyPy project
      • has own tracing JIT
    • runs on os x, linux, ARM (!)
    • very similar to clojure, but deviates from it where he wanted to for performance reasons
    • has continuations, called stacklets
    • has an open-ended object system; deftype, etc
    • also wanted good foreign function interface (FFI) for calling C functions
    • wants to be able to do :import Math.h :refer cosine
    • ended up writing template that can be called recursively to define everything you want to import
    • writes C file using template that has everything you need and then compiles it and then uses return values with the type info, etc
    • you can actually call python from pixie, as well (if you want)
    • not ready for production yet, but a fun project and PRs welcome

    History of Programming Languages for 2 Voices

    • David Nolen and Michael Bernstein
    • a programming language "mixtape"
    Big Bang: The World, The Universe, and The Network in the Programming Language
    • Matthias Felleisen
    • worst thought you can have: your kids are in middle school
    • word problems in math are not interesting, they're boring
    • can use image placement and substitution to create animations out of word problems
    • mistake to teach children programming per se. they should use programming to help their math, and math to help their programming. but no programming on its own
    • longitudinal study: understanding a function, even if you don't do any other programming ever, means a higher income as an adult
    • can design curriculum taking kids from middle school (programming + math) to high school (scheme), college (design programs), to graduate work (folding network into the language)
    → 9:00 AM, Oct 7
  • Clojure/West 2015: Notes from Day Three

    Everything Will Flow

    • Zach Tellman, Factual
    • queues: didn't deal with directly in clojure until core.async
    • queues are everywhere: even software threads have queues for their execution, and correspond to hardware threads that have their own buffers (queues)
    • queueing theory: a lot of math, ignore most
    • performance modeling and design of computer systems: queueing theory in action
    • closed systems: when produce something, must wait for consumer to deal with it before we can produce something else
      • ex: repl, web browser
    • open systems: requests come in without regard for how fast the consumer is using them
      • adding consumers makes the open systems we build more robust
    • but: because we're often adding producers and consumers, our systems may respond well for a good while, but then suddenly fall over (can keep up better for longer, but when gets unstable, does so rapidly)
    • lesson: unbounded queues are fundamentally broken
    • three responses to too much incoming data:
      • drop: valid if new data overrides old data, or if don't care
      • reject: often the only choice for an application
      • pause (backpressure): often the only choice for a closed system, or sub-system (can't be sure that dropping or rejecting would be the right choice for the system as a whole)
      • this is why core.async has the puts buffer in front of their normal channel buffer
    • in fact, queues don't need buffer, so much as they need the puts and takes buffers; which is the default channel you get from core.async

    Clojure At Scale

    • Anthony Moocar, Walmart Labs
    • redis and cassandra plus clojure
    • 20 services, 70 lein projects, 50K lines of code
    • prefer component over global state
    → 7:00 AM, Apr 29
  • Clojure/West 2015: Notes from Day Two

    Data Science in Clojure

    • Soren Macbeth; yieldbot
    • yieldbot: similar to how adwords works, but not google and not on search results
    • 1 billion pageviews per week: lots of data
    • end up using almost all of the big data tools out there
    • EXCEPT HADOOP: no more hadoop for them
    • lots of machine learning
    • always used clojure, never had or used anything else
    • why clojure?
      • most of the large distributed processing systems run on the jvm
      • repl great for data exploration
      • no delta between prototyping and production code
    • cascalog: was great, enabled them to write hadoop code without hating it the whole time, but still grew to hate hadoop (running hadoop) over time
    • december: finally got rid of last hadoop job, now life is great
    • replaced with: storm
    • marceline: clojure dsl (open-source) on top of the trident java library
    • writing trident in clojure much better than using the java examples
    • flambo: clojure dsl on top of spark's java api
      • renamed, expanded version of climate corp's clj-spark

    Pattern Matching in Clojure

    • Sean Johnson; path.com
    • runs remote engineering team at Path
    • history of pattern matching
      • SNOBOL: 60s and 70s, pattern matching around strings
      • Prolog: 1972; unification at its core
      • lots of functional and pattern matching work in the 70s and 80s
      • 87: Erlang -> from prolog to telecoms; functional
      • 90s: standard ml, haskell...
      • clojure?
    • prolog: unification does spooky things
      • bound match unbound
      • unbound match bound
      • unbound match unbound
    • clojurific ways: core.logic, miniKanren, Learn Prolog Now
    • erlang: one way pattern matching: bound match unbound, unbound match bound
    • what about us? macros!
    • pattern matching all around us
      • destructuring is a mini pattern matching language
      • multimethods dispatch based on pattern matching
      • case: simple pattern matching macro
    • but: we have macros, we can use them to create the language that we want
    • core.match
    • dennis' library defun: macros all the way down: a macro that wraps the core.match macro
      • pattern matching macro for defining functions just like erlang
      • (defun say-hi (["Dennis"] "Hi Dennis!") ([:catty] "Morning, Catty!"))
      • can also use the :guard syntax from core.match in defining your functions' pattern matching
      • not in clojurescript yet...
    • but: how well does this work in practice?
      • falkland CMS, SEACAT -> incidental use
      • POSThere.io -> deliberate use (the sweet spot)
      • clj-json-ld, filter-map -> maximal use
    • does it hurt? ever?
    • limitations
      • guards only accept one argument, workaround with tuples
    • best practices
      • use to eliminate conditionals at the top of a function
      • use to eliminate nested conditionals
      • handle multiple function inputs (think map that might have different keys in it?)
      • recursive function pattern: one def for the start, one def for the work, one def for the finish
        • used all over erlang
        • not as explicit in idiomatic clojure
    → 7:00 AM, Apr 28
  • Clojure/West 2015: Notes from Day One

    Life of a Clojure Expression

    • John Hume, duelinmarkers.com (DRW trading)
    • a quick tour of clojure internals
    • giving the talk in org mode (!)
    • disclaimers: no expert, internals can change, excerpts have been mangled for readability
    • most code will be java, not clojure
    • (defn m [v] {:foo "bar" :baz v})
    • minor differences: calculated key, constant values, more than 8 key/value pairs
    • MapReader called from static array of IFns used to track macros; triggered by '{' character
    • PersistentArrayMap used for less than 8 objects in map
    • eval treats forms wrapped in (do..) as a special case
    • if form is non-def bit of code, eval will wrap it in a 0-arity function and invoke it
    • eval's macroexpand will turn our form into (def m (fn [v] {:foo "bar :baz v}))
    • checks for duplicate keys twice: once on read, once on analyze, since forms for keys might have been evaluated into duplicates
    • java class emitted at the end with name of our fn tacked on, like: class a_map$m
    • intelli-j will report a lot of unused methods in the java compiler code, but what's happening is the methods are getting invoked, but at load time via some asm method strings
    • no supported api for creating small maps with compile-time constant keys; array-map is slow and does a lot of work it doesn't need to do

    Clojure Parallelism: Beyond Futures

    • Leon Barrett, the climate corporation
    • climate corp: model weather and plants, give advice to farmers
    • wrote Claypoole, a parallelism library
    • map/reduce to compute average: might use future to shove computation of the average divisor (inverse of # of items) off at the beginning, then do the map work, then deref the future at the end
    • future -> future-call: sends fn-wrapped body to an Agent/soloExecutor
    • concurrency vs parallelism: concurrency means things could be re-ordered arbitrarily, parallelism means multiple things happen at once
    • thread pool: recycle a set number of threads to avoid constantly incurring the overhead of creating a new thread
    • agent thread pool: used for agents and futures; program will not exit while threads are there; lifetime of 60 sec
    • future limitations
      • tasks too small for the overhead
      • exceptions get wrapped in ExecutionException, so your try/catches won't work normally anymore
    • pmap: just a parallel map; lazy; runs N-cpu + 3 tasks in futures
      • generates threads as needed; could have problems if you're creating multiple pmaps at once
      • slow task can stall it, since it waits for the first task in the sequence to complete for each trip through
      • also wraps exceptions just like future
    • laziness and parallelism: don't mix
    • core.async
      • channels and coroutines
      • reads like go
      • fixed-size thread pool
      • handy when you've got a lot of callbacks in your code
      • mostly for concurrency, not parallelism
      • can use pipeline for some parallelism; it's like a pmap across a channel
      • exceptions can kill coroutines
    • claypoole
      • pmap that uses a fixed-size thread pool
      • with-shutdown! will clean up thread pool when done
      • eager by default
      • output is an eagerly streaming sequence
      • also get pfor (parallel for)
      • lazy versions are available; can be better for chaining (fast pmap into slow pmap would have speed mismatch with eagerness)
      • exceptions are re-thrown properly
      • no chunking worries
      • can have priorities on your tasks
    • reducers
      • uses fork/join pool
      • good for cpu-bound tasks
      • gives you a parallel reduce
    • tesser
      • distributable on hadoop
      • designed to max out cpu
      • gives parallel reduce as well (fold)
    • tools for working with parallelism:
      • promises to block the state of the world and check things
      • yorkit (?) for jvm profiling

    Boot Can Build It

    • Alan Dipert and Micha Niskin, adzerk
    • why a new build tool?
      • build tooling hasn't kept up with the complexity of deploys
      • especially for web applications
      • builds are processes, not specifications
      • most tools: maven, ant, oriented around configuration instead of programming
    • boot
      • many independent parts that do one thing well
      • composition left to the user
      • maven for dependency resolution
      • builds clojure and clojurescript
      • sample boot project has main method (they used java project for demo)
      • uses '--' for piping tasks together (instead of the real |)
      • filesets are generated and passed to a task, then output of task is gathered up and sent to the next task in the chain (like ring middleware)
    • boot has a repl
      • can do most boot tasks from the repl as well
      • can define new build tasks via deftask macro
      • (deftask build ...)
      • (boot (watch) (build))
    • make build script: (build.boot)
      • #!/usr/bin/env boot
      • write in the clojure code defining and using your boot tasks
      • if it's in build.boot, boot will find it on command line for help and automatically write the main fn for you
    • FileSet: immutable snapshot of the current files; passed to task, new one created and returned by that task to be given to the next one; task must call commit! to commit changes to it (a la git)
    • dealing with dependency hell (conflicting dependencies)
      • pods
      • isolated runtimes, with own dependencies
      • some things can't be passed between pods (such as the things clojure runtime creates for itself when it starts up)
      • example: define pod with env that uses clojure 1.5.1 as a dependency, can then run code inside that pod and it'll only see clojure 1.5.1

    One Binder to Rule Them All: Introduction to Trapperkeeper

    • Ruth Linehan and Nathaniel Smith; puppetlabs
    • back-end service engineers at puppetlabs
    • service framework for long-running applications
    • basis for all back-end services at puppetlabs
    • service framework:
      • code generalization
      • component reuse
      • state management
      • lifecycle
      • dependencies
    • why trapperkeeper?
      • influenced by clojure reloaded pattern
      • similar to component and jake
      • puppetlabs ships on-prem software
      • need something for users to configure, may not have any clojure experience
      • needs to be lightweight: don't want to ship jboss everywhere
    • features
      • turn on and off services via config
      • multiple web apps on a single web server
      • unified logging and config
      • simple config
    • existing services that can be used
      • config service: for parsing config files
      • web server service: easily add ring handler
      • nrepl service: for debugging
      • rpc server service: nathaniel wrote
    • demo app: github -> trapperkeeper-demo
    • anatomy of service
      • protocol: specifies the api contract that that service will have
      • can have any number of implementations of the contract
      • can choose between implementations at runtime
    • defservice: like defining a protocol implementation, one big series of defs of fns: (init [this context] (let ...)))
      • handle dependencies in defservice by vector after service name: [[:ConfigService get-in-config] [:MeowService meow]]
      • lifecycle of the service: what happens when initialized, started, stopped
      • don't have to implement every part of the lifecycle
    • config for the service: pulled from file
      • supports .json, .edn, .conf, .ini, .properties, .yaml
      • can specify single file or an entire directory on startup
      • they prefer .conf (HOCON)
      • have to use the config service to get the config values
      • bootstrap.cfg: the config file that controls which services get picked up and loaded into app
      • order is irrelevant: will be decided based on parsing of the dependencies
    • context: way for service to store and access state locally not globally
    • testing
      • should write code as plain clojure
      • pass in context/config as plain maps
      • trapperkeeper provides helper utilities for starting and stopping services via code
      • with-app-with-config macro: offers symbol to bind the app to, plus define config as a map, code will be executed with that app binding and that config
    • there's a lein template for trapperkeeper that stubs out working application with web server + test suite + repl
    • repl utils:
      • start, stop, inspect TK apps from the repl: (go); (stop)
      • don't need to restart whole jvm to see changes: (reset)
      • can print out the context: (:MeowService (context))
    • trapperkeeper-rpc
      • macro for generating RPC versions of existing trapperkeeper protocols
      • supports https
      • defremoteservice
      • with web server on one jvm and core logic on a different one, can scale them independently; can keep web server up even while swapping out or starting/stopping the core logic server
      • future: rpc over ssl websockets (using message-pack in transit for data transmission); metrics, function retrying; load balancing

    Domain-Specific Type Systems

    • Nathan Sorenson, sparkfund
    • you can type-check your dsls
    • libraries are often examples of dsls: not necessarily macros involved, but have opinionated way of working within a domain
    • many examples pulled from "How to Design Programs"
    • domain represented as data, interpreted as information
    • type structure: syntactic means of enforcing abstraction
    • abstraction is a map to help a user navigate a domain
      • audience is important: would give different map to pedestrian than to bus driver
    • can also think of abstraction as specification, as dictating what should be built or how many things should be built to be similar
    • showing inception to programmers is like showing jaws to a shark
    • fable: parent trap over complex analysis
    • moral: types are not data structures
    • static vs dynamic specs
      • static: types; things as they are at compile time; definitions and derivations
      • dynamic: things as they are at runtime; unit tests and integration tests; expressed as falsifiable conjectures
    • types not always about enforcing correctness, so much as describing abstractions
    • simon peyton jones: types are the UML of functional programming
    • valuable habit: think of the types involved when designing functions
    • spec-tacular: more structure for datomic schemas
      • from sparkfund
      • the type system they wanted for datomic
      • open source but not quite ready for public consumption just yet
      • datomic too flexible: attributes can be attached to any entity, relationships can happen between any two entities, no constraints
      • use specs to articulate the constraints
      • (defspec Lease [lesse :is-a Corp] [clauses :is-many String] [status :is-a Status])
      • (defenum Status ...)
      • wrote query language that's aware of the defined types
      • uses bi-directional type checking: github.com/takeoutweight/bidirectional
      • can write sensical error messages: Lease has no field 'lesee'
      • can pull type info from their type checker and feed it into core.typed and let core.typed check use of that data in other code (enforce types)
      • does handle recursive types
      • no polymorphism
    • resources
      • practical foundations for programming languages: robert harper
      • types and programming languages: benjamin c pierce
      • study haskell or ocaml; they've had a lot of time to work through the problems of types and type theory
    • they're using spec-tacular in production now, even using it to generate type docs that are useful for non-technical folks to refer to and discuss; but don't feel the code is at the point where other teams could pull it in and use it easily

    ClojureScript Update

    • David Nolen
    • ambly: cljs compiled for iOS
    • uses bonjour and webdav to target ios devices
    • creator already has app in app store that was written entirely in clojurescript
    • can connect to device and use repl to write directly on it (!)

    Clojure Update

    • Alex Miller
    • clojure 1.7 is at 1.7.0-beta1 -> final release approaching
    • transducers coming
    • define a transducer as a set of operations on a sequence/stream
      • (def xf (comp (filter? odd) (map inc) (take 5)))
    • then apply transducer to different streams
      • (into [] xf (range 1000))
      • (transduce xf + 0 (range 1000))
      • (sequence xf (range 1000))
    • reader conditionals
      • portable code across clj platforms
      • new extension: .cljc
      • use to select out different expressions based on platform (clj vs cljs)
      • #?(:clj (java.util.Date.) :cljs (js/Date.))
      • can fall through the conditionals and emit nothing (not nil, but literally don't emit anything to be read by the reader)
    • performance has also been a big focus
      • reduced class lookups for faster compile times
      • iterator-seq is now chunked
      • multimethod default value dispatch is now cached
    → 7:00 AM, Apr 27
  • Software Engineering Lessons from NASA: Part One

    Long before I became a programmer, I worked as an optical engineer at NASA's Goddard Space Flight Center. I was part of the Optical Alignment and Test group, which is responsible for the integration and testing of science instruments for spacecraft like the Hubble Space Telescope, Swift, and the upcoming James Webb Space Telescope.

    While most of the day-to-day engineering practices I learned didn't transfer over to software engineering, I've found certain principles still hold true. Here's the first one:

    The first version you build will be wrong.

    At NASA, it was taken as axiomatic that the first time you built an instrument, you'd screw it up. Engineers always pressed for the budget to build an Engineering Test Unit (ETU), which was a fully-working mock-up of the instrument you ultimately wanted to launch. Since the ETU was thrown away afterward, you could use it to practice the techniques you'd use to assemble the real instrument.

    And you needed the practice. The requirements were often so tight (to the thousandth of an inch) that no matter how well you'd planned it out, something always went wrong: a screw would prove too hard to reach, or a baffle would be too thin to block all the light.

    No amount of planning and peer review could find all the problems. The only way to know for sure if it would work was to build it. By building an ETU, you could shake out all the potential flaws in the design, so the final instrument would be solid.

    In software, I've found the same principle holds: the first time I solve I problem, it's never the optimal solution. Oddly enough, I often can't see the optimal solution until after I've solved the problem in some other way.

    Knowing this, I treat the first solution as a learning experience, to be returned to down the line and further optimized. I still shoot for the best first solution I can get, but I don't beat myself up when I look back at the finished product and see the flaws in my design.

    → 10:56 AM, Dec 26
  • Five Reasons Your Company Should Allow Remote Developers

    If you don’t allow your software developers to work from home, you’re not just withholding a nice perk from your employees, you’re hurting your business.

    Here’s five reasons letting developers work remotely should be the default:

    1. Widen your talent pool

    Good software engineers are already hard to find. On top of that, you've got to hire someone skilled in your chosen tech stack, which narrows the pool even further. Why restrict yourself to those engineers within driving distance to your office? Can you really afford to wait for talent to move close to you?

    The CTO for my current gig lives an hour away from the office, and can’t move because of his wife’s job. We wouldn’t have been able to hire him if we didn’t let him work from home. Who are you missing out on because you won’t look at remote devs.

    2. Reclaim commute time

    The average commute time in the US is 30 minutes. That's an hour a day your in-office developers aren't working. If you let them work from home, they can start earlier and finish later.

    Don’t think they will? The evidence shows they do: people working from home work longer hours than people in the office.

    An extra hour of work a day is five more hours a week, or almost three more work days in the month. Why throw that time away?

    3. Reduce sick leave

    When I've got a cold or flu, I stay home. I usually spend the first day or two resting, but by the third day I'm usually able to work for a little, even though I'm too sick to go into the office.

    If my boss didn’t let me work from home, he wouldn’t get those “sick hours” from me. I’d be forced into taking more time off, getting less done.

    And when my wife’s sick, I don’t have to choose between taking care of her and getting my work done. By working from home, I can do both.

    4. Increase employee retention

    The only thing worse than not hiring a good dev is losing an engineer you've already got. When they leave, you're not only losing a resource, you're losing all the historical knowledge they have about the system: weird bugs that only show up once a quarter, why the team chose X db instead of another, etc.

    Since the competition for talent is fierce, you don’t want to lose out to another company. Letting developers work from home sends a clear signal to your employees that they’re valued and that you appreciate work-life balance. And with many companies sticking to the old “gotta be in the office” way of thinking, you’re ensuring that any offer your employees get from another company won’t be as attractive.

    5. Stay focused on work done

    Finally, letting developers work from home forces the entire team to focus on what's really important: getting work done. It doesn't matter how many hours a developer spends in the office; if that time isn't productive, it's wasted.

    What does matter is how much work a dev gets done: how many bugs squashed, how many new features completed, how many times they jump in to help another engineer. What you need from your developers is software for your business, not time spent in a cubicle. If they’re not producing, they should be let go. If they are producing, does it matter if they’re at a coffee shop downtown?

    And if you don’t have a way of measuring developer productivity beyond hours spent at their desk, get one. You can’t improve something you don’t measure, and team productivity should be high on your list of things to always be improving.

    → 1:00 PM, Mar 29
  • ClojureWest 2013: Day Three Notes

    Editing Clojure with Emacs: Ryan Neufeld

    • emacs live, emacs prelude, emacs-starting-kit: for getting up and running
    • bit.ly/vim-revisited - post about going back to basic editors
    • bit.ly/clj-ready: ryan's version of emacs starter kit
    • nREPL & nREPL.el instead of inferior-lisp
    • melpa for your package manager
    • have a look at the projectile minor mode for project management
    • use paredit to build up clojure code trees, not just characters
    • slurp and slice to add new structure: () then slurp to wrap

    Ritz: Missing Clojure Tooling: Hugo Duncan

    • clojure debugging tool
    • nREPL: lets you connect to remote clojure VM (transport + socket + protocol + REPL)
    • sits in-between your local nrepl and the remote nrepl process
    • available as marmalade package
    • also lein plugin: lein-ritz
    • turn on break on exceptions: gives you common-lisp like stacktrace + restart options (continue, ignore, etc)
    • can open up stacktrace to see local variables within the frame
    • can even evaluate expressions within the frame (!)
    • also pull up the source code for a frame (clojure or java)
    • can set breakpoints on lines of code in emacs; view list of all current breakpoints in a separate buffer
    • warning: lists appear in stacktrace frame fully-realized (will be fixed)

    Macros vs Monads: Chris Houser and Jonathan Claggett

    • synthread: library of macros that use Clojure's -> (threading macro) as the do
    • usually pulled in with -> as its alias
    • defines macros for most of clojure's control-flow code
    • also has updater macros
    • use for cases where pure functional code is too verbose and/or hard to read
    • replaces use of state monad
    • monads are infectious (end up passing them around everywhere)
    • clojure 1.5 has cond-> macro
    • rover example project up on github: lonocloud/synthread

    How to Sneak Clojure into Your Rails Shop: Joshua Bellanco

    • and improve your rails hosting along the way
    • chief scientist at burnside digital (based in portland)
    • if this was 2006, we'd be talking about sneaking rails into your java shop
    • learn from rails: better to ask forgiveness than permission, use clojure whenever it's the right tool for the job, don't be afraid to show off your successes
    • step 1: convince them to use jruby (better tooling, better performance, java ecosystem, plenty of hosting options)
    • step 2: torquebox for deployment (benefits of jboss)
    • step 3: go in with clojure and start using immutant overlay (gives jboss, torquebox, jruby); lein immutant run runs both ruby and clojure apps
    • step 4: openshift (open source heroku from redhat)
    • step 5: make clojure and ruby talk to each other (hornetq + torquebox/immutant messaging libraries)
    • step 6: show off!
    • example project: memolisa: sends alerts and confirmation when alert is read; rails for users + groups, clojure for the messaging

    clj-mook: Craig Brozefsky

    • library for testing web apps
    • persistent session, default request params, html parsing
    • motivated by shift from ring to immutant

    RxJava: Dave Ray

    • open-source implementation of M$ Reactive Extensions
    • operators for creating, composing, and manipulating Observable streams
    • sketch up at daveray/rx-clj
    • also: netflix/rxjava

    VMFest: Toni Batchelli

    • goal: make virtualbox behave like lightweight cloud provider
    • instantiate multiple vms from the same image
    • wrap the OOP api of virtualbox with a sane clojure one
    • has hardware dsl
    • one step further: little-fluffy-cloud -> RESTful interface for vmfest
    • visaje: build VMs from data

    shafty: Chris Meiklejohn

    • basho technologies: erlang and js, with some clojure
    • functional reactive programming library
    • based on flapjax, implemented in clojurescript
    • implementation of core API from flapjax
    • FRP: authoring reactive programs without callbacks
    • FRP: event streams and behaviors

    swearjure: gary fredericks

    • subset of clojure with no alphanumeric characters
    • exercise in extreme constraints
    • integers but no floats
    • true and false available

    Evolutionary Art with Clojure: Alan Shaw

    • clevolution: partial implementation of paper on genetic programming
    • converting s-expressions to images
    • using self as filtering function: delete the images he doesn't like
    • want to move to true evolutionary: use function to weed through the images, allow cross-breeding between s-expressions
    • clisk, clojinc, clevolution

    Simulation Testing with Simulant: Stuart Halloway

    • example-based tests: setup, inputs, outputs, validation
    • originally built as tool for testing datomic
    • no language indirection: it's about using clojure and datomic
    • write model for what will happen to the application, then writeup actions to take against the system
    • can speed up time in simulation, so don't have to wait for 6 mo for 6 months of results to go through
    • stores db with test results *and* the db tests ran against
    • can find and diagnose bugs by querying db after tests run
    • use clojure.data.generators to generate random test data (ints, vectors, maps)
    • github.com/stuarthalloway/presentations/wiki
    • contact at @stuarthalloway to have come out to speak at company or group
    • even working through the model of users and use is a good exercise; good way to validate the assumptions you're making about the system
    → 9:08 AM, Mar 21
  • ClojureWest 2013: Day Two Notes

    Winning the War on Javascript: Bodil Stokke

    • catnip: beginners clojure editor in browser
    • originally used coffeescript because cljs was immature and hard to work with js objects
    • currently working on converting catnip to cljs
    • error: another clojurescript testing framework, built around asynchronous testing

    PuppetDB: Sneaking Clojure into SysAdmins' Toolkits: Deepak Giridharaghopal

    • ops has a lot of entropy: spooky action at  distance: devs or admins logging in to one of many servers and mucking around without telling you
    • lack of predictability ruins automation and abstraction
    • problems with previous software in Ruby: not fast, only one core, mutable state everywhere, runtime compatibility a problem
    • solution: puppetdb in clojure for storing and querying data about systems
    • used CQRS: command query responsibility separation -> use different model to update then to read info
    • send commands to a /command endpoint, which queues the command for parsing and processing
    • build command processing functions as multi-methods switching off of the command and version sent
    • can also turn on live repl, to connect to running code and hack
    • queries have their own AST-based syntax; sent as json, built as vector tree
    • can ship the whole thing as a single uberjar, with built-in db, etc

    Securing Clojure Web Services & Apps with Friend: Chas Emerick

    • authentication & authorization (who are you? what are you allowed to do?)
    • options: spring-security (java, not recommended), sandbar, ring-basic-authentication, clj-oauth2
    • most common: roll your own
    • wrote friend to have a common auth framework
    • uses ad-hoc hierarchies for roles
    • add workflows to specify how to authenticate a request that doesn't have authentication yet
    • friend-demo.herokuapp.com for multiple demos with source code
    • recommend using b-crypt over sha

    FRP in ClojureScript with Javelin: Alan Dipert

    • event stream: sequence of values over time
    • behavior: function that updates according to changing values from event stream
    • reactive evaluation: holds off on evaluating until all values are available
    • similar to spreadsheet formula evaluation (!)
    • FRP maintains evaluation order despite lack of all values at once
    • current FRP in clojurescript: FlapJax
    • javelin: abstract spreadsheet library for reactive programming with values
    • everything contained in the "cell" macro
    • web app has single state at any point in time, contained in the "stem cell"
    • everything in app either in stem cell or derived from it

    SQL and core.logic Killed my ORM: Craig Brozefsky

    • uses clojure for analysis engine looking for possible malware actions
    • core.logic engine takes observations and creates IOCs (indications of compromise) + html
    • observations: wrapper around core.logic's defrel
    • IOCs: severity + confidence, explanation, suggested remediation
    • the reasoned schemer: handed out to all their analysts to explain logic programming to them so they can use the system

    Macros: Why, When and How: Gary Fredericks

    • macro: special function that takes form as argument and returns a form
    • run at compile time
    • can always be replaced by its expansion
    • when writing macros, helps to know what you want it to expand to
    • use macroexpand-1 to find out when it's going to return
    • cannot pass macro to higher-order function (not composable at runtime)
    • macros can make code harder to read; person reading code has to be familiar with macro expansion to really know what your code is doing
    • tolerated usage: defining things, wrapping code execution, delaying execution, capturing code, DSLs, compile-time optimizations (hiccup produces as much html as possible at compile time)
    • avoiding macros: get more familiar with higher-order function usage and paradigms
    • writing tolerable macros: use helper functions, naming conventions, no side effects
    • syntax-quote (backtick): like quote on steroids, gives you multiple benefits when used in a macro
    → 9:45 AM, Mar 20
  • ClojureWest 2013: Day One Notes

    Domain Driven Design in Clojure: Amit Rathore

    • read the book from eric evans
    • Lot of oop design principles carry over
    • shoot for 3-4 lines of clojure code per function
    • validateur, bouncer, clj-schema (validation)
    • if code confusing, demand simplification
    • make temp namespaces explicit: zolo.homeless
    • domain: business-important logic, not the API, not services, not validation, not talking to the db, just the stuff business people care about; should be pure
    • if you don't need it now, don't build it

    RESTful Clojure: Siva Jagadeesan

    • liberator, bishop: libraries to help build proper REST APIs in clojure
    • use the status codes: 1xx - Metadata, 2xx - success, 3xx - redirect, 4xx - client error, 5xx - server error
    • 405: method not allowed
    • 409: conflict
    • 404: resource not present
    • create returns Location header with location of new resource, in addition to the 201 (created) status code
    • even better: also return a set of links to related resource (rel = self) and transitions (rel = cancel)
    • allows client to be loosely coupled from API
    • client doesn't need to know how resources move through the system (transition logic)
    • REST means using multiple URIs, HTTP status codes, and Hypermedia

    Clojure in the Large: Stuart Sierra

    • def'ing refs and atoms at the top level is basically global mutable state via singletons, please avoid
    • recommend using constructor functions to *return* the state variables you want to use, then pass that state along to each function
    • easier to test
    • explicit dependencies
    • safe to reload when working at the repl
    • thread-bound state also bad: assumes no lazy sequence returned in function bodies, hides dependencies, and limits caller to using one resource at a time
    • prefer passing context around to functions
    • can pull resources out of it
    • use namespace-qualified keys for isolation
    • isn't confined to a single thread
    • still need to cleanup at the end
    • more bookkeeping
    • true constants are fine as global vars (^:const)

    Pedestal: Architecture and Services: Tim Ewald

    • alpha release from relevance of open-source libs
    • use clojure end-to-end to build RIAs
    • demo: hammock cafe: clojurescript apps communicating to same back-end using datomic store
    • 2 halves: pedestal-service, pedestal-app
    • ring limits: bound to a single thread's stack
    • interceptors: map of functions, has enter and leave for processing requests and responses
    • can pause and resume along any thread
    • pushed to be as ring-compatible as possible
    • use of long polling and server-side events (requests that come in slow and last a long time, get updated as more data comes in)

    Design, Composition, and Performance: Rich Hickey

    • take things apart
    • design like bartok (embrace constraints, use harmonic sense)
    • code like coltrane (constant practice, keep harmonic sense)
    • build libraries like instruments (design for players, able to be combined with other things)
    • pursue harmony
    → 9:16 AM, Mar 19
  • Rewryte.com is live!

    For about 8 months now, I’ve been working every Sunday morning with a good friend of mine building rewryte.com. It’s our own little web app, a tool for giving writers automatic feedback on their writing.

    We’re trying to go beyond grammar checks and spellcheckers, to answer questions like:

    • Are my sentences too long?
    • Are the words I'm using too specialized for my audience?
    • Should I submit this story as horror or science fiction?
    Today we went into public beta. Please check us out if you can, and leave feedback so we can improve.
    → 8:39 PM, Jan 27
  • eReader for Android!

    They just released a version of the eReader software (formerly Palm eReader, then just eReader, now the Barnes and Noble eReader) for the Android platform.

    It’s a little bit buggy: you need to wait for an entire book’s table of contents to load before reading/scrolling, else the book will get stuck partway through. Other than that, it works great on my G1. Nice to see a commercial ereader on a Linux platform. (Yes, the books still have DRM, but the format’s got some longevity behind it, and is supported on enough devices that I’m not worried about getting locked into one platform).

    → 8:39 PM, Nov 29
  • RSS
  • JSON Feed
  • Surprise me!