How Fighter Jets Lock On: Tim Morgan
How Fighter Jets Lock On: Tim Morgan
he end of procrastination
is the art of letting go.
Ive been a lifelong
procrastinator, at least until recent
years. I would put things off until
deadline, because I knew I could
come through. I came through on
tests after cramming last minute,
I turned articles in at the deadline
after waiting until the last hour, I
got things done.
Until I didnt. It turns out
procrastinating caused me to miss
deadlines, over and over. It stressed
me out. My work was less-thandesirable when I did it last minute.
Slowly, I started to realize that procrastination wasnt doing me any
favors. In fact, it was causing me a
lot of grief.
But I couldnt quit. I tried a lot of
things. I tried time boxing and goal
setting and accountability and the
Pomodoro Technique and Getting
Things Done. All are great methods,
but they only last so long. Nothing
really worked over the long term.
Thats because I wasnt getting to
the root problem.
Curator
Lim Cheng Soon
Contributors
Tim Morgan
Eric Lippert
Justin Kan
Steve Klabnik
James Hague
Matthew Plant
Julia Evans
Jonathan Katz
Philip Guo
Bryan Kennedy
Advertising
Published by
Netizens Media
46, Taylor Road,
11600 Penang,
Malaysia.
Proofreader
Contact
Emily Griffin
Printer
Blurb
Hacker Monthly is published by Netizens Media and not affiliated with Y Combinator in any way.
Contents
FEATURES
Morgan
10 Melting Aluminum
By Eric
Lippert
Photo: Milan Nykodym [flickr.com/photos/milannykodym]
STARTUP
SPECIAL
34
14
By Justin Kan
By Philip Guo
38
By Bryan Kennedy
By Steve Klabnik
23
By Jonathan Katz
36
PROGRAMMING
18
By James Hague
24
By Matthew Plant
30
By JuliA Evans
FEATURES
Photo: flickr.com/photos/milannykodym
he primary technology
6 FEATURES
Photo: flickr.com/photos/milannykodym
8 FEATURES
Melting Aluminum
By Eric Lippert
10 FEATURES
11
I then surround the crucible with additional charcoal, put the lid on the furnace, turn the air back on,
and put an aluminum tube into the crucible through
the hole in the lid. Theres also a small amount of scrap
aluminum in the crucible already. You dont want to fill
the crucible with big pieces of aluminum as it will
expand as it heats, and possibly damage the crucible.
Its less of a concern with an iron crucible like mine;
ceramic crucibles are inelastic and can easily crack if
theyre full of expanding metal.
12 FEATURES
13
STARTUP
When to Sell
Similar to raising money, the best
time to sell your startup is when
you dont need to or want to. Paradoxically, you are probably thinking
about selling your startup as you
are experiencing a lack of traction,
tough competition, or difficult time
fundraising. However, this is a bad
time to sell your startup: you will
have few bidders and be more likely
to acquiesce to the demands of
anyone who does show up.
The best time to sell your startup
is when you have many options.
These options dont all have to be
acquisition offers, they can also be
venture term sheets for your next
round. You might even be operating
14 STARTUP
A competitor to an acquirer is
out-executing it in a business
and you can help the acquirer
become better.
Getting Offers
Bullshit Offers
15
Hiring a Banker
16 STARTUP
Closing
The most dangerous stretch during
the acquisition process is the time
between when you decide you are
going to sell, and when the sale
actually occurs. Youve decided to
exchange stress for riches, and you
can already see that new house on
the horizon (and maybe one for
your parents).
What happens when the acquirer
comes back and changes the total
deal value?
What happens when the acquirer
changes its mind, and you have to go
back to the grind?
What happens when the acquirer
has talked to your senior management, and then decided your team
isnt good enough?
If you are running low on cash,
what happens when you run out of
cash before the deal closes, because
In Summary
Entering the acquisition process is
one of the most dangerous things
an early stage startup can do,
because the process is distracting,
demoralizing, and usually involves
giving your competition most of
your proprietary business data.
Founders who have been through
the process have said it is ten times
as distracting as fundraising. It often
cripples your ability to oversee the
business operations. Do not enter
into an acquisition process lightly. n
Justin Kan is a partner at Y Combinator.
Previously he founded Justin.tv, TwitchTV
and Socialcam.
Reprinted with permission of the original author.
First appeared in hn.my/sellingcompany (justinkan.com)
17
PROGRAMMING
18 PROGRAMMING
Origins
From the start, there was an idea that something
needed to be built to handle some API-related things.
With this dummy commit, the first question kicked off:
Markdown or reStructured Text.
There were three big questions to tackle:
1. How can we validate that our API is working as
intended?
* - ``name``
- The display name of the account
`optional`.
An initial solution
It was settled that reStructured Text was the answer.
Heres what they looked like, roughly.
===============
accounts.create
===============
:uri: /v1/marketplaces/
(marketplace:marketplace)/accounts
:methods: POST
Fields
******
.. list-table::
:widths: 20 80
:header-rows: 1
* - Name
- Description
* - ``email_address``
- The email address of the account, unique
constraint.
:uri: /v1/marketplaces/
(marketplace:marketplace)/cards
:methods: POST
19
"$ref": "responses/cards.json"
matches: { "cards": [ { "links": { "customer": "{customer,customers.id}" } } ] }
20 PROGRAMMING
}
response:
status_code: 201
schema:
"$ref": "responses/customers.json"
matches: { "customers": [ { "merchant_
status": "underwritten" } ] }
- name: customer_with_card
request:
method: POST
href: /customers
schema:
"$ref": "requests/customer.json"
body: {
"name": "Darius the Great",
"email": "[email protected]",
"source": {
"name": "Darius the Great",
"number": "4111111111111111",
"expiration_month": 12,
"expiration_year": 2016,
"cvv": "123",
"address": {
"line1": "965 Mission St",
"line2": "Suite 425",
"city": "San Francisco",
"state": "CA",
"postal_code": "94103"
}
},
"meta": {
"ip_address": "174.240.15.249"
}
}
response:
status_code: 201
schema:
"$ref": "responses/customers.json"
- name: merchant_with_bank_account
request:
method: POST
href: /customers
schema:
"$ref": "requests/customer.json"
body: {
"name": "Henry Ford",
"dob_month": 7,
"dob_year": 1963,
"address": {
"postal_code": "48120"
},
"destination": {
"name": "Kareem Abdul-Jabbar",
"account_number": "9900000000",
"routing_number": "021000021",
"account_type": "checking"
}
}
response:
status_code: 201
schema:
"$ref": "responses/customers.json"
matches: { "customers": [ { "merchant_
status": "underwritten" } ] }
href: /cards
schema:
"$ref": "requests/card.json"
body: {
"number": "4111 1111 1111 1111",
"expiration_month": 12,
"expiration_year": 2016,
}
response:
status_code: 201
schema:
"$ref": "responses/cards.json"
- name: associate_customer_card_with_customer
request:
method: PUT
href: "{customer,customers.href}"
schema:
"$ref": "requests/customer.json"
body: {
"card_uri": "{customer_card,cards.href}"
}
response:
schema:
"$ref": "responses/customers.json"
- name: card_processor_failure
request:
method: POST
href: /cards
schema:
"$ref": "requests/card.json"
body: {
"number": "4444444444444448",
"expiration_month": 12,
"expiration_year": 2018
}
response:
status_code: 201
schema:
"$ref": "responses/cards.json"
21
22 PROGRAMMING
Here are the specs [hn.my/p2cspec] for push-tocard. By using this approach, we caught problems
before the feature was even finished. The initial implementation contained a bug with a typo in one of the
response keys. There was some confusion in one corner
of the spec, and while some of the discussion happened
in person, the ways in which the spec failed while the
feature was being built out helped make sure that
everyone was on the same page.
Going forward
Now that we have a testable validation that our API
is working as intended, we can do all kinds of things.
Wed like to integrate this suite into our more general
continuous integration suite. Wed like to run this test
every hour, or every three hours, which can be a form
of alerting against regressions.
In order to do all that, we need to fix our build.
Thats what happens when you dont run the tests
automatically: regressions can creep in and you wont
realize it. These failures are all related to a bug which
only happens with a brand new marketplace, and
doesnt strictly affect customer behavior. I wanted the
fix to roll out before this post, but you dont always
get what you want. This is a good reminder that tests
are not perfect, and that theyre a tool to alert you that
something may have gone wrong, not proof that theres
an error. Test code can be fragile or have bugs, too. But
without these tests, we wouldnt have realized that
there was a regression, no matter how small.
Its hard to get any complex software system behavior correct. So far, weve found that these external tests
give us a really nice forum for working out these kinds
of issues. They also give us something to share with our
customers, and a way to ask for advice from experts
outside of the company. n
Steve Klabnik is a Rails committer, Rust enthusiast, and works for
Balanced Payments in San Francisco. He has authored Designing Hypermedia APIs, Rust for Rubyists, and Rails 4 in Action.
When hes not programming, he reads philosophy books and
plays Android: Netrunner.
Reprinted with permission of the original author.
First appeared in hn.my/tddapi (balancedpayments.com)
nstructured program-
or
PRINT COS(2)/2
It wasnt just math. I remember seeing the Atari 800 on display in Sears, the distinctive blue
23
think that
writing a garbage collector is really hard, a deep
magic understood by a few great
sages and Hans Boehm (et al)
[hn.my/boehm]. Well, its not. In
fact, its rather straight forward. I
claim that the hardest part of writing a GC is writing the memory
allocator, which is as hard to write
as it is to look up the malloc
example in K&R.
A few important things to note
before we begin. First, our code will
be dependent on the Linux kernel.
Not GNU/Linux, but the Linux
kernel. Second, our code will be
32-bit and not one bit more. Third,
please dont use this code. I did not
intend for it to be wholly correct,
and there may be subtle bugs I did
not catch. Regardless, the ideas
themselves are still correct. Now,
lets get started.
eople seem to
24 PROGRAMMING
} else
p->next = bp;
freep = p;
}
#define MIN_ALLOC_SIZE 4096 /* We allocate
blocks in page sized chunks. */
/*
* Request more memory from the kernel.
*/
static header_t *
morecore(size_t num_units)
{
void *vp;
header_t *up;
if (num_units < MIN_ALLOC_SIZE)
num_units = MIN_ALLOC_SIZE /
sizeof(header_t);
if ((vp = sbrk(num_units *
sizeof(header_t))) == (void *) -1)
return NULL;
up = (header_t *) vp;
up->size = num_units;
add_to_free_list (up);
return freep;
}
Now that we have our two helper functions, writing our malloc function is pretty straightforward. We
simply scan the free list and use the first block that is at
least as big as the chunk were trying to find. Because
we use the first block we find instead of trying to find a
better block, this algorithm is known as first fit.
25
26 PROGRAMMING
if (p == NULL)
/* Request for more memory failed. */
return NULL;
}
}
}
sp++) {
v = *sp;
1 <= v &&
1 + bp->size > v) {
bp->next = ((unsigned int)
bp->next) | 1;
break;
}
} while ((bp = UNTAG(bp->next)) !=
usedp);
}
}
27
if (up != bp &&
up + 1 <= v &&
up + 1 + up->size > v) {
up->next = ((unsigned int)
up->next) | 1;
break;
}
} while ((up = UNTAG(up->next)) !=
bp);
}
}
}
Fortunately for the BSS and initialized data segments, most modern Unix linkers export the etext and
end symbols. The address of the etext symbol is the
start of the initialized data segment (the last address
past the text segment, which contains the programs
machine code), and the address of the end symbol is
the start of the heap. Thus, the BSS and initialized data
segment are located in between &etext and &end. This
is simple enough, but not platform independent.
The stack is a little harder. The top of the stack is
super simple to find using a little bit of inline assembly, as it is stored in the %esp register. However, well
be using the %ebp register as it ignores a few local
variables.
Finding the very bottom of the stack (where the
stack began) involves some trickery. Kernels tend to
randomize the starting point of the stack for security
reasons, so we cant hard code an address. To be honest,
Im not an expert on finding the bottom of the stack,
but I have a few rather poor ideas on how you can
make an accurate attempt. One possible way is you
could scan the call stack for the env pointer, which
would be passed as an argument to main. Another way
would be to start at the top of the stack and read every
subsequent address greater and handling the inexorable SIGSEGV. But were not going to do it either
way. Instead, were going to exploit the fact that linux
puts the bottom of the stack in a string in a file in the
processs entry in the proc directory (phew!). This
sounds silly and terribly indirect. Fortunately, I dont
feel ridiculous for doing it because its literally the
exact same thing Boehm GC does to find the bottom of the
stack!
Now we can make ourselves a little init function.
In it, we open the proc file on ourselves and find the
bottom of the stack. This is the 28th value printed so
28 PROGRAMMING
Conclusion
From elementary school through half of high school,
I played drums. Every Wednesday at around 4:30pm I
had a drum lesson from a teacher who was quite good.
Whenever I was having trouble learning a new
groove or beat or whatever, he would always give me
the same diagnosis: I was trying to do everything at
once. I looked at the sheet of music, and I simply tried
to play with all my hands. But I couldnt. And the
reason why is because I didnt know how to play the
groove yet, and simply trying to play the groove wasnt
how I was going to learn.
So my teacher would enlighten me as to how I could
learn: dont try playing everything at once. Learn to
play the high-hat part with your right hand. Once
youve got that down, learn to play the snare with
your left. Do the same with the bass, the tom-toms,
and whatever other parts there are. When you have all
the individual parts down, slowly begin to add them
together. Add them together in pairs, then in threes,
and eventually youll be able to play the entire thing.
I never got good at drums, but I did take these lessons to heart in my programming. Its really hard to
just start to type out an entire program. The only algorithm you need to write code is divide and conquer.
Write the function to allocate memory. Then, write
the function to look through memory. Then, write the
function that cleans up memory. Finally, add them all
together.
As soon as you get past this barrier as a programmer,
nothing practical becomes hard. You may not understand an algorithm, but anyone can understand an algorithm with enough time, paper, and the right book. If a
project seems daunting, break it up into its individual
parts. You may not know how to write an interpreter,
but you sure as hell can write a parser. Find out what
else you need to add, and do it. n
Matthew Plant is a sophomore undergraduate computer science
student at the University of Illinois at Urbana-Champaign. He was
born in San Francisco in 1995.
Reprinted with permission of the original author.
First appeared in hn.my/gcinc (web.engr.illinois.edu)
29
that executables were totally impenetrable. Id compile a C program, and then that was
it! I had a Magical Binary Executable that I could
no longer read.
It is not so! Executable file formats are regular file
formats that you can understand. Ill explain some
simple tools to start! Well be working on Linux, with
ELF binaries. (Binaries are kind of the definition of
platform-specific, so this is all platform-specific.) Well
be using C, but you could just as easily look at output
from any compiled language.
Lets write a simple C program, hello.c:
used to think
#include <stdio.h>
int main() {
printf("Penguin!\n");
}
30 PROGRAMMING
Type
Bind
FUNC
GLOBAL
FUNC
GLOBAL
FUNC
GLOBAL
Symbols
When you write a program, you might write a function called hello. When you compile the program, the
binary for that function is labelled with a symbol called
hello. If I call a function (like printf) from a library,
we need a way to look up the code for that function!
The process of looking up functions from libraries is
called linking. It can happen either just after we compile the program (static linking) or when we run the
program (dynamic linking).
So symbols are what allow linking to work! Lets find
the symbol for printf! Itll be in libc, where all the C
standard library functions are.
If I run nm on my copy of libc, it tells me no
symbols. But the internet tells me I can use objdump -tT instead! This works! objdump -tT /lib/
x86_64-linux-gnu/libc-2.15.so gives me this output.
[hn.my/objdump]
If you look at it, youll see sprintf, strlen, fork,
exec, and everything you might expect libc to have.
From here we can start to imagine how dynamic linking works we see that hello calls puts, and then we
can look up the location of puts in libcs symbol table.
f0505449
0048c7c7
4883ec08
6e75782d
00
You can see that it shows us all the bytes in the file
as hex on the left, and a translation into ASCII on the
right.
There are a whole bunch of sections here. This
shows you all the bytes in your binary! Some sections
we care about:
31
32 PROGRAMMING
xor
mov
pop
mov
and
Step 5: Segments!
Not magic!
Program Headers:
[... removed ...]
INTERP
0x0000000000000238
0x0000000000400238 0x0000000000400238
0x000000000000001c
0x000000000000001c R
1
[Requesting program interpreter: /lib64/
ld-linux-x86-64.so.2]
LOAD
0x0000000000000000
0x0000000000400000 0x0000000000400000
0x00000000000006d4
0x00000000000006d4 R E
200000
LOAD
0x0000000000000e28
0x0000000000600e28 0x0000000000600e28
0x00000000000001f8
0x0000000000000208 RW
200000
[... removed ...]
Julia Evans likes programming, playing with data, and finding out
why things that seem scary actually arent. She lives in Montreal
and works on Stripes machine learning team.
Reprinted with permission of the original author.
First appeared in hn.my/exe (jvns.ca)
33
SPECIAL
re you thinking of
becoming a scientist?
Do you want to uncover
the mysteries of nature, perform
experiments, or carry out calculations to learn how the world works?
Forget it!
Science is fun and exciting. The
thrill of discovery is unique. If you
are smart, ambitious, and hardworking you should major in science as
an undergraduate. But that is as far
as you should take it. After graduation, you will have to deal with
the real world. That means that
you should not even consider going
to graduate school in science. Do
something else instead: medical
school, law school, computer science, engineering, or something else
which appeals to you.
Why am I (a tenured professor
of physics) trying to discourage you
from following a career path which
was successful for me? Because
times have changed (I received my
Ph.D. in 1973, and tenure in 1976).
American science no longer offers
a reasonable career path. If you
go to graduate school in science, it
is in the expectation of spending
your working life doing scientific
research, using your ingenuity
and curiosity to solve important
34 SPECIAL
years later, and a step off the treadmill of looking for a new job every
two years). The latest example is a
39 year old candidate for another
Assistant Professorship; he has
published 35 papers. In contrast, a
doctor typically enters private practice at 29, a lawyer at 25 and makes
partner at 31, and a computer
scientist with a Ph.D. has a very
good job at 27 (computer science
and engineering are the few fields
in which industrial demand makes
it sensible to get a Ph.D.). Anyone
with the intelligence, ambition, and
willingness to work hard to succeed
in science can also succeed in any of
these other professions.
Typical postdoctoral salaries
begin at $27,000 annually in the
biological sciences and about
$35,000 in the physical sciences
(graduate student stipends are less
than half these figures). Can you
support a family on that income?
It suffices for a young couple in a
small apartment, though I know of
one physicist whose wife left him
because she was tired of repeatedly
moving with little prospect of settling down. When you are in your
thirties you will need more: a house
in a good school district and all the
other necessities of ordinary middle
35
36 SPECIAL
A Bit Of Narcissism
To give a personal example, the
website you are now viewing is the
primary hobby that I have maintained throughout the past decade.
I now consider myself fairly good at
creating personal websites and writing online articles.
I wasnt always proud of my
website design and writing. Ive
only begun receiving some praise
for my website in the past few
years, but Ive been making websites for over a decade, starting
back in 1997. My first few attempts
looked pretty horrendous (e.g., MS
Paint and stock clip art, 3-D naked
men). Some people have told me
that they think I have some sort
of talent for writing and website
design. I can guarantee that nobody
told me that when I first started at
age 13! I was a horrible writer back
in middle school: I got C and D
grades on some of my essays. And
I had absolutely no sense of visual
aesthetics.
Take-Home Message
Philip Guo is an assistant professor of computer science at the University of Rochester. His main research interests are in
human-computer interaction (HCI), with a
focus on user interfaces for online learning.
He created a free Web-based tool for learning programming called Online Python
Tutor [pythontutor.com], which has been
used by over 500,000 people in over 165
countries. He has previously researched
online education at edX and Google.
37
I decided to
start a vegetable garden. I have
fond memories of gardening with
my folks when I was a young boy, and I
figured a garden would be a good outlet from
my day to day life in tech.
Looking up and down the aisles at Lowes
and not finding a raised garden bed that met
my needs, I inquired with a staff member:
Sorry, we dont carry anything like that.
Darn. Ok, Ill try another store then, I
sighed in resignation.
You know, he said to me, its just wood.
It took me a moment to realize how
liberating this statement was. To him, woodworking held no mystery at all it was just
a thing you did. If he wanted a garden bed,
thered be no question in his mind that hed
make it himself. Why spend more on something suboptimal when you can build exactly
what you want?
So I did exactly that, and we now have a
wonderful, custom-built gardening bed growing some very tasty kale.
38 SPECIAL
Dashboards
StatsD
Happiness
*Hosted Graphites mantis shrimp / eagle breeding program has been unsuccessful thus far
39