1

I have an ordered collection that I would like to convert into a literal array. Below is the ordered collection and the desired result, respectively:

an OrderedCollection(1 2 3)
#(1 2 3)

What would be the most efficient way to achieve this?

AnimalTesting
  • 127
  • 2
  • 10

4 Answers4

6

The message asArray will create and Array from the OrderedCollection:

    anOrderedCollection asArray

and this is probably what you want.

However, given that you say that you want a literal array it might happen that you are looking for the string '#(1 2 3)' instead. In that case I would use:

    ^String streamContents: [:stream | aCollection asArray storeOn: stream]

where aCollection is your OrderedCollection.

In case you are not yet familiar with streamContents: this could be a good opportunity to learn it. What it does in this case is equivalent to:

    stream := '' writeStream.
    aCollection asArray storeOn: stream.
    ^stream contents

in the sense that it captures the pattern:

    stream := '' writeStream.
    <some code here>
    ^stream contents

which is fairly common in Smalltalk.

UPDATE

Maybe it would help if we clarify a little bit what do we mean literal arrays in Smalltalk. Consider the following two methods

method1
  ^Array with: 1 with: 2 with: 3

method2
  ^#(1 2 3)

Both methods answer with the same array, the one with entries 1, 2 and 3. However, the two implementations are different. In method1 the array is created dynamically (i.e., at runtime). In method2 the array is created statically (i.e., at compile time). In fact when you accept (and therefore compile) method2 the array is created and saved into the method. In method1instead, there is no array and the result is created every time the method is invoked.

Therefore, you would only need to create the string '#(1 2 3)' (i.e., the literal representation of the array) if you were generating Smalltalk code dynamically.

Leandro Caniglia
  • 14,495
  • 4
  • 29
  • 51
5

You can not convert an existing object into a literal array. To get a literal array you'd have to write it using the literal array syntax in your source code.

However, I believe you just misunderstood what literal array means, and you are infact just looking for an array.

A literal array is just an array that (in Pharo and Squeak [1]) is created at compile time, that is, when you accept the method.

To turn an ordered collection into an array you use asArray.

Just inspect the results of

#(1 2 3).
(OrderedCollection with: 1 with: 2 with: 3) asArray.

You'll see that both are equal.

[1]: see here for an explanation: https://stackoverflow.com/a/29964346/1846474

Community
  • 1
  • 1
eMBee
  • 793
  • 6
  • 16
  • @bert though i wonder, isn't the fact that a literal array is created at compile time an implementation detail? as http://stackoverflow.com/a/29964346/1846474 explains, what is significant is that we can not rely on literal arrays creating distinct objects or not. – eMBee Jan 25 '16 at 14:58
1

In Pharo 5.0 (a beta release) you can do:

    | oc ary |
oc := OrderedCollection new: 5.
oc addAll: #( 1 2 3 4 5).
Transcript show: oc; cr.
ary := oc asArray.
Transcript show: ary; cr.

The output on the transcript is:

an OrderedCollection(1 2 3 4 5)
#(1 2 3 4 5)
John Pfersich
  • 135
  • 2
  • 7
0

the literalArray encoding is a kind of "poor man's" persistency encoding to get a representation, which can reconstruct the object from a compilable literal array. I.e. an Array of literals, which by using decodeAsLiteralArray reconstructs the object.

It is not a general mechanism, but was mainly invented to store UI specifications in a method (see UIBuilder).

Only a small subset of classes support this kind of encoding/decoding, and I am not sure if OrderedCollection does it in any dialect. In the one I use (ST/X), it does not, and I get a doesNotUnderstand.

However, it would be relatively easy to add the required encoder/decoder and make it possible.

But, as I said, its intended use is for UIspecs, not as a general persistency (compiled-object persistency) mechanism. So I rather not recommend using it for such.

blabla999
  • 3,130
  • 22
  • 24