Hacker News new | past | comments | ask | show | jobs | submit login
Pharo Smalltalk Overview (pharo.org)
133 points by 7thaccount on July 20, 2020 | hide | past | favorite | 50 comments



My favourite feature of Pharo (which I believe it inherited from Squeak) from my very limited experience with Smalltalk environments is the ability to search for methods via example.

In the Finder window, you can type an example of an input and the result that you want, for instance `2. -2`, and the system will search for a method to do that operation for you. In this case you'd see the "negated" method which given `2` spits out `-2`.

https://www.youtube.com/watch?v=awAB4zHrlHI


This seems like total magic. How on earth is that implemented?


VPRI has some nice writeups about extending the Squeak method finder in various ways:

Improving on the Method Finder: http://www.vpri.org/pdf/m2009012_fnd_sine.pdf

Method finder for R: http://www.vpri.org/pdf/rn2013002_locatr.pdf

Connections to memoization: http://www.vpri.org/pdf/rn2017002_memoization.pdf

Larger-scale applications: http://www.vpri.org/pdf/tr2014003_callbymeaning.pdf


It turns out the docs [1] try to explain how it works:

> The method finder will take the input objects (receiver and arguments) and perform their permutation to be able to find more results. Then, it will lookup in the receiver's hierarchy the approved and forbidden methods to run on the hierarchy and run them on the permutation of objects.

which sounds like an exhaustive search.

I dug a little further and found this [2] which points to the actual implementation in the `MethodFinder` class. I don't know enough Smalltalk to decipher it :(

[1] https://github.com/pharo-open-documentation/pharo-wiki/issue...

[2] https://csharp.developreference.com/article/18692966/How+doe...


> the actual implementation in the `MethodFinder` class. I don't know enough Smalltalk to decipher it :(

For reference, here is the relevant class: https://github.com/pharo-project/pharo/blob/9ad3324bf8aff11e...

A core snippet is:

   foundPermutationSends := (receiver class
    allSelectorsToTestInMethodFinderWithArity: inputCollection size - 1)
    collect:
     [ :method | MethodFinderSend receiver: receiver deepCopy selector: method withArguments: args deepCopy ].
This means, roughly:

- ask the receiver class (in the example above, the class of 2, which is something like SmallInteger) for "all the selectors (= method names) to test" with the given number of arguments.

- for each of these methods, build a MethodFinderSend object, which is at this point is just a container holding a copy of the receiver object, the method to call on it, and a copy of the arguments to test with

Then, given this collection of MethodFinderSend objects:

    ^ (self possibleSolutionsForInput: inputCollection) select: [ :send | send resultIn: expectedResult ].
This means:

- execute the "resultIn:" method on each of the MethodFinderSend and return a collection of those where this returns true

The implementation of this "resultIn:" method is in https://github.com/pharo-project/pharo/blob/c896913a00fa6e2b...:

    [ [ ^ expectedResult = (receiver perform: selector withArguments: arguments) ]
      onErrorDo: [ :anError | ^ false ] ]
       on: Deprecation
       do: [ :depr | ^ false ]
This is, roughly:

- try to perform the call

- return false if there is an exception

- otherwise, return true or false depending on whether the result equals the expected result

So yes, it's an exhaustive search over the methods that the receiver's class promises are OK to test. If you write a method that tries to format the hard drive, and your class exports this method in its "selectors to test", then searching for a method on this class will attempt to format your hard drive.


Thanks for that explanation! Is there any form of sandboxing in Pharo VMs that would prevent accidental side effects like the hard drive reformatting?


Not as far as I know. In fact, the system prides itself on allowing you to modify everything in it.

One striking demo I saw once a few years ago (so details are a bit hazy) involved the become: message. This is a special operation for swapping references around. "X become: Y" has the effect of everything that previously referred to X to now refer to Y, and everything that previously referred to Y to refer to X.

So the demo was to execute something like:

    White become: Black.
which immediately switched all white pixels to black and vice versa.

I think the person giving the demo even demonstrated

    True become: False.
though that made the VM unusable pretty much immediately IIRC.


