packages feed

forml-0.1.1: src/forml/readme.forml

-- Forml
-- -----

-- <script type="text/javascript">
-- $("header ul").prepend('<li><a href="https://github.com/texodus/forml/zipball/master">Download <strong>ZIP File</strong></a></li><li><a href="https://github.com/texodus/forml/tarball/master">Download <strong>TAR Ball</strong></a></li><li><a href="https://github.com/texodus/forml">View On <strong>GitHub</strong></a></li>').css("width", "360");
-- $("header h1").after('<p></p><p class="view"><a href="https://github.com/texodus/forml">View the Project on GitHub <small>texodus/forml</small></a></p><br style="clear: both;"/>');
-- </script>

-- Forml is an modern programming language for the discriminating
-- programmer.  More importantly, forml is my vanity project, an
-- attempt to learn ML by writing one.  

-- Philosophy
-- ----------

--     1) Writing software is unnecessarily hard, because the language's
--        syntax treats the programmer like a machine.  A modern programming
--        language should be read and written for programmers - a philosophy
--        lifted unapologetically from [Ruby](http://www.artima.com/intv/ruby4.html).

--     2) Writing software is unnecessarily hard, because the language
--        lets the programmer make mistakes.  A modern programming language
--        should prevent the programmer from writing incorrect code, in so far
--        as it never conflicts with #1.

-- Features
-- --------

--   * Buzzwords:  functional, strict, expressive, pure(ish), static(y), inferred, fast, fun.
--     Strong like a gorilla, yet soft and yielding like a Nerf ball.

--   * Targets Javascript, but please regard this as an implementation detail -
--     forml is not intended as an answer to "the Javascript problem."  Simple
--     foreign function interface, which allows the
--     introduction of untyped values for quick & dirty
--     code integration, which can later be restricted via explicit typing.

--   * Type system which is designed to be simple and catch obvious errors,
--     not entirely exhaustive, dictatorial and somewhat combative (I'm looking
--     at you, Haskell).   Strucural types, partials records, arbitrary unions, 
--     ability to introduce unrestricted types via FFI.

--   * Sugary, flexible syntax.

--   * Inline testing, compiles to a separate suite.

--   * Fast.  Automatic tail call optimization,
--     inline functions, designed for use with [Google Closure Compiler](https://developers.google.com/closure/)
--     advanced optimizations mode.

--   * Heavily inspired by 
--          [Haskell](http://www.haskell.org/haskellwiki/Haskell)
--        , [F#](http://msdn.microsoft.com/en-us/vstudio/hh388569.aspx)
--        , [Coffeescript](http://coffeescript.org/).
--        , ([_](http://en.wikipedia.org/wiki/Category:ML_programming_language_family))([S](http://www.smlnj.org/))([OCA](http://caml.inria.fr/))ML
--        , [Clojure](http://clojure.org/)
--        , [JMacro](http://www.haskell.org/haskellwiki/Jmacro)
--        , [Ruby](http://www.ruby-lang.org/en/)

-- Installation
-- ------------

-- Mac OSX (tested on Snow Leopard & Lion).  Note that Forml also requires
-- [Closure](https://developers.google.com/closure/)for optimizations and
-- either [Phantom.js](http://phantomjs.org) or [Node.js](http://nodejs.org)

-- Install the
-- [Haskell Platform](http://hackage.haskell.org/platform/index.html), then

--        <pre><code>--$ cabal install forml</pre></code>

-- To compile some forml files:
   
--        <pre><code>--$ forml -o app test.forml test2.forml</pre></code>

-- will create an app.js and app.spec.js with the compiled code and
-- test suite respectively.

-- Forml will by default try to minify/optimize your code with Closure, via the
-- $CLOSURE environment variable, which should point to the closure jar.  Failing this,
-- forml will attempt to post your code to the Closure web service.

-- Additionally, forml will attempt to run the test suite with the phantomjs binary,
-- which it expects to find on your PATH.  You may optionally specifiy to run your suite
-- via node.js with

--        <pre><code>--$ forml -node-test test.forml</pre></code>

-- To compile literate
-- forml (eg, Forml code embedded in Markdown):
   
--        <pre><code>--$ forml test.lforml</pre></code>
   
-- To see the inferred types:
   
--        <pre><code>--$ forml -t test.forml</pre></code>
   
-- To turn off optimizing (eg, Closure) or testing:
   
--        <pre><code>--$ forml -no-test -no-opt test.forml</pre></code>

-- To watch a file for changes and incrementally compile:
   
--        <pre><code>--$ forml -w test.forml</pre></code>

-- To generate an HTML (like this one!) and test suite:
   
--        <pre><code>--$ forml -docs test.forml</pre></code>


-- Tutorial
-- --------
-- This is unfortunately not comprehensive, and presumes some working knowledge of 
-- ML or Haskell.  For more examples, see the annotated 
-- [prelude](http://texodus.github.com/forml/Prelude)
-- and [parsec](http://texodus.github.com/forml.Parsec.html).  

-- Forml supports a flexible, forgiving syntax that supports many synonymous forms.
-- This will be illustrated by adherring to an entirely random, arbitrary style throughout.

-- All forml programs must reside in a module.
-- Within a module, the compiler recognizes logical sections divided by 
-- `open` statements and sub modules.  Within a section, declarations
-- can be in any order.

module readme

    open prelude
    open prelude.string

    -- Simple function.  Forml allows functions to be written in ML style, or
    -- in more traditional java style.

    square x = x * x

    add(x, y) = x + y

    -- With pattern matching

    fib 0 = 0 | 1 = 1 | n = fib (n - 1) + fib (n - 2)

    -- Patterns can be separated with `|`, or by repeating the definition's
    -- name ala Haskell.  Definitions can have optional type annotations and
    -- assertions (which are compiled separately from your application code).

    private

    fib' : Num -> Num

    fib' 0 = 0
    fib' 1 = 1
    fib' n = fib' (n - 1) + fib' (n - 2)

    fib' 7 == 13
    fib' 0 == 0

    -- Forml has the basic primative types from Javascript:  Num, String, Bool;  plus
    -- a record, which is structurally typed and implemented as a simple Javascript object.
    
    person name address = { 
        name    = name
        address = address
        message = "`name` lives at `address`"
    }

    person("Andrew", "123 Fake St.").message is "Andrew lives at 123 Fake St."

    point = {x: 10, y: 10}
    
    20 == point.x + point.y
   
    -- Also supports partial records.

    magnitude {x: x, y: y, _} = sqrt (square x + square y)

    magnitude {x: 3, y: 4, other: "test"} == 5
    magnitude {x: 4, y: 3, test: "other"} == 5

    -- Operators can be defined much like in Haskell.  Precedence is currently fixed,
    -- though you can declare right associative operators by ending them with a `:`.
    -- For performance, you can declare functions to be `inline`.  This example
    -- will compile to a loop, as it is tail recursive.

    inline (**): 

         String -> Num -> String
         text   ** n    =

             var f(_, 0, acc) = acc       -- `let` and `var` are synonyms
                 f(text, n, acc) =
                     f(text, n - 1, acc +++ text)
             
             in f(text, n, "")            -- `in` is optional


    "hello" ** 3 == "hellohellohello"
    length ("a" ** 10000) == 10000

    -- Anonymous functions also follow Haskell, can be written with `\` or `λ`, and
    -- allows pattern seperation via `|`

    -- Note this function mutates its argument, so we name it with an exclamation.

    map!: (a -> b) -> Array a -> Array b
    map! f xs = do! `xs.map(f)`

    let fil = λ x when x > 5 = x
              | x            = 5

    map! fil [2, 6, 3, 7] is [5, 6, 5, 7]

    -- Interop / Side Effects
    -- ----------------------
    -- Forml technically allows unrestricted side effects, but by default
    -- wraps them in a `JS a` type, which can be composed with the
    -- `>>=` and `>>` operators, or a variation of Haskell's `do` notation.

    hello_world = do

        `console.log("Hello World")` -- Calls to Javascript always return type `JS a`
        x <- `Math.sqrt(9)`          -- `x` is inferred to be the unrestricted type `a`
        let z = x + 1                -- `x` is now restricted to type `Num`
        return (z + 1)               -- type of `hello_world` is inferred to be `JS Num`

    8 == do! hello_world >>= λx = `x + 3`

    -- Though this function is inferred to be `a -> b`, you can restrict it with
    -- a signature.  

    inline
    sqrt: Num -> Num                 
    sqrt x = do! `Math.sqrt(x)`      -- `do!` realizes its argument immediately

    -- Forml also supports additional keywords `lazy` and `yield`.  Both take
    -- expressions as arguments (as opposed to `do` syntax), but return an
    -- unrealized type `JS a`, the difference being that `lazy` will only
    -- evaluate it's arguments once, then cache the result.

    let x = 0
        test = lazy do! `x = x + 1; x`

    in  1 == do! test >> test >> test >> test

    -- Types, Aliases & Unions
    -- -----------------------

    -- Forml lacks algebraic data types in the ML sense, instead opting for
    -- only structural typing of records.  However, you can add explicit type
    -- signatures to tell the Forml compiler it is OK to overload the types
    -- of specific symbols.

    num_or_string:

          (Num | String) -> String
        | x when num? x   = "Num"
        | _               = "String"

    -- You can also gives union types such as these an alias, effectively allowing
    -- algebraic data types to be declared in a local scope, for all
    -- records which are structurally equivalent to those declared.  For instance,
    -- we could declare a `Maybe a` ADT in forml via
  
    Maybe a = {just: a} | {nothing}

    -- ... where `{nothing}` is shorthand for the strucural type `{nothing: {}}`.
    -- Any scope which imports the alias `Maybe a` will now allow values which
    -- can be typed both a `{just: a}` or `{nothing}` record

    maybe x {just: y} = y
    maybe x {nothing} = x

    maybe 3 {just: 4} == 4
    maybe 3 {nothing} == 3

    -- In case this sort of things floats your boat, you can also declare
    -- polymorphic types in "java" style, with `< >`.

    has_value: Maybe<a> -> Bool
    has_value {just: _} = true
    has_value _ = false

    has_value {just: 4}
    not (has_value {nothing})
    
    -- Changes
    -- -------
    
    -- 0.1.1

    -- * Documentation generation has been greatly improved.  Better styling, generates individual pages for each file.
    -- * The prelude is now embedded in the compiler.  Simply import it via `open prelude` - the compiler will include
    --   the code automatically.  Currently weighs in at ~11k, if you care about that sort of thing.
    -- * Command line interface is more pleasant to work with