41 comments

[ 3.1 ms ] story [ 94.2 ms ] thread
Doesn't work in FF mobile...
This is great. Reminds me of Bret Victor’s work.
This article (starting with its nonsense title and domain) gets bogged down in pretentious philosophy instead of focusing on what this actually does.

"magic notebook" "thinking with code" "visionary software artist"

It's a javascript notebook by the way

Why is it whenever somebody 'famous' has a code blog, it's a javascript blog.
I was looking for a list of the Maynard's laws mentioned in the article. Turns out the author is called Maynard and he just made them up on the spot.
When you have a resume like this https://www.software-artist.com/me/ you can make up any laws you want as far as I am concerned.

He worked for Engelbart! Worked on ARPANet! Was sending email in 1975! And is still coding! What an inspiration. Very cool blog.

I too read his bio and thought the same thing. As I read it, it reminded me of “The Music Scholar” routine by Scharpling and Wurster [0], where a radio caller personally witnessed like the entire history of ‘70’s rock.

Engelbart, Xerox Parc, EA, Silicon Graphics, and Google Maps? Yeah, he can call out his own laws.

0: https://youtu.be/Z75qsaak9Po

Can it be used to call numpy, pytorch etc? If not, it's useless
Whats wrong with the domain. Do you not believe software could be considered a form of art ?
Just stop being an ass, life isn't about it. No matter how old are you, and what did you make, you can still have an urge to learn. On the other hand, there will always be those who will complain and kill joy... :)

Here are few quotes from his blog posts I like:

This lovely showcase current times. :)

> The complexity of the systems involved has almost kept pace. In 1982 my entire development environment was 250 KB (three floppies). Today my Darworms project directory alone is about 100 MB or 400 time larger.

https://www.software-artist.com/software-artist-1982-vs-toda...

Here you can know why?:

> For fun but, alas, probably not for profit. I enjoy coding. I retired in 2017. I want to learn front-end development, JavaScript (ES6), modern frontend development practices, HTML 5 and canvas graphics.

https://www.software-artist.com/darworms/

"an engineer codes what someone else thinks they want" seems a fairly damning indictment of our industry although I think the author meant it tongue-in-cheek.

Lack of ownership of responsibility is still quite a big roadblock for many companies.

All the while I was consulting I never met a client who knew what they needed until you started putting something in front of them.

Some of them had already produced detailed requirements documents but those documents never really represented the reality.

The industry is also full of so many stories of a developer trying to say "Thinking ahead, I don't think you want X because it won't do what you really want which is Y", getting nothing but "Just do X, that's what we researched and PMed into all these requirements documents" to only be followed by complaints of "Why doesn't this do Y? That's what we really need." when presented with "finished" software based on the requirements.
In practice, that depends a bit if you are getting paid for that ownership as a developer. Ownership also implies a lot of work aside from developing.
This is intentionally done at some larger companies. Engineers are resources (owned, not owners) and management is layered in a way that prevents true authority at all but the highest levels.
There must be something wrong with me, but I don't get the Observable (the fact that its name is the same as that of a primitive in functional reactive programming, as in rxjs, with which it has nothing to do, doesn't help either).

