Skip to content
/ elfu Public

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

Notifications You must be signed in to change notification settings

exebook/elfu

Repository files navigation

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][100].
  • 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. [100]: http://exebook.github.io/fonts/elfu.ttf

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(a == b) }
 compare a b { console.log(a == b) }
 compare { console.log(a == b) }
[1,2,3].forEach( { console.log(a) })
n = 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 @, $, , , , , '∞', ';', '⌥'.
 (x == 1)  'GREAT'
 (x == 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
 (x < 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) @
		 (x > 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⁰) ⫴ (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

About

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

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published