oftenpaper.net

a website that i put stuff (on top of it) ™

One of the nice things about Lisp is that you can color the parentheses pink, which looks pretty:

  1. ; simple iterator
    
    (= f (co
        (let x 0
          (while t
              (yield (++ x))))))
    
    
    (f) ;returns 1
    (f) ;returns 2
    (f) ;returns 3
            
  2. ;passing yield into a tree-traversal function
    
    (= f (co
        (co:treewise
         (fn (a b)) ;empty function given as the join function    
         yield   ;yield given as the leaf function
         '(a . ((b . c) . d)))))
    
    (f) ;returns 'a
    (f) ;returns 'b
    (f) ;returns 'c
    (f) ;returns 'd
    (f) ;returns nil
    
  3. ;passing values into the coroutine
    
    (= x 1)
    (= f (co
        (while t
            (if (= in (yield x)) ;if the call supplied an argument
                (do (= x in) ;reassign x and print message
                    (prn (string "you gave me: " x)))))))
    
    (f) ;returns 1
    (f) ;returns 1
    (f 0) ;prints "you gave me: 0" and returns 0
    (f) ;returns 0
    (f) ;returns 0
    (f 'hello) ;prints "you gave me: hello" and returns 'hello
    (f) ;returns 'hello
    
  4. (mac co body
      (w/uniq (con1 con2 argl)
    
        `(withs (,con1 nil ,con2 nil
                 yield (fn ((o val nil))
                          (ccc [do (= ,con2 _) (,con1 val)])))
    
          (def ,con2 ,argl
              ;(while t ;make generation cyclic
              ,@body
              ;)
              (def ,con2 args nil)
              (,con1 nil))
    
          (fn args
            (ccc [do (= ,con1 _) (apply ,con2 (or args (list nil)))]))
    )))
    

Speaking of pink, just the other day I saw this awesome Hello Kitty folder at Target, and even though she didn't ask, I let the cashier know that I was buying it for myself. That's how secure I am in my manliness.

On a serious note, the design of Arc is very pretty on many levels. My own language that I'm currently designing has a similar kind of aesthetic, although it's a completely different language.

When I was young my parents bought me a Spirograph set at the flea market. I wasted lots and lots of paper with it. A modern tree-friendly rendition:

  1. 
    
    
    
    
    Manipulate[
     Module[{
       (* non-integer values of \[Zeta] give progressively more entwined paths, 
       but require smaller cycle widths to keep the plot from looking scrambled *)
       \[Psi] = Round[Abs[FractionalPart[\[Zeta]]]*1., .25] /. {
          0. -> y,
          .5 -> y/2,
          .25 | .75 -> y/4}},
    
      ParametricPlot[
    
       (1. + spirality*(Log[\[Theta] + 1.] - 1.))*
        {\[Psi] Cos[\[Theta]] + x  Cos[64. \[Theta]] + (1 - effect*RandomReal[])*\[Zeta]* (Cos[512. \[Theta]] + Cos[64. \[Zeta] \[Theta]]),
         \[Psi] Sin[\[Theta]] - x Sin[64. \[Theta]] + (1 - effect*RandomReal[])* inflection*\[Zeta]* (Sin[512. \[Theta]] + Sin[64. \[Zeta] \[Theta]])}
    
       , {\[Theta], 0, 2 \[Pi]},
    
       ImageSize -> {470, 410},
       PerformanceGoal -> "Quality",
    
       (* reduced opacity helps bring the shape out and gives an elegant tone *)
       PlotStyle -> {{color, Opacity[.43], AbsoluteThickness[thickness]}},
       PlotRange -> Full,
        PlotPoints -> 270,(* increase for higher-resolution images *)
       Axes -> None]],
    
     OpenerView[{"Style", Column[{
         Control@{{color, Black, "line color"}, ColorSlider},
         Column@{
           (* these controls are smallerized for consistency *)
           Control@{{thickness, 0., "line thickness"}, 0, 20, Appearance -> "Labeled", ImageSize -> Small},
           Control@{{effect, 0., "charcoal effect"}, 0, .25, Appearance -> "Labeled", ImageSize -> Small}}}]}],
    
     Row[{
       Control@{{inflection, 1}, {1 -> " concave ", -1 -> " convex "}, Appearance -> "Vertical"},
    
       Spacer[30],
    
       Column@{
         Control@{{\[Zeta], 2., "angularity"}, -7.5, 7.5, .5, Appearance -> "Labeled", ImageSize -> Small},
         Control@{{x, 8., "tension"}, 0, 12, Appearance -> "Labeled", ImageSize -> Small}},
    
       Column@{
         Control@{{y, 2., "cycle width"}, 0, 2, ImageSize -> Tiny},
         Control[{{spirality, 0.}, 0, 1, ImageSize -> Tiny}]}
    
       }],
    
     Alignment -> Center,
     SynchronousUpdating -> False,
     AppearanceElements -> "ManipulateMenu",
    
     Bookmarks -> {
    
       (* this bookmark assigns random values to the factors.
       I intentionally didn't make this feature rapid-fireable *)
       "Random" :> (
         color = RGBColor[RandomReal[], RandomReal[], RandomReal[]];
         inflection = RandomChoice[{1, -1}];
    
         (* effect, thickness, and spirality have distributions that make
         small values smaller and large values rarer [you mean "power law" -- future version of myself]*)
         effect = .25*RandomReal[]^8;
         thickness = 10*RandomReal[]^8;
         spirality = RandomReal[]^3;
    
         If[spirality < .035, spirality = 0];
    
         x = RandomReal[]*12;
         y = RandomReal[]*2;
    
         Module[{
           (* +/- .5 are generally not interesting when x > 3 *)
           weights = If[x > 3, {.1, .03, .87}, {.1, .07, .83}]},
          \[Zeta] = RandomChoice[{-1, 1}]*RandomChoice[weights ->
              {RandomReal[7.5], (* small chance to fall on non-integral \[Zeta] *)
               RandomChoice[{0, .5, .5}],(* multiple .5 isn't a typo *)
               Round[RandomReal[{1, 7.5}], .5]}]];
         ),
    
       "Rose" :> {thickness = 0, color = Red, effect = 0, inflection = -1, x = 0, y = 1.1343, spirality = 0, \[Zeta] = 3},
       "Glyph" :> {thickness = 0, color = Black, effect = 0.198, inflection = 1, x = 5.2, y = 0., spirality = 0, \[Zeta] = 2},
       "Mass Atomic" :> {thickness = 0, effect = 0, inflection = -1, x = 5.84, y = 0.412, spirality = 0, \[Zeta] = -4.2504},
       "Jello" :> {thickness = 0, color = Red, effect = 0, inflection = -1, x = 12., y = 0.846, spirality = 1., \[Zeta] = -1.},
       "Grim" :> {thickness = 3.35, color = Black, effect = 0.0675, inflection = 1, x = 8., y = 0.296, spirality = 1., \[Zeta] = -1.},
       "Angelwings" :> {color = RGBColor[0.07693598840314336, 0.39046311131456474, 1], effect = 0, inflection = 1, spirality = 1.`, thickness = 0, x = 12, y = 0, \[Zeta] = -5.4946511679431715`},
       "Rollers" :> {color = RGBColor[0.`, 0.`, 0.`], effect = 0.`, inflection = -1, spirality = 0.`, thickness = 0.`, x = 5.5`, y = 0.1`, \[Zeta] = -0.984032039033508`},
       "Lifespark" :> {color = RGBColor[0.1026, .9878, .0201], effect = 0, inflection = 1, spirality = .0995, x = 3.2757, y = .2002, \[Zeta] = -5.5}
       }
     ]
    
    
    
    
    
    

I'm particularly proud of this program because it can produce a wide variety of images from just a few parameters. Though that's not an accident. A lot of fine-tuning and experimentation was involved. For the "Super Mario 64" to this program's "Super Mario," see my Cycowtron 4800 Deluxe.

How do you programmatically construct a hexagon? Easy, we can just use equiangular points on the circle, taking advantage of the fact that for a complex number $z$ on the complex plane,

$$z e^{i \phi}$$

represents a rotation of $z$ about the origin by $\phi$ radians. From this rotation definition you can derive $e^{i \small{\frac{1}{2}} \tau} = -1$. If you rotate a point $\small {\frac 1 2}$ way around the circle, you've effectively multiplied its real and imaginary components by -1. Since $i$ itself is a quarter turn, two quarter turns $i^2$ is also -1. If you go one full swing (a.k.a. 4 quarter turns), you've done nothing:

$$i^4 = e^{i \tau} = 1$$

Although this is commonly understood, I encountered this coherent description for complex numbers in geometric algebra, wherein $i$ is just one instance of a "directional plane" in the same sense that a vector is a "directional line." (The proper description may be more subtle, but this is a good approximation). Most importantly, the "mysterioUs" complex numbers can be seen as a non-mysterious encoding of geometric truths. And so within a broader context no less.

Our code for a hexagon is:

  1. Graphics[Polygon[{Re[#], Im[#]} & /@ (E^(I 2 Pi Range[6]/6))]]

It's of course easily parameterized. What if we alternate the polarity of the points (using $(-1)^x$) as we generate the polygon? We get stars:

  1. 8 vertices

  2. 32 vertices

  3. 65 vertices

  4. 4000 vertices

  5. 12000 vertices

  6. 40000 vertices (downsampled)

  7. 40000 vertices (close up)

  8. draw[v_] := Module[{vertices},
       vertices = (-1)^Range[v] E^(I 2. Pi Range[v]/v);
       Graphics[Polygon[{Re[#], Im[#]} & /@ vertices]]];
    

Vector graphics renderers typically use the so-called even-odd rule for handling polygon self-intersections, which results in the checkered appearance. Notice that the images are fractal-like towards the center, as if the rings repeat endlessly.

Higher vertex counts have strong Moire patterns. These depend on a variety of factors and contain a lot of interesting patterns, like parabolic-looking arcs and thumbprint artifacts. It's like looking into the soul of the rendering engine. For a potential Twilight Zone experience, take a look at high-resolution 120k-vertex and 4k-vertex renderings at different zooms.

$(-1)^x$ generates $\{1, -1\}$ cyclically. What if we use $i^x$ instead? It generates $\{1, i, -1, -i\}$. What if we make the distance taper up or down as we generate the vertices? What if we use logarithms, or hyperbolic sines and cosines. What if we add color depending on the performance of the stock market?? What if we get totally smashed and plot points at different positions depending on how many chunks of pizza we can identify after we projectile vomit all over ourselves??? YEA!!!

  1. $(-1)^x x e^{\frac{i 2 \pi x}{n}}$ with 128 vertices

  2. $i^x i^{\frac{i 2 \pi x}{n}}$   with 128 vertices

  3. $i^x \log(x)^{e^{\frac{i 2 \pi x}{n}}}$   with 600 vertices

  4. $i^x x e^{\frac {i 2 \pi p_x} n}$   ($p_x$ the $x$th prime) with 500 vertices

  5. $\text{krabby patty formul'r}$

  6. draw[expr_, v_] := Module[{vertices},
       vertices = Table[expr /. n -> v, {x, v}];
       Graphics[Polygon[{Re[#], Im[#]} & /@ vertices]]];
    
    draw[(-1)^x x E^(I 2 Pi x/n), 128]

Sadly there is a small storm on our parade. Since we have to eventually convert the points to regular cartesian coordinates using {Re[#], Im[#]} &, it's more prudent for us to skip complex numbers and just use sines and cosines instead:

  1. Graphics[Polygon[{Cos[#], Sin[#]} & /@ (2 Pi Range[6]/6)]]
    

$\cos(\phi)$ and $\sin(\phi)$ themselves are the $x$ and $y$ coordinates of a point at angle $\phi$, which trigonometrists think of as the adjacent and opposite legs of the right triangle specified by that point. This is about as direct as it gets, so we have to accept the straightforwardness of cos-sine vs re-im-E^I.