About erlinghellenas

55 year old male from Stockholm, Sweden interested in politics and information technology. University education in industrial management and engineering, business administration, organizational psychology and computer science. Experiences from mechanical industry, telecommunications, software industry, construction, banks, county administration, health care, education, public services.

JWithATwist – Scalar Operations

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question is the functionality of scalar operations.

A noun in J is an n-dimensional array. Each element in this array can be a simple value, but it can also recursively contain other n-dimensional arrays. The number of dimensions of this array is called its rank. An array of the lengths in each dimension is called its shape.

When you write x + y in APL, J and similar languages it does not simply mean that two values are added. In JWithATwist x + y means that:

  • If the left and right noun arguments have the same shape the elements in corresponding positions in the argument arrays are added. This operation is called map in many functional languages.
  • If one of the arguments is scalar, a single item, this item is added to each of the items in the other argument.
  • If the arguments have different shapes, then if the shapes have a common left part, the argument with the shorter shape is logically replicated to the same shape as the larger argument and the operation is performed between corresponding elements. When a row of two elements is added to a table of two rows the first element in the row of two elements is added to each element in the first row of the table of two rows, and the second element of the row of two elements is added to each element in the second row of the table of two rows.

The first two cases can be seen as special cases of the third case. A special case in which the left common part is empty and a special case in which the common part is the whole shape of both arguments.

There is an integer and a float add operation. Numeric arguments of different types are converted before the operation if possible.

The performance of this operation is excellent. There is little overhead. Basically just a loop and the add operation. The additional overhead needed for the third case is just an integer division in the loop.

Lets say the addition operator was a scalar operation between two scalar nouns, and a separate adverb or separate adverbs would handle the loop,  then there would be a considerable overhead for each addition.Verify argument type and shape, select integer or float operator, check if type conversion is needed, perform type conversion, perform add. Now most of this is performed only once for the scalar operation over the whole arguments.

An advantage is that the notation can be used like the notation for matrix operations in mathematics.

A disadvantage is that the notation is different from that in most other languages.

It is also peculiar that the scalar operation verbs are said to have rank 0 0 and thus are supposed to operate on scalars, and still these operations operate on the whole of their left and right argument arrays with the help of what I call the scalar operation helper program.

It is strange with these helper programs which are never mentioned in the J documentation, but which must be understood by the user anyway, since they are obviously needed to explain how scalar operations can operate on whole array arguments.

As I see it the operation is complex. Seen on its own you can easily understand its function, but when used inside of the rank operator and inside other operators it is not easy to understand how the operators work together.

There is also an irregularity. Let’s call the third operation the Agree operation and the first the Map operation. There is another possible similar Agree operator with the shapes right-aligned. A row added to a table using this Agree operator would instead add the row argument to each row in the table argument. There is a possible general case in which the smaller argument dimensions could match any selected dimensions in the larger argument and the shorter shape argument would be logically replicated to the size of the larger shape argument.

Both the left-aligned and the right-aligned Agree operators are highly useful. The right-aligned Agree operator can be performed with the Rank adverb. The general case might be too complex to be a built-in operator. In JWithATwist there is a general transpose verb with which you can transpose the argument with the longer shape to a similar argument where the dimensions corresponding to the dimensions of the argument with the shorter shape is right- or left-aligned within the shape of the argument with the longer shape. You can then use the right- or left-aligned Align operators and transpose the result back. This means that you can easily write a code snippet which handles the general case, but that there would be some performance penalty compared to an operator for this general case.

A possible change would be to make the scalar operations scalar, make the helper programs explicit and take the performance penalty. There could be a Map adverb, and AlignLeft and AlignRight adverbs. These operations would then have to give domain error if the verb argument is not a scalar verb. The rank of the verbs would have to be registered.

