Live data from Hacker News

A final proposal for Rust await syntax

boats.gitlab.io

261–265 of 265 posts

Re: A final proposal for Rust await syntax

#261

Earlier quoted context omitted.

Extensibility and composability is a better abstraction. Say that our modern day programmer is comfortable with + × > In Python, that is many standalone disconnected patterns which do not compose, In APL the "and more" is because composability means there are lots of ways of putting these operations together. values.prod() is what you have to do without composability, you can't re-use the builtin multiply without mak…

That's still just pixels[brightness >50] with numpy. Which brings me back to what I said before: if I want a powerful array manipulation dsl, I still have it, but I'm not limited by it. To your statement "you can't use the built-in multiply without adding an overload": yes, but that's because apl forces everything to be an array. If I want to work with something with non-array syntax (as an example, where addition us…

> Note also that you're being unfair to Python. List comprehensions, array index notation, and numpy methods cover pretty much everything you've mentioned in apl.

All of that to cover ~ten symbols. Is it unfair to Python to point out that this is a huge difference in complexity that someone needs to learn to be able to do those things from scratch?

> Which brings me back to what I said before: if I want a powerful array manipulation dsl, I still have it, but I'm not limited by it.

Which is fine. It's just that the few operations of array manipulation DSL go so much farther than I expected they would. I do know that APL is not going to be the language to implement WireShark or Halo vNext.

The big catch in paragraph two is "if my objects support that"; yes you would have to do something more complex in APL. But not /much/ more complex. In Python you'd need to understand classes and magic methods and overloading before you could write that overloaded addition - and understand CPython internals, C and NumPy to add it to NumPy objects, I imagine. I doubt you can do that all in APL, but then again if I'm correctly reading what l2 norm addition is, Pythagorean square-root-of-sum-of-squares including complex numbers, it's not a lot of code to write that anyway:

    values ← 4J3 ¯2J8 10 20
    abs ← |values
    squared ← abs * 2
    sum ← +/squared
    sqrt ← squared * 0.5
or without the temporary variables which don't add much clarity:

    ( +/ (|values) * 2 ) * 0.5
⍨ is a cool operator which lets you swap arguments around, so instead of having to read from inside nested parens out, you can remove parens and read serial code left/right instead:

    0.5 *⍨ +/ 2*⍨ |values
Name that with a lambda/anonymous function/dfn:

    l2NormAdd ← {0.5 *⍨ +/ 2*⍨ | ⍵}
    l2NormAdd values
Which .. isn't so bad that you'd wish for overloading, if the cost of writing the overloading was so much higher, is it?

> That's still just pixels[brightness >50] with numpy.

That is cool, I didn't know you could do it. But it is completely separate from the normal Python list comprehension style, apparently a different use of > (?), won't compose with the normal Python sort(key=) to sort the pixels by brightness. At what point does learning one-off skills for every task start to get annoying? (From my personal experience, it never does get annoying, and that seems weird to me now).

----

But then a tiny amount more APL and here's a depth first recursive tree traversal with accumulator function, projecting a tree structure onto a nested array:

    ⊃∇⍨/⌽(⊂⍺ ⍺⍺ ⍵),⍺ ⍵⍵ ⍵
     │└┬┘  └─┬──┘  └─┬──┘
     │ │     │       └──── (possibly empty) vector of sub-trees.
     │ │     └──────────── new value of accumulator.
     │ └────────────────── left-to-right reduction →foldl←
     └──────────────────── recursive call on (⍺⍺ trav ⍵⍵).

 - https://dfns.dyalog.com/n_trav.htm
