ID:2177843
 
Applies to:DM Language
Status: Open

Issue hasn't been assigned a status value.
What is this?


datum/testlist
var/mylist = list()
var/datum/mydatum = new()
var/obj/myobj = new()
mob
verb/testlistfuckary()
holy_jesus___what_is_that___what_the_fuck_is_that(/datum/testlist)

proc/holy_jesus___what_is_that___what_the_fuck_is_that(var/T)
var/list/L = list(T = 1)

for (var/key in L)
world << "[key] = [L[key]]"


The output should be "/datum/testlist = 1"

But it's "T = 1"

This is supposedly an intended feature, so i can't make a bug report on it, so I'll do the next best, request it be removed as a feature because GOD DAMN i wasted too much time debugging this oddity.
I'd imagine removing it would break existing projects that rely on it, as changing any intended behavior would, it would need to be optional somehow.
I think the better choice would to just not use the list instruction for a single thing;

L[T] = 1


but either way, there's already a bug report posted for this with backing from Lummy.

http://www.byond.com/forum/?post=1623440
I say lummox makes using it a warning in 512, then removes it flat out in 513, so we can be done with it.

If he must, he could make a new proc, object() that does this, since this kind of behavior is akin to javascript objects.

It's not like this is the first time a change has broken games. Every new major version has lead to /tg/station having to change SOMETHING about our code, we have processes in place for it by now, that its not really something we can feel empathy for.
But, why even use the list() instruction for this purpose? This has been list()'s documented behavior forever.

Alternatives include:
L[T] = 1


proc/n(t)
. = t

mob/verb/test(T as text)
var/d = list(n(T) = 1)
world << json_encode(d)

mob/verb/test2(T as text)
var/d = list(pick(T) = 1)
world << json_encode(d)
I've been coding in byond for 3 years and this is the first i'm hearing about it.

This is also one of the few languages I've seen where this is a "feature". In javascript you at least have to use {} to make it an object, so that the parser knows not to mix in scope vars with object names.

Alot of our coders come from other languages, and they will always look for analogs for concepts they already know, and every language has a proc that takes a variable number of arguments, and makes an array/list like thing, and they all take and treat associated shit the same way.

Byond that, list's OBSERVED behavior, is that list("keystring" = value_var) works, why would anybody assume the reverse doesn't. In languages, an expression is an expression is an expression. if you can put a string somewhere, you can put a variable holding a string there as well. list is the only place in all of byond where a keyword can get converted to a string, why would anybody assume anything different?

Like ya, it's documented, but it's not expected, and it causes silent bugs and no amount of minor simi-crypted snippets are gonna change those facts.
In response to MrStonedOne
I don't understand. It's documented, so it should be expected. It's entirely your fault that it's unexpected. You can't blame the documentation for not smacking you in the face with everything you failed to notice.
In response to Kaiochao
I would agree, if list() wasn't so simple you can skim over it in 5 seconds because the part where it actually uses this "feature" is in an example at the bottom of the entry for it.

Because it's documented doesn't mean it should, and not expecting this behavior is extremely logical, considering that's how it works in any sane language.
Perhaps the best middle ground would be to make {} use this syntax, (like in other languages) and () use the sane normal way of doing this. (or make object())
The known syntax for all argument lists is that they're a comma-separated sequence of "value" or "parameter = value".

The list() proc is special because it accepts strings as parameters (something you learn when you first learn lists), and it treats missing parameters as new string parameters (also should have been clear when you first learned lists).

No proc lets you pass a named argument in the form "value = value".
In response to Kaiochao
Yet you just shot yourself in the foot, because if list() is special and doesn't play by the rules, why can't it do the same for keywords without string?
In response to PJB3005
If you learn that list() is special without learning how it is special, you've shot yourself in the foot.
Issue is, it's extremely common to see list("x" = "test") in other code and such, and if you're not aware of the exact way list works, it's extremely easy to assume that it'll accept variables instead of strings too.
There is no reason for this to be a thing, period.
In response to PJB3005
PJB3005 wrote:
Issue is, it's extremely common to see list("x" = "test") in other code and such, and if you're not aware of the exact way list works, it's extremely easy to assume that it'll accept variables instead of strings too.

/thread
I think rather than out-right change the behavior, Lummox had already mentioned a solution in the topic I linked earlier: "that when the var name is available in scope, it's worth using the var contents as the key instead of the name. This is probably compile-time behavior."

This would not be a breaking change, unless really wrote their code in a really odd way.

That would then solve two other existing (but deferred bug reports) as well
http://www.byond.com/forum/?post=706546
http://www.byond.com/forum/?post=1393390
And then if you mistype the variable name the compiler will not throw any errors or warnings and your code still wouldn't work as intended.

It should just be removed.
Also, would just lead to issues where either global vars conflict, or global vars are ignored but coders don't know or expect that and we come full circle

I already ruled that out before i even found that post, it can't work because either global vars cause too many conflicts, or it's limited to proc scope and you just cause more confusion.

I don't make the suggestion of removal lightly, but it is the only way.
I've been reading over the posts in this and mulling over what to do. A lot may depend of course on what options I have in the compiler code--as in how much context it has.

I know the reason this behavior exists is because of named argument lists. But I do think it makes sense that this behavior should not apply to list(), only to arglist() and of course to implicit arglist() cases. And I suspect changing list() would not break any existing code.

So the big question is what options the compiler gives me as far as knowing context. It seems likely that I'll have a way of knowing if list() has been specified.
Using variables with the same name as a key in a list isn't exactly something I'd write off as being an uncommon use case. Of course using strings is fine and I've never not done that but I'm sure others will.
Page: 1 2