The Pooh language / Learnable programming in action

I would like to present my project; it might be interesting in light of the 'Learnable programming' discussion. The Pooh language lives here It has the following features:
  • Does not force to introduce OO concepts from the start; non strict OO viewpoint.
  • Makes flow visible by tracing of the program flow; the -x command line option instructs the interpreter to trace each statement and evaluation results + intermediate values.
  • A focus on readability and clarity in syntax and semantics
    • no statement delimiters - no semicolons
    • all function parameters are passed as named parameters;
    • all variables declared in function are local;
  • Variable must be defined before use, similar to strict mode in Perl; variable is defined if value is assigned to a name.
  • The language has closures and can do objects by prototyping; has higher order functions like map/fold/filter .
  • If a non local variable is referenced, then it must have the prefix outer . ; references to global variables from a function must have prefix global . ; object member references must have prefix this .
  • the Pooh language has green threads / co-routines / generators like Lua; so there are nice for loops like in Python. The local variety of this idea is called Pooh routine.
Thank you for your attention.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

... And the Pooh language

... And the Pooh language has green threads / co-routines / generators like Lua; so there are nice for loops like in Python. The local variety of this idea is called Pooh routine.

What does the IDE look like?

What does the IDE look like?

What does the IDE look like

Right now there is no IDE yet, right now I only have an interpreter that runs as command line program;

I am open to suggestion about how an appropriate IDE for teaching programming should look like. I think that an IDE derived from eclipse would be far too complicated for the purpose of teaching programming;

I think an important requirement for the IDE should be that it is customizable so that is would fit different activities. Examples of different activities:

  • turtle graphics;
  • writing simple 2D games;
  • parsing / playing with words and grammars.
  • robot simulation

What are your suggestions?

Its easy to hack up your own

Its easy to hack up your own editing environment, especially to leverage all the feedback your system provides. Judging from the example activities, you should probably do something like Processing.

Environment suggestion

Do you mean This one ? Thanks for the suggestion, I will look at it.

In any event easy it ain't. I have done some GUI programming and it always turns into a mess ;-)

I'm not sure if you can play

I'm not sure if you can play this game without getting your hands really dirty in UI. I suggest you take something like Ace (might as well do an online IDE) and customize it heavily.

What should the IDE look like

Since you language is based on trace and is meant for education I think it should be a 3 panal IDE:

1) large panel for code. Aggressive automatic syntax highlighting.
2) small trace panel that when executed colors the code panel and line numbers it then produces the output. clicking on a line in the trace should hit the associated line in code panel.
3) a variably sized output panel. This should be detachable and float.

Thanks for the suggestion. I

Thanks for the suggestion. I also think that one panel for code , meaning one editable file is enough for the purpose of education (although the language allows to include files, but that would be for power users)

Now how do you think is the best way to do a read-eval-print-loop in an IDE ?

  1. One way is to split the trace panel into two areas; one area where commands can be entered; the other for trace output
  2. Turn trace output window into a sort of terminal with a prompt where both command traces and new commands can be entered. this option is probably better but its more work to do.

Now with the old REPL one does not have a separate editor window for writing code; a function is entered/edited at the prompt, it becomes part of the interpreter environment / the code;

Here I guess one has two options

  1. The terminal just enters test expressions and commands, what you type here does not become part of the code in the editor
  2. the terminal can edit functions and what you change here will be synchronized with the editor.

I would guess the first option is good enough.

Ah yes, one still needs a window for compilation errors; so that would be a tab with the trace/REPL window.

And that's enough work for two years already ;-)

REPL

I'd say since your language is based on trace you don't offer a simple command line REPL. Rather at breakpoints you allow variable and expression evaluation, which makes it part of the trace and intellectually connected to the tracing not to the authoring function. So I'd say a button on the trace pane that allows the person to enter an expression which gets evaluated and that splits the trace pane.

As for a terminal, I'd say given the trace focus which is fundamentally a dual pane IDE function, i.e. in a deep fundamental sense graphical I'd feel comfortable reduce terminal to something that is impractical. Go ahead and make the language unpleasant outside of an IDE similar to yours.

No one ever programs logo without an actual graphical turtle on the screen. The whole point of the language is the tie between the IDE turtle and the code. Similarly for your trace based system.

____

As for compilation errors, I'd inject them right into the code in RED. It is an IDE take advantage of the fact that you can intermix the output of the compiler with the original source file.

Thoughts

I really like the idea of pervasive named parameters. In my experience, new programmers seem to be susceptible to long function signatures—if the parameters are named, at least the order need not trip them up. The tilde syntax isn’t immediately clear, though; I would prefer something with = or :, e.g., push(array=ret top=func(arg=v)). Also, naming functions is hard enough; now programmers need to name their parameters as well, and will likely give them poor names.

Could you elaborate on your “simplified model of references to values”?

If you’re looking for readable parsing/matching primitives, you might investigate some (Haskell) parsing libraries such as Parsec or Alex.

On an unrelated note, the bright green text on the website is not very readable. You should consider changing it.

more on simplified model of references

Assignment with = copies the value of the expression into left hand side.

Assignment with := makes a reference; the left hand side is now a reference to the right hand side. If the right hand side is a reference then both left and right hand side will refer to the same data.

There is no dereference opererator; if a reference is used then you automatically get the value of the reference.

Is that really simpler? Good question;
It does away with call by sharing, which is a bit ambiguous;
Also I guess that normal usage is simpler because the dereference operator becomes implicit.

On the other hand it doesn't make the runtime faster ;-)

Parser libraries

Thanks for the suggestion on colors; I have fixed them.

Now I have looked at the documentation for Parsec and Alex and Happy; What I don't understand is how they handle ambiguities of the input grammar and left recursion; Any ideas ?

Are named parameters any good?

>Also, naming functions is hard enough; now programmers need to
>name their parameters as well, and will likely give them poor names.

Are named parameters any good? On one hand they add context and make it easier to read code; when one looks at a function call with positional arguments one has to recall the whole function signature just to make sense of what is written on the screen, not very clear.

Finding good names is hard, I agree, but the benefit of added readability is worth the cost.

It is harder to write down a function call when using named parameters, I think here and IDE will eventually help;

I'm interested to see how it look in practive

In theory, I think that named parameters are better than positional arguments because they can provide better readability.
But in practice I'm not so sure: they provide better readability when you call a function with numbers not variable, but you're not supposed to put numbers in the code (aside from defining const value of course) so when you have named parameter and descriptive variable name aren't those two names redundant?
An example:
print(color:color_blue, style:style_bold, text:my_text);

I like the idea of binding

I like the idea of binding values in a call to arguments based on matching type. If there is any ambiguity, then you can specify the name explicitly. So in your case print(color_blue, style_bold, my_text) or print(style_bold, color_blue, my_text). If you have two colors, then you'll have to disambiguate using named params.

The problem with named

The problem with named parameters is that changing a name changes every call site. Some of these call sites may not be in your own code.

Bug or feature?

Cosmetic changes to symbol names (renaming with no intended change to binding) is a problem that exists for non-parameter symbols already and can be mitigated with refactoring tools. If more semantically significant changes to symbol names require you to revisit binding sites, that's probably a good thing.

Cosmetic changes to symbol

Cosmetic changes to symbol names (renaming with no intended change to binding) is a problem that exists for non-parameter symbols already

I'm not sure about anyone else, but I rename function parameters far more often than I rename a record field. Ditto for renox's point about parameter order. I find naming function parameters far more difficult than naming field records as well, perhaps why I end up renaming them so often.

Refactoring tools generally only work on your own codebase, hence why I specified that it's a problem for code that's not your own.

This is (generally) true if

This is (generally) true if the language source encoding is just the entered user text. If your encoding supports explicitly referencing the defined symbol, then this isn't a problem.

Not a new issue

[The problem with named parameters is that changing a name changes every call site. Some of these call sites may not be in your own code.]

Bah, "normal" function calls have the same issue when you change the order of parameters..

Yet another reason why

Yet another reason why programs shouldn't be stored as text and why names should be there purely for the human.

+1. I'm afraid it will take

+1. I'm afraid it will take awhile for PLs to get rid of names as a compiler concern, especially if they aren't co-designed (and dependent) on their IDE.

Not sure

This is a communication issue between the maintainer of an API and the developer who use this API.
Currently when the API change, the compilation breaks, with your mechanism what would happen?
1- nothing change? But the maintainer of an API doesn't change it 'just because' it is usually to help users (better name, order of parameter less confusing).
2- the program view of the developer who use the API would be updated 'auto-magically'?
This is better but it can be a bit confusing, the IDE feature would have to be carefully designed..

Names are just documentation

Names are just documentation provided by the API writer; the API GUID stays constant of course. If the API changes (args are added or removed), compilation will still break, but if just the name changes, nothing happens accept the visualized name will be updated. You could even warn the user of this change by storing a GUI/observed name pair in the source representation and checking against the actual name on compilation.

The same is true of named procedures

Change the name of a procedure, you have to change every call site too. It's no different in principle.

It's the frequency of the

It's the frequency of the change that's problematic. The same name changing can happen to the module name the function belongs to, or the namespace it's in, or the library it's linked to, or the program it forms a part of. As we move up a program's abstraction hierarchy, I find changes become less common, and so name changes are less of a problem.

Syntax of named parameters

A good side of the ~<parameter name> syntax for named parameters is that context is clearer - no way to mix up passing a parameter with assignment.

Although you are of course right that = would be be more obvious and regular syntax.

John, thanks for the suggestion, I would have to think about it.

Following Smalltalk

An idea would be to say that the name of a procedure includes the names of its parameters in a strong sense: two procedures can have the same name provided their lists of parameters are different. Thus you could define (in the famous example) both draw(gun) and draw(picture, canvas). This is like the way in which Smalltalk methods with more than one argument are named. In Smalltalk the named parameters are required to always appear in the same order, so that ifFalse:ifTrue: and ifTrue:ifFalse: have to be defined separately (and usually programmers don't bother), but Pooh would have no need for that.

This idea isn't directly consistent with optional parameters, but it would be easy to make a parameter optional by having an overloaded version of the procedure that didn't have the parameter, but invoked its sibling that did: thus split(string) would be defined to call split(~string x ~separator ' '). By the rule above these procedures would be distinct.

optional parameters

You can't overload functions in the Pooh language - one function name means one function - less problems this way.

You can have optional parameters, and optional parameter means that the value of the parameter is Null, if no value is supplied by the caller. It needs the keyword optional after the parameter name.
By default all parameters are passed by value (i.e. in only). For collections/objects that means the interpreters does some form of copy on write for parameter values.

sub function( param optional )
   if  param == Null
      param = 1234 # a default value is assigned if none supplied
   end
end

I think this rule is clear, but maybe I am the only one who thinks so ;-)

Another thing is that a parameter can be passed by reference (i.e. in/out) , byref keyword added after parameter name.

sub foo( param byref )
  param = 42 # assigned value is passed to the caller
end