I have not tried to use J since J402, but I still/get the blog.
I LOVE Dan's exposition, wish I had it back in 402 days. Dick Penny ----- Original Message ----- From: "Dan Bron" <j...@bron.us> To: programm...@jsoftware.com Sent: Friday, January 11, 2013 2:26:11 PM Subject: Re: [Jprogramming] joining to an empty list In J, we think in terms of items. We use items to represent fundamental concepts in our programs, such as a person (name, age, gender) or a stock transaction (instrument, quantity, direction, price) or a ledger entry (asset, liability, total) or a point in a plane (x, y) or anything else with structure. And we represent collections of these items with arrays; in particular, every array is a list of its items (which items can recursively be lists of sub-items, like a book of pages of paragraphs of sentences of words of letters). Furthermore, these lists of items are homogeneous. All items have the same structure. That allows us to reason about collections of items without being bogged down in details specific to each item. This is why we can be more expressive in J than in so many other languages, and, for example, why we never have to write a loop. In other words, this philosophy is the source of J's power (well, one of them). So, to use J, you're going to have to start thinking this way, too. If for no other reason than because writing J is an attempt to communicate with the interpreter, and the interpreter thinks in these terms. But more importantly, accessing this "J way of thinking" is the primary benefit of working in the language (notation as a tool of thought). So, let me try describe it in a little more detail*. -------------- In J, all data, any noun, is represented as an array. An array is an ordered list of homogeneous items. The items are homogenous in both type and shape. So each entry in the ordered list will have the same type and (critically!) shape. It is not possible to have a noun where one of the items has a different type or shape from the others. If you want to have a list of heterogeneous items, you need to box each, which makes them homogeneous again (which is the purpose of boxing). One consequence of this is that all arrays are rectilinear (orthotopic: the N-dimensional analog to "rectangular"). It's not possible to have "ragged" arrays in J.** So, once you internalize this philosophy, one thing you'll start to get sensitive to is shape. And you'll wince a little every time you start to combine nouns with incompatible shapes. Rather than trying to work around that (as with "carefulappend"), you'll start asking yourself "why am I trying to do this in the first place?". In your specific example, you'll be asking yourself "Here, I've got a list of pairs" (maybe they represent Cartesian coordinates, or married couples, or something), "now why am I trying to append that to (a list of) solitary figures?". If the table represents married couples, then (0$0),i.2 2 is analogous to asking "how can I mix in some bachelors?" or if the table represents points in the 2D plane, it's asking "how can I locate points in the plane without giving both coordinates?". That is: dealing with your table, you'll start thinking of its rows as society of equals, and you'll think of appending as adding another (equal!) member to that society. You'll feel that (0$0),i.2 2 is doing something weird: introducing a hobo at your garden party or locking Gandhi up in your prison or electing some third-party candidate to Congress. It just doesn't fit. In short, you'll start to feel that asking (0 $ 0),i. 2 2 is somewhat of a nonsensical question. You'll be much more comfortable when mixing homogeneous items, and instead of (0 $ 0),i. 2 2, you'll find yourself instinctively writing (0 2$ 0),i. 2 2 . That's the key insight. The rest is book-keeping. -------------- But, for the sake of completeness and to address the original question: why does (0 $0), i.2 2 give the result it does? Where do those extra zeros come from? Well, if we want J to give an answer to the question (0 $ 0),i. 2 2 (and it turns out that sometimes this can be useful), we have to choose a way to interpret it meaningfully. But it's critical that that interpretation be consistent under all analogous circumstances. Since the normal case of vector,table is to prepend a row to the table, J extends this interpretation consistently, and treats your empty vector as a weird, degenerate row, which it dutifully prepends. But since the degenerate vector and the table's rows have different lengths, and you can't have non-rectangular arrays in J, either the vector or the rows of the table (or both, I guess) must change length. Specifically, since the vector is shorter than the rows of the table, either the rows of the table must be pared down, or the vector must be extended. Since throwing away data is destructive and much harder to undo that simply adding elements to the vector, J prefers the latter. And, as expected and required, this is consistent under all analogous circumstances: (4 $ _),i. 2 2 _ _ _ _ 0 1 0 0 2 3 0 0 (3 $ _),i. 2 2 _ _ _ 0 1 0 2 3 0 (2 $ _),i. 2 2 NB. Add a normal row to the table _ _ 0 1 2 3 (1 $ _),i. 2 2 _ 0 0 1 2 3 (0 $ _),i. 2 2 0 0 0 1 2 3 Note that (only) in the "normal" case of adding a row to the table were no zeros introduced. Note also that in all other cases, the "shorter" items were extended (padded with zeros) to conform to the shape of the "longer" items. When the vector was longer than the rows of the table (4&$ and 3&$), the rows of the table were extended. When the vector was shorter than the rows of the table (1&$ and 0&$), the vector was extended. -------------- In short: if we want J to give answers for these situations and not errors, and we want those answers to be consistent, and we do not want our data destroyed, then this "automatic promotion" is the best available choice. It's simple, consistent, and useful. But it's also beside the point. The moral of the story is: think in terms of items and lists of items. Combine like with like. If you try to mix immiscible items, sure J will try its best to save you, but frankly, you're already damned. -Dan * KEI explained this philosophy with the dual concepts of "cell" (item, object of interest) and "frame" (collection of items, structure). Under those headings, you can find much better and clearer introductions to the relevant concepts in the J primer, wiki, and other coursework than I can offer in this email. ** Another consequence is that much of J programming is interpretation and manipulation of shape. On Jan 11, 2013, at 11:52 AM, Steven Taylor <tayl...@gmail.com> wrote: > I didn't expect this extra (0 0) in the result. > > (0 $ 0),i. 2 2 > 0 0 > 0 1 > 2 3 > > i.e. nothing prepended to shape equals the same shape (not more or less) > > Is this a bug, or does this make sense in some situations? What should the > J way be? > > For a simple list, we get my expected behaviour : > > (0 $ 0),i. 3 > 0 1 2 > > Here's a possible solution > > empty=:(<'') = [: < [ > > empty 0 $ 0 > NB. build result > (xci sort~ u,xa),ya > ) > > empty=:(<'') = [: < [ > > carefulappend=:13 : '(empty x)}. x,y' f. > > carefulappend2=:4 : 0 > if. (empty x) do. > r=.y > elseif. empty y do. > r=.x > elseif. do. > r=.x,y > end. > r > ) > > (0 $ 0) carefulappend i. 2 2 > 0 1 > 2 3 > > (0 $ 0) carefulappend2 i. 2 2 > 0 1 > 2 3 > > thanks, > -Steven > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm