elfu

0.0.40 • Public • Published

screenshot

Elfu - hosti lammen

Elfu is highly experimental symbolic language. UNICODE contains thousands and thousands of symbols, why not use them?

  • Elfu stands for elvish functional language or elvish numeric gongfu.
  • Elfu in elvish is called hosti lammen, or computing language.
  • Elfu is Javascript compatible, you mix Javascript and Elfu in Elfu file.
  • Elfu file extension is .yy (this is elvish)
  • Elfu is written in Javascript itself.
  • To type symbols we use TAB completion feature of the editor.
  • Most of symbols are just replaced with their Javascript counterparts.
  • Some symbols are parsed in a special way, like or .
  • Editors known to be Elfu-friendly are Sublime Text, Geany, Deodar.
  • If your computer does not show all symbols, there is a font file elfu.ttf.
  • Elfu only uses Unicode standard symbols.
  • Elfu is mostly reversable, in other words you can convert .yy->.js and .js->.yy. Mostly.
  • Read this document in better font here.

Contents

/* TODO: ∼◬ String.fromCharCode() - auto arg ꘉ bind - auto arg - mini functions f = ➮ a + b ⦙ ロ f(2, 3)

*/

Screenshot

Here is how Elfu looks in author's editor:

screenshot

Syntax


function definition
  • typed as fu|TAB.

  • Elfu translator will replace with function.

  • you can avoid (, ) and , in argument declaration.

  • if you omit any arguments, arguments a b c are default.

  • use ➮f(){} or ➮{} syntax to declare an anomymous function without arguments.

  • ➮ {} is a lambda with default arguments a, b, c.

  • ➮ a + b ; becomes ((➮ { $a+b }).bind(this)) - aka "arrow function"

  • anonymous function with arguments a,b: ➮ - a b {}

➮ compare (a, b) { console.log(== b) }
➮ compare a b { console.log(== b) }
➮ compare { console.log(== b) }
[1,2,3].forEach(➮ { console.log(a) })
= 2
a ∆ [1,2,3,4,5] ꔬ ➮ a > n ; // 'this' is bound to a caller
ロ a // prints [3,4,5]
Math.sum = ➮ - x y {
    $ x+y
}

return statement $
  • $ is replaced with return.
➮ four { $ 2 + 2 }

while and for statements and
  • is replaced with while.
  • is replaced with for.
  • typed as wh|TAB, fo|TAB.
  • parens () can be avoided if you have braces {}
⧖ (true) step()
⧗ (var i = 0; i < 3; i++) step()

break and continue statements @
  • @ is replaced with break.
  • is replaced with continue.
⧖ (true) {
    step()
    if (again()) ♻
    if (finished()) @
}
n ∆ 5
⧖ n > 0 { // parens, ( and ) are not needed
    ロ n--
}
 

