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
Cybernetic Vermin
Apr 18, 2005

VikingofRock posted:

defining a function within a function

it really is weird how this relatively simplistic and easy to understand feature ended up not being more standard in mainstream languages, encourages breaking pieces of functionality apart while keeping the namespace easy to navigate

Adbot
ADBOT LOVES YOU

fritz
Jul 26, 2003

Cybernetic Vermin posted:

it really is weird how this relatively simplistic and easy to understand feature ended up not being more standard in mainstream languages, encourages breaking pieces of functionality apart while keeping the namespace easy to navigate

now imagine it in the hands of academics

Bloody
Mar 3, 2013

matlab is extremely bad

VikingofRock
Aug 24, 2008




So I've never really run into a use case for fully heterogenous lists. When do people use them? I'm assuming there must be some use case since so many weaker-typed languages tote them as features.

leftist heap
Feb 28, 2013

Fun Shoe

Cybernetic Vermin posted:

it really is weird how this relatively simplistic and easy to understand feature ended up not being more standard in mainstream languages, encourages breaking pieces of functionality apart while keeping the namespace easy to navigate

it's not that great man. the namespace thing is a non issue in any lang that has an actual package/module system anyway? i really don't see nested function defs as some killer feature

VikingofRock
Aug 24, 2008




fritz posted:

now imagine it in the hands of academics

Python has caught on in astronomy, even among the older people. Mostly they just don't use nested functions.

distortion park
Apr 25, 2011


VikingofRock posted:

So I've never really run into a use case for fully heterogenous lists. When do people use them? I'm assuming there must be some use case since so many weaker-typed languages tote them as features.

I tried to think if an good example but none qualified as a "good" use case. I suppose you could pattern match against the type to determine behaviour? Otherwise you're just using an implicit interface

e: and even then you've really just got a homogeneous list of "object"

VikingofRock
Aug 24, 2008




leftist heap posted:

it's not that great man. the namespace thing is a non issue in any lang that has an actual package/module system anyway? i really don't see nested function defs as some killer feature

Nested functions are often equivalent to closures, which are super useful. I'm writing some fairly generic code in C right now, and it sucks having to pass around (foo)(*function)(bar, void *) for a pointer to a function which takes a bar and maybe some other stuff as input and returns a foo (admittedly maybe there's a better way to do that though).

leftist heap
Feb 28, 2013

Fun Shoe
java basically had heterogenous lists before 1.5 and it sucked really hard. imagine a boot casting an object to an interface forever

leftist heap
Feb 28, 2013

Fun Shoe
maybe i'm prejudiced against nested functions because python weenies in particular seem to have hardons for it. or maybe i've just been in java world too long

VikingofRock
Aug 24, 2008




leftist heap posted:

imagine a boot casting an object to an interface forever

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



VikingofRock posted:

Nested functions are often equivalent to closures, which are super useful. I'm writing some fairly generic code in C right now, and it sucks having to pass around (foo)(*function)(bar, void *) for a pointer to a function which takes a bar and maybe some other stuff as input and returns a foo (admittedly maybe there's a better way to do that though).

something like this??

code:
typedef (foo)(*functionPointerType)(bar, void *);

void poop(functionPointerType a, functionPointerType b, int c) { ... }

functionPointerType piss(int a) { ... }
and then call it a real name instead of functionPointerType obvs

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

VikingofRock posted:

So I've never really run into a use case for fully heterogenous lists. When do people use them? I'm assuming there must be some use case since so many weaker-typed languages tote them as features.

scheme programmers like to use heterogeneous lists as an ad-hoc record type. i consider this an argument against them.

i've basically never wanted heterogeneous lists in a language that doesn't have them. i guess i might have used a std::vector<boost::any> once? i don't think it survived to the final version of the code though

VikingofRock
Aug 24, 2008




Oh yeah it wasn't the verbosity I was complaining about. It's just an awkward thing to work with compared to a closure.

MononcQc
May 29, 2007

VikingofRock posted:

So I've never really run into a use case for fully heterogenous lists. When do people use them? I'm assuming there must be some use case since so many weaker-typed languages tote them as features.

Options/configs for something. Imagine that instead of going with binary flags you can pass in [read, write, {encoding, "utf-8"}, {buffer, Size::Int, Delay::Int}] as a list of config options. Makes for readable stuff.

It's nice because you can use similar stuff for TCP sockets like [raw, keep_alive, whatever] and merge that list with SSL options like [{private_key, "some data"}, {cipher_suites, ["AES-...", "ECDHA-..."]}, {sni_hostname, "example.org"}, ...] and have it work together. I guess you would enumerate all the possible combinations in your type signature if you really wanted to, you're just not forced to do it in a dynamic lang.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

MononcQc posted:

Options/configs for something. Imagine that instead of going with binary flags you can pass in [read, write, {encoding, "utf-8"}, {buffer, Size::Int, Delay::Int}] as a list of config options. Makes for readable stuff.

It's nice because you can use similar stuff for TCP sockets like [raw, keep_alive, whatever] and merge that list with SSL options like [{private_key, "some data"}, {cipher_suites, ["AES-...", "ECDHA-..."]}, {sni_hostname, "example.org"}, ...] and have it work together. I guess you would enumerate all the possible combinations in your type signature if you really wanted to, you're just not forced to do it in a dynamic lang.

a list of key-value pairs is just a lovely dictionary. i think there's plenty of obvious use-cases for a dictionary with heterogeneous values.

qntm
Jun 17, 2009

Plorkyeran posted:

a dictionary with heterogeneous values

you mean like

an object?

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today
Heterogeneous anything usually only makes sense if you pretend algebraic datatypes don't exist.

MononcQc posted:

It's nice because you can use similar stuff for TCP sockets like [raw, keep_alive, whatever] and merge that list with SSL options like [{private_key, "some data"}, {cipher_suites, ["AES-...", "ECDHA-..."]}, {sni_hostname, "example.org"}, ...] and have it work together. I guess you would enumerate all the possible combinations in your type signature if you really wanted to, you're just not forced to do it in a dynamic lang.
I'm not sure why you wouldn't always prefer this stuff to be statically checked. Vulkan pervasively uses options structs like this in C of all places and it works great. If a better version of your API can be expressed in C you're not accomplishing very much.

Captain Foo
May 11, 2004

we vibin'
we slidin'
we breathin'
we dyin'

leftist heap posted:

imagine a boot casting an object to an interface forever

thread title please

MononcQc
May 29, 2007

Plorkyeran posted:

a list of key-value pairs is just a lovely dictionary. i think there's plenty of obvious use-cases for a dictionary with heterogeneous values.

You have single values, some pairs, some that are triple, and some that are nested structures. You can fit them into a key-value structure if you really must, but that's because you'd have no better way of expressing things. A hash map also has no concept of ordering in cases where that might be important.

MononcQc
May 29, 2007

Ralith posted:

Heterogeneous anything usually only makes sense if you pretend algebraic datatypes don't exist.

I'm not sure why you wouldn't always prefer this stuff to be statically checked. Vulkan pervasively uses options structs like this in C of all places and it works great. If a better version of your API can be expressed in C you're not accomplishing very much.

Yeah I don't know. Whenever I use these I also add type annotations for Dialyzer to catch up. The types are just not necessary to make it work, and not all type systems are necessarily nifty enough to allow that without problem, or to encode all constraints properly (i.e. you probably can't have a file that is both using 'raw' encoding and a 'utf8' encoding at once, but encoding that in the type system is often not doable and still requires external logic anyway)

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

MononcQc posted:

