I don't know any language not having
flaws/limitations/imperfections/missing-features, so here are merd's.
The items below can range from imperfection to flaws, depending on the item,
but also (and quite importantly) on what people think is right or wrong.

## Variable declaration

merd has chosen the Python way of declaring variables. It's expressive, but it
doesn't scale well in very nested constructs where you can't know wether a
assignment is a side-effect or a declaration.
! The scope of variables is still an open issue !

## One element tuple

merd uses "`((a))`" for 1-uple.
See the explaination of this trade-off

## Using a tuple for a function call

add(x,y) = x + y
t = (1, 2)
s = add(t)

Seems quite ugly. Alas, disallowing "`add(t)`" and forcing to use
"`add(*t)`" a la Python/Ruby [1] implies the following
for higher-order functions:
apply(f, x) = f(x)
apply'(f, x) = f(*x)
s = apply(add, t) #=> error
s' = apply'(add, t) #=> ok

Which is detrimental to functional programming [2]

## List containing a tuple

- list containing 1 and 2:
l1 = (1,2) has type List(1|2), or
l1 = [1,2] has type List(1|2)

- list containing the tuple "
`1,2`":
l2 = ((1,2)) has type ((1,2))
l2 = [((1,2))] has type List(1,2)

- OCaml avoid this problem by using "
`;`" for separating list elements:
`l1` is "`[1;2]`" and `l2` is "`[1,2]`"
- in Haskell and Python,
`l1` is "`[1,2]`" and `l2` is "`[(1,2)]`"

## Assignment doesn't return any value

This means you can't write `if ((i = 0)) ...` as you can do in C.

## Control structures are multi-operators (aka distfix operators)

This means there must be exactly one argument between each operator.
For example "`while a do b`" is "`multiple_while_do(a, b)`"
(prefix distfix operator).
Since control structures are no special construct, you can't have something like:

- C's "
`if (cond) do_something`" (note the special mandatory parenthesing around the condition)
- Ruby's "
`if cond ; do_something end`"

## Values in strings

`"foo{val}bar"` is `"foo" + val.to_string + "bar"`. It means
that it doesn't enforce that `val` is a string.

## Complexity

The flexibility of the type system allows a nice expressivity together with
static typing. The penalty is of course the complexity of the types, and
complex type error messages.

## Compile-time cost

The algorithm for infering/checking types is time costly.

## Run-time cost

The ability to multiple dispatch implies some computation to find out the
right function to call. The case is worse than most languages having runtime
dispatch because the types are anonymous, a value belonging to a potentially
infinite lattice of types.

## Expressivity "restrictions"

- return values must be explictly ignored
- numbers, strings... are not boolean values (contrary to C/C++/Python/Perl/Ruby [3])

# Notes

[1]
Using prefix "`*`" would conflict with multiplication.

[2]
Here is the Python version:

def apply(f,x): return f(x)
def apply2(f,x): return f(*x)
def add(x,y): return x+y
apply (add, (4,5)) #=> TypeError: add() takes exactly 2 arguments (1 given)
apply2(add, (4,5))

[3]
What is *true* depends from one language to another:

0 | "" |

false | false | Perl, Python, JavaScript, PHP |

true | true | Ruby, Common Lisp, Scheme, Dylan |

false | true | C |

false | error | Tcl |

More about it

Pixel
This document is licensed under GFDL (GNU Free Documentation License).
Release: $Id: flaws.html,v 1.12 2002/09/23 11:25:54 pixel_ Exp $