
Ni – A language influenced by Smalltalk written in Nim - mpweiher
http://goran.krampe.se/2015/09/16/ni-a-strange-little-language
======
nicklaf
From README.md:

 _" Ni is meant to mix with Nim. The idea is to use Nim for heavylifting and
binding with the outside world, and then let Ni be a 100% live dynamically
typed scripting engine inside Nim. Ni will stay a very small language, but
hopefully useful."_

Writing in Smalltalk or Lisp in order to control a more conservative language
such as Nim would appear to be a winning idea.

I'd be interested to learn more about the difference between the approach
taken by Ni, and the one taken by Hy or Clojure. In the latter two,
S-expressions are transformed into the AST (or directly to bytecode) of the
host language.

The author of Ni seems to have defined a new AST, and then written an
interpreter in Nim:

 _" Ni comes in two modules, the parser (500 loc) and the interpreter (750
loc). The parser produces an AST which is also the internal representation of
data in Ni. The interpreter then interprets the AST."_

Perhaps this was necessary due to the more static nature of Nim compared
Python or the JVM.

~~~
gokr
Yes, I made my own AST. You know, it started as a parser, evolved into an
interpreter :). But I will definitely talk to Andreas (creator of Nim) if
using Nim AST would be an advantage.

~~~
nicklaf
At any rate, your language does look rather interesting, and I should thank
you for your blog post. It has made me think about how the syntax of Rebol
(which was unknown to me) could possibly inform a language designed to combine
ideas from both Smalltalk and Lisp.

~~~
gokr
Smalltalk is quite lispish in many ways (closures, most stuff is an
expression, simplicity etc). Rebol fascinates me - and I have only scratched
its surface. For more on Rebol you should look at www.red-lang.org. Especially
the stuff around the Parser DSL, like:

[http://www.red-lang.org/2013/11/041-introducing-parse.html](http://www.red-
lang.org/2013/11/041-introducing-parse.html)

Red is in fact very impressive and definitely the "modern Rebol".

~~~
draegtun
In terms of development toolkit and implementation then yes Red could/should
be considered the "modern Rebol".

However in terms of the _language_ (syntax & semantics) then Rebol 3 is
definitely the "modern Rebol". Have a look at Ren/C for the new ideas and the
very latest development of the Rebol 3 codebase -
[https://github.com/metaeducation/ren-c](https://github.com/metaeducation/ren-c)

~~~
gokr
You are ever so correct, sorry about that! I also would like to say that I am
slightly "disappointed" that Red decided to stick so closely to Rebol.
Personally I definitely don't find everything in Rebol to be so perfect. ;)

------
giancarlostoro
> Who says Ni?

There were knights once upon a time who did indeed say Ni, but it is no longer
so.

~~~
vezzy-fnord
In fairness, a language named "Ekke-Ekke-Ptang-Zoom-Boing-Ni" would be far
easier to search for than Ni.

Concerning the language itself, the block-based Lisp influence taken from
REBOL is noteworthy. The latter is quite underappreciated in general.

~~~
gokr
Also, I found it interesting that this free form of syntax actually can be
made quite readable (in comparison to Lisp, which I love in theory but balk at
trying to read).

I even think Ni is turning out more readable than Rebol/Red - probably due to
the use of keyword syntax and infix arguments. And the idea with arg words
made lambdas very lightweight, much more so than in Rebol.

~~~
draegtun
It's trivial to add an _arg words_ style lambda to Rebol.

For example, here is a very _naive_ version:

    
    
      lambda: function [block] [
          args: sort unique collect [
              parse block [
                  any [
                      w: set arg get-word! (
                          keep to-word arg
                          change w to-word arg
                      )
                      | skip
                  ]
              ]
          ]
          function args block
      ]
    

test in REPL...

    
    
      >> f: lambda [:a + :b]
    
      >> f 1 2
      == 3
    
      >> foo: lambda [c: :a + :b  print [:a "+" :b "=" c]]
    
      >> foo 1 2
      1 + 2 = 3
    

NB. However you wouldn't really use _:arg-name_ here because this is already
reserved for the get-word! datatype.

~~~
gokr
Yes, and I never implied its not hard to do. And examples such as this one are
quite impressive - which is what got me interested in Rebol in the first place
and triggered the development of Ni.

However... if I understand your code properly - you are basically generating
an argument declaration by scanning for "get words". So its still a static
declaration.

In Ni an arg word is an _operation_. That means a Ni func can decide how many
arguments to pull, and in which order, dynamically, much like stack oriented
languages can do. Usefulness? Dunno :) But its not the same.

Also, yes, I opted out of set words in Ni since I want to be able to have
keyword syntax á la Smalltalk/Self. And I use "^" instead of ":" prefix for
get words, because I wanted the argwords to be similar to how they look in
Smalltalk. :)

------
_zachs
Anytime I see Smalltalk all I can think of now is design patterns

