4 ms·
> This sounds really interesting! Cheers! > I'm happy my article was helpful to you. It was just the thing! Very helpful. Thank you for writing it. > I rea
by carapace 7y ago
> This sounds really interesting!
Cheers!
> I'm happy my article was helpful to you.
It was just the thing! Very helpful. Thank you for writing it.
> I really like how your notebooks integrate (judiciously chosen)
execution trace display with explanation. I think this is something
literate programming benefits a lot from.
Cheers again. I find those traces aesthetically pleasing in and of
themselves. I can imagine a (strange, niche) art gallery that had large
prints of them on display. Jupyter notebooks have so many good things
going on. (Not that they're perfect, but they hit a sweet spot IMO.)
> I wonder if there's a way to include a smooth gradient from specific
examples like your V('80 P') to more general cases, either with abstract
interpretation or a Bret-Victor-style overwhelming battery of data
points.
I'm sure there is, there are so many possibilities. Just the traces
alone could be animated or made into (partial) graphs (have you seen
http://pythontutor.com/ http://pythontutor.com/ ?)
Concerning abstract interpretation, if you squint a little,
the Prolog code already does that. Markus Triska suggested using the
CLP(FD) integer constraints for the math primitives, which was brilliant,
so it's doing a kind of abstract interpretation. You can give it a
completely general stack "type" (just a logic variable) and it will tell
you, e.g. '+' is:
int(A), int(B) -> int(A+B)
and so on. It's also pretty easy to replace the main operators to get a
different (but related) semantics, and I'm pretty sure that relates to
what Conal Elliot's "Compiling to Categories".
I'm not sure which Bret Victor thing you're thinking of, but it's easy to
do things like evaluation over a domain (rather than a single value), or
partial evaluation (again with specific values, domain, or logic vars.)
And you can do that trick where you give it the result and ask it to
generate programs (as in http://webyrd.net/quines/quines.pdf http://webyrd.net/quines/quines.pdf) and
variations on that. I think it would also be easy to e.g. add slider
widgets and have them evaluate expressions (possibly already partially
evaluated for efficiency) when the user "sweeps" them.
Also, and this is more hand-wavey, I think there should be a way to use
the traces to extract information about how programs unfold over time.
What I mean is, the traces typically have clear initialization and
completion phases with a loop or recursive function in between, those
repetitive parts show up clearly in the traces, and it should be possible
to overlay them on each other and find the static vs dynamic terms, and
maybe do something with that information. (Unroll loops or create new
versions that do less work or whatever. Hand wave.)
> I watched an Aaron Hsu talk from Functional Conf not long ago where he
claimed that Co-dfns has a comment-to-code ratio of 400:1 or something,
because his dissertation is the comments, and there are several pages of
it per line of code. Having seen the glyphs in the talk, I haven't dared
to open the dissertation yet; I'm afraid it may open a gate, causing
cenobites to come out of xpdf.
Heh heh heh. Yeah, that makes sense if you're working in a system that
allows for easy refactoring: code should approach the Kolmogorov
complexity limit of the problem it solves as it ages, eh? Ripen instead
of rot.
> I really like RPN calculators because of their immediate feedback —
http://canonical.org/~kragen/sw/dev3/rpn-edit http://canonical.org/~kragen/sw/dev3/rpn-edit is one keyboard-driven
prototype with a structure editor —
Okay that is freakin cool. I'm probably going to have steal some ideas from
that if you don't mind? I like the idea of being able to edit and
re-evaluate sort of like a spreadsheet. And making the structure of the
expression visible like that seems like it would be very useful.
> but I think that while they reduce the gulf of evaluation, making it
easy to see if the step you just took was the right step, they may expand
the gulf of execution, making it harder to figure out what you need to do
to get closer to your goal.
> An extreme version of this, which is not RPN, is
InputStream s = foo();
return new BufferedReader(new InputStreamReader(s, Charsets.UTF_8));
> where it takes considerable familiarity with java.io to immediately know
how to get a BufferedReader given only an InputStream, because of the
intermediate step via an InputStreamReader.
That's where Joy seems to shine, it's been pretty easy so far to set up
the context for a function I want to write and then derive an
implementation in a kind of mathematical way.
> Today I was thinking about the cisco IOS CLI described in
https://news.ycombinator.com/item?id=22498665#22500151 https://news.ycombinator.com/item?id=22498665#22500151 — something I
haven't used in a long time — and it occurred to me that LOGO or REBOL is
close to being FORTH or Joy spelled backwards. Instead of reverse Polish
notation, it's forward Polish notation, enabled by all the functions
having fixed arity. So, if you're writing left to right, you write your
code top-down, as in C or bash, instead of bottom-up, as in Smalltalk or
FORTH. You've built a noun-verb system, like the Macintosh, while Unix
and IOS verb-noun. Is one or the other globally more usable? I don't
know! The Java above is hard for programmers new to Java to write, but
it's verb-noun.
> One thing that has occurred to me is that in purely functional
contexts, in a verb-noun system, it might be reasonable to execute every
type-applicable operation and display the results, maybe as a balloon
next to the operator name; then the user need only select which of all
the possible next states they want to go to. So, for example, if you have
two numbers on the stack, you might have their sum, their difference,
their product, their quotient, and the results of dup, drop, and swap,
each displayed next to the relevant operator; then you can select the
desired operator to go to that stack state. That seems like it might help
with the gulf of execution, providing you with one step of lookahead. But
maybe it would be more distracting than helpful?
I had that idea too. The Prolog code does that anyway to type-check (the
interpreter is also the inferencer, because Prolog is awesome that way)
so there's no reason to throw the result away rather than display it
somehow. But with infinite undo you've got that tree of possible
evaluation already, eh? It comes down to ergonomics.
> But then, you could imagine doing the same thing with a verb-noun
system, as long as all the arguments have reasonable default values so
that you can somehow get useful visual feedback on the results even
before you have chosen all the arguments; for example, for arithmetic
operations like that, the default value might be λx·x, the identity
function, so that you see graphs of all possible results.
That would be pretty cool.
> I used to chat with Slava when he was first working on Factor (before
he started working at Apple)
That's cool! :-)
> but I'm embarrassed to admit I've never actually tried Factor. (Or
Joy!)
Heh, me neither. I want to use it just because it's so cool.
> Is there a screencast of the hypertext features you mention?
Dunno, but you can just download it, fire it up, and click "Help". It's
nothing fancy, just a little mini-browser with hyperlinks.
> What do you think about Cat?
I looked at it when I first started with Joy but it wasn't quite right
somehow. Slightly too complicated, or wrong emphasis or something, I
forget.
- kragen 7y agoBy all means, feel free to copy the UI of any of my UI experiments! Most of the things I write I license under a liberal license to make sure people know they can do that; Dercuano http://canonical.org/~kragen/dercuano http://canonical.org/~kragen/dercuano is in the public domain, for example, and it might have some things in it that you enjoy. I like Philip Guo's Python Tutor, and I used it a few weeks ago to show my girlfriend some algorithmic stuff, but (following Victor's Magic Ink) I think its mandatory interactivity is a significant drawback. To the extent that it's possible to visualize a program's behavior as a static image — perhaps a zoomable one — rather than an animation or a slideshow, I think doing so is an improvement. (In many cases it's adequate to just use a comic strip, as Victor did in his binary-search visualization in Inventing on Principle, or as you are doing with your V, but sometimes that involves too much compromise.) But Python Tutor is already tackling a very difficult visualization problem, and the static equivalent is an even harder visualization problem. I enjoy Conal's work but I haven't read Compiling to Categories yet. I don't know much about category theory or Haskell, so I always struggle with his papers. The particular Victor thing I was thinking about when I said "overwhelming battery of data points" was Up and Down the Ladder of Abstraction, but it also applies to, for example, the circuit example in Inventing on Principle. I think Prolog CLP(FD) is less powerful than miniKANREN, except in the sense that you can of course implement miniKANREN in Prolog, but I'm no expert. I haven't seen an equivalent to Byrd's mindblowing quine-generation paper that uses Prolog instead of Scheme for either the implementation or the language being interpreted; I wonder if you could get some mileage out of that approach? What you're describing about modeling traces of programs for a Turing-complete machine with a finite state machine is something I'd like to see explored more. Of course it's straightforward to produce a conservative NFA approximation of a more powerul automaton: whenever the automaton makes a decision based on information that's excluded from the NFA's state, the NFA makes a nondeterministic choice among the possible alternatives. So, given any possible mapping from the state of the more powerful automaton into some finite set of states, you can straightforwardly compute the NFA, and from that you can compute a DFA. Bjoern Hoehrmann's parselov takes such an approach to the problem of parsing context-free grammars, for example. (For better or worse, his favorite logic programming language is SQL.) A difficulty I have with the programming-as-Kolmogorov-compression approach is that, at least in the case of Co-dfns, it didn't really speed up the process of creating the software; in fact, it slowed it down. It might speed up the process of understanding the software for other people, which is the major benefit in my view of the similar compression of algebraic notation for equations, but I haven't seen strong evidence of that, and I've seen weak evidence of the opposite — legions of programmers throwing up their hands at maintaining APL code, calling it unreadable, and flocking to alternatives as soon as they became available, such as VisiCalc, MATLAB, S, and Lisp, and their modern replacements such as Gnumeric, Octave, Numpy, TensorFlow, R, and Python. I guess I finally need to buckle down and learn an APL after 25 years of dithering. It's possible that with better visualizations of examples, some of that perceived difficulty will evaporate. Thank you for this wonderful conversation! Forgive me for not having responded earlier.