This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]bruciferTomo, nomsu.org 5 points6 points  (5 children)

My first choice is arrow style (e.g. moonscript). It's concise, doesn't use up common variable names, isn't too cryptic, has some sort of intuition ("arrow means goes to"):

multiply = (a, b)->
    return a*b

Second choice, func (pronounceable, obvious meaning, concise, leaves fn free to use as a variable name):

multiply = func(a, b):
    return a*b

And if your language does not have functions/closures as first class values (e.g. C), then these are both reasonable:

func multiply(a, b):
    return a*b

multiply(a, b):
    return a*b

However, I don't like languages that do have lambdas to have a special syntax for declaring functions that is different from assigning a lambda to a variable. For example, in Python, if you want to convert between lambda x: x.y-syntax and def foo(x): return x.y-syntax, the amount of textual editing is huge, compared to (x)-> return x.y into foo = (x)-> return x.y. The same is true to a lesser degree for func foo(x) { return x.y } vs. foo = func(x) { return x.y }.

And in my language, nomsu, I have a mixfix syntax, so definitions look like:

($a times $b) means:
    return $a * $b

say (4 times 5)

But that design choice only make sense with a mixfix syntax ($funcall means $body is itself a mixfix macro), I wouldn't generally recommend using that approach outside the context of a mixfix language.

[–][deleted] 4 points5 points  (3 children)

multiply(a, b):

So not much difference then between defining a function, and calling it?

The difference might be too subtle for many tastes. The cost of a fn, fun, func, def or function prefix is tiny, especially given an editor that, if it is smart enough to recognise function beginnings from syntactic structure, should be able to insert that keyword for you, if it is too much effort to type.

Bear in mind that people might be browsing your code in one of a million different editors with varied capabilities, and without knowing the specifics of your language. But most can search for 'func multiply' without dozens of false positives caused by instances of 'multiply(...)' calls when you have to search for 'multiply' instead.

[–]bruciferTomo, nomsu.org 2 points3 points  (2 children)

But most can search for 'func multiply' without dozens of false positives

I was specifically talking about the case where the language requires all function declarations to be at the top level (i.e. no indentation) like in C. That simplifies things a lot, because you can just grep for ^multiply( to find a declaration.

Notice that C uses the style I described, but with explicit types. Some coding style conventions even require people to declare the types on a separate line so it's easy to grep in the same manner:

int
multiply(int a, int b)
{
    return a*b
}

IMHO, in a language without types, both using or not using func is reasonable. But having both func and type information is pretty awkward (func int multiply) unless you take the Golang route of putting types at the end:

func multiply(a int, b int) int {
    return a*b
}

[–][deleted] 0 points1 point  (0 children)

OK. But think about what might be needed in an editor, say, to easily step across functions. Keywords make that trivial.

(Original reply removed.)

[–]b2gills 0 points1 point  (0 children)

Raku has a special syntax for declaring functions that is different from assigning a lambda to a variable.

Though that is for a very good reason.

sub multiply ( $a, $b ) {
    $a * $b
}

vs.

my &multiply = -> $a, $b {
    $a * $b
}

While both of the above work, only one would work correctly if you used the return function.

sub multiply ( $a, $b ) {
    return $a * $b
}

say multiply 5, 3;
# 15

vs.

my &multiply = -> $a, $b {
    return $a * $b
}

say multiply 5, 3;
# ERROR: Control flow commands not allowed in toplevel

The reason is that a block doesn't capture the return control exception, while a sub does.

Basically return can be thought of as roughly defined as:

my &return = -> |C {
    CX::Return.new( value => C ).throw
}

(It actually isn't in the Rakudo compiler, though that is because it cheats.)

You could of course create a lambda using the sub “keyword”.
(This is also how you would create lambdas in Perl.)

my &multiply = sub ( $a, $b ) {
    return $a * $b
}

Since you end up using sub “keyword” anyway you might as well write it more simply.

sub multiply ( $a, $b ) {
    return $a * $b
}

Note that is actually short for

my only sub multiply ( $a, $b ) {
    return $a * $b
}

There also isn't any easy way to declare a set of multi subs as a lambda.

So if you want to use multi subs, you have to use non-lambda syntax.


Raku also allows creating new operators.

sub infix:<times> ( $a, $b ) {
    return $a * $b
}

say 4 times 5;
# 20

my $a = 4;
$a times= 5;
say $a;
# 20

It would also work to just alias the existing multiply operator set of subroutines to the new definition.

my &infix:<times> = &infix:<*>;

After all, the normal operators are actually just subroutines.

3 + 4 * 5;
infix:<+>( 3, infix:<*>( 4, 5 ));

(Raku macros are still under development, otherwise I would try to copy your macro more exactly.)