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
Jigsaw
Aug 14, 2008
^^^ beaten

hyphz posted:

Looking over a student's Python code, and see this:

code:
for mylist[1] in mylist:
  print(mylist)
I think I double-taked at that. That can't even parse, right? Even the peer assistant had written "I have no idea how this would be interpreted."

Shockingly, it does parse and run. I pop open a Python REPL and try a few horrors.

code:
>>> test = {"holy": "crap", "you're": "kidding"}
>>> for test["holy"] in test: print(test)

{'holy': 'holy', "you're": 'kidding'}
{'holy': "you're", "you're": 'kidding'}
code:
>>> lista = [1,2,3,4]
>>> listb = [0,0,0,0]
>>> x = 0
>>> for lista[x] in listb: x+=1
>>> lista
[0, 0, 0, 0]
code:
lista=[1,2,3,4,5,6,7]
listb=[0,0,0,0,0,0,0]
import random
for listb[random.randint(0,6)] in lista: pass

listb
[7, 6, 1, 0, 4, 0, 2]
Now, ok, I get that these all make sense if they are unwound into terribly written C for statements but still. A bit of faith in Python as a teaching language just died.

Well, trying to parse this out has taught me something about how Python assigns variables in for loops so that’s something. It’s dumb as hell to actually do it but not really senseless in what it’s doing.

If I’m understanding right, it’s just setting the x variable in for x in y to each y as it goes through the loop. So when you’re iterating through the dictionary, this is going through the keys, and setting test["holy"] to "holy" and then "you're", which is what prints (and likewise for the lists). Everything gets modified in place because Python passes by reference.

I guess you could avoid this behavior if Python passed by value rather than by reference, or kept the x variable local to the for loop, but otherwise I don’t see why it should fail to parse and run (though no one should ever actually do this, of course).

Adbot
ADBOT LOVES YOU

ultrafilter
Aug 23, 2007

It's okay if you have any questions.


So there really is more than one way to do it?

hyphz
Aug 5, 2003

Number 1 Nerd Tear Farmer 2022.

Keep it up, champ.

Also you're a skeleton warrior now. Kree.
Unlockable Ben
So I looked at this again and suddenly thought, hang on, if you can just change the identity of the loop control variable like that then there must be a hidden loop control value somewhere that actually tracks the position in the list. And of course there is, it's the status of the iterator created by the for loop. Which means that you can do:

code:
>>> for x in range(5): print(x); x=1; print(x)
0
1
1
1
2
1
3
1
4
1

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

More because if you've had students putting stuff in classes without learning what they are, then they get deeply confused when they do learn them. But this is partly because so many courses want to teach OO using janky physical metaphors like "This desk is an object, this other desk is an object, they are both of class desk, they are different instances.." etc instead of admitting it's just type strengthening and syntactic sugar for overloaded function calls.

Soricidus
Oct 21, 2010
freedom-hating statist shill

Jigsaw posted:

otherwise I don’t see why it should fail to parse and run

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?

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

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

RPATDO_LAMD posted:

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

...

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)
strong agree - the freshman CS class I TAed as a Msc student used the How To Design Programs curriculum which was taught in a subset of Racket, and it worked so much better both in terms of students being taught "the entirety of the language" and said language being scoped down enough to avoid weird unintentional complexity issues

QuarkJets
Sep 8, 2008

hyphz posted:

So I looked at this again and suddenly thought, hang on, if you can just change the identity of the loop control variable like that then there must be a hidden loop control value somewhere that actually tracks the position in the list. And of course there is, it's the status of the iterator created by the for loop. Which means that you can do:

code:
>>> for x in range(5): print(x); x=1; print(x)
0
1
1
1
2
1
3
1
4
1
More because if you've had students putting stuff in classes without learning what they are, then they get deeply confused when they do learn them. But this is partly because so many courses want to teach OO using janky physical metaphors like "This desk is an object, this other desk is an object, they are both of class desk, they are different instances.." etc instead of admitting it's just type strengthening and syntactic sugar for overloaded function calls.

This seems pretty intuitive to me, can someone explain the horror here that my eyes aren't perceiving? The loop control variable isn't hidden, it's part of the Sequence that was created when you invoked range(). Generators work this way too:

Python code:
def weird_number_generator():
    yield 0
    yield 10
    yield -40
    yield 50

values = weird_number_generator()
x = next(values)
print(x)  # 0
x += 4
print(x)  # 4
x = next(values)
print(x)  # 10
print(next(values))  # -40

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

agreed, the root cause of this coding horror is that x is being mutated by both range as well as the loop body. This looks way less like a horror, imho, but is functionally the same thing:

code:
>>> def f(x): print(x); x = 1; print(x)
...
>>> [f(x) for x in range(5)]
0
1
1
1
2
1
3
1
4
1
[None, None, None, None, None]
>>>
this is why mutability is bad :eng101:

fritz
Jul 26, 2003

ultrafilter posted:

So there really is more than one way to do it?

Always has been, and the way that you're doing it will get deprecated in a few minor versions.

