Archives For author

Pavel Krivanek has written a great article on the Self Object Model which is worth a read, or you can discuss it on news.ycombinator.com or reddit.

 

Newcomer Gregg has been doing a series of great short Youtube clips showing off the Self  GUI development environment. Check it out!

It’s been a while since we did a proper release of Self – too long in fact.

The last duck themed release was “Mallard” a couple of years (!) back – we’re overdue for more ducks so here is a new release of Self brought to you by this beauty:

320px-Aix_galericulata_(Male),_Richmond_Park,_UK_-_May_2013

Self 2017.1 is downloadable for Linux x86 (.zip) and MacOS (.dmg), or you can build it yourself from the GitHub source tree.

There is also a handbook included and available to read online.

A brief change log is:

New features:

  • Changed to new versioning system for key subsystems (vm, core, morphic, outliners)   and for release as a whole.
  • New `about` object accessible from main menu with system info.
  • New `preferences` object allows easy access to system preferences.
  • ew themeing system for outliners and a new look.
  • Extensive reorganisation of object categories in `globals` to make global objects more easily discoverable and understandable.
  • New option on `worldbuilder.self` script to allow for fully automated building of Self worlds by setting subsystem options on command line.
  • New string helper methods: `splitOn:`, `joinUsing:` and `slice:`.
  • The `transporter` is now aware of code being in multiple independent trees, not  only one single Self tree, allowing for separate projects to be kept in separate   version control repositories.
  • A system-wide logger has been included to standardise logging practices within    Self.

Updates:

  • Self Control.app on macOS updated to work with El Capitan.

Fixes:

  • Fix on macOS to reduce CPU usage when idle.
  • VM build will now explicitly show which macOS SDK it is using.
  • ^D (EOF) handled correctly at prompt
  • Fix to bug preventing compilation on recent GCC
  • Many other misc fixes.

Documentation:

  • General improvements to Self handbook.
  • Self website moved out of main repository.

Other:

  • Webserver moved to separate repository: github.com/russellallen/self-webserver
  • travis-ci.org integration for VM building

It’s been a while since we did a Self release, and although there is a never ending stream of things which should be done and aren’t, I’m moving towards a new release so that our GitHub version isn’t too far out of sync with the last release version.

As part of that preparation process, I’ve fixed up some work Tobias started and have integrated with travis-ci.org.  Every push to the master branch on GitHub now builds and tests four VMs: Linux with GCC, Linux with Clang, macOS with GCC, macOS with Clang.

You’ll be pleased to know that our current status is:

 

I have long maintained that Self is the finest Yak shaving system in existence. Everything is possible and nothing is finished 🙂

So I was playing with building a website front end for the mailing list archives, which led me to improving the Self web server, which led me to making a new experimental stream framework for Self. This also led me to some interesting ideas on automatically checking for methods which should be present in an object but aren’t, but I’ll write about that later!

Self already has a readStream and writeStream prototypes, which are very basic entities modelled largely on Smalltalk-80. They’re mainly used in the context reading and writing to files and sockets.

What I’ve put together is a quick stream framework for putting together pipelines of filters etc and streaming objects through them. The general aim is to avoid the technical and conceptual overhead of copying collections multiple times as you handle them.

This isn’t particularly groundbreaking, lots of other languages do this sort of thing. I’d like to hear suggestions on how to make what I’ve done more elegant and Self-ish.

The code is at https://github.com/russellallen/flow

Basically, streams are entities which understand either readIfFail: or write:IfFail:. Streams can only be read or write.

Flow streams are composable, which means you can link them in a chain with pipeable connectors.

The relevant parts are in the global object ‘flow’.

This isn’t optimised at all – ideally streams should cheat by copying larger chunks behind the scenes where appropriate for performance. Also file streams probably need to be more aware of reading and writing chunks with internal buffers, and string writing should be optimised to reduce copying!

Possible improvements include adding spitting and merging pipes, specific buffering pipes etc.

Using flow streams is a two or three step process:

1 Build structure.

| myPipeline |

myPipeline: 
      'This is a bit of text for us to play with' reading 
   |= (flow pipeable map copyOn: [|:c| c capitalize])
   |= (flow pipeable filter copyOn: [|:c| c isVowel])
   |= (flow pipeable gather copyOn: [|:c| (c & c) asList])
   |= flow writable string copy. 

2 Put pipeline into action

myPipeline flush.

3 (Optionally) convert your stream into something else

[myPipeline contents = 'IIIIAAIIOOEEOOUUOOAAII'] assert.

And that’s about it. I’ll play with this some more, any suggestions?

David Ungar and Harold Ossher’s talk at SPLASH 2013, called “Dancing with Symmetry to Harness the Power of Complexity: Subjective Programming in Context” is now online with slides and video at InfoQ.

David and Harold discuss a new programming language and environment they have been researching which allows to contextual, multidimensional dispatch of messages so that the behaviour of objects depends on the context of the method invocation. They also give a quick demonstration of a development environment they have build to explore these ideas in Self.

Check it out!

Named after the majestic, awe inspiring Anas platyrhynchos, the latest Self release 4.5.0 is now available for download.

mallard

What’s new since 4.4?

  • Build system redone by Tobias Pape. Now based on cmake, with a single modern build process for both Linux and OS X. The VM can be built on both GCC and Clang on the latest vesions of both operating systems.
  • New Self Control.app on OS X to manage your running worlds as a more robust and featured replacement for the older ‘Self Droplet’. Use of this app is optional and you can still access the Self VM through the command line.
  • New look for standard world, with better fonts, colours and greater use of space.
  • Various fixes to the standard world, including a new build script ‘worldBuilder.self’ replacing several ad hoc build scripts.
  • Updated Self Handbook at handbook.selflanguage.org

Sources for the VM and for the basic Self world are available as always from the GitHub repository. Although Self, like Smalltalk80, can use an image (in Self called a snapshot of a world), this can be built from text sources.

Self Mallard is available for OS X and Linux. You can download binaries:

  • For OSX, a disk image containing the Self Control.app and a prebuilt clean snapshot (“Clean.snap”). Copy the app to your Applications folder, run it and click the Choose snapshot… button.
  • For Linux, a gripped tar file containing a prebuilt 32-bit binary and Clean.snap. Unpack, then run ./Self -s Clean.snap

Following on from his SelfVM build for Android x86, Chris Double has fixed up some bitrot in an old Self application, which allows sharing a Self world through a Java applet (without requiring a X11 server).

Check out his writeup here, including a screencast of how to make it work. His changes have been merged into the Self tree.

Chris Double has announced a build of the Self VM for x86 Android. No GUI yet and only x86:

Image

This follows on from my previous post on an error handling mechanism. Prompted by David Ungar to think further on how that mechanism could be made more general and powerful, and less of a one off special exception, this is a description of one way in which certain objects can adjust their behaviour based not only on their delegatees and but also on a ‘perspective’ – a viewpoint bound to a process. It’s a great example I think of the power of Self as a language.

Subjectivity and Us

Normal objects in Self are objective – that is their behaviour depends only on themselves and will be the same in all contexts.

In 1996, Randall B Smith and David Ungar wrote a paper called “A simple and unifying approach to subjective objects” (download as a pdf) in which they described a system called ‘Us’ where objects were subjective rather than objective. The behaviour of Us objects (in technical terms the lookup mechanism for delegation) depended on what perspective the message was sent with.

Objects were to be built up in two planes – by normal delegation and by layering pieces onto the whole. Each message received by the object would be dispatched into that three dimensional space based upon not only message selector but also on an implicit argument to the message – the perspective object.

So two people could look at an object in two different ways – to me it might be a circle, to you a set of slots. Or it might look like a pie chart to me and a table to you. An object would be not so much a concrete thing like a pebble but a ‘figment of its viewers beliefs’ (as the authors quote Alan Kay as saying)

Randall and David didn’t build a complete system this way. I don’t know of anyone who has, although the work done on Classboxes in Smalltalk-80 and Java is a very interesting application of similar ideas to modularisation and there are a number of other interesting papers which cite the Us paper.

I understand Randall and David’s paper correctly, a pure Us implementation would require a check at every lookup, so turning Self into Us would take a lot of effort and changing the VM lookup code if it were to be efficient.

However it might be a useful exercise to build a mechanism to investigate and play with subjectivity, even if that mechanism doesn’t get us all the benefits of a full-blown Us.

This is a thought experiment on some of the Us principles. It’s not an implementation of Us and neither Randall not David should be blamed for its inadequacies! In particular, perspectives in Us are not necessarily bound to a process, nor do they necessarily as I understand it hold true beyond the initial method – that is unlike the mechanism below a perspective wouldn’t stay fixed for the call stack until the original method exits. As well, Us wasn’t envisioned as an being a capacity of Self but as a new language which was a superset of the existing Self language.

On the other hand, as you’ll see below, this is a short and simple experiment!

Mechanism

The mechanism I have in mind looks like this:

To make an object “subjective”, we share the subjective mixin:

o: (| 
    m* = mixins subjective 
  |)

Ordinary slots will behave ordinarily:

o: (|
     m* = mixins subjective.
     x = 1. 
  |).
 o x == 1

To create subjective behaviour, we add layers (with overlapping slots) as parent slots:

o: (|
 m* = mixins subjective.
 default* = (| hello = ('Hello') |).
 french* = (| hello = ('Bonjour') |)
|)

These layers shouldn’t themselves have further parent slots, and they should overlap so that their slots are the same. If we want undefined behaviour we need to do something like (| hello = (|l = lobby| l raiseError) |) rather than leaving the hello slot out of our layer.

Once we have done this, sending our object the message ‘hello’ will get us the string ‘Hello’. However, if we do:

[o hello] @ 'french'

then we will get the result ‘Bonjour’.

What’s happening?

Perspective objects must understand a message forObject: o Selector: s, where o is the current self of the object doing the lookup and s is the selector. They return a canonicalString. Strings know to return themselves, so ‘french’ is a shortcut for a perspective object which always returns ‘french’. The system finds the perspective object by sending a message to self, so

[o hello] @ french

will, as you would expect, look for the perspective object by sending the message ‘french’ to self.

Perspectives are placed on the process. They are not placed in a stack; but the @ message on traits block manages reinstalling the old perspective after itself, so if we have:

([o hello] @ 'french'), ' ', o hello

the result is ‘Bonjour Hello’

OK, so how is this done?

(1) We create the mixin:

mixins subjective = (|
  ambiguousSelector: sel
               Type: t 
          Delegatee: d 
       MethodHolder: m 
          Arguments: a = ( | l = lobby | 

    sel    sendTo: self 
     DelegatingTo: ((l process this perspective forObject: self 
                                                 Selector: sel) sendTo: self)
    WithArguments: a

 ) 
|)

This traps the vm send error message ambiguousSelector:Type:Delegatee:MethodHolder:Arguments: and chooses which of the parents of our object is resent the message based on sending to the perspective object found on process this the message forObject:Selector:, which returns a string which is then sent to our original object to get the appropriate delagatee.

(2) globals process is given a new assignable slot called ‘perspective’ with the contents the string ‘default‘.

(3) traits block is given a new slot @

@ p = ( | h. r | 
  h: process this perspective. 
  process this perspective: p. 
  r: onNonLocalReturn: [|:v| process this perspective: h. v ] 
               IfFail: [|:e| process this perspective: h. raiseError ]. 
  process this perspective: h. r 
)

which handles installing a new perspective and cleaning up after itself, and

(4) traits string is given a new slot

forObject: o Selector: s = (self)

so that we can just use a string if we find it easier.

That’s it.

What can we do with it?

Well, first off let’s implement the error handling style mechanism from last post.

defaultBehavior = "Apart from all the other slots of course" (| 
    m* = mixins subjective. 
    default* = (| error: x = ( "Normal existing error code") |). 
    logErrors* = (| error: x = ( "Some code to log our error but not bring up debugger") |). 
    logErrorsPerspective = 'logErrors' 
|)

Now we’re done. If we try to get

9 / 0

we get a debugger, whereas if we do

[ 9 / 0 ] @ logErrorsPerspective

then any error silently logged without a debugger being opened.

This isn’t perfect, and there are I’m sure lots of interestingly dangerous corner cases and unexpected behaviours lurking, but its a great example of way in which a simple but well thought out base like Self gives us great power. There are many languages where this wouldn’t nearly be as nice to play with.