HNHacker News
TopNewBestAskShowJobs

linknoid

55 karma · joined July 20, 2020

submissionscomments
linknoid··on Ten influential programming languages (2020)
I've done some porting of VB6 into C# with WinForms. It's actually a pretty direct mapping. I wrote a converter, and then spend a few minutes cleaning up the converted code per form. Took me a couple weeks to convert a 500KB program, which mostly involved going through and converting VB6-isms that failed to auto-convert into C#. I can't imagine trying to translate something like that into such a different language and UI environment as Python. Unfortunate that they'd reject such a thing just because C# came from Microsoft.
linknoid··on The world map that reboots your brain
https://earth.google.com/
linknoid··on DRY is an over-rated programming principle?
If the statement is "if (!isGreen)", it's much clearer to say "if is not green" than it is to say "if is green is false". Putting == true or == false makes you convert a clear statement "is green" into "true" or "false" instead of just being a natural English statement. It would be like saying in conversation, "I want to go to the store is false" instead of "I don't want to go to the store".
linknoid··on C# 10 new feature CallerArgumentExpression
A lot of the improvements are just logically extending the language to remove arbitrary restrictions. That's what most of C# 10 and 9 appear to be. So most of the features you wouldn't go out of your way to use, but instead stuff that used to be impossible is now possible. I can't say that I've ever wanted a generic attribute, or a constant interpolated string, but if I did want them, I'd be surprised when they didn't work. C# 8 was the last major new language features.
linknoid··on Ask HN: Where to post solutions to problems to help future people Googling?
StackOverflow actually has a checkbox when you ask a question that says: "Answer your own question – share your knowledge, Q&A-style" which lets you post your answer at the same time as your question.
linknoid··on Has a remote Amazonian tribe upended our understanding of language? (2007)
A lot of things a human can do can be found in other species, but I think the ability to read and write arbitrarily complex ideas really does set us apart, and caused a phase transition. It allows us to transmit ideas across time and space that would otherwise be lost. It allows the accumulation of knowledge that no brain is large enough to hold. Outsourcing our memories to persistent storage. Someone can write down an idea, it can be forgotten for hundreds of years, and then rediscovered and applied. It can allow one person to design something, and communicate that design to thousands of other people. Take that away, and local achievements in knowledge remain local until they are forgotten because other knowledge has takes precedent.

A beaver might instinctively know how to build a dam because it's built into its DNA, but a human can read the writings of past dam builders, learn the abstract theory of dam building, come up with their own improvements, debate those changes with other people interested in dam building, communicate their design to dam builders, and publish their work to become a permanent part of dam building literature. For a beaver to change how it builds dams, it would require a change in their DNA to pass on to future generations.

linknoid··on Java Is Underhyped
And then they decided to end that line of succession. .NET Framework 4.8 is the last version of the framework. I've started experimenting with converting code to .NET 5, but it's a rather large jump compared to any previous upgrade. Going from 2.0 to 4.0 had a few minor hiccups, but going to .NET 5 is basically a rewrite of the framework and runtime, and I'm not sure how old and new assemblies will co-exist. It feels like a fragmenting of the ecosystem, where a bunch of code will be stuck on .NET 4 forever, and other code will move to the .NET 5 and later.

I'm almost expecting a few years down the road, Microsoft will go back on 4.8 being end-of-the-line for .NET 4 and start releasing new minor versions of it because of all the customer code that can't be ported to .NET 5. Or maybe it will just end up like VB6. Stuff written in it still works, and will continue to work, but it's considered a dead language.

linknoid··on Dvorak vs Colemak (2010-2020)
Dvorak plays pretty nice with default vi keybindings, for the most part. Both y (yank) and p (put) are on the left hand, as well as x (delete characters), . (repeat last), u (undo), q (record macro), @ (execute macro) and " (choose register). And even though d is technically on the right hand, it's still in easy stretch range of the left. You can do a lot quite quickly with those keys and a mouse. So I don't miss ctrl-c/v too much when I have vi keys available. Whereas the right hand tends to be a lot of movement keys, which are more important when not using a mouse: h (move left) l (move right), b (previous word), f (jump to character), t (jump before character), n (next search result), g (goto top/bottom/line number/etc).

