#256 Odd compiler error

cbeust Tue 24 Jun 2008

The following code:

Void process(|Int -> Bool |[] functions)
{
  functions.each |Int fun -> Bool, Int index|
  {
    echo(fun)
  }
}

is giving me:

/Users/cbeust/fan/curry.fan(25,21): Unexpected type literal

This corresponds to the "Int" right after each.

What am I missing?

-- Cedric

brian Tue 24 Jun 2008

The type specification for a function is |A, B, C->R| - you can't have more than one return type. In your case if iterating a list of functions typed as |Int->Bool|, then you probably want:

Void process(|Int->Bool|[] functions)
{
  functions.each | |Int->Bool| fun, Int index |
  {
    echo(fun)
  }
}

The |...| always wraps the function type, they aren't optional.

Let me know if that works - there might still be some parser bugs related to nesting of function types. You might be required to put a space between the two pipes in the closure (or maybe not).

cbeust Tue 24 Jun 2008

Yes, that fixes it, thanks Brian.

I am a bit confused by the rules regarding closure declarations. Sometimes, the formal parameter is inside and sometimes, it's outside:

| Int -> Bool | f
| Int f -> Bool |

What's the rule?

-- Cedric

brian Tue 24 Jun 2008

In this example |Int -> Bool | f, f is not a formal parameter - it is the parameter typed by |Int->Bool|, just like Str f is a parameter called f typed as Str. So the formals of a function signature are never outside.

A function type does not require the formal parameter names - they are optional. Consider these local variable declarations:

|Int->Bool| func := null    
|Int f->Bool| func := null

However a closure must specify a parameter name for each of its parameters. So there is a subtle difference between a function signature and a closure signature. Your original example is a little confusing because you have a closure whose first parameter is a function type:

||Int->Bool| fun, Int index|    // ok
||Int f->Bool| fun, Int index|  // ok
||Int->Bool| fun, Int|          // not ok
||Int->Bool|, Int index|        // not ok

Does that make sense? Because everything is wrapped inside |...| it tends to be much easier to read than C like function signatures once you get the hang of it.

cbeust Tue 24 Jun 2008

Yes, this makes sense, thanks. For some reason, your description is exactly the understanding that I have but I failed to apply it to my own example. I'll blame the jet lag.

I agree that the || notation clarifies things quite a bit.

Groovy started this way and then they started playing with alternate syntaxes: removing the first | and then finally removing both and using -> to separate the closure parameters from its body. I think all these approaches are reasonably readable, so I don't have any preference. For the record, they removed the first bar because they noticed that it always happened right after an opening brace, which is not a problem in Fan.

-- Cedric

Login or Signup to reply.