The types are just not necessary to make it work, and not all type systems are necessarily nifty enough to allow that without problem, or to encode all constraints properly (i.e. you probably can't have a file that is both using 'raw' encoding and a 'utf8' encoding at once, but encoding that in the type system is often not doable and still requires external logic anyway)
If your type system is that much less expressive than C's I don't think it gets to be called a type system anymore.

MononcQc
May 29, 2007

Ralith posted:

If your type system is that much less expressive than C's I don't think it gets to be called a type system anymore.

tell me more about that type system of yours that can support multiple disjoint options together but forbid specific combinations of them exclusively.

E: example, I can configure an SSL client to use either the option '{private_key, Blob}', or '{private_key_file, Path}', and if either is used, so must be the option '{private_key_pass, Password}', but you also cannot both have 'private_key' and 'private_key_file' options specified at once. How do you express that in C's type system in a non-cumbersome way to use?

MononcQc fucked around with this message at 19:07 on Jun 9, 2016

weird
Jun 4, 2012

by zen death robot

VikingofRock posted:

So I've never really run into a use case for fully heterogenous lists. When do people use them? I'm assuming there must be some use case since so many weaker-typed languages tote them as features.

they're nice for things like (elt "foo" 0)

Dr Monkeysee
Oct 11, 2002

just a fox like a hundred thousand others
Nap Ghost

VikingofRock posted:

Oh yeah it wasn't the verbosity I was complaining about. It's just an awkward thing to work with compared to a closure.

the one killer feature i wish for in c are type-checked typedefs instead of just aliases. that's how everyone wants to use them anyway.

Dr Monkeysee fucked around with this message at 20:17 on Jun 9, 2016

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

MononcQc posted:

tell me more about that type system of yours that can support multiple disjoint options together but forbid specific combinations of them exclusively.

E: example, I can configure an SSL client to use either the option '{private_key, Blob}', or '{private_key_file, Path}', and if either is used, so must be the option '{private_key_pass, Password}', but you also cannot both have 'private_key' and 'private_key_file' options specified at once. How do you express that in C's type system in a non-cumbersome way to use?
That's different than your original example, but:
code:
enum key_type { KEY_DATA, KEY_PATH };
struct key { key_type type; const char *value; size_t value_len; const char *password; };
foo((struct key){.type = KEY_PATH, .value = "foo", .value_len = 3, .password = "bar" });
Of course it's easy to come up with more heterogeneous examples, and this specific case would be better served by only taking the data and leaving the IO to the user, but this sort of problem is easily solved in general by algebraic datatypes. Encoding those in C isn't always that convenient, but it's not much worse than the ad-hoc heterogeneous list you're describing, and any half-decent modern PL (even C++17!) can do far better statically.

Ralith fucked around with this message at 20:22 on Jun 9, 2016

VikingofRock
Aug 24, 2008




Dr Monkeysee posted:

the one killer feature i wish for in c are type-checked typedefs instead of just aliases. that's how everyone wants to use them anyway.

What do you mean by this?

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

VikingofRock posted:

What do you mean by this?
He wants
code:
typedef int thing;
int foo = 42;
thing bar = foo;
to produce a type error, but that can be easily accomplished by wrapping it in a struct.

MononcQc
May 29, 2007

Ralith posted:

That's different than your original example, but:
code:
enum key_type { KEY_DATA, KEY_PATH };
struct key { key_type type; const char *value; size_t value_len; const char *password; };
foo((struct key){.type = KEY_PATH, .value = "foo", .value_len = 3, .password = "bar" });
Of course it's easy to come up with more heterogeneous examples, and this specific case would be better served by only taking the data and leaving the IO to the user, but this sort of problem is easily solved in general by algebraic datatypes. Encoding those in C isn't always that convenient, but it's not much worse than the ad-hoc heterogeneous list you're describing, and any half-decent modern PL (even C++17!) can do far better statically.

That solution doesn't keep me from submitting the two variations of that struct in a single linked list for example, which is kind of important when we're talking of mixed types containers. The enforcement of that is still left to the runtime.

JewKiller 3000
Nov 28, 2006

by Lowtax
a fully heterogeneous list is completely useless
if the position of the elements is fixed and you determine their types that way, you have a tuple, not a list
otherwise, you must have some tag on each item that you check to tell what it is, so use an algebraic datatype like Ralith said, and now it's a homogeneous list
"but i don't want to write a type that enumerates all my cases" is not really an argument when type inference is a thing

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

MononcQc posted:

That solution doesn't keep me from submitting the two variations of that struct in a single linked list for example, which is kind of important when we're talking of mixed types containers. The enforcement of that is still left to the runtime.
Why are you putting sub-components of your SSL client configuration in linked lists??? :psyduck:
The point is heterogeneously typed containers are pretty much always the wrong solution.

JewKiller 3000 posted:

"but i don't want to write a type that enumerates all my cases" is not really an argument when type inference is a thing
Writing a type to cover all the cases of something is a good way to verify and formalize your understanding of a value space, anyway.

Ralith fucked around with this message at 20:56 on Jun 9, 2016

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

MononcQc posted:

That solution doesn't keep me from submitting the two variations of that struct in a single linked list for example, which is kind of important when we're talking of mixed types containers. The enforcement of that is still left to the runtime.

which is why you use an options struct which only has a single struct key field rather than a stupid linked list that lets you express all sorts of nonsense

distortion park
Apr 25, 2011


MononcQc posted:

tell me more about that type system of yours that can support multiple disjoint options together but forbid specific combinations of them exclusively.

E: example, I can configure an SSL client to use either the option '{private_key, Blob}', or '{private_key_file, Path}', and if either is used, so must be the option '{private_key_pass, Password}', but you also cannot both have 'private_key' and 'private_key_file' options specified at once. How do you express that in C's type system in a non-cumbersome way to use?

Really sounds like an argument for OOP rather than untyped lists with surprise additional requirements. Even a dictionary with nullable entries would be better.

Ralith
Jan 12, 2011

I see a ship in the harbor
I can and shall obey
But if it wasn't for your misfortune
I'd be a heavenly person today

pointsofdata posted:

Really sounds like an argument for OOP rather than untyped lists with surprise additional requirements. Even a dictionary with nullable entries would be better.
Any kind of record type at all, really. If anything this is a great case-in-point of how pointlessly complicated trying to safely represent complex structured data with dynamic types is.

MononcQc
May 29, 2007

Y'all my point is not that it is impossible to do it any other way, but that this flexible format is way harder to replicate through a type system but absolutely dead simple to represent in any loving dynamic language out there. To properly replicate the kind of semantics you can have with such an option list you tend to usually defer a part or all of its enforcement to user-written code and the runtime and it cannot be fully represented into the type system unless you're able to do fancy rear end constraints you would see in probably Haskell compiler extensions, agda, or some other similar language.

I'm not saying there's no equivalence, nor that there is no gain in getting the compiler to do part of the work; there's plenty. But you've all spent half a dozen post with various recommendations somewhat reminding me of the "how do you do a list in XML" debate while dynamic language people have just written their loving list and moved on a page ago.

The countdown is set until the discussion devolves into the bob harper argument about all dynamic languages being in fact unityped and a rehash of the same idiotic debate that has been had 500 times on who has the cleverest way to frame their viewpoint to prove that what they will keep doing anyway is right.

Dr Monkeysee
Oct 11, 2002

just a fox like a hundred thousand others
Nap Ghost

Ralith posted:

He wants
code:
typedef int thing;
int foo = 42;
thing bar = foo;
to produce a type error, but that can be easily accomplished by wrapping it in a struct.

easily but not elegantly. wrapping all your types in a struct is awkward and obscures your intent. like, size_t has deliberate semantics beyond "an unsigned integer of a certain size" and it's annoying that if i write a function that takes a size_t it'll also blindly accept a uint64_t or a long long or whatever (even aside from the fact that it'll accept *different* types on a different architecture).

if i say i take a size_t then i should *only* accept a size_t. and if you need to punch through the type system that's what casts are for.

Dr Monkeysee fucked around with this message at 21:08 on Jun 9, 2016

Dr Monkeysee
Oct 11, 2002

just a fox like a hundred thousand others
Nap Ghost
i suppose this goes back to what someone said earlier that c is almost entirely about describing the mechanics of what the computer is doing instead of the meaning of what the programmer intent is but strongly-typed typedefs seems like not much to ask.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

MononcQc posted:

Y'all my point is not that it is impossible to do it any other way, but that this flexible format is way harder to replicate through a type system but absolutely dead simple to represent in any loving dynamic language out there.

but you've done the exact opposite? you've taken something that's trivial even with a lovely type system like C's and shown that you can do it in a much more error prone and not any simpler way in a dynamic language

if we don't have record types then we need heterogeneous lists so that we can fake them is not a very compelling argument that heterogeneous lists are a good thing

Bloody
Mar 3, 2013

i still dont even understand the use case presented

Adbot
ADBOT LOVES YOU

MononcQc
May 29, 2007

Plorkyeran posted:

but you've done the exact opposite? you've taken something that's trivial even with a lovely type system like C's and shown that you can do it in a much more error prone and not any simpler way in a dynamic language

if we don't have record types then we need heterogeneous lists so that we can fake them is not a very compelling argument that heterogeneous lists are a good thing

Record types can coexist there. The idea is just that for some configs (which was a random example), it's much simpler to go [a, b, {c, value}, {d, something, other}] and then doing a runtime check on the values format that declare 4 types of records and then the list union and then still need to go over it at runtime to ensure the conditions are respected (i.e. you can't set b and c at the same time, but individually they're fine).

In both cases, you'll end up with manual validation and hopefully a test to confirm it and what your type system has saved you is from a typo going 'oh shoot I entered p instead of b!'

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