QuarkJets
Sep 8, 2008

Dijkstracula posted:

this is why mutability is bad :eng101:

That doesn't seem like the best takeaway, but if you really want to only use immutable containers then tuple is right there

gnatalie
Jul 1, 2003

blasting women into space
my contribution is an angular/c# webapp with tons of typescript any and c# dynamic, courtesy of some contractor. had we not been legally required to have it go live at the beginning of the year, i would have nuked everything and started from scratch. luckily was able do that with the db schema.

dougdrums posted:

I feel like uuids are dumb but I don’t have any real argument to go off of

devs who decide to use guids as clustered primary keys. loving may as well make your primary key a random number.

champagne posting posted:

Active Directory has a bunch and the Dumb of them is that different systems have different ways to identify A Thing to a Resource so that for one system you need to use a Service Principal Id while for another you'll be using an Application App Id even though you're referring to the same thing.

They should really stream line it or do something

well...yeah...but active directory is 20+ years old now. it could have been a lot worse.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

gnatalie posted:

devs who decide to use guids as clustered primary keys. loving may as well make your primary key a random number.

obligatory reminder that it's a bit more nuanced that this:

in postgres primary keys are NOT clustered so guids or other randomized / distributed ids are fine

in sqlite they are also not clustered unless you use WITHOUT ROWID, and if you do you hopefully know what you're doing

in mssql they are clustered by default, so if you NEED sharding you should make a nonclustered pk with a guid or other shard-friendly data type, and a clustered index with a plain into

in other databases, you're probably paying 5-6 figures a year for some extortionate support contract so ask them I guess

gnatalie
Jul 1, 2003

blasting women into space
ah yea i'm in the mssql world. a former dev of ours would do this whenever he could its so annoying to see, luckily there are no performance problems, compared to...

...a current dev in a completely unrelated project did this on a db with tables in the hundreds of millions / billions of rows and they ended up having to separate that into 5 (!!) servers because of huge performance problems and an inability to rewrite with a correct data structure.

not my circus, not my monkeys.

redleader
Aug 18, 2005

Engage according to operational parameters
in sql server, you can use NEWSEQUENTIALID() to get the worst of both worlds. genius stuff

Nude
Nov 16, 2014

I have no idea what I'm doing.
Speaking of python I stumble across this the other day,

code:
test = [[1,2,3]]*3
test[0][0] = 99
print(test) # [[99, 2, 3], [99, 2, 3], [99, 2, 3]]
Can anyone think of a scenario where I would want an array of arrays that reference each other lol?

Jabor
Jul 16, 2010

#1 Loser at SpaceChem
The code literally says "I want a size-3 array, each entry should be a pointer to this object", yeah?

Surprise deep-copying arrays in some situations seems like it would be an even bigger horror.

QuarkJets
Sep 8, 2008

Nude posted:

Speaking of python I stumble across this the other day,

code:
test = [[1,2,3]]*3
test[0][0] = 99
print(test) # [[99, 2, 3], [99, 2, 3], [99, 2, 3]]
Can anyone think of a scenario where I would want an array of arrays that reference each other lol?

Python sequences are always passed by-reference, so you're the one who asked for 3 references to the same object

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
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.

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER

I would've thought Repeat would create new objects each time, consider me schooled

champagne posting fucked around with this message at 21:39 on Dec 11, 2022

Xarn
Jun 26, 2015
This is why I love C++'s explicit references (and values by default).

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
And why I love Swift's copy-on-write.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

champagne posting posted:

I would've thought Repeat would create new objects each time, consider me schooled

Forgive me, but I don't know why you'd have that expectation. The name doesn't suggest to me that it does that, but rather that it "repeats" the same object several times.

The one-line help summary (here) says that it "generates a sequence that contains one repeated value".

If anything, it's still more clear in the C# code that it'll be the same object every time, because the array is an argument to Enumerable.Repeat() and it has already been constructed when Enumerable.Repeat() starts executing. You don't really expect Enumerable.Repeat<T>() to know how to deep clone an arbitrary T?

Nothing to stop you from making a method that generates a new object every time... (and of course you can do similar in Python)

code:
static IEnumerable<T> RepeatFactory<T>(Func<T> f, int count)
    => Enumerable.Range(0, count).Select(_ => f());

static int[] GetArray()
    => new [] {1, 2, 3}; 

var L = RepeatFactory(GetArray, 3).ToArray();
L[0][0] = 99;
string s = "[" + string.Join("], [", L.Select(a => string.Join(", ", a))) + "]";
Console.WriteLine(s); // [99, 2, 3], [1, 2, 3], [1, 2, 3]
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

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER

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

this is certainly A Take

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

champagne posting posted:

this is certainly A Take

is it, now! I thought that would be a pretty uncontroversial remark.

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.

champagne posting
Apr 5, 2006

YOU ARE A BRAIN
IN A BUNKER

Hammerite posted:

is it, now! I thought that would be a pretty uncontroversial remark.

It just seems much harsher than you may have meant it

QuarkJets
Sep 8, 2008

champagne posting posted:

this is certainly A Take

A Correct Take

e: I'm not even sure what else can be said about this, these functions/methods are doing exactly what's printed on the tin

QuarkJets fucked around with this message at 22:34 on Dec 11, 2022

Plorkyeran
Mar 22, 2007

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

Hammerite posted:

is it, now! I thought that would be a pretty uncontroversial remark.

I would consider it one of the most banal true statements you could make. There are certain things you most understand or you'll have a very bad time, and what things do and don't have reference semantics in your language is absolutely one of them.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

champagne posting posted:

It just seems much harsher than you may have meant it

ok, well if it came across as a barbed comment, it was not intended in that way.

redleader
Aug 18, 2005

Engage according to operational parameters

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

every day i pray that the offshore contractors will learn this

Xarn
Jun 26, 2015
Last time I worked with offshore contractors, they would check if key is in hashset by iterating all elements in it and compare them with the key they wanted to check. I think that's actually several steps down from "understands the reference model in language"

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

Xarn posted:

Last time I worked with offshore contractors, they would check if key is in hashset by iterating all elements in it and compare them with the key they wanted to check. I think that's actually several steps down from "understands the reference model in language"

Make it work in the least efficient way possible.
Make it reasonably efficient.
Make it fast.

You can bill for all of these. And if you do it right, you can bill for them multiple times on a single feature.

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

RPATDO_LAMD posted:

but Python makes it a lot harder to understand how references work than C# does.
The behaviour of `*` on lists in Python is one of my biggest footguns. Should say, though, that if one wants the behaviour that everyone expects, a list comprehension is just as succinct and will do the right thing:

Python code:
python3 -q
>>> a = [[1,2,3] for _ in range(3)]
>>> a[0][0] = 42
>>> a
[[42, 2, 3], [1, 2, 3], [1, 2, 3]]
>>>

hyphz
Aug 5, 2003

Number 1 Nerd Tear Farmer 2022.

Keep it up, champ.

Also you're a skeleton warrior now. Kree.
Unlockable Ben
Ugh, yes, reference semantics wind me up. We teach languages in the order Python, Java, C/C++ and the Python and Java sessions both elide any mention of the reference model because it’s “too complicated”. Then when the students hit C’s explicit pointers they freak out completely.

leper khan
Dec 28, 2010
Honest to god thinks Half Life 2 is a bad game. But at least he likes Monster Hunter.

hyphz posted:

Ugh, yes, reference semantics wind me up. We teach languages in the order Python, Java, C/C++ and the Python and Java sessions both elide any mention of the reference model because it’s “too complicated”. Then when the students hit C’s explicit pointers they freak out completely.

I learned machine language, C, then a bunch of high level languages. It just hosed me up in different ways.

There's no winning move for teaching this stuff.

CPColin
Sep 9, 2003

Big ol' smile.

leper khan posted:

I learned machine language, C, then a bunch of high level languages. It just hosed me up in different ways.

There's no winning move for teaching this stuff.

A curious game

QuarkJets
Sep 8, 2008

Dijkstracula posted:

The behaviour of `*` on lists in Python is one of my biggest footguns. Should say, though, that if one wants the behaviour that everyone expects, a list comprehension is just as succinct and will do the right thing:

Python code:
python3 -q
>>> a = [[1,2,3] for _ in range(3)]
>>> a[0][0] = 42
>>> a
[[42, 2, 3], [1, 2, 3], [1, 2, 3]]
>>>

What kind of issues do you encounter with `*`?

(I've sometimes seen this referred to as the splat operator, I like that name - and for Python it even describes the operator's behavior)

Zopotantor
Feb 24, 2013

...und ist er drin dann lassen wir ihn niemals wieder raus...

QuarkJets posted:

What kind of issues do you encounter with `*`?

(I've sometimes seen this referred to as the splat operator, I like that name - and for Python it even describes the operator's behavior)

The name "splat" for * goes back at least to the original INTERCAL paper.

Dijkstracula
Mar 18, 2003

You can't spell 'vector field' without me, Professor!

QuarkJets posted:

What kind of issues do you encounter with `*`?
the one discussed right above, where folks use it to construct a list of some value with a tacet assumption that each element will be distinct, but if it's a reference type then every element in the list shares the reference to the RHS of the `*`.

one of those "oh yeah that's obvious" things once you know what you're looking for, but diagnosing weird mutations that only materialise in a different part of your program is tricky

Adbot
ADBOT LOVES YOU

RPATDO_LAMD
Mar 22, 2013

🐘🪠🍆

hyphz posted:

Ugh, yes, reference semantics wind me up. We teach languages in the order Python, Java, C/C++ and the Python and Java sessions both elide any mention of the reference model because it’s “too complicated”. Then when the students hit C’s explicit pointers they freak out completely.

my school's CS program taught ARM assembly and C in the first two semesters and made students program an rc car on a cortex m3 chip to drive around a racetrack
at least when you know what a register is and wtf the difference between eax and [eax] is, it's really easy to understand C pointers

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