trash: planning, iteration 2
      ----------------------------

      I put all my plans for trash on this
      tilde site, so when tilde.club was down
      recently I temporarily lost all my plans.
      impatiently, I just wrote down some new
      ideas in my notebook and I like them
      better than what I had previously.
      so here's the 2nd iteration of plans for
      trash:

      - lots of braces
      - no commas
      - comments use // and /* ... */
      - ridiculous symbol/variant stuff
      - no more sigils
      - there are no types
      .. can a language actually have no types?
      .. well, you know what I mean by this
      - design philosophy: be as fun and
      .. ridiculous as possible, so that readers
      .. of hackernews will never want to use
      .. or discuss or criticize the language

      trash uses the following names for keyboard
      symbols, because it makes discussing the
      language a whole lot cuter:
      - # = crunch
      - ' = spark
      - \ = hack
      - @ = strudel
      - & = pretzel
      - ` = tick
      - < = tic
      - > = tac
      - % = cherries
      - ~ = worm
      - * = splat, sparkle
      - " = snakebite
      - ? = pop
      - | = spike
      - [ = square
      - ] = unsquare
      - ^ = hat
      
      variable declarations:
      | foo = 2;
      nothing much to this, except it's crucial
      to note that spacing around the equals
      sign just doesn't matter. variable names
      are symbols.

      symbols:
      | foo = bar;
      normally, symbols evaluate to themselves
      | foo = 2;
      | baz = #foo; // baz = 2
      use a crunch to dereference a symbol's
      value. if the symbol doesn't refer to anything,
      it will evaluate to ~nil:
      | #x // => ~nil, if x is undeclared
      symbols can contain underscores, letters,
      dashes, and digits, but cannot begin with a digit.

      deferred evaluation:
      | foo = 2;
      | bar = 'foo;
      | #bar      // => foo
      | ##bar     // => 2
      | #'''x     // => ''x
      | ##'''x    // => 'x
      | ###'''x   // => x
      adding a spark  makes a symbol evaluate
      to itself, but with one less spark (it's still
      equal to itself with any number of sparks).
      this is like an atom (see next) but you can
      eventually get a value out of it.

      atoms:
      | foo = ~nil;
      | #foo  // => ~nil
      | ##foo // => ~nil
      | #~nil // => ~nil
      beginning a symbol with a worm makes
      it _atomic_, so it always evaluates to itself
      (bools also work like this, with ~t and ~f)

      more crunch stuff
      | name = 2;
      | "name: #name" // => "name: 2"
      | "sum: #(add 1 2)" // => "sum: 3"
      | "name: \#name" // => name: #name
      putting crunch inside a string evaluates
      and (possibly dereferences, if it's a symbol)
      the expression that follows it. it can be escaped
      using a hack.

      more spark stuff
      | foo = '(echo 2); // => no output
      | #foo; // => outputs 2
      the spark from earlier can also defer evaluation
      of entire expressions, so you can save function
      calls for later evaluation via the crunch.

      cherries
      | foo = %(echo 2); // => a pid
      | bar = %firefox; // => a pid
      | baz = echo 2;
      | quux = %#baz;
      cherries are used to get the PID of a process.
      this operator can accept an expression, an
      actual process name, or a dereferenced variable
      name that refers to a process (the latter
      operation requires a %# combination, which is
      called _cherry pie_).

      pretzel
      | &echo 2;
      | &for {1 2 3} |n| { echo #n };
      the pretzel just runs the subsequent process
      in the background, so control flow won't block on it.
      notice how you can do this with loops too.

      square
      | xs = {1 2 3};
      | xs[0]   // => 1
      | xs[-1]  // => 3
      | xs[0 2] // => {1 2 3}
      the square operator is for indexing and slicing
      lists (0-indexed and inclusively sliced). you
      can also use negative indices. note how the square
      implicitly dereferences symbols. it also works on
      hashes, but without the range/negative indexing.

      strudel
      | xs = {1 2 3};
      | @xs // => 3
      | {1 2 @} // => 3
      | xs[sub @ 1] // => 3
      the strudel finds the length of a list (or hash).
      it also implicitly dereferences symbols. 
      the very cool part of the strudel is that in a
      list expression and in an indexing expression,
      the list's length is saved so that any occurence
      of @ inside will evaluate to the length.

      splat
      | names = {foo bar baz};
      | echo *names; // echoes foo, bar, baz separately
      | // the above macroexpands to this:
      | // echo foo;
      | // echo bar;
      | // echo baz;
      the splat operator is very treacherous and needs
      to be used wisely. it operates on lists and hashes,
      and copies the outer expression onto each element
      of the list/hash, basically working like some sort
      of macro.

      tictac
      | x = ~foo;
      | #x <1>   // => ~foo<1>
      | #x <1 2> // => ~foo<{1 2}>
      | #x <1 2> haha <"yeah">
      | // ... => ~foo<{1 2}>haha<"yeah">
      | <1> // => 1
      the tictac operator can stick values next to atoms,
      symbols, and other tictacs. if you space out values
      inside a tictac, it's desugared into a list. tictac
      structures ("dragons") are kind of like variants in
      statically typed languages, eg haskell. anything
      enclosed by tictacs on its own will evaluate to the
      inner value.

      hat and tick
      | foo = ~just<2>~and<3 4>;
      | ^foo    // => ~just
      | `foo    // => <2>~and<3 4>
      | ^`foo   // => 2
      | ```foo  // => [3 4]
      | ````foo // => ~nil
      the hat and tick operators implicitly dereference
      symbols. these are used for destructuring dragons;
      the hat gets the first element of a dragon (the head)
      and the tick gets all _but_ the first (the tail).

      other operations
      there are some other operations for arithmetic,
      string manipulation, etc but those all look like
      ordinary functions.

      conditionals:
      | if ~t {
      |   echo "makes sense";
      | } elsif ~f {
      |   echo "what???";
      | } else {
      |   echo "emergency!!!";
      | }
      |
      | if `dragon |tail| {
      |   echo "dragon's tail: #tail";
      | }
      conditionals work as expected. truthy values are
      ~t and any other value that isn't falsy; falsy values
      are ~f and ~nil. notice how you can bind the result
      of conditionals using spikes.

      loops:
      | my-hash = { a: "bon" b: "appetit" };
      | my-list = { "bon" "appetit" };
      | for my-hash |k, v| { echo "#k: #v"; }
      | for my-list |i, v| { echo "list[#i] = #v"; }
      | for my-list |v| { echo "#v"; }
      |
      | x = 0;
      | for {
      |   if (eq x 3) { brk; };
      |   if (eq x 4) { nxt; };
      |   x = add x 1;
      | }
      the for loop has four forms: it can iterate over
      the key-value pairs of a hash, the index-value pairs
      of a hash, and just the values of a list, providing
      variables between the spikes. the final form is just
      a blank `for`, which loops forever. the `brk` statement
      breaks out of the enclosing loop, and `nxt` iterates again.
      is it asinine to name this loop `for` when none of
      these forms read like normal `for` loops? yes -- and
      that's the point.
      
      functions:
      | greet name-1 name-2 {
      |   echo "hello, #name-1 and #name-2!";
      | }
      |
      | greet "apple" "orange";
      normal function definitions list the name, parameters,
      and then provide a body within braces. they're invoked
      like all the other command-line commands, and the first
      element of these commands (ie the function name) is
      automatically dereferenced.
      | greet ?name {
      |   if #name {
      |     echo "hello, #name!";
      |   } else {
      |     echo "who are you?";
      |   }
      | }
      putting a pop before a parameter makes it optional,
      and it's set to ~nil if none is provided. remember that
      optional parameters can only occur at the end of the
      parameter list, because that wouldn't make sense otherwise.
      | greet name *names {
      |   echo "hello, #name!";
      |   echo "also these people: #names";
      | }
      |
      | greet "ralph";
      | greet "coral" "christina" "ralph"
      adding a sparkle (not a splat!) before the final
      parameter means that the function can take
      any number of arguments at the end, and they all get
      collected in a list with that parameter's name.
      |
      |
      just kidding! I bet you were expecting keyword
      arguments, right? well, I really hate keyword
      arguments, because they're ugly! so this language
      doesn't have them.
      | {|name| "hello #name!"} "liselot";
      lambdas are just like functions, but they don't have
      a name and the parameter list goes inside the body
      in between some spikes.