diff --git a/distributors.scad b/distributors.scad
index fde784d..588acb8 100644
--- a/distributors.scad
+++ b/distributors.scad
@@ -40,24 +40,30 @@ module move_copies(a=[[0,0,0]])
 }
 
 
-// Module: line_of()
+// Function&Module: line_of()
 //
 // Usage: Spread `n` copies by a given spacing
-//   line_of(spacing, [n], [p1]) ...
+//   line_of(spacing, <n>, <p1=>) ...
 // Usage: Spread copies every given spacing along the line
-//   line_of(spacing, l, [p1]) ...
+//   line_of(spacing, <l=>, <p1=>) ...
 // Usage: Spread `n` copies along the length of the line
-//   line_of(l, [n], [p1]) ...
+//   line_of(<n=>, <l=>, <p1=>) ...
 // Usage: Spread `n` copies along the line from `p1` to `p2`
-//   line_of(p1, p2, [n]) ...
+//   line_of(<n=>, <p1=>, <p2=>) ...
 // Usage: Spread copies every given spacing, centered along the line from `p1` to `p2`
-//   line_of(p1, p2, spacing) ...
-//
+//   line_of(<spacing>, <p1=>, <p2=>) ...
+// Usage: As a function
+//   pts = line_of(<spacing>, <n>, <p1=>);
+//   pts = line_of(<spacing>, <l=>, <p1=>);
+//   pts = line_of(<n=>, <l=>, <p1=>);
+//   pts = line_of(<n=>, <p1=>, <p2=>);
+//   pts = line_of(<spacing>, <p1=>, <p2=>);
 // Description:
-//   Copies `children()` at one or more evenly spread positions along a line. By default, the line
-//   will be centered at the origin, unless the starting point `p1` is given.  The line will be
-//   pointed towards `RIGHT` (X+) unless otherwise given as a vector in `l`, `spacing`, or `p1`/`p2`.
-//   The spread is specified in one of several ways:
+//   When called as a function, returns a list of points at evenly spread positions along a line.
+//   When called as a module, copies `children()` at one or more evenly spread positions along a line.
+//   By default, the line will be centered at the origin, unless the starting point `p1` is given.
+//   The line will be pointed towards `RIGHT` (X+) unless otherwise given as a vector in `l`,
+//   `spacing`, or `p1`/`p2`.  The spread is specified in one of several ways:
 //   .
 //   If You Know...                   | Then Use Something Like...
 //   -------------------------------- | --------------------------------
@@ -74,6 +80,7 @@ module move_copies(a=[[0,0,0]])
 // Arguments:
 //   spacing = Either the scalar spacing distance along the X+ direction, or the vector giving both the direction and spacing distance between each set of copies.
 //   n = Number of copies to distribute along the line. (Default: 2)
+//   ---
 //   l = Either the scalar length of the line, or a vector giving both the direction and length of the line.
 //   p1 = If given, specifies the starting point of the line.
 //   p2 = If given with `p1`, specifies the ending point of line, and indirectly calculates the line length.
@@ -102,40 +109,42 @@ module move_copies(a=[[0,0,0]])
 //       cube(size=[1,3,1],center=true);
 //       cube(size=[3,1,1],center=true);
 //   }
+// Example(2D):
+//   pts = line_of([10,5],n=5);
+//   move_copies(pts) circle(d=2);
 module line_of(spacing, n, l, p1, p2)
 {
-    assert(is_undef(spacing) || is_finite(spacing) || is_vector(spacing));
-    assert(is_undef(n) || is_finite(n));
-    assert(is_undef(l) || is_finite(l) || is_vector(l));
-    assert(is_undef(p1) || is_vector(p1));
-    assert(is_undef(p2) || is_vector(p2));
-    ll = (
-        !is_undef(l)? scalar_vec3(l, 0) :
-        (!is_undef(spacing) && !is_undef(n))? (n * scalar_vec3(spacing, 0)) :
-        (!is_undef(p1) && !is_undef(p2))? point3d(p2-p1) :
-        undef
-    );
-    cnt = (
-        !is_undef(n)? n :
-        (!is_undef(spacing) && !is_undef(ll))? floor(norm(ll) / norm(scalar_vec3(spacing, 0)) + 1.000001) :
-        2
-    );
-    spc = (
-        cnt<=1? [0,0,0] :
-        is_undef(spacing)? (ll/(cnt-1)) :
-        is_num(spacing) && !is_undef(ll)? (ll/(cnt-1)) :
-        scalar_vec3(spacing, 0)
-    );
-    assert(!is_undef(cnt), "Need two of `spacing`, 'l', 'n', or `p1`/`p2` arguments in `line_of()`.");
-    spos = !is_undef(p1)? point3d(p1) : -(cnt-1)/2 * spc;
-    for (i=[0:1:cnt-1]) {
-        pos = i * spc + spos;
-        $pos = pos;
+    pts = line_of(spacing=spacing, n=n, l=l, p1=p1, p2=p2);
+    for (i=idx(pts)) {
         $idx = i;
-        translate(pos) children();
+        $pos = pts[i];
+        translate($pos) children();
     }
 }
 
+function line_of(spacing, n, l, p1, p2) =
+    assert(is_undef(spacing) || is_finite(spacing) || is_vector(spacing))
+    assert(is_undef(n) || is_finite(n))
+    assert(is_undef(l) || is_finite(l) || is_vector(l))
+    assert(is_undef(p1) || is_vector(p1))
+    assert(is_undef(p2) || is_vector(p2))
+    let(
+        ll = !is_undef(l)? scalar_vec3(l, 0) :
+            (!is_undef(spacing) && !is_undef(n))? (n * scalar_vec3(spacing, 0)) :
+            (!is_undef(p1) && !is_undef(p2))? point3d(p2-p1) :
+            undef,
+        cnt = !is_undef(n)? n :
+            (!is_undef(spacing) && !is_undef(ll))? floor(norm(ll) / norm(scalar_vec3(spacing, 0)) + 1.000001) :
+            2,
+        spc = cnt<=1? [0,0,0] :
+            is_undef(spacing)? (ll/(cnt-1)) :
+            is_num(spacing) && !is_undef(ll)? (ll/(cnt-1)) :
+            scalar_vec3(spacing, 0)
+    )
+    assert(!is_undef(cnt), "Need two of `spacing`, 'l', 'n', or `p1`/`p2` arguments in `line_of()`.")
+    let( spos = !is_undef(p1)? point3d(p1) : -(cnt-1)/2 * spc )
+    [for (i=[0:1:cnt-1]) i * spc + spos];
+
 
 // Module: xcopies()
 //