each looping and
  • typed as ea|TAB.
  • compiles to for (var i = 0; i < obj.length; i++).
  • just type i ⬌ obj, it converts to the above.
  • (iterator) typed as it|TAB.
  • ► is similar to ⬌, but the 'i' is an array item rather than an index.
  • typed as fe|TAB.`
  • simply converts to .forEach.
var a = [1,2,3]
i ⬌ a { console.log(a[i]) }
a ∆ [1,2,3]
i ⬌ a ロ aⁱ
a ∆ [1,2,3]
i ► a ロ i
// index still can be accessed with `_` + name, in this case `_i`.
The `i` will be replaced with `a[i]`. Operator `` either requires `{}` or the expression must be on a single line. (Otherwise Elfu would need to use the full blown expression parser, which is beyond the scope of the current version).
A ∆ [1,2,3,4]
A ⬍ (➮ { ロ a ; })

console.log
  • typed as lo|TAB
  • is Chinese/Japanese character for mouth.
  • tired typing console.log hundreds times a day?
  • takes everything until the end of line or ; as arguments.
  • make sure you add ';' if your code continues on this line.
ロ 'hello world!'
ロ 'numbers are:', 1, 2, 3
if (true) ロ 'here'
➮ compare { ロ a == b; }

Automatic + insertion. You can avoid + for brevity, because inside all string literals can be automatically glued to identifiers and some obvious expressions with '+'.

x ∆ 12345
a ∆ [1,2,3]
 
ロ 'x = ' x
ロ 'four means ' (2+2)
ロ 'a = ' a ' and length is ' a↥
 

Elfu allows you to mix with ${} style of strings.

a ∆ 5678
ロ `a = ${a}`

if, else, elseif ⌥ ⎇ ⥹
  • typed as if|TAB, el|TAB, ei|TAB.
  • is replaced with if.
  • is replaced with else.
  • is replaced with else if.
  • if the conditional statement is enclosed in {}, then () are optional
  • () are optional when the conditional statement starts with one of @, $, , , , , '∞', ';', '⌥'.
⌥ (== 1) ロ 'GREAT'
⥹ (== 2) ロ 'OK'
⎇ ロ 'WRONG'
 
⌥ x == 2 { ロ 'x equals to two' ⦙ }

var and def ∇ ∆ ≜
  • typed as va|TAB, de|TAB, df|TAB.
  • is replaced with var.
  • x ∆ is translated to var x =.
  • reads as is defined as or just define.
  • used to be delta, but in fact it is a simplified form of a math symbol -- definition or is defined as.
  • x ≜ y is replaced with if (typeof x == 'undefined') x = y.
x ∆ 100
⧗ (∇ i = 0; i < x; i++)
a ∆ 1  b ∆ 'string'  c ∆ {}  d ∆ []
➮ countIt {
    a.count ≜ 0
    a.count++
}
state ∆ {}
countIt(state)
countIt(state)
ロ state

stack operations
  • are typed as pu|TAB and po|TAB.
  • is for .push and is for .pop.
  • you can omit ( and ).
  • are typed as Pu|TAB and Po|TAB.
  • is for .shift and is for .unshift.
  • mnemonically shift() is pop() from the other side.
  • mnemonically unshift() is push() from the other side.
  • add ( and ) if you push an expression.
A ∆ []
A ⬊ 1
A ⬊ (2 + 2)
// A = [1, 4]
ロ A ⬈ ; // 4
 

superscript indexing Xⁱ
  • aⁱ translates to a[i].
  • a⁰ translates to a[0].
  • aⁱ⁰ translates to a[i][0].
  • typed as .i|TAB or .1|TAB.
  • super-script index can only be single character.
  • supported are all lowercase latin characters and digits 0-9.
  • do not try to use UPPERCASE characters.
  • do not try to use multicharacter variables like count.
A = [1,2,3]
i ⬌ A ロ Aⁱ
B = [[1,111],[2,222],[3,333]]
i ⬌ B ロ Bⁱ¹

this and undefined are
  • is translated to this..
  • is translated to this.
  • is translated to undefined.
  • typed as th|TAB.
  • typed as this|TAB.
  • typed as un|TAB.
➮ f {
    ⌥ (⚫name == ∅) ロ 'no name'
    ⎇ ロ ⚫name
}
f()
⚫name = 'f1'
f.bind()()

comparison operators and
  • typed as eq|TAB and ne|TAB.
  • converts to ==.
  • converts to !=.
⌥ (x ≟ 2) ロ 'two'
⌥ (x ≠ 2) ロ 'not two'

clean and visible semicolon
  • since elfu code is so condensed, many expressions fit on the same line, to improve readability of such dense code, cleaner version of semicolon was introduced.
  • typed as sc|TAB.
  • and ; both can be used.
ロ 2+2 ⦙ ロ 3+3 ⦙ ロ 4+4 ; ロ 5+5

delete and new are and
  • typed as dl|TAB.
  • typed as new|TAB.
➮ f { ⚫name = 'f1' }
a ∆ ⟡ f
ロ 'name =', a.name
⏀ a ⦙ a = ∅

length of an array or a string
  • typed as .le|TAB.
  • is translated to .length.
  • do not type '.' before , it is implied.
A ∆ [1,2,3]
s ∆ 'hello'
ロ s↥, A
x ∆ 0
⧖ (< s↥) { ロ sˣ ⦙ x++ }

require directive ≣
  • typed as re|TAB.
  • is replaced with require.
  • you can use ( and ) or avoid them.
fs ∆ ≣ 'fs'
spawn ∆ ≣ ('child_process').spawn

Math functions
  • is typed as ra|TAB.
  • is converted to Math.random()
  • is typed as ro|TAB.
  • is converted to Math.round()
  • is typed as fl|TAB.
  • is converted to Math.floor()
  • and can omit ( and ) for simple expressions.
⧗ (i ∆ 0 ⦙ i < 20; i++) ロ ⬠ (⚂ * 1000000)
∇ a = 0.5
ロ ⬠ a, ⍽ a

infinite loop
  • typed as in|TAB.
  • '∞' is replaced with while(true).
  • sometimes you just need an infinite loop.
  • or you need a loop whose logic is more complex than for or while.
    ∞ step() // infinite
    x ∆ 0
    ∞ {
        x += ⚂ * 2
        ⌥ (x ≟ 5) @
        ⌥ (x ≟ 7) @
        ⌥ (> 10) @
        ロ x
    }

time operations
  • is converted to setTimeout.
  • is converted to setInterval.
  • ⌿⌛ is converted to clearTimeout.
  • ⌿⌚ is converted to clearInterval.
  • is converted to (new Date().getTime()).
  • gives you millisecond tick.
  • is typed as st|TAB.
  • is typed as si|TAB.
  • is typed as tt|TAB (mnemonic: time tick).
  • ⌿⌛ is typed as ct|TAB.
  • ⌿⌚ is typed as ci|TAB.
ロ 'please wait two seconds'
(➮ {ロ 'ready';}, 2000)
T ∆ ⚡ ⦙ s ∆ ''
⧖ (s↥ < 1000000) s += 'a'
ロ 'benchmark: ', ⚡ - T, 'ms'

node.js fs functions ,
  • is replaced with fs.readFileSync.
  • is replaced with fs.writeFileSync.
  • is typed fsrs|TAB.
  • is typed fsws|TAB.
  • you can omit ( and ) for ⛁ with a single argument.
fs ∆ ≣ 'fs'
A ∆ ⛁'readme.txt' ≂ ⌶ '\n'
ロ A ↥, 'lines loaded'

str serialization with .
  • is typed as sp|TAB.
  • is typed as jo|TAB.
  • is typed as ts|TAB.
  • is compiled as .split
  • is compiled as .join
  • you can omit ( and ) for simple expressions with , and .
  • is converted to .toString
// replace all occurences of "-" with "+"
ロ '1-2-3-4-5' ⌶ '-' ⫴ '+'
// same with ( and )
s ∆ '-+'
ロ '1-2-3-4-5' ⌶ (s⁰) ⫴ ()
x ∆ 123.456
ロ 'length of string representation of number', x, 'is', x≂↥
fs ∆ ≣ 'fs'
ロ 'Readme contains: ' + ⛁ ('README.md') ≂ ⌶ '\n' ↥ + ' lines'

booleans ⦿ and
  • ⦿ is replaced with true.
  • is replaced with false.
  • ⦿ is typed as tr|TAB.
  • is typed as fa|TAB.
    a ∆ ⦿
    ⌥ (a) a = ⦾
    b ∆ { initialized: ⦾ }

last item of a string or an array
  • is typed as .la|TAB.
  • is typed as .lx|TAB.
  • is used to access the last item of an array or a string.
  • is compiled to [x.length - 1], so xꕉ becomes x[x.length - 1].
  • x↟ is compiled to (x.length - 1).
A ∆ ['X','Y']
➮ appendAndReturnIndex { A ⬊ a ⦙ $ A↟ }
z ∆ appendAndReturnIndex('Z')
ロ 'inserted', Aᶻ, 'at:', z
A ∆ ['hey', 'there', '.', '.', 'how', 'are', 'are', 'you', '.']
➮ removeDoubles {
    R ∆ []
    i ⬌ a {
        ⌥ (aⁱ ≟ R) ♻
        R ⬊ (aⁱ)
    }
    $ R
}
ロ removeDoubles(A) ⫴ ' '
// hey there . how are you .

finding occurence in a string or array with ≀≀
  • is typed as io|TAB.
  • ≀≀ is typed as lio|TAB or io|TABio|TAB.
  • is replaced with .indexOf.
  • ≀≀ is replaced with .lastIndexOf.
  • ( and ) can be used or omited.
s ∆ 'hello world!'
ロ  s ≀ 'world', s ≀ ('o'), s ≀≀ 'o'
// 6 4 7

array utilities , string and character utilities
  • is typed as sl|TAB.
  • is typed as pl|TAB.
  • is typed as fi|TAB.
  • is typed as ma|TAB.
  • is typed as aa|TAB.
  • is typed as so|TAB.
  • is replaced with .slice.
  • is replaced with .splice.
  • is replaced with .filter.
  • is replaced with .map.
  • is replaced with .concat.
  • is replaced with .sort.
  • is typed as cc|TAB.
  • is typed as ca|TAB.
  • is typed as su|TAB.
  • is replaced with .charCodeAt.
  • is replaced with .charAt.
  • is replaced with .substr.
➮ numbersOnly { $ a ⌶ '' ꔬ (➮ { $ a◬(0) <= 57 }) }
ロ numbersOnly('a1b2c4d8q11')
// same as above. but sorted
➮ numbersOnly { $ a ⌶ '' ꔬ (➮ { $ a◬(0) <= 57 }) }
ロ numbersOnly('a1b2c4d8q11')❄ (➮ { $a - b })

symbolic variables
  • there are three types of symbolic variables.
  • the goal is to provide more condense, formula-like notation.
  • α γ β ... ζ are greek letters.
  • Javascript supports greek letters, no translation is needed.
  • Typing in greek: alf=α bet=β gam=γ del=δ eps=ε zet=ζ eta=η tet=θ iot=ι kap=κ lam=λ muu=μ nuu=ν xii=ξ pii=π roo=ρ sig=σ tau=τ ups=υ fii=φ chi=χ psi=ψ ome=ω.
∇ α = 10, δ = 5
α += δ
ロ 'alfa plus delta is:', α
  • ... are encircled letters.
  • encircled letters are typed ooa|TAB, oob|TAB, ooz|TAB etc.
  • they are useful if you are out of latin letters.
  • internally they are represented as _oo_0 to _oo_26.
∇ ⓐ = 0, ⓩ = 26
ロ ⓐ, ⓩ
  • are tags or labels, they have special syntax.
  • is a label definition, ❶ 5 equals to ;var var0 = 5.
  • is a label reference, or usage, ロ ① will convert to console.log(var0).
❶ 'hello' ❷ 'world'
ロ ①, ②

is defined
  • is typed as id|TAB.
  • ⟑ <expr> is replaced with (typeof <expr> != undefined).
s ∆ {x:123}
⌥ (s.x) ロ 's.x is not undefined'

multi line strings

Elfu supports multi line strings enclosed with opening '''\n and closing '''.

console.log('''
   Hello, multi line
   strings world
''')
 
str ∆ '''
   Hello, multi line
   strings world'''
   

(GitHub markdown does highlight with red background for some reason.)


tuples
  • is typed as tu|TAB.
  • a,b ꔪ <expr> is replaced with tmp=<expr>;a=tmp[0],b=tmp[1].
➮ repl { $a.replace(b, c) }
 
➮ half {
    $[a, a/2]
}
 
A ∆ {whole:, part:}
 
☛ A { whole, part ꔪ half(200) }
 
∇ a,b,c ꔪ [33,44,55]
 
ロ A,a,b,c
//{ whole: 200, part: 100 } 33 44 55

TODO: add support for simple name matching with ꔪ, like this:

obj ∆ { a:1, b:2 }
b,a ꔪ obj
//b = obj['b'], a = obj['a']
ロ a, b
// 1, 2

object keys as an array with '⚷'
    obj ∆ {a:1, b:2, c:3}
    ロ ⚷ obj // ['a', 'b', 'c']

namespace utility with ➮| and ➮]

If your elfu source file has ➮] anywhere in it, then all top level declared functions of this file will be automatically exported to module.exports. If you use ➮|, the functions will be exported as global variables.

main.yy
|
'lib'
➮ load {
    ロ 'loaded...'
}
 
scan()
lib.yy
➮ scan {
    load()
    ロ 'processing...'
}
 
|
 
new syntax for branching with ]232
  • is typed as q|TAB or [|TAB.
  • is typed as w|TAB or ]|TAB.
  • is typed as e|TAB.
  • replace '❱' with ')', or '){' when the next token is on the same line.
  • replace '◇' with: a. '} else if(' if followed by the next non-space character '❰'; b. '} else {' if the next token is on the same line; c. 'else'. -- not possible, ◇ cannot be used with the oneliners.
  • replace '⁋' with '}'.
  • replace '❰' with 'if ('.

There is no if keyword or it's analog if you use this notation, the test condition is enclosed in and . The conditional statement is a one liner if it goes on the same line, otherwise end it with the . Same is true with else which is .

This syntax does not replace original JavaScript or original Elfu if else and , but coexist.

/*
    Nested conditional expressions.
    You cannot use ◇ with one-liners. But ◇ itself could have a oneliner expression.
*/
 
1
    ❰2
        b = 3
    ◇
        b = 4
    ⁋
    ❰5
        b = 6
    ◇
        b = 7
    ⁋
❰a ≟ 5❱ a = c
◇ b = 1
 
❰a == 5❱ b = 4
 
❰a == 5
    b = 4
    b = 6
❰a == 5❱ b = 4 ◇ b = 6
 
❰a == 5❱ b = 4 ◇ ❰a == 5❱ b = 6
 
 
❰a == 5❱ b = 4 ◇ ❰a == 5
    b = 6
 

You can combine syntaxes like this:

 
1
    { 2 }
⎇  { 3 }

...or like this:

1
    { 2 }
else
    { 3 }
String array literals
ロ [@ dormouse hare hatter]
 
// [ 'dormouse', 'hare', 'hatter']
extras
`__arrarr` - get the function arguments as an array.
`__elfuver` - return a string specifying current elfu version. This is read from `package.json`.

Usage

  • install with npm, [sudo] npm i -g elfu.
  • yy <program> run the .yy program.
  • yyj program.yy convert program.yy to Javascript. Data is written to standart outout.
  • jyy program.js convert Javascript to Elfu.
  • require('elfu'); require('example.yy') you can require modules written in Elfu.

Dotcall syntax

  • Elfu supports dotcall syntax.
  • dotcall is callback hell remedy.
  • read dotcall README for details.

Feedback

Package Sidebar

Install

npm i elfu

Weekly Downloads

4

Version

0.0.40

License

Public domain(unlicense)

Last publish

Collaborators

  • exebook