News for hackers. Stuff that matters.

veebat

Re:Brave 0.55 released on Friday October 19, 2018 @04:29AM (#18255076)
I'm willing to make a speculative bet on Brave/BAT. The existing user growth is good, and the incentives for their ad system are basically correct for everyone.

The product Brave is actually peddling is akin to anti-cheat software: It takes steps to prevent fraud throughout digital advertising and improve the cost effectiveness of digital ad campaigns. That pitch means that they have the ear of advertisers already, and it's only a question of executing on the rest. Given prodding, advertisers will cooperate in order to fix up the market because what they really want is a "commoditize your complements" scenario. They are not there to become adtech wizards. They want to find qualified customers for their primary business. If Brave succeeds in forming a coalition, you'll start to see businesses from other sectors talk it up and give users and content creators hard incentives to sign on. They can even use such marketing efforts as part of their own speculative plays on the currency.

On the user end of things, that means that Brave engages in the click fraud arms race, but with higher-powered weaponry than can be accessed from within Javascript. They get a deal that is a definite improvement on the status quo: they choose exactly when and where they want to see ads. For the other parts of the system, the cryptocurrency marketplace replaces most of the middlemen and associated incentives for fraud. If you're in the business of total control either way(whether it be "never-again-an-ad" or "I want to access as many users as possible"), it's a devil's bargain, but if you're interested in getting the Web on a more sustainable path where quality is encouraged, this is something that could do it.

Re:Decision Tables on Thursday October 18, 2018 @05:09PM (#18252151)
I recommend checking out the material about Subtext[1] for elaborations on tabular programming. Often in practical systems an enumeration of finite state is a tool to "squash" very large decision tables into a more comprehensible pattern. But having the decision table aids in discovery of just how many states you have to deal with.

[1] http://www.subtext-lang.org/

This is kind of analogous to photorealism versus cartooning. A history or biography would attempt to adapt events and experiences directly to the page: "this happened, and then this happened, and it felt like that". Fictional work transforms those same elements into exaggerated characters and scenarios. Both kinds of works require some creativity to build up a coherent story, but fiction has a freer hand to manipulate elements and choose its focus.

Just making it up without adapting from anything real usually isn't something that good fiction is built up from, though. That path goes directly to cliche, and it's easy to find cliched fiction.

Reading aloud is something I've returned to in later years as speaking practice, vocal warmup, and testing my own writing. It was, of course, a chore in school.
Re:Why Zig When There Is Already CPP, D, and Rust? (2017) on Sunday October 14, 2018 @10:59PM (#18217119)
There's a profound wisdom to knowing the niche you're in, and Zig does seem to have that. The applications part of the stack is saturated with options, all trying to encroach on each other, but when it comes to the genuinely low-level, unsexy stuff...the viable options are all pretty old languages, and languages that patch over those old languages.

And with respect to discussion of boilerplate, you can, of course, always have a "Zig++" language that patches over Zig. By cutting out its own metaprogramming functionality, it's much more straightforward to generate useful Zig source. There are a lot of advantages to restraint in the design, and Go does share that, too.

I read all that and still think, "you don't what you're talking about".

This is 100% a problem of dependency management, i.e. a problem common to software everywhere at all times that has never gone away. Whether more work survives is ultimately a factor of whether it's whether it's easy to make it survive, not on the "blame them for lacking effort" angle. Some folks will take the extra time, some won't.

The software that still has its dependencies, we can do something about. For most games that equates to "emulate the release platform, and we get the playable release back" - which is the defacto standard, since it's relatively easy to get copies off a ROM or CD, and it's the single artifact that is most representative of creative intent. It absolutely makes sense that almost all the effort would go towards that. We like seeing Leonardo Da Vinci's plans and studies, but he was focused on results, and we mostly know him for those results.

The source is more specialized, and not as easy to subject to the emulator model. A lot of shops "back in the day" did not even have good backup or version control practices and the game's build system involved a whole custom software project of its own, and only one person knew how to make it go. Getting it even to the point where all the code and assets were accounted for would incur a person-weeks expense, and studios then as now would finish a release with layoffs to shave off salary expense, which in turn gave an incentive to jump ship before finishing to dodge the layoff, leaving certain knowledge about the project in limbo. And employees are often not trusted enough by the management to let them bring in an external drive and dump the project: the optimism of "preserve the art for the future" goes right up against the pessimism of "i'm building a business, not art", and the psychopathy of "if they can't dump the project, they can't steal it". (yes, it happens - on both ends) There are numerous barriers in those crucial weeks around the ship date that can cut off this aspect of archival right at the start, and many a preserved game is the result of some hero who went against the direct wishes of their bosses and made copies in secret.

Nowadays, project tooling tends to fall a little more along standardized lines, and if you start with the goal of minimizing dependencies, you can feasibly have a smooth path to restoring the build without incurring the same overheads that make managers give up on archival to save a dime. So while commercial conflicts of interest remain, it's gotten easier, relatively, if your project scope is not so large that you need to bring in the custom tooling again(which, of course, is what happens in AAA). It's not "sneeze and you've preserved history" easy, but we can work on that.

And what if we're talking about an online game? That's the preservation nightmare taking place today. All the MMOs, mobile games, and so on - those are living things. You can't reconstruct a userbase. So even having running code and assets, it gives you a part of the experience, but it will be empty, fossilized. You will have to fall back on video footage to see it in contemporary context. That said there is the occasional revival effort, such as with Habitat[1].

tldr; if you want better archival, support game labor, support projects that improve basic software infrastructure.

[1] https://en.wikipedia.org/wiki/Habitat_(video_game)#Revival

I think most of the dynamic/static bias depends on the specific experiences of your problem domain.

If you have a lot of types of data to model(layers of records, sequences, indirection, etc), dynamic types make it easy to start bodging something together, but result in write-only code. So you end up wanting to have additional structure and definition - maybe not immediately, but just after prototyping is done and you have a first working example.

If you're just applying a routine algorithm that ultimately does a round trip from SQL, you don't need that additional assurance. The database is already doing the important part of the work.

If you have simple data but it needs to go as fast as possible, you end up wanting to work at a low level, and then the machine size of the data becomes important - so you end up with a static types bias.

Re:Maybe adding generics to Go is about syntax after all on Tuesday September 04, 2018 @05:03PM (#17912778)
Another helpful comparison is Lisp syntax versus Forth syntax. If you actually want a simple, terse, unstructured language, Forth is the way to do it: Words will consume and return any number of inputs or outputs to the stack, and you get entire classes of error when it's unbalanced that would surface as syntax errors anywhere else.

Just adding s-expressions is actually a huge jump up in syntactic complexity and structure, since now you can define a whole hierarchy statically, "on the page", instead of having to use a series of stack operations to manipulate memory from afar. And then as you lucidly put it, going from s-expressions to a practical Lisp dialect adds another level of context on top of that.

(And yeah, it's possible to bolt structure onto a Forth dialect, too, but the "Chuck Moore way" is that you do that custom every time you need it, instead of trying to generalize. Generalizing a concatenative structure leads to something like Factor.)

That really speaks to the horrors of America, given that in Japan, as a white male foreigner with command of "hai", "arigato" and on good days, "ah, so desu ne", I definitely got the sense of being put up with - albeit more so in Tokyo than elsewhere.

But at the same time I can sympathize in that street interactions in California have grown openly hostile across the board. The level of polite hospitality is so low and paranoia so high that it is actually hard to go outside and do business without ending up in a confrontation of some kind. Just the other week I was crossing the street in SF after seeing a movie[1] and a lady(a white lady) crossing the other direction gave me the finger and screamed "fuck you, fuck you" for no reason I could fathom.

We passed, and then I had a feeling of deja vu and thought, "didn't that happen the last time I saw a movie here too? Does this woman just go around in the evening cursing out strangers for self-care?"

And that is the kind of thing that sounds dreadfully believable for SF these days. The privilege spares me from most avenues of material loss, but that's hardly something to be proud of.

[1] The film was Sorry to Bother You, if it matters. I enjoyed it

Re:Game Programming Patterns: Double Buffer (2014) on Tuesday August 28, 2018 @08:08AM (#17858152)
Early 3D games are primarily limited on how they handle occlusion. If your scene is designed favorably(e.g. wireframe spaceships), you can ignore occlusion, but that doesn't describe most interesting scenes.

Leaderboard is using a kind of painter's algorithm to do everything, which is flexible but requires using overdraw, and by itself, will produce rendering errors in many scenes because the depth will be sorted per object or per triangle, versus per pixel. Filled triangle rasterization is particularly expensive to compute and requires a fair amount of numeric precision, both of which compound the issue of using overdraw.

Fractalus does not use these techniques for terrain - although the exact implementation is idiosyncratic[1], it's ultimately filling an outline that defines the horizon, and then adds texture to the landscape with dot patterns. Bear in mind, it doesn't render to the full screen either, it's mostly HUD, while Leaderboard is a little more expansive.

[1] A similar technique is described for Captain Blood: http://bringerp.free.fr/RE/CaptainBlood/main.php5

Re:Losing Earth: The Decade We Almost Stopped Climate Change on Wednesday August 01, 2018 @09:56AM (#17662512)
Leverage.

You don't throw your foe to the ground with brute force alone. You take him off-balance, and move in with good timing and technique.

If your goal is solving climate change, well, the leverage isn't really in the technical solution, but in the political economy. We need a redesign. That's problem one.

But if it's the power structure that needs changing, what affects it? Knowledge. Signalling. Valuation. And then you get into things that you can potentially change as a tech worker, by pushing for information systems that change our valuation metrics to match a philosophy of sustainability. And that positions actors who wish to take sustainable actions to have the leverage to realize it.

That, I think, is the trick to feeling OK about it. At the end of the day, it's a war fought in an abstract, everyday sense: Build up your sense of morality and build your career around those principles. You might not be the hero, but you won't be the villain.

Re:The internals of testing in Rust in 2018 on Monday July 23, 2018 @08:45PM (#17597266)
I love how the ambiguity has caused BOTH compiler teams to comment on what they're optimizing.
Re:The Wrong Abstraction (2016) on Friday July 20, 2018 @08:14PM (#17579998)
I use the "dueling sins" model of "copying versus coupling." Early lifecycle code benefits from the flexibility of copying. Mature code benefits from the coupling forces of abstraction. Both have the capacity to do harm.
Re:The Wrong Abstraction (2016) on Friday July 20, 2018 @08:11PM (#17579980)
I know what you mean, but you need to find a different or more nuanced term. Deduplication is abstraction, it just isn't an abstraction mapped to the domain problem. Even a compression algorithm abstracts:

An abstraction can be seen as a compression process, mapping multiple different pieces of constituent data to a single piece of abstract data; [1]

There are wrong abstractions.

[1] https://en.wikipedia.org/wiki/Abstraction#Compression

Re:Anti-If: The missing patterns (2016) on Wednesday June 27, 2018 @06:59PM (#17412624)
Sum types are a huge benefit to branchy code. Philosophically, OOP polymorphism can do a similar thing, but it doesn't really cover it as succinctly: if your operation is of the "similar data, mostly the same algorithm but with variations at points depending on the data's type", going down the polymorphic route requires a lot more naming of things to cover each variation, and then when you go to inspect it, the code is twisty and jumps all over the place. I've had a lot of bugs introduced by method boundaries obscuring the execution flow.

What polymorphism is good at is building the black box, the soft boundaries, and that isn't a good thing to do for fine-grained details. I do occasionally find a use for extension, but it's at a scale closer to "call this entire subprogram as a kind of state machine", vs "write this algorithm as a collaboration of objects abstracted away from each other".

The "alternate hard and soft layers"[0] pattern comes to mind: if what you really need is modularity, going towards full dynamism and reflection seems like a better choice than to try to extend everything statically, which creates a very large latency issue(the default response to every form of change in a static system is "recompile from the beginning, precompute all answers"). At the same time, it's not a good fit to have a vast codebase do everything dynamically since the comprehensibility and throughput suffer.

[0] http://wiki.c2.com/?AlternateHardAndSoftLayers

Re:Anti-If: The missing patterns (2016) on Wednesday June 27, 2018 @06:36PM (#17412464)
There's a semantic thing going on with this expression that is rather interesting.

First, consider this reworking:

    boolean a = this.doesSomethingWithA();
    if (a) {a = a && !this.doesSomethingWithB();}
    if (a) {a = a && !this.fooBar2000.isEmpty();}
    if (a) {a = a && !this.anotherLongAttribute;}
    if (a) {a = a && !this.anotherMethod();}
    return a;
And then this one:

    boolean a = this.doesSomethingWithA();
    a = a && !this.doesSomethingWithB();
    a = a && !this.fooBar2000.isEmpty();
    a = a && !this.anotherLongAttribute;
    a = a && !this.anotherMethod();
    return a;
In the first version and your original, it's clear that there's short circuiting and it can return early, but automatic formatting will bloat up the vertical size of the code. In the one-liner there's also short circuiting, but it doesn't format well. In my second version you get the formatting, but it will always evaluate every possibility.

In general, when I'm favoring code formatting, the variable declarations come out. Quickly aliasing something into a name when it could exist purely as an expression adds a degree of conceptual flexibility. It keeps the code local(no new function name and jumping over into it). But it does also result in this kind of unnecessary computation.

Many of the sauces are sweet, and the recipes tend to incorporate every major food allergen you can think of. I still visit regularly because you can opt out one portion at a time: You can go half-and-half veggies and chow mein, broccoli beef, mushroom chicken and have something a bit plain, but far more balanced than most fast food. And while the service model is extremely scripted and doesn't accommodate larger orders gracefully, my average time from getting in line to finished service is faster than Mcdonald's and more consistent since the order is put together right in front of you.
Re:AMD Zen 2 Update: 7nm EPYC in Labs Now, Launching in 2019 on Wednesday June 06, 2018 @04:58AM (#17245473)
The most likely cause of Intel's lagging is a wall of cost/benefit to being both designer and fab. This hit AMD earlier by being smaller(and arguably, with a different management style, AMD could have held on to their fabs longer) but each node only gets more expensive and harder to keep busy with orders which in turn means a greater need for external customers to fund R&D.

Intel had a reprieve of almost a decade with a weak AMD that let them coast along with the desktop monopoly and extract a yawn-worthy 5-10% improvement per generation, but now that they have the incentive to compete again they're struggling to get their house in order - the chip design hasn't had a major refresh in a long time and they have been very late with their version of 10nm.

So they're really at a crossroads now where they can't rely on old tactics and their long-term prospects are in serious doubt, since they didn't position themselves to counter the efficient small-core/big-package architecture that AMD is pushing with the Zen chips. For now, they can still put out competitive flagship product launches simply by binning extremely expensive parts and running them hot(e.g. compare i9 and Threadripper) but that advantage might erode within one more generation.

Re:Stripe is building a Ruby typechecker on Sunday June 03, 2018 @06:31PM (#17222741)
Well, what kind of projects? And what order of magnitude big?

Whether dynamic type errors become an issue depends a lot on how often all codepaths are run.

If what you're running is a batch processing script, it's likely to crash out as quickly as a type-checking compiler, and then static types have no direct appeal.

On the other hand, if it's a long-running server with a lot of finite state machines(maybe it's running a multiplayer game or something) it's really hard to reach type errors without an extensive manual test.

This becomes a relatively bigger issue as the codebase gets bigger, again depending on the type of code. If the main way the system expands is by handling a more diverse set of data types, dynamic types allow less code to be written, but also make it harder to verify.

In practice what I tend to see happening is that a glue layer appears that needs dynamic behavior, while the codepaths underneath that benefit more from static typing.

Re:Myrddin Programming Language on Sunday June 03, 2018 @06:05PM (#17222553)
I just got through evaluating Zig. It's idiomatic to use defer right now but the language is also still pre-1.0 and making big changes, and that's one that might be covered in syntactical sugar at some point. Rust had a GC at one time, after all.

Overall Zig feels closer in intent to C than most "better C" languages. In its current form it has a lot of attention to detail about its behavior around common edge cases. It cares about not blowing the stack and dealing with OOM, and the default behavior of numeric overflow is a crash. Stuff that allocates to the heap is stuff that the programmer is made aware of, and "defer" is one of those little additions. It's less developed w/r to higher level abstractions, with the exception of a strong metaprogramming facility and sum types.