9

I stumbled upon Smalltalk and further downloaded Pharo, because it was recommended. My first impression is very positive. I wanted to port some simple programs I have written in C++ (my main language), so I can get a feel for Smalltalk.

However, I realized I can't find a simple way to just get some input from the user, e.g. I want to create a console calculator with a REPL loop, but I can't find a way to do this in Pharo. I don't want a gui with buttons, because that is just slow and inconvenient.

Could someone please point out to me how to do simple stuff in Smalltalk, like have the user enter 10 numbers or a command etc.? Do I have to use a different implementation? I'm aiming at std::cin/cout or python's print/input

I know Transcript show:, but that only covers the output portion.

Thanks in advance!

2 Answers 2

12

Getting input from the user is easy, but emulating a line-based console not so much. At least it would be more cumbersome than relying on the GUI, which is not really so slow and inconvenient after all.

The closest input equivalent to Transcript show: would be:

UIManager default request: 'Title of the request'

If you mark this snippet and "print it" or "inspect it", you will see a prompt dialog and can type something into it. When you accept the dialog with OK or return, you will get the entered String back as the return value of request:.

Getting ten numbers could be done like this:

(1 to: 10) collect: [:each | (UIManager default request: 'Enter number ', each asString) asNumber ]

The result will be an Array of the entered numbers.

Or, without using collect: and building up the collection yourself:

numbers := OrderedCollection new.
10 timesRepeat:
    [ numbers add: (UIManager default request: 'Enter next number') asNumber ].
numbers do: [:each | Transcript show: each ].

You might also like UIManager default chooseFrom:. Browse the UIManager class and try out the various methods.


Note that Pharo's playground (called workspace in most other Smalltalks) already does what a REPL does, albeit it is not limited to line-based input. You can type Smalltalk expressions, evaluate them and have the results printed there. I am aware that this information does not give you the experience of porting your calculator app from C++. But I guess the way how the I/O works, or rather the interaction with the user, is not the essence of the programs you are trying to port, right? So you might as well write a class Calculator, in which you implement your calculator app, taking a String as input and returning the resulting number, and then invoke it from the playground by evaluating an expression like the following:

Calculator new calculate: '3 + 4'

If you really, really want to stick to console stuff and miss the benefits of the usual Smalltalk IDE and the experience of learning and using it, you might be better off with GNU Smalltalk. I think there are ways to create console applications with Pharo as well, but I would not recommend that to Smalltalk newcomers and I will leave that answer to someone who has already done it once.

2
  • 1
    Hi, thank you for your detailed answer. I like the input box, especially since it keeps the cursor inside, so I think I could enter expressions quickly and get the result. However, every time I enter something it moves slightly on the screen, which is sort of irritating. Would there be a way to make sure the box stays in place. This happens with chooseForm as well: Every time I select something, it moves a bit.
    – smoothware
    Commented Dec 6, 2018 at 7:06
  • "Would there be a way to make sure the box stays in place." – File a bug? At least, I would consider it one. Commented Dec 8, 2018 at 8:18
1

You can use Pharo and get immediate feedback from the terminal like this:

➜  ./pharo Pharo.image eval "6+5"               
11

Whatever you have between these quotes is being used as source by the compiler and the answered object will be printed to the stdout. In that example, it will be using SmallInteger>>asString behind the scenes.

For making a REPL, you don't need a lot. If you want to take a look, I've made REPLEndpoint using the Zinc HTTP server. In REPLEndpoint >> post you'll find the part where it uses the snippet you send to be evaluated:

snippet := '6+5'.
answer := OpalCompiler new evaluate: snippet.
answer

And answer will be the 11 SmallInteger instance you'd expect.

For additional hints on how your command line based REPL, take a look at the EvaluateCommandLineHandler class as it implements the basic step of what a REPL would do.

Not the answer you're looking for? Browse other questions tagged or ask your own question.