Monday, October 5, 2015

Off to new adventures

A few weeks ago I posted about moving teams inside of Microsoft.  As sometimes happens when you make a change, you realize that you actually need to make a bigger change.  A few weeks into the new team, and I could tell that it was time for me to move onto new adventures.

Microsoft has been a great place for me to "grow up" as a program manager.  When I started as an intern, I was mentored by some of the most capable PMs I've ever met.  They took a keen interest in me, and I benefited greatly from their years of experience and patience.

From a little bird of a PM, I grew to being able to lead the great TypeScript team.  I got to meet countless numbers of people and make some good friends along the way.  It was a wild adventure to be on the team, and I'm excited to see what they come up with next.

But as little birds grow, there comes a time to leave the nest and to take more risks. There are many adventures to be had, and to have them, you have to ride out the storms in search of the blue skies.

My first step will be to take some time to travel the world and see friends I haven't seen in years.  My goal: recharge, explore, and take stock.  After that, who knows.

Part of the adventure is not seeing the way ahead and going anyway.

Friday, September 4, 2015

Moving lower in the stack

It's time for something new.  On Tuesday, I'll be moving from the TypeScript team to the Chakra team.  Chakra is the JavaScript engine for Edge/IE.

It's been an awesome ride, coming up on 3.5 years on the TypeScript team.  I was fortunate enough to jump in before it was publicly released.  Since then we released 1.0, announced Angular 2 being built on TypeScript, and recently announced React/JSX support (and a bunch of other cool stuff in between).  TypeScript is doing better than ever, and the team is growing.  If you're interested in joining up definitely send in your resume.

For me, though, it's time to jump into a new set of challenges.  Counting my time doing programming language design as a hobby, grad school, and the TypeScript team, I'm coming up on 10 years.  While I love programming languages, I wanted to take a break and experiment with other parts of the stack. I got the itch to jump into doing systems level design again.

Before joining the TypeScript team, I worked on compilers, real-time signal processing, head-tracking, and hardware emulation.  A year ago, for fun, I threw together a little JIT to try out what it's like to jump in and out of the code you assembled on the fly.  

Working on a JIT and wanting to do low-level development got me talking to the folks on the Chakra team.  After chatting with a few people, it sounded like a good fit.  I'm looking forward to de-rusting my C++ skills, sharing what I learned in the JavaScript world, and learning a bunch of new optimization, development, and hardware tricks.

It's bittersweet to make the move, as I've grown close to the people on the TypeScript team and the people I met over the last 3.5 years, but I'm also equally excited about jumping in and sharpening a whole new set of skills on the Chakra team.

Living the low-level dream, here I come.

Saturday, February 21, 2015

Where am I?

