Chapter 4, skips over a bit, explaining how surface coordinates (u,v) are computed for a sphere.
In particular, Listing 20 updates hit_record to add surface coordinates double u and double v:
struct hit_record {
  vec3 p;
  vec3 normal;
  shared_ptr<material> mat_ptr;
  double t;
  double u;
  double v;
  bool front_face;
  ...
Two dimensional coordinates (u,v) correspond to the location at which a ray hit the (2D) surface of an object (sphere).
Listing 21 then updates scatter to pass in the rec.u and rec.v values from hit_record rec:
        attenuation = albedo->value(rec.u, rec.v, rec.p);
However, Chapter 4 does not explain how coordinates (u,v) are calculated and set in the hit_record, presumably when sphere::hit() is called with an incoming ray.
Skipping ahead to Chapter 6, get_sphere_uv() in Listing 42 seems to solve this problem, which is what I eventually added to my hit() for my updates for Chapter 4 to compile. It produces a plausible result:
