Multiple distinct objects: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
(Added Java, changed some code tags to tt tags)
Line 20: Line 20:
<code lisp>(make-list n :initial-element (make-the-distinct-thing))
<code lisp>(make-list n :initial-element (make-the-distinct-thing))
(make-array n :initial-element (make-the-distinct-thing))</code>
(make-array n :initial-element (make-the-distinct-thing))</code>
which are incorrect since <code>(make-the-distinct-thing)</code> is only evaluated once. A common correct version is:
which are incorrect since <tt>(make-the-distinct-thing)</tt> is only evaluated once. A common correct version is:
<code lisp>(loop repeat n collect (make-the-distinct-thing))</code>
<code lisp>(loop repeat n collect (make-the-distinct-thing))</code>
which evaluates <tt>(make-the-distinct-thing)</tt> <var>n</var> times and collects each result in a list.
which evaluates <tt>(make-the-distinct-thing)</tt> <var>n</var> times and collects each result in a list.
Line 30: Line 30:
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>map makeTheDistinctThing [1..n]</code>
<code haskell>map makeTheDistinctThing [1..n]</code>
=={{header|Java}}==
{{works with|Java|1.5+}}
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.
<code java5>public static LinkedList<Object> getNNewObjects(int n, Class c){
LinkedList<Object> ans = new LinkedList<Object>();
try {
for(int i=0;i<n;i++)
ans.add(c.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return ans;
}


public static LinkedList<Object> getNNewObjects(int n, String className)
throws ClassNotFoundException{
return getNNewObjects(n, Class.forName(className));
}</code>
=={{header|Python}}==
=={{header|Python}}==
The mistake is often written as:
The mistake is often written as:
<code python>[Foo()] * n # here Foo() can be any expression that returns a new object</code>
<code python>[Foo()] * n # here Foo() can be any expression that returns a new object</code>
which is incorrect since <code>Foo()</code> 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>[Foo() for i in xrange(n)]</code>
<code python>[Foo() for i in xrange(n)]</code>
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.
Line 42: Line 61:
<code ruby>[Foo.new] * n # here Foo.new can be any expression that returns a new object
<code ruby>[Foo.new] * n # here Foo.new can be any expression that returns a new object
Array.new(n, Foo.new)</code>
Array.new(n, Foo.new)</code>
which are incorrect since <code>Foo.new</code> is only evaluated once. A common correct version is:
which are incorrect since <tt>Foo.new</tt> is only evaluated once. A common correct version is:
<code ruby>Array.new(n) { Foo.new }</code>
<code ruby>Array.new(n) { Foo.new }</code>
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 <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.

Revision as of 16:29, 29 January 2009

Task
Multiple distinct objects
You are encouraged to solve this task according to the task description, using any language you may know.

Create a sequence (array, list, whatever) consisting of n distinct items of the same type. n should be determined at runtime.

By distinct we mean that if they are mutable, changes to one do not affect all others; if there is an appropriate equality operator they are considered unequal; etc. The code need not specify a particular kind of distinction, but do not use e.g. a numeric-range generator which does not generalize.

This task was inspired by the common error of intending to do this, but instead creating a sequence of nreferences to the same mutable object; it might be informative to show the way to do that as well.

This task mostly makes sense for languages operating in the pass-references-by-value style (most object-oriented or 'dynamic' languages).

C

foo *foos = malloc(n * sizeof(*foos)); for (int i = 0; i < n; i++)

 init_foo(&foos[i]);

(Or if no particular initialization is needed, skip that part, or use calloc.)

Common Lisp

The mistake is often written as one of these: (make-list n :initial-element (make-the-distinct-thing)) (make-array n :initial-element (make-the-distinct-thing)) which are incorrect since (make-the-distinct-thing) is only evaluated once. A common correct version is: (loop repeat n collect (make-the-distinct-thing)) which evaluates (make-the-distinct-thing) n times and collects each result in a list.

Haskell

If the creator of the distinct thing is in some monad, then one can write replicateM n makeTheDistinctThing in an appropriate do block. If it is distinguished by, say, a numeric label, one could write map makeTheDistinctThing [1..n]

Java

Works with: Java version 1.5+

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 String of the class name. public static LinkedList<Object> getNNewObjects(int n, Class c){ LinkedList<Object> ans = new LinkedList<Object>(); try { for(int i=0;i<n;i++) ans.add(c.newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return ans; }

public static LinkedList<Object> getNNewObjects(int n, String className) throws ClassNotFoundException{ return getNNewObjects(n, Class.forName(className)); }

Python

The mistake is often written as: [Foo()] * n # here Foo() can be any expression that returns a new object which is incorrect since Foo() is only evaluated once. A common correct version is: [Foo() for i in xrange(n)] which evaluates Foo() n times and collects each result in a list. This last form is also discussed here, on the correct construction of a two dimensional array.

Ruby

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