Observable seems to be a cross between Jupiter notebooks and plain old javascript, but sufficienly different from either to feel uncannily bizarre. Those imports in the bottom of a notebook! And I am still not sure whether it has access to the whole node_modules ecosystem or not (since it has to run in the browser and doesn't seem to involve a transpiler). I remember looking at some notebooks that involved React and thinking to myself that they felt plain wrong.

That's pretty unfair. Once you spend a little time to understand its concepts, it becomes second nature, and it's really a joy to use.

The fact you can reorder cells in any way you want (and import cells from other notebooks) is the whole point — this way you can build narratives with code, embedding important bits in the story while leaving out fluff like imports at the bottom. Maybe you just haven't seen notebooks that take good advantage of this, but I'll shamelessly plug mine as an example: https://observablehq.com/@mourner/martin-real-time-rtin-terr...

You do have access to nearly the whole NPM ecosystem. Most useful packages either provide a browser build in their package (which gets picked up automatically), or you can use https://bundle.run/ to produce a browser bundle for any Node package.

> the fact that its name is the same as that of a primitive in functional reactive programming, as in rxjs, with which it has nothing to do, doesn't help either

It's based on reactive programming though. Cells observe the entities mentioned in them and update accordingly when they change, which is why you can have imports at the bottom, and you don't have to care about cell evaluation order as with Jupyter Notebooks.

> cross between Jupiter notebooks and plain old javascript

More like a cross between literate programming and Excel, in a browser.

I urge you to give it a shot for a few weeks. It is significantly different from other programming environments, and what at first might feel “uncannily bizarre” pretty quickly starts to like a huge leap forward.

(comment deleted)
The name Observable does have some indirect relation to rxjs, but by way of another historic fork in the reactive programming world of JS: Object.observe [1]. Albeit an obsolete tool today, with the recommendation is to use ES2015+ Proxy instead, Object.observe left other relatives of similar names in the web stack: IntersectionObserver, MutationObserver, others.

The idea behind Observable is that it observes changes to cells (wherever they occur in document order) and reflects those changes everywhere else in the dependency tree, similar to databinding techniques like used in MobX or classic Knockout. (One way to think about Observable is that every cell is a Knockout "computed property".)

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

I find it a bit strange that the post lists both LISP and Python as "truly elegant software system[s]". To me Python is a super-pragmatic language that sacrifices intellectual elegance to allow people (even, but not necessarily) without a CS/Math background to "get stuff done". I also wonder how software "artists" should be different from other artists. For example, in music, there are great teams of artists, like Lennon/McCartney.
As far as I can tell "Elegant" means "I like it, and believe that my aesthetic preferences are a universal law of humanity"
I'd say that elegant is a tight implementation to language fit. When you can express an implementation purely in terms of idiomatic language constructs in an obvious simply understandable way, that is elegant.
Nah, there's a property of elegance that appears similar in mechanical engineering, typography, maths, poetry and a bunch of other places. I don't know exactly what it is, but I think it maps closely to "the minimum number of moving parts necessary to complete the task"
Somewhat similar, I always thought of elegance as the minimum complexity required. However, truly elegant solutions are sometimes counter-intuitive or 'hidden' beneath a few layers of detail, but once understood feel "obvious." That "oh man that's smooth" feeling is often the first step for me to think of something as elegant, and separates 'good solutions' from truly elegant ones.
"I also wonder how software "artists" should be different from other artists. For example, in music, there are great teams of artists, like Lennon/McCartney"

Yes, in music, composers do work together although I wouldn't make a general rule about it. Writers tend to be solitary. They reach out to people when they're researching something for a story. But outlining, thinking through story lines, and the actual typing part are solitary. From interviews with writers, I get the impression that a good editor is indispensable for developing a story though.

Likewise, painters and sculptors in my acquaintance work alone.

> For example, in music, there are great teams of artists, like Lennon/McCartney.

Read this made me think of John Carmack and Michael Abrash, working on the Quake engine. Both are programming artists, but in different ways. When they came together, working on Quake, I'm sure we can all agree that the result was magic.

Not sure where I first read about their work on Quake, but The Graphics Programming Black Book[1] contains some details in the forewords from both. There's also more details in various sections.

[1]: http://www.jagregory.com/abrash-black-book/

> For example, in music, there are great teams of artists, like Lennon/McCartney.

I think there are similarly great teams in software that have multiple hits (Pike, Thompson, and Ritchie being one that comes to mind).

> Python is a super-pragmatic language that sacrifices intellectual elegance to allow people (even, but not necessarily) without a CS/Math background to "get stuff done"

Is this its elegance? That it exposes general purpose programming and an exhaustive library list to the Muggles? So that people without a CS background can do Real Work?

I'm with you on gut reaction, though. Python always struck me as an open-source VBA.

Does anybody know where to sign up to the 'Monday Morning Tickler' as mentioned in the post?
from his blog:

    If you would like to receive a weekly puzzle from me - called the Monday Morning Tickler - all you gotta do is send a request to:

    rj@mical.org (RJ Mical)
Wait till you try out Mathematica!
(comment deleted)
here's a js brute-force for question 1 and 3:

    const cards = [...Array(13).keys()];
    const standardDeck = Array(4).fill().reduce((acc, v) => {
      return acc.concat(cards);
    }, []);
    
    const makeShuffledDeck = () => {
      const deckInst = standardDeck.slice();
      const shuffledDeck = [];
      while (deckInst.length) {
        const removeIdx = Math.floor(Math.random() * deckInst.length);
        shuffledDeck.push(deckInst[removeIdx]);
        deckInst.splice(removeIdx, 1);
      }
      
      return shuffledDeck;
    };
    
    const numDrawsNeeded = () => {
      const counts = Array(13).fill(0);
      const deck = makeShuffledDeck();
      
      while (deck.length) {
        const card = deck.pop()
        if (++counts[card] === 4) {
          return standardDeck.length - deck.length;
        }
      }
      
      throw "Drew all cards, but never found 4 of a kind.";
    };

    // average
    const numTrials = 10000;
    console.log([...Array(numTrials)].map(numDrawsNeeded).reduce((acc, v) => {
      return acc + v;
    }, 0) / numTrials);
    
    /*
    // max
    const numTrials = 10000;
    console.log([...Array(numTrials)].map(numDrawsNeeded).reduce((acc, v) => {
      return Math.max(acc, v);
    }, 0));
    */