Hello,
Just for toying around, i wanted to design (and maybe implement) a
custom language of my own.
I used to see the languances being either functional or imperative.
Thus, being influenced by both, i tried to combine both in a simple
neat language.
Despite everything looked fine at first sight, i'm running in some
issues when digging a little deeper.
If this teases you, I would welcome your insights about the language
design/ideas as a whole
and also (and more im****tantly) about the issues it triggers as shown
in the end of this post.
Maybe your experience can enlighten these in a helpful manner.
Instead of introducing my little language with boring syntax and
semantics, I preferred to present
it by the means of examples. It's both easier and more refre****ng
while keeping perfect accuracy.
The post is somewhat long but should be an easy reading, i hope you
will enjoy it.
The core is based on the difference between equality (=) and
affectation (:=). Equality is used
in the true sense, meaning that the variable will always be equal to
the expression of the right hand
side. I.e. by reference. On the opposite, affectation means that it is
equal to the value of the right hand side expression at this current
moment of execution. I.e. by value.
So, let us start with a few examples:
---=== Equality vs Affectation ===---
x = 1
x = 2 // ERROR: x is already equal to 1
y := 1
y := 2 // OK, the value of y is now 2
declare b
a = b
print a // prints undefined
b := 1
print a // prints 1
b := 2
print a // prints 2
b := 1
a := b
print a // prints 1
b := 2
print a // prints 1
declare b,c
a = 100 + b // OK, b has been declared previously
b = 10 * c // OK, c has been declared previously
// now, we have a == 100 + 10*c
print a // prints undefined
c := 3
print a // prints 130
c := 7
print a // prints 170
c := a // c := 170
print a // prints 1800
declare b,c
a = b
b = 2*c
c = a // ERROR: cyclic dependency
The other main part of the language are functions. Variables are
linked (equal or affected) to either
values or functions. There are three im****tant fact about these
functions:
-functions are deterministic/stateless
-functions cannot produce side effects
-functions can be nested
Declaring a function looks like this:
f = function: (x) -> (y)
In words, f is a function taking as input x and returning y as output
---=== Functions are stateless ===---
a = 2
b := 3
c = b
f = function: (x) -> (y)
y = a*x // OK, a is stateless
g = function: (x) -> (y)
y = b*x // ERROR, b is stateful
h = function: (x) -> (y)
y = c*x // ERROR, c is (indirectly) stateful
f = function: (x) -> (y)
//...
g := function: (x) -> (y)
//...
hf = function: (x,y) -> (z)
z = f(x) + f(y) // OK, the function is still stateless
hg = function: (x,y) -> (z)
z = g(x) + g(y) // ERROR, because g is stateful
hh = function: (x,y) -> (z)
if x == 1 or y == 1 then
z = 1
else
z = hh(x-1,y-1) + x*y // OK, stateless recursive calls
---=== Functions without side-effects ===---
declare a,b
f = function: (x,y) -> (z)
a = 1 // ERROR, functions cannot modify variables outside their
scope
b := 2 // ERROR, functions cannot modify variables outside their
scope
a = 1
b := 2
g = function: (x,y) -> (z)
declare a,b // redeclaring variables with local scope
a = 3 // OK, local variables
b := 4 // OK, local variables
print a // prints 1
print b // prints 2
---=== Function calls ===---
f = function: (x,y) -> (z)
z = x^2 + y^2
declare a,b
c = f(a,b)
print c // prints undefined
a = 2
b := 3
print c // prints 13
f = function: (x,y) -> (z)
z = x^2 + y^2
g = function: (x,y) -> (z)
z = x^2 - y^2
declare h as function
ans = h(1,2)
print ans // prints undefined
h := function f
print ans // prints 5
h := function g
print ans // prints -3
h := function: (x,y) -> (z)
z = f(x,y) + g(x,y)
print ans // prints 2
print h(10,20) //prints 200
---=== Nested functions ===---
binomial = function: (i,n) -> (ans)
fact = function: (n) -> (ans)
if (n > 1)
ans = n * fact(n-1)
else
ans = 1
ans = fact(n)/(fact(i)*fact(n-i))
---=== Returning functions ===---
norm = function: (i) -> (function ans)
ans = function: (x,y) -> (dist)
dist = (x^i + y^i)^(1/i)
taxicabLength = function norm(1)
euclideanLength = function norm(2)
norm5 = function norm(5)
dist := taxicabLength(3,4)
print dist // prints 7
dist := euclideanLength(3,4)
print dist // prints 5
dist := norm5(3,4)
print dist // prints 4.174...
That was for the nice part. Now comes the trouble... ;)
....are function always stateless if they satisfy the above examples?
consider the following case:
f = function: (c,d) -> (function g)
g = function: (x) -> (y)
y = c*x + d // Authorized or not? ...can lead to state indirectly
encapsuled in the function
declare a,b
h = function f(a,b) //What happens? ...OK if a is stateless, ERROR if
a is stateful?
// h is a function depending indirectly on a and b
a = 2 // still OK
b := 5 // ERROR, introduces state in h
....this last example is causing me trouble because I would like to
ensure that functions are always stateless, but the fact that
functions can be returned and that the input arguments are bound by
equality cause issues:
-either indirect state can ******* into functions
-either it becomes both hard to ensure that functions are always
stateles and can be unconvinient for the user since "forgotten"
variables cannot be assigned if part of a function
....i'm curious to hear any feedback.
cheers
....btw, is something similar already done in some language?


|