Before we begin: I'm new to Nim and it's been a while since I did anything to 
do with AST, parsing, etc. so my suggestions may be whacky. If they are, simply 
say so and turn the discussion in the right direction.

**Where we're at**

List comprehension is currently available through the _future_ module. For 
loops as expressions have been suggested to replace it but what should their 
capabilities be, and what should the syntax look like?

**Requirements**

Should the syntax be:
    

  * 1) Familiar to anyone knowing math/Python? (e.g., x for x in y [if z])
  * 2) Similar to for statements? (e.g., for x in y: [if z:] x)



_(The pros and cons of each are probably best found by providing examples of 
each.)_

Should it be capable of:
    

  * A) Creating only seq[T]? (So, sequence comprehension)
  * B) Creating any type Y[T] implementing add()? (Basically, [mutable] 
collection comprehension)



_(I'm guessing B, since expressiveness is a higher priority than elegance.)_

Assuming B, should the type be denoted:
    

  * X) Through constructors? (Araq mentioned this but I'm not sure I understood 
correctly)
  * Y) Only for types other than seq? (i.e., the type is seq if it can't be 
inferred. I can imagine the AST is built in a way that makes this infeasible or 
impossible)



Should it be implemented on parser level, as a macro, or something else? I'm 
not very familiar with the any of these things, but it I'm guessing they put 
different limitations on the syntax and provide varying levels of efficiency.

For Y, this is what I had in mind:
    
    
    # @[2, 3, 4]
    var a = for x in [1, 2, 3]: x+1
    
    # {2, 3, 4}
    var a: set[int] = for x in [1, 2, 3]: x+1
    
    # With input "A", "B", "C": {"A", "B", "C"} and @["A", "B", "C"]
    # With input "A", "A", "C": {"A", "C"} and @["A", "A", "C"]
    var a: set[string] = for x in 1..3: readLine(stdin)
    var a = for x in 1..3: readLine(stdin)
    

And lastly, here's a wall of code that contains my not-so-well-structured notes:
    
    
    import strutils, algorithm, math
    
    var bowlSizes = (var s: seq[int] = @[]; for _ in 1..3: 
s.add(parseInt(readLine(stdin))); s)
    # var bowlSizes = lc[parseInt(readLine(stdin)) | (_ <- 1..3), int]
    
    bowlSizes.sort(system.cmp[int])
    echo bowlSizes[1]
    
    """Syntax suggestions; line one describes the syntax, line two is how it 
could be expanded."""
    
    # Syntax 1
    var a: seq[T] = for x in y: expr
    var a: seq[T] = (var s: seq[T] = seq[T](); for x in y: (var e: T = expr; if 
e != nil: s.add(e)); s)
    
    # Syntax 2, rule 1
    var a: seq[T] = expr for x in y
    var a: seq[T] = (var s: seq[T] = seq[T](); for x in y: (var e: T = expr; if 
e != nil: s.add(e)); s)
    
    # Syntax 2, rule 2
    var a: seq[T] = expr for x in y cond
    var a: seq[T] = (var s: seq[T] = seq[T](); for x in y: (var e: T = expr; 
cond: (if e != nil: s.add(e))); s)
    
    
    """Random examples"""
    
    # Syntax 1 examples
    A) var a: seq[int] = for x in [1, 2, 3, 4]: if x mod 2 == 0: x else: x + 1 
# @[2, 2, 4, 4]
    B) var a: seq[int] = for x in [1, 2, 3, 4]: if x mod 2 == 0: x # @[2, 4]
    C) var a = ... # type inference
    D) var a = for x in 0..10: if x mod 2 == 0: (if x < 5: 5 - x else: x - 5)
    E1) var a = for x in [1, 2, 3, 4, 5]: for y in [1, 1, 2, 3, 5]: if x mod y 
== 0: x / y
    E2)
    var a =
      for x in [1, 2, 3, 4, 5]:
        for y in [1, 1, 2, 3, 5]:
          if x mod y == 0:
            x / y
    
    # Syntax 2 examples
    A) var a: seq[int] = x if x mod 2 == 0 else x + 1 for x in [1, 2, 3, 4] # 
@[2, 2, 4, 4]
    B1) var a: seq[int] = x for x in [1, 2, 3, 4] if x mod 2 == 0 # @[2, 4]
    B2) var a: seq[int] = x if x mod 2 == 0 for x in [1, 2, 3, 4] # @[2, 4]
    C) var a = ... # type inference
    D) var a: seq[int] = 5 - x if x < 5 else x - 5 for x in 0..10 if x mod 2 == 0
    E1) var a = x / y for x in [1, 2, 3, 4, 5] for y in [1, 1, 2, 3, 5] if x 
mod y == 0
    E2)
    var a = x / y
            for x in [1, 2, 3, 4, 5]
            for y in [1, 1, 2, 3, 5]
            if x mod y == 0
    
    """More examples. From 
http://www.secnetix.de/olli/Python/list_comprehensions.hawk""";
    
    # Plain math
    S = {x^2 : x in {0 ... 9}}
    V = (1, 2, 4, 8, ..., 2^12)
    M = {x | x in S and x even}
    
    # Python
    S = [x**2 for x in range(10)]
    V = [2**i for i in range(13)]
    M = [x for x in S if x % 2 == 0]
    
    # Syntax 1
    var S = for x in 0..9: x^2
    var V = for i in 0..12: 2^i
    var M = for x in S: if x mod 2 == 0: x
    
    # Syntax 2
    var S = x^2 for x in 0..9
    var V = 2^i for i in 0..12
    var M = x for x in S if x mod 2 == 0
    OR var M = x if x mod 2 == 0 for x in S
    
    
    """Allow any collection that implements add(). Is it unintuitive or harder 
to implement?"""
    
    # Variation of Syntax 1
    var a: Y[T] = for x in y: expr
    var a: Y[T] = (var s: Y[T] = Y[T](); for x in y: (var e: T = expr; if e != 
nil: s.add(e)); s)
    
    # Assume seq if not specified?
    var a = for x in y: expr
    var a: seq[T] = ...
    
    # Variation of Syntax 2
    var a: Y[T] = expr for x in y
    var a: Y[T] = expr for x in y cond
    var a: Y[T] = (var s: Y[T] = Y[T](); ...
    

Reply via email to