I'm at an impasse with my project of a live-updati...
# thinking-together
k
I'm at an impasse with my project of a live-updating postfix programming environment (https://futureofcoding.slack.com/archives/C0120A3L30R/p1607329853147000) and would appreciate some UX ideas/feedback: * It's not clear how to scale this UI along several dimensions. What should happen when a line gets too long for the screen? What should happen as values on the stack get wide? Or deep? My screen objects (https://futureofcoding.slack.com/archives/C0120A3L30R/p1605244930088000) explored multi-line values on the stack, but it feels wasteful to repeatedly show screens, especially as the screen sizes grow larger and more realistic/useful. * Many attempts to add capabilities hit the scaling limits even faster. If I try to reimplement shell utilities like
grep
I need to support files with at least 50-character lines. Requesting URLs on the internet also requires showing long URL strings on the stack. * One thing I keep rubbing up against is the distinction between editing a program and browsing its state. Bret Victor's demos like https://vimeo.com/36579366 consistently gloss over this. Yes, it's nice to be able to play what-if experiments with your program, but you quickly realize you need to unwind one experiment to try out another. Either you need smart undo, with the ability to somehow drop milestones into the timeline after the fact. Or you need to somehow separate browsing operations from manipulations of the program itself. It feels more feasible to show many copies of a screen object if most of them stay collapsed. Or to truncate URLs if they can be expanded on demand. I do have one more idea for an interesting demo: supporting APL-like array operations. But I'm not sure if I should go down that road if there are potentially fatal problems with this whole approach. A Mu-specific constraint here is the lack of a mouse. My UI has a single point on the screen where I can manipulate things. There's no mouse, because mouse support in text-mode terminals is non-standard and requires understanding differences between terminals. Which requires dependencies beyond a Linux kernel. That's something I've managed to sidestep so far by staying extremely lowest-common-denominator in terminal capabilities. Perhaps I'll switch gears and focus on getting off the Linux kernel. Then I won't need to worry about terminal compatibilities. But then people would be required to use Qemu to play with Mu. Which sucks 😕 Perhaps that's the fundamental psychological block here: I want to keep Mu easy to try out, but beyond a point I can't undo bad historical decisions without adding some friction to checking it out. Then again, it's not like many people try it out anyway, and requiring Linux is just as much friction for someone on a Mac. Yeah, perhaps there's more OS hacking in my future. Thoughts/suggestions appreciated on this angle as well.
d
I would love to help sketching some designs. Where I normally start is having examples for longer/more complex functions and from there sketch different UX design options
❤️ 1
c
What to do about line getting too long?
Just infiniscroll to the right within in a window/frame (perhaps I'm misunderstanding the issue, this seems completely analogous to new lines in a source file).
What about awkward values on the stack
I think you'll have to just put a marker on the timeline stacks (like [$1]), then on the left of the screen show [$1]["http://example.com/blah/122512"] with the same colouring. The values are const (IIUC), so you can show a single list of values across all stacks in the timeline view
💡 1
Your point about BV skimming over the crux of live editing is a whole other thing...
g
i’m also free to sketch whenever! my initial suspicion on the stack depth stuff is that the stack shouldn’t ever really get too deep—some examples would help here. i tend to err on the side of “worry about it when it’s a problem because then you’ll have enough information to make the tradeoff” truncation is tricky and my temptation would be to truncate with a reasonable default but make the default accessible. visual stuff like this also benefits from examples. if i were to put my rebol hat on my suspicion would be that long data is often secretly structured in one of two ways: you’re using data to represent a lot of small differences, like with hash ids, and all you need is displaying something like a scannable difference, or it’s deeply structured and made linearized (like urls) and you actually want a struct and to display relevant differences based on some context (in a web app you might care if something belongs to a person or a team, or you might just be interested in document ids) if you’re just worried about unix compatibility, it might be helpful to investigate the goals: do you want to keep the ui the same? or do you want to have code for unix work on your platform? or do you just want equivalent functionality?
❤️ 1
k
Thanks everyone for the offers! While I come up with some scenarios, please free to also suggest things you wish you could do. @Garth Goldwater
my initial suspicion on the stack depth stuff is that the stack shouldn't ever really get too deep
Yeah, for sure, stack depth feels like less of a constraint compared to line length and how much horizontal space we devote to the stack state of each word. I don't care about compatibility with Unix or functional equivalence. Just something that is internally consistent and reasonably discoverable. I think if push came to shove I'd make the same trade-off as everyone else and compromise on discoverability. @Chris Knott
Just infiniscroll to the right within in a window/frame (perhaps I'm misunderstanding the issue, this seems completely analogous to new lines in a source file).
You're right. If we can solve the problem of wide values on the stack, long lines seem viable. --- One constraint I hadn't mentioned until now: I'd like for the number of hotkeys this environment needs to be small enough that I can describe them all in the menu at the bottom for some reasonable screen width. Excluding intuitive stuff like arrow keys. I think I have a new idea after this thread. Values on the stack will have 3 possible states: collapsed, truncated and maximized. By default, any value wider/taller than some threshold will be collapsed -- except at the top of the stack, where it's truncated to the threshold width and height by default. Now we need just one new hotkey: toggle the top of stack at the cursor between trunated and maximized. Maximize does exactly what it sounds like. It puts you in full screen mode browsing the data as necessary. The idea is to avoid any ambiguity about what will scroll. No nested scrollbars. Values in the stack are always in read-only mode when maximized; you can only browse within them. This suggests an analogous maximized edit mode for input words (say literal strings or arrays). But I haven't thought that angle through. Ideally I'd like this to be the totality of the UI (or some single prototype UI) for the Mu computer. Just text mode, no mouse. A single cursor on screen, an infinite 2D space that you can move around in, containing panels (functions or sandboxes) that in turn contain values. Panels and values can be collapsed or maximized. Everything one can do to be done within this framework, whether it's editing code or browsing data or running programs. (Tentatively I imagine a single address space so strong sandboxing, no concurrency only lazy streams.) Thoughts?
❤️ 2
c
Sounds like good ideas. Difficult to know how well a lot of good ideas actually work until they make contact with the enemy 😂 There's a very early Unix demo here

https://youtu.be/tc4ROCJYbm0▾

(5:58) where he corrects spelling in a pipeline. This could be a good stress test for whatever you come up with? I think your eventual solution will be far more discoverable than Unix because you'll be able to hop up and down the pipe and won't have to play computer, but you'll face the challenge of representing a dictionary that will always be too large to show in full.
❤️ 1
k
Really cool documentary, thanks Chris. I'm going to think about that spellcheck pipeline. Lol, look at the code they considered worth including in the show.
d
The more I think about this, the more I want the stack to be horizontal instead of vertical. And now the interface looks just like a Repl! (Not sure yet if it’s good or bad 😝)
❤️ 1
👍 1
➕ 1
🤔 1
k
Also interesting to see how they chose to reword Unix commands for the documentary:
Copy code
makewords file |lowercase |sort |unique |mismatches
I believe this would in reality have been something like:
Copy code
sed 's/ /\n/g' |tr A-Z a-z |sort |uniq |grep -vf dictionary
(The
sed
could also be replaced by a call to
awk
.
sed
was created in 1973, and
awk
in 1977.)
Oh no, I missed your second screenshot @Daniel Garcia.
d
A function call looks like this. First image is collapsed, second image is after expanding it. Sorry for the poor drawings I made them with my phone. Also I can explain further if it’s not clear what’s going on
➕ 1
❤️ 2
k
A vertical layout does have some advantages. I've been wondering what it would mean to "click into" a primitive. Ideally we'd switch to Mu's statement-oriented language and start showing logs of statements executed. That would flow more smoothly with a vertical layout. Can you elaborate on what advantages you see with the vertical layout? (I actually chose the horizontal layout partly because it looked like more a repl. How would you chunk a complex task into 'lines' with the vertical layout?)
d
Strings can grow horizontally in the stack and have a max-width after witch they will show with an ellipsis “really long string ...”
➕ 1
❤️ 2
Can you type more than 1 digit numbers in your current design? (Happy to move to DMs if you think we’re creating too much noise here)
k
Sure thing. In fact, if you like we can do a quick Zoom, and you can try it out interactively (with me as operator).
I'm happy with this noise for now. This feels like "thinking together" 🙂
d
Will you be available for a zoom call later today? It’s 4 am in my time zone 😬
k
Oh yes, 😬 for sure. Let's DM for scheduling.
👍 1
Conditionals and multi-line functions I've been noodling on how to do conditionals in my postfix shell. Some ideas for keywords/functions: *
return
seems quite essential. Stops executing the current function and returns top of stack. *
if{
and
}
and
}else{
. Here's how factorial would look with them:
Copy code
n fact
  = n 1 <= if{ 0 return } n 1- fact n *
*
->
executes rest of line only if top of stack is true. Factorial again, this time in two lines:
Copy code
n fact
  = n 1 <= -> 0 return
    n 1- fact n *
*
-<
executes one of the next two words depending on whether top of stack is true or false. *
->
and
-<
may also work well with
{
and
}
which group words together:
Copy code
n fact
  = n 1 <= -> {0 return} n 1- fact n *
A more challenging example is binary search. The gold standard here is Bret Victor's demo in "Inventing on Principle" (linked above; screenshot below). Some attempts in postfix:
Copy code
array key bsearch
  = array key 0 array len bsearch-range          # delegate to helper with explicit low and high

# option A
array key low high bsearch-range
  = low high >= if{ null return }                # not found
    low high + 2 div =mid                        # mid = (low+high)/2
    array mid [] key = if{ mid return }          # if array[mid] == key, return mid
    array mid [] key < if{ array key mid high bsearch-range return }  # if array[mid] < key, recurse over [mid, high)
    array key low mid bsearch-range              # otherwise recurse over [low, mid)

# option B
array key low high bsearch-range
  = low high >= -> null return                   # not found
    low high + 2 div =mid                        # mid = (low+high)/2
    array mid [] key = -> mid return             # if array[mid] == key, return mid
    array mid [] key < -> array key mid high bsearch-range return   # if array[mid] < key, recurse over [mid, high)
    array key low mid bsearch-range              # otherwise recurse over [low, mid)

# option C
array key low high bsearch-range
  = low high >= -> null return                   # not found
    low high + 2 div =mid                        # mid = (low+high)/2
    array mid [] =midval                         # midval = array[mid]
    midval key = -> mid return                   # if midval == key, return mid
    midval key < =upper?                         # upper? = (midval < key)
    # return bsearch-range(array, key, upper ? mid : low, upper ? high : mid)
    array key upper? -< mid low upper? -< high mid bsearch-range
But how to visualize a function spanning multiple lines that operates on an array? There aren't enough dimensions.
g
i think collections and branching are the two hardest things for a stack language to pull off ergonomically. here’s how factor handles them: https://docs.factorcode.org/content/article-cookbook-combinators.html . i like the approach of using quotations for control flow, although it could get hairy since your quotations would also have variable names in them. i may have some harebrained ideas incoming on a couple of these fronts, although they may be nonstandard (example preview: you should have a stack language, an array language, and a hash/record/dictionary language, and their editors should just compose/nest )
k
I've been thinking similarly. Though I'm not sure what an array language with indexing looks like. I should have mentioned quotations. I'm resistant to them because they occupy space on the stack without advancing the computation. However, Daniel Garcia did point out that the effect of
if
could be expanded like a function call. So it's worth trying.
I'm now noodling on two ideas:
break
and
loop
words and infix-chunking. It seems promising how
break
and
loop
carry over like themes from lower levels of the stack. And we really need infix-chunking once we start indexing into arrays. Most of the time you want to see
ÂŤarray[i]Âť
with a single stack under it, but to edit it I'm imagining first expanding it to
array i []
with 3 stacks under it. The following mock-up could be 6 months of work. I'm still weighing whether it's worthwhile.