Venturing a guess: Make up a unit test that runs on all relevant functions of the class (I.e. type) that the object “2” belongs to, and pick functions that pass the test.


How could that possibly be safe in a non-pure programming language? There could be a function that deletes the n first files found in the working directory.


I remembering wondering about the same thing a few years ago, and came across this: https://stackoverflow.com/questions/30177559/how-does-find-b...


Yes.


    for each function in known_functions:
        if function.apply(input) == output:
            return function


MethodFinder in Pharo is a litte bit smarter and does not use the list of known functions (unlike Squeak).


So how does it identify functions which are pure, and thus safe to pump random sample inputs through?


I'm not sure how they do it, but I would be tempted to have some static analysis at save time. The static analysis can't be perfect in a Turing complete language embedded in an environment that admits impurity, but it can be proven conservative so that no impure methods are falsely marked as pure at save time. I've done something similar for commit-time code analysis to generate an error if a proven non-negative seed is passed to a Numerical Recipes in C-style random number generator (non-negative seeds silently ignored).

Alternatively, if the interface to the OS itself is small enough, they could run their tests in a sandboxed environment where all methods to access the file system, network, clock, etc. are replaced with stubs that throw exceptions.


There is no magic; it does not know it for sure. But unlike the original MethodFinder, now the classes themselves decide about the approved selectors. In Squeak, the tool itself had a long whitelist of approved selectors. Moreover, the blacklists were updated.



I’m sure it can’t be done, but I’d love to see Pharo running natively on iOS one day.


Why not? I’m sure if you cull the JIT you could probably compile it for the platform. Apparently there’s even macOS and ARM support, so it’s more than halfway there ;)


Squeak was ported to iOS right after the iPhone came out. The virtual machine only had an interpreter back then but, as you said, there is not reason why the JIT (called Cog) couldn't be used as well. Apple has never allowed it on the app store (but applications built with it have been allowed as long as they are completely closed) so people can't get it, but that is a non technical issue.

The needed code is at

https://github.com/OpenSmalltalk/opensmalltalk-vm/tree/Cog/p...


Not so, Apple has closed some loopholes in iOS 14 to make (already limiting) JIT restrictions more annoying to the point where it's not really usable anymore…


I'd prefer iOS running in Pharo, since Pharo is good for debugging and since all iOS documentation isn't freely available.


I love Smalltalk but apart from the commercial versions, the UI frameworks are very limited or immature and have very few examples or doc's. Yes, you can build your own 'morphs' etc but that doesn't scale well for anything but one off small/toy applications.

Pharo is probably the best placed open source Smalltalk to get into the enterprise dev market and has a promising UI framework under dev at the moment but until this gets sorted out I think it will remain on the sidelines for a while yet.


Commercial Smalltalks for Windows are as flexible as Win32.

http://www.cincomsmalltalk.com/main/

This was the path they were on when Java happened.


There is also Dolphin Smalltalk[0] which is an open source Smalltalk with native Win32 UI support.

[0] https://github.com/dolphinsmalltalk


Yes that was another one.

I was using Smalltalk/V for Windows 3.x back in the day, as part of some university project assignments.


I love the idea of being able to visualize the state of everything while it's running, for me, that's the killer feature I'd love to see in other languages.


Erlang's VM comes to mind. It has great APIs for inspecting a running system and quite a few options for consuming that data: build-in observer [0], CLI version [1], web live dashboard [3] and more.

[0] https://erlang.org/doc/apps/observer/observer_ug.html

[1] https://github.com/zhongwencool/observer_cli

[2] https://github.com/phoenixframework/phoenix_live_dashboard


We started to describe these features in more detail on the The Pharo Dev blog: https://thepharo.dev/tag/pharofeatures/


From my little experience with Pharo, i can say it offers many things i can't find elsewhere and there is a huge room for innovation and improvement, and on top of that a lot of fun, Pharo is not getting the attention it deserves.


I love Pharo and occasionally explore it, but I worry that there are very few examples of applications developed with it. [0]The ones listed seem to be old(at least the last time i checked). This page is currently unavailable

[0]https://pharo.org/success