I sure could bash out a depth-first tree traversal in Python, with dictionaries or a dedicated tree-node class, and it would take me way less time than understanding this will take me. Yes this may be 20 characters, but it seems a shame to make "few characters" the main focus of why this is interesting. Each of these primitives in the line is almost trivial to learn on its own, none of them are complex magic not even omega-omega. But an expert combining them together carefully makes them do something way more than the sum of their parts, and way more than the shortness suggests they will do. (Here's John Scholes, founder of Dyalog APL, building on this to solve the N-Queens problem: https://www.youtube.com/watch?v=DsZdfnlh_d0 the commonly linked Conway's Game of Life in APL is more approachable, but this is more amazing because of what it's doing to treat arrays as trees, but way harder to follow and more "magic")

Re: A final proposal for Rust await syntax

#262
post #126
post #55

Earlier quoted context omitted.

> Rust is already a weird language to come to from the likes of python, Java, or Javascript Every time I see a statement like this, I remember a (paraphrased) statement from Rich Hickey: "[musical] instruments are made for people who can play them!". I think unless you are specifically designing a beginner language (like Scratch), you should not take into consideration "ease of use" or "familiarity" arguments.

That statement from Rich Hickey makes no sense at all, because we aren't born knowing how to play instruments. And if your brand new instrument is weird, then not many people are going to bother learning how to play it. Thinking that "ease of use" should not be considered because [favourite reasons] is probably the number one misunderstanding software engineers have about humans. :) Please read Norman's "The design o…

> And if your brand new instrument is weird, then not many people are going to bother learning how to play it.

Which musical instruments are _not_ weird?

Re: A final proposal for Rust await syntax

#263

Earlier quoted context omitted.

That's still just pixels[brightness >50] with numpy. Which brings me back to what I said before: if I want a powerful array manipulation dsl, I still have it, but I'm not limited by it. To your statement "you can't use the built-in multiply without adding an overload": yes, but that's because apl forces everything to be an array. If I want to work with something with non-array syntax (as an example, where addition us…

> Note also that you're being unfair to Python. List comprehensions, array index notation, and numpy methods cover pretty much everything you've mentioned in apl. All of that to cover ~ten symbols. Is it unfair to Python to point out that this is a huge difference in complexity that someone needs to learn to be able to do those things from scratch? > Which brings me back to what I said before: if I want a powerful ar…

> I sure could bash out a depth-first tree traversal in Python, with dictionaries or a dedicated tree-node class, and it would take me way less time than understanding this will take me.

That's my point. APL is interesting, but its enforced structure doesn't fit things intuitively (perhaps there's an implied "for most people" here). Yes, omega combinators or whatever it is that's doing is neat and perhaps pedagogically useful. But

> That is cool, I didn't know you could do it. But it is completely separate from the normal Python list comprehension style

That's because you're not using list comprehensions, you're using ndarrays, which do poweful things to python's already powerful slice notation, and as a result get all of the nice broadcasting things that you get in APL. Its why a + b and a * b just do what you expect in numpy-land.

Slice notation in python is already powerful: a[:], a[5:], a[:5], a[::2], and a[::-1] are things I'd expect someone relatively new to understand intuitively (those are copy, head(5), tail(5), every_other, and reversed).

Adding the ability to customize it: `a[:,:,::-1,:]` for example inverts the 3rd axis of a 4d array, similarly you can pull out a subarray, strided subarray, etc. very declaratively. And numpy further extends that by allowing the argument to be a mask (which is what I showed you in the last comment), so a array[boolean_mask] does the kind of thing you'd expect.

>At what point does learning one-off skills for every task start to get annoying?

When the one-off skills are better abstractions for the task than the "consistent" thing, never, as it seems you're realizing.

Re: A final proposal for Rust await syntax

#264
post #65

Earlier quoted context omitted.

> Rust is already a weird language to come to from the likes of python, Java, or Javascript I think that's a great reason to evaluate new syntax/features on how they will be used, as opposed to how they will attract (or not) new users. New users are already going to be expecting things to be different, and so making this one thing more familiar probably won't make much difference. On the other hand, code lives for a…

New users expect things to be a bit different by assuming there are good reasons for change of convention. EDIT: this might very well be the case here though, especially future extension for similar operators and chain-ability.

Right, which is why I mentioned that focusing on readability/maintainability is the right move in this case. I think we're in agreement.

Re: A final proposal for Rust await syntax

#265

Here's a question that may sound a little naive but I'm behind on where the Rust async stuff is shaping up and I don't know what to search for to answer it. You can of course already do async things in Rust the same way you do in C: by passing around function pointers and either passing around a handle to the event loop or, more commonly, using a single global handle. But you theoretically could run multiple event lo…

You do not lose access to it. A short version of the answer is that at its core, you create a chain of futures, and then place them on an executor. The executor is responsible for executing them. Async is sugar for creating a chain of futures. Doing that stuff is a property of the executor. Completely different axis. (And tokio today has a multi-threaded, work-stealing executor, for example.)

I see, so the "root" Future in the chain is bound to an executor and that's where the "which event loop" part is specified
Post reply on HN