Skip to content
This repository

Neat and tidy Erlang alternative syntax based on indentation rather than punctuation

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 examples
Octocat-spinner-32 src
Octocat-spinner-32 .gitignore
Octocat-spinner-32 Emakefile
Octocat-spinner-32 LICENSE
Octocat-spinner-32 README
Octocat-spinner-32 make.bat
Octocat-spinner-32 make.sh
Octocat-spinner-32 neaterl.app
README
neaterl
Erlang alternative syntax based on indentation rather than punctuation
Software authored by Walt Woods, project start date 6 June 2010

-INTERACTIVE SHELL-
Make the neaterl module, make sure the binaries are in the erlang path
(for instance, use "erl -pa ebin" if you're testing this out from the 
module's directory), and type the following in a standard erlang 
interpreter:

1> neaterl:shell().
N1> 

And the N1> prompt means you're now typing erlang code through neaterl!  
Statements execute by entering a blank line after you've entered all the
lines you want evaluated.  For example:

N1> 1 + 1
N2> 
2
N1> [
N2>   1
N3>   2
N4>   3
N5> 
[1,2,3]
N1> 

The prompt numbering might continue going up at some point.  However,
at the moment its numbering is useful if you receive syntax errors, or
for entering modules on the command line, like so:

N1> -module(test)
N2> -export(hi/0)
N3> oops
N2> -export([hi/0])
N3> 
N4> hi() -> 
N5>   Name=io:get_line("Your Name? ")
N6>   io:format("Hello, ~s!~n", [ Name ])
N7> 
N8> 
{module,test}
N1> test:hi()
N2> 
Your Name? Walt
Hello, Walt
!
ok
N1> 

Two things to note:
  1. Two blank lines terminate a module definition.
  2. The "oops" command means, "I made a typo and don't want to retype
     every line, please let me retype the last!"  It can be executed 
     as many times as you'd like, all the way back to N1> 

The two blank lines might change at some point, as modules entered in the 
shell probably are not very long, and don't really need blank lines for
formatting.

Typing "exit" or "quit" will leave the neaterl shell.

N1> quit
N2> 
(Back to regular erlang prompt)
2> 

-COMPILING .erln FILES-

Create a file with a .erln extension, such as test.erln.  Copy the
following into it:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-module(test)
-export([ hello_world/0, fac/1 ])

hello_world() -> io:format("Hello, World!~n", [])

fac
  (0) -> 1
  (N) when is_integer(N) and N > 0 ->
    N * fac(N - 1)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Then, open up any erlang prompt, and run "neaterl:compile(test)" to
generate the corresponding .beam file.  

If you'd like to load the module immediately to play with it, similar 
to the default shell's c() command, run "neaterl:load_file(test)"

(Incomplete) If you want to have neaterl check the entries in your
Emakefile for .erln source files, run "neaterl:make_all()" from a 
script or some such.

-GETTING EQUIVALENT ERLANG CODE-

neaterl exposes four functions: file/1, file/2, string/1, and string/2, 
that return the equivalent erlang code for the content of the file or
string.

Line numbers and indentation are preserved for the most part.

-COOL POINTS-
In addition to removing most statement termination symbols, neaterl 
changes the grammar such that line breaks and commas are relatively 
interchangable.  All statements can either be inline (comma-separated) 
or indented (line-separated).  For example, a long list could be 
written in neaterl as:

[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

OR

[
  1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  
Note that there's no closing bracket on the indented version - the
indentation (or lack thereof) of the following statement implies that 
the previous structure is closed.  Though a little odd at first, it 
really helps to remove a lot of the unnecessary punctuation.  Compare 
with closing symbols:

test() ->
  D = lists:map(
    fun(X) ->
      [
        {hi,there}
        {yo,val}
        {eep, street}
      ]
    lists:seq(1,1000000)
  )
  fprof:apply(
    {lists,map}
    [
      fun(X) -> proplists:get_value(eep, X)
      D
    ]
  )
  
To without closing symbols:

test() ->
  D = lists:map(
    fun(X) -> 
      [
        {hi, there}
        {yo, val}
        {eep, street}
    lists:seq(1,1000000)
  fprof:apply(
    {lists,map}
    [ 
      fun(X) -> proplists:get_value(eep, X)
      D

Omitting the closing symbols better subscribes to the idea that 
indentation is what delineates one statement from another.  It also 
produces more succinct code.

--and/or/andalso/orelse/,/;--
andalso, orelse, ',', and ';' have all been merged into 'and' and 'or'.
The compiler will choose the appropriate symbol based on if the operator
occurs in a guard expression or not.  To see how these symbols translate,
use the "keep_temp" option in neaterl's compilation.  Note that, at 
present, there is no non-shortcircuiting version of these operators.

--Functions With Multiple Matches--
Functions in neaterl only have their name once, followed by any number of 
body definitions, much like Erlang's anonymous function syntax.  E.G.:

fac
  (0) -> 1
  (N) when is_integer(N) and N > 0 ->
    N * fac(N-1)
    
Which helps to keep the bodies grouped together and makes a functional 
grouping more readily identifiable.

Something went wrong with that request. Please try again.