I was trying to contribute a Pharo 8 solution to this as a exercise. It's a simple sorted word count challenge. For example, one python solution is:
import sys
counts = {}
for line in sys.stdin:
words = line.lower().split()
for word in words:
counts[word] = counts.get(word, 0) + 1
pairs = sorted(counts.items(), key=lambda kv: kv[1], reverse=True)
for word, count in pairs:
print(word, count)
Where the sys module allows us to have the text piped from terminal, instead of manually opening the file from inside the script, with a path and a filename.
So far I was able to write a Pharo 8 solution to this challenge by loading the file from within Pharo:
Object subclass: #WordCounter
instanceVariableNames: 'contents sortedResults'
classVariableNames: ''
package: 'MyWordCounter'
WordCounter>>readFile: aPath
"Takes a filepath and reads the contents of the file"
| stream |
contents := OrderedCollection new.
stream := aPath asFileReference readStream.
[ stream atEnd ] whileFalse: [ contents add: stream nextLine asLowercase substrings ].
stream close.
WordCounter>>rank
"Counts the words and sorts the results"
| dict |
dict := Dictionary new.
contents do:
[ :line | line do:
[ :word | dict at: word put: (dict at: word ifAbsent: 0) + 1 ] ].
sortedResults := dict associations asSortedCollection: [ :a1 :a2 | a1 value > a2 value ]
WordCounter>>show
"Print the sorted results to transcript"
Transcript clear.
sortedResults do: [ :each | Transcript show: each key; show: ' '; show: each value; cr ]
With this class defined, now I can get the results by doing this code in playground:
| obj |
obj := WordCounter new.
obj readFile: '/home/user/WordCounterPharo/kjvbible_x10.txt'.
obj rank; show.
I think I got the algorithm working properly, as shown bellow:
Now the problem is, I'd like to modify this program, so that, instead of reading data with a filepath, and writing the results to transcript, it just ingested data from a pipe and printed the results back to the terminal, in Linux. I know that Pharo has command line capabilities, as one of the first examples I was presented when I downloaded Pharo was running this in the terminal:
./pharo Pharo.image eval "42 factorial"
So the end result I want is something like this mock output:
user@PC:~$ ./pharo Pharo.image WordCounter < kjvbible_x10.txt
user@PC:~$ the 640150
user@PC:~$ and 513130
user@PC:~$ of 346340
user@PC:~$ to 135670
user@PC:~$ that 127840
user@PC:~$ in 125030
user@PC:~$ he 102610
user@PC:~$ shall 98380
user@PC:~$ unto 89870
user@PC:~$ for 88100
user@PC:~$ i 87080
user@PC:~$ his 84500
user@PC:~$ a 81760
user@PC:~$ they 72970
user@PC:~$ be 68540
...
But I still could not figure out how to do it myself. I tried to follow this answer by @tukan, but I suspect the class used, OSProcess, was removed since then, as Pharo 8 doesn't recognize it (coloured red in playground, returning unknow variable error when inspected). I also noticed there is a similar question about pharo under Windows, but is unanswered.
Bonus question: While writing this, I noticed to share code here, I had to copy and past code on a method by method basis. That could be a bit cumbersome if it were a large class (mine fortunately has only 3 methods). Is there a easier way to do it, all at once?