Let’s say you have a chain of scalar operations. It would be more computationally efficient to make this chain into a single scalar verb than to execute a chain of Align- or Map- operations. It would also describe the algorithm you would use in most other languages better. To do this you would need the possibility to create user-defined scalar verbs.

If the scalar verbs had a type, the performance penalty could be avoided and the type verifications and type conversions could be moved to the Align- and Map- operations. The + verb would have to be split into a +Integer and a +Real verb in JWithATwist, with types like Integer -> Integer -> Integer and Real -> Real -> Real if we use the F# type notation.

As you can see these are complex changes and we would get a totally different language. For now I decided to keep the more APL- and J-like notation. However, I documented the helper programs clearly.

JWithATwist – Number of Arguments

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question is how many arguments should be allowed and if the notation should be infix or not.

Since you can have as many arguments as you want in one boxed argument the number of arguments is not actually restricted. You can have as many as you want and they can be only to the right or to the right and left, which means infix notation. So there is no restriction and I can see no reason to have one.

One thing I dislike is that boxed arguments are avoided in built-in words in J. I understand that many were defined before we had a boxed data type, but I can see no reason not to redefine them. I dislike when arguments are set in the interpreter to avoid boxed arguments. One reason is that you sometimes want to set them from variables and you can’t.  We can have boxed arguments and we should use them and remove all variables set in the interpreter, as I see it.

Many words, like amend, use the most twisted syntax to avoid boxed arguments. I think that should be changed. We should just use the number of arguments we need and box them. I can see no reason whatsoever to try to make the syntax extremely terse. What is important is clear simple definitions of all words. It is important that when you see the word you can immediately, without thought, recall exactly what it does. No complex word definitions, no words with many meanings.

We don’t work at teletypes any more. There is no reason to use short keyboard combinations for words. We can use beautiful symbols with colors, maybe many of those used in mathematics and which you find in LaTex.  We have computers with graphical user interfaces and you can easily and quickly pick symbols from controls on the screen. We can also have touchscreens or touchpads, possibly beside us as we work.Unique symbols will make the language much easier to read.

What we need is a coherent algebra with rules which makes it easy to successively simplify our programs until we have a solution we like. There should be no strange hidden features.

JWithATwist From F#

These two tests show how JWithATwist can be used from F#. Any APL and J programmers out there working in F# and missing their APL symbols or J words? Try JWithATwist as cool lambda expressions or as F# functions?

        [Fact]
        member x.``Group mean`` () =
            let GroupMean = JVerbMonadicDefine @"
{!
    {! 
        |<         
        {! ( 0 + / ] ) % |# ] }          
        |> ] 
    } 
    |'/ 0 / ]
}"
            let y = JNounDefine @"{ ( |< 4 2 8 ) , ( |< 13 7 9 2 ) , |< 0 1 }"
            let actual = GroupMean y
            let expected = JNounDefine @"{ |< |'/ 0 / ( 4 + 2 % 3 ) , 7.75 0.5 }"
            Assert.Equal(expected,actual)

        [Fact]
        member x.``Group mean i F#`` () =
            let each y u = 
                JRankMonadic y (fun yy -> JBox (u (JOpen yy))) ZeroNounConstant
            let mean  y = 
                JDivide (JFold ZeroNounConstant y JAdd) (JTally y)
            let sets = JNounDefine @"{ ( |< 4 2 8 ) , ( |< 13 7 9 2 ) , |< 0 1 }"
            let actual = each sets mean
            let expected = JNounDefine @"{ |< |'/ 0 / ( 4 + 2 % 3 ) , 7.75 0.5 }"
            Assert.Equal(expected,actual)

JWithATwist – Functions as Primary Citizens

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question is whether functions should be primary citizens of the language or not.

Since JWithATwist is written in F# where functions are primary citizens it would be easy to include them as data types in the JWithATwist Nouns and make them primary citizens in JWithATwist.

With functions as primary citizens you wouldn’t need adverbs and conjunctions, you could have only verbs with one or two noun arguments which could contain other verbs you could execute freely and use to create new verbs.

It would also be possible to keep adverbs and conjunctions. Verbs, adverbs and conjunctions could be free to use and create any word.

One question I did not solve is if this is a data security question and if that would pose any restrictions on the solution. In Windows I think programs and data is kept separate. It is not possible to change the programs at runtime. If you try to write to a program area you get a general protection fault. Lets say you could create a program from an ascii string and then execute this program. Then an intruder could get his program running in the system by changing a data area. I think this would not be acceptable from a security point of view.

As long as we are in F# I guess F# keeps track of this and the problem needs no solution.

For now I decided to create a JWithATwist closely resembling J because I want to involve the APL and J communities in discussions.

JWithATwist or Tacit J

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question is the choice of overall syntax, mainly if it should be strict right-to-left evaluation as in APL and explicit J or if what I call the “hook-and-fork” logic of tacit J should be used.
In J there is a unified data type called a noun. It is an n-dimensional array which recursively can contain other n-dimensional arrays. A function is called a verb. A verb can have one or two arguments. A verb with one argument is called monadic, a verb with two arguments is called dyadic. There are two kinds of operators, the adverb with one functional argument and the conjunction with two functional arguments. Adverbs and conjunctions also have one or two noun arguments and are also called monadic or dyadic. Verbs, adverbs and conjunctions have an infix notation. If there is one noun argument it is to the right, if there are two noun arguments the second is to the right. The functional arguments of adverbs and conjunctions are also infix, but reversed. The first functional argument is to the left, if there is a second functional argument it is to the right.
APL and explicit J has a simple right-to-left execution logic, modified by parenthesis, like this:
( 1 + 2 ) * 3
9

There is no precedence between verbs. There are some simple associativity rules. A noun to the left of a dyadic verb is tied to this verb. A verb to the left of an adverb or conjunction is tied to this adverb or conjunction.
The hook-and-fork logic of tacit J is more complicated.
A tacit J expression can have one or two arguments, it can be monadic or dyadic.
One basic difference between explicit J and tacit J is that in explicit J the result of a verb is input to the next verb to the left. This is called composition. We have two functions f and g and the result is f(g). This means that the default operation between two consecutive functions in explicit J is composition. In tacit J there is no such default operation. The operation between two consecutive functions must be explicitly stated. If you want composition you have to explicitly state it. As a comparison, in mathematics we have multiplication default. If you write fg it means f * g.
Another basic difference between explicit J and tacit J is that in tacit J there is no reference to the nouns. The nouns are still there, but there is nothing to denote them. It is like the persian language in which the vowels are never printed. The reader has to guess vowels until the resulting word makes sense in the context. In tacit J the reader has to construct the nouns in his mind. There are a lot of different functions for routing nouns to the right verb.
There is Left and Rigth, denoted [ and ]. These are verbs which takes both arguments of the J expression and returns the left or right argument. If the tacit J expression has only one argument both return this argument. In this case Left returns the right argument.
There is the Reflexive adverb with which causes the right argument to also be used as the left argument of a dyadic verb. There is the Passive adverb which switches the arguments of a dyadic verb.
There are composition adverbs which take the result of a dyadic verb and moves it into a monadic context where monadic verbs can be applied.
There is the Cap function with which a monadic verb can be used in a dyadic context.
In tacit J we still have right-to-left execution like in explicit J. If a bracketed J expression ends with a verb it is a tacit J expression.
A tacit J expression is interpreted. The result is a new verb which is applied to its argument or arguments or which is input to an adverb or conjunction. We say that the result is a single verb.
If a tacit J expression contains only one verb, the result is this verb.
A tacit J expression is then normally extended by two verbs at a time, one new verb and the verb to use between the result of this new verb when applied to the tacit J expression argument or arguments and the previous result.
Thus, a tacit J expression normally contains an odd number of verbs, one first verb and a number of dyads.
However, a tacit J expression containing an even number of verbs is totally valid. The tacit J expression is then called a hook.
You can only get two nouns into a tacit J expression, it’s two arguments. However, there is something called constant functions, which allows you to have a noun constant as argument to a verb. A constant function takes the argument or arguments of the tacit J expression and returns the constant argument to the constant function.
One of my design alternatives is to use the explicit J syntax and add Left and Right. Left and Right would then be used instead of the nouns in the explicit J definitions. Since brackets is used in explicit J to change the order of execution I need something else, like the curly brackets, to use to delimit the verb definitions.
The other design alternative is to use the tacit J syntax.
Functionally the design alternatives are equivalent. There is nothing you can do with the tacit J syntax which you can’t do with the explicit J syntax. As far as I understand there are no performance differences.
The explicit J syntax is simple, clear and easy to read.
The tacit J syntax is a total mess of utter complexity.

  • Hooks and forks are interpreted differently, so to read a verb train you first have to count the number of verbs. There is no easy way to do this.
  • If you want to move an expression from explicit to tacit J a total rewrite is needed.
  • If you add an argument to a tacit J expression you have to rewrite it.
  • If you move a tacit J expression from a monadic to a dyadic context you have to rewrite it.
  • You need to create a mental map of the data flow, since it is not explicit. There is no easy way to do this.
  • Composition is a good default. It is what you most frequently need. When you take it away you have to write a lot of tie functions which would otherwise not be needed.
  • People tend to avoid writing expressions like [: – [: – [: – [: – ] to execute a number of monadic verbs in sequence, probably because it reveals that the notation is not good. Instead they tend to write something like this -&-@- – ] and pretend that they use a cool language. The amount of complex functions used for simply routing the rigth argument to the right function obscures the logic.
  • The constant functions is a complexity.

As you can see the choice could not be easier and I have chosen the modified explicit J syntax for JWithATwist.

 

 

 

JWithATwist – Insert or Fold

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question  is the choice between the J Insert operator and a very similar Fold operator with an implementation similar to the one in F# and other functional languages.

The J Insert operator is described here. The F# Fold operator is described here.

The description is different, but the main difference is that the Fold operator has an initial state argument, the J Insert operator has no such argument.

The initial state is what these operators return if passed an empty array. In both these languages you regularly handle empty arrays and functions which can not handle such arrays are a major inconvenience. Thus, an initial state is necessary.

How does J solve this problem?

For common function arguments like +, *, +.(or) and *.(and), J as far as I understand has special cases in the parser. J identifies these funktion arguments and adds the initial state for these cases. It is 0, 1, false and true for these four example function arguments. For general cases J can not handle empty array input. It returns Domain Error.

For general cases there is a workaround. The programmer determines the initial state and adds it to the input array. If no other input the initial state is returned. The problem with this is that the initial state can be of any number of dimensions, any length in these dimensions and of any type. To handle such an initial state the argument array has to be an array of arrays. If the input stream for example is a long array of characters, each character has to be boxed. This would create performance problems. So, there are many cases when the J Insert operator is very inconvenient to use, to  say the least.

What is good with it is that you can type a character less when you use it in the normal case. I think that is a very minor advantage. Thus, I have chosen the F# Fold operator for JWithATwist.

Infinity, NaN, NA, Overflow,Loss of Significance

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question  is how to handle infinity, NaN, missing data, overflow and loss of significance in integer and floating point types.

J is an array processing language. Normally you handle a lot of data at the same time. It is important to have efficient arithmetic operations.

In J a division of integers returns a double. Division with zero returns positive or negative infinity.

Integer overflow in J is handled by transforming the variable to double. This seems like a problematic solution since the user can lose significance. He could get 100 instead of 104 as a faulty result of a calculation without any notice whatsoever.

In .NET the default response to buffer overflow in integers is nothing. .NET gladly returns the resulting truncated integer.

Generally if you have a problem like this in a calculation you have to handle the problem. You have to show the user what went wrong. You have to stop this particular transaction and put it on some fault list. You can’t crash with an exception. How do this in a language where you could handle 500 000 000 transactions at a time?

In J data is stored in arrays and arrays of arrays. There is no space for a “fault list”. Having separate fault lists for this kind of problems would be inconvenient, to say the least.

I think the problem is best handled late in the chain, by the user directly, by the user interface programmer, before committing the transaction. Information about faulty data must be encoded in the variables in some way, but how?

Infinity, negative infinity and undefined/NaN are all perfectly legitimate values in a language like J which is used for mathematics. In integers as well as in floats. NaN can not be used to indicate faulty or missing data.

Processor designers like Intel and AMD follow standards. The standards give us infinity, negative infinity and NaN, but only for floats. How get them for integers in J and JWithATwist? How handle buffer overflow and loss of significance?

In calculations data frequently is missing. Should this be handled in basic variable types? How? If left to the user/programmer, is there a good way for him to handle the problem?

To get infinity, negative infinity and NaN in integer calculations you could possibly do them in floats. You have integer variables and float variables, but they are both float.

To solve the loss of significance problem you can check results of all integer calculations. If the exponent is to large the integer should be fault marked.

Not fault marked floating point integers can safely be converted to integers if they are used for things like indexing.

However, you still need a way to fault mark. The most obvious possibility is discriminated unions. You store all integer floats and floats with information about if they are faulty or not. This will slow calculations a lot, but can be done.

In the same way you can handle missing data, you just need a new category. Faulty, missing or OK.

Or you can have real integers for integer calculations and discriminated unions for both integers and floats with infinity, negative infinity, NaN, missing data and faulty.

Lets say you have missing data encoded in the variables and missing data information slips into a variable which is used in a function which can not handle missing data. Then this function must crash. You must handle this everywhere.

Another way is to encode this information in the value range of integers and floats. You pick some values for this information. But it is hard to handle this in a safe way. This integer or float is used by a function that can’t handle it and you crash or get unpredictable results. With discriminated unions you can handle it in a safe way and you follow standards. It’s hard work to get this done and it slows calculations, but it has to be done this way?

 

The Tacit J Design Space

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question  is if the language should take functions as arguments and return functions or only have data types as arguments.

As I argued in a previous post J is in a way an advanced functional language which allows creating functions and taking these as arguments to other functions. However, at execution time only nouns, variables, are passed as arguments to functions.

In this post I show one way to add the possibility to pass verbs as arguments to verbs in tacit J, and pose a question to my audience – would this open lots of new possibilities?

In J there is only one basic data type, called a Noun. A Noun contains an n-dimensional array of some basic data type, or of boxed, which means it is an n-dimensional array of other n-dimensional arrays.

The function types in J are Verbs, Adverbs and Conjunctions. A verb takes one or two nouns as arguments and returns a noun. An adverb is something that takes a verb as argument. A conjunction is something that takes two verbs as arguments.

Verbs, Adverbs and Conjunctions can take one or two noun arguments. A function type with one noun argument is called monadic, one with two is called dyadic.

In JWithATwist verbs, adverbs and conjunctions clearly always return nouns. These nouns are processed in what I call a noun train. As I see it this noun train is functionally equivalent to the “verb train” in J. A noun train is like a statement which creates a variable. In JWithATwist a verb train is a train of monadic verbs, adverbs and conjunctions interpreted from right to left and leaving their noun result to the verb to its left.

A noun definition in JWithATwist which creates the sum of a vector: { 0 + / 1 2 3 }

JWithATwist has a “verb definition” which is a noun train with argument placeholders for it’s left and/or right noun argument. The placeholders are like anonymous variables. Instead of naming the right argument something it is simply called “]”.

A verb definition in JWithATwist which creates a monadic increment verb: {! 1 + ] }

In the JWithATwist interpreter it would be possible to create functionality to define adverbs and conjunctions in a similar way to the way verbs are define. You could add a “Left verb” and a “Right verb” and use these with the Left Noun and Right Noun to define adverbs and conjunctions.

In tacit J there is no way to define adverbs and conjunctions.

An adverb definition which unpacks the right argument, applies its verb argument to it and packs it again could look like this: {! |< ]. |> ] }.

However, it would also be possible to create a verb definition from verbs. This verb definition would not take any noun arguments. What I imagine is that you could do everything you can do in functional programming in this verb definition from verbs. It would open a new design space for J, as important as the present design space which, as I see it, only handles nouns.

Tacit J does not have side effects, as far as I know. There are no functions with a “void” or “unit” result. This is another possible extension.

In terms of function types J has the following at execution time(this is under discussion, see previous post):

  • Noun -> Noun
  • Noun -> Noun -> Noun
  • Noun -> Verb -> Noun
  • Noun -> Noun -> Verb -> Noun
  • Noun -> Verb -> Verb -> Noun
  • Noun -> Noun -> Verb -> Verb -> Noun

I think these could be added while still sticking to the general concepts of J.

  • Noun -> Verb -> Verb
  • Noun -> Noun -> Verb -> Verb
  • Noun -> Verb -> Verb -> Verb
  • Noun -> Noun -> Verb -> Verb -> Verb
  • Noun -> Verb -> Unit Noun
  • Noun -> Noun -> Verb -> Unit Noun
  • Noun -> Verb -> Verb -> Unit Noun
  • Noun -> Noun -> Verb -> Verb -> Unit Noun

We could add a side-effect adverb and a side-effect conjunction to tacit J which returns one argument and which takes a side-effect verb argument which returns a unit verb.

Tacit J also obviously lacks the possibility to do recursive calls from more than one place in the code.

Would this open lots of new possibilities?

J, a Functional Language?

I am designing a J-like language I call JWithATwist. Some design questions are under discussion and I will describe them here. I welcome comments. One such design question  is if the language should take functions as arguments and return functions or only have data types as arguments.

In this post I describe how J works in this regard.

In J there is only one basic data type, called a Noun. A Noun contains an n-dimensional array of some basic data type, or of boxed, which means it is an n-dimensional array of other n-dimensional arrays.

I think J could be described as mainly a scientific effort to find a notation for manipulation of arrays and arrays of arrays.

The function types in J are Verbs, Adverbs and Conjunctions. A verb takes one or two nouns as arguments and returns a noun. An adverb is something that takes a verb as argument. A conjunction is something that takes two verbs as arguments. These are things I think everyone agree on, even if the documentation sometimes seems strange.

Verbs, Adverbs and Conjunctions can take one or two noun arguments. A function type with one noun argument is called monadic, one with two is called dyadic.

There is a question about if any J function returns a function or not. I think you could say that no functions returns a function. That the J functions only manipulate data types, never functions. This question is under debate. I will try to explain how it works in reality and how there could be different opinions on such a basic point.

There is explicit J and tacit J, two very different languages in one. With explicit J you can create a function from a text string, so basically you can do anything. However, that’s not by far up to the standards of present functional languages. With explicit J you can create an adverb or conjunction. These take verbs as arguments and logically creates another verb. However, it is only logically. The definitions of adverbs and conjunctions are textual descriptions. The name is replaced by the contents of these descriptions before the parsing takes place. What is parsed is only verbs and nouns. It’s like macro assembler.

The adverb and conjunction definitions have no possibilities whatsoever to manipulate their verb arguments. The only thing they can do is to use them instead of a verb in the syntax.

According to the J descriptions, in Tacit J everything is verbs, adverbs and conjunctions. The explicit user defined adverbs and conjunctions can be used, but are replaced by it’s definitions like I described. What remains of adverbs and conjunctions in runtime is only those built into the language. None of these modify verbs in significant ways. They take verbs as arguments. These verbs are then used internally.

Tacit J is a verb train that is merged to a single verb by different manipulations like composition. This single verb is then executed with nouns as arguments. In the verb train you can use functions like the identity function and constant functions. However, at execution time the only thing they do is to return the noun argument or a noun constant. They return no functions. However, on a theoretic plane, they might be seen as identity functions and constant functions.

I’ll illustrate with an example:

f =: +/
g =: */
(f + g) 1 2 3
12
(f + g) f.
+/ + */
1*2*3
6
1+2+3
6
6+6
12

This example shows how the verbs f and g are defined as a sum function and a product function. In the tacit J expression (f + g) these functions can on a theoretic plane be seen as if they were added. When applied to the vector 1 2 3 this new function correctly returns the sum of the sum and the product of the argument. The line (f + g) f. prints the code to be parsed. As we can see, the functions are replaced by their definition before parse time.
When the code is interpreted, a code package is created, a function with one argument, which calculates the sum and the product and then adds them. The creation of this code package is in a way functional programming. However, at runtime only nouns are passed as arguments to functions, except maybe for some verb arguments to adverbs and conjunctions which are used internally. These verb arguments can be user defined verbs.
When the code package is created, some of the functions in the verb train can possibly be factored out. In reality some functions might take verbs as arguments and produce other verbs in this process.

JWithATwist Mock Parser

I am designing a twisted version of J. I call it JWithATwist. Today I made a first pre-release of a parser with some mock language elements. I think this is interesting mainly in the community of J programmers. I have aired some opinions about Tacit J. The response is always a question – How should it be instead. This parser is made to answer that question.

You can find information about the J programming language at www.jsoftware.com .

Tacit J is in my opinion a very cryptic language, mainly due to what I call the hook and fork logic. Tacit J is supposed to be functional. However the data types can not contain functional values. The code is made up of all functions, called verbs, adverbs and conjunctions. The code is mainly written in units of three verbs, two verbs are actors and the third in the middle describes how to merge the results. To understand an expression you have to start by counting the verbs, if an expression ends with a unit of only two verbs the meaning of the expression is totally different.

You can write very short expressions. This is how you calculate the mean of a vector:

(+/ % #) 1 2 3

The sum divided by the length. Seems simple enough? Well, it’s not. Let’s say you want to negate something. There are numerous ways, just not the one you would expect. To specify that you mean negate when you write “-” and not subtract you can use the Cap verb “[:”.

There is nothing like named variables, so the thing called a noun, a value, that you want to negate is delivered either as something called a constant function, written “1:” if it is one, or the noun is delivered through the Left verb or Right verb, placeholders for the left and right noun arguments. These are written “[” and “]”.

Another way is to use the Atop conjunction, written “@”. The atop conjunction is very similar to a composition operator. It tells that the result of the function to the right is going to be input to the function to the left.

Here are these three ways to do a negation:

 ([: - ]) 1
 _1
 (-@]) 1
 _1
 ([: - 1:) 77
 _1

I don’t want to say that this is crazy. There are powerful operators and you can probably get more functionality into a line of code than in any other programming language. I think it is too complicated for most practical use. I also think it is too complicated to use as a notation to describe algorithms that you later implement in other languages. This is what I particularly dislike, since I would like it to be a notation you could use when you communicate about algorithms with others, and as a tool of your own thought.

So, to state my point I have written this little interpreter and I will later release it with a more realistic J-like language behind.

My main goal with this is to learn F# and a parsing tool called FParsec.

You find the code and a Windows installer here.

All opinions are welcome. You can comment on this blog. There will probably be discussions in the J chatroom #jsoftware at Freenode and in the mailing lists at http://www.jsoftware.com. You can also comment to my user @erlheldata on Twitter.