Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
They're probably cool if it's 1850 and you have 3 whole bits of RAM to rub together
or embedded systems i guess, but why the hell are embedded systems working with strings

Adbot
ADBOT LOVES YOU

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

dougdrums posted:

If you don't want people to make money off of your work, don't release it for free?

just use the GPL

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Bruegels Fuckbooks posted:

i do think a language with no garbage collector which also doesn't support manual memory management is complete genius and i wish all languages were like that. "gently caress it, nothing we can do about that memory leak."

Pretty sure Rust does this. You have to try pretty hard to slip a memory leak by the compiler's checks though.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
IIRC C++ has so many syntax ambiguities that in mathematical terms the language is "undecidable".

One simple example:

code:
foo bar(baz);
Am I declaring a function bar that accepts an arg of type baz and returns type foo?
Or am I instantiating a foo object named bar, passing a variable named baz to the constructor?

The only possible way to know is to look at the context around the statement.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
You're allowed to have a constexpr function that returns a compile-time constant if passed compile-time-constant arguments but just gets called normally if passed variable / runtime values.
They up and added the consteval keyword to the language to do what constexpr sounds like it's *supposed* to do.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Dylan16807 posted:

Most people don't want their compilers to crash or hang.
Unless I'm missing a joke.

Except when you'd rather have it fail to compile so you can adjust the code.

In order of preference, when I write broken code (such as an infinite loop in a compile-time evaluated expression):

  1. The compiler should fail and produce a helpful error.
  2. The compiler should produce a warning
  3. The compiler should crash and burn horribly

Absolutely no where on the list is

  • The compiler should "helpfully" alter my code to do something else (such as evaluating at runtime instead)

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

tankadillo posted:

I need someone to make a linter to enforce that now just to see how many people unironically start using it.

It wouldn't be too bad as long as the linter or IDE enforces indentation/whitespace to ensure the visible structure matches the actual structure of the code.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

code:
// Do we really need to define a macro for "if"?
#define CHECK_WCF_FUNCTION(X) if (X)
:eyepop:

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
A reasonable lang would make it a syntax error to declare two variables of totally different types in the same statement.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Plorkyeran posted:

Signed int overflow is UB, yeah.

And the number of bits in an int is implementation-defined!

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Woodsy Owl posted:

Heck no, what language spec permits you to put a space before the left parenthesis of a function call?

C allows you to put whitespace pretty much anywhere except the middle of a word.

code:
#include                                                  <stdio.h>
int
  main
    (
      void
        )
          {
            printf    
              (
                "H"
                  "e"
                    "l"
                      "l"
                        "o"
                          " "
                            "W"
                              "o"
                                "r"
                                  "l"
                                    "d"
                                      "!"
                                        )
                                          ;
                                            return
                                              0
                                                ;
                                                  }
                                                    ;

RPATDO_LAMD fucked around with this message at 09:26 on Apr 27, 2019

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
When passed through OCR software, 93% of Paint Splatters are Valid Perl Programs

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
well clearly it doesn't already work (or at least not well) if the insecure car radio has to have permission to touch the steering system

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Obviously what he is saying is that the piece of hardware in a car radio in charge of reading data from the CAN and sending ACK/NACK messages should be segregated from the piece of hardware in charge of running the buttons and radio antenna. You are free to design the internal communication between these two components of your radio in any way since it does not affect the external interface that the rest of the vehicle sees.
The CAN-talk-to-er chip unavoidably has write access if it is connected to the network, but the radio proper does not need to (and should not) have write access to its CAN-talk-to-er.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

NihilCredo posted:

I live in the blessed land of GC and exceptions. I thought that unsigned overflow was simply the codification of what would happen by default anyway if unsigned overflow were left as UB. Are there any architectures that need to specifically handle them because they would do weird things otherwise and not guarantee 255 + 2 = 1?

UB is more than just "the compiler doesn't guarantee this". It means "the optimizer is allowed to assume this will never happen and use that assumption to rearrange code and generate slightly faster binaries that explode and fail horribly if it ever actually does."

Unsigned overflow is defined though. It's just signed overflow which is UB.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Jabor posted:

The real key points are
- They added this to their actual production website, not a private dev instance
- They never actually tested the code path they added the debug logging to before shipping it

"this" is pretty fucky in JS, isn't it? I don't know much about the language, but is it possible that a code change somewhere else in the project altered the context in that logging function? this.print() is calling window.print() now but perhaps it was intended to be someobject.print().

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

xtal posted:

I think Firefox had that before Chrome came out

There were extensions that did it but it wasn't in vanilla firefox until after chrome got popular.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
Well he's right that untyped programming languages are stupid garbage for idiots

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Suspicious Dish posted:

Probably the best-known example of testing in video games is Riot's test harness for League of Legends, where they record game playback and ensure very high-level things like "when I am this character with this spell with these stats, and fire at this enemy with these stats 5 times, it will eventually die". That's not unit testing, that's super high-level and just about the level that starts becoming helpful for games.

The factorio devs also run a bunch of automated tests on every commit, and have written about it on their dev blog before
But yeah those are super high-level non-unit tests also.

https://www.youtube.com/watch?v=erYjMMBXy7A

Theirs are apparently more in depth than just "this character will eventually die" though. To guarantee that the game logic is deterministic (important for multiplayer, to avoid desync bugs) they simulate every game tick on two separate processes and then checksum the game states to see whether they're identical.

RPATDO_LAMD fucked around with this message at 07:49 on Nov 12, 2019

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

NihilCredo posted:

Are there any games that are developed in a modular fashion like a business app? I.e. with a pure "business logic" library where all the rules play out and the abstract game state evolves via ABI calls, and a separate "frontend" that gets the updated game state from the library and renders it in the engine?

Deserts of Kharak did this. A dev did a talk about their architecture and other stuff at GDC. Interestingly, despite being a 3d game the simulation layer only runs a 2d abstraction, and then the presentation layer fakes the third dimension (even including running a separate physics engine to make vehicles bounce on their shocks and get airtime from jumping off dunes)

https://www.youtube.com/watch?v=wwLW6CjswxM

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

DaTroof posted:

Years ago there was an article about how an engine developer implemented scripting so level designers could write their own high-level game mechanics, but I can't find it now. I'm pretty sure it was a Star Wars game.

Many games do this, hence the popularity of Lua. It's a bad scripting language whose main redeeming feature is being easy to integrate into a pre-existing codebase, so you can expose internal game stuff for designers/modders/players to tinker with.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Dylan16807 posted:

Yeah but they have semicolons on every line that isn't the last in a block. it's horrible style.


And semicolons at the end of function declarations, which is a bit weird.

"Semicolons on every line except the last in a block" is actually the official style in the Rust language

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
A lisp dialect, but instead of parens it uses quote marks and you have to escape them an extra time for every layer of nesting

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

It's a language for bitcoin nonsense so "it's not a scam" is by definition false.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
Here's another fun bit from Beef.
code:
class Widget
{
    private int32 id;
    protected Rect pos;
    public uint32 color;
}

class Button : Widget
{
    /* This class can access 'pos' and 'color' but not 'id' */
}


static void Main()
{
    var button = new Button();
    /* We can only access 'button.color' */

    /* The [Friend] attribute allows us to access members which are normally hidden */
    int32 id = button.[Friend]id;
    /* Note that the 'friend' relationship is inverted from C++ here - the user is 
    promising to be friendly rather than the defining types declaring its friends */
}
There's a keyword to just ignore the private specifier and access any class's internal data.
Though I suppose C++ technically lets you do the same thing with evil pointer arithmetic shenanigans.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Hammerite posted:

I named my street the empty string as a joke and now the postal service sends all the mail with unreadable addresses here, it's blowing in to my garden and making a mess

This actually happened to an American who chose "NULL" as a vanity license plate number. Had something like $5000 in parking tickets mailed to his house

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Xarn posted:

Without a cast, you cannot downcast at all though.

C++ code:
struct Base {};
struct Derived : Base{};

