Peter Christensen

  • Presentations
  • Contact Me

Thoughts on Choosing a College

October 20, 2018 by Peter Leave a Comment

A friend asked for advice for her son on how to choose which college to attend. Here’s my $0.02. (Note: Most of my examples are technical-related, because that’s what I know.)

The things you get from college are, from most to least important: certification, connections, and education.

Certification – many jobs in many fields require a college degree. Period. It’s proof to a hiring manager that you can follow directions for a long period of time. Without a degree, the burden of proof is on you.

Connections – at college, you meet peers, work with professors, and connect with alumni. These can be valuable connections, but only if you use them. The value of this is very school- and career-specific. For instance, every Supreme Court Justice went to either Harvard or Yale. Stanford is deeply tied to the tech entrepreneurship community, USC to filmmaking, CalTech to NASA, etc. If you know you want to enter a career that’s tightly coupled to one school, then it can be worth the cost to go there. Also, if you want to live in a certain region, then attending a big state school there gives you lots of general connections – eg if you go to Ohio State and stay in Ohio, you’ll have a connection to lots of people across society there. This goes double for careers with state certification like law and teaching.

Lastly, education. Once you’re in a decent enough school, the level of education is largely a product of what bar you set for yourself and how hard you work to achieve it. Many of the best programmers are self taught because they put in time way beyond what school would require. Top athletes, artists, etc go way beyond what you need for an A. This is available to anyone with an internet connection.

My advice to a future college student would be: if you absolutely know you want to work in a field strongly affiliated with a certain university, by all means go there and consider the cost an investment. Otherwise, if you’re going to a less specific field or don’t know what you want to do, go to the least expensive Division 1 college in the region you want to live in and spend as little money as possible until you know what you want to do. Then, use your courses as a starting point to learn as much as you can and produce as much demonstrable work as possible. Your work and knowledge aren’t limited by where you go to school, but your career choices can be limited by how much you spent on school.

Filed Under: Education

Learning Foreign Languages with Fluent Forever

September 18, 2018 by Peter Leave a Comment

I’ve followed Tim Ferriss since the first release of The Four Hour Work Week. He’s taken his share of criticism, and his huge success has given him a bit of an excessive reputation, but he is world class at showing how to break down a problem and create a process to solve it. His material goes into depth, so reading his new blog posts or podcast episodes is often too much at that moment. But when you encounter that problem, his resources are some of the best to go to when getting started.

Tim is big into travel and foreign languages, and he has had three long posts about learning a new language, two of which were guest posts by language learning experts. I skimmed all three and decided to dive into the process by Gabriel Wyner of Fluent Forever, in the article “How to Learn Any Language In Record Time and Never Forget It”. It ended up being 20+ pages printed, along with a feast of links to Gabe’s other writing and materials.

Here’s a one page summary of his main points:

To really learn a word in a foreign language, you need to build connections to all parts of that word – spelling, sound, meaning, and personal connection.

First, learn the sounds (1-3 weeks):

  • Study the specific sounds that are new or different in the target language – he has compiled these “Pronunciation Trainer” lists and sells them for a reasonable price, and he tells you how you can make your own
  • Practice hearing, pronouncing, and spelling the sounds

Second, learn a set of common words using pictures (1-2 months)

  • Common words are used more often, so learning them has disproportionate benefit
  • Google search for images using the foreign word, not your native translation, so you can learn the subtle differences in meaning
  • Making your own cards with images you found is part of the learning process

Third, learn grammar and abstract words (2-3 months)

  • Grammar is easy when you have a strong vocabulary
  • Learn grammatical forms using example sentences
  • You can get translated sentences from Google Images, by finding the original captions
  • You can have your own sentences translated at sites like Lang-8

After that, you pursue fluency in the way that works for you:

  • YouTube has lots of video of long-running TV programs in many languages. The familiarity of character and voices make them easier than news or movies
  • Books you know or about topics you’re familiar with are more likely to engage you and get you to actually study – in one of Tim’s other language blog posts, he wrote about how much Japanese he learned from a judo textbook
  • For speaking, you can find tutors on Craigslist, foreign language Meetup groups, or find people to talk with on sites like iTalki.com.

Gabe’s article was a wealth of information, and if my summary is useful, you should read his whole long post. For ~$50 you can get his pronunciation trainers and word lists, and the Anki mobile app. He’s also making his own app that looks to incorporate his training methods and materials, but it’s still in beta/pre-order as of September 2018.

I’m going to add the Fluency Forever methods to my daily use of the Hello Chinese app. I will report on my progress.

Resources:

  • How to Learn Any Language in Record Time and Never Forget It – guest post on Tim Ferriss’ blog
  • Fluent Forever – https://fluent-forever.com/
    • Book – https://smile.amazon.com/dp/0385348118/?tag=toweofbabe-20
    • App – https://fluent-forever.com/app/ – looks like it encapsulates the flash cards, spaced repetition, and word lists
    • Pronunciation Trainer Anki flashcard decks – https://fluent-forever.com/product/fluent-forever-pronunciation-trainer/
    • Word lists – https://fluent-forever.com/product/most-awesome-word-lists-ever-seen/
  • Anki Spaced Repetition program
    • Web based version, links to desktop downloads – http://ankiweb.net/
    • AnkiMobile iOS app ($25) – https://itunes.apple.com/us/app/ankimobile-flashcards/id373493387?mt=8 – he recommends it because the free app from Ankiweb doesn’t cache audio files
  • Fluency Practice Resources
    • Lang-8 – get sentences translated to a target language, either paid or in exchange for translating other users’ sentences to English
    • iTalki– get in touch with a conversation partner, either free for talking half of the time in your native tongue, or $4-$12/hr to talk all in the foreign tongue

Filed Under: Book Review, Education

Kia-Fu Lee, AI, and Sinophilia

September 4, 2018 by Peter Leave a Comment

I’m a heavy consumer of media. I called it learning, but even if it was tech stuff or business stuff or whatever, I realized that because I wasn’t writing anything down or changing anything about my life or career, it was the equivalent of watching TV, just with a browser history. So my two content goals now are:

  1. Focus on reading/watching things worth taking notes on, and
  2. Summarizing and publishing those notes.

Like many Americans, I’ve been aware of China’s growth my whole life, from the little gold stickers on my toys, to their manufacturing rise, to crazy GDP numbers, the Great Firewall, etc. And like many Americans, I always assumed that no matter how successful China was, it wouldn’t threaten America’s pre-eminent position in the world order. But this year, China has been seeping into pop culture and technology, arguably the two industries most dominated by America. In movies, I noticed Chinese companies providing financing, movies like World of Warcraft that were made partly because of the interest of Chinese audiences, and noble, heroic Chinese characters in movies like The Martian, Pacific Rim 2, The Meg, and more. Watching Crazy Rich Asians topped it off – seeing a whole movie where every character was better looking, richer, smarter (ok, maybe not Bernard) and more successful than even American movie characters, flipped a switch in my head. China wasn’t an abstract concept – it’s a real place full of real people, as diverse and alive as America. That, overnight, flipped my interest in Chinese culture and it got me looking.

Over this same timeframe, multiple sources referenced Kai-Fu Lee, the Chinese AI researcher and venture capitalist. I briefly encountered his work years ago when I hobby-level explored speech recognition. I found his TED talk, and I find them to be a useful introduction to a person’s work. He’s unapolagetic about how hard Chinese entrepreneurs work and how in the field of AI, America retains the advantage for research and discovery, while China has the advantage in implementation and business. I’d heard bits of this sentiment, but they lacked the clarity and authority that Lee presented. He also showed the transition that work will take post-AI, from manual and repetitive to personable (social work, teacher, etc) and creative (research, marketing, arts, leadership, etc). It’s still a huge transition, but hopeful.

Since I’m super impressionable to things once I let myself be convinced, I have decided to double down on my work learning machine learning, deep learning, and AI, and to begin learning Chinese. There are so many resources, apps, courses, that this is something limited by my time effort, not availability or resources. We’ll see how it goes.

Filed Under: Education, Personal Sprints

Surviving the Framework Hype Cycle – Brandon Hays

May 13, 2016 by Peter Leave a Comment

I was recommended this 35 minute talk from the Mountain West Ruby 2016 conference, and I wanted to share my notes. It captures feelings I’ve had about the pace of technology change, with the rise of Javascript frameworks over the last 4 years. It’s a useful framework for evaluating new technologies, as well as when is the right time for you to adopt them. FWIW I’m definitely a Settler.

Great talk, Brandon!

Links

  • (35 min vid) – https://www.youtube.com/watch?v=9zc4DSTRGeM 
  • http://confreaks.tv/videos/mwrc2016-surviving-the-framework-hype-cycle
  • https://speakerdeck.com/tehviking/surviving-the-framework-hype-cycle
  • https://news.ycombinator.com/item?id=11659611

Notes

  • Web developer’s career ins entering a mid-life crisis
  • Pain points
    • impossible to keep up with new tools
    • There’s no way new things can live up to your expectations
    • New stacks are less robust and more brittle than older
    • The tech you love is now obsolete – it’s never safe to fall in love
  • Once a tech gains popularity, it doesn’t go away, it just loses popularity
  • The Hype Cycle
    • Technology trigger, early adopters
      • e.g. Rails 5 minute blog video
    • Peak of inflated expectations
      • Promise – this will make you 10x more productive
    • Trough of Disillusionment
      • Prominent defectors – e.g. Zed Shaw “Rails is a Ghetto”
    • Slope of Enlightenment
    • Plateau of Productivity
  • 3 types of users
    • Pioneers – itch for the latest, thrill of discovery
      • Vision/Experiments
    • Settlers – order from chaos, build infrastructure and community, connect with real users and business need
      • Strategy/Synthesis
    • Town Planners – get things done at a scale not possible with unproven tech – turn exciting tech boring
      • Tactics/Execution
  • How to lose at the hype cycle
    • Dismiss new stuff, become commodotized
    • Get caught up in the cycle and burn out
    • Bet and crash with tech that doesn’t clear the trough
  • How to win – depends on your preferences
    • What stage is the tech in? Should I concern myself?
    • Pioneers ride the wave at Peak of Inflated Expectation
    • Settlers start at Trough of Illusionment, full speed at Slope of Enlightement
    • Planners start at Slope of Enlightenment, Plateau of Productivity
  • The Comfort – No one gets to make you feel ashamed for liking the things you like
  • The Caution – There comes a time for you to leave the plateau
  • Recommendation
    • Day job with productivity
    • Side project for fun with less mature technology
  • The real promise is on helping you reach the plateau
    • To focus on things that have real value, business value
    • One the plateau, you have time to think

Filed Under: Presentations

Learning iOS, Swift Part 1

August 25, 2015 by Peter Leave a Comment

I’m about a week into learning iOS and Swift 2.0 and I am pleased and impressed. For reference, I’m using this course (currently $59 on StackSocial).

This week, I went through the basic Swift language sections and lessons about creating a basic app to demonstrate controls, outlets, and actions. I am pleased at how Swift looks so natural and unsurprising – I have to admit that I looked iOS a couple years ago and a page of Objective-C was enough to make me turn around and leave.

For background, I programmed in Pascal as a kid, then C and C++ in college (which I hated), then C# for my first 5 years of work (which I loved), then Ruby/Rails/JS/web for the next 5 years (which I currently love), with Common Lisp and Clojure sprinkled over the last several years for fun. Ruby is my goto language for getting things done, but Clojure is inspiring for its clarity of design and how it guides you to do the right thing. Swift has nice, comforting C-style syntax while providing a lot of the guidance, protection, and convenience that I like about Clojure. For instance:

  • the way you have to opt into nil using Optional types
  • the way you can save some boilerplate where possible using the forcible unwrap operator
  • using guard instead of if to emphasize your main logic
  • the flexibility around parameters – binding a local variable with the param name, explicit inout params when you need to change them, variadic parameters

I tend to program defensively and I get the feeling Swift will make that very natural.

I had more fun using the Storyboard, view controllers, and control library than I’ve had in a long time. My first work as a programmer was building Windows Forms in .Net 1.1, and it was so fast and productive for such a rich app experience. I love the web, but no web programming I’ve ever done (even now in 2015) has that same rush of creating results as fast as you can click and type as I got from using Visual Studio way back when. But building a silly toy app that lets you click buttons to change background colors and show/hide controls when you toggle a switch was every bit as good. I know there’s so much more to iOS than the control library, but if the rest of the platform is a well developed and simple to code against as that, then I’m in for a real treat!

Next up are an Ad Libs app and an RGB app.

 

Filed Under: iOS, Programming

Finding Things Fast in Emacs

August 17, 2015 by Peter Leave a Comment

I use emacs, and it is super powerful, but out of the box, it has some rough edges. Finding files in stock emacs isn’t great.

I used to use a plugin called find-things-fast (https://github.com/eglaysher/find-things-fast), but a previous employer had a codebase too big that made it grind to a halt. (Hint: different projects should be in different repos.) I grew out of the habit of using it, but when I upgraded and tried using it again, I got no results. Turns out the new version has a file extension whitelist, and the author sets it to his type of project, the Chromium project with lots of C++ file extensions. I wanted to use the file extensions for my projects, but rather than guess and make an ad-hoc list, I decided to roll up my command line sleeves and figure it out for real.

Find all files in Git repo:

git ls-files

Run a regex to strip out the ending file extension:

git ls-files | perl -ne 'while(/\.[^\.\/]+$/g) {print "$&";}'

Sort the lines, and filter down to unique extensions:

git ls-files | perl -ne 'while(/\.[^\.\/]+$/g) {print "$&";}' | sort | uniq

Append this to a file:

git ls-files | perl -ne 'while(/\.[^\.\/]+$/g) {print "$&";}' | sort | uniq >> ~/src/file_extensions.txt

Run this command in each project.

Create a sorted unique list from all projects:

sort ~/src/file_extensions.txt | uniq > ~/src/sorted_file_extensions.txt

The I used an emacs editor macro to make an elisp list of wildcard strings, that looked like this:

'("*.asd" "*.bash" "*.bowerrc" "*.clj" "*.cljs" "*.coffee" "*.conf" "*.css" "*.csv" "*.editorconfig" "*.el" "*.eot" "*.erb" "*.example" "*.gif" "*.gitattributes" "*.gitconfig" "*.gitignore" "*.gitkeep" "*.gitmodules" "*.goo" "*.haml" "*.htm" "*.html" "*.info" "*.irbrc" "*.jade" "*.jpg" "*.js" "*.jshintrc" "*.json" "*.k" "*.lisp" "*.lock" "*.lua" "*.md" "*.nrepl-port" "*.nvmrc" "*.orig" "*.png" "*.rake" "*.rb" "*.rdoc" "*.rspec" "*.ru" "*.ruby-gemset" "*.ruby-version" "*.scm" "*.scss" "*.sh" "*.sml" "*.ss" "*.swf" "*.texi" "*.text" "*.ttf" "*.txt" "*.woff" "*.xml" "*.yml" "*.zsh")

I customized the variable ftf-filetypes, restarted emacs, and now if works like a dream again. Thanks Elliot!

Filed Under: Emacs, Programming

Starting to Learn iOS, Swift

August 16, 2015 by Peter Leave a Comment

I have a project idea that has been bugging me for years, and I finally feel like it’s time to work on it. It’s an app, with a server-side back end. In the past I had been focused on startups and making a business, but I realized that at this point in my life and career, I’d rather stretch and expand my technical skills. Admitting that lets me focus on it as a cool technology project, and demands that I learn new things, as opposed to starting a company, which would require me to use what I could be most productive with right away.

I’ve been a Clojure fan for years but was never had more than intermediate mastery of it, and never used any of the amazing cutting edge libraries from that community. But the combination of ClojureScript, various React wrappers (Om, Reagent, etc), React Native wrappers, and Datomic is such a compelling stack that it has kicked me into action. This talk from David Nolen is a great summary of the state of advanced Clojure:

As much as I would love to lean on the Clojure stuff, I have been burned in the past when I didn’t know the stack underlying a cool library. So over the next few months, I’m going to learn Swift and iOS, and then React. For Swift, I’m using this course on iOS 9 and Swift Mastery. Several iOS developers recommended the Stanford iOS course from iTunes U, but I wanted a course that covered the newest version of Swift, because of the big recent changes.

I plan on writing up my experience learning Swift, and downloading Xcode 7 (3.6 GB) gave me plenty of time to write this!

Filed Under: iOS, Programming

Faking an ActiveRecord Attribute

June 12, 2015 by Peter Leave a Comment

Recently, I had a problem in Rails that took some extra research to solve. In the process, I read numerous StackOverflow posts, mailing list posts dating back to 2008, and tried, like, a million things before coming to a fairly clean solution. The solution is either clever or genius, and either way, future me will need present me’s help to understand it, which is why I’m writing it down.

The problem was that I had a Rails ActiveRecord model User, that had an attribute named phone. We switched our associations so that a User could have multiple PhoneNumber objects, but we wanted to preserve the user.phone and user.phone= interface.

The classes look something like this:

  class User < ActiveRecord::Base
    has_many :phone_numbers, as: :phoneable, dependent: :destroy
  end
 
  class PhoneNumber < ActiveRecord::Base
    belongs_to :phoneable, polymorphic: true
  end

All the rest of the code is in the User class.

In order to ensure that the accessor methods were operating on the same object, I wrote a wrapper method for accessing the same object:

  def phone_number_obj
    phone_numbers.find_by_primary(true)
  end

The getter looked like this:

  def phone_number
    self.phone_number_obj.try(:number) 
    # PhoneNumber objects have a string field named number
  end

The setter was a little more complicated, because it had to either create or update a PhoneNumber object:

  def phone_number=(new_phone_number)
    if p = self.phone_number_obj # Number already exists
      if p.number != new_phone_number # Only update if number changes
        p.update_attributes(number: new_phone_number)
      end
    else
      phone_numbers.create({primary: true, number: new_phone_number})
    end
  end

All this worked lovely and wonderfully for objects that already existed, but it caused a number of problems when creating objects. ActiveRecord uses attribute setters when creating and initializing objects, but phone_number= requires that the User must already be persisted in order to create a PhoneNumber object in its phone_numbers association. I needed to strip out the phone_number attribute when creating a new User, save that value, and then create the PhoneNumber object once the User was saved.

The second part, creating the PhoneNumber object was saved, was easy. ActiveRecord callbacks (http://guides.rubyonrails.org/active_record_callbacks.html#available-callbacks) include after_create:

  after_create :assign_phone_number
  def assign_phone_number
    if @phone_number
      self.phone_number = @phone_number
    end
    @phone_number = nil
  end

The first part, stripping out the incoming attributes when creating a new object, that was not so easy. Lots of painful searches (most of which told me to not do what I was trying to do) and experiments later, I learned some things about Ruby and Rails and came up with something that worked.

  • The earliest AR callback, after_initialize, was too late for what I needed to do. When it runs, all of the attributes have already been assigned.
  • I thought of them interchangeably, but new is a class method on the model, and initialize is an instance method (this was a good explanation: http://stackoverflow.com/a/10383786/1895697). Model.new creates an object (allocates memory, connects functions, language implementation stuff), and the it calls initialize on the new object, which sets values for attributes. I tried overriding new (based on the implementation in http://api.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create), on the model, and it worked as expected in console but it failed in every rspec test, with the very unhelpful error:
    • Failure/Error: Unable to find matching line from backtrace
      ArgumentError:
      wrong number of arguments (2 for 0..1)
  • super is a helpful keyword when using inheritance. You can call it with specific parameters
    • super(a, b)
    • or if you call it with no parans or arguments, it passes the same parameters in the same order as the containing function.

Once I figured that out, the implementation was pretty straightforward:

  def initialize(attributes = nil, options = {})
    phone_number = nil
    if attributes.is_a?(Hash)
      phone_number = attributes.delete(:phone_number)
    end
    new_user = super
    phone_number && new_user.instance_variable_set(:@phone_number, phone_number)
    new_user
  end

This lets me:

  • strip out the phone_number attribute so the setter is not called during initialization
  • use super to assign all the remaining attributes with ActiveRecord::Base.initialize
  • Save the phone_number you stripped into an instance variable so the after_create hook can use it
  • Return the user object as expected

Since it preserves all the behavior of initialize, ActiveRecord association methods that create Users still work.

Caveats

  • This is a usable but not perfect copy of the AR interface. For instance, you can’t put phone_number in a .where query or dynamic finder.
  • This does a lot more database queries. It could be reduced by caching the phone number in an instance variable but for now I’m going for correctness.
  • The setter (phone=) uses update_attributes on the PhoneNumber record, so there’s no way to assign a new phone number and save later.
  • This doesn’t play nicely with new, build, etc – the User has to be persisted before the PhoneNumber can be assigned to it. Lots of our tests and factories used build instead of create to save time, but those had to be changed from:
    • let(:user) { build(:user, phone_number: “555-555-5555”) }
    • to
    • let (:user) do
      u = create(:user)
      u.phone_number = “555-555-5555”
      u
      end

Conclusion

In retrospect, it probably would have been easier to break the .phone interface rather than hop through these hoops. This code is sort of a land mine that looks like one thing but behaves slightly differently. Use at your own risk, but it’s here in case you have this specific need.

Filed Under: Programming, Rails

#sfcljs August Meetup – Om vs Reagent vs Quiescent, Converting to Om

August 25, 2014 by Peter Leave a Comment

[UPDATE: Added links to slides for some of the talks]

ClojureScript is my new toy, so I was glad to see the San Francisco ClojureScript Meetup plan a new event, and all of the talks were about Om, which made it even better. It was a great event at Etsy’s SF office. Thanks to Melissa and Sean Grove for organizing it!

Here are my notes:

  • http://www.meetup.com/SF-Clojurescript-Meetup/events/201007552/
  • Official Meetup Hashtag: #sfcljs – https://twitter.com/search?q=%23sfcljs
  • Etsy (host) is hiring: https://www.etsy.com/careers/
  • Diogo
    • Slides: http://htmlpreview.github.io/?https://github.com/diogo149/om-no/blob/master/notes.html
    • Project: Social network with data mining, in stealth
      • switched from Om to Reagent
      • hit a wall after 5k+ LOC, months
    • What was good about Om
      • Global undo – really easy, but didn’t apply to the app
      • One atom to contain global app state
    • The Bad
      • reify and build/build-all was error prone – you have to keep straight which fns return reified functions and which are normal
      • API is verbose
        • he built syntactic sugar for it, but that shows weakness with API
      • Too slow – much slower than Angular JS
      • No anonymous fns as components
        • didn’t throw error messages, just re-mounted and caused site to flicker
      • Can’t compose components, because components track their parent
      • Cursors – pointers into app state
        • async transact! can change the value or order of the app state, making the cursor point to the wrong data
      • Local state mixed with global state
        • you can’t wholesale replace new app state, b/c you don’t know where it’s mixed with local state that you would lose
      • cursors behave like maps
        • you can pass maps like cursors, except for when you want to transact!
      • Need to Know principle
        • In React, components work best when they know as little as possible, so they don’t re-render for unnecessary changes
        • In Om, app state is a tree, so you need knowledge of lowest common ancestor
        • same data in multiple places
      • hard to be both consistent and performant
    • Reagent
      • principle of least surprise
      • more Clojure-y – lazy components, normal functions,
      • data model works better with React.js
      • easier to work with data as a direct acyclic graph
      • We were able to teach a new employee the codebase without knowledge of app or Reagent – testament of a good API
      • Simpler for small apps, more scaleable for large apps
    • Reagent – https://github.com/holmsand/reagent
  • Anton – http://textik.com/
    • Slides: http://www.slideshare.net/AntonAstashov/textik
    • ASCII diagram generator
    • Pet project, so he needed something he could build in an hour a day
    • Normal design of front-end web apps
      • observe changes in view models by any other observer models, sometimes cascading
      • Works well, but hard to figure out what happened in exception
      • Many inputs, many code paths
    • Prefer one-way flow of events → data → rendering → events
      • One global code path
      • Full state of the app when exceptions happen
    • Like React for fast view layer, use Quiescent for cljs
      • lightweight, ~200 LOC
      • Simple
      • Opinionless
    • Cons
      • slowly developing – few recent commits, pending pull requests
      • you have to maintain your own fork for e.g. animations
      • Has bugs that are fixed in Om
    • Lifecycle
      • Init – call Render
      • View – render, register event handlers that send payload to core.async channel
        • core.async used b/c you can’t have circular dependencies on namespaces, since view would require dispatch and vice versa
      • Dispatch – listen to channel, call mutators, call render
      • Mutators – change data (only layer where data is changed)
      • Data → return to Dispatch
    • Code – https://github.com/astashov/tixi
    • Minimal app using Quiescent, this architecture – https://github.com/astashov/mintik
    • Quiescent – https://github.com/levand/quiescent
  • Danny from CircleCI – Om From a Designer’s Point of View
    • Does not like writing Om, but likes how everything is in one language, so it’s easier to reason about (vs HAML, CoffeeScript, CSS, etc)
    • Can be harder to find where the data is coming from
    • Only sort of gets the lifecycle, design of components
      • Learning is coming faster than expected
    • Workflow + tools are the same except for a ~10sec delay when making changes
      • Using production data, and has to use the whitespace compiler to produce a single Javascript file
      • Sublime, Chrome Dev tools, etc
    • This is not a natural tool for a designer – most would need someone to help with the more programmery/Clojure-y stuff
    • Syntax for Hiccup etc isn’t a big change from HTML/CSS
    • Could use a more applicable cheat sheet for designers
    • Uses CSS or SVG animations
    • Surprised by React making assumptions/transformations on markup – e.g. moving an anchor to be a sibling of inline tag, from inside of it
    • Design process would be easier if he ran a local dev environment, but that’s a big new dependency that requires maintenance
  • Daniel from CircleCI – Converting a Site from Knockout to Om
    • Can now use CircleCI for open source projects – free container, public build pages
    • Open sourced front-end code: https://github.com/circleci/frontend
      • You connect to your own CircleCI backend data, so you can push changes/fixes to be merged into the main, public repo, while protecting your data
      • Still working out details of the open source workflow
    • (this was more showing code than presentation)
    • Old site used Knockout.js, 2-way data binding
      • data binding in JS, HAML-coffee templates in CoffeeScript, etc, so there were language mismatches, string interpolation
    • Converter from HAML-coffee to Hiccup – not perfect, but close enough
      • Difference between whitespace automatically included vs required
    • Event handlers put messages into core.async channels
    • Took about 2.5 months full time development to convert
    • How it works
      • All state is serializable in a single Atom
      • Build messages – something we know about the build that we want to tell you (~100 messages)
        • Gave a representative sample of serialized state to designer
      • In theory you can store and replay messages to rebuild state
      • core.async – e.g. Stripe checkout – complete/cancel puts message into channel, and the page blocks on that
    • Problems with Om
      • haven’t figured out testing, still just using webdriver tests
      • Rendering too much to the virtual DOM – parents have to know about child data, even if they don’t need it
        • hasn’t been too big a problem yet
      • Slow enough that you can drop characters on input, because of how much rendering goes on when everything is in global app state
        • More of a problem in tests
        • Needed to pull input data out of app state and into local component state

Filed Under: Clojure, Programming

Notes on Core.Async Webinar

August 23, 2014 by Peter Leave a Comment

Recently, David Nolen of Cognitect held a webinar about “Designing Front End Applications Using core.async”. I’m a huge fan of David’s teaching style (see his tutorials on Enlive, LightTable+ClojureScript, Om Basic and Om Intermediate) so I cleared my calendar. I’m very excited about Clojure’s front-end stack, with ClojureScript, core.async, and Transit, and after this webinar, I have a much clearer idea of how core.async fits in.

UPDATE: The recording is now live: http://go.cognitect.com/core_async_webinar_recording

Here are my notes

  • EXAMPLES – https://github.com/cognitect/async-webinar
  • Problems with Asynchronous programming
    • nesting callbacks is hard to maintain, read
    • JS is single-threaded
    • JS promises
      • better looking code, somewhat easier to read, but still a lot of callbacks. Chaining, not as nested
    • JS ES6 generators – extremely low level – core.async delivers the same benefits, but with a much higher level abstraction
  • ClojureScript
    • Cognitect – write the same types of apps, but simpler. Embrace and enhance the host
    • Immutability
    • ClojureScript – good interop with JS runtimes + libraries, with Clojure language platform
  • Why ClojureScript?
    • ClojureScript – good interop with JS runtimes + libraries, with Clojure language platform
    • Leverage Google Closure Compiler/Library
      • JS has many methods of packaging and delivery; Cljs only uses Closure
      • Superior minification + compression
        • dead code elimintation – include whatever you want, with no code bloat
      • Battle-tested standard library – support back to IE6
  • Core.Async
    • based on CSP (communicating sequential processes) – naturally captures one-off async tasks AND async streams/queues (e.g. mouse movements, etc)
    • Go blocks are a source transform that give the illusion of blocking, even in single-threaded context (i.e. JS hosts)
  • Terminology
    • Channels – conduit between different processes – put values in, take values out
      • Buffers – channels use them to configure backpressure, handle bursts of events; you can customize semantics
      • Transducers (new!) – efficient way to control how values enter and exit channel, e.g. map/filter
    • Go blocks – async blocks of execution with the illusion of blocking operations
  • Core Operations
    • putting values onto a channel
    • taking values off a channel
    • selecting over multiple channels (puts & takes)
  • 10 short examples
    • good enough first principles
    • repo available – https://github.com/cognitect/async-webinar – build, launch, follow along in browser
    • helpers
      • includes examples of JS interop
      • events→chan – listen for events, put them into the channel
        • use core.async to deal with events, instead of callbacks
      • mouse-loc→vec – turn events into vector
    • Example1
      • create a channel of clicks, block, and add a note
      • <! – blocking read inside of go blocks
    • Example 2 – same, but wait for 2 clicks
    • Example 3 – 2 channels, wait for one from each channel
    • Example 4 – shows how writing to a channel blocks that program until some other go block takes from the channel
    • Example 5 – separate go block to consume the channel
      • go blocks are like forking a process
      • looks like 2 separate processes running together and communicating over channels
    • Example 6 – stream processing
      • use transducer to convert events before they come into the channel
      • looks like an infinite loop – but getting a message off the click channel ends it
      • alts! – select over multiple channels – non-deterministically read from whichever channel has data first
        • line 140 – pattern matching on the channel
      • transducers let you work at a higher level of abstraction and data like you like it
    • Example 7 – more transducers
      • discard events unless the y is divisible by 5
      • loops can use the loop var bindings to record state
    • Example 8 – use loop vars to store state
    • Example 9 – more like real web
      • next/prev buttons to loop through a list
      • listen on prev/next channels to change vals, enable/disable prev/next
    • Example 10 – bigger example, broken out into helpers
      • more transducers – take all key presses, map the keyCode, filter by the set #{37 39}, and map them to :prev/:next
        • efficient because all those transformations happen in one function, inside the channel
      • click start, construct the keys channel
        • async/merge – take any number of channels, merge them into one channel (e.g. prev, next, keys) → a single channel that spits out :prev/:next
        • you can add more channels (e.g. left/right swipe on a tablet) and convert them to the same channels
  • Code is easier to manage and reason about new sources of events
  • Resources & Next Steps
    • original announcement – http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
    • Tim Baldrige Clojure/conj 2013 core.async talk (40 min vid) – http://www.youtube.com/watch?v=enwIIGzhahw
      • server-side work
      • portability between Clojure and ClojureScript
    • Facebook React – http://facebook.github.io/react
      • Works well with immutable data structures for UI
      • ClojureScript libs – Om, Reagent, Quiescent, Reacl
  • Q&A
    • How do you compose small pieces into a large front-end application?
      • Think about the abstract event types and handling, not concrete event sources
      • Core.async lets you write little distributed elements inside your UI
      • Components are independent and share a message language for coordination
    • Chan function – up to 3 args
      • int that sets buffer size or properties
        • more useful in server context than UI
      • on front end, best is to use size 1 and a transducer to transform the stream
    • Complex data?
      • All pre-built React components can work with any ClojureScript React library
    • Buffer size is 1 event – with data of arbitrary value
    • If you’re already running JVM, it makes more sense to use Nashorn JS on JVM lib instead of Node
    • You cannot monitor channels – they are purposely opaque

Filed Under: Clojure, Programming

Next Page »

Categories

  • Blog
  • Book Review
  • Business
  • Clojure
  • Education
  • Emacs
  • Fun
  • iOS
  • Lisp
  • Personal Sprints
  • Pictures
  • Polyphasic
  • Presentations
  • Programming
  • Rails
  • Startups
  • Uncategorized

Copyright © 2023 · Minimum Pro Theme on Genesis Framework · WordPress · Log in