James Coglan writes about programming topics such as diff algorithms, monads, promises, Rust, and the Y combinator.
Commenters link its JavaScript monads article repeatedly and recommend the Myers diff series.
A day later I looked at this again and I'm a little closer to understanding.
var listPromise = new Promise();
creates an object that, being a Promise object, has certain methods and internal state, derived from the prototype of Promise.
for (var k in listPromise) promises[k] = listPromise[k];
This confused me because I thought "k" was a stand-in for a numeric index, e.g. that it was doing promises[0] = listPromise[0], promises[1] = listPromise[1], etc. That is not what's going on. Rather, "k" refers to attributes and/or methods that objects of the Promise class have by default. It's copying those onto `promises` — the array `promises` itself, not the individual items `promises[i]`, which keep their existing methods and attributes.
Coming from a Python background, I think I would have found this more obvious if the variable "k" were instead called "method" or "attr". If it was `for (var method in listPromise)` it'd be much clearer what's going on, whereas single-letter variables like i, j, and k are, to me, stand-ins for integers.
It was also confusing, as you said, that the function uses destructive update rather than treating the input as a value. James did mention this ("augmenting the list with promise methods"), but it's still unexpected, especially when the function is preceded by a Haskell type
signature.
The reason I only say I'm closer to understanding, and not quite there yet, is I'm not sure what it means to do `new Promise()` or what is being…
Thank you Eatonphil for writing this.
I agree that I would love to see more of this kind and quality this kind of article of technical subjects.
https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/
https://keleshev.com/abstract-syntax-tree-an-example-in-c/
I don't want to add more work to people who are already working more than everyone else. But when you write software or code that is truly good, I want people to write lots of examples and descriptions of their mental model and how to think of the software.
I'm still trying to understand what the difference between a poller and an awaiter in Rust async.
I use Flask because I find Flask easier to understand than Django. There's even a simple example on the Flask homepage. But Django has a very large tutorial which still doesn't really explain how each component fits together. I don't understand the mental model behind Django but I do with Flask.
For example, I'm still trying to understand C++ coroutines. And I have some code that kind of works and some code someone provided on Stackoverflow I cannot get to work with GCC. There's not large amounts of documentation on C++ coroutines.
I see people post fascinating awesome GitHub projects and have sparse README.md and no screenshots
The code doesnt speak for itself. You can write the perfect code at a company and that code never flourishes because nobody wrote about it. Or you can write the perfect code at home but it doesn't get used.
I would rather…
Oh god. Most of this is hilarious.
"A seasoned C developer with 10 years experience can not instantly morph into an advanced front end web application developer"
True, but they'll be a damn sight quicker at picking it up than anyone else. And they'll write far better code when they're there.
If you're looking for a permanent employee, all development experience is relevant -- there is a huge amount of overlap and retraining just for a different language is no biggie. They'll also have solved (i'd bet) far harder problems than "HOW DO I GET THIS UI WIDGET TO UPDATE WHEN THIS HAPPENS".
If you're looking for someone to hit the ground running from day 1, or work as a contractor, it's different. But you generalise too far here.
"However, they have failed to mention anything else to back it up. I would expect to see some of the following throughout their CV; Design Patterns (MVC, Factories, Singletons, ActiveRecord), Classes, Objects, UML…"
In my CV (highly rated by everyone i've given it to) you won't find a single one of these. Instead, you'll find real descriptions of what i've accomplished, who I worked with (mentoring etc), my methodology (agile, test driven development) and so on.
And UML... holy shit, yeah, no.
Community work? See Ashe Dryden's "The Ethics of Unpaid Labor and the OSS community", http://www.ashedryden.com/blog/the-ethics-of-unpaid-labor-and-the-oss-community, and James Coglan's "Why GitHub is not your CV",…
You are correct, thanks for the clarification. From https://www.gnu.org/software/diffutils/manual/diffutils.html#diff3-Merging
> You can think of this as subtracting older from yours and adding the result to mine, or as merging into mine the changes that would turn older into yours.
The point stands: taking history in account is unconvincing, as it assumes intent where none is explicitly given. In the example, if the top branch had a single commit, AB => ABGAB, then there is no way to reliably infer that A 'intended' [+ABG]AB, vs. AB[+GAB]. Even with the given history, maybe the author of the top branch really intended AB => AB[+GAB], but made an error, corrected in the 2nd commit. The problem is fundamentally ambiguous. We can argue which of the diff3 or anu/pijul heuristics are better. In practice I suspect the difference is not that large.
For completeness, here's a guess of what diff3 does, assuming merging top into bottom, following https://blog.jcoglan.com/2017/05/08/merging-with-diff3.
[bottom] => A [+X] B
[top] => AB [+GAB]
B O T
A A A
+X
B B B
+G
+A
+B
Resulting in A[+X]B[+GAB] without conflicts.
Hi, author here. Glad you've enjoyed the post! To answer your questions:
As leshow pointed out, Rust uses the Result type to propagate errors. The way we'll integrate this in parallel-stream is by adding `try_for_each`, `try_fold`, and `try_map` methods. These methods will short-circuit when an error is returned, and have counterparts in `std` and `async-std` already. One tricky part is to get cancellation right, but we already have a design for that, it's just a matter of implementing it now.
`async-std` comes with support for the `log` crate built-in, which provides information when a new `Task` (lightweight thread) is spawned. `parallel-stream` doesn't perform any logs on top of that, but it probably should! I'll open an issue.
Result sets can be generated through the `collect` method which calls the `FromParallelStream` trait. This can be implemented for various types, but common examples include: `Vec<T>`(generic array), `HashMap`, and `Result<Vec<T>>`. If you're interested in how this exactly works this post by jcoglan goes into incredible detail: https://blog.jcoglan.com/2019/04/22/generic-returns-in-rust
I hope this answers your questions!
Conflating github projects as being "your experience", is not really sensible really. After all, github is only 8 years old at this point, and many real world projects (ie the day job where your experience lies) can't be in github public repositories. (And for many predate the existance of github)
For a selection of good reasons as to why using github like this is a bad metric take a look at:
https://blog.jcoglan.com/2013/11/15/why-github-is-not-your-cv/
(There are lots of good counterpoints to the arguments there in the hackernews discussion of that post here - https://news.ycombinator.com/item?id=6738952 - but personally I still think it's incredibly dangerous to start assuming that you can really measure experience from github.
After all, do you also include repositories forked, but not worked on? If so, it'd be incredibly easy to game this...
As a toy it seems kinda fun/neat, but as a tool... far less so.