void foo() {
    Base* bptr = nullptr;
    Derived* dptr = nullptr;
    bptr = dptr; // upcasting, always ok
    dptr = bptr; // compilation error
}


It's possible to static_cast or reinterpret_cast a pointer at compile time with no runtime checks at all. You have to explicitly opt in to runtime typechecking by deciding to use dynamic_cast, and it's "slower" so people are likely to skip it out of premature optimisation.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

raminasi posted:

F# (and apparently OCaml as well) has one, but it relies on special-casing within the compiler, which might count as cheating.

Rust has one!

Rust's println! macro basically just calls rust's version of ToString on every argument and then shoves all those into the format string, which AFAIK is a pretty much foolproof way to do printf entirely type-safely in any lang.
(Actually it calls 'fmt', which doesn't return a string but instead writes text to a "formatter" object, I guess like a C++ stream kinda thing? Presumably this helps to avoid creating a million unnecessary strings at runtime. And then there are a bunch of different functions that have to be defined on the type for it to work with the other printf specifiers like printing in binary or hexadecimal.)

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

A 40 minute video about twitter arguments is definitely some kind of horror, but I'm not gonna watch long enough to find out whether there's coding in it.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Tei posted:

Creating custom widgets like scrollbars is a outdated tecnique from the 90's, early 00's. I believe.

Somebody tell the Chrome devs this
They're still handrolling their own scollbars and right click menus instead of using the OS-native ones for some godawful reason

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Hammerite posted:

I don't understand what you're saying here either (why would increasing the amount of tuition students receive result in a lowered graduation rate?) but the conversation has moved on and it was tenuously relevant anyway, so never mind.

You raise tuition to bring in more money, but higher costs mean fewer students can afford it, and enrollment drops.
So you lower the admission barriers to bring in more students and get back up to the old enrollment numbers.
Now the more lax admission process means you have dumber students, and they don't do as well in classes.

At least that's what I think Dumb Lowtax's point was.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆
The only thing you should ever actually write a new variadic function for
is if you're creating a wrapper function around printf for debug logging or whatever.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Ola posted:

If C was made today, I am convinced you could make a type safe, non-variadic "print to console" function that was every bit as a fast as printf. It was a fair mistake made at the time, there is no need to repeat it.
Rust has one, but the compile times are horrendous. Rust's println is implemented as a procedural macro so there's a lot of actual code execution during compile time.
There was a thing where somebody tried to compile a file with 1000 lines of println!("Hello world!"); and a VPS with even 1tb of ram was choking on it.

quote:

Is there not some limit of n for std::tuple<type 1, type 2, type 3 ... type n> in C++?
With a proper variadic template implementation there shouldn't be one. Someone mentioned earlier Microsoft used to just fake it with copy-pasted code for each N from 1 to 10, so it wouldn't work for something larger if you compiled with MSVC.

It's not variadic-related but Rust still does that same thing with methods on char arrays. The language has no support for "length of the array" as a template parameter so they just have all the std lib implementations copy-pasted for "array of 1 character", "array of 2 characters", etc up to 32.

RPATDO_LAMD fucked around with this message at 22:00 on Jun 28, 2020

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Ola posted:

Print to console takes one string argument, the stock tuples go up to 17, boom, done. The world is a better place.

Stock tuples should only go up to 3 or 4
anything longer and you should define an actual named struct or record type or whatever.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Foxfire_ posted:

I was being dumb above; Java gets variadic's of heterogeneous types exactly the same way python does:
- Take all the excess parameters and dump them into a single array of generic objects
- Do a runtime type test when they are accessed and fail then if they're wrong

It abandons static type safety just like the C version (python never had static safety to begin with). C/C++ doesn't have a way to implement the runtime type test and has uglier syntax, but is otherwise the same.

How do Rust/Haskell/etc.. that have static type-safe variadic's work?
I'm a rust newbie but here's my understanding of how it works in Rust:

Every printable type has to implement a function named fmt (inside the Display trait) that writes to a "formatter" object (basically just a character buffer).

At compile time the variadic macro in println!("The cat is {} years old", 7) is transformed by find and replace macro magic into basically something like this (fake code):
And yes, the format string has to be known at compile time.
code:
buf = "The cat is ";
7.printtobuffer(buf);
" years old".printtobuffer(buf);
print(buf);
But with more cleverness to avoid string copying.

So it basically works the same way as C++'s iostream.

RPATDO_LAMD fucked around with this message at 00:06 on Jun 29, 2020

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Space Gopher posted:

Are you arguing against variadic functions in general, or C++'s specific implementation?

In general, they can be a useful way to pass a list of arguments determined at compile time, for something like printf or a logging function. Why copy-paste (and run the risk of errors buried in your pile of almost-but-not-quite identical logic) when you don't have to?

C++'s implementation is ugly because there's no way to express "some type, I don't care what it is" without templates, and that's a common case for variadic functions. Java, C#, and most other modern OO languages handle variadic functions in a clean, type-safe way by just giving you an array of params, that can be of the base object type or anything else you want.

Accepting an array of base-object pointers and attempting to cast them to the appropriate type at runtime sounds like the exact opposite of type-safe.
The only advantage of that over C-style printf is that you get an actual exception when it fails at runtime instead of garbage data or a crash.

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Vanadium posted:

imo, if you can't call your thing Foo because there's already a Foo, you should just call it Foo_ and own the fact that there is a name collision instead of trying to obfuscate it by coming up with new taxonomies for different roles of classes or w/e.

The fact that the Butt class and ButtType enum have the same name isn't a coincidence.
ButtType is deeply tied to Butts. Each instance of a Butt will have one of several ButtTypes, which other code will look at to change its behavior (like the display code choosing a different description string for the Butt).

RPATDO_LAMD fucked around with this message at 22:37 on Jul 14, 2020

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

fourwood posted:

What if it were, and I’m just spitballing here, Butt::Type.

yeah that's better

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Dijkstracula posted:

I'm increasingly convinced that the world decided python was a good teaching language because somebody (rightfully) got tired of making first-year students memorise "public, static, void, main, paren, String, args, bracket, bracket paren" without understanding it, and (wrongly) not realising that complexity is just getting pushed around

needing to put all your code inside a class and an object is a coding horror all on its own though

give those kids a good old fashioned int main() and then force them to grind their faces against pointers and malloc/free until they understand the difference between values and references. it builds character!
oop is terrible for learning, analogies to realworld nouns are awful when you don't understand what's even being analogized. (and realworld nouns aren't good oop anyways)
so is duck typing tbh. don't trust kids with a dynamic type system until they've wallowed in enough C to understand that the types still exist under the hood in python

Soricidus posted:

I guess the question is “why does for…in take an arbitrary lvalue”. What use cases are there for binding anything other than an identifier or a tuple of identifiers, like we all probably assumed it did until we read that post?
im gonna guess "ease of implementation" is the main/only reason for this working the way it does

Adbot
ADBOT LOVES YOU

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

Hammerite posted:

It's also something you see in other languages that have a similar object-reference model to Python. For example in C#

code:
var L = Enumerable.Repeat(new [] {1, 2, 3}, 3).ToArray();
L[0][0] = 99;
string s = "[" + string.Join("], [", L.Select(a => string.Join(", ", a))) + "]";
Console.WriteLine(s); // [99, 2, 3], [99, 2, 3], [99, 2, 3]
It's not accurate to call this "an array of arrays that reference each other". It's an array containing three references to a single object, which happens to be another array. Since there is only one inner array it doesn't make sense to say that there are multiple objects that "reference each other". To the extent that it could be taken to mean that the multiply-referenced array is self-referential, it is a false statement; neither the outer nor the inner array is self-referential.

In C# you must explicitly use the new keyword so it's obvious you're playing with references and not values.

The big problem is when 'friendly' languages like Python hide all that stuff so without a deeper knowledge of the language you actually have no clue whether you're holding a reference or a copy or what until you try to mutate it and see what breaks.

Basically,

Hammerite posted:

at the end of the day if you don't understand how object references work in your language it will generate plenty of surprises for you
but Python makes it a lot harder to understand how references work than C# does.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply