Forms
It's important to note that in idk-lang, every syntactically valid construct is known as a form. There are two types of forms, there are statements and there are expressions. Statements do not return a value. Expressions return a value.
Assignment & Blocks
Assignment comes in two flavors: a single-line assignment statement and a multiline assignment statement. Single-line assignment statements are (unsurprisingly) assignment occuring entirely on a single line. Multiline assignment statements must be started by a newline, and indented some amount of spaces to form a block. The last line of the block must be an expression and that value is what will be used for the assignment. Here are two valid assignment statements
          Assignment is a statement, and thus cannot be used as a value. For
          example, 1 + (x: 1) would be a syntax error because
          x: 1 does not return a value.
        
          Also, in an attempt to have unified syntax, wherever a colon :
          is syntactically valid, it can be followed by a single-line form or a
          multiline list of forms. A multiline list of forms is known as a block
          and must be indented with some amount of tabs or spaces (but not both!).
        
Expression Forms
          The following forms (if, when, and
          match) are all expressions. Therefore, they can be used on
          the right-hand side of a single-line assignment and as the expression in
          the last line of the block of an assignment.
        
If Expression
          The general syntax for if expressions look like
          this, (very similar to Python's syntax)
        
          Remember, since if is an expression, it returns a value. The
          last value in the if or else block is what is
          returned. For example,
        
          This expression (rather verbosely) evaluates to the absolute value of
          x.
        
When Expression
          when expressions are a generalized version of if
          expressions. They can take a list of boolean expressions and code to
          execute. It's easier to explain with an example,
        
This mostly reads like english: When x and y are equal: return "equal". When the absolute value of their difference is less than one: return "close". Otherwise: return "far".
Notice, the first true boolean that is ecountered is the one whose branch will be executed. For example,
          will return "which".
        
Parameterized When Expression
          when expressions are more than just multiple if expressions,
          they can also pass paremeters to functions for a more expressive piece
          of code.  For example,
        
          Here, x and y are passed to the functions in each
          branch, until one evaluates to True. If a when
          expression is missing an else branch, the compiler will
          complain if it can't figure out that the when expression is
          exhaustive. That is, if the compiler can't tell that at least one of the
          branches of the when expression will return True,
          it will raise a compilation error.
        
          Parameterized when expressions can take any number of
          parameters. Here's one with one parameter using operator sections that
          evaluates to the sign of x
        
Match Expressions
          The last expression form is a match expression.  It's similar
          to the pattern matching facilities in other languages, but maybe slightly
          more advanced. A match expression is made up of a value
          and several patterns to test the value against.  Here's an example match
          statement that computes the boolean expression x or y,
        
          Here, the match expression tests the tuple x, y
          against possible patterns. The underscore _, or any other
          variable name for that matter, matches against any object. Thus, the pattern
          (_, True) matches against all 2-tuples that have their second
          element as True.
        
          match expressions also have disjunctive patterns
          meaning that multiple patterns can be matched in one branch. For example,
          this expression returns True is one of the elements is
          0,
        
          match expressions also have if and
          when guards. These are useful for finer grained logic against
          matched values. For example, let's say we have a tuple person
          with type (String, Int) representing the name and age of an
          individual. Then we can have the following match expression.
        
          As you can hopefully see, if guards are pretty useful. However,
          as you can also hopefully see, multiple if guards begin to get pretty
          verbose, even if they are doing conditionals on the same portion of the
          pattern. There has to be a better way! In the same way that you can use
          when expressions as multiple if expressions,
          you can use when guards as multiple if
          guards! Here's a cleaner version of the code above,
        
          Note: the when guards need not be exhaustive. If
          a when guard fails to find a branch that evaluates to
          True, the entire pattern matching branch fails and moves
          onto the next branch. Because of this, the else clause in the
          example above could be on either the when guard block or as
          the final clause in the match expression.
        
          The last feature of match expressions is being
          able to have multiple instances of the same variable in one pattern.
          Here's an example of a match expression that
          evaluates to True if the 2-tuple
          tup contains two elements that are equal to
          eachother,
        
This is exactly euivalent to
          Thus the additional constraints on tup having two elements that
          are of the same type and that inherit from Equatable will apply.
        
The next section will be on loops and lambdas.