For those of you who stumbled onto this blog and are wondering where I am these days, you can follow along with my current project, TypeScript, on the TypeScript blog or following @typescriptlang on Twitter (I'm also @jntrnr if you want to follow me).

Saturday, October 8, 2011

Running a limited REPL in Racket

Let's say you want to only expose some functionality to a REPL and you're using Racket.  One way to do this is to create a module with the functionality you want to expose and then create a namespace that only includes this functionality.


(module um racket
  (provide x doit #%module-begin #%app #%datum)
  (define x 100)
  (define (doit a) (display (+ a 1))))


#lang racket

(define ns (make-base-empty-namespace))
(define (ns-req e ns) (parameterize ([current-namespace ns]) (namespace-require e) ns))
(ns-req "modlang.rkt" ns)

(define (prompt-user)
  (printf "prompt> ")
  (define input-string (read-line (current-input-port)))
    [(not (string=? input-string "quit"))
     (printf "~a\n" (eval (read (open-input-string input-string)) ns))


And now you can run use_modlang.rkt.  At the prompt you can only do simple numerics, x, and the doit function, but even + isn't available.

Wednesday, September 21, 2011

Promising New Programming Languages

It seems like these days there are lots of programming languages springing up.  A combination of the web, parallel programming, and just outright curiosity seems to be fueling creativity towards new mixtures of classic features and experimental new ones.

Here are a few new(-ish) projects I'm keeping my eye on:

  • Rust (Mozilla Research) - Concurrent language that only allows sharing of mutable state if it's handed off between threads.  Uses typestates to enforce this ownership.  Expected to be used in Project Servo, Mozilla's experimental parallel browser engine.  Recent talk slides look promising.  Still experimental (haven't reached 0.1 yet).
  • Kotlin (JetBrains) - Impressively clean/lightweight syntax language for the JVM in the spirit of a Scala light.  Perhaps may be to Scala what Firefox was to Netscape, but it's not yet release so it's hard to say for sure.  Still, their presentation at the JVM Language Summit is worth a watch. 
  • ooc - You have to like the infectious audacity of this project.  Hobbyist putting together a language, then proceeding to write one compiler for it in itself and then another.  
  • Dart (Google) - Mentioning it here because I'm curious, but the hype has already overshadowed it. We're still weeks away from knowing anything about it.  Still, Gilad Bracha is like a "curiously strong mint", so we at least know it won't be flavorless.

These are just the ones on my radar.  There are certainly others (Ceylon, Gosu, Mirah - and those are just the ones on the JVM), but they haven't quite made it to my twitter follow list.

Sunday, September 18, 2011

Fun with pattern matching in Racket

Finally managed to circle back to playing with Racket.  The more I play, the more impressed I get.  Here are a few examples, from how Racket handles pattern matching:

(match 2
  [1 'one]
  [2 'two]
  [3 'three])

; outputs 'two

This is from the Racket language guide, which so far is proving to be a pretty good place to dip in your toe.  It's got tons of examples without drowning you in all the variations that Racket allows.  I get the feeling that Racket has a very lush vocabulary, which makes drowning a real danger.  Scuba gear attached, we dive in.

We see from the first example that something we might have suspected: we can match against pretty much anything.  Having this kind of general flexibility gives using the system a nice predictable even-ness.  We'll see later that Racket also allows us a few useful other tricks for certain data types.

(struct item (label size))
(match (item "foo" 4)
  [(item "foo" 4) (display "matched!")]
  [2 'two])

Here we create a struct that has two fields: a label and a size.  We match against a new value of this type with something that matches it directly.  Notice, too, that our patterns don't have to have the same "type", we can try to match against potentially very different data types.

That's cool, but not particularly powerful.  To gain some flexibility, we introduce variables into our patterns.  Once we do this, the value in that position in what we match against is bound to our variable, and we can use it later.

(struct item (label size))
(match (item "foo" 4)
  [(item lbl 4) (display lbl)])

; outputs foo

Now 'lbl' is going to have the string "foo" bound to it once this pattern matches.  Those who've played with Ocaml or Haskell might be familiar with this - and it's the heart of pattern matching.  Being able to pull your data apart and get at the values you need, and to do so in a very succinct way, is very powerful. Once you get used to having it, you loathe going back to languages that don't have it.

Do not fear, Racket has it in spades.

Let's get a bit trickier and switch to working with lists.  To help us play with lists, Racket has '...' which is a way to match multiple things in a list.

(match '(1 2 3 4 5)
  [(list x ...) (print x)])

; outputs '(1 2 3 4 5)

Again, not particularly interesting (at first).  We can match an entire list into a variable.  Now, we let our imagination run wild.  What else can this '...' do?  By looking at the syntax, we can hypothesize that the '...' after a variable means to match everything in that position and after with the variable.  Is it smart enough to match everything but, say, the last element and then bind that to a separate variable?

(match '(1 2 3 4 5)
  [(list x ... y) (begin (display x) (display "\n") (display y))])

; '(1 2 3 4)
; 5

It is smart enough!  We can match lists as if they were simple regular expressions.

We can even have multiple '...'

(match '(1 2 3 4 5)
  [(list 1 x ... 3 y ... z) y])

; '(4)

If the '...' follows a constant, it matches it being repeated

(match '(1 1 1 3)
  ((list 1 ... x) x))

; 3

Very cool, and this barely scratches the surface.    

Let's say we wanted to match the elements in a list, but we weren't sure of the order.  I can see you shaking your head "oh no".  Oh yes!

(match '(1 2 3 4)
  [(list-no-order 3 x 4 1) x])

; 2

What happens if we throw multiple variables in that pattern?

(match '(1 2 3 4)
  [(list-no-order 3 x 4 y) (begin (display x) (display y))])

; 12 (for me)

I have no idea what kind of deterministic order it picks, if any, but there you have it.  We can mix list-no-order with '...'

(match '(1 2 3 4 5)
  [(list-no-order 4 2 y ...) (display y)])

; '(1 3 5)


Going back to the list style, we can also match against a duplicate value

(match '(1 2 3 1)
  [(list x 2 3 x) x])

; 1

If we changed our matched value '(1 2 3 4), it would fail, because x can't be bound to both a 1 and a 4.  In the example, we bind x to the same value multiple times, so it succeeds.

What if we wanted to do the same thing, but we weren't sure where the duplicates would occur.  We might be tempted to use the list-no-order from before:

(match '(1 2 3 1)
  [(list-no-order 2 3 x x) x])

but this throws an error:

compile: unbound identifier (and no #%top syntax transformer is bound) in: x7

Not a particularly helpful error at that, unless you notice that 'x7' might be referring to some kind of uniquing going on that we don't want.  We can tweak our example to get what we want (and there may be a more idiomatic way - anyone know?)

    (match '(1 2 3 1)
      [(list-no-order 2 3 x ... ) x])
  [(list x x) x])

; 1

Can matching patterns have expressions?  Scary thought.  Oh wait, that's normal in these parts

(match '(2 4 6)
  [(list (? odd?) ...) (display "odd")]
  [(list (? even?) ...) (display "even")]
  [_ (display "neither odd nor even")])

; even

If you can use expresions, can you also call functions and check their results?  Of course

(match '(4 5 6)
  [(list 1 _ ...) (display "starts with 1")]
  [(app length 3) (display "has three elems")])

We've been using a lists quite a bit, but let's not forget that many of these patterns work with structs too

(struct person (name height))
(match (person "bob" 6.0)
  [(person (app string-length 3) _) 
   (display "Name of three chars")])

Incidentally, if we want to bind to the result of an inner pattern, like capturing the name that matches this string-length, we can use the 'and' keyword.

(struct person (name height))
(match (person "bob" 6.0)
  [(person (and x (app string-length 3)) _) 
   (display (string-append "Name of three chars: " x))])

This is ridiculously fun to see what all can do.  Thanks for reading!

For those curious in exploring further, the full list of pattern types that Racket supports is enormous, with lots more tricks like those above.

Monday, March 7, 2011

Will parallelism go implicit?

I've been spending quite a bit of time recently with Implicit Parallel Programming in pH, which luckily the school library had a copy of.  It's quite a good textbook to introduce programmers to functional programming, perhaps even one of the better ones (next to the original Introduction to Functional Programming by Bird, Wadler that I mentioned in an earlier blog post).  What turned me on to it, though, wasn't the treatment of functional programming - it was its far more audacious titular goal.

Which leads to the obvious question. What is implicit parallelism?

If you bring up the term around PL geeks, you might get a few questioning looks and some comments that hint at automatic loop parallelization.  Even more confusingly, this second kind of parallelism is sometimes referred to as automatic parallelism.  It refers to taking sequential codes and reasoning about where parallelism could occur without changing any results.  Implicit parallelism is a more holistic approach - what if the only sequentiality in your program comes from the data dependencies?  Then the rest, it stands to reason, can be done in parallel.

I mentioned this as an audacious effort.  The first and foremost reason, to my engineering mind, is how in the world will you make this efficient?  I can just imagine the compiler identifying tens, perhaps even hundreds, of tiny tasks that can be done in parallel at any one timeslice.   How do we schedule these tasks in such a way we don't pay a high overhead for synchronization and task switching?

I haven't dug into the implementations of the languages yet to see how they address this issue, but as I was brainstorming this morning it hit me.  Implicit parallelism isn't so different from implicit (or automatic) memory management.  When garbage collectors first came out, they weren't the lean mean things they are today.  That's part of the advantage of having decades to polish an approach, and now fewer and fewer applications programmers use languages that don't have gc support.  It saves more headaches than it causes, and that's generally a winning combination.

Not always, of course.  The HPC community has regularly shunned gc in their languages, where high performance codes are hand-tuned Fortran or C with manual memory management.  Still, I would argue that HPC is boutique, a cottage industry focused on maximal efficiency.

Most everyday programmers don't need these levels of efficiency, and I imagine, will instead opt for automatic support for parallelism.  This saves them the headache of separately tuning for the same application to run comfortably on either 16 or 128 cores.  From the consumer's point of view, this is also a win.  Buying that new 256 core machine actually will make these apps run faster.

Some final thoughts

Perhaps it's time to focus on introducing more forms of automatic and implicit parallelism into our programming languages and runtime systems.  Our early attempts, taking from the experiments of the past could kick it off, and once industrial interest has turned to it, I'd expect steady progress in efficiency (just like we've seen in gc).

Is there some practical limit to the amount of parallelism in code?  There's a tension between Amdahl's law, that maximum speedup through parallelism is limited by the amount of sequential code, and Gustafson's law, which says that the increased computing power lets us tackle larger problems.  To continue to gain we may have to change how we approach problems, or even reframe the problems themselves.