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