News for hackers. Stuff that matters.
Re:Things I Was Wrong About: Types by tluyben2 on Sunday September 27, 2020 @05:00AM (#24605237)
What are you working on though? What algorithmic structure?
Re:Things I Was Wrong About: Types by TooCreative on Sunday September 27, 2020 @07:26AM (#24605838)
Compare this:

    private static function request(?string $method, ?string $url, array $options): array
    {
        ...
    }
To this:

    function request($method, $url, $options)
    {
        ...
    }
I can grasp the latter much better. It immediately forms a structure in my head that I will remember while I read other parts of the code. To do the same with the former, I think my brain uses up twice the energy or more. And even then, I will not have such a good grasp on it as with the former.
Re:Things I Was Wrong About: Types by viraptor on Sunday September 27, 2020 @08:35AM (#24606179)
You're showing an example of a function signature in a specific language, not an example of typing though. These are related but not exactly the same.

For example here is a Ruby version, very dynamic:

    def request(method, url, **options)
    end
    request("get", "http...", foo: "bar")
And here is a completely statically typed Crystal version:

    def request(method, url, **options)
    end
    request("get", "http...", foo: "bar")
The argument types are inferred automatically from the usage and mismatched usage will be caught at compile time. And in the second case the ide can still tell you the types in the signature if you want to know them.

In the third example, here's completely dynamic python:

    def request(method: str, url: str, **options): Dict[...]
No type checking happens here in the language itself.

So what I'm getting at is - if you don't like languages with verbose explicit type signatures, it doesn't mean you don't like static types.

Re:Things I Was Wrong About: Types by nyanpasu64 on Sunday September 27, 2020 @08:07PM (#24611399)
Nitpick: It's -> Dict[...]. Colons begin a function body.
Re:Things I Was Wrong About: Types by unrealhoang on Sunday September 27, 2020 @08:04AM (#24605997)
Counter point: with the former, I know exactly how to use it: for item in request(“get”, “google.com”, []) { .... } Whereas if there’s no example for the latter, I’d have to read the code of that function (or sometime the code of the functions it called) to know how to use correctly.
Re:Things I Was Wrong About: Types by TooCreative on Sunday September 27, 2020 @08:16AM (#24606072)
Wishful thinking.

You know it returns an array, but you don't know what the array contains. So you don't know how to use it.

You still need to look into the code to see what it returns. Then you will see that it returns an array and what the array contains.

And now you had to process the information that it returns an array twice. Once in the function definition and once in the function body.

Re:Things I Was Wrong About: Types by castwide on Sunday September 27, 2020 @09:04AM (#24606333)
> You know it returns an array, but you don't know what the array contains. So you don't know how to use it.

That's a limitation of your specific example, not type systems in general.

Re:Things I Was Wrong About: Types by TooCreative on Sunday September 27, 2020 @11:01AM (#24607125)
For the example I took a random line from Symfony and shortened it a bit:

https://github.com/symfony/http-client/blob/master/HttpClien...

You are free to link to some other example.

Re:Things I Was Wrong About: Types by castwide on Sunday September 27, 2020 @12:25PM (#24607816)
Any example where the type is defined as something more specific than an array (especially in PHP, where the `array` type doesn't even differentiate between numerically indexed arrays and dictionaries).

Regardless, I still think the type hints in Symfony's version are better than nothing. It's also worth noting that `private static` is concerned with scope, not types.

Re:Things I Was Wrong About: Types by unrealhoang on Sunday September 27, 2020 @10:23AM (#24606841)
Heck, not only I don't have to look at the code, with proper IDE setup, I even don't have to go to the documentation page, just `item.` and my IDE/editor will present me with the list of things that are applicable to my item.

And that's only the response part of the usage, there's absolutely no way for me to know if the method is an enum/constant or is it a string without looking into the code for dynamic typing, and again, sometime N-level deep to get enough information of "what to pass to this function so it will work".

Re:Things I Was Wrong About: Types by mplanchard on Sunday September 27, 2020 @09:56AM (#24606626)
Most type systems also provide information about what’s in the array, like Array<String> or int[]
Re:Things I Was Wrong About: Types by TooCreative on Sunday September 27, 2020 @10:54AM (#24607068)
That is just another piece of metadata. But it does not help either. Now you know you get an array of strings. But you still don't know what is inside of the strings.

It might be ['headers'=>'...','body'=>'...' ] or ['status'=>'...','response'=>'...'] or god knows what.

And you are back to reading the function body.

Re:Things I Was Wrong About: Types by mplanchard on Sunday September 27, 2020 @11:11AM (#24607193)
Is that like a hashed array you’re implying? In that case, the type wouldn’t be string anyway, but something like HashMap, Object, Dict, etc. More commonly though, something like HTTP options would be its own type, with defined properties, which you could browse via autocomplete or your IDE’s hover/peek functionality. That type would then specify the types of its values, so you can be certain that options.status is an integer, for example.

You’d generally only use an otherwise untyped array of strings when you can’t know beforehand what their values can be.

Re:Things I Was Wrong About: Types by jenscow on Sunday September 27, 2020 @09:51AM (#24606609)
A better example for a typed function would be something like:

    function Request(string method, string url, RequestOptions options) : Result {...}
or

    Result Request(string method, string url, RequestOptions options) {...}

Here, we know `url` is a string (rather than the parsed object), we know all the supported options (they're members of the RequestOptions object/enum), and every value in the return value. Some might suggest even making `method` an enumeration.

If the function name was better, you could call that function right now without needing any more information.

Also, especially if you're a fan of defensive programming, most of the basic argument checking is performed at compile time, leaving the function body cleaner.

Based on your example alone, perhaps you don't have enough experience with typed languages to appreciate the benefits. I don't mean that in a belittling way, but more of an invitation to learn more about the craft.

Re:Things I Was Wrong About: Types by TooCreative on Sunday September 27, 2020 @10:58AM (#24607104)
For the example I simply took to a random, recently updated file from Symfony:

https://github.com/symfony/http-client/blob/master/HttpClien...

And shortened it a bit. In the real example, as you can see, there are even more parameters, making it even harder to read.

Re:Things I Was Wrong About: Types by jenscow on Sunday September 27, 2020 @11:43AM (#24607467)
Well, for me it's easier - perhaps because I'm used to reading parameters in type+name pairs.

The data type is right next to the parameter name - and it will be in the pop-up provided by my IDE when I use the function... I don't need to look at the docs or comment (which may not exist).

Re:Things I Was Wrong About: Types by tluyben2 on Sunday September 27, 2020 @08:52AM (#24606265)
Got that, but was triggered by ‘algorithmic structure’; that sounds a tad ‘over the top’ when you then come with some basic web request.

However, I would not call your example particularly well typed. Array is still basically untyped.

When I talk about types I mean things like;

     Either<Error,Group> AddGroup(string GroupName, User[]? users)
In this case I know what I am getting and I know the users are already, when reaching the webserver, deserialized, validated (or the type would reject them and produce an error and I know I am getting an actual Group back.

in your case that would be;

      function AddGroup(GroupName, Users)
I have no idea how that is better or clearer or less work to write? No idea what it returns; Users probably is an array of users, but is it? Or is it a typo? And I need to validate whatever comes in.

You can add docs but I do that still with the typed version (although thats automated mostly unless I need to explain something).

Worse as well is that when I have this:

      function AddGroup(GroupName, Users)
      function AddGroups(GroupNames, Users)
Now i'm completely lost. I'm not even sure these users as input are the same things? Both arrays? Both the same User 'things'? Output?

But yes, in php I write typeless mostly too (although I luckily do not have to touch it much anymore) as the types mostly suck. But in more advanced type systems, the types will tell you a lot/all about the input/output, so you can do without a lot of docs and trying things out can be automated; as we know the precise input so some generator can generate example input that will immediately work; like swagger on speed.

Etc. But agreed, your example does not benefit too much from typing, however I would define Option[] as something precise than just a void* and hope for the best. Also Method and URL so I know invalid input for those very well defined things cannot be violated.

So your example:

    private static function request(Method $method, URL $url, Option[]? $options): WebResult
would clear up a lot for me. Now, for instance, I can see, and not guess, that you are answering a web request instead of some request with confusingly similar names to webrequests.

But how about some more 'concrete' examples; 'request' is rather a low level / abstract thing (I hope...). But your business logic would contain more concrete functions; any examples from those that are similarly badly geared to types?

Re:Things I Was Wrong About: Types by TooCreative on Sunday September 27, 2020 @11:10AM (#24607190)
And now instead of

    $body = Http::request('GET', 'https://example.com')['body'];
You have to do this?

    $body = Http::request(new Method('GET'), new URL('https://example.com'))->body;
And you have cuttered the global namespace with "Method", "URL" and "Option"?
Re:Things I Was Wrong About: Types by tluyben2 on Sunday September 27, 2020 @11:41AM (#24607447)
Why would they be in the global namespace? They would be in imported namespaces (something\Http for instance). That's rather normal.

And yes, now you have to make sure you are passing the proper and valid types, which is obviously the goal here:

    $body = Http::request(Method.GET, URL.Parse('https://example.com'))->body;
In other languages you can make it so that the static URL is validated at compile time even.
Re:Things I Was Wrong About: Types by TooCreative on Sunday September 27, 2020 @12:06PM (#24607669)
For that to work, you have to import those explicitly:

    use something\Http;
    use something\Http\Method;
    use something\Http\URL;
    $body = Http::request(Method.GET, URL.Parse('https://example.com'))->body;
Now you have a bunch of lines instead of one. And have "Method" and "URL" in your current scope.

And all of that instead of this beauty:

    $body = Http:request('GET', 'https://example.com')['body'];
Re:Things I Was Wrong About: Types by tluyben2 on Sunday September 27, 2020 @12:50PM (#24608003)
Beauty is in the eye of the beholder, however we were not talking about verboseness vs terseness though.

You can make anything terse with stringy types and you indeed seem to favour that, however, this was about how types change readability and brittleness. This is all easier to read by people who do not know what request() does => request is not a good example, but it still stands. In your case, you have no case what $method or $url are supposed to be; you can do;

    $body = Http:request('rabbit', 'cracker')['body'];
I assume something in Symfony catches that, but I cannot see it from the signature at all, and the validation error is, in my opinion (obviously) in the wrong place; it should be at the call site because that's where you are creating the erroneous input so that's where I want to be lead to.
Re:Things I Was Wrong About: Types by sktguha on Sunday September 27, 2020 @03:55PM (#24609647)
you could possible write an IDE plugin that hides the types information and only show them on hover etc. I don't think this reason is that strong of a point IMHO.