Hi,
I solved the "Grade School" exercise available on Exercism.io the following way:
from algorithm import sortedByIt
from sequtils import unzip, filterIt
type
Student* = tuple
name: string
grade: int
School* = object
students*: seq[Student]
proc roster*(scool: School): seq[string] =
scool.students.sortedByIt((it.grade, it.name)).unzip[0]
proc grade*(scool: School, graad: int): seq[string] =
# Does not work:
#scool.students.filterIt(it.grade == graad).sortedByIt(it.name).unzip[0]
# Works:
let stuudents = scool.students.filterIt(it.grade == graad)
stuudents.sortedByIt(it.name).unzip[0]
# Also works:
#scool.students.sortedByIt(it.name).filterIt(it.grade == graad).unzip[0]
What I don't get is why I can chain sortedByIt then filterIt but not filterIt then sortedByIt.
If I use the last formulation, the Nim 1.2.6 compiler complains with something like: sequtils.nim(569, 7) Error: internal error: environment misses: result. The Nim 1.4.0 compiler complains with: sequtils.nim(576, 7) Error: 'it' is of type <lent Student> which cannot be captured as it would violate memory safety, declared here: sequtils.nim(576, 7); using '-d:nimWorkaround14447' helps in some cases; if I activate the workaround, I get the same error message as returned by the Nim 1.2.6 compiler.
Thanks for any light on this matter :)
Please submit this as a bug on the github issue tracker.
The trouble lies within sortedByIt, where it constructs the comparison proc and tries to get the type of the sequence with typeof(seq1[0]) changing that to auto seems to work:
template sortedByIt*(seq1:typed, op: untyped): untyped =
var result = sorted(seq1, proc(x, y: auto): int =
var it {.inject.} = x
let a = op
it = y
let b = op
result = cmp(a, b))
result
This issue is an old one in fact: I just stumbled upon a GitHub issue opened by someone having encountered this internal error on the same Exercism problem.
I've updated the GitHub issue through this comment.