Glamorous Toolkit[0] is pretty neat! More of something designed for making software on top of, but it's a pretty cool example of what's possible.

[0]: https://gtoolkit.com/


Why is that only possible in Pharo? The concepts seem pretty language agnostic. Maybe I've mis-understood what it does but I can imagine a devtools plugin for Chrome/Firefox that basically does effectively

    if (x instanceof foo) ShowUIForFoo
    else if (x isnstanceof bar) ShowUIForBar
    ...
And then let you register your object UIs so they show up in the debugger.


Thanks for sharing. I'll explore it.


I've been meaning to find some time and go through the Pharo MOOC. Would love to learn the language and environment.

https://mooc.pharo.org/


I enjoyed that MOOC, I can definitely recommend having a look. I watched the videos in French, IIRC there was English dubbing available, but it was not great.


Thanks for the encouragement! Yes, I've seen the English dubbing, as I've watched the few videos or so. It seems like an interesting language, and I really like the idea of interactive programming systems. It's similar to what I use and the languages I am interested in, but I haven't given a Smalltalk system proper learning time. I feel it's an area of computer science that has not received much attention. If programming languages and their environments were more interactive and gave better feedback, then I feel I don't need all sorts of fancy stuff like dependent types, which really seem to excite people. If the system's interactability and feedback is good enough, I, the programmer, can make the right decisions, which is the primary challenge when programming.


Possibly a case of a Hacker News Hug of Death.


The main thing that put me down on investigating Pharo even for hobby projects is the absence of native multi-threading support. I know that it depends on the application context but still...


the "Smalltalk" word is missing from this page and the main one, interesting marketing move :)


Pharo has been distancing itself from the word "Smalltalk" pretty much since day one. This is not surprising at all.


Pharo is no longer a pure Smalltalk-80, it follows its own path.

Squeak is the real Smalltalk for modern computers if one wants to be precise.


IMHO, thats a trifle misleading.

Squeak was the open-source smalltalk, but got bogged down by the accumulated baggage of unfinished projects stuck inside it. Etoys, an aging morphic implementation, etc.

Squeak was forked in two separate directions:

One was Cuis, which went the "simple-is-better" route, and went on an aggressive cull against complexity. They stripped out as much as they could, and modularised what they could.

The result is a much smaller "smalltalk", and yes, more in line with the feel of the original smalltalk-80.

Pharo also forked from squeak at about the same time. Their goals were "get rid of some of the squeak baggage, and add newer stuff. So in that sense, its in many ways more complex than squeak (and much more complex than cuis).

BUT, they are all essentially forks from squeak. They use essentially the same VM underneath. There are LOTS of squeak classes in the standard classes of both cuis and pharo.

In many ways, squeak, pharo and cuis are really 3 different distributions of squeak, as opposed to 3 different languages.

I think the following is the more realistic comparison:

- squeak = debian stable

- pharo = arch linux (or gentoo)

- cuis = alpine linux

But, they're all linux, and neither one is "more" linux than the other.


Didn't Cuis[1] branch off from Squeak even before that to be closer to its ST-80 roots. Although, if I recall correctly, it does at least use Morphic and not MVC.

[1]: https://github.com/Cuis-Smalltalk/Cuis-Smalltalk-Dev


The focus of Cuis is simplicity, not tradition. So it is only closer to ST80 than Squeak in the cases where new features make Squeak "fat", like Etoys.


It is the very first time I see anything about it, so not sure.


Squeak was never supposed to be a modern Smalltalk. See https://pbs.twimg.com/media/EMJoLicXsAA7dej?format=jpg&name=...


I know, just making the point where Pharo and Squeak differentiate themselves. :)


"The server is temporarily unavailable".

Wonder if it's written in Pharo.


It appears to be. Zinc is the default http client/server package.

  $ curl -I https://www.pharo.org/features
  HTTP/1.1 200 OK
  Date: Tue, 21 Jul 2020 05:18:23 GMT
  Server: Zinc HTTP Components 1.0
  Content-Type: text/html;charset=utf-8
  Content-Length: 27546
  Connection: close
Not sure how common it is to have it serve traffic directly instead of through a reverse proxy like nginx though.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: