[squeak-dev] Not Squeak but... Ni goes multithreaded

Göran Krampe goran at krampe.se
Tue Feb 2 12:40:03 UTC 2016

Hey guys!

I am unfortunately not hacking in Squeak/Pharo anymore but I am instead 
playing along with my Ni-language in my spare time. But the Squeak 
community is still very dear to me and I just couldn't help sharing some 
fun I had last night! ;)

As we all know native threads (multicore) and Smalltalk is not a "common 
combo" but Ni is now sporting a first trivial native threading mechanism!

Last night I threw together a first hack on utilizing the native 
threadpool module in the underlying Nim. So in the REPL this works:

gokr at yoda:~/nim/ni/src$ ./nirepl
We are the knights who say... Ni! Enter shrubbary... eh, code and
an empty line will evaluate previous lines, so hit enter twice.
>>> 5 timesRepeat: [spawn [echo "yo"]]

The "nil" at the end is the return value from timesRepeat: so nothing 
"wrong". If the code looks odd (spawn and echo) it's because Ni can use 
prefix syntax for functions as well as Smalltalkish style.

This is "shared nothing" threading, the spawned block gets run in a 
completely separate instance of the Ni interpreter inside its own native 
thread. The code block passed over is deep copied. Each native thread 
has its own GC etc. Of course Nim has MUCH more advanced mechanisms for 
intercommunication so... this is just a toe dipping.

...but the larger commented trixier example below runs fine too!

Next up is probably to try to make Ni "stackless" (rewrite the 
interpreter so that it doesn't nest the calls so). This would enable 
even more fun stuff.

regards, Göran

# This is called a block in Ni. It is like an OrderedCollection.
# At this point the block is just a series of nested words and literals.
# Assignment is actually an infix function!
code = [
   # This is a local function to recursively calculate factorial.
   # ifelse is currently a 3-argument prefix function, but Ni could use
   # Smalltalk syntax for that too.

   factorial = func [
     # Arguments are sucked in as we go, so no need to declare n first
     ifelse (:n > 0)
       [n * factorial (n - 1)]
   # Echo is a prefix function.
   echo factorial 1

# Ni has keyword messages that can take the first argument from the left.
# Ni also has closures and non local returns so we can implement 
# control structures and things like select: or reject: easily. Or we 
can write
# them as Nim primitive functions.
10 timesRepeat: [
   # Ni is homoiconic so we can modify the block as if it is code.
   # We remove the last element of the code block (the number) and add
   # a random number from 1-20.
   code removeLast

   # In Ni the parenthesis is currently needed, evaluation is strict 
from left to right.
   code add: (20 random)

   # Spawn fires upp a native thread from a threadpool and
   # inside that thread a new fresh interpreter is created.
   # Spawn will deep copy the Ni node being passed and will
   # then run it as code in the new interpreter.
   # Currently the result value is not handled.
   spawn code
echo "Spawned off threads"

# Sleeping this thread to wait for the 10 above
sleep 1000
echo "Done sleeping, bye"

More information about the Squeak-dev mailing list