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; |
||
</ |
</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}}== |
||
< |
<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]); |
||
</ |
</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: |
||
< |
<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; |
||
</ |
</lang> |
||
Using the standard library |
Using the standard library |
||
< |
<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()); |
||
</ |
</lang> |
||
Instead of < |
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: |
||
< |
<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) |
||
</ |
</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: |
||
< |
<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)) |
||
</ |
</lang> |
||
which are incorrect since < |
which are incorrect since <code>(make-the-distinct-thing)</code> is only evaluated once. A common correct version is: |
||
< |
<lang lisp> |
||
(loop repeat n collect (make-the-distinct-thing)) |
(loop repeat n collect (make-the-distinct-thing)) |
||
</ |
</lang> |
||
which evaluates < |
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 < |
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. |
||
< |
<lang haskell> |
||
replicateM n makeTheDistinctThing |
replicateM n makeTheDistinctThing |
||
</ |
</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 |
||
< |
<lang haskell> |
||
mapM makeTheDistinctThing [1..n] |
mapM makeTheDistinctThing [1..n] |
||
</ |
</lang> |
||
An incorrect version: |
An incorrect version: |
||
< |
<lang haskell> |
||
do x <- makeTheDistinctThing |
do x <- makeTheDistinctThing |
||
return (replicate n x) |
return (replicate n x) |
||
</ |
</lang> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{works with|Java|1.5+}} |
{{works with|Java|1.5+}} |
||
simple array: |
simple array: |
||
< |
<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 |
||
</ |
</lang> |
||
simple list: |
simple list: |
||
< |
<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 |
||
</ |
</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.). |
||
< |
<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)); |
||
} |
} |
||
</ |
</lang> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
Line 171: | Line 171: | ||
Incorrect: |
Incorrect: |
||
< |
<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 *) |
||
</ |
</lang> |
||
which is incorrect since < |
which is incorrect since <code>new foo</code> is only evaluated once. A correct version is: |
||
< |
<lang ocaml> |
||
Array.init n (fun _ -> new foo);; |
Array.init n (fun _ -> new foo);; |
||
</ |
</lang> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
incorrect: |
incorrect: |
||
< |
<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 |
||
</ |
</lang> |
||
which is incorrect since < |
which is incorrect since <code>Foo->new</code> is only evaluated once. |
||
A correct version is: |
A correct version is: |
||
< |
<lang perl> |
||
map { Foo->new } 1 .. $n; |
map { Foo->new } 1 .. $n; |
||
</ |
</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: |
||
< |
<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 |
||
</ |
</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: |
||
< |
<lang python> |
||
[Foo() for i in xrange(n)] |
[Foo() for i in xrange(n)] |
||
</ |
</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: |
||
< |
<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) |
||
</ |
</lang> |
||
which are incorrect since < |
which are incorrect since <code>Foo.new</code> is only evaluated once. A common correct version is: |
||
< |
<lang ruby> |
||
Array.new(n) { Foo.new } |
Array.new(n) { Foo.new } |
||
</ |
</lang> |
||
which evaluates < |
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. |