List comprehensions: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (syntax highlighting fixup automation)
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(11 intermediate revisions by 5 users not shown)
Line 21:
{{trans|Python}}
 
<syntaxhighlight lang="11l"> print(cart_product(1..20, 1..20, 1..20).filter((x, y, z) -> x ^ 2 + y ^ 2 == z ^ 2 & y C x .. z))</syntaxhighlight>
 
{{out}}
Line 275:
end mReturn</syntaxhighlight>
{{Out}}
<syntaxhighlight lang="applescript"pre>{{3, 4, 5}, {5, 12, 13}, {6, 8, 10}, {7, 24, 25}, {8, 15, 17}, {9, 12, 15}, {12, 16, 20}, {15, 20, 25}}</syntaxhighlightpre>
 
=={{header|Arturo}}==
Line 397:
C doesn't have a built-in syntax for this, but any problem can be solved if you throw enough macros at it:
{{works with|GCC}}
The program below is C11 compliant. For C99 compilers note the change on line 57 :(output remains unchanged).
<syntaxhighlight lang="c">
for (int i = f + 1; i <= t; i ++) { e = e->nx = listNew(sizeof i, &i); }
</syntaxhighlight>
to
<syntaxhighlight lang="c">
int i;
for (i = f + 1; i <= t; i ++) { e = e->nx = listNew(sizeof i, &i); }
</syntaxhighlight>
Output remains unchanged.
<syntaxhighlight lang="c">
#include <stdlib.h>
Line 464 ⟶ 455:
List * intRangeList(int f, int t) {
List * l = listNew(sizeof f, &f), * e = l;
for (int i = f + 1; i <= t; i ++) { e = e->nx = listNew(sizeof i, &i); } // C11 compliant
//int i;
//for (i = f + 1; i <= t; i ++) { e = e->nx = listNew(sizeof i, &i); } // use this for C99
return l;
}
Line 611 ⟶ 604:
[x, y, z]
))
# pyth can also be written more concisely as
# pyth = (n) -> flatten (flatten ([x, y, z] for z in [y..n] when x*x + y*y is z*z for y in [x..n]) for x in [1..n])
 
console.dir pyth 20</syntaxhighlight>
 
<code>pyth</code> can also be written more concisely as
 
<syntaxhighlight lang="coffeescript">pyth = (n) -> flatten (flatten ([x, y, z] for z in [y..n] when x*x + y*y is z*z for y in [x..n]) for x in [1..n])</syntaxhighlight>
 
=={{header|Common Lisp}}==
Line 1,045 ⟶ 1,036:
12 16 20
->
</pre>
 
=={{header|Insitux}}==
 
{{Trans|Clojure}}
 
<syntaxhighlight lang="insitux">
(function pythagorean-triples n
(let n+1 (inc n))
(for x (range 1 n+1)
y (range x n+1)
z (range y n+1)
(unless (= (+ (* x x) (* y y)) (* z z))
(continue))
[x y z]))
 
(pythagorean-triples 20)
</syntaxhighlight>
{{out}}
<pre>
[[3 4 5] [5 12 13] [6 8 10] [8 15 17] [9 12 15] [12 16 20]]
</pre>
 
Line 1,651 ⟶ 1,663:
=={{header|OCaml}}==
 
As of OCaml 4.08 (2019), [https://v2.ocaml.org/manual/bindingops.html binding operators] were added to the language syntax. A general notion of "comprehension syntax" can be recovered using them.
[http://batteries.forge.ocamlcore.org/ OCaml Batteries Included] has uniform comprehension syntax for lists, arrays, enumerations (like streams), lazy lists (like lists but evaluated on-demand), sets, hashtables, etc.
 
ComprehensionAssuming area comprehension is of the form
<code>[? expression | x <- enumeration ; condition; condition ; ... ]</code>
We can rewrite it using binding operators like so
<syntaxhighlight lang="ocaml">let* x = enumeration in
if not condition then empty else
return expression
</syntaxhighlight>
 
For instance, we can write the required Pythagorean triples comprehension:
For instance,
<syntaxhighlight lang="ocaml"># [? 2 * x | x <- 0 -- max_int ; x * x > 3];;
- : int Enum.t = <abstr></syntaxhighlight>
or, to compute a list,
<syntaxhighlight lang="ocaml"># [? List: 2 * x | x <- 0 -- 100 ; x * x > 3];;
- : int list = [2; 4; 6; 8; 10]</syntaxhighlight>
or, to compute a set,
<syntaxhighlight lang="ocaml"># [? PSet: 2 * x | x <- 0 -- 100 ; x * x > 3];;
- : int PSet.t = <abstr></syntaxhighlight>
 
<syntaxhighlight lang="ocaml">let pyth n =
etc..
let* x = 1 -- n in
let* y = x -- n in
let* z = y -- n in
if x * x + y * y <> z * z then [] else
[x, y, z]
</syntaxhighlight>
 
where the <code>(let*)</code> and <code>(--)</code> operators are defined for the <code>List</code> module like so:
 
<syntaxhighlight lang="ocaml">let (let*) xs f = List.concat_map f xs
let (--) a b = List.init (b-a+1) ((+)a)
</syntaxhighlight>
 
=====Historical note=====
 
:OCaml never had a built-in list-comprehension syntax. However, there have been a couple of preprocessing syntax extensions which aimed to add list comprehensions sugar to the language. One of which was shipped directly with [https://github.com/camlp4/camlp4 camlp4], a tool for syntax extensions that was bundled with the OCaml compiler distribution, up to version 4.02 (2014), and was completely deprecated after version 4.08 (2019).
 
:Another, [https://github.com/ocaml-batteries-team/batteries-included OCaml Batteries Included], had uniform comprehension syntax for lists, arrays, enumerations (like streams), lazy lists (like lists but evaluated on-demand), sets, hashtables, etc. This later split into the now legacy package [https://github.com/murmour/pa_comprehension pa_comprehensions], which is similarly deprecated.
A standard OCaml distribution also includes a number of camlp4 extensions, including one that provides list comprehensions:
<syntaxhighlight lang="ocaml"># #camlp4o;;
# #require "camlp4.listcomprehension";;
/home/user//.opam/4.06.1+trunk+flambda/lib/ocaml/camlp4/Camlp4Parsers/Camlp4ListComprehension.cmo: loaded
# [ x * 2 | x <- [1;2;3;4] ];;
- : int list = [2; 4; 6; 8]
# [ x * 2 | x <- [1;2;3;4]; x > 2 ];;
- : int list = [6; 8]</syntaxhighlight>
 
=={{header|Oz}}==
Line 1,929 ⟶ 1,947:
 
=={{header|Python}}==
<syntaxhighlight lang="python">
List comprehension:
import itertools
 
n = 20
<syntaxhighlight lang="python">[(x,y,z) for x in xrange(1,n+1) for y in xrange(x,n+1) for z in xrange(y,n+1) if x**2 + y**2 == z**2]</syntaxhighlight>
 
A Python generator expression (note the outer round brackets), returns an iterator over the same result rather than an explicit list:
 
<syntaxhighlight lang="python">((x,y,z) for x in xrange(1,n+1) for y in xrange(x,n+1) for z in xrange(y,n+1) if x**2 + y**2 == z**2)</syntaxhighlight>
 
A slower but more readable version:
 
# List comprehension:
<syntaxhighlight lang="python">[(x, y, z) for (x, y, z) in itertools.product(xrange(1,n+1),repeat=3) if x**2 + y**2 == z**2 and x <= y <= z]</syntaxhighlight>
[(x,y,z) for x in xrange(1,n+1) for y in xrange(x,n+1) for z in xrange(y,n+1) if x**2 + y**2 == z**2]
 
# A Python generator expression (note the outer round brackets),
Or as an iterator:
# returns an iterator over the same result rather than an explicit list:
((x,y,z) for x in xrange(1,n+1) for y in xrange(x,n+1) for z in xrange(y,n+1) if x**2 + y**2 == z**2)
 
# A slower but more readable version:
<syntaxhighlight lang="python">((x, y, z) for (x, y, z) in itertools.product(xrange(1,n+1),repeat=3) if x**2 + y**2 == z**2 and x <= y <= z)</syntaxhighlight>
[(x, y, z) for (x, y, z) in itertools.product(xrange(1,n+1),repeat=3) if x**2 + y**2 == z**2 and x <= y <= z]
 
# Or as an iterator:
Alternatively we shorten the initial list comprehension but this time without compromising on speed. First we introduce a generator which generates all triplets:
((x, y, z) for (x, y, z) in itertools.product(xrange(1,n+1),repeat=3) if x**2 + y**2 == z**2 and x <= y <= z)
 
# Alternatively we shorten the initial list comprehension but this time without compromising on speed.
<syntaxhighlight lang="python">def triplets(n):
# First we introduce a generator which generates all triplets:
def triplets(n):
for x in xrange(1, n + 1):
for y in xrange(x, n + 1):
for z in xrange(y, n + 1):
yield x, y, z</syntaxhighlight>
 
# Apply this to our list comprehension gives:
[(x, y, z) for (x, y, z) in triplets(n) if x**2 + y**2 == z**2]
 
# Or as an iterator:
<syntaxhighlight lang="python">[(x, y, z) for (x, y, z) in triplets(n) if x**2 + y**2 == z**2]</syntaxhighlight>
((x, y, z) for (x, y, z) in triplets(n) if x**2 + y**2 == z**2)
 
# More generally, the list comprehension syntax can be understood as a concise syntactic sugaring
Or as an iterator:
# of a use of the list monad, in which non-matches are returned as empty lists, matches are wrapped
# as single-item lists, and concatenation flattens the output, eliminating the empty lists.
 
# The monadic 'bind' operator for lists is concatMap, traditionally used with its first two arguments flipped.
<syntaxhighlight lang="python">((x, y, z) for (x, y, z) in triplets(n) if x**2 + y**2 == z**2)</syntaxhighlight>
# The following three formulations of a '''pts''' (pythagorean triangles) function are equivalent:
 
from functools import (reduce)
More generally, the list comprehension syntax can be understood as a concise syntactic sugaring of a use of the list monad, in which non-matches are returned as empty lists, matches are wrapped as single-item lists, and concatenation flattens the output, eliminating the empty lists.
 
The monadic 'bind' operator for lists is concatMap, traditionally used with its first two arguments flipped. The following three formulations of a '''pts''' (pythagorean triangles) function are equivalent:
 
<syntaxhighlight lang="python">from functools import (reduce)
from operator import (add)
 
 
# pts :: Int -> [(Int, Int, Int)]
Line 2,023 ⟶ 2,042:
 
 
main()</syntaxhighlight>
</syntaxhighlight>
{{Out}}
<pre>[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
Line 2,061 ⟶ 2,081:
Raku has single-dimensional list comprehensions that fall out naturally from nested modifiers; multidimensional comprehensions are also supported via the cross operator; however, Raku does not (yet) support multi-dimensional list comprehensions with dependencies between the lists, so the most straightforward way is currently:
<syntaxhighlight lang="raku" line>my $n = 20;
say gather for 1..$n -> $x {
for $x..$n -> $y {
for $y..$n -> $z {
Line 2,068 ⟶ 2,088:
}
}</syntaxhighlight>
{{out}}
<pre>((3 4 5) (5 12 13) (6 8 10) (8 15 17) (9 12 15) (12 16 20))</pre>
 
Note that <tt>gather</tt>/<tt>take</tt> is the primitive in Raku corresponding to generators or coroutines in other languages. It is not, however, tied to function call syntax in Raku. We can get away with that because lists are lazy, and the demand for more of the list is implicit; it does not need to be driven by function calls.
Line 2,566 ⟶ 2,588:
 
<syntaxhighlight lang="ti89b">seq(x^2, x, 1, 4)</syntaxhighlight>
 
=={{header|Transd}}==
The language's construct for list comprehension closely follows the established set-builder notation:
 
<pre>
FOR x IN <SET>
WHERE predicate(x)
PROJECT f(x)
</pre>
The special form of 'for' construct performs list comprehension and returns a collection with selected elements.
 
In basic form, the returned vector is created and filled automatically:
 
<syntaxhighlight lang="Scheme">
(with v (for x in Range(10)
project (* x x))
(textout v))
</syntaxhighlight>
{{out}}
<pre>
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
</pre>
 
Basic form with 'WHERE' clause:
 
<syntaxhighlight lang="Scheme">
(with v (for x in Range(10)
where (mod x 2)
project Vector<ULong>([x,(* x x)]))
(textout v))
</syntaxhighlight>
{{out}}
<pre>
[[1, 1], [3, 9], [5, 25], [7, 49], [9, 81]]
</pre>
 
In cases when more customized behaviour is required, there is an option to define
and fill the returned collection directly:
 
<syntaxhighlight lang="Scheme">
(with v (for x in Range(1 n) project<Vector<ULong>>
(for y in Range(x n) do
(for z in Range(y n)
where (== (* z z) (+ (* y y) (* x x)))
do (append @projRes Vector<ULong>([x,y,z])))))
(textout "Pythagorean triples:\n" v))
}</syntaxhighlight>
{{out}}
<pre>
Pythagorean triples:
[[3, 4, 5], [5, 12, 13], [6, 8, 10], [9, 12, 15]]
</pre>
 
=={{header|Visual Basic .NET}}==
Line 2,633 ⟶ 2,707:
=={{header|Wren}}==
Using a generator.
<syntaxhighlight lang="ecmascriptwren">var pythTriples = Fiber.new { |n|
(1..n-2).each { |x|
(x+1..n-1).each { |y|
9,482

edits