Multiple distinct objects: Difference between revisions

markup fixes: <code> to <lang>, <tt> to <code>
(added perl)
(markup fixes: <code> to <lang>, <tt> to <code>)
Line 9:
 
=={{header|Ada}}==
<lang ada>
A : array (1..N) of T;
</adalang>
Here N can be unknown until run-time. T is any constrained type.
=={{header|C}}==
 
<codelang c>
foo *foos = malloc(n * sizeof(*foos));
for (int i = 0; i < n; i++)
init_foo(&foos[i]);
</codelang>
 
(Or if no particular initialization is needed, skip that part, or use <tt>calloc</tt>.)
Line 25:
=={{header|C++}}==
Using only language primitives:
<codelang cpp>
// 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
Line 31:
// when you don't need the objects any more, get rid of them
delete[] p;
</codelang>
 
Using the standard library
<codelang cpp>
#include <vector>
 
Line 48:
for (int i = 0; i < n; ++i)
vec3.push_back(makeDistinctObject());
</codelang>
Instead of <ttcode>vector</ttcode>, <ttcode>deque</ttcode> or <ttcode>list</ttcode> 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:
<codelang cpp>
#include <vector>
 
Line 89:
// set the pointers to NULL after deleting; again, using a smart pointer
// would remove this need)
</codelang>
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}}==
The mistake is often written as one of these:
<codelang lisp>
(make-list n :initial-element (make-the-distinct-thing))
(make-array n :initial-element (make-the-distinct-thing))
</codelang>
which are incorrect since <ttcode>(make-the-distinct-thing)</ttcode> is only evaluated once. A common correct version is:
<codelang lisp>
(loop repeat n collect (make-the-distinct-thing))
</codelang>
which evaluates <ttcode>(make-the-distinct-thing)</ttcode> <var>n</var> times and collects each result in a list.
 
=={{header|Haskell}}==
 
Below, we are assuming that <tt>makeTheDistinctThing</tt> is a monadic expression (i.e. it has type <ttcode>m a</ttcode> where <ttcode>m</ttcode> is some monad, like <ttcode>IO</ttcode> or <ttcode>ST</ttcode>), 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.
<codelang haskell>
replicateM n makeTheDistinctThing
</codelang>
in an appropriate do block. If it is distinguished by, say, a numeric label, one could write
<codelang haskell>
mapM makeTheDistinctThing [1..n]
</codelang>
 
An incorrect version:
<codelang haskell>
do x <- makeTheDistinctThing
return (replicate n x)
</codelang>
 
=={{header|Java}}==
{{works with|Java|1.5+}}
simple array:
<codelang java>
Foo[] foos = new Foo[n]; // all elements initialized to null
for (int i = 0; i < foos.length; i++)
Line 132:
Foo[] foos_WRONG = new Foo[n];
Arrays.fill(foos, new Foo()); // new Foo() only evaluated once
</codelang>
 
simple list:
<codelang java5>
List<Foo> foos = new ArrayList<Foo>();
for (int i = 0; i < n; i++)
Line 142:
// incorrect:
List<Foo> foos_WRONG = Collections.nCopies(n, new Foo()); // new Foo() only evaluated once
</codelang>
 
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.).
<codelang java5>
public static <E> List<E> getNNewObjects(int n, Class<? extends E> c){
List<E> ans = new LinkedList<E>();
Line 165:
return getNNewObjects(n, Class.forName(className));
}
</codelang>
 
=={{header|OCaml}}==
Line 171:
 
Incorrect:
<codelang ocaml>
Array.make n (new foo);; (* here (new foo) can be any expression that returns a new object, record, array, or string *)
</codelang>
which is incorrect since <ttcode>new foo</ttcode> is only evaluated once. A correct version is:
<codelang ocaml>
Array.init n (fun _ -> new foo);;
</codelang>
 
=={{header|Perl}}==
incorrect:
<codelang perl>
(Foo->new) x $n # here Foo->new can be any expression that returns a reference representing a new object
</codelang>
which is incorrect since <ttcode>Foo->new</ttcode> is only evaluated once.
 
A correct version is:
<codelang perl>
map { Foo->new } 1 .. $n;
</codelang>
which evaluates <tt>Foo->new</tt> <var>$n</var> times and collects each result in a list.
 
=={{header|Python}}==
The mistake is often written as:
<codelang python>
[Foo()] * n # here Foo() can be any expression that returns a new object
</codelang>
which is incorrect since <tt>Foo()</tt> is only evaluated once. A common correct version is:
<codelang python>
[Foo() for i in xrange(n)]
</codelang>
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}}==
The mistake is often written as one of these:
<codelang ruby>
[Foo.new] * n # here Foo.new can be any expression that returns a new object
Array.new(n, Foo.new)
</codelang>
which are incorrect since <ttcode>Foo.new</ttcode> is only evaluated once. A common correct version is:
<codelang ruby>
Array.new(n) { Foo.new }
</codelang>
which evaluates <ttcode>Foo.new</ttcode> <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.