Search code examples
list-comprehensionrascal

How to do a list comprehension to a relation?


In my code I have the following two methods:

public void AllDivisors(int max) {
     lrel[int,list[int]] div = [ <i,d> | int i <- [0 .. max], list[int] d <- GetDivisors(i)];
     println("<div>");
}

public list[int] GetDivisors(int n) {
      return [ p | p <- [1..n], n % p == 0];
}

The second one (GetDivisors) gives the list of divisors for n and returns those as a list[int]. Next I want to map those on the values of n using a lrel in the first method (AllDivisors). I was trying to get this done in one go using a list comprehension, but this doesn't seem to work.

rascal>GetDivisors(10);
list[int]: [1,2,5]

rascal>AllDivisors(10);
|project://Sevo/src/NumberEx.rsc|(189,1,<8,85>,<8,86>): Expected int, but    got list[int]
Advice: |http://tutor.rascal-mpl.org/Errors/Static/UnexpectedType/UnexpectedType.html|

I'm having a hard time figuring out where Rascal is expecting an int but getting a list[int]. I suppose it's in d <- GetDivisors(i). How can I generate the correct tuples in my list-comprehension?


Solution

  • It is in:

    list[int] d <- GetDivisors(i)
    

    when you iterate over the results of GetDivisors you are getting int's not, list[int]'s. So changing that to int d, or just d (type inference) should be good enough.

    you could also do this:

    lrel[int,list[int]] div = [ <i,d> | int i <- [0 .. max], list[int] d := GetDivisors(i)];
    

    This binds the d variable to the result of GetDivisors

    But for this case I would write it as follows:

    div = [ <i, GetDivisors(i)> | i <- [0..max]];