HN user

ndh2

578 karma
Posts2
Comments209
View on HN
Maybe Not [video] 8 years ago

I don't understand your example. What does compile-time computed stuff have to do with readInt()?

I get that it might be possible to do that, use a Maybe Maybe T. But it's like an optional<bool> in C++. It can be done, it's just not a good idea. So if you design your system not to allow that in the first place, nothing of value was lost.

If you have specific error cases that you want to communicate, like "what was read from the console didn't parse as an int" as opposed to "the computation didn't find a result", then using the two values "Nothing" and "Just Nothing" as the two distinct values to encode that is not a sound design. Either you have meaning, or you have Nothing. Nothing shouldn't have any meaning attached to it.

Maybe Not [video] 8 years ago

So you're saying that the one Nothing has a different meaning than the other Nothing, and that this is something that anybody would want? Or that we have a Nothing and a Just Nothing? I'm sorry, but I don't get how that would be considered good design in any context. Do you have any example where this would be considered sensible?

First I want to thank you for your honesty. It is so refreshing to read, in this sea of self-promotion of Medium posts that go around here.

You may want to talk to a coach about this. I'm sure you can find someone specialized in finding jobs. You make it sound like you somehow let yourself down, and if that shimmers through in an interview, you won't leave a good impression. I think you need somebody to help you with finding a good way to frame this time in a better light. Not only for your next application, but also for yourself. What started as time off might have turned into involuntary unemployment, with all the negative weight that this brings.

My understanding is that this is only about memory access patterns, and has nothing to do with multithreading. The basic example being matrix multiplications C=A∙B. If the matrices are too big to fit in the L2/L3 cache, you have to think about how to optimize memory access. So instead of having the compiler just generate instructions to read/write memory, you want it to interleave instructions to prefetch memory, ahead of time. But how do you do that? What is the best point in time to prefetch?

Another optimization is locality: The basic algorithm is to loop over i and j, then multiply A's row i with B's column j. You do that with another loop over k to compute the sum over Aᵢₖ∙Bₖⱼ, then store the result in Cᵢⱼ. But what if one row or column is already too big for the cache? Also, once you invested into loading the data into the cache, you want to make the best use of it. You don't want to load it again if you can avoid it. So what you do is you limit the loop ranges for i, j, and k such that the overall memory accessed fits into the cache. But what are the optimal loop sizes?

The answers depends on the CPU architecture (cache sizes) and probably also the memory that you're using.

NOTE 2: Depending on the shape of your head the head band of the earmuffs can make the crown of your head hurt – though this is not limited to earmuffs as may headphones have this undesirable feature.

I tied a piece of memory foam that I salvaged from an old mattress to the head band, using two strips of velcro tape. Looks ridiculous, works really well.

Because Starcraft is 1v1 and LoL is 5v5. Poker AIs also focus on 1v1 as opposed to full ring games. It's easier.

Also because Starcraft has three races, i. e. 9 matchups. But if you pick one race for your AI, you only have three matchups to worry about. LoL on the other hand has about 500 champions (give or take), whose strengths and weaknesses are vastly dependent on the current patch. LoL is less about skill or strategy, and more about picking the champion of the week.

Starcraft works because they have such a small number of matchups that balancing them is possible. Certainly not easy, and players keep figuring out ways to evolve the meta game. Maybe an AI could even find interesting new strategies. But LoL has so many matchups that their balancing team has an absolutely impossible task of trying to catch up. It's so complex that they can't just think about in theory, but they have to look at win-rate statistics, over different skill ranges. At this point it's more a problem of data science. And the number of champions keeps growing, because that's how they make money.

Does the compiler build the initial AST based on a grammar, before the transformations happen? That would mean you can't expand the grammar with user-defined rules. The reason you can "implement for loops in user land" is because they're already part of the grammar, is that correct?

How abstract is that initial AST? Can you use these rewriting transformations to expand the grammar?

Ben, could you go a little into detail on what you had in mind with the term rewriting system? The sin/cos example seems a little underwhelming, since these should be evaluated at compile-time in the first place.

They seem like a variant on C macros, but without the restriction on function syntax. Maybe one could implement Python's with statement in userland, which is very nice.

It also seems to me that you could replace C++ templates, yet you do have generics. How come? What's the difference?

My intuition is that ambiguities are at least possible, so what about precedence, which AST term is evaluated first? I'm thinking of some situation where two subtrees match the rule, but you end up with different results depending on which is transformed first. E. g. if you were to define a cross product rule, and apply it to a × b × c.

What about infinite loops in rule sets? What about recursion?

What about a situation where multiple rules could be applied? Is there any way to debug the transformations? Is that what the `using` scopes are for? If the compiler was to detect ambiguities, that seems pretty expensive, because it would need to match every rule to every subtree, right?

This thing seems very, very powerful, I just find it a bit hard to grasp what you can do with it in practice, and what the limitations are. I would be very interested to hear what you ran into so far.

Hi Bruce. This is a fantastic article, but I needed to read it twice to understand everything. Very dense in information, and sometimes the order of things make it hard to follow. Sometimes you tell us what you did (e. g. modified the virtual memory scanner) before telling us why (what CFG is, how it works), which was confusing.

It turns out that reproducing the slow scanning from the sampling data was quite easy.

This was the first thing that went over my head. Going from one stack trace to reproducing it is quite the jump. Maybe add a sentence "The interesting part of this trace is NtQueryVirtualMemory, which is used to scan process memory." Might be obvious to you, but for me that trace was "just a bunch of Windows stuff" at first.

The author tried to be clever with the title, but failed to take into account how human perception works. The second "review" gets filtered out like that gorilla in the basketball video.

The biggest problems in my opinion are the drive-by downvotes. If you're not willing to fix the problem, you should not have the right to engage.

Downvotes should be tied to some sort of criterion that the asker/answerer can meet, like in a code review. If you get downvoted, you should have the ability to notify the downvoter "alright, I fixed the issue you had with my question/answer", and get the downvote undone. If the downvoter doesn't engage, undo the downvote automatically after a certain period. This process should be completely public, and have a log/history that everyone can see.

Same with flagging as duplicate. As the asker you should have the right to defend yourself against overzealous flagging, and be able to let the mods know why some other question is not actually a duplicate. Flagging as duplicate should be phrased as a question to the asker: Hey, did you see this question? Does this answer your question? And the asker should then be the one to decide whether or not it does.

Was fed up with Quake Live not providing any matchmaking, so I tried to make my own. Of course they didn't have any API, so I needed to scrape their website to get the match results. I sent a lot of requests.

So when they blogged about their web site becoming occasionally very slow, I sheepishly emailed them, and asked if this might be due to my scripts. I assumed that of course they'd have some sort of IP based limiter in place in case I got to greedy. Well, they didn't. They requested that I send them my scripts, which I happily did. They also banned my account, which I thought was quite petty.

They might have unbanned me a couple weeks after that, but I quickly lost interest in Quake Live.

Sounds like a mason working on a sculpture. You need to identify and cut off all the superfluous parts.

Abstraction is generalization of special cases. If you only consider one case, you can't generalize from it. Only when you get two, can you work out the differences and the similarities. It's like forming the intersection of two sets: You remove all the elements that are not part of both.

I wonder how accurate this process is. If you're not careful, you might confuse experience with being narrow-minded. Thinking outside the box requires you to consider exactly what you know you don't know.