Smalltalk, displaying OrderedCollection to List Widget - smalltalk

Hi I have an ordered collection of strings which I'm trying to display on a list widget.
I do the following:
self displayWidget list: coll.
where displayWidget is a List Widget and coll is the OrderedCollection containing the strings. It will display it, but it displays it in a single line.
Instead of getting
line one
line two
line three
I get:
line oneline twoline three
I'm using visual works.*

Inside list: you probably want something similar to
coll do: [:element | Transcript show element; cr]
When you send do: [:e | ...] to a collection it evaluates the block once for each element in the collection, each time passing the element into element.
Each time I'm sending cr to Transcript to add a carriage return after each element.

You can iterate the collection and send withCRs message to the Strings.
Here is an simple example:
| i |
i:= 0.
[i < 5] whileTrue: [ Transcript show: 'Hello world.\' withCRs.
i := i +1.
]
withCRs method replace each \ ocurrence for a new line and carry return.
Hope it helps you.

Related

Loop and List in Python

With below code, I was expecting to swap two lists and was expecting all the elements from 'names' list to 'Excluded_list'using Pop() function. But it is not working expectedly, can someone please tell the issue with below code ??
names=['Ram','Sham','Mohan','John','Kuldeep']
Excluded_list=[]
print('names list',names)
print('Excluded list ',Excluded_list)
Code to swap/reprint lists
for name in names:
Excluded_list.append(names.pop())
print('names list',names)
print('Excluded list ',Excluded_list)
You are modifying "names" in the for-loop, which means that the "for name in names" does not evaluate as you expect.
Replace the for-loop with a while-loop.
while len(names):
Excluded_list.append(names.pop())

Stringtemplate 4 (st4) - Render if string is not empty

I need an st4 expression to render an element if a string is not empty:
<if(theString)>...<endif> does not work - it seems to only work for arrays.
I've tried if(theString.length > 0) and all kinds of stuff, but it looks like it this only works for variables that are not set or for arrays.
I am iterating over a list and rendering this, so I could have values in the middle that are empty strings that I don't want to render anything at all for.
I've been struggling trying to find the ability to compare strings in a conditional. I want to be able to test for a condition like obj.Name == 'foobar'. Not sure if stringtemplate-4 can do it?
To render if the value is not null you should be able to do the following.
$if(obj.Name)$ $obj.Name$ $endif$ // prints the Name property of obj
But to find the length of a string you can use strlen function.
ie.
// obj.Name = "foobar", prints 'Length of Name is 6'
$if(strlen(obj.Name))$ Length of Name is $strlen(obj.Name)$ $endif$
Here is a helpful list of all the functions:
https://github.com/antlr/stringtemplate4/blob/master/doc/cheatsheet.md

Converting Ordered Collection to Literal Array

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?
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.
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
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)
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.

Print a SortedCollection to screen using keysAndValueDo (smalltalk)

Hello i'm learning and am new to smalltalk and I'm trying to print my SortedCollection to screen trying to use keysAndValueDo but im not sure how its done, if anyone could give me a general example that would be great
Part 1 - Displaying to the screen
The most straight forward way to print to the screen in a GUI-based Smalltalk is to use the message:
Transcript show: 'some text'
(The Transcript is a system object that displays into a scrollable window).
To make sure there is a newline before each line of display text, we send the message cr to the Transcript
Transcript cr.
Transcript show: 'some text'.
A shorthand method, that saves us re-typing Transcript over and over, is to send Transcript a series of messages one after another. This is called a message cascade. Each time we end a message in ; it means send to the same receiver as the last message was sent to.
We can then shorten this again, as Smalltalk pays no attention to newlines in expressions.
The final display message cascade becomes:
Transcript cr; show: 'some text'.
Part 2: Enumerating aSortedCollection using keysAndValuesDo:
This keyword message is SequencableCollectionand its method header is:
keysAndValuesDo: aBlock
"Enumerate the receiver with all the keys (aka indices) and values."
(It works the same way in Dolphin, and in Squeak and its derivatives, Pharo and Cuis).
The keyword message keysAndValuesDo: takes a block argument.
A block is an anonymous object, with one method. Its method is defined between a matched pair of square brackets - a [ ... ] pair.
In this case, we need a local variable in the block for the key of each element of the collection, and another local variable for the value of each element.
We can call them anything we like, and in this case, it is the order that they appear in that is important. keysAndValuesDo: will put the element's key into the first local variable in the block, and will put the element's value into the second local variable in the block.
Local variables in a block are declared at the start of the block, and each variable name is identified by prefixing it with :. The local variable declarations are ended with a |.
The block then looks like
[:local1 :local2 |
"do something for each element, with the key in local1 and the value in local2"
]
I prefer meaningful local variable names, so I'll use eachKey and eachValue.
Part 3: Putting it all together
To enumerate through mySortedCollection
"Declare the mySortedCollection variable"
|mySortedCollection|
"Initialise the collection"
mySortedCollection := SortedCollection new.
"add in some data to the collection"
mySortedCollection add: ('First') ;
add: ('Second') ;
add: ('Third').
"Enumerate through the collection, displaying to the Transcript window"
mySortedCollection keysAndValuesDo:
[:eachKey :eachValue |
Transcript cr; show: eachKey; show: ' '; show: eachValue
] .
Paste the code into a Workspace (known as a Playground in Pharo, from version 4.0 onwards). Select the text. Once selected, right-click (on a two or three button mouse) and select "Do it" from the menu. Or use Ctrl-d as a keyboard shortcut. (The exact chording key may vary on your platform)
Final notes
In a SortedCollection or an OrderedCollection, the key is the index. The value is what is stored at element[index].
In a Dictionary, the key of the element is the key, and the value of the element is the value.
SortedCollections are sorted in order of the element values, according to the definition of the collections sort block. In the absence of a custom sort block, they will be added in ascending order. 'First', 'Second' and 'Third' are, coincidentally, in alphabetical order. It happens to work out nicely in this example.
The following example works with Pharo Smalltalk, other Smalltalk implementation might work similar.
First, look at existing print methods as examples. In case of SortedCollection, you find them in the printing protocol of its superclass Collection.
You will find that the printing of elements is defined in printElementsOn:. So you could overwrite this method in SortedCollection.
Here is a printElementsOn: method that will use keysAndValuesDo:, as you were asking for:
printElementsOn: aStream
aStream nextPut: $(.
self keysAndValuesDo: [:key :value |
aStream
nextPut: $(;
print: key;
nextPut: $:;
space;
print: value;
nextPut: $)].
aStream nextPut: $)
Now a collection that before printed:
"a SortedCollection(1 2 3 3 5 10)"
will print:
"a SortedCollection((1: 1)(2: 2)(3: 3)(4: 3)(5: 5)(6: 10))"

How to, in smalltalk,append two arrays

Had to change this up. I have two arrays and I want to essentially concatenate them into one array.
completearray:= completearray, temparray."concatenate the new array to the existing one"
How do I get this working please? Thanks.
Your code works in Squeak, so what is the problem?
anArray := #(1 2 3 4).
anotherArray := #(5 6 7).
anArray, anotherArray "Returns #(1 2 3 4 5 6 7)"
if your code doesn't run, you probably don't have an Array object in "completearray", but instead have an object that doesn't respond to #, (i.e. nil doesn't respond to #,).
you are adding a character ($,), but you have to add a string with #, (cancat).
try: yourString , ','
I don't know, why it may not work in your version of VisualWorks, but you can try to do this:
completearray addAll: temparray.
Source, just in case:
addAll: collection
^ collection
do: [ :element | self add: element];
yourself