Planet Squeak

blogs about Squeak, Pharo, Croquet and family
planet squeak - planet squeak es - planet squeak jp - planet croquet - planet squeak code - planet smalltalk

December 19, 2014

Torsten Bergmann

WKHTML2PDF for Pharo

Want to use http://wkhtmltopdf.org from Pharo to convert HTML pages or URLs to PDF?

Then read more here and checkout the project on STHub. You can also load it from the config browser in Pharo 4 beta.

by Torsten (noreply@blogger.com) at December 19, 2014 09:57 AM

December 17, 2014

Torsten Bergmann

Another Smalltalk Book in 2015

There is another Smalltalk book upcoming in 2015. Look at Amazon for details.

by Torsten (noreply@blogger.com) at December 17, 2014 04:54 PM

New Collections for Pharo

There is a package to introduce new kind of collections. Lets see how this moves forward.

by Torsten (noreply@blogger.com) at December 17, 2014 09:52 AM

December 16, 2014

Torsten Bergmann

Smalltalk2014 videos

Smalltalks 2014 videos are available.

by Torsten (noreply@blogger.com) at December 16, 2014 03:54 PM

Craig Latta

Smalltalk Reflections episode three is up

Check it out!


by Craig Latta at December 16, 2014 08:40 AM

December 11, 2014

Torsten Bergmann

RMapViewer

A viewer for reaction maps among isomers implemented in Pharo Smalltalk.


by Torsten (noreply@blogger.com) at December 11, 2014 11:17 AM

GTSpotter - another new tool

A new tool in the GT (Glamorous Toolkit) to easily  spot objects. Read more here and here.
It is now part of upcoming Pharo 4.0.

by Torsten (noreply@blogger.com) at December 11, 2014 10:17 AM

HoneyGinger

HoneyGinger is an interactive simulation environment based on Smoothed Particle Hydrodynamics. Implemented in Pharo.

by Torsten (noreply@blogger.com) at December 11, 2014 07:47 AM

Dynamic Code Evolution VM

Found that on the web:

The Dynamic Code Evolution Virtual Machine (DCE VM) is a modification of the Java HotSpot(TM) VM that allows unlimited redefinition of loaded classes at runtime. The current hotswapping mechanism of the HotSpot(TM) VM allows only changing method bodies. Our enhanced VM allows adding and removing fields and methods as well as changes to the super types of a class.

Nice - should move Java a little bit closer to Smalltalk.

by Torsten (noreply@blogger.com) at December 11, 2014 07:21 AM

December 09, 2014

Torsten Bergmann

Chalten - working with times in Pharo

Chalten: an interesting library to work with dates, you can load it from the config browser in Pharo.

by Torsten (noreply@blogger.com) at December 09, 2014 02:17 PM

Craig Latta

Context release 4 alpha 1

Context 4 alpha 1 is released. This one fixes loading errors in the welcome page, supports remote debugging and process browsing, and makes Naiad and remote messaging support available as Monticello packages. Thanks in advance for reporting bugs!


by Craig Latta at December 09, 2014 01:30 PM

December 08, 2014

Torsten Bergmann

LampSort

Another nice article written by Sven.

by Torsten (noreply@blogger.com) at December 08, 2014 08:25 PM

Pharo binding to R

R is a free software environment for statistical computing and graphics. Now there is a Pharo binding to R released as an initial version. Read more.

by Torsten (noreply@blogger.com) at December 08, 2014 03:03 PM

December 02, 2014

Göran Krampe

Nim seq

One of the most important aspects in a language is how powerful and easy it is to use its collection/container types. At least that is my feeling coming from Smalltalk where the Collection classes and their rather rich protocols are used extensively and also cover String and Array and much more. If you peek into the current leading open source Smalltalk - Pharo - you can see Collection allSubclasses size evaluate to 78. Of course, lots of those are special subclasses and not for general use, but fact remains that a strong language needs a strong library of good collections.

In Smalltalk I can for example run this: ``` smalltalk

(1 2 3 4 5) select: [:x | x isOdd ] thenCollect: [:x | x * 3 ]

``` This is actually a single method call taking two closures, one to perform a "filtering", and one to perform a "map". This is not a standard message in "good old" Smaltalk-80, but it has eventually been added since the usage pattern is so common. To me personally a modern language needs similar power or I would go nuts. :)

Nim has some fundamental Collection types too - and tries deliberately to keep this number small - which I also sympathize with. Nim is meant to be lean and mean, so being minimal in the core is the Right Thing To Do. The ones in the system library are:

I am not listing range, string and cstring types, although especially string/cstring can be viewed as collections, and in Smalltalk they in fact are Collections.

So... in Nim we have seq as the single most important general purpose dynamically sized collection. Now... this is in the Nim language, if we extend our view to also include the standard library, we find lots more.

In order to first learn all you can do with a seq.... ah. Not so easy it turns out! Nim is not structured with "everything you can do with type X here". This fact actually screams for better tooling, but that is another story. One way is basically to search for "seq" in the documentation of the system module. I did that and also searched through the source :)

I ended up writing code exploring what I found and more, so put on your Nim glasses, read the code and comments and join the ride. If you want to compile it yourself here is the code, just do "nim c seqtest.nim" and run it.

``` nimrod Code exploring seq import fruitbase, future, sequtils, algorithm

Collections are very important in Smalltalk, and they offer a huge protocol

for working with them. The workhorse in Smalltalk is OrderedCollection - which

together with Dictionary probably covers 90% of all collection use.

In Nim the equivalent of an OrderedCollection is the type seq.

#

This is a little rundown of what you can do with seq using stdlib.

For fun we also add some Smalltalk behaviors, to learn how.

Create an empty collection of Fruit. We can also use:

var s: seq[Fruit] = @[]

var s = newSeqFruit

Some Fruit objects to play with, borrowed from earlier articles on OOP

var b = newBanana(size = 0, origin = "Liberia", price = 20.00222.Dollar) var p = newPumpkin(weight = 5.2.Kg, origin = "Africa", price = 10.00111.Dollar)

First we have add(), contains() and len()

s.add(b) echo("Seq is " & $s.len & " elements long and contains banana: " & $s.contains(b)) echo("Seq is " & $s.len & " elements long and contains pumpkin: " & $s.contains(p))

We can add with & too, but it will copy s into a new seq with at least 1 more slot.

This needs discard or assignment since it returns a new seq.

So this is actually concatenation via "copy into a new seq" but for a single element.

s = s & p echo("Seq is " & $s.len & " elements long and contains pumpkin: " & $s.contains(p))

We can access using [index] and also let the whole seq represent itself as a string,

The implementation of $ of course calls $ for the contained elements.

echo("First fruit: " & $s[0]) echo("The whole seq: " & $s)

Simple iteration, uses the items() iterator under the hood. Iterators are normally inlined

by the compiler and thus cost basically nothing. Calling "items(s)" is not needed,

the for loop will do that automatically and also infer the type of i for us.

Smalltalk: s do: [:i | ... ]

for i in s: echo(i.origin)

Insert an element at a given index

s.insert(p, 1)

Print countries and index, uses pairs() instead of items() to iterate over both index and value.

Equicalent to Smalltalk: s keysAndValuesDo: [:i :v | ... ]

for i,v in pairs(s): echo("index: " & $i & " country: " & v.origin)

Convert iterator to a seq of key/val tuples, just stumbled over it.

Like calling Dictionary>>associations in Smalltalk, but here its

generalized for any kind of iterator.

echo(toSeq(pairs(s)))

It should produce a copy, so should hold true

assert(toSeq(items(s)) == s)

Print in string form, neat for debugging.

echo("repr:" & repr(s))

Delete at index. Here is a little issue with system.nim and sequtils.nim overlapping slightly.

Should be fixed. The following will not compile since its ambiguous:

s.delete(0)

Instead we need to explicitly call it in the system module.

system.delete(s, 0)

Get and remove last element.

echo s.pop echo("The whole seq: " & $s) echo("Seq is " & $s.len & " elements long and contains banana: " & $s.contains(b))

Concatenate two seqs copying into a new longer seq. Like in "," in Smalltalk.

s = s & s echo("After concat seq is " & $s.len)

Throw in a banana again for tests below

s.add(b)

Sort using proc syntax

s.sort(proc(x, y: Fruit) :int = cmp(x.origin, y.origin))

Sort using do syntax

s.sort do (x, y: Fruit) -> int: cmp(x.origin, y.origin)

Sort using new lambda syntax

s.sort((x, y: Fruit) => cmp(x.origin, y.origin))

NOTE: In the following three calls to map we needed to wrap with $(...) to avoid

an internal error in Compiler for Nim 0.10.1.

#

Smalltalk's #collect: is Nim's map, here using proc syntax.

In Smalltalk: s collect: [:x | x origin ]

echo($(s.map(proc(x:Fruit): string = x.origin)))

...and future lambda syntax, basically as short and clean as Smalltalk!

echo($(s.map((x:Fruit) => x.origin)))

...or using mapIt template variant, but needs a type arg for the new seq

echo($(s.mapIt(string, it.origin)))

Smalltalk's #select: is Nim's filter, here using proc syntax.

In Smalltalk: s select: [:x | x origin = 'Liberia' ]

echo(s.filter(proc(x:Fruit): bool = x.origin == "Liberia"))

...and future lambda syntax, almost as short and clean as Smalltalk!

echo(s.filter((x:Fruit) => (x.origin == "Liberia")))

...and filterIt template variant, muahaa, shorter than Smalltalk!

echo(s.filterIt(it.origin == "Liberia"))

But Smalltalk has a HUGE amount of more behaviors like:

detect:ifNone:, allSatisfy:, anySatisfy:, reject:, inject:into:

...well, there are TONS we would like :)

#

Here is allSatisfy: and anySatisfy:, easily implemented.

proc allSatisfy*T: bool {.closure.}): bool = ## Returns true if all the items fulfill the predicate. ## ## Example: ## ## .. code-block:: ## let numbers = @[10, 20, 30] ## assert numbers.allSatisfy(proc(x: int): bool = x > 5) result = true for i in seq1:

if not pred(i): return false

proc anySatisfy*T: bool {.closure.}): bool = ## Returns true if any of the items fulfill the predicate. ## ## Example: ## ## .. code-block:: ## let numbers = @[10, 20, 30] ## assert numbers.anySatisfy(proc(x: int): bool = x > 25) result = false for i in seq1:

if pred(i): return true

let numbers = @[10, 20, 30] assert(numbers.allSatisfy(proc(x: int): bool = x > 5)) assert(numbers.anySatisfy(proc(x: int): bool = x > 25))

echo($s & " all come from Africa: " & $s.allSatisfy((x:Fruit) => (x.origin == "Africa")))

We can also check if s isNil

echo(s.isNil) s = nil echo(s.isNil)

Let's see what happens if we try to port a few random Smalltalk snippets I wrote

down just perusing the Smalltalk protocol for OrderedCollection:

#(1 2 3 4 5) select: [:x | x odd ] thenCollect: [:x | x * 3 ]

Above we do a filter on an array of Numbers getting those that are odd

and then we map them by multiplying with 3.

We need odd, an immediate template should inline it I think.

SomeInteger is a type class matching all integer types in Nim.

template odd(x: SomeInteger): bool {.immediate.} = (x and 1) == 1

And then we can write it like this using the lambda macro.

For filter we don't need to declare type for x, but for map we do.

I suspect this is because we start out with a literal from which

type is inferenced one level.

var q = @[1,2,3,4,5].filter((x) => x.odd).map((x:int) => x * 3) echo(q)

Or procs style, slightly longer and also needing return type of procs.

Here we get away without declaring x:int, turning the code into generic procs.

Andreas would call it "bad style" I think.

q = @[1,2,3,4,5].filter(proc(x): bool = x.odd).map(proc(x): int = x * 3) echo(q)

#(1 2 3 4) sum

Sum is already defined in math module

from math import sum echo(@[1,2,3,4,5].sum)

#(one two three two four) copyWithoutAll: #(one two)

The above creates a new collection without any ones or twos.

One and two are symbols (canonical strings)

We need copyWithoutAll:, let's call it filterWithout.

In Nim we don't need "All" to imply that the argument

should be a collection, we can overload for other types.

accumulateResult is a template taking an iterator.

sequtils both has a filter iterator and a filter proc, here

we use the iterator. This means both the accumulation and the iteration

will be inlined. I think :)

#

notin is a template which is sugar for not seq2.contains(x)

It is also marked as a keyword so x.notin(seq2) does not compile, it needs

to be x notin seq2

proc filterWithout*T: seq[T] = accumulateResult(filter(seq1, proc(x:T):bool = x notin seq2))

var qq = @["one", "two", "three", "two", "four"].filterWithout(@["one", "two"]) echo($qq)

#(1 2 3 4) includesAny: #(1 2)

#(1 2 3 4) includesAll: #(1 2)

Both the above can be added easily similar to allSatisfy, anySatisfy:

proc containsAny*T: bool = ## Returns true if any of the items in seq2 is in seq1. ## ## Example: ## ## .. code-block:: ## let numbers = @[10, 20, 30] ## assert numbers.containsAny(@[5, 10]) result = false for i in seq2:

if i in seq1: return true

proc containsAll*T: bool = ## Returns true if all of the items in seq2 are in seq1. ## ## Example: ## ## .. code-block:: ## let numbers = @[10, 20, 30] ## assert numbers.containsAll(@[10, 20]) result = true for i in seq2:

if i notin seq1: return false

assert(@[1,2,3,4].containsAll(@[1,2])) assert(@[1,2,3,4].containsAny(@[1,2,20])) ```

Conclusion

The seq type has a reasonable minimal set of behavior, but we should add more into sequtils IMHO. Make it really strong, really smart and convenient. This is extremely important for developer productivity. I can gladly sit down and look through the Smalltalk Collection hierarchy to find more behavior we could implement.

Happy hacking!

December 02, 2014 11:00 PM

Craig Latta

a most useful virtual machine debugging aid: simulated objects

Squeak’s virtual machine simulator is extremely useful for debugging. You can use it to inspect and change objects “while time is stopped”, between the execution of individual virtual machine instructions. Traditionally, though, it takes an address-based view of objects. There are several useful utility methods which, given an object address, will print useful information to the Transcript. Wouldn’t it be nicer, though, if you could use normal inspectors to look through the fields of the objects in a simulated virtual machine’s object memory?

I created simulated objects for this purpose. They are instances of a SimulatedObject class; each one has an interpreter and an address. They can print useful information about themselves, like the interpreter can, but they can also modify themselves and interact with each other, changing the interpreter’s object memory appropriately. Are you wondering about the instructions of a compiled method? Would you like to make a few choice modifications to those instructions? A simulated object for that method’s address will help you.

Simulated objects play nicely with Squeak’s object inspectors, and, more importantly, with its object explorers. You feel like you’re inspecting normal objects, except that you can’t send normal messages to them. Or can you? I’m pondering this. It might be useful, for example, to terminate a process in a simulated interpreter’s object memory, without having to do it in another process. Time is stopped, but perhaps you could queue up messages to send when it starts again, through a collaboration between simulated objects and a coordinating object in the memory they describe.

I’ve been using simulated objects recently to chase references with the absolute assurance that I won’t be creating new ones. They’re very useful for debugging virtual machine primitives. Sometimes, when I’m debugging a headless system with a broken remote messaging system, it’s the only user interface I have for inspecting things. And it’s sure a lot nicer than inspecting things in a C debugger.

What will you do with them?


by Craig Latta at December 02, 2014 09:55 PM

Torsten Bergmann

Squeak on Plan9 OS

Looks like Alex Franchuk got Squeak VM working on Plan 9 operating system. Read more.

by Torsten (noreply@blogger.com) at December 02, 2014 01:38 PM

GetOpt for Pharo 3.0

When working with Pharo Smalltalk on the commandline there is already some support in class CommandLineHandlers to retrieve arguments and options. Now Phillipe Back has improved this even further by making Ian Piumarta's GST GetOpt work in Pharo 3.0.

You can load the code from SmalltalkHub. Getopt should be known to you if you ever work(ed) in C/C++ world. It automates some of the chore involved in parsing typical unix command line options. Java has something similar with CLI.

With Phil's project for Pharo it is now fast to use command line options and it allows also easy to debug them in the most lively environment you can work with.

by Torsten (noreply@blogger.com) at December 02, 2014 09:49 AM

Web development with Smalltalk

Web development presentation using Smalltalk by Mariano.

by Torsten (noreply@blogger.com) at December 02, 2014 08:26 AM

Scale command line handling for Pharo 3.0

Guillermo Polito once blogged about replacing bash with Pharo by using a custom command line handler. Now Philippe Back has packaged this up in a project called Scale for Pharo 3.0. Read more.

by Torsten (noreply@blogger.com) at December 02, 2014 08:24 AM

Onion Pharo

... or a way to continue modularizing Pharo is described by Guillermo Polito on his blog.

by Torsten (noreply@blogger.com) at December 02, 2014 08:03 AM

Smalltalk and business

within the context of Pharo was presented by Mariano Martinez Peck during "Summer School on Languages and Applications" 2014 in Cochabamba, Bolivia. Here is the presentation.

by Torsten (noreply@blogger.com) at December 02, 2014 08:00 AM

Simple DDS Pharo client

SimpleDDS Is a Publisher / Subscriber (DDS) Architecture framework - a Data Distribution Service Implementation for Pharo. Read more here or checkout the project here.

by Torsten (noreply@blogger.com) at December 02, 2014 07:57 AM

Deep Roassal integration in the Moose Finder

Read more at Tudors blog.

by Torsten (noreply@blogger.com) at December 02, 2014 07:51 AM

Smalltalk Reflections episode one

Craig Latta and David Buck released episode one of “Smalltalk Reflections”, a podcast about Smalltalk. This initial podcast is a tribute to James Robertson (R.I.P.). James would be proud that this valuable resource of Smalltalk information continues to run.

by Torsten (noreply@blogger.com) at December 02, 2014 07:35 AM

Craig Latta

the Smalltalk Reflections podcast, episode one: a tribute to James Robertson

We did it! On James Robertson’s birthday, David Buck and I released episode one of “Smalltalk Reflections”, a podcast about Smalltalk. Our first episode is a tribute to James, who started the previous incarnation of the show. It’s hosted by David and myself, and features remembrances from several friends and co-workers, as well as a few choice words from the man himself. I edited it, and wrote the theme music. Enjoy!


by Craig Latta at December 02, 2014 02:33 AM

November 29, 2014

Gilad Bracha

A DSL with a View

In a previous post, I promised to explain how one might define UIs using an internal DSL. Using an internal DSL would allow us to capitalize on the full power of a general purpose programming language and avoid having to reinvent everything from if-statements to imports to inheritance.

Hopscotch, Newspeak's UI framework, employs such an internal DSL.  Hopscotch has been discussed in a paper and in a talk.  It will take more than one post to describe Hopscotch; here we will focus on its DSL, which is based on the notion of fragment combinators.

Fragments describe pieces of the UI; they may describe individual widgets, or views constructed from multiple pieces, each of which is in turn a fragment. A fragment combinator is then a method that produces a fragment, possibly from other fragments.

One of the simplest fragment combinators would be label:, which takes a string. The expression

label: 'Hello Brave New World' 

would be used to put up the string "Hello Brave New World" on the screen.  Other examples might be

button: 'Press me' action: [shrink]

which will display a button




that will call the method shrink when invoked.  The combinator button:action: takes two arguments - the first being a string that serves as the label of the button, and the second being a closure that defines the action taken when the button is pressed. Closures in Newspeak are delimited with square brackets, and need not provide a parameter list if no parameters are required.  This is the most lightweight syntax for literal functions you will find. Along with the method invocation syntax, where method names embed colons to indicate where arguments should be placed, this gives a very readable notation for many DSLs.

Further examples:

row: {
  button: 'Press me' action: [shrink]. 
  button: 'No, press me' action: [grow].
}

The row: combinator takes a tuple of fragments (tuples in Newspeak are delimited by curly braces, and their elements are separated by dots) as its argument and lays out the elements of the tuple horizontally:


the column: combinator is similar, except that it lays things out vertically

column: {
  button: 'Press me' action: [shrink]. 
  button: 'No, press me' action: [grow]
}

produces:



In mainstream syntax (Dart, in this case) the example could be written as

column(
  [button('Press me', ()=> shrink), 
   button('No, press me', () => grow)]
 )

The Newspeak syntax is remarkably readable though, and its advantage over mainstream notation becomes more pronounced as examples grow. Of course none of this works at all if your language doesn't support both closures and literal lists/arrays.

So far, this is very standard stuff, much like building a tree of views in most systems.  In most UI frameworks, we'd write something like

new Column([new Button('Press me', ()=> shrink), 
            new Button('No, press me', () => grow)]
    )

which is less readable and more verbose.  Since allocating an instance is more verbose than calling a method in most languages, the fact that fragment combinators are represented via methods, which act as factories for various kinds of views, helps make things more concise. It's a simple trick, but worth noting.

The advantage of thinking in terms of fragments becomes clearer once you consider  less obvious fragments such as draggable:subject:image:, which takes a fragment and allows it to be dragged and dropped. Along with the fragment, it takes a subject (what you might call a controller) and an image to use during the drag. Making drag-and-drop a combinator means everything is potentially draggable. Conventional designs would make this a special attribute of certain things only, losing the compositionality that combinators provide.

Presenters are a a specific kind of fragment that is especially important. Presenters provide user-defined views in the Model-View-Controller sense.  To define your own view, you subclass Presenter. Because presenters are fragments, any user defined view can be part of a predefined compound fragment like column: or draggable:subject:image:.

A presenter has a method definition which computes a fragment tree which is used to render the presenter. The fragment DSL we discussed is used inside of presenters. All the combinators are methods of Presenter, so they are inherited by any class implementing a view, and are therefore in scope inside a presenter class.  In particular, combinators are available in the definition method.

To see how all this works, imagine implementing the well known todoMVC example.  We'll define a subclass of Presenter called todoMVCPresenter  to represent the todoMVC UI.  The UI is supposed to present a list of todo items. It consists of a column with:


  1. A header in large text saying "todos" 
  2. An input  zone where new todos are added.
  3. A list of todos, which can be filtered using controls given in (4). 
  4. A footer, that is empty if there are no todos at all. It materializes as a set of controls once there are todos.

We can translate these requirements directly:

definition = (
     ^column: {
      (label: 'todos') hugeFont.
      inputZone.
      todoList.
      footer.
     }
)

More notes on syntax:  methods are defined by following their header with an equal sign and a body delimited by parentheses; ^ signifies return; method invocations that take no parameters list no arguments, e.g., inputZone, not inputZone(); chained method invocation does not require a dot - so it's 
(label: 'todos') hugeFont rather than label('todos').hugeFont.

We haven't yet specified what inputZone, todoList and footer do. They are all going to be defined as methods of todoMVCPresenter.  We can define the UI in such a top down fashion  because we are working with a language that supports procedural abstraction. You get it for free in an internal DSL.  

We can then define the pieces, such as

footer = (
 ^subject todos isEmpty 
 ifTrue: [nothing]
 ifFalse: [controls]
)

Here, we use conditionals to determine what view to produce, depending on the state of the application.  The application logic is embodied in the controller, subject, which we query for the todos list. The nothing combinator does exactly what it says; controls is a method we would have to define in todoMVCPresenter, detailing what should appear in the footer if it is visible.  Again, the code corresponds closely to the natural language description in bullet (4) above.

To elaborate todoList we'll need a loop or recursion or something of that nature; in fact, we'll use the higher order method collect:, which is Newspeak's version of map

todoList = (^list:[subject todos collect: [:todo | todo presenter]])

The list: combinator packages a list of fragments into a list view. We pass list: a closure that computes the list to todo items. 

Aside: We could have passed it the list itself, computed eagerly. Often, fragment combinators take either suitable fragment(s) a closure that would compute them.

To compute the fragment list we compute a presenter for each individual todo item by mapping over the original list of todos.
The closure we pass to collect: takes a single parameter, todo. Formal parameters to closures are introduced prefixed by a colon, and separated from the closure body by a vertical bar.

What are the odds that higher order functions (HOFs) were part of your external DSL? Even if they were, one would have to define a suite of useful  HOFs. One should factor the cost of defining useful libraries into any comparison of internal and external DSLs.

The Hopscotch DSL has other potential advantages. Because fragment combinators are methods, you can override them to customize their behavior.
We believe we can leverage this  to customize the appearance of things, a bit like CSS. To make this systematic, we expect to define whole groups of overrides in mixins. I'm not showing examples where Hopscotch is used this way because we have done very little in that space (and this post is already too long anyway). And we haven't spoken about the other advantages of Hopscotch.
such as its navigation model, lack of modality and very clean embodiment of MVC.

Ok, now it's time for the caveats.


  1. First and foremost,  Hopscotch currently lacks a good story for reactive binding.  In our example, that means you'd have to put explicit logic to refresh the display in some of the controls.  This makes things less declarative and harder to use. We always planned to solve that problem; I hope to address it in a later post.  But the high order bit is that we have code in a general purpose language that gives a very readable, declarative description of the UI. It corresponds directly to the natural language description of the requirements.
  2. Hopscotch lacks functionality in order to support richer UIs, but the design is naturally extensible: one adds more fragment combinators.
  3. We also want more ports, especially to mobile/touch platforms. However, Hopscotch has already proven quite portable: it runs on native Win32, on Squeak's Morphic and on HTML (the latter port is still partial, but that is just an issue of engineering resources).   More ports would help us deal with another controversial goal - defining a UI platform that works well across OS's and devices.


Regardless of the current engineering limitations, the point here is simply to show the advantages of a well-designed internal DSL for UI.  The lessons of Newspeak and Hopscotch apply to other languages and systems, albeit in an attenuated fashion.










by Gilad Bracha (noreply@blogger.com) at November 29, 2014 03:04 AM

November 28, 2014

Torsten Bergmann

Smalltalks 2014 report

A quick report on Smalltalk 2014 conference, just found on the web

by Torsten (noreply@blogger.com) at November 28, 2014 04:15 PM

November 27, 2014

Torsten Bergmann

Visual Design Inspector for Pharo

Vidi is a visual Design Inspector for Pharo. Read more details at:

 http://vidi.inf.usi.ch

To try out you can grab a premade image from CI or check
the project on GitHub.

Dont know about the status - I guess work is currently still in progress.
But I was already able to check some own projects with it. Nice!

by Torsten (noreply@blogger.com) at November 27, 2014 10:52 AM

November 26, 2014

Torsten Bergmann

PaymentFont for Seaside

The “PaymentFont for Seaside” project is a small Seaside wrapper for the PaymentFont project.

by Torsten (noreply@blogger.com) at November 26, 2014 12:05 PM

Pharo HTTP fundamentals

http://zn.stfx.eu/zn/pharo-http-fundamentals.pdf

by Torsten (noreply@blogger.com) at November 26, 2014 08:06 AM