Barry - v0.0.11-dev

License: This documentation is licensed under CC BY 4.0. Code snippets are dual-licensed under CC BY 4.0 and the MIT License.

Introduction

At the moment this specification is just as incomplete as the implementation. We make a continuous effort to update this document to be consistent with the implementation as much as possible. We are at a very early stage of development so lessons learned from the implementation effort influence the language design a lot.

Hopefully as we move forward, less and less of my original notes will remain in the document as we rewrite them to comply with the environment.

These kind of notes will mark sections painfully outdated or flat out incorrect. They can still shed some light on the future of the design or the thought process behind it.

The Funky Seal

The best thing about the language is its namesake, Barry the Funky Seal, who is rather lazy, loves fish curry and forestry and looks something like (_*_) when dreaming about interesting ideas.

Your First Time with Barry

But enough of that serious business and let's talk about the fun part: the interesting ideas of Barry. Let's wet our flippers!

"Hello World!"   >> a Str idea, with ominous content!

Yep, I think that's the closest Barry can get to the only mandatory requirement of modern, general purpose programming languages. Barry doesn't know how to print and he doesn't have a teletype either, so that's that.

12                      >> is a Num idea
23 34 45                >> is a List idea of Num ideas
"I'm a quoted string"   >> is a Str idea
.                       >> an All idea. Or True or Yes if you will
()                      >> a Nothing idea. Or False or No if you will
12 "foo" () .           >> is a List idea of various value ideas in it
1 (2 3) 4               >> a List idea with another List idea item
12 ("foo" 43) ()        >> a tree of various ideas

As you can see Barry thinks in ideas. Since everything is an idea in Barry, we won't even say it every time we encounter one. We just say, a List of Nums for example.

Some ideas have multiple names, most obviously the values that a single bit can express. This might be strange at first, but these names are just answers to the fundamental question: what information can be expressed as a single bit? The traditional answer to this question in computer science is truthness, in the form of the True or False boolean values, but Barry thinks that a single bit can also express the extreme limits of extent and that's kind of more useful way of thinking about them. This is how we ended up defaulting the name of these ideas on All and Nothing.

Anyway, these are just different names assigned to the same underlying idea: basically you can call them however it feels right. It's also worth mentioning that All and Nothing are not different configurations of a shared idea kind. The two are different and they mean, behave and interact different in different situations. This doesn't mean you can't use them as bit values: . () . . () . is a perfectly valid List of bits.

To add insult to damage, some idea names are intentionally botched to remind us of the underlying digital representations' limitations. Num is a 64 bit float under the hood, which is adequate for our purposes, but it would be a bold overstatement to call it the Number idea.

All of the aforementioned idea kinds are so called leaf ideas except List. In Barry the List is the most important compound idea and thus the main vehicle of structuring your program and data. With a List of Lists users can describe arbitrarily shaped trees of arbitrary ideas. And that's exactly what Barry is about: building trees of ideas that can be evaluated and mutated during runtime.

In Barry everything is an idea, where every idea kind interacts with the idea tree in a different way. There are similarities of course, so we distinguish value and operator ideas for example, decorators like Comments, which are just another kind of ideas for a different purpose. But still, everything is an idea.

Fifty Shades of Snow

Whitespace is meaningful in Barry, which is kind of relatable knowing that Barry lives on seemingly infinite fields of snow covered icesheets. Another argument in favor of this design choice is that whitespace is meaningful in every language: a sweetheart and a sweet heart have entirely different meanings to Barry.

Luckily, meaningful whitespace rules are rather minimal and will be covered in detail in the affected sections. Be prepared to swallow some meaningful indentation rules and operator overloading where whitespace will actually help to differentiate between different roles the idea plays.

One of the most important and general meaning of whitespace is to append items to Lists. 1 2 3 means a list of three numbers because of the spaces between each number!

1
2
3

The above is also a list, in fact the same list, but with a vertical layout. In the case of vertical lists it's the newlines that append new items to them.

A Comment on Comments

The act of programming involves at least ten times more reading than writing code. Probably much more, as you read back your own code constantly. Barry treats readability as king.

1 2 3             >> _this_ is a Comment idea binded to a line
4 (5 >> Wow!) 6   >> a Comment binded to an item

Comments are little snippets of natural language inserted into the program for different purposes, mostly to describe why are things the way they are. Comment is a decorator, so it does not intervene in the evaluation of the tree. Nevertheless Comments are not discarded during the parsing process: they're preserved on the idea tree as a Comment idea and get removed only during evaluation.

Smooth Operators

Barry uses a fairly standard set of operator ideas to express arithmetic operations on other ideas. Evaluation is the act of reducing an idea to a value.

1+2     >> evaluates to 3
1+2*3   >> evaluate to 7

Grouping operators is also fairly standard.

12 (34 56) 78   >> an embedded list
(1+2)*3         >> evaluates to 9

Operators and values are both grouped the same way: with simple pairs of parens.

In Barry we build idea trees and the expression (1+2)*3 is exactly that. It can be sketched up like this:

    *
   / \
  +   3
 / \
1   2

This idea tree can be evaluated, that means Barry tries to reduce recursively to a single value. Most programming languages are designed around the concept of evaluation. Barry is not. Barry is designed around the goal to help the users create the best idea tree they possibly can. Every programming language has a similar concept to the idea tree, usually called the Abstract Syntax Tree, but it is treated as an implementation detail, a temporary datastructure, that can be thrown away after something evaluatable has been produced.

One's thrash is another's treasure: for Barry the idea tree is precious and evaluation is only one thing we can do with it.

Greedy Little Imps

Most operators try to bind to their immediate neighbours as arguments and if there's more than one operator fighting for the same idea, the final binding order is decided by comparing the bind values of ops in the race.

1+2*3

When parsing the example above both + and * compete for 2. Since Mul's bind value or precedence is higher than Add's, 2 will bind to Mul, and suddenly the idea that Add sees as its right neighbour will be the already bound Mul.

Some operators don't follow this default behavior and instead of trying to bind their immediate neighbours they try to bind to entire implicit Lists if possible. Implicit Lists are just ordinary Lists with the only difference that they don't require explicit grouping, in other words, they don't need a parenthesis pair around them due to their position in the code.

These somewhat special ideas are called eager operators and we refer to implicit lists as imps colloquially. At the moment Label, Eval and Graft ideas are defined as eager operators.

a: 1 2 3
4 5 6 => 4 5 6
_+_ <- 7 8

In all the above examples the operators bind to the entire list after or before them, instead of their immediate neighbour. Label a: gives name to the List 1 2 3, Eval injects the evaluated result of the List 4 5 6 and Graft substitute the List of 7 8 into the two Gaps of the Add.

Of course if the default behavior is not what we want, with explicit grouping we can override the behavior of eager operators just as we can override the binding of ordinary operators.

(a: 1) 2 3
4 5 (6 => 6)

Labels also support imp termination, which means they terminate the implicit lists started by earlier Labels in the line.

a: 1 2 b: 3 4 => (1 2) (3 4)

Eager operators intended to provide better readability by reducing the need for explicit grouping by parentheses.

Pump Up the Jam

In Barry's eyes, his universe is the best possible universe of all universes for the simple reason, that that's the only one he perceives. This makes him so understanding and patient towards the state of affairs, that he finds it really hard to see something as erroneous. To be precise he doesn't really get the idea of an error at all: like it or not, things are the way they are.

Despite all the understanding and patience in the world, sometimes there are consequences to the fact that things are the way they are, and sometimes they lead to circumstances that makes evaluation impossible. While there are no errors in the system, these situations can most certainly jam the evaluation process. The canonical example is a division by zero.

When evaluation is impossible for some reason Barry returns a jam instead of a computed value. This returned jam propagates over all evaluation paths leading to the jammed idea. This also works something like the maybe pattern in other languages, but it's built into the language and applies in general. A jam can also carry additional information about the jam, most importantly a message and an address to the idea where the jam occurred on the tree.

You can create jams by binding the ! prefix operator to a Str value, and you can of course also return it to initiate your own jam on the tree.

!"ohh my"   >> A jam

Now Barry is Different

Evidently Barry happens to be a little off in some departments. Luckily these deviances are mostly only differences from other programming languages.

To achieve it's intended goals, Barry facilitates some fundamental rules, that might be hard to appreciate at first, without seeing the language that they enable. At the same time if we don't know these rules, it's hard to imagine that such an almost primitive language can be expressive and general at the same time.

The following sections are short introductions to these concepts with examples that can contain code constructs not yet discussed. Do not worry is some doesn't make sense at the first read. Feel free to come back later after the details are filled.

One Tree to Rule Them All

Barry has a quirk, a tick, a bad habit. Barry compulsively turns Lists of a single item into that single item. It's not that Barry has a problem with single item Lists, it's more like, that the two are indistinguishable in Barry's eyes.

(1) = 1            >> evaluates to .
"Wow" != ("Wow")   >> to ()

As we mentioned, we call this the single item rule or colloquially SIR. You might feel some nostalgia for the ability to distinguish a single item list from that single item, but on the sunny side, their indistinguishibility also means that you can do things you would with a single item list. For example you can append two non-list ideas together, to form a list of that two ideas, which is the minimum number of items that justifies the existence of a List idea. You can add ideas to nothing, or even to everything, which is epic.

At first glance, it may seem, that applying SIR is removing structure from the tree. In fact it's something quite the opposite. SIR is removing noise from the tree making the structure canonical. It removes ambiguity as a single item list in a truly recursive system is just two ways to express the same thing, and in practice leads to questions like "is an item equal to a list with that single item in it". Now in Barry's eyes these kind of questions are best kept unanswered.

There is another extension to SIR (that's obviously contradicts the name): empty Lists become a Nothing idea. Again it's not that there's no such thing as an empty List, but it's just Nothing. This also sheds some light on why we write Nothing as (). Probably a name something like prune would be more fitting and common reduction would be more precise, but they would still mean the applying of SIR. So that's that.

Mind the Gaps

We already met the basic leaf value kinds, but next to Num, Str, All and Nothing there are another leaf kind that is not a value at all, but quite the opposite. The Gap idea expresses a hiatus of a value, a piece of withheld information, that's otherwise necessary to evaluate a result.

Gaps are represented by underscores (_) in the standard notation, and they can initiate the forming of arbitrary complex trees called stems, with an arbitrary number of unfilled locations called slots. These slots are exact locations on the stems where other branches can be grafted later.

addOne: 1+_     >> adds 1 to something
join: _+"/"+_   >> joins two ideas together with a "/" in-between

Stems are not as powerful as functions as they don't support recursion by themselves, but they're much more flexible as they all happen evaluation time. Stems are the first examples of trees as evaluation values.

Since stems are values you can freely compose them by grafting a stems on the gap of another one. This will produce a new composed stem that can be further reused, and so on.

_*_ <- _+_ => (_+_)*_
a: _*_
a+_ => _*_+_

We will talk about stems a lot in Fish Curry Funks Good section.

A List of Differences

Barry considers itself a spiritual successor of Lisp, that looks and feels quite different, but nevertheless it builds on the same basic principles as its forefather did. Most importantly data and code are of the same nature, and shares the same namespace. Despite this close relation, Barry frames things quite differently. Instead of stressing the importance of lists it puts the emphasis on trees. While lists play an absolutely essential role in building a system like this, Barry still treats Lists as only one essential building block of idea trees.

We will talk about Lists a lot, since a large number of the language's features are concentrated around this single idea. In this section we only discuss how the List idea handles Gap members and how we can sidestep this default behavior.

The rule is simple: Lists can't have Gaps in them. The system pro-actively removes Gap ideas in Lists, in other words the Gaps are interpreted as deletion requests.

1 _ 3   >> this input becomes `1 3`

This rule is in place primarily because Lists have to terminate stem propagation to be able to express a list of stems. So an ordinary List idea can not be a stem, to provide a natural boundary for stems. If this rule won't be in place any Gap idea anywhere on the tree would turn the entire source into one big stem with one slot in it.

Now, there are some situations when we need stemmed Lists. The creation of stemmed Lists can be explicitly initiated by grouping items with curly braces ({}).

{1 _ 3} => {1 _ 3}

Stemmed Lists can be used to construct stems that need unfilled slots in a List, for example as a function's argument, that expects a List as one of its argument. If this doesn't make any sense at this moment, that's fine.

The End of All Differences

These unusual rules allow Barry to be simple and coherent. They're inseparable parts of both the language itself and the environment's implementation.

To be honest the list of differences doesn't end here, as the concept is based on a fundamentally different implementation model, where the environment keeps the idea tree in memory and able to render the textual representation and provide editing capabilities.

The examples you read are just textual representations of idea trees in a hopefully human readable form. In other words Barry is a bi-directional programming language: the system is able to build the idea tree from the text, but it can also output the textual representation of any tree in memory, that will produce the exact same tree when read back. The whole environment and the user experience it provides is based on this capability entirely.

In other words, the Barry Standard Notation or BSN is just a serialization format of the idea tree. This capability influences the design a lot, because when we add a new language feature it's not enough to be able to parse it correctly, we always have to provide a standard way to output the construct too.

Luckily that means, that while being somewhat different to other languages, at least Barry is identical to itself and that's refreshing.

The Magic of Computational Forestry

Forests are magical, trees are magical, seals are magical. Everything is magical. Is Nothing magical? Is nothing something? Anyway, trees are especially magical in the context of computing, because they grow downwards. Once you see it, you can't unsee it, but luckily this doesn't seem to bother anyone.

Either it's because in western cultures we read top to bottom, or it's because of our deep adaptation to oppressive top down power structures, but this became the norm. Trees grow downwards in computers. Root is at the top, leaves are at the bottom. These are actually roots if we want to be consequent, and I imagine there must have been some actual attempts to call them roots, but that most probably made it kind of hard distinguish the root itself from its root. So that's that.

Luckily roots are trees topologically, so I guess everyone just looked the other way. Including Barry. Barry says it's best to think about these trees as ones growing on the inner surface of a hollow planet. Now, that's Barry.

What you should take away from this silliness is that when we say upstream we're talking about the children to parent direction and when we say downstream, we're referring to the parent to children direction.

1+2
3 4 5

Both 1 and 2 are a child of an Add idea and 3, 4 and 5 are the children of a List idea. And the two vertical lines form a List with an Add and a List child. The entire idea tree is traversable from any idea in it to the root upstream, and can be recursed down to the leaves downstream along parent-child relationships.

The Hardest Thing in Programming

If naming is the hardest thing in programming (not counting cache invalidation which doesn't sound too hard), then programming must be an easy endeavour. Unfortunately naming involves the definition of boundaries around the things you name. It's significantly easier to come up with name "seal" than to tell where the concept of a seal starts and where it ends. You can stare into this abyss, if you ask yourself the question if Barry is a seal or not.

Names are created by Labels.

x: 1           >> This is a labelled Num idea
x              >> evaluates to 1
1 (y: 4) 3 y   >> to 1 4 3 4

Names propagate sideways and downstream. This means that in a List a labelled item can be referenced by both its siblings and its descendants.

(a: 1) a (a a) => 1 1 (1 1)

In Barry you can attach a Label to any idea on the tree. Names are always registered on first non-Label upstream to the Label idea that assigns it.

(a: 1)+a => 2

The a: Label is registered on the parent in this case the Add idea, and since the right argument is a child of it, the Ref at that position will see and resolve the a name.

Barry doesn't produce errors when a name is not resolvable from the point of reference. An unresolved name produces a dangle, that is a possible state of a Ref idea.

1 a 3 4   >> not an error, `a` is a dangle, typeset in middle grey

Dangle is just a short name for unresolved references. Treating dangles as normal accepted part of the code underlies the mechanism of hoisted references.

1 a 3 a: 4   >> evaluates to 1 4 3 4, despite the reference precedes the label

When the parser reaches a the Ref idea, it becomes a dangle, so it gets registered under that name. When the parser reaches the label definition, the registration process discovers the already registered dangle with that name, and calls all dangles with that name to re-resolve themselves.

x: 1
p: x y   >> this evaluates to 1 2, despite y is further down in the input
y: z: 2

Yes, on the last line we complicated matters by attaching two Labels to 2 in vain, just to demonstrate that in Barry you can assign multiple names to the same idea.

Seals Are Funky

As we all know, seals are magical creatures. Now to add just a touch of mystic sheen to the syntax - that can appeal to the opposite sex if the opposite sex is male - sometimes we use squiggles to name things. For the aforementioned (or whatever) reasons we call these squiggles seals. For example the Add idea is represented as + in the code. Now that's a seal, probably a very positive one.

Seals increase the magical cuteness of the code, making it more readable and shorter. 1 add 1 or even add 1 1 is readable to some extent, but 1+1 is just more natural. You already encountered several seals like : of Label's fame, the arithmetic operators + - / * or >> for Natlang.

The good news is that seals are mostly just names of operators. What's interesting that they're allowed to be stacked, that normal names doesn't allow. The rule of seals is that the parser will always prefer the longer seal if there is any ambiguity. For example both ! (Jam) and = (Equal) are defined in the language as a single-character seal, yet when the parser sees != it will produce a Inequal idea.

Walking the Lines

In Barry we refer to the root node of the idea tree as Shebang. In other words Shebang is the idea that the entire source produces. Except for really simple or artificially obfuscated code, it usually ends up being a List.

Now consider for a moment that the next two examples are both constitute the entirety of their source code.

1 2 3

In this case Shebang is a List of three Num ideas.

1
2
3

In this case Shebang is also a List of three Num ideas. This might be strange at first, yet it's kind of natural at the same time, as in both cases we set out three numbers.

In Barry Lists can be laid out both horizontally and vertically. It's entirely up to the user to decide which layout they prefer in a certain situation: everything that's expressible in a vertical layout remains expressible as a single line too.

(a: 1 b: 2 c: a+b => 3)

Is the same as

a: 1
b: 2
c: a+b => 3

Dressing Up Penguins

In Barry we distinguishes a class of nodes called sides that don't participate in the evaluation process. Practically they behave transparent in that context. They're essential to build up the flow of evaluation, the best example being Label, which enables symbolic referencing, but doesn't modify the values passing through it during an eval run.

Some ideas are not sides, and these can become meat ideas for side ideas. As we build the idea trees side ideas maintain a reference their belonging meat idea, and pass this along, that allows the user to form chains of side ideas.

a: b: \ 12 =>

In the example above we have one single meat idea, of course the Num with the value 12 and all the other ideas defined on the line are side ideas located upstream to the meat. Nor Eval, nor Extern, nor Label intervene in the evaluation process. One injects the result into the render, one emits a log line if non-cached evaluation flows passes it, one assigns a name to an idea. In this example the chain the line produces is Label-Label-Eval-Extern-Num.

Currently Label, Eval and Extern are the tree idea kinds defined as sides, all the other kinds can become a meat. The meat of a side is always the first non-side idea on the tree downstream.

a: b: 1 2 3
c: 4+5

In the first line a: and b: are the side and both has a reference to their meat, which is a List of three Nums. The three Nums are not meat, only the topmost idea is, that attaches to the first side idea. In the second line it's the Add, that has two Num children that are not meat.

Breakdancing on Ice

Barry's syntax is carefully designed to allow users to write their entire program in one single line. For some reason some programmers prefer another approach, namely to break up their code into vertical lines. This is somewhat understandable, since this approach utilize both dimensions instead of just one.

We can initiate the vertical layout of ideas with the help of meaningful indentation rules of the syntax. Indentation signifies the presence of a break, which means laying out an idea vertically. Basically we're breaking long horizontal lines into multiple shorter horizontal lines stacked vertically. All non-side ideas can be laid out vertically.

The Unbreakables

Laying out a Num idea vertically seems to be a dubious adventure, but we provide this facility to sidestep ugly layout caused by long names.

my_humble_but_very_important_idea:
  12
my_humble_but_very_interesting_calculation:
  1+2 => 3

In some circumstances this notation might lead to a better overall layout. As you can see in the second example, postfix sides of non-list ideas get written in the same line as the idea itself.

Breaking Lists For Good

This might be preferable in some circumstances, but where vertical layout really shines is is the List idea of course.

a:
  1
  2
  3
:
  4
  5
  6

Increased indentation tells the parser that the user wants to continue the previous line as a vertical List. But vertical Lists always have to have a header rooted at the indentation level where they belong. The example above produces a List of two Lists both with three items. The first List is labeled with a: the second is anonymous. The indentation of the lone colon communicates the parser where we intend to root the anonymous List we want to lay out vertically.

This can produce really neat looking layouts.

a: (1 2 3) (4 5 6) (7 8 9)
b:
  1 2 3
  4 5 6
  7 8 9

a: and b: will produce the same result, as vertical layout is only affects how we, well, laying out the tree.

Prefix side operators attached to the list are written to the header and similarly we need a footer for postfix side operators.

a: (
  1+2 3+4
  5+6 7+8
) =>
  3 7
  11 15

Footers start with ) for normal Lists, but stemmed Lists' footers start with a } of course. Stemmed Lists need a footer even if they have no postfix sides attached.

a: {
  1 2
  {_ 4}
}

Breaking Arguments

Postfix non-side operators' arguments can also be broken and while this provides a similar look to vertical lists, argument breaking is governed by somewhat different rules. Infix operators can only break their right arguments and postfix operators can not be laid out at all.

floor
  1.5 => 1
max
  -1
  1
_+_ <-
  1
  2

Laying out arguments of conditionals particularly useful.

if a>0
  1
  2

Operators can decide themselves where their right arguments break. For example if keeps the first argument in the line where it stands, and only breaks the second and third argument.

Ruling the Break

The most important rule governing all break operations is that an idea can not be broken if it's not a child of an idea that is already laid out vertically. In other words only an idea occupying its own line can be broken into vertical layout.

a: (1 2 3) (4 5 6)

In the example above we can't break 4 5 6 in itself, because it doesn't have its own line as it's part of a horizontally laid out List. We can only break it if we already broke the parent idea.

a:
  1 2 3
  :
    4
    5
    6

This produces the same tree as the previous idea, but laid out vertically.

The Truth About Barry

1 = 2 => ()
3 = 3 => .

It might look strange if you're coming from the C side of the world, but at least it reads nice and natural despite all the heredity.

Barry is pretty chill at most of the time, but if equality is at stake, he can get pretty dramatic: suddenly it's an All or Nothing question. Again, these are just synonyms for true and false. Feel free to read the examples above as "one equals two evaluates to false" if you don't like the sound of "... evaluates to nothing". You can get a feeling of how commutable these concepts are if you think of it as "all threes are equal to all threes" for example.

3 != 4  => .   >> as != represents the Inequal idea
. = .   => .   >> as everything is everything, as we all know from the song
() = () => .   >> as nothing is nothing, there must be a song about this
3 != () => .   >> as 3 is something and that's not nothing
3 != .  => .   >> as 3 is not everything
0 != () => .   >> as 0 is not nothing, it's a number that happens to be 0

In other words equality checking is pretty strict.

So what?

This rigor can be loosened up with the so-called So operator represented by ? in the code. The So op reduces any idea to one of the extremes: All or Nothing.

1?      => .
0?      => ()
"tuna"? => .
""?     => ()
1/0?    => ()

Barry considers Nums with the value of 0, empty Strs and Jams to be more nothing-like, so So will reduce them to Nothing. Of course we can use So to construct truthiness checks.

Only Love is Unconditional

Conditionals are just operators like any others. The if operator expects three arguments, the first being the condition, then the idea to return in case the condition evaluates to True and lastly the idea to return on False.

if 3>2 "Yay!" "Nah" => "Yay!"
if 1=1 "Yay!" "Nah" => "Yay!"

Like any operators with right arguments, you can break If's arguments to be laid out vertically. The system treats Ifs a bit specially as it will keep the first argument in the same line with the idea's name.

if 3>2
  "Yay!"
  "Nah"
 => "Yay!"

A Fine Selection of Conditions

The Select idea allows chaining multiple condition-value pairs and a default value in an ordered List. Select has a single argument and Barry expects it to be a List of Lists of two items, one for the condition and one for the value to be returned if the condition evaluates to All. The List can be arbitrary long, but the last item is special as it's the value to be returned if none of the conditions evaluate to All. In other words the last item is interpreted as one single idea as opposed to the items before it.

a: 21
select
  a=1 "one"
  2=2 "two"
  3=3 "three"
  "Too much!"
 => "Too much!"

Fish Curry Funks Good

We already touched on the theme of Gaps in the code, when discussing Barry's striking differences to other programming languages. Barry is about building computational trees from text and Gap ideas let the user define these trees as incomplete. During evaluation when the system encounters a Gap, it starts to form a stem instead of reducing incoming values to single values.

_+_ => _+_

This simple stem of an Add with Gaps for both of its arguments evaluate to itself. This doesn't mean that all stems evaluate to themselves though.

(1+2)*_ => 3*_

Since stems form during evaluation runs, branches that can be evaluated do reduce just as they normally would. This means that only the paths that are affected by the presence of one or more Gaps needs re-evaluation when we fill the Gaps later. We call this process chewing and this state of a branch chewed.

Again, because stems are forming during evaluation you can compose them with ideas just as you would compose leaves and ops.

addOne: 1+_            => 1+_
addOneAndDouble: addOne*2   => (1+_)*2

Stems don't become functions in Barry. It's the other way around: functions become stems. You can't call a stem like you would a function.

addOne: 1+_
addOne 2 => 1+_ 2   >> a List of a stemmed Add and a Num

If we want to evaluate a stem with filled slots, we need to use the Graft operator idea. Slots are filled in the same order as they read in the stem.

myAdd: _+_
myAdd <- 1       => 1+_
myAdd <- 1 <- 2  => 3
myAdd <- 1 2     => 3

Here we grafted simple Nums into the slots. Note that we don't have to fill all the slots, and that will result in a stem with fewer slots naturally. By passing a List to Graft we can fill more than one slot in one go, which is computationally advantageous. And of course complete trees can be grafted on stems too in the form of other stems.

myMul: _*_
addOne: 1+_
addTwo: _+2
ohMy: myMul <- addOne addTwo => (1+_)*(_+2)

ohMy is a stem grafted together from three other stems.

I Wants to Get Funked Up

All sections below need a considerable rewrite. Basically they're my original notes from the times of the inception of the project. Information in them thus might got flat out incorrect since. I left them here instead of removing them for future reference.

It's no wonder, as "Funk is the absence of any and everything you can think of, but the very essence of all that is", as Bootsy Collins nailed it so precisely.

Stems doesn't provide means to define recursions in themselves. For that we need to define our own functions.

f: x -> 1+2*x   >> a function definition
f 3 => 7

f': a b -> a+b*3   >> multiple function arguments
f' 1 2 => 7

hw: -> "Hello " + "world!"   >> a really pure function with no argument, epic

With the Define idea which is represented by -> you can define a new operator. If you hang a label to the operator definition, you can even use this operator elsewhere in your source, which is pretty useful.

You might be a bit disappointed to hear about operators if you wished for pure functions deep in your heart. Luckily operators can be functions if they happen to be pure as fresh arctic snow, at least in the sence, that they're deterministic. It basically means that they are guaranteed to evaluate to the same result given the same arguments.

Since all machine instruction changes the state of the underlying machine, even the deeply admired nop instruction increments the program counter, Barry think it's better to lift this somewhat unrealistic requirement of not having side effects on functions. Now just as in case of pills, we still prefer functions that don't have side effects, or at least have as few as absolutely necessary. Anyway Barry acknowledges that sometimes they will, and looks the other way.

Now, that both imperative imperials and somewhat functional rebels can lie back comfortably, and call Barry a traitor, we can raise the question: what the hake is an operator anyway? It's simple. An operator is a list that evaluates to its last item instead of the entire list. Basically inside of an operator you can use the operator's list as a playground and only return what you want from it, after you fooled around.

f: ->
  "first"
  "second"
  "last"
f            >> evaluates to "last"

Now that's silly, you might think and you're absolutely right. Anyway we can try to use Barry's silliness to our advantage.

f: x ->
  y: 12
  x+y
f 3       >> evaluates to 15

In this case returning the last item makes more sense as otherwise the result would be y: 12 15 . A list of a labelled constant and the result. Now, nobody wants to see those innards, are they? Anyway, you can approach the concept from the angle of multiline codeblocks in other languages, which can help to turn your head to the right direction, but it also becomes misleading soon as Barry has no real concept of lines. Only lists.

If you happen to be very clever, you might already suspect, that the the source, the top level of the tree itself is an operator and evaluates to its last item, and you would be spectacularly wrong. It's not. It's just a list. If you want the source to act like an operator you have to explicitly state it.

->
  a: 1
  a+1

>> now . is an operator and . would evaluate to 2

A blank idea can be used to signify the location of the operator name in the argument list and to define postfix and infix operators.

%: v _ p -> v*100/p
2000 % 50                 >> evaluates to 1000

Since most seals are just names, seals can be used to label new operator definitions just like ordinary names.

Barry's a great fan of the modulo operator and sees the utility of percentages as something fainter, but if the programmer decides to redefine % to her own liking, he just looks the other way and thinks about something else. Names propagate downstream so such a redeclaration is only visible to the descendants of their context.

Not all operator ideas are nice enough to call them functions though. Some operators are designed to evaluate to different values on different calls, like random generators and time related operators for example. Some even change the state outside of their own family.

The Name of All Things Except Nothing

We said that references in embedded or child lists can see the labels defined in the outer or parent list.

outer:
  a: 1
  b: 2
  inner:
    a+b   >> evaluates to 3
    b+c   >> to 5
  c: 3

This raises the question if we can do the opposite and reference things from the outer list inside of an inner one? If naming is the act of organizing All things into groups or sets and hanging Labels on these divisions, then it seems logical to use All as an operator on names for this job. What else, really?

fish:
  name:  "Kilgore Trout"
  kind:  "trout"
  count: 1

fish.name   >> evaluates to "Kilgore Trout"

With the All operator we could reach a labelled idea inside an embedded List. If we combine these two rules even ideas in sibling lists can be accessed easily.

p:
  x: 1
  y: 2

p`:
  x: p.y
  y: p.x

p`: evaluates to 2 1

Since upstram labels are visible from downstream ideas, p is visible from p', and with the All operator can access names inside that list. If you squint you can look at it as if the All operator would make p the all for the next name lookup. It might sound forced, but the concept of giving names and than reffering to them and the concept of all the things is really very closely related. At least in Barry's eyes.

There must be no whitespace between the all operator and the name, as with whitespace after it, it's parsed as an All value instead of an All operator. Yes, the All idea is overloaded. There's an All value and an All operator. Please don't tell anyone. Anyway, that's an exception and since All represents everything we could have botched it much more. Actually we did, but it's too early to confess that yet.

Rangers of This Universe

A Range is specialized compound value idea, that expresses a continuous range of Nums between two Nums.

[1 10]   >> the range between 1 and 10 including both endpoints
[1 10[   >> the same ranage excluding 10
[9[     >> the range between 0 and 9 excluding 9
[-9]    >> the range between 0 and -9 including -9

Ranges are a new idea to the language so they're not finalized yet. The plan is that we will support arithmetic operations on them in a way that a List of Ranges could describe arbitrary patterns. Another planned feature is to be able to generate series of Nums based on Ranges.

The Blissfull Ignorance of Operators

You might have realized that I tried to emphasize that the rule of upstream labels being visible to downstream references only applies to Lists. Operator definitions hide upstream labels except for operators defined upstream.

f: x -> x*2
a: 1
f': y -> f y+1   >> this is valid as f is visible from f'
f'': y -> y+a    >> this is invalid, as a is an unquoted Str

Evaluating f'' from the above example will produce an error as a will be an unquoted string, that can not be added to anything. This rule intend to provide a relatively clean namespace for operators to work in.

It's a Family Matter

When it's absolutely necessary operators can access their parents' namespaces by piling multiple All operators on top of each other, forming a so called relative reference.

a: 1

f: x -> x+..a   >> relative reference

Now since parents and their children are considered relatives, we call this a relative reference, and because All is everything and the absolute truth at the same time, we call references starting with a single . absolute references.

If you start a reference with a single . that name will be looked up in the topmost idea of the tree.

x: 1
l:
  x: 2
  l':
    x: 3
    r: .x+1   >> absolute reference
    r': x+1

l.l'.r    >> evaluates to 2
l.l'.r'   >> evaluates to 4

Since we redefined x we need to tell Barry that we are referring to x in the root namespace and not the local one.

Barry stronly believes in the privacy of families, so it prefers this relative naming over abolute ones even in lists. Absolute references are epic but also fragile. Relative names move with the parents if the parents are relocated on the tree.

OCD for Lazy Persons

As Barry is liberal at heart, the parser accepts a lot of input that looks a bit different from what Barry outputs as standard notation. Among other things, this means that Barry is it's own formatter and normalizes input to standard notation by architecture instead of tooling.

1+1                                 >> sn is 1 + 1
"Wily" >> Fish! >> "hake" "knitten"   >> sn is "Wily" >>Fish!>> "hake" knitten

Yes, even Natlang's get formatted in certain situations.

This architecture has the potential to bring world peace itself closer to reality by rendering the tabs vs spaces kerfuffle moot, once and for all. At least in the context of Barry.

Mutators are Volatile

Not everybody likes mutants the same, but everyone has a place in Barry's huge heart of warmth. Barry has no problems with mutants, and he quietly suspects, that somewhere deep inside everybody might be a mutant somehow.

->
  x: 3     >> evaluates to 3, just a labelled Num
  x := 4   >> to 4, using a set operator idea on x
  x        >> to 4, operator returns 4

Set is a mutator idea as it changes the idea tree. In Barry, automatic upstream name resolution stops at operator definitions, so you are only able to mutate things inside of a function itself and downstream without using explicit relative or absolute references.

Since most operators are meant to return, Barry is just to lazy or liberal to care about what they are mutating inside themselves, until they behave deterministic.

x: 3
m: y -> ..x := y   >> m is a new mutator operator
m 4                >> evaluates to 4
x                  >> to 4 as value has been mutated

Non-deterministic functions are usually also mutators in some sense as otherwise they wouldn't be very useful. A random generator either needs to advance a seed somewhere outside of the function or rely on something that is constantly mutating anyway. Counters and clocks are very similar in this regard. What's important is that mutators can be discovered by examining the tree without ambiguity.

You might ask what happens if you evaluate this source again? The short answer is it evaluates the same, because x: 3 also reevaluates during reevaluation.

After running the source Barry might show you the end state of the tree after returning with all the effects and end results of mutations occured on the tree, but it always keeps the source's state before evaluation. Because the source is that: the state of the idea tree before applying mutations it defines on itself.

There are some fundamental mutators like rename and rip and you can write your own ones to botch up the tree anyway you see fit. Basically Barry lets you edit the source and bang it several times until it proves useful.

A Single Source of Soot

If you're as unhinged as Barry is, you might even raise the question, what's the difference between a change initiated by the user and a change initiated by the tree on itself by a mutator? In a sense not much: the idea tree just changes for whatever reason. On the other hand if the change is initiated by the tree itself, it is deterministic, so we can reproduce any number of those changes given an initial state to start from.

The act of starting the idea tree to mutate itself is called bang, because "banging the source" sounds much more appropriate and family friendly than "executing" it. Running a tree was also a candidate but since neither trees nor seals have legs the name "bang" came out on top in this case as well.

\bang .   >> start mutating the source

The \ before the operator tells Barry that this request is coming from the outside world, in other words it's not part of the source. Then what is it?

Now, the program you write can be as many nested layers of ideas as you see fit, nevertheless the idea tree always roots from one single idea. And this root idea kind of represents the entirety of the idea tree. For Barry it seemed that the All idea is the prefect candidate for this job.

\rip .   >> Good bye!

In this example rip sends All to a one way trip somewhere. As it does with everything you throw at it. In other systems it would be called something like "deleting the source" or worse, but that's just rude. Barry also thinks that it's kind of silly too, as he doesn't see how ideas could be deleted at all. How do you delete 3? Or +? Barry justs send them away with rip, when they're not interesting enough to waste precious memory on them.

Inside the Outside World

The most significant difference between the outside world and the source itself is that the source is timeless: it only has a current state. The \ or Extern idea plced in the source externalize the evaluation of that point of the tree that will cause a persistent timestamped log line to be produced. We can use this to debug the cache behavior for example.

Banging the source is the controlled way of mutating the tree into a sequence of states.

It's Just a Matter of Time

One interesting question regarding mutatiors is when do they change the tree, and that leads to the most interesting question: in what order. Until the point you start to use mutators the order of execution doesn't really matter, since references work independently from the reffered labels definition order.

a: 1 b: 2 a+b   >> evaluates to 1 2 3
a+b a: 1 b: 2   >> also works evaluates to 3 1 2

On the other hand the execution order mutators can change the outcome of an operator.

->
  a: 1
  a := a+2
  a := a*3   >> evaluates to 9

->
  a: 1
  a := a*3
  a := a+2   >> evaluates to 5

Mutators execute in a left to right top to bottom fashion, exactly in the order of their underlying lists, or in other word: as they read.

More Time to Talk About

The concept of time can be confusing and intimidating, and is also a source of a never-ending stream of misunderstandings among otherwise seemingly intelligent beings. It also happens to be one of, if not the single most important and successful invention of all times. Time is an abstraction of change. The discombobulation roots from the simple fact that time happens to only exist in our imagination.

Time travel is actually possible, in fact it's quiet easy, given you accept the fact that it's only possible in your imagination, because time itself happens to only exist there. In other words, what exists in a perceptible and measurable fashion is the moment of now and the change of state. Change is a bit tricky as we need memory to compare two moments, which is implemented in the reality that's changing. Luckily Barry also happens to deal with imaginary abstractions, so we don't have to deal with these disturbing details. Time travel is a breeze with Barry.

Keep it Simple Silly

Mutators are fun, mutators are necessary and mutators allows the programmer to express algorithms orders of magnitudes slower than their pure functional counterparts, which usually also happen to read better and on the long run easier to reason about.

Branches without mutators can be simplified confidently, while parts with moving part are just not. Basically parts targeted by mutators must be held intact during evaluation.

1+2*3           >> no moving parts can confidentally simplified to 7
t: 1+m: 2*3     >> must be kept intact as it's a target of a mutator
t.m := 3            >> now t evaluates to 10

These toy examples are just quick demonstrations of the underlying phenomenon, they doesn't really show the possible implications this can have.

Luckily Barry is doing everything in it's power to help you bring your source to the best shape you can. Simplifications done by other programming languages are kept from the programmer most of the time. Barry can suggest and apply simplifications on the idea tree as you edit it, and can show how a mutator holds a section hostage, by marking locations targeted by mutators.

Often mutated parts can be kept isolated and as these parts are usually data structures and not program code. Not being able to simplify those is a much lesser problem as it doesn't affect performance that much and kind of natural too.

Theoretically with mutators you can write code optimizers on functional parts of the tree that will produce functions specialized on a large input. For example you can produce a grep optimized for specific settings that will run faster on large datasets than a generic one.

Measure Twice Cut an Infinite Number of Times

Barry calls information originating from the outside world measurements. Measurements are information that Barry would be not able to recreate for the exact reason that they are originating from outside the idea tree. Measurements get recorded as time series data, for the exact reason: that they are unreproducible by Barry.

This can happen during an ongoing bang. For example a game can record every keyboard stroke and mouse input coming from the user and from that Barry can reproduce the entire game run later since it's deterministic nature. Which is neat.

Even more interestingly the source itself is treated as a measurement: a measurement of the quantum state of the programmer's brain, regarding the best possible idea tree it can produce at the given moment. Because of this, changes on the source code by the programmer get recorded in exactly the same infrastructure.

And that's version control from Barry's viewpoint. Again, version control is not implemented by tools, but by architecture.

To Infinity and Back

Computers are awesome. If you're dealing with trees. Otherwise not so much. Let's suppose I decide to build an application that lets the user sculpt with her computer. After some years of heroic effort, which if succeeds, most probably involved trees to effectively store and process the clay particles and/or voxels, I end up with a probably useful and marketable tool. And that's tool is also most probably inferior to the real thing: a kilogram of good quality sculpting clay. If you're not convinced think of sculpting as a domain specific quantum programming language that runs on the most advanced specialized quantum computer humanity could came up with during the milennias: clay.

On the other hand, if you want to deal with large amounts of information organized into trees, then computers are absolutely awesome. Luckily dealing with trees of information also happens to be the easiest thing to do with computers. Barry suspects that the two facts might be related: tools tend to be good at things that are easy to do with them.

Dealing with trees is straightforward with computers, because code that processes information can be organized similarly to what the tree describes. When I want to output the standard notation of the idea tree I just need to write the stdn method on every idea. A Num will output it's value, + a "+" character and its left and right arguments. Ideas just need to call the stdn method on their arguments or items in case of lists and the tree renders itself. I just need to care about rendering each idea, the tree itself emerges from the links between the ideas.

It's called recursion: a function calling itself. Walking trees is just one example of what you can do with recursion. Another useful construct one can express with recursion is loops. A function calling itself is basically a loop. If there is no stop condition it's an infinite loop, which is the basis of application user interfaces and networking among other things.

You might be aware, that in some languages this would lead to an ever growing stack with each cycle, which would cause infinite loops to eat up the computers memory without any real benefit. The truth is that if a recursive function returns the result of the recursion verbatim to the caller, then there's no need for a new stack frame. Even Barry can recognize these circumstances and recognize that there's no need to create a new stackframe with each call: the last recursive call can pass back the result directly to the caller that initiated the chain of recursion.

This technique is usually called tail call optimization in other languages. Since in Barry the last line of an operator is the return value this pattern is easily recognizable in the stdn too.

count: i stop ->
  if i = stop
    i
    count i+1 stop

This should be just as effective as a while or for loop in other comparable languages.

Cache is King

Now the easy part: cache invalidation. Imagine that you succeeded to build a source that you like so much, that you want to bang it multiple times. You also happen to work on one of two computationally expensive branches. You practically don't touch one of the branches. You're probably the patient type if you reached to this point, but evaluating one branch is already expensive in itself, so it would be nice to store the result of the unchanged branch instead of calculating it.

When reading back a result from possibly persistent storage is faster than calculating it constantly over and over, everybody thinks about caching and sighs with sad resignation.

Barry's slow but mostly deterministic behavior guarantees that any result arriving on the tree can be confidently cached. Cache invalidation propagates upstream kind of obviously. One of Barry's favourite occupation is rebuilding caches from other cached sub branches. What makes Barry scratch his head - which is harder for seals than you think - is what ideas to cache. Which locations on the tree are the best candidates for caching?

Barry plays a little game in his head, to come up with acceptable answers to this question. He assigns a cost to ideas, because for an eternal being the idea of a cost is morbidly entertaining. So Barry immediately assigns three costs to ideas, because that's even more entertaining. These are time, storage and bandwith. From these associated costs and information about currently available resources, Barry can figure out which ideas are the better candidates for caching in the given circumstances.

Interestingly enough, from this perspective we can think about measurements as ideas with infinite cost, because they just cannot be reproduced by any means. Basically measurements are results that are always cached and cannot be invalidated by Barry: only the user can rip them.

The Hyperdimensional Telescope

Until now we accessed items by their name, but in computing it's also very common and useful to access items by their numerical index in the list they are in. The At or @ idea allows accessing list items procedurally, both numerically and symbolically.

(1.1 2.2 3.3) @ 1   >> evaluates to 1.1
fishery:
  1 2 3
  4 5 6
  7 8 9
fishery @ (3 3)     >> evaluates to 9

Of course Barry starts indexing items from 1. He is slow. And a bit simple too. Even he acknowledges that we loose a considerable amount of identity as programmers by this decision, but on the other hand with this convention the index of the first item is one, the second's is two and the 100th's 100. Anyway, Barry is simpleton, so he quietly considers the ability to talk about item positions and indexes without ambiguity a little win. An infinite number of little wins, to be precise.

data:
  fish: "hake"
  fishy: "Kilgore Trout"

what: "fish"

data@1              >> evaluates to "hake"
data@(1+1)        >> to "Kilgore Trout"
data@what           >> to "hake"
data@(what ~ "y")   >> to "Kilgore Trout"

Eating Banana in the Cryosphere

We can import names defined in other parts of the tree by the Import idea designated by << in the code.

myLib:
  myModule:
    f: -> "Super"
    f': -> "Duper"

<< myLib.myModule
myModule.f myModule.f'   >> evaluates to "Super" "Duper"

Import adds myModule to the name resolution process, somewhat similarly as if the name would be defined where the import resides.

myLib:
  myModule:
    f: -> "Super"
    f': -> "Duper"

<< myLib.myModule..
f f'   >> evaluates to "Super" "Duper"

By unrolling myModule with the .. operator after the import name, we can import all names defined in myModule with one go. But what's unrolling?

Unrolling Sushi for Whatever Reason

The Unroll idea, represented as .. after something that evaluates to a list, makes the items look like if they would appear as individual items in the code.

L: 1 2 3
L': 0 L 4      >> evaluates to 0 (1 2 3) 4
L'': 0 L.. 4   >> to 0 1 2 3 4

This means that we can implement knitting by the following code.

~: a b -> a.. b..

With unrolling you can also pass lists as if they were operator arguments.

L: "Yes" "No"
if 3 > 4 L..    >> evaluates to "No"

One Unit of Common Sense

The idea of the number is so magnificent, that even its botched little cousin, Num is quite amazing. Num can express cute tiny and huge epic numbers alike. You can express the number of atoms in the universe and the distance between two protons in a healthy nucleus with it. Or at least what you think these numbers might be. At the same time numbers start to behave like an ant nest under the supervision of over-curious nine year old boys, when they are dealing with real world data. Whatever the hake the term "real world" means.

To avoid avoidable discombobulation Barry decided to look at quantities and units through his star shaped pink eyeware, and treat them with the love they deserve, to save precious hours of sleep time. Basically Barry thinks that quantities and units are good ideas.

<- sf.physics
t: 1s
l: 2m
sum: t+l   >> evaluates to 1s + 2m

Now that's unusual! What's going on? Again it's only weird if Barry is not your first programming language. Those are units defined in the standard fantasy, the closest thing Barry can think of a standard library. s and m are ideas of physical units, second and meter to be specific. They're just operators that accept a left argument (_s) (_m). Parsing the result of the last line would produce the following idea tree:

1 2
| |
s m
|/
+

And that's exactly what you see there. As Barry can recognize that he can't reduce an addition of a value of time to a value of length, the idea tree can't be simplified further and gives back this idea as the result.

t: 3s
t+2      >> evaluates to 3s + 2
t+1min   >> to 63s
t*3      >> to 9s

You can't add a number to a second meaningfully, as not having a unit means that the number is not a quantity: it's just a number. But you can most certainly multiply a quantity with a number. A unit imply both the quantity the unit expresses and the conversion functions necessary to convert the underlying number to the quantity's base unit. Units are treated as an interface layer, the underlying representation is always the same base unit.

Barry suspects that of units may have somehow more related to the concept unification and less to the concept of confusion, but he is quiet about it to avoid ridicule.

What Type of Question is That!?

Everybody love types - including Barry -, as they seems to help us a great deal to keep our sanity. It just happens that Barry likes ideas more, as he doesn't care about sanity that much. To be honest, it's probably because he's just too simple to comprehend the idea of sanity adequately.

Barry thinks that 1s describes what it attempts to describe fairly well: it's parsable, it's displayable and it even seems to be flexible enough to swap s to min if needed, since the underlying value is in the base unit of the quantity it represents.

t:
  v: 90 u: s   >> evaluates to 90 s
t.u := min     >> mutates the tree
t              >> evaluates to 1.5 min

The idea of a second or minute can be expressed as an incomplete operator, passed around like values. Instead of types Barry thinks about trees of ideas representing a compound idea, like a quantity of time. But you can still disassemble these compound ideas and assemble them to your heart's desires.

Even better they can naturally grow to express more complex ideas.

date: 2025 years+12 month
date s ago                  >> will show the seconds elapsed since date

date's value will change as the clock of the underlying computer will advance. The underlying value never changes, ago is just an operator that outputs the value relative to system's clock. In one hand it's just an interface thing, but on the other hand it's the exact idea behind the concept of "ago".

What's great about this that ago can know about itself that it's time dependent, so the user interface can register it as such, and update it regularly as time progresses.

But what happens if you input a value to Barry in that form? I'm glad I've asked!

when: 10 years ago
when

When will reset on each bang to point to 10 years before the source was banged. If your application has infinite loops ago will display different values, but the underlying point in time is not changes. It still points to 10 years before the bang.

Obscure Objects of Desire

Excellent! So why on Earth are we talking about quantities and units in a language definition? You must have run out of language specifics and you're trying to show off desperately with this. Really!? No, not really.

I needed to show that Barry is in a state of grace where he doesn't have to simplify everything to a single value of a certain type, as most other programming languages does. Other programming languages would define the type of time and would equip it with all kinds of bells and whistles that can do everything a value of time does, like parsing, displaying, validating, adding, multiplying, etc. And 1m + 1s would most probably result in an error. As it should since it's nonsensical to add a length to a time. Or should it?

Imagine that we already learned to define our own units, and we created a unit of herring and hake. Is it an erroneous to say 3 hake + 5 makarel?

h: 3 hake
m: 5 makarel
s: h+m       >> evaluates to 3 hake + 5 makarel
s+3 hake     >> evaluates to 6 hake + 5 makarel
s*2          >> evaluates to 6 hake + 10 makarel

That seems useful. Barry prefers simplified trees as results over errors. What's strange is that these so called units show some resemblences to types, which is weird as they are operators. How does it works? Did Barry figured out how to add and multiply trees? Not to hurt anybody's feelings, but that seems too complicated for Barry, even to comprehend the problem's complexity.

Quantifying Metaphysical Values

No. Barry didn't figured out how to add two trees together. For him it took epochs, even to figure out how to figure out how to merge trees properly. Barry uses the idea of meta-data to escape fishy situations like this.

During evaluation units attach meta-data about the value to the value and return these bedazzled values back to their callers. So 1s + 3s works, because + receives 1 and 3 and by examining the attached meta-data it can decide to add them or not, making simplification possible. +'s task does not ends here, as it yet has to create the tree of the result, again based on the info in the arguments' received metadata. Barry abbreviated meta-data using the first syllable from the first word and the second syllable from the second word, which resulted meta. When Barry talks about meta it means metadata. Meta is represented in the sn by the @ character.

To be honest we already used metadata as natlangs are stored as metadata.

a: 1          >> oh my!
a.@.natlang   >> evaluates to "oh my!"

@ is a name defined for every idea and is like any other idea. All units has to do is to return the enriched values.

s: v _ ->
  (v @:(quantity: "time", unit:"s"))

myTime: 5s
myTime.@.quantity   >> "time"
myTime.@.unit       >> "s"

It's not how it's done, but that's the gist of it. Metadata is invisible to the single item rule so s won't return a list, just the value, but the meta will be there for + to access it and make decisions based on that.

The good thing is that you can define your own metadata just the way you want. You can express types, classes, kinds or any other kind of constraints, documentation as we already do with natlang and so on.

I See! But What IS Barry Anyway?

Because it's not a programming language, that's for sure. The short answer is that Barry is an software abstraction layer over the Naumannian computer architecture that tries not to botch the original model's most valuable property, that data and program are of the same nature. Just kidding! Barry is a funky seal of course.

Barry is not a programming language. It's a proposal for a programming environment where code and data is abstracted together with the same primitives and even more importantly, where the abstract syntax tree is considered to be the main product of programming. You can solve problems by simplifying this tree and you can create application by running or banging this trees ad infinitum, which is simplifying and complicating the tree recursively.

While it can feel alien - as Barry is an alien technically -, but it is built or dreamed up from off the shelf components, and widely adopted techniques. Nothing exotic really.

Not Working Slowly

Seals are pretty awkward on land, but they are pretty agile in water. Barry abstracts the computer's linear memory away and present it in the form of an arbitrary large labelled tree. Of course not Barry is the first programming language that tries something similar, and common knowledge about these experiments tells that these kinds of runtimes have an upper limit to their performance. On the other hand these languages proved to be seemingly useful as glue languages in high performance computing environments, but not on their own rights, but mainly due to links to low level libraries.

Barry has a more direct approach to low level performance, as its meta-data system allows the programmer to inform the system about possible hardware related constraints of a list, for example the size of a list, or the allowed ideas in it and their precision requirements. For example a user can tell about a list that it's exactly 1000 items of Nums with a 8 bit integer precision. These constraints allow the runtime to store and process such a list with all this information at hand, and map it optimally on the underlying hardware.

In Barry's eyes the labelled tree is an universal interface capable to provide unified access to all the useful data primitives like arrays, maps, structs, enums and trees of course, but it doesn't mandate any particular underlying implementation of these. It provides a generic variant of the List idea to support arbitrary complexity trees, that is performant enough to work in the scale of the 10s of thousands, to express programs and their object structures, but also provides meta-data constraints to map computations in the billions to hardware properly.

This way the user can manipulate the object structure of an application by the full power of a generic programming language.

Lore

Barry, the Funky Seal

Now, enough of that nonsense! Let's talk about the fun stuff: Barry, our extremely likeable namesake.

Barry, to be honest, a little bit on the slow side of things, but this is quiet understandable as he lives on a planet, where seals just live forever. And ever. While not being the sharpest knife in the drawer - some might say, he's more on the spoon side of things -, he sidesteps this limitation by a heart of warmth and limitless love and patient curiosity towards everyone and everything around him. Especially fish.

Barry likes to read a lot, mostly books that he came up with in his imagination. But sometimes he reads books he finds lying around to spend time somes with friends who signed up to one of Rip's travel agenciy's offerings.

knitten

While Barry lives forever knitten dies and reborn one and half times per Planck time, which is pretty fast. The infinite sadness over knitten's death and the infinite joy over his best frind's rebirth kind of smooths out each other in Barry's heart, so he got used to it Epochs ago.

knitten is officially the cutest white small fluffy arctic cat on the planet who is the match maker there, a little cupid, who birngs lovers together in sweet-sweet harmony. She also happens to be a bloody psychopath who tears these lovers apart to recreate them as one in the match making process. Luckily she is pretty quick so nobody feels a thing. Only Barry knows about this, but since it doesn't bother anyone really, on the contraray coming together makes everybody more happy, he just looks the other way.

Sometimes knitten wears lipstick, at least that's what she says it is. Barry's not so sure but loves knitten anyway.

Victor the Lofty Worm

Victor is a quiet n-dimensional worm who can function as a hyperdimensional telescope for Barry. He doesn't mind either if the friends throw him around during board games of epic proportions as a dice as he is quet rectangular. At least for a worm that is.

Victor likes sports in general, but simply manic about football. The only thing he likes more is winning. He plays football alone, because that way he can always win. It doesn't really bother anyone and everybody remembers when Victor challenged the penguins for a match and forced everyone to try to beat them. Of course the penguins won. knitten got a red card in the first nanosecond for disintegrating a penguin. Victor was running around the pitch, shouting with everybody all the time, shaming his friends and insulting the penguins. After the match he melted and was blaming Barry for epochs for the outcome, who was the goalie of course. Anyway, Barry likes waterpolo much better. In theory.

Rip

The Reaper, or just Rip for his friends, wears a black hooded rope that shadows it's face and walks with a scythe all the time, which is kind of strange. If it even has a face, we don't know. Anyway, everybody avoids Rip for some reason. Surprisingly Rip is kind of bubbly despite all the loneliness, probably for the succsess of the travel agency it runs, that specializes on one way trips.

Stella

Stella is all the starfish on the planet, and she is beautiful. She is the most beautiful in starlight during the night. She reproduces by multiplication so Stella is all around and that makes the whole planet beautiful.

Wily

Wily is an orca and he is a bike messenger. Since most orcas are named William, one form or another, if you encounter a being named William, there's a very high probability it's an orca. Anyway, Wily's thinking seems to revolve around the concept of freedom: how important freedom is, how iportant the freedom of Wily is and how proud Wili is of his freedom. At least he is so occupied with his own freedom, that he doesn't bother trying to limit others'. It can get a bit anoying anyway, because in Wily's interpretation freedom gives him the right to change others. Now this can lead to friction if, as it happens, the party on the other side of Wily's "freedom" doesn't want to change that much.

But Wily is good listener, you can share your heart's weights with him anytime, if you don't mind the seemingly infinite monologe about how you should modify your personality. Completely.

Barry sometimes comes up with imaginary hardships that he can share with Wily, so he can listen to Wily's endless suggestions, advices and mandatory recomendations, because the idea of changing his personality entertains him infinitely. It just makes him giggle.

mU

mU is a mostly white cow with large black spots. mU is essentially Barry, just happens to live on another planet. On that planet cows live casually forever. It needless to say that mU is also pretty lazy. She's actually the same being, like another cap of the same fungi living under the roots of the same forest.

mU is a bit older than Barry, which doesn't make a lot of difference between eternal being, yet this fact kind of sets the tone of imagination when they're thinking about each other.

Welv

Welv is an arctic fox. If you ask her she will tell, she's interested in metaphysics, but what she really seems to be interested in is gossip. She talks about others all the time, and to be honest not always the nicest things. Luckliy everybody likes gossip just enogh to not being bothered.

Shebang

Shebang is the entire universe in which Barry's planet located and happening in. She is very nice and helps to everybody, until they behave like she wants them to. Friction usually occurs when they're not. It's not that's she's angry or something, it's more like she knows best how she works. She constantly tries to communicate, but everybody is living inside her, and everybody is used to communicate with beings in their surrounding and not with it, and it makes this usually a bit difficult.

Dyllberd

Dyllberd is the husbend of Shebang and they're inseparable. Now, while Shebang is uncomprehensibly huge, Dyllberd is uncomprehensibly small. Whyle Shebang is composed of everything - at least in that universe -, everything is composed of Dyllberd. Barry thinks he kind of understands this, or at least feels it. Dyllberd wears silly hats and always in the process of walking out on a door, which is kind of strange. This makes it a bit cumbersome to engage in longer or deeper conversations with him.

Nope

Nope always feels lonely and usually a bit moody too, constantly hanging his nose, over the sadness of the eternal and unbreakable loneliness. Some even suggest that he intentionally try to push this gloom over others. What's for sure, is that when sombody is sad, Nope is so quick to show up, that it's hard to decide which came first.

Anyway, Nope lives in between things: where there is Dyllberd ther's no Nope. They appear always side by side, as they can not overlap. Theaw two old hoods are spending a lot of time together talking about presumably interesting topics, as Nope is the only one who can be at both side of the door on which Dyllberd is stepping out.

Nope is a serious and dedicated hypochondriac, and probably not independently from this, he is constantly on some self prescribed medications nobody else ever heard of. The friends slowly adapted to his strange behavior, that they mainly attribute to the side effects of the snake oils he consumes on a pretty regular basis. Despite the fact that he's extremely thin, he looks pretty round to be hoenst.

Dagger

Dagger is Barry's husky, not that Barry has a proper understanding of the concept of property. Barry interprets this one sided determination as a sign of sympathy and likes Dagger's company anyway. Dagger helps Barry a lot, as Barry isn't very handy with his flippers and Dagger also has a overachiever mentality anyway, that Barry lacks completely. Dagger is much more competent in practical matters as he can run around and bark at least.

We don't really know what Dagger eats, as he is quiet private about this. As a matter of fact nobody have seen him eating. Sometimes he wonders behind the snow dunes down the continent and when he comes back there's usually red spots on him, mainly around his moth. He says its jam, but Barry has some reservations about this, as Dagger can spin himself into self induced agitated monologues about how he despises jam. Luckily there are an infinite number of other ways Barry can look.

Dagger looks something like this when inspecting something: ^..^ and like this when some jam gets into his mouth or jammed in other words: ^oO^ and as he gets tired of working his mood progressively deteroriates from Ok to passed out through the phases of ^++^, ^**^ to ^xX^. When they are laughing together with Barry he looks like this: vv^v as he is lying on his back and his tongue is hanging out.

Bianca

Bianca is one particular snowflake. She is small, entirely unique and very hard to find because she is white, small, usually lying flat on her face or back, and there is snow and ice all around. But the firends know that she's out there somewhere on the continent, minding her own business. They can just feel it, deep down in their sweet little hearts.

Zaphir

Zaphir is a huge round cloud, waving above the continent.

Vally

Vally is a herring.

Marketing Material

We only use effective and well targeted tag-lines for enhancing the public image of Barry.