The worst thing I've experienced with Dvorak is typing "ls<enter>" repeatedly. It's really painful on the pinky. Putting L on the right pinky stretch was a really bad decision.

One advantage Dvorak has over Colemak is that it's included with every OS and easy to switch to, whereas Colemak often requires a download and an install to use. And some games include Dvorak keybindings, but I haven't seen one with Colemak keybindings yet.

I learned Dvorak back in college, and got fast by playing muds. Type fast, or you're dead. Took a few months to get up to speed.

linknoid··on Dvorak vs Colemak (2010-2020)
So did you switch from Dvorak to Colemak? I just did a typing test on code-like things, and my typing speed is much slower, around 45 wpm, although that's normally accelerated by an IDE. I started learning Colemak for about a day a few years ago, and then decided that it wouldn't actually benefit me over Dvorak, especially because vi keybindings are quite important. Is the big improvement that it leaves {} in their original place instead of the farther reach?
linknoid··on Dvorak vs Colemak (2010-2020)
As a full time developer, I'm sure my typing speed directly affects my productivity (probably between 80-100 wpm in Dvorak). There are a lot of times I'm typing at full speed for hours, aided by code auto-completion and vim macros, and since the program already exists in my head, the limiting factor is how fast I can type it out. Other times not so much, I'm sitting there reading code, or debugging line by line, or whatever. But when I'm ready to code, my typing speed is the single biggest factor of how fast I can get it out.
linknoid··on uBlock Origin works best on Firefox
I think I figured out what it is. I turned off web assembly in Firefox to reduce my attack surface for general web browsing (I wish I could turn off Javascript completely, but that doesn't really work these days, so NoScript is as close as I can come). I think Netflix must be the only site I actually care about that won't work without WASM, so I'm fine relegating it to a separate browser with a higher exposed surface that I never use for untrusted sites.
linknoid··on uBlock Origin works best on Firefox
Nope, I get Error Code F7701-1003. I have Wildvine enabled, and I tried completely disabling NoScript. It's easier to just use Chrome for that one thing than have to troubleshoot the problem.
linknoid··on uBlock Origin works best on Firefox
I cleared my cookies in Firefox for everything Costco related, and it works now. Thanks for pointing out that it works. No clue how it got in that state.
linknoid··on uBlock Origin works best on Firefox
The only two places I use Chrome are Netflix and Costco. Costco's behavior is just plain weird:

"Access Denied You don't have permission to access "http://www.costco.com/" on this server."

Is this from running NoScript? Or does it affect all Firefox users? (Also the URL is https://, not http://, so the error message doesn't match the URL).

linknoid··on A CO2 capture solvent with exceptionally low total costs of capture
Maybe you can help enlighten me on this. I've been struggling to understand the basics thermodynamics of carbon capture for quite some time.

So we have a hydro-carbon, we mix it with oxygen, and the oxygen combines with the hydrogen and the carbon, and releases heat as a byproduct. The heat energy increases the pressure of the newly created CO2. This higher pressure is placed on one side of a turbine or a piston, and we extract useful work by moving it from a high density state to a low density state, causing it to cool in the process.

Now it seems like if you want to re-concentrate that CO2, it should take at least as much work to compress it back to its original size as it released when you burned it in the first place, and probably a lot more, because the CO2 has been diffused into the general atmosphere.

To state it more succinctly, we extract work through a pressure differential, and by reversing that pressure differential, won't that require more work than we got out in the first place by the second law of thermodynamics?

I ignored the part where part of the energy is coming from the hydrogen. Is the hydrogen -> water where most of the energy is coming from, and the carbon part relatively insignificant?

linknoid··on Windows 95 – How Does It Look Today?
Do you also remember waiting 5 minutes for a game to load from the insanely slow 1541 floppy drive? I'll gladly take a 10 second boot time with instant application start time over instant boot time with 5 minute application start time.
linknoid··on 50 Years of Pascal and Delphi Is in Power
Having worked extensively with both WinForms and Delphi GUI designers, I consider WinForms far better.

WinForms designer is actual C# code, you can copy and execute that code outside of the designer. It's possible to search for references to a control in the designer, just the same as any other code. Often in Delphi, trying to accomplish the same thing in code as in the designer had a very obscure relationship. WPF feels much closer to the way Delphi did things, where your GUI is defined in different format than your code.

In WinForms, creating a new control requires, well, just write a class that descends from Control, compile, and then you can start using it. In Delphi, creating a new control means you need an independent project, compile it into a package, and figuring out how to install it. I remember fighting Delphi trying to understand the package management system, and it was way more complicated.

In WinForms, when you design a new control, it actually executes your code, so design time behaviors actually reflect what will happen at runtime. I remember having stuff in Delphi where a large control would be collapsed into a single line, and you couldn't actually tell what you were working with until you run it.

linknoid··on Handles are the better pointers (2018)
> Because SQL is amazing for executing business logic.

Can you explain this a bit more? I've always heard that there are supposed benefits to writing business logic in SQL, and I've made efforts to put it into practice, but the more I deal it, the more I dislike it.

I just finished rewriting a complex calculation that was being done in SQL into C#, and the C# runs about 10 times faster, is easier to understand, easier to debug, easier to change, and easier to test. The SQL was written as a series of views each building on top of another, some doing grouping, some doing calculations, etc. until it gets the final result which is copied into a table.

Let's say I need to calculate intermediate result A (like maybe a giant case statement) as input to calculate B, C, and D, which will then go on to be combined in various ways. In order to avoid inlining complex calculation A in 3 different places, I can either write a sub-select, a CTE, put it in a view, or copy it to a new table variable. But no matter how I handle it, I end up with layers and layers of nested select statements, each performing one more step of the calculation. Doing the same thing in an imperative language usually ends up seeming trivial compared to doing the same thing in SQL. In C#, I'd just add a function or read-only property to calculate A, and then use that wherever it's needed, but in SQL, adding such a requirement can mean restructuring the entire query.

In another case, I've taken a stored procedure that selected data into a table variable and manipulated that, and rewrote the whole thing in C#, getting a 15x performance gain (from almost a minute down to 3-4 seconds, and pretty much all that time is retrieving relevant rows from various tables). It does the exact same work, but working with classes instead of a table variable. When I originally started working on the stored procedure, it used cursors, and took 15 minutes to run.

In another case I was recently working on, what should be an efficient calculation joining 5 tables together into a view ended up taking several seconds to select one record and is called quite frequently (i.e. like 50 times in a second during application startup). I added an index to speed it up, but instead that index made other queries unbearably slow because the optimizer for those queries completely changed how they were executed based on the new index. So I put triggers to copy the view to a cache table every time something changes that the view depends on. But now it takes several seconds for each update of a row, which is still a win, because writes are maybe a few times a day, but reads are continuous. But it means that updating multiple rows at once will now be really, really slow, because the cache table has to always be up to date, and the trigger has to update it preemptively rather than lazily, because querying from the cache table can't cause it to update itself. I might end up having to rewrite the trigger to do the joining in C# if it causes too many performance problems.

On another database, I have to manually call update statistics pretty frequently, or the query optimizer breaks (i.e. extreme slowness), because frequently appending hundreds of records to a table that holds over a hundred thousand rows with an auto-increment primary key should obviously invalidate the entire query plan. I'm not blaming this on a poor job by the query optimizer. Rather, on the fact that SQL depends too much on letting a generic query optimizer decide on the fly what it thinks is the best way to accomplish a complex query, instead of writing code that will always have deterministic performance characteristics no matter what the statistics say. It's a blessing and a curse that the query optimizer can change based on actual data. But that seems much more important for writing ad hoc queries, and when writing an application, I think it's more important to have more direct control over the performance characteristics.

SQL definitely has its strengths, and I have no desire to stop using it, but I don't understand the claim that it's good for writing general business logic. Maybe I just haven't seen the places where it really shines in this regard, so I would like to hear about ways it's better, because maybe I'm doing it wrong.

linknoid··on C# 9 top-level programs and target-typed expressions
There are a few language features which require a specific type to be defined, but you can define those types yourself.

For example, to use record syntax, you need to define this attribute:

    namespace System.Runtime.CompilerServices { public class IsExternalInit : Attribute { } }
And supporting the new indexing syntax requires you to define System.Index and System.Range types, which are a bit more involved, but still pretty trivial:

https://docs.microsoft.com/en-us/dotnet/api/system.index?vie... https://docs.microsoft.com/en-us/dotnet/api/system.range?vie...

But pretty much all the other new C# language features I've tried have just worked straight out of the box with .NET 4.7.2.

linknoid··on C# 9 top-level programs and target-typed expressions
The C# compiler has always been included with the .NET Framework, it has never required Visual Studio:

https://stackoverflow.com/questions/861384/is-it-possible-to...

linknoid··on Piano Practice Software Progress
Nope, I pretty much stopped once I got to college. At some point I decided I was going to learn Rhapsody in Blue on the piano, and got the sheet music (book) and started practicing. I didn't make it too far, but I made it a lot farther by trying to imitate what I heard than trying to play it from the book.
linknoid··on Piano Practice Software Progress
I think different individuals learn different ways. I had piano lessons from a young age, and everything was done off of sheet music. I would spend all this time reading through note by note, chord by chord, working my way through. But even after practicing reading music for over 10 years, I ALWAYS learn to play a song much, much faster by hearing it than by trying to read the music. My brain just can't automatically look at the position of black dots and translate that to which keys to press, I have to actively think about it, but once I can hear the music, my brain says, "I want to hear this note, so that's what note that dot must correspond to".

Imagine trying to learn to read English, and instead of seeing words, you see a bunch of letters and have to decipher each letter. I'd almost describe it as dyslexia for musical notation or something (which isn't a problem for me when reading text). I can recognize C,D,E,F,G pretty instantly because of their position relative to the bottom bar of the treble clef, but as soon as you start getting above that, I start having to count spaces relative to a known position, because everything internal looks like a big jumble. So G-B-E (on the treble clef) is easy because I see G as the base, and then the other two notes are space by two, but if it's just B-E without the context of the G, I have to stop and figure out exactly where those notes fall. And as soon as I get below C (on the treble clef), I start having to stop to count the separator lines.

But if I can hear what I'm trying to play, I can usually just jump to the correct note/chord. Maybe I'll have to stop and experiment to get the right chord periodically, but I don't have to stop and analyze the position of each dot on the score. To me, the greatest value of sheet music for me has always been in keeping place, so I associate the location of specific patterns on a specific page, and based on all the context, and know that I'm supposed to be at this point in the song that I've already taken the time to memorize beforehand. But I'm pretty much never paying attention to the actual notes on the notation at that point.

linknoid··on Show HN: Svelte NodeGUI, a lightweight Electron alternative with native UI
The VsVim plugin for Visual Studio makes an attempt at supporting everything in the .vimrc (or _vimrc) file. Compatibility is not 100%, so certain things just fail, but it's a lot more than just basic key bindings.
linknoid··on Again on 0-based vs. 1-based indexing
12:00 should actually be 0:00 on the 12 hour clock, it belongs to the next 12 hour period. 11:59 PM is yesterday, 12:00 AM is one minute later, and falls on today. Same with noon, 12:00 PM comes one minute after 11:59 AM. When I see 12:00, I automatically convert that to 0:00, otherwise AM/PM doesn't make sense.
linknoid··on Binary Search Reconsidered (2018)
That's my C# implementation, so long is 64 bits and int is 32 bits. 64 bits will never overflow in my lifetime. That's basically a Google scale amount of data.
linknoid··on Binary Search Reconsidered (2018)
Usually when I'm doing a binary search, I'm not searching over integers, so the comparison itself will be quite expensive compared to the rest of the loop, so I prefer it like this:

  int BinarySearch<t>(t[] array, t find, int min, int max, Comparer<t> comparer)
  {
      int mid = 0;
      while (min <= max)
      {
          mid = (int)(((long)min + (long)max) / 2);
          int compared = comparer.Compare(find, array[mid]);
          if (compared > 0)
              min = mid + 1;
          else if (compared < 0)
              max = mid - 1;
          else
              return mid;
      }
      return ~mid;
  }
linknoid··on Lode Runner
I've been playing this version of it a lot recently: http://loderunnerwebgame.com/game/

Even though I'm a lot better than when I was a kid, I've only made it up to level 14 so far.

linknoid··on All Mersenne prime exponents below 100m tested at least once
The simple trick with modulo 7 is take all the 3 bit sequences: (x & 111), (x & 111000) >> 3, (x & 111000000) >> 6, etc. and add them all together. It means you just have to do bitshift + add instead of all the complexity of division. Same applies to higher powers of 2^n-1 as well.