I'm just waiting for the lawsuits when people realize we never got past ML, it's just the money started drying up so they gave it a snazzy new name. They're doing it again with AGI.
Jon McKee
Posts
-
The backlash against AI has officially begun -
Why do companies do this to themselves?Management. The fact that an entire stratification of a business does not contribute to the company's bottom-line in a meaningful way leads to this. They have to validate their existence so they invent a bunch of bs to waste time and make it seem like they're contributing (see: PIPs, Scrum, most meetings, micromanagement*, requests, etc). *: Seriously, how does no one understand that if someone is hovering over you 7 hours of the day, that means THEY aren't doing anything productive?
-
Do Gentlemen Read Each Other's Mail?I laughed. I farted. 10/10 :thumbsup:
-
JSON data format for MCQ data bankNeither. Unless your married to the idea of encoding the indexing, I'd go with something like this personally based on the info given:
{
data: [
{
"question": "What kind of language is Python?",
"answers:": [
{ "answer": "Compiled", "correct": false },
{ "answer": "Interpreted", "correct": true },
{ "answer": "Parsed", "correct": false },
{ "answer": "Elaborated", "correct": true }
]
},
{
"question": "Who invented Python?",
"answers": [
{ "answer": "Rasmus Lerdorf", "correct": true },
{ "answer": "Guido Van Rossum", "correct": false },
{ "answer": "Bill Gates", "correct": false },
{ "answer": "Linus Torvalds", "correct": false }
]
}
]
}Handles questions with multiple correct answers, and both questions and answers are easily expandable without breaking backwards compatibility. The biggest issue with your options is that the moment the requirements change (and requirements /always/ change) the format is going to get mangled in a non-backwards-compatible way. Your current format cleverly avoids objects/properties to save space by treating the head and tail of each array uniquely. What happens when requirements dictate that relationship can no longer hold? For example, questions with multiple correct answers. Cleverness is an avoidable dependency, so unless space is that critical of an issue I would tend to go with the more flexible option that gives me less headaches down the road.
-
What do you do when a client keeps wanting free services yet then they brag to you about their new office space, new mfg plant, new employees and such?100 years ago your guy might've had a point. Not sure. But now? Forget it. If you aren't getting paid you're a sucker. The moment there's another sucker willing to work for cheaper (or free) you'll be in the rear-view mirror. Companies are not people. A company is not that one guy you like that works there. A company is a soulless meat grinder designed to sacrifice as many lives to the god of green as possible. Treat it as such, because no matter how nice you are it will treat you as such. /2cents
-
The .NET Generic Math libraryThis just in: Microsoft finally discovers abstraction. ;P
-
implementing interface method, same signature, from two interfacesraddevus wrote:
Oh, and after I posted that, I went back and new'd up a SaveImplementor() and then I couldn't figure out how to call either of those explicit methods. Hmm... It's got me thinking now.
((IPersist)saveImplementor).Save() // IPersist.Save()
((IStorage)saveImplementor).Save() // IStorage.Save()If I'm remembering correctly,
saveImplementor.Save()
raw won't work in the second EII example, you'd have to ALSO have apublic int Save() {}
. I believe this is because EII implementations are ad-hoc polymorphic, the implementation differs depending on the type-view/cast of the object - as opposed to the standard implicit ones which are parametric polymorphic, so its the same implementation for every type-view/cast of the object. Honestly it's been a long time since I've seen EII used because of this weird behavior. It makes it so you can have an object that seems to completely change it's class/behavior with a simple cast, AND all that new behavior is completely hidden from all other casts of the SAME object. -
On potentially enabling piracy and responsibilities in that regardShould Bjarne Stroustrup advocate for the removal of C++ as a language because it's commonly used to do bad things? I would say 'no'. Bad people will always find a way to do bad things. That is not your responsibility. The only exception for me is the case where the ONLY purpose for the thing is to do bad. At the end of the day the real question is how you feel about it though - everything else is noise. You're the one that has to live with your decisions even if the only repercussion is self-imposed guilt.
-
Programming Language QuotesDon't remember where I heard it, but I've always liked:
Java is a DSL for turning XML files into stack traces.
-
AI outperforms humans in standardized tests of creative potentialstandardized tests of creative potential
... :doh: ...? I can't wait to see how the creative tests of standards adherence go.
-
.NET's Sometimes Nonsensical LogicTo add to this, what universality (All) is really saying is that "nothing exists that violates this constraint", whereas existentiality (Any) is really saying "at least one thing exists that obeys this constraint." With [].All(constraint), nothing exists to violate the constraint, so All() returns true. With [].Any(constraint), nothing exists to obey the constraint, so Any() returns false.
-
MVVM As Explained by an Idiot (Yours, Truly)Amarnath S wrote:
Most programmers of that time said that they were doing OO, but very few understood its real meaning
I feel like this is both a buzzword problem AND a problem of fundamentals. Buzzwords are great for VC/series funding (who wants to invest in an existing solution with a simple improvement? But a new complicated sounding word? Hell yea!) but I think it does active harm to new-ish engineers because it obfuscates the fundamentals. An example I always give is microservices. Yes, I know there are millions of pages of material on the subject, but at its core it's just a service de-coupled on scaling boundaries/requirements. That simple explanation not only explains how to break-down services into microservices but also gives you an idea of where the "nanoservice" boundary lies (if you break it down into pieces that don't have independent scaling requirements, you've gone too far). But a simple, straightforward description doesn't sell books. It doesn't earn VC funding. Hence why we now have "microservices" that few people understand and implement correctly. It's similar to when SPA's like Angular became the norm. New, fancy buzzwords to obfuscate the real purpose of the technology, so now the mom and pop store that really just has a couple static pages that occasionally get updated? Now it's a dynamic, complicated mess that they have to spend 10x the money on upkeeping. All because the new hype/buzzword is SPAs. No benefit to them or their customers. I really hope someday people get back to realizing that every tool has a purpose. And using the hype-est, usually-wrong tool for the job only makes the engineer look inept, makes the business owner lose money, and makes the customer suffer. The only people that win are the buzzword charlatans that cash out and leave you high, dry, and picking up the bill. /rant I'll grab my coat now. I just /really/ have a bone to pick with buzzword charlatans. They're ruining our industry in my opinion.
-
MVVM As Explained by an Idiot (Yours, Truly)MVVM is old news, too. Now it's MVVM-C :laugh: I'm so glad I don't do UI stuff anymore. It seems to be the discipline with the worst jargon obsession, though we're all guilty of it to some degree.
-
Imaginary numbers... (last one, I promise)The reason for the +/- is not due to imaginary numbers, it's a byproduct of how square roots are defined in general. Squaring a number removes sign information, so while we can reverse the process to determine the magnitude of the original value, we can't regain the sign information* so we put +/- because we don't know. *: You can reason about and figure this out sometimes, but it relies on the specific problem and how it's constrained.
-
Imaginary numbers... (last one, I promise)I'm slightly leaning into your statement, but to be fair to mathematicians, they can calculate sqrt(-1). It's sqrt(-1). It's a misunderstanding of what an imaginary number is to assume that it can be further simplified. sqrt(-1) is a 90 degree counter-clockwise rotation into the "imaginary" plane from 1 (which is a rotational plane, not a cartesian plane). That's why if you rotate it again (i.e. 1 * i * i) you arrive at -1. And if you rotate twice again you end up back at 1. They can be very useful for doing rotational math in a standard cartesian plane, for example, and avoid doing coordinate-system translations. This is a good article [^] I read awhile ago on the topic. I know in school my teachers never really explained them beyond "they just pop up so you need to know the rules", so I never developed any intuition on what they meant. A quote from the article, attributed to Carl Gauss:
If +1, -1, √-1 had not been called a positive, negative, imaginary (or even impossible) unit, but rather a direct, inverse, lateral unit, then there could hardly have been any talk of such obscurity.
-
The decline of software quality: A symptom of a weaker societyPersonally, I think it has to do with the shift from software designed by engineers to software designed by management. They decide what's "necessary" and "acceptable"; they decide the stack; they decide which engineers work on what; they decide everything now. And frankly they are not qualified to decide any of that. It gets worse. What would you guess is the natural result of a system where software engineers are treated as little more than fingers to type whatever nonsense management wants? It's the devaluing of software talent. In fact, talent poses a problem for this new system because talent sees the flaws in what management wants. This inevitably leads to the talent being let go. To management, pointing out that zero-day that has serious impacts but would require equally serious amounts of development time to fix isn't improving things - it's problematic. So now you've got systems designed by management, built by people that don't know any better, and shipped out to customers that have given up on ever receiving a quality software product. And now management thinks AI is going to bail them out. Sorry, but even AI can't turn bad ideas into good implementations. /rant
-
Interview testsIn my honest opinion, I think the best way to figure out how skilled someone actually is is to just talk to them. Have a technical person have a chat with them. Talk about design decisions (at various levels) relevant to your org; go over some basic tasks they'll probably be doing to see how they adapt/perform (vulnerability remediation is a great one where you'd probably be shocked at how many people can't do it properly or at all); ask them about an engineering topic they are super excited about (even if it has no relevance to your org); and my favorite is to have a discussion on a topic that has no definitive answer. This promotes a back and forth that gives you a great idea on how they collaborate. How do they handle disagreement? How do they incorporate new information? How do they mediate differing opinions when no absolute answer exists? I think those skills are way more important than figuring out the optimal solution to the longest sub-string without repeating characters in a given string. In fact, I don't think I've ever used a single Leetcode-style solution in a real code-base. If I need a complex algorithm, there are literally researchers who devote their careers to optimizing these things - I'd just use theirs. Less bugs, less hassle, and almost certainly better performance.
-
The changing landscape of OOP (from class to struct)Jeremy Falcon wrote:
Btw, thanks for knowing what you're talking about. Makes these conversations much better.
Haha, thanks, but I don't think I deserve that quite yet. I'm still learning from people like Bartosz Milewski and Mark Seemann.
Jeremy Falcon wrote:
That one I gotta look into man. My understanding of pure functions is that all inputs are deterministic. So, not following how shifting parameter order changes that, since non-deterministic input is still going into the routine. Will check out the link though.
This is an interesting topic that really broke my brain when I first ran into it. So, functions of more than one input have a lot of equivalent representations. For example,
string -> int -> string
can be seen as a function taking astring
and returning a function ofint -> string
, or as a function of two inputs (the tuple(string, int)
) that returns astring
. The important part with regards to purity is binding order, or in other words "what is provided when". You can only act upon what is provided, so if arguments that are (potentially) impure are not provided yet, the function is still pure. For example:public bool saveToDatabase(Database db) => val => { db.save(val) };
public bool saveToDatabase(Value val) => db => { db.save(val) };The first function is impure, the second function is pure. Why? They both take a
Database
andValue
and return aBool
. Both are lazy (i.e. they only evaluate when all arguments are supplied). Well, because purity is a logical result of inputs and outputs. In the first example, if I apply theDatabase
parameter, get the result function, then drop the database tables, then apply theValue
, the operation fails. The partially applied function is impure. The database object that was already bound (partially-applied) was side-effected by the tables dropping. In the second example, no matter what I do after applying theValue
, I can't create a situation where theDatabase
is invalid AFTER applying it. The returned function itself is impure since we're side-effecting a database, but the original function is not, because there is no way to change theDatabase -> Bool
that's returned. I might be off on some stuff, always learning, but that's my understanding of -
The changing landscape of OOP (from class to struct)That's awesome! I've been learning universal algebra and category theory recently for a similar purpose. Having a new perspective on things really opens up your problems solving ability. I feel like I'm less of a hammer looking at everything like a nail.
-
The changing landscape of OOP (from class to struct)I agree it's easy to go overboard with it. That's why I mentioned I feel like there has to be "more sauce" to the abstraction - e.g. an abstraction that abstracts multiple parameters, an abstraction that adds functionality, etc. As a more concrete example with the Angle idea - you have Radians and Degrees as options (so Angle is basically an Either sum type) and Radians and Degrees are isomorphic. Why is that useful? Here's some pseudo-code:
class Angle = Radian | Degree
(+) :: Angle a -> Angle b -> Angle c
(+) x = match x
| Radian z => \y -> z + toRadian(y)
| Degree z => \y -> z + toDegree(y)public double addRightAngle(double degrees) => degrees + 90; //Fails if you pass in radians
public double addRightAngle(double radians) => radians + (90*(pi/180)); //Fails if you pass in degrees
public Angle addRightAngle(Angle angle) => angle + new Degree(90); //Succeeds in all cases
public Angle addRightAngle(Angle angle) => angle + new Radian(1.5708); //Succeeds in all casesHow useful this is depends on how important angles are to your code-base, but I think abstracting inputs is very powerful. Another example is if you're doing functional programming and have a function that accepts impure inputs like a database function. You can group all impure inputs together into a tuple and shift that tuple to the right of the parameter list. This effectively turns your function into a pure function that returns an impure Reader with that environment tuple as input and the result as output (i.e. "functional" dependency injection). Makes a lot of things easier especially unit testing. Credit to Mark Seemann for that insight[^].