2023-09-10 00:42:47 TEXAS BEAT ALABAMA. 34-24. Yee HAAAAAAAAA!!!!! 2023-09-10 00:43:20 I'm a big fan of ANYONE that beats Alabama, but in this case it's extra good because I went to Texas. 2023-09-10 02:34:01 So, there are 255 function in my DM42 "catalog." 2023-09-10 02:35:49 xelxebar: One fundamental "friction" between Forth and APl is APL's monadic vs. dyadic functions (I.e., cases where the same function or operatore works either way, and sometimes does very different things). 2023-09-10 02:36:09 You don't necessarily have only one object on the stack when you want to do a unary / modadic operation. 2023-09-10 02:36:46 If I have a sharp separation between "proram code" and "algebraic expression" then it's not that much of a problem. But it is problematic if I am attempting any more thoroughgoing fusion. 2023-09-10 02:39:07 It's easy enough to solve if algebraic expressions are "contained.' You'd just assume an "empty slate" when you started at the right. ⍺ and ⍵ would give you the left and write operands, and you'd just go from there. It would be like putting a "bubble" around that sequence of activities. 2023-09-10 02:39:37 The only way for data to get in would be via those symbols ⍺ and ⍵. 2023-09-10 02:39:50 Or via a named variable or a literal. 2023-09-10 02:41:14 You'd be able to store an algebraic expression in a variable. That's more or less what APL does with foo ← dfn 2023-09-10 02:42:40 So, if you want to use items on the stack, you'll have to reference them via ⍺ / ⍵. 2023-09-10 03:01:03 KipIngram: Exactly. You're pretty much describing exactly lexical scope in dfns, IIUC. 2023-09-10 03:01:40 Though, honestly, I'm not super bullish about marrying languages with such a stark boundary like that. 2023-09-10 03:04:04 It's part of my beef with regular expressions. I love them, but most languages have an extremely narrow band interaction with the regex language itself, which causes lots of pain around its use in practice. 2023-09-10 03:06:19 sed, awk, and sam with it's structural regular expressions are kind of best in class in this regard, IMHO. 2023-09-10 03:08:32 Basically, I think there's gotta be a way to marry the bare-metal feel and implementation simplicity of Forth with the ergonomics of APL. 2023-09-10 08:30:01 i try to think on the best way to provide method calls 2023-09-10 08:30:55 i have . as a prefix for a method call, which will take an object from the stack 2023-09-10 08:31:16 .some_name 2023-09-10 08:32:01 but for now it does not take any argument and always pushes the return value on the stack 2023-09-10 08:33:02 i need some way to give arguments, but i don't want to expect always an argument list or having two alternate syntax for when you give it arguments or not 2023-09-10 08:33:30 cause i also need an alternative syntax for when you want to call a method, but do not want any result on the stack 2023-09-10 08:34:20 i think i'll use - for method calls that do not put anything on the stack 2023-09-10 08:34:46 but still i need a way to push arguments to that method call 2023-09-10 08:35:25 in the past i had 4 variations of syntax 2023-09-10 08:35:43 push the return or not, give arguments or not 2023-09-10 08:36:14 i don't like that and already have .method and -method 2023-09-10 08:36:39 - won't return any value on the stack while . does 2023-09-10 08:36:54 but still need to give arguments when needed 2023-09-10 08:37:36 vms14: I'm looking at making a subset of my vm instructions operate in a type-dependent way (type of top stack item). 2023-09-10 08:37:47 for now the only idea i have is to have some kind of alternative stack to push arguments there 2023-09-10 08:37:58 At least I'll have that possibility as something I can "activate." 2023-09-10 08:38:05 and this stack gets reset at every method call 2023-09-10 08:38:19 but it looks like it can give troubles 2023-09-10 08:38:26 Alternative stacks always wind up requiring some way to specify when to use the alternative instead of the main. 2023-09-10 08:38:37 as at any moment everyone can push arguments there 2023-09-10 08:39:12 KipIngram: in my case the idea is to have some word that pushes an argument from the stack, to that alternative stack 2023-09-10 08:39:40 you never have to retrieve from it, it's just an array for method calls 2023-09-10 08:40:02 when you call the method like .something 2023-09-10 08:40:18 if there's something on that array it will be given to the method call 2023-09-10 08:40:32 and after execution it will be reset 2023-09-10 08:40:47 but it's a bit weird 2023-09-10 08:41:01 and everyone can push arguments there 2023-09-10 08:41:19 i have no more ideas for not having 4 syntax variations 2023-09-10 08:41:35 this way i have .method and -method 2023-09-10 08:41:51 and if they need arguments i'd have a word to push them 2023-09-10 08:42:15 but it would be global accessible 2023-09-10 08:42:42 KipIngram: about activate 2023-09-10 08:42:54 there could also be a flag 2023-09-10 08:42:56 but meh 2023-09-10 08:43:18 what i did in the past was to append a * on the method call nane 2023-09-10 08:43:25 like .method* 2023-09-10 08:43:35 this means it expects arguments 2023-09-10 08:43:39 Actually it will involve changing the table entries for those instructions. Or having a pointer to that table and changing it. 2023-09-10 08:43:52 So that it points to a table with the changed pointers. 2023-09-10 08:44:37 hmm 2023-09-10 08:44:59 i think i'll stay with the * suffix 2023-09-10 08:45:22 .method -method .method* -method* 2023-09-10 08:45:31 i kind of dislike that 2023-09-10 08:45:54 but a global accessible alternative array looks like a worse idea 2023-09-10 08:49:24 i need a way to specify that 4 things 2023-09-10 08:49:43 that way i can even create perl objects with this 2023-09-10 08:50:01 'IO::Socket .new 2023-09-10 09:11:27 The array approach is just because of my overall architecture - I'm implementing my vm via an instruction table. When I'm in "native Forth" mode, the entries for those instructions (the ones that actually depend on the kind of data on the stack) will point to the usual basic functions. When i want to switch to the "type sensitive" mode, I'll just change that. I'll probably have two tables - one with the 2023-09-10 09:11:29 optimally efficient native instructions and one with those entries able to look at the stack item's type and then use that to make a choice as to what to do. 2023-09-10 09:11:48 But this is totally dependent on how I'm putting my system together - I wasn't implying that it would be the 'best way for you'. 2023-09-10 09:19:20 I don't plan to rewrite a bunch of table entries every time I change modes - I'll just have two tables and will switch the whole table out. Most of the entries will be the same, but the ones for these "non-agnostic' instructions will be altered. 2023-09-10 09:19:58 For example, DROP will be DROP - DROP doesn't care what kind of data is represented by the stack item it's dropping. 2023-09-10 09:20:38 But + for example will do something different for stings vs. numeric arrays vs. integers etc. 2023-09-10 09:23:06 s/stings/strings/ 2023-09-10 09:28:38 hmm 2023-09-10 09:29:08 i think i don't want to mess with multiple dispatch 2023-09-10 09:29:33 not for now at least, it will always remain open 2023-09-10 09:29:51 some time ago i was joking about perl oop 2023-09-10 09:30:12 and i was told it's more like a framework to create your own oop system 2023-09-10 09:30:16 Yeah - I'm only considering it because there's already a dispatch table in my design. In the type sensitive mode, it will be easy to use the stop stack item's type to do a second dispatch for an instruction. 2023-09-10 09:30:49 i see it's kind of true 2023-09-10 09:31:04 See, those non-agnostic instructions would otherwise become useless. 2023-09-10 09:31:22 A piece of code that adds two integers on the stack does nothing for you if you don't HAVE two integers on the stack. 2023-09-10 09:31:38 i do have interest in common lisp object system 2023-09-10 09:31:47 So I figure I may as well arrange to have those instructions do something else that IS useful. 2023-09-10 09:32:00 CLOS and the metaobject protocol 2023-09-10 09:32:14 And meanwhile I'll still get the compactness benefits of my instructions. 2023-09-10 09:32:26 it's mainly made with hash tables 2023-09-10 09:32:46 but for now i just want to blend with perl oop 2023-09-10 09:32:54 Instead of having a matrix/matrix add or multiply require a call that consumes a whole cell, I'll still be able to do it with an instruction. 2023-09-10 09:33:48 And there are quite a few of these non-agnostic instructions. All the basic arithmetic instructions, the boolean logic instructions, etc. 2023-09-10 09:34:15 So for types that don't need a huge number of methods, this covers the whole dispatch situation. 2023-09-10 09:34:26 i ended with emacs and evil mode 2023-09-10 09:34:40 i feel fine for now 2023-09-10 09:34:52 feel evil 2023-09-10 09:35:54 :-) What's evil about it? 2023-09-10 09:36:55 APL doesn't require spaces the same way Forth does. 2023-09-10 09:38:01 For example, that string from yesterday, 5 5⍴⎕A, parses as 5 5 ⍴ ⎕A. 2023-09-10 09:38:50 So, two things going on there. First, adds a separation after the , and also ⍴ is recognized as a token. 2023-09-10 09:39:25 I once thought about adding a list of tokens to Forth (usually single characters) that will be recognized as soon as they're seen, regardless of whether they're space-delimited or not. 2023-09-10 09:39:50 That list would initially be empty, so you'd get standard behavior. But you could populate it if you chose to. 2023-09-10 09:40:35 And for a while I've been thinking that Forth really ought to offer a way to recognize "complex literals." For example, "I am a string" is a perfectly fine string literal. 2023-09-10 09:40:42 But we can't use it in Forth. 2023-09-10 09:41:26 We have special-case code (i.e., code that doesn't just look for dictionary matches) to handle numeric literals, but we pay no mind to other types of literals. 2023-09-10 09:41:34 I think strings are just as fundamental as numbers are. 2023-09-10 09:42:11 Given that it's Forth, I think the right approach would be for the programmer to be able to TELL Forth what things were going to be literals. 2023-09-10 09:42:28 We've got all this control over the code we execute, but no control over how our input is processed. 2023-09-10 09:42:36 It's a fairly small box we've been put in. 2023-09-10 09:50:48 It's a kind of open-ended issue (in terms of the programmer being able to DEFINE literal formats), but at the most basic level I feel like literal strings should exist. 2023-09-10 09:51:15 I think the reason Forth has never gone there is because it doesn't really offer a good place to put such strings anyway. 2023-09-10 09:52:06 The thing is, though, now that I've got this two-layer system in mind, with "basic Forth and then type-sensitive mode," this could also be something that comes with the more powerful mode. 2023-09-10 09:52:23 Keeping the "basic mode" pure Forth. 2023-09-10 09:54:50 A simple way to get closer to the "spaces not absolutely required" functionality would be to match partial strings. Say you're parsing characters out of the input, and after a few characters you see that what you've got so far has a match in the dictionary. Keep parsing - as long as you still match, greedily take characters. But if you pick up a character that doesn't match, then take everything before 2023-09-10 09:54:51 that as a word. 2023-09-10 09:56:41 So in that string above, we'd parse the first 5 when we saw the space. Then we'd get the second 5, and by itself it represents something valid. Then we see the ⍴ and 5⍴ isn't in the dictionary, so we take the second 5 then. 2023-09-10 09:57:08 And for the next item, we have ⍴ and that has a match, but when we see ⎕ the match is broken, so we take the ⍴. 2023-09-10 09:57:38 I've barely thought about this - there may be some example case that shows it as no good. Haven't thought of it yet, though. 2023-09-10 10:30:28 In that book he wrote Chuck proposed somethin at least kind of along these lines. His notion was that you'd parse out a space delimited word, and search the dictionary for it. If the search failed, then you'd drop a character from the end and search again. Repeat. If you eventually found a word, you'd execute it and the characters you had to drop to get there would be treated as parameters of some kind. 2023-09-10 10:31:23 Not really the same thing, but similar in the sense that it's a departure from rigorous space delimiting. 2023-09-10 10:46:56 The way I was looking at doing this was modeled along the RPL lines. In RPL, an "algebraic expression" is delimited by single-quotes. 2023-09-10 10:47:13 "program code" is delimited by those << ... >> symbols. 2023-09-10 10:47:31 Anyway, they're different types - they can be processed with different parsers. 2023-09-10 11:19:52 xelxebar: I'd been thinking that the part of this system that does 'algebraic expressions' is where the APL type stuff would come in. However, I think the primary purpose of algebraic expression support in RPL is to allow the solver to work with equations expressed in that form. For example, you might put in 'a*x^2+b*x+c=0' and then you could aim the solver at that - it would offer you up a, b, c, and x as 2023-09-10 11:19:54 the variables and you could set any three of them and solve for the fourth. 2023-09-10 11:20:37 I'm not sure an apl expression would allow that much flexibility. Doesn't mean apl has no value in the system - I'm just not sure if it actually goes in "like that." 2023-09-10 11:20:49 it feels to me like the real benefit of it is the access to array processing. 2023-09-10 11:22:01 So maybe these are different things. Once an array type is supported, it just offers a new set of things one can do with the arrays. 2023-09-10 11:37:58 xelxebar: How would you want to see a multi-dimensional "array editor / browser" work on a calculator? 2023-09-10 11:38:58 For 2D matrices, the DM42 just offers you up/down/left/right cursor motion keys, and it looks like you can "go to" a particular position too. 2023-09-10 11:39:59 For a general dimensionality, though, I think you'd need some more generic type of motion system. 2023-09-10 11:40:44 I doubt anyone would have a lot of interest in ENTERING higher than 2D arrays, but you might generate them via calculations and then want to inspect them. 2023-09-10 11:43:11 I want to be able to work with tensors - I've had that as a target for a while. That's going to impose an extra requirement on the representation, above and beyond what APL needs, because each axis can be contravariant or covariant. 2023-09-10 11:43:57 For example, in general relativity you've got this bad boy: 2023-09-10 11:43:59 https://i.ytimg.com/vi/-Il2FrmJtcQ/maxresdefault.jpg 2023-09-10 12:05:19 Heh - this is fun: 2023-09-10 12:05:21 https://www.google.com/maps/d/viewer?mid=1EVEViVHIuS8nXzhz66b7rEwwRqo&ll=41.901883714102524%2C-87.5588755657483&z=9 2023-09-10 12:05:40 someone painted up a Google Map of the Chicago area with all the pertinent Dresden Files landmarks. 2023-09-10 12:10:09 KipIngram: not evil at all, it feels good cause now i have both hotkeys 2023-09-10 12:10:23 i can use the one i prefer at any moment 2023-09-10 12:10:42 say to save with ctrl+x ctrl+s or :w 2023-09-10 12:10:57 it's cool 2023-09-10 12:24:01 xelxebar: Looks like ? gives me a random integer from integers up to , and ?0 gives me a random number betwee 0 and 1. What if i want to fill a vector or a matrix with random numbers from 0 to 1? 2023-09-10 12:24:33 3 4⍴?0 gives me 12 copies of the same random number. 2023-09-10 12:47:14 Ah, that works. 2023-09-10 12:47:17 x←3 4⍴(12?1000000000)×0.000000001 2023-09-10 12:47:19 x 2023-09-10 12:47:21 0.182629632 0.217457735 0.422122593 0.184416736 2023-09-10 12:47:23 0.42848243 0.886052393 0.303773321 0.353070613 2023-09-10 12:47:25 0.400099606 0.192657316 0.265074796 0.966209742 2023-09-10 12:47:59 Slightlly annoying, though to have ?0 give a result like I want but have to do those backflips to get an array of them. 2023-09-10 13:17:53 I'm starting to see how Monte Carlo analyses would work well in APL. Start out with a "model" - the math relationships capturing your system dynamics. Then expand that over a vector of random numbers that get used to nudge one of your model parameters. So you get a copy of the analysis all along that new dimension. Then peel the results of interest out of it. 2023-09-10 13:30:30 what RNG does it use? 2023-09-10 13:31:35 Oh, I saw something about that a few minutes ago. A fairly standard one, I think, though I did see articles implying that it's less than perfect. Apparently if you interpret the sequential items that come out of it as N-tuples, then your N-tuples wind up lying in hyperplanes instead of being distributed the way you'd like. 2023-09-10 13:31:49 The advice was to shuffle your samples before grouping them into N-tuples. 2023-09-10 13:32:29 Multiplicative congruential generator. 2023-09-10 13:33:38 x(n+1) = 7^5 * x(n) mod (2^31-1) is in this one paper I'm looking at. 2023-09-10 13:36:54 Oh, nice. After adjust the real time clock calibration on my calculator, it's now stayed within about three seconds of the right time, since the last time I set it. 2023-09-10 17:13:41 You know, I have a feeling there were heated discussions among the planners of APL over starting arrays at 0 or 1. And in the end no one would give in, so you can do either one. 2023-09-10 17:28:13 KipIngram: The standard idiom is something like ?3 4⍴0. ? automatically lifts to higher arrays, so you just fill an array with the upper bound first. 2023-09-10 17:30:57 Yeah, ⎕IO lets you set the Index Origin and is agreed to be mildly annoying. APL papers usually start out declaring their ⎕IO and ⎕ML convention. 2023-09-10 17:33:05 What's ⎕ML? 2023-09-10 17:34:33 Oh, nice - that's much better than my random matrix snip. 2023-09-10 17:36:39 Oh, I found ⎕ML. 2023-09-10 17:39:09 That's almost more of a disruption that ⎕IO. 2023-09-10 17:46:21 KipIngram: Yeah, Dyalog APL does have historical quirks. In practice, though, almost every just uses the default ⎕ML these days. It was originally there to help people migrating from other APL systems. 2023-09-10 17:57:45 Well, the first non-calculator programming I ever did was FORTRAN, and arrays started with index 1. So I got used to that, and then later when I ran into C it seemed odd. These days, though, it seems entirely normal. Hard to overlook the fact that N bits holds 0 through 2^N-1, and not 1-2^N. 2023-09-10 17:57:53 hold 2023-09-10 18:58:59 Wow - all these weird manipulations you can do on arrays are crazy. This seems like it's a lot more than math to me (Iverson was originally just trying to create an improved math notation - I think it grew well beyond that later on). I know a good bit of math, and I've just never seen any math that does all of the different re-arrangements I see possible in some of these cases, like all the possibilities 2023-09-10 18:59:01 with transpose. 2023-09-10 19:00:45 Yeah, at first blush it's a lot of abstract array manipulations. 2023-09-10 19:01:31 Where APL really comes alive is what these abstract manipulations reify to when given some domain data. 2023-09-10 19:01:52 And how they combine together in serendipitous ways. 2023-09-10 19:02:45 Here's a little blog post I munged together that kind of gets at that: https://blog.wilsonb.com/posts/2023-07-24-suggestivity-and-idioms.html 2023-09-10 21:37:52 Like your blog entry. At any rate, the point I was trying to highlight was that there seem to be more operations in APL than I ever saw in linear algebra. I'm not familiar, at any rate, with any linear algebra application for reversing the entries in a vector. As in (t, x, y, z) -> (z, y, x, t). 2023-09-10 21:38:01 There looks to be quite a few things of that nature in there. 2023-09-10 21:38:28 But, I guess data processing might bring up things that math doesn't bring up. 2023-09-10 21:44:14 You know, it would be pretty easy to do a map word in Forth. At the time map executed, the operand would be on the stack, and the mapped operation would be pointed to by the instruction pointer. So map would just iterate over the operand and EXECUTE that xt, and nudge IP past it when done. 2023-09-10 21:44:19 Clean and simple. 2023-09-10 21:44:50 Or, if map was a definition itself, then the address of the mapped function would be on the return stack. Either way - map can get at it. 2023-09-10 21:45:49 The F18A caches the top item of the return stack in a registers as well as the top of the data stack. Given that design, EXECUTE is simply swapping IP with TOR. 2023-09-10 21:46:27 Seeing that was basically what encouraged me to do that return stack top cache - that's just really clean. 2023-09-10 21:47:30 Probably would make coroutines work really cleanly as well. 2023-09-10 21:50:21 that "how not to code in APL" article I linked the other day seems quite focused. It's like there's a subset of the language they "approve of" and a subset the definitely do *not*. 2023-09-10 21:50:41 If I guessed they approved of the purely function aspects only would I be close? 2023-09-10 21:50:59 Functional programming really seems to be something that breeds fanaticism. 2023-09-10 21:57:08 So, if I do this: 2023-09-10 21:57:11 (+/?10000000⍴0)÷10000000 2023-09-10 21:57:44 That's going to actually create a 10 million long vector of random numbers and then sum over it, right? It's not just adding 10 million times? 2023-09-10 21:57:55 Amazing how fast it can do that. 2023-09-10 21:58:34 But it won't do a hundred million. 2023-09-10 22:00:08 some languages can operate on "infinite" lists 2023-09-10 22:02:46 I guess they'd keep some script representing it instead of having it explicit? 2023-09-10 22:03:44 Easy enough to do if it's just "random numbers," but what if it was bank balances or something? 2023-09-10 22:03:53 You can't very well "summarize" such a list. 2023-09-10 22:04:43 the trick is to be lazy and only calculate what is asked for, on the assumption that the ask is reasonable 2023-09-10 22:09:09 xelxebar: Consider transpose and other similar array rearrangements. Does APL typically actually move the data, or does it adjust its internal representation so that it just changes the way it accesses the data? 2023-09-10 22:10:00 I want to think that the latter should be possible. 2023-09-10 22:11:01 KipIngram: One use of ⌽ is to get left-associative folds. Due to evaluation order and the definition of Reduce (/), folds default to being right-associative. 2023-09-10 22:11:55 E.g. consider f/V vs f⍨/⌽V for some dyadic function f and vector V. 2023-09-10 22:15:37 Ok. You're stretching me a little. 2023-09-10 22:15:41 AFAIU, Dyalog arrays are stored as contiguous blocks of elements arranged with the elements in row-major order. 2023-09-10 22:16:05 Ok, that implies that transpose and friends will shift the data. 2023-09-10 22:16:29 Which seems like the "obvious brute force" way to handle such things. 2023-09-10 22:17:29 There might be a "transpose" boolean flag in the array rep for rank 2 arrays (i.e. matrices). 2023-09-10 22:17:43 I'll ask the devs. 2023-09-10 22:17:44 ^ right. 2023-09-10 22:18:02 I was imagining a sort of "generic" thing of that sort. 2023-09-10 22:18:27 Where you don't have a fixed standard for how the dimensions lay out, but rather can specify it on an array-by-array basis. 2023-09-10 22:18:41 Then you might be able to transpose or whatever just by rewriting that map. 2023-09-10 22:19:05 But for higher-rank arrays, you'd need 64-ish bits at minimum to represent arbitrary permutations of higher-ranked shapes. 2023-09-10 22:19:23 Though, it might limit your ability to later use things like the rep prefix and so on for some calculations. 2023-09-10 22:19:27 And that *vastly* complicates the underlying striding algs. 2023-09-10 22:19:40 Or maybe not - maybe you'd use rep whenever you were working on continguous items. 2023-09-10 22:20:08 Yeah - I've barely started thinking about it - who knows what traps are lurking there. 2023-09-10 22:20:34 I enjoy that kind of low level stuff though, especially when it's "clever." 2023-09-10 22:20:53 You have to be really careful about associativity and commutivity, though. There are lots of clever algs and short-circuts to make reductions crazy fast for well-known idioms. 2023-09-10 22:22:59 Yeah, it's totally interesting. One of the less satisfying things about Dyalog APL is that the map between code and "what the machine is actually doing" is kind of opaque 2023-09-10 22:24:06 Anyway, about reductions, do you grok f/V, say +/1 2 3 for concreteness? 2023-09-10 22:24:36 Yes, I know what that does. 2023-09-10 22:25:57 That seems to be one of the "early examples" when you start reading about the language. 2023-09-10 22:26:32 Cool, this is a good example, then. So f/a b c is (extensionally) equivalent to a f b f c, which the order of operations rules make equivalent to (a f (b f c)), i.e. right-associative. 2023-09-10 22:27:02 ok. 2023-09-10 22:27:07 But what if we want ((a f b) f c)? If f is non-associative like minus or divides, then it matters. 2023-09-10 22:27:19 Right. 2023-09-10 22:28:46 So just put that expression in the mirror (c f' (b f' a)) and define f' such that it's just f but with left- and right-args swapped. 2023-09-10 22:29:12 That swapping operation is just called Commute and written ⍨ 2023-09-10 22:30:56 So f⍨/⌽a b c is just (c f⍨ (b f⍨ a)) which is just a mirrored ((a f b) f c) . 2023-09-10 22:32:25 Ah, that sheds a bit of light on the commute operation. 2023-09-10 22:32:49 One nifty thing about right-to-left evaluation order, +/ gives the sum and -/ gives the *alteranting* sum. 2023-09-10 22:32:49 Good explanation - that mirror picture helps. 2023-09-10 22:33:13 And both of those pop up in series that you run into in various places. 2023-09-10 22:33:30 Exactly. ⌽ and ⍨ are extremely common. 2023-09-10 22:33:58 I'm using basically this pattern to strip leading and whitespace from strings in a parser project of mine. 2023-09-10 22:34:56 When you start messing with APL trains, commute becomes really relevant there as well. 2023-09-10 22:35:10 This is an interesting puzzle. Because Forth and APL diverge a bit in how they "take input." But the input layout seems just about as important in APL as the data structures and so on. 2023-09-10 22:35:37 The data structures - easy enough to move into a Forth world. The input layout - not quite as easy. 2023-09-10 22:35:59 Unless I just draw a sharp line and say "here's a string, and it will be processed as APL." 2023-09-10 22:36:23 A true synthesis between the two seems a harder undertaking. 2023-09-10 22:37:00 Yeah, IIRC, there are Python libraries that do basically that. It's a quick 'n dirty way of making APL available. 2023-09-10 22:37:53 It's a way I've thought about making LISP available in Forth. A simple LISP interpreter itself didn't seem like it would be that hard, so the idea would be for Forth to just chuck a string over and say "Hey LISP - run this." 2023-09-10 22:38:49 The main obvious challenges to a tighter synthesis would be supporting left and right arguments, as you notice, but also operators. 2023-09-10 22:39:05 Another difference between Forth and APL is the fact that lines mean nothing in Forth. 2023-09-10 22:39:22 Not really. It just sees a continuous stream of input characters. 2023-09-10 22:39:53 It may PROCESS line by line, but logically it's unimportant. 2023-09-10 22:40:41 : foo 1 2 3 . . . 2023-09-10 22:40:43 ; 2023-09-10 22:40:45 works fine. 2023-09-10 22:41:16 I change my prompt - if there's an open definition at the end of the line I print ... instead of ok 2023-09-10 22:41:31 Well, operators are "left associative", so L f∘g∘h∘j R is the same as L ((f∘g)∘h)∘j R. 2023-09-10 22:41:31 In green, for "all is well." 2023-09-10 22:42:13 So that's a rigorous difference between functions and operators? 2023-09-10 22:44:03 Yup. Operator binding is defined that way. The lingo says that they have "long left scope" whereas functions have "long right scope", meaning that operators take as much as the can to their left, while functions do that to their right. 2023-09-10 22:44:27 Ah. This is very helpful. 2023-09-10 22:44:36 "Greedy." 2023-09-10 22:45:02 In a way, yeah.