Multiple distinct objects: Difference between revisions

Content added Content deleted
(added perl)
(markup fixes: <code> to <lang>, <tt> to <code>)
Line 9: Line 9:


=={{header|Ada}}==
=={{header|Ada}}==
<ada>
<lang ada>
A : array (1..N) of T;
A : array (1..N) of T;
</ada>
</lang>
Here N can be unknown until run-time. T is any constrained type.
Here N can be unknown until run-time. T is any constrained type.
=={{header|C}}==
=={{header|C}}==


<code c>
<lang c>
foo *foos = malloc(n * sizeof(*foos));
foo *foos = malloc(n * sizeof(*foos));
for (int i = 0; i < n; i++)
for (int i = 0; i < n; i++)
init_foo(&foos[i]);
init_foo(&foos[i]);
</code>
</lang>


(Or if no particular initialization is needed, skip that part, or use <tt>calloc</tt>.)
(Or if no particular initialization is needed, skip that part, or use <tt>calloc</tt>.)
Line 25: Line 25:
=={{header|C++}}==
=={{header|C++}}==
Using only language primitives:
Using only language primitives:
<code cpp>
<lang cpp>
// this assumes T is a default-constructible type (all built-in types are)
// this assumes T is a default-constructible type (all built-in types are)
T* p = new T[n]; // if T is POD, the objects are uninitialized, otherwise they are default-initialized
T* p = new T[n]; // if T is POD, the objects are uninitialized, otherwise they are default-initialized
Line 31: Line 31:
// when you don't need the objects any more, get rid of them
// when you don't need the objects any more, get rid of them
delete[] p;
delete[] p;
</code>
</lang>


Using the standard library
Using the standard library
<code cpp>
<lang cpp>
#include <vector>
#include <vector>


Line 48: Line 48:
for (int i = 0; i < n; ++i)
for (int i = 0; i < n; ++i)
vec3.push_back(makeDistinctObject());
vec3.push_back(makeDistinctObject());
</code>
</lang>
Instead of <tt>vector</tt>, <tt>deque</tt> or <tt>list</tt> can be used. Note that with standard containers containing the object type itself (instead of a pointer), you don't need to explicitly destroy the objects.
Instead of <code>vector</code>, <code>deque</code> or <code>list</code> can be used. Note that with standard containers containing the object type itself (instead of a pointer), you don't need to explicitly destroy the objects.


For polymorphic objects:
For polymorphic objects:
<code cpp>
<lang cpp>
#include <vector>
#include <vector>


Line 89: Line 89:
// set the pointers to NULL after deleting; again, using a smart pointer
// set the pointers to NULL after deleting; again, using a smart pointer
// would remove this need)
// would remove this need)
</code>
</lang>
Of course, also in this case one can use the other sequence containers or plain new/delete instead of <tt>vector</tt>.
Of course, also in this case one can use the other sequence containers or plain new/delete instead of <tt>vector</tt>.


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
The mistake is often written as one of these:
The mistake is often written as one of these:
<code lisp>
<lang lisp>
(make-list n :initial-element (make-the-distinct-thing))
(make-list n :initial-element (make-the-distinct-thing))
(make-array n :initial-element (make-the-distinct-thing))
(make-array n :initial-element (make-the-distinct-thing))
</code>
</lang>
which are incorrect since <tt>(make-the-distinct-thing)</tt> is only evaluated once. A common correct version is:
which are incorrect since <code>(make-the-distinct-thing)</code> is only evaluated once. A common correct version is:
<code lisp>
<lang lisp>
(loop repeat n collect (make-the-distinct-thing))
(loop repeat n collect (make-the-distinct-thing))
</code>
</lang>
which evaluates <tt>(make-the-distinct-thing)</tt> <var>n</var> times and collects each result in a list.
which evaluates <code>(make-the-distinct-thing)</code> <var>n</var> times and collects each result in a list.


=={{header|Haskell}}==
=={{header|Haskell}}==


Below, we are assuming that <tt>makeTheDistinctThing</tt> is a monadic expression (i.e. it has type <tt>m a</tt> where <tt>m</tt> is some monad, like <tt>IO</tt> or <tt>ST</tt>), and we are talking about distinctness in the context of the monad. Otherwise, this task is pretty meaningless in Haskell, because Haskell is referentially transparent (so two values that are equal to the same expression are necessarily not distinct) and all values are immutable.
Below, we are assuming that <tt>makeTheDistinctThing</tt> is a monadic expression (i.e. it has type <code>m a</code> where <code>m</code> is some monad, like <code>IO</code> or <code>ST</code>), and we are talking about distinctness in the context of the monad. Otherwise, this task is pretty meaningless in Haskell, because Haskell is referentially transparent (so two values that are equal to the same expression are necessarily not distinct) and all values are immutable.
<code haskell>
<lang haskell>
replicateM n makeTheDistinctThing
replicateM n makeTheDistinctThing
</code>
</lang>
in an appropriate do block. If it is distinguished by, say, a numeric label, one could write
in an appropriate do block. If it is distinguished by, say, a numeric label, one could write
<code haskell>
<lang haskell>
mapM makeTheDistinctThing [1..n]
mapM makeTheDistinctThing [1..n]
</code>
</lang>


An incorrect version:
An incorrect version:
<code haskell>
<lang haskell>
do x <- makeTheDistinctThing
do x <- makeTheDistinctThing
return (replicate n x)
return (replicate n x)
</code>
</lang>


=={{header|Java}}==
=={{header|Java}}==
{{works with|Java|1.5+}}
{{works with|Java|1.5+}}
simple array:
simple array:
<code java>
<lang java>
Foo[] foos = new Foo[n]; // all elements initialized to null
Foo[] foos = new Foo[n]; // all elements initialized to null
for (int i = 0; i < foos.length; i++)
for (int i = 0; i < foos.length; i++)
Line 132: Line 132:
Foo[] foos_WRONG = new Foo[n];
Foo[] foos_WRONG = new Foo[n];
Arrays.fill(foos, new Foo()); // new Foo() only evaluated once
Arrays.fill(foos, new Foo()); // new Foo() only evaluated once
</code>
</lang>


simple list:
simple list:
<code java5>
<lang java5>
List<Foo> foos = new ArrayList<Foo>();
List<Foo> foos = new ArrayList<Foo>();
for (int i = 0; i < n; i++)
for (int i = 0; i < n; i++)
Line 142: Line 142:
// incorrect:
// incorrect:
List<Foo> foos_WRONG = Collections.nCopies(n, new Foo()); // new Foo() only evaluated once
List<Foo> foos_WRONG = Collections.nCopies(n, new Foo()); // new Foo() only evaluated once
</code>
</lang>


Generic version for class given at runtime:
Generic version for class given at runtime:


It's not pretty but it gets the job done. The first method here is the one that does the work. The second method is a convenience method so that you can pass in a <tt>String</tt> of the class name. When using the second method, be sure to use the full class name (ex: "java.lang.String" for "String"). <tt>InstantiationException</tt>s will be thrown when instantiating classes that you would not normally be able to call <tt>new</tt> on (abstract classes, interfaces, etc.).
It's not pretty but it gets the job done. The first method here is the one that does the work. The second method is a convenience method so that you can pass in a <tt>String</tt> of the class name. When using the second method, be sure to use the full class name (ex: "java.lang.String" for "String"). <tt>InstantiationException</tt>s will be thrown when instantiating classes that you would not normally be able to call <tt>new</tt> on (abstract classes, interfaces, etc.).
<code java5>
<lang java5>
public static <E> List<E> getNNewObjects(int n, Class<? extends E> c){
public static <E> List<E> getNNewObjects(int n, Class<? extends E> c){
List<E> ans = new LinkedList<E>();
List<E> ans = new LinkedList<E>();
Line 165: Line 165:
return getNNewObjects(n, Class.forName(className));
return getNNewObjects(n, Class.forName(className));
}
}
</code>
</lang>


=={{header|OCaml}}==
=={{header|OCaml}}==
Line 171: Line 171:


Incorrect:
Incorrect:
<code ocaml>
<lang ocaml>
Array.make n (new foo);; (* here (new foo) can be any expression that returns a new object, record, array, or string *)
Array.make n (new foo);; (* here (new foo) can be any expression that returns a new object, record, array, or string *)
</code>
</lang>
which is incorrect since <tt>new foo</tt> is only evaluated once. A correct version is:
which is incorrect since <code>new foo</code> is only evaluated once. A correct version is:
<code ocaml>
<lang ocaml>
Array.init n (fun _ -> new foo);;
Array.init n (fun _ -> new foo);;
</code>
</lang>


=={{header|Perl}}==
=={{header|Perl}}==
incorrect:
incorrect:
<code perl>
<lang perl>
(Foo->new) x $n # here Foo->new can be any expression that returns a reference representing a new object
(Foo->new) x $n # here Foo->new can be any expression that returns a reference representing a new object
</code>
</lang>
which is incorrect since <tt>Foo->new</tt> is only evaluated once.
which is incorrect since <code>Foo->new</code> is only evaluated once.


A correct version is:
A correct version is:
<code perl>
<lang perl>
map { Foo->new } 1 .. $n;
map { Foo->new } 1 .. $n;
</code>
</lang>
which evaluates <tt>Foo->new</tt> <var>$n</var> times and collects each result in a list.
which evaluates <tt>Foo->new</tt> <var>$n</var> times and collects each result in a list.


=={{header|Python}}==
=={{header|Python}}==
The mistake is often written as:
The mistake is often written as:
<code python>
<lang python>
[Foo()] * n # here Foo() can be any expression that returns a new object
[Foo()] * n # here Foo() can be any expression that returns a new object
</code>
</lang>
which is incorrect since <tt>Foo()</tt> is only evaluated once. A common correct version is:
which is incorrect since <tt>Foo()</tt> is only evaluated once. A common correct version is:
<code python>
<lang python>
[Foo() for i in xrange(n)]
[Foo() for i in xrange(n)]
</code>
</lang>
which evaluates <tt>Foo()</tt> <var>n</var> times and collects each result in a list. This last form is also discussed [[Two-dimensional array (runtime)#Python|here]], on the correct construction of a two dimensional array.
which evaluates <tt>Foo()</tt> <var>n</var> times and collects each result in a list. This last form is also discussed [[Two-dimensional array (runtime)#Python|here]], on the correct construction of a two dimensional array.


=={{header|Ruby}}==
=={{header|Ruby}}==
The mistake is often written as one of these:
The mistake is often written as one of these:
<code ruby>
<lang ruby>
[Foo.new] * n # here Foo.new can be any expression that returns a new object
[Foo.new] * n # here Foo.new can be any expression that returns a new object
Array.new(n, Foo.new)
Array.new(n, Foo.new)
</code>
</lang>
which are incorrect since <tt>Foo.new</tt> is only evaluated once. A common correct version is:
which are incorrect since <code>Foo.new</code> is only evaluated once. A common correct version is:
<code ruby>
<lang ruby>
Array.new(n) { Foo.new }
Array.new(n) { Foo.new }
</code>
</lang>
which evaluates <tt>Foo.new</tt> <var>n</var> times and collects each result in an Array. This last form is also discussed [[Two-dimensional array (runtime)#Ruby|here]], on the correct construction of a two dimensional array.
which evaluates <code>Foo.new</code> <var>n</var> times and collects each result in an Array. This last form is also discussed [[Two-dimensional array (runtime)#Ruby|here]], on the correct construction of a two dimensional array.