1

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:

enter image description here

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?

kleite
  • 195
  • 1
  • 16
  • I put a bounty in the similar windows question, [How to read from stdin and write to stdout of WindowsProcess in Pharo/Squeak?](https://stackoverflow.com/questions/65229887/how-to-read-from-stdin-and-write-to-stdout-of-windowsprocess-in-pharo-squeak), so pharoers locked to windows can benefit as well. – kleite Mar 16 '21 at 15:36
  • 1
    Did you take a look at the Bag class? That can count occurrences – Stephan Eggermont Mar 23 '21 at 17:13
  • @StephanEggermont No, I didn't know this. Thank you. I will look into it. – kleite Mar 23 '21 at 17:26
  • 1
    Apparently nobody ported `OSProcess` to Pharo 8 so probably it is abandoned @Pharo. Your best best is to use `LibC` in Pharo on Windows. Maybe in the future you could use `OSSubprocess`. – tukan Mar 25 '21 at 11:58

0 Answers0