Preferences

rspeele
Joined 1,196 karma

  1. Don't watch Big Fish unless you're ready to cry.
  2. "Why would you need to see it? You're the genius who invented the product in question!"

    > https://www.youtube.com/watch?v=9LtT0xZ11wM

  3. This reminds me of playing Ecks vs. Sever on the GBA. A raycasted 2.5d doomlike game based on a crappy movie. It was pretty impressive for a GBA game, and it ran well, never stuttering. It had some pretty cool levels, I remember one where you fight through a hotel using IR night vision. It also had a sequel which added a guided missile launcher and some crazy Robocop ED-209 type enemies. As I recall both had multiplayer deathmatch but good luck finding a friend who also had the game and a link cable.

    One thing I took full advantage of as a kid was that both games had some cheesy behavior with the sniper rifle scope implementation.

    In the first game, while zoomed in with the scope you could use the D-pad to move your view a few clicks left/right/up/down to refine your aim. However, this was not really turning you, it acted more like you were a ghost side-stepping and poking his head up and down. So, you could crouch behind a box, scope in on the box, then D-pad up to look over it and shoot an enemy mob who still couldn't see your character and wouldn't engage you. Or stand just slightly behind a corner, scope in, and D-pad right to shoot around it.

    The last level of the first game involves fighting a boss character who has a powerful weapon and a ton of HP, and is surrounded by his infinitely-respawning goons. There's no way kid me would've beaten it without abusing this trick, which reduces the challenge to avoiding his attacks while fighting enough lower-tier enemies to obtain their precious sniper rifle ammo.

    In the second game, the D-pad moves a crosshair around a fixed viewport rather than shifting the whole viewport around. So the trick doesn't work exactly the same way. If you zoomed in staring at some obstacle right in front of you, you couldn't move the viewport to see around it like you could before.

    However... when you zoomed in, it worked like you were a ghost moving forward in space, instead of narrowing your FOV from your original vantage point. So you'd instead stand about 10 feet back from a corner, zoom in past the edge, and voila: you were able to see more around the corner just as if you'd walked up next to it. Sure enough, you could slide the crosshair over and snipe the enemies now visible in your viewport despite your player character still being safely 10 feet back around the corner.

    Good times. They were still great GBA games even with this exploit, it just made the (scarce) sniper rifle ammo even more valuable to the player.

  4. SQL, C, Javascript: the three kings of "good enough".

    Bad enough that their flaws are evident even to novice practitioners.

    Good enough, entrenched enough, that they will be around for the next 50 years too.

  5. I empathize with you. I had a (very small) side business where I was making custom wood grip panels for handguns. On the one hand, these are firearm parts but on the other hand, they are also inert, harmless pieces of wood that aren't needed for the firearms to function. I used Stripe to accept payments. When I originally signed up for the Stripe account I specifically asked customer support whether this would be OK. The response I got (in 2019) was:

    > Stripe does have some strict rules over the types of businesses we can and cannot support. Firearms accessories is an area that we split into two. Businesses selling firearms and parts required for the functioning of the firearm are restricted from using Stripe. Businesses selling firearms accessories and parts not required for the functioning of the firearm can be fully supported.

    > As your business falls into the second category, I'm pleased to say that you would be able to use Stripe.

    In 2022 my Stripe account was closed. I entered an "appeal" quoting that original response and asking whether their policy had changed, or their assessment of the products I was selling. The response I got did not answer that and simply said "we are unable to accept payments for weapons, ammunition, and related products, as mentioned on our restricted businesses list."

    To be honest I was kind of done with it anyway, it had gotten to that "not fun" point where a hobby becomes a chore. And it wasn't an income stream big enough to make any difference in my quality of life. So I didn't bother appealing further or even seeking an alternate payment provider. But I was still annoyed that they didn't tell me what changed between when I got approval and when I got shut down.

  6. Lazy loading was a mistake in EF. A lot of apps had awful performance due to lazy loading properties in a foreach loop creating N+1 queries to the database. It would be fine in dev with 50-100 rows and a localhost SQL and blow up in prod with 1000s of rows and a separate Azure SQL.

    Also if you relied on lazy loading properties after the DbContext had been disposed (after the using() block) you were out of luck.

    With old EF we would turn off lazy loading to make sure devs always got an exception if they hadn’t used .Include() to bring the related entities back in their initial query. Querying the database should always be explicit not lurking behind property getters.

    Fortunately with EF core MS realized this and it’s off by default. EF with wise use of .Include and no lazy loading is a pretty good ORM!

  7. [footnote] If this part of the explanation is bugging you, consider these related problems:

    Problem 1. There are two opaque, externally identical bags, each containing 2 marbles. One bag contains 2 black marbles. The other bag contains 1 black marble and 1 white marble.

    You choose a bag and draw a marble from it, without looking inside. The marble is black. What should you conclude are the odds that the remaining marble in the chosen bag is black?

    Answer: .elbram kcalb dnoces a dnif ot ylekil sdriht-owt era ew oS .gab etihw-dna-kcalb eht morf si eno ylno dna ,gab kcalb-lla eht morf era elbram kcalb a werd ew hcihw ni soiranecs elbissop eht fo owT

    Problem 2. There are three opaque, externally identical bags. One bag contains 2 black marbles. The other two bags each contain 1 black marble and 1 white marble.

    Again you choose a bag and draw a marble from it, without looking inside. The marble is black. What should you conclude are the odds that the remaining marble in your chosen bag is black?

    Answer: .tnecrep ytfif era elbram kcalb dnoces a gniward fo sddo ruO .gab kcalb-lla eht nesohc gnivah fo sddo ytfif-ytfif ta won era ew oS .sgab etihw-dna-kcalb tnereffid owt eht morf era owt dna ,gab kcalb-lla eht morf era elbram kcalb a werd ew hcihw ni soiranecs elbissop eht fo owT

    You can connect Problem 2 to our random door opening and a goat being revealed, in the Monty Fall (with an F) problem.

  8. Since this bugged me all day, and I suspect you are the kind of person where it bugged you all day, too, here is a better description of the "fall"/"hall" distinction.

    I think we can agree that these are the six possible, equally likely, configurations of the problem starting from me having chosen door 1. G1 here is "goat 1" and G2 is "goat 2". For each possible prize behind my chosen door, there are two possible configurations of the remaining prizes.

        My Door | Door 2 | Door 3
        Car     | G1     | G2
        Car     | G2     | G1
        G1      | Car    | G2
        G1      | G2     | Car
        G2      | Car    | G1
        G2      | G1     | Car
    
    With the "Monty Hall" problem, Monty uses his knowledge to always open a goat door. Thus we see the following revealed options and resulting 2/3s probability of switching succeeding. This is the classic version of the problem.

        My Door | Door 2 | Door 3 | Monty Reveals | Switch Result
        Car     | G1     | G2     | Either        | Lose
        Car     | G2     | G1     | Either        | Lose
        G1      | Car    | G2     | G2            | Win
        G1      | G2     | Car    | G2            | Win
        G2      | Car    | G1     | G1            | Win
        G2      | G1     | Car    | G1            | Win
    
    With "Monty Fall", the first thing that happens is a randomly chosen door, that isn't our own, reveals a goat. This is interesting. In the classic problem we were always going to see a goat next, because those are the rules Monty plays by. But in this case, the fact that we randomly found one wasn't guaranteed.

    Essentially, you are blindfolded and throw a dart at the 2x6 grid of cells under the headers "door 2" and "door 3", and I tell you that the cell you've hit is a goat. What do you know about the row you hit being a switch-or-stay row? Well, half the possible goats you might've hit are in the first 2 scenarios where you should stay, and half the possible goats are in the last 4 scenarios where you should switch. So you're at 50/50. You don't have any new information to switch on.

        My Door | Door 2 | Door 3
        Car     | G1(a)  | G2(b)
        Car     | G2(c)  | G1(d)
        G1      | Car    | G2(e)
        G1      | G2(f)  | Car
        G2      | Car    | G1(g)
        G2      | G1(h)  | Car
    
    You are just as likely to be looking at (a), (b), (c), or (d) (so you should stay) as you are to be looking at (e), (f), (g), or (h) (so you should switch). It is 50/50 in this version of the problem.[footnote]

    This may make it confusing going back to the original. I seem to have shown that both ways make sense but still, how is it different? Imagine it like Monty is doing a random dice roll for which door to open, and he simply juices the outcome by correcting it to the goat door when a car door is selected, since he can't reveal a car and spoil the game. Now we have these equally possible scenarios (a) through (l) for his fair dice roll...

        My Door | Door 2 | Door 3
        Car     | G1(a)  | G2(b)
        Car     | G2(c)  | G1(d)
        G1      | Car(e) | G2(f)
        G1      | G2(g)  | Car(h)
        G2      | Car(i) | G1(j)
        G2      | G1(k)  | Car(l)
    
    Which he corrects, avoiding cars, to:

        My Door | Door 2 | Door 3
        Car     | G1(a)  | G2(b)
        Car     | G2(c)  | G1(d)
        G1      | Car    | G2(f,e)
        G1      | G2(g,h)| Car
        G2      | Car    | G1(i,j)
        G2      | G1(k,l)| Car
    
    Now we are back to the original game scenario where we see a goat no matter what. And we can see that 8 of the possible ways we might have arrived at seeing this goat come from "switch" rows while 4 come from "stay" rows.
  9. They are two different problems. Map out all the scenarios exhaustively and you'll find the difference.

    In both cases we were originally 1/3 chance of being right. That is not in dispute.

    In the original (fully defined) "Monty Hall", Monty was going to show us a goat no matter what. It's part of the rules, he has to show a goat. So the fact that we see a goat behind the revealed door is no surprise, and no new information. But which of the two unchosen doors was the goat, is valuable information because in 2/3s of the scenarios Monty's hand was tied and he HAD to show that door to avoid revealing the remaining car.

    In the "Monty Fall" problem, the fact that we see a goat at all is interesting information. This becomes more likely when we picked the car in the first place, because if we had initially picked the car, and a random other door is opened, it's 100% going to be a goat, whereas if we had picked the goat in the first place, we are only 50% likely to see a goat when a random other door is opened. Let's call the goats Alice and Bob to illustrate this point. We know we DID see a goat, but we don't know which of these equally probable scenarios led to that:

    1. We picked the car and saw Alice

    2. We picked the car and saw Bob

    3. We picked Alice and saw Bob

    4. We picked Bob and saw Alice

    Notice how "we picked the car" originally had 1/3 odds but represents half the scenarios that remain possible, because there are two ways to see a goat with that start, while only one way to see a goat with the others.

    This kind of brings the problem back around to similar territory as Bertrand's Box[0] where the fact that you drew a gold coin is already hinting to you that you're more likely on the "both gold" box than on the "half gold" box.

    [0]https://en.wikipedia.org/wiki/Bertrand%27s_box_paradox

  10. > It doesn't make a difference what causes Monty to reveal a goat.

    Oh, but it does! See the "Monty Fall" version of the problem, in which Monty accidentally trips and opens a door, which just happens to reveal a goat. In this variant there is no advantage gained by switching, because no more information was revealed about the remaining unopened door.

    The information gain only happens in the original game because we know that Monty was forced to avoid the winning door in the (66% likely) case where we didn't already pick it.

  11. I am curious how you feel about the "Monty Fall"/"Monty Crawl" problems linked elsewhere in the thread.[0]

    For my part I am somewhat sympathetic to jncfhnb's point. The exact phrasing that Vos Savant was asked did not specify the rules that the host was required to open a door, nor that it always must be a goat door. It simply says that the host has knowledge of what's behind the doors, and in this particular iteration of the game, he showed you a goat and asked you about switching.

    That does not exclude a scenario where the host is a manipulative fellow, who chose to show you the goat only because he knows you are about to win, trying to convince you to lose. A contestant on the real show would surely worry about this possibility.

    Of course, the people who wrote to disagree with Vos Savant almost never said "the problem is not fully stated", they said "it's 50/50 you fool", which isn't right. Additionally, since it wouldn't be a math problem at all if we let the host have agency, it is reasonable to assume the unspoken rule that he does not, leading to Marilyn's correct 2/3rds answer.

    [0]https://web.archive.org/web/20230706235720/https://probabili...

  12. One way to think about is, suppose you switch -- why not switch back?

    In the random-open case, you really know nothing new about either of the closed doors. If you can talk yourself into switching, you could make an equally good argument for switching back.

    In the Monty-knows-and-always-shows-goat case, you have gained information about one of the closed doors. You haven't gained any information about your initial pick door. But the other remaining door, you know there's a 2/3rds chance that Monty was forced to avoid it so as not to reveal the car. Only in the 1/3rd case where you were already on the car does Monty have freedom to open either door willy nilly.

  13. That's especially tempting since we're used to probability problems often being set up where considering previous state is the sucker's answer. E.g. a fair coin has landed on heads three times in a row, what are the odds of it being tails on the next throw?
  14. The explanation that worked for me was:

    Suppose after you make your initial choice, instead of opening a door, Monty simply asks if you'd like to switch to BOTH the other two doors, such that you win if the prize is behind EITHER of them.

    That switch is intuitively a great deal, giving you 2/3 odds. The only way you can lose is in the 1/3rd case where you already picked a winner. The original scenario is equivalent to this, since by revealing a goat Monty is allowing you to pick "the best of" the two doors.

    ---

    Often people who don't like this problem complain that actually Monty, with his knowledge of the winning door, may be trying to trick you into losing. Maybe he offers this trade conditionally based on whether you've already selected a winner. Of course, this wouldn't support the most common intuitive answer of "it's 50/50", either, making this a bad excuse. If we accept this behavior from Monty -- not stated in the problem -- it becomes a very uninteresting problem based on whether we are dealing with Evil Monty who only offers the trade when it's a bad one (stay wins 100% of the time), Friendly Monty who only offers the trade when it's a good one (switch wins 100% of the time), or somewhere in the middle. It has no analytical answer. So for this to be a solvable problem at all we must assume we are dealing with Fair Monty who offers the trade all the time, or at least, offers it at random times not based on the contestant's initial pick.

  15. > The global bitcoin system is well within rearch of a hostile state 51%'ing it

    > I’ll believe it when I see it. They honestly have a better chance outlawing it and imprisoning anyone who’s ever used it.

    First of all I don't think any state is currently motivated to do this. However, if I were a state agency trying to attack Bitcoin, I would start by creating my own mining pool, which of course would purport to be privately run. I would be the most efficient mining pool in the business, offering miners a slightly better cut than other mining pools since while most pool operators are trying to extract a low-margin profit, I'm willing to break even or, if necessary, run at a small loss. It would be ideally to gradually create several sock-puppet pools that appear to be in competition with one another, while in fact I control all of them.

    Even with competitive payouts, it may take several years to build up my pools reputation and gain a significant share of miners. And when I start having my pools mine blocks that I'm not actually submitting to the chain (to support my double spend), pretty soon miners will notice and switch. But I only need a couple hours to cause chaos, and I may benefit from miners confusedly switching to other pools that are also under my control. If I look at the regions where I have the most miners and time to the attack to occur overnight in those areas, I may succeed. And unlike trying to 51% the network myself by throwing hardware at the problem, I won't be left with worthless SHA256 hashing machines at the end of the attempt, nor will I have to pay for power. And I don't have to outmine the entire network -- I've enlisted half of it to be on my side. The only cost is the minimal pool operating expenses (not mining, just issuing work to miners, checking their work and arranging payouts), spread over how ever many years it takes me to gain dominance.

  16. > Also, when talking about extra service payment networks like Visa offering, like anti fraud, gotta remember that at least part of problems this service solving is caused by the design of the network itself. And while it is not obviously energy hungry service, it is part of what everyone is paying 2-3% in credit card processing fees.

    The design of credit cards does suck for fraud. I go to a website to buy a product, I put in my card number, exp date, CVV, and it turns out that site was actually compromised and some attacker got my card info. Now I have to cancel it and get a new card. It would be way better if what I entered on that vendor's site was a one-time authorization code, not the full information with which the attacker can spend from my card at other places.

    Crypto is better in this regard since I never transmit my secret information to the vendor! But crypto is also worse, in that, if I do send a transaction to the wrong place (for example, because the vendor's website was compromised and told me the attacker's address to send to), I'm screwed. And if my electronic device is compromised and my private key stolen I'm really screwed.

    Ultimately even though crypto has a technically better design, since it also has no support department and no dispute resolution I'm at higher risk. I've never lost money from a stolen credit card. You're right that I pay for that in the 2-3% processing fees... but it's not like Bitcoin is feeless, either.

  17. It's meaningful since Bitcoin is the most popular, most energy-consuming crypto and it has this limitation, with no plans of changing.

    "Well, it's supposed to suck like that" doesn't change that Bitcoin is consuming tremendous amounts of energy to serve very, very few customers.

  18. You can roll back transactions for whatever duration of time you were able to outspend the network. Critically, that can include your own transactions.

    You mine quietly, outpacing the regular network, creating your own longer chain. Perhaps you do this for an hour, several hours, or a day. The only transactions on this chain are those in which you send your own coins to yourself -- maybe plus some random transactions from the mempool you throw in to help cover your own tracks. Meanwhile you spend those same coins (UTXOs) on the "honest" chain.

    Once you are satisfied, you publish your longer chain. By the rules of the network the longest chain is the true one. Honest miners immediately begin building their blocks on top of your dishonest version of events. Since you are now working together with them, blocks are produced quickly. The honest chain dies.

    Chaos would ensue.

    Anybody who received coins on the dead chain can try to republish the transaction to the mempool and hope it gets mined again, so they get their money again. But if the sender is fast, they might realize they have a double-spend opportunity here, and submit a higher-fee transaction in which they sent those coins to themselves. It's a race. Of course, for your own UTXOs that were already spent in the dishonest chain, the race has already been won. Those double spends are successful.

  19. Your first point kind of makes it impossible to call anything a waste, right? Everything we do in society is paid for by somebody so it must all be worthwhile.

    For the second point, are you talking about Layer 2 solutions that track cryptocurrency in a centralized database, like an exchange, where most transactions happen? Basically just traditional banking but with crypto as the unit of account. Or are you talking about decentralized layer 2 solutions like Lightning Network? I don't think Lightning Network can scale to match what the banking sector does, even if you ignore all the services banks provide other than facilitating transactions. For example you could not pay the US workforce with Lightning Network because it would take several months worth of of blocks just to open a channel to each person, and quickly those channels would run out of inbound capacity and you'd need to open more on top of that, so the Layer 1 capacity still limits the ability to use LN at that scale.

  20. Another reason to keep the stakes small is to avoid problems like the assassination market[0]. I'd rather have podunk, inaccurate prediction markets like PredictIt than one which amounts to putting massive bounties on public figures. Or incentivizing public figures to do their job badly like make a surprise change in their vote on an important bill, just to win a longshot bet.

    PredictIt even used to have markets on, like, which SCOTUS justice would be the next to leave. People got paid when RBG died. That literally would've been this, if it weren't for the fact that the small investment limit kept the returns low. Realistically I don't think anybody was going to be committing assassinations just to make a thousand bucks.

    The same things that keep prediction markets inaccurate keep them from causing bigger problems.

    [0]https://en.wikipedia.org/wiki/Assassination_market

  21. I really enjoyed the market "Will either Biden or Trump concede within 2 weeks of the election?"

    As I recall "no concession" was priced at like 40c, at the same time that Biden winning the election was priced at something like 55c-60c. I was pretty sure Trump was not going to concede, period, so this was just a substantially cheaper version of betting "Biden wins". And as it turned out, it also had the advantage that it closed much, much sooner than the actual election market -- thus freeing up my funds to go into those other markets that hung at 85c or so till December.

  22. Copying my comment from the dead zzzeek post:

    Long shot bets are almost always overpriced on PredictIt.

    PredictIt specifically encourages these long shots to be over weighted thanks to their $850 risk limit in any given market. If one long-shot bettor places a max buy order for YES at 10c per share, the order book has 8500 buys at that price point. I can come along, see that what they're betting on is absolutely nuts and max out NO... but at 90c per share I can only fill 944 of those orders before I'm maxed out at my $850 risk limit. I might be supremely confident and WANT to bet $7,650 on this but I simply am not allowed to. So it takes eight more people like me to come along and plunk that money down before we're moving the needle on the order book.

    In the 2020 election they somewhat mitigated this by making a dozen markets that were all basically the same question: Is Trump going to succeed at overturning this? They had markets for each state, plus combo markets they added like "Will Trump win any of AZ, GA, PA", plus the electoral college markets, the margin-of-victory markets, etc. But it was still way more effort to go in with a big chunk of change and manage spreading your bets out across all those different markets to max your $850 caps as efficiently as possible.

    This is in addition to the other factors, that it is simply more FUN for people to gamble on long odds because it's like buying lottery tickets (who wouldn't want a 10:1 return?). And that, when you factor in fees, opportunity cost (I could have this money in the S&P 500), and counterparty risk (how long will my money be tied up if PredictIt gets shut down), it's really not very attractive to put money in shares in the $0.90-0.99 range unless A. you already have the cash sitting in your PredictIt balance and B. the end date of the market is known and approaching rapidly.

  23. You are absolutely correct. It doesn't make sense to buy that contract unless you already have the money in your PredictIt balance, you want to keep it there as "dry powder", and you really can't think of a better market to park it in (unlikely). Time value of money being what it is... contracts like that have a pretty dead market. There is no reason to hold either the longshot YES that's realistically less than 1% likely OR the tie-up-your-dollar NO.

    Of course if you already have a balance on PI, you just won in another market, and say it's Nov 6th and you've got nothing better to do... you might as well buy 99c shares because the $1 payout could be in as little as a couple days and what else are you doing with the money? So the high priced shares DO eventually sell but basically anything that's months away dies out in trading volume before it reaches the 99c mark.

    Personally if I still had money sitting in PI I'd probably park my dry powder in NO on "Joe Biden resign in his first term", which has been as high as 10c this month, but even assuming I could get 90c NO shares that is not worth me moving money from my bank back into PI just to skim those pennies.

  24. As somebody who made a decent chunk of change (enough to get a 1099 from PredictIt in 2020 and 2021) off the situation... long shot bets are almost always overpriced on PredictIt.

    PredictIt specifically encourages these long shots to be over weighted thanks to their $850 risk limit in any given market. If one long-shot bettor places a max buy order for YES at 10c per share, the order book has 8500 buys at that price point. I can come along, see that what they're betting on is absolutely nuts and max out NO... but at 90c per share I can only fill 944 of those orders before I'm maxed out at my $850 risk limit. I might be supremely confident and WANT to bet $7,650 on this but I simply am not allowed to. So it takes eight more people like me to come along and plunk that money down before we're moving the needle on the order book.

    In the 2020 election they somewhat mitigated this by making a dozen markets that were all basically the same question: Is Trump going to succeed at overturning this? They had markets for each state, plus combo markets they added like "Will Trump win any of AZ, GA, PA", plus the electoral college markets, the margin-of-victory markets, etc. But it was still way more effort to go in with a big chunk of change and manage spreading your bets out across all those different markets to max your $850 caps as efficiently as possible.

    This is in addition to the other factors, that it is simply more FUN for people to gamble on long odds because it's like buying lottery tickets (who wouldn't want a 10:1 return?). And that, when you factor in fees, opportunity cost (I could have this money in the S&P 500), and counterparty risk (how long will my money be tied up if PredictIt gets shut down), it's really not very attractive to put money in shares in the $0.90-0.99 range unless A. you already have the cash sitting in your PredictIt balance and B. the end date of the market is known and approaching rapidly.

  25. I interpreted GP's comment less as "drum sucks compared to disc" and more as "well, it's got brakes" being the only listed safety feature, on a car that is sold in some markets without even airbags.

    It's kind of like the old "front fell off" sketch:

    > [Senator Collins:] No, rubber’s out .. Um, They’ve got to have a steering wheel. There’s a minimum crew requirement.”

    > [Interviewer:] What’s the minimum crew?

    > [Senator Collins:] Oh, one, I suppose.

    Or the Simpsons gag about the Carnivale knockoff TV set:

    > It features a two pronged wall plug, pre-molded hand grip wells, durable outer casing to prevent fall-apart.

  26. Yeah, Spotify's shuffle sucks. I have the same experience with it picking "favorite" songs and choosing to replay them many times while others in the list go unplayed forever. Maybe it believes those songs are my favorites because of how many times they've been played, in a form of circular reasoning.

    I think I would be happy with a weighted random selection. Take 2 (or K) random numbers in range [0.0,1.0] and multiply them together to get X. X will favor the low end of the [0.0,1.0] range. Now sort the playlist from least recently played to most recently played. Next song = playlist[round(X * (playlist.Length - 1))].

    Something like that. Note that "least recently played" would be a persisted attribute, not something that gets discarded in each shuffle "session". And not even local to this playlist -- just literally what is the last DateTime at which I played that song from my Spotify. It's possible to get a repeat but rare. When I hear a song I enjoy I know I could hear it again soon -- I'm not going to have to work through my entire library to hear it again -- but the odds favor hearing older stuff.

    You could also remove the last N songs from the candidate list completely if you wanted to guarantee never repeating super recent tracks. Increasing the K factor would increase the favoritism of long-unplayed songs.

  27. I think there's probably a different optimum shuffle experience for real playlists like you describe vs. "all my liked songs" where the latter is often what I'd put on in the car by default.
  28. > most bitcoin blocks this year have transaction fees greater than the block reward

    What?

    [1]https://bitinfocharts.com/comparison/bitcoin-fee_to_reward.h...

  29. F# does have [<Struct>] DUs now but I believe because of the runtime limitations you mention, it ends up as sizeof(fields of case 1 + fields of case 2 + ...). They might reuse fields of the same type so if your DU cases can carry an A of string or B of string*int, the underlying struct is sizeof(string+int) not sizeof(string+string+int), but I'm not sure.

    Regardless F#'s biggest downfall is that to use it you basically have to be a C# expert already and learn the F# syntax and additional features on top of that. Otherwise it's a baffling standalone language because you're left wondering why there are two ways to do almost everything -- Task vs Async, struct ("tup", "les") vs ("regular", "tuples"), two kinds of extension methods for classes, Nullable<T> vs Option<T>, it goes on and on.

  30. I haven't found the async call stack in VS to be bad unless I'm doing stuff like firing off "async void" calls or firing off "Task.Run"s. It sure does make the stack trace on Exception.ToString() ugly but the call stack in the debugger is ordinarily quite navigable.

    Now what can be annoying is when your problem is in some ASP.NET core middleware and you can't find it debugging your controller methods.

    Also I don't love the "fluent API" configuration style they've adopted. I always have to Google what my chain of services.AddMvc(options => ...) and app.UseMvc(...) is supposed to look like. These APIs seem like they should be very discoverable through intellisense but since you can't "see" extension methods until you open their namespace, sometimes you have to already know exactly what you're looking for to find it. But then again, the old way of configuring a lot of those same things was via web.config and even less discoverable, so that's kind of a wash.

    Edit: one other thing about the modern style of C# library design is the total rejection of statics in favor of dependency injection. Which I think is done with good intentions but somewhat overzealous. We no longer use HttpContext.Current, we have an IHttpContextAccessor that needs to be injected. We no longer use ConfigurationManager.AppSettings["foo"] we have an IConfiguration which again, needs to be injected. I get why this was done but I feel it trades convenience in the 99%-of-the-time case where those things really are quite reasonable to treat as static, for elegance in the 1% of cases where they are not.

This user hasn’t submitted anything.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal