funq: syntax that doesn't scare off C++ developers
Aaron J. Seigo
aseigo at kde.org
Fri Jul 25 11:00:29 UTC 2014
On Friday, July 25, 2014 11:24:12 Ivan Čukić wrote:
> 1. The first thing I'm concerned about is the colon syntax for preconditions
> - it will be confused for initialization (c++), or typing (pascal, scala).
> I'd rather have an explicit keyword like 'assuming', 'requires', 'assert'
> or similar.
>
> Like:
> someFunction(a, b, c)
> requires(a > 0 && b + c < 100)
> {
> something here
> }
The use of ':' is indeed terse; honestly I simply borrowed that over from
Erlang. A keyword like "requires" is a pretty good idea, though, for the
reasons you note. How about "when"? As in:
someFunction(a, b, c) when (a > 0)
{
... block ...
}
it's just four keystrokes and when read out loud is exactly how one would
explain it: "this variant of someFunction runs when a is greater than 0"
> 2. What would a function look like if one wants to do explicit typing for
> arguments and/or result?
currently a bit messy ... the preconditions are currently being used for this
but i like it less and less. i'm thinking of simply allowing one to optionally
state the type in the parameter list.
> > Preconditions optionally follow the the parameter list and allow various
> > boolean checks to be made on the parameters. The third fibonacci function
> > version checks that x is an integer and greater than 2.
>
> 3. I'm guessing that preconditions are also involved in pattern matching?
yes. during compilation the param list and preconditions should compile down
to a single set of comparisons.
> > There are no return types; functions are free to return different types.
>
> 4. Related to (2):
> - it seems strange to have a statically typed language where a function can
> return a different type depending on arguments
> - it is useful to have strict compiler-checked typing (even optional) -
> less bugs can get into the code
true, and i keep going back and forth on this one in my head. i want to keep
the syntax "terse" and consistent and requiring return types to be defined or
making them optional works against one or the other.
there are many times when having multiple return types is very useful, of
course. if nothing else, it allows error objects to be treated as a normal
return value rather than an exceptional state like an exception.
the other nice result is that it makes many functions type-generic without
having to think too much about it. yes, some functional languages have the
'type type' (e.g. `a) but that is one more concept for the developer to learn
and keep straight.
i'm not entirely against return types being defined ... but currently i lean
away from them due to the above and the fact that a number of successful
languages also avoid them.
hard one ...
> > part to single-assignment). Due to single-assignment, there is no need for
> > a comparison operator (==). The assignment operator does both assignment
>
> While there is no technical need for ==, it doesn't mean that the resulting
> code is readable. It is needed for usability - if you are reading a long
> function and encounter something = 2, you need to go upwards and check
> whether something was already defined or not to see whether it is a new
> alias or a comparison.
There are unfortunate ambiguities in having '==' present. First the trivial
and not-too-bad example:
func() { a == 2; }
The compiler could throw an "undefined variable" error there. I'd like to be
able to avoid compiler errors as they slow one down .. that is balanced, of
course, against this function:
func() { a = 2; }
doing the "least surprise" thing of returning 2 but being oddly meaningless as
Marco noted. A compiler error would at least let you know .. but then you'd
also get a compiler warning in that case. So for the trivial case I could go
either way and think you do have a valid point in terms of usability.
The real problem comes with pattern matching assignment:
{ "blue", x } = someTuple;
Now it is a combined assignment and comparison. This will generate an error if
the first element of someTuple is not equal to the literal value "blue". If the
first element is "blue", then x gets assigned.
Or:
y = "blue";
{ y, x } = someTuple;
This is the same as above ... except one variable is already defined and so it
is a comparison while the second variable is only now being assigned and so it
is being assigned.
Does one use '=' or '==' there? with pattern matching assignment '==' becomes
not only redundant to '=' but rather confusing as to its actual purpose.
Pattern match based assignment is amazingly useful and not hard to get the
hang of with a little practice. It also shows up in comprehensions, of course.
So getting rid of '==' might indeed be worse for the simple case but it
generates inconsistency with pattern matching thrown in.
--
Aaron J. Seigo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part.
URL: <http://kde.org/pipermail/funq-devel/attachments/20140725/60820a75/attachment.sig>
More information about the Funq-devel
mailing list