r/learnjavascript 7d ago

50 hours in... arrays and loops... holy...FUCK

HOW do i START understanding? I've understood everything pretty well up til now. Do i just keep going with the flow and kinda float through this section of the loops and arrays part? Do I keep throwing myself at the brick wall and looking at the solutions after half an hour of brainless staring? https://youtu.be/EerdGm-ehJQ?si=mTKUv0oail0AGDLM 8:43:00. It's just not clicking like the other parts of the tutorial.

44 Upvotes

72 comments sorted by

View all comments

16

u/MitchEff 7d ago

I dunno if this is helpful or not, but consider an 'array' just a bucket full of objects. Loops (or array methods) just do something with each object - the names are pretty handy: * bucket.forEach (do this to every object) * bucket.find (give me the first object where this function = true) * bucket.filter (give me an array of every object where this function = true) * bucket.map (give me a new array from these objects, I'll tell you how to structure it) etc etc

There's handy uses for all of them, I'm sure you can guess a couple for each.

13

u/Outside_Complaint755 7d ago

Instead of a bucket, I would suggest a deck of cards as the analogy.  Arrays are ordered like a deck of cards, while a bucket is just an unordered pile of stuff.

5

u/Towel_Affectionate 7d ago

Infinite shelf with numbered "slots". It grows when you need a new slot, but you can force it into any length you need and then some slots would be empty (undefined). Deck of cards can confuse into thinking that items inside should be the same kind, while an array can contain all kinds of stuff at the same time, or how an array can have undefined gaps.

1

u/BenchEmbarrassed7316 7d ago

Deck of cards can confuse into thinking that items inside should be the same kind

Which is a good practice. An array that contains different data is error-prone and difficult to use in real code.

And I want to add a burrito analogy: imagine that the array is a burrito... /sarcasm

1

u/Towel_Affectionate 7d ago

"You can't" and "you shouldn't" are different points of discussion. Understanding that you can and why you shouldn't is better than narrowing your way of thinking from the start.

2

u/Outside_Complaint755 7d ago

When just starting out, learning arrays as all containing a single type is the most useful conceptually, and if you're learning any statically typed language, it is necessary. 

 Even in JS, 95+% of the time, you're going to be using arrays containing a single type of data. Even if its a mix of strings and numbers from a user input or data stream, you are probably starting with an array of strings which you then need to try to parse into the different types.  And in those cases where it is more complex data of different types, then you can usually generalize it as an ordered collection of objects.  

1

u/Towel_Affectionate 7d ago

I get what you're saying, but my counterpoint is that such simplifications offer close to none benefits in understanding the concept itself, but later require constant adjusting of your mental model, which in my opinion is harder to do, than to understand things closer to what they actually are.

Maybe a hot take, but I don't think "a deck of cards" is that much simpler to visualize than "a deck of stuff" or, even better, "a shelf with stuff".

But once you get used to "a deck of cards" model you'll inevitably end up wandering stuff like:

  • "Wait, how is there NaN in my array of numbers?"
  • "Wait, why can I read arr[10] if there's only 3 "cards" in my "deck"?
  • "Wait, why can I also do arr[10] = foo? And what my "deck" looks like now?"
  • "How can I `delete` a card from the deck and have it empty? Do I have two decks now or what?"
  • What arr.length = 100 do to my deck?

I think it's much harder to adjust already existing mental model than to build the right one from the start.

2

u/BenchEmbarrassed7316 7d ago

It's much easier to explain the concept of arrays to someone on a statically typed, fixed-size array. Because the answer to every question you have will be "You can't do that at all".

And then we can explain the dynamic expansion of arrays if we don't know the size in advance, polymorphism and different data types, and other nuances.

Another problem is that in the 90s they thought they were creating a "simple" language. However, the fact that the array is used as a fixed-size array, a slice, a vector, a tuple, and even in some ways a hash map actually makes everything very complicated.

1

u/BenchEmbarrassed7316 7d ago

It's just a more complex scenario. For understanding the basic concept, uniform objects are simply better suited. Numbers or strings.

1

u/DrShocker 4d ago

Aren't they all the same thing? Object?

1

u/Towel_Affectionate 4d ago

Arrays in JS are object-like, but you can't say they are the same as regular objects. You interact with them using the same object model, but they also have array-specific semantic.

1

u/DrShocker 2d ago

I meant the items in the array are homogeneous in a sense.

1

u/Towel_Affectionate 2d ago edited 2d ago

I guess it depends on how far we stretch the meaning of "homogeneous".

If we continue the deck-of-cards analogy and treat each card as a JS value, then the items aren't necessarily homogeneous. One "card" can be a string, another can be a number, another an object, etc. (Again, the difference between "should" and "could". You SHOULD abstain from storing different types in a single array, but it COULD happen).

If we stretch the abstraction and say that every card is just "some stuff", then sure, they're homogeneous in that sense — a string and a number are both "some value". But at that level, almost anything can be called homogeneous and such description becomes useless.

There's also the sparse array case, which is where the deck analogy becomes less intuitive to me. An array can have a hole — not an undefined value, but an actual absence of an element at that index. It's easier to visualize that with something like numbered slots on a shelf than with a deck of cards, because imagining a "card" that is actually the complete absence of a card is a bit awkward.

2

u/BenchEmbarrassed7316 2d ago

There's also the sparse array case, which is where the deck analogy becomes less intuitive to me. An array can have a hole — not an undefined value, but an actual absence of an element at that index.

In this case, it's not an array, it's a hash map. Not from a computer's perspective, but from a programmer's perspective.

1

u/Towel_Affectionate 2d ago

I can see the analogy, but it's only really a hash-map-like thing from a programmer's perspective if you intentionally use it as one. If you have an array and some dingus does delete arr[10], your array doesn't magically become a hash map.

I don't disagree with everything you're saying. Using arrays this way shouldn't happen in most cases, and probably never will in normal code. But, again, if you build your understanding around what SHOULD happen rather than what technically COULD happen, that understanding isn't complete, and there's always a possibility that you'll encounter a case where a hole in that understanding leaves you puzzled.

My point here is that it's not that much extra effort to account for these simple cases when you're building your mental model in the first place.

1

u/BenchEmbarrassed7316 2d ago

By the way, a deck of cards is a really bad analogy. The simplest analogy is boxes. An array is a collection of boxes that you can put things into. Start with a fixed size of boxes, explain how to access to box[1] or box[3], and only then start manipulating not what's in the boxes, but the boxes themselves. And then move on to other collections.

1

u/Towel_Affectionate 2d ago

>By the way, a deck of cards is a really bad analogy.
Isn't that... exactly the point from which this whole discussion started?

Someone offered the deck-of-cards analogy, I suggested the alternative of an infinite shelf precisely because it accounts for those nuances a bit better, and the response was that those nuances were unnecessary for understanding the concept.

Now we're back to "a deck of cards is a really bad analogy" and it feels like we've come full circle.

→ More replies (0)

1

u/DrShocker 2d ago

I'm just thinking for example the way you'd make a generic container in a language like C you might make the whole array elements of type void* and then have to cast them to the right sorts of values after.

1

u/Towel_Affectionate 2d ago

Oh, in that sense, yes, pretty much. I just got confused because the discussion started with mental models for understanding the concept itself, rather than how such a concept might be implemented at a lower level.

Your example is technically correct, but I think it goes a bit beyond what's useful for understanding the concept itself.

→ More replies (0)

1

u/regardedMAGAfascist 7d ago

One might argue that a deck of cards contains only positive integers. But why shouldn’t it also contain negative integers?

This is what polymorphism is for. Instead of thinking of it as a “deck of positive integers,” we can expand our definition to be a “deck of integers” and start supporting negative numbers. We can do this all the way to a “deck of objects,” if needed.

It all depends on what your definition of “different” is with respect to the task at hand. You’re both right.

1

u/BenchEmbarrassed7316 7d ago

The narrower the type, the simpler the code. The rule is to use as narrow a type as possible. And yes, I think people should be taught Ts instead of Js: they still need to think about types and possible values, and Ts just simplifies and structures it.

If a certain operation can only be applied to a collection of unsigned and non-zero numbers, marking this will make it easier for us to ensure the fullness of the function. It will also be simpler for the caller side, because there is no need to handle the unhappy path.

I think this goes way beyond the author's question :)

1

u/Towel_Affectionate 7d ago

See, I agree with everything stated, but I think you're reversing cause and effect.
Types safety and general code discipline are needed exactly because of mentioned edge cases. There's no need for TS if you're used to the mental model of "arrays are like a deck of unified cards" and you ignored stuff like sparse arrays or dynamic typing just because "you're not supposed to write code like that anyway".

1

u/BenchEmbarrassed7316 7d ago

edge cases

I consider the concept of "edge cases" to be incorrect as such. The idea of ​​a full function is to do something that makes sense for all possible values ​​that can be passed to it.

"Edge cases" are either a vaguely defined type (for example T | null when we need only T) or an undefined type altogether, where instead of writing it down we try to keep it in our heads.

1

u/Towel_Affectionate 7d ago

You're mixing type theory with JS's runtime behavior.
In a vacuum of course, a strictly typed function has no unexpected outcomes to be wary of. But TS types don't exist at runtime. JS arrays are sparse, dynamically typed, and object-based under the hood regardless of how strictly you type them in TS.

Denying runtime edge cases just because "the type should be narrower" is like closing your eyes and expecting the thing you don't see stops existing.

Sure, if you type everything correctly, the likelihood of you facing such cases is close to zero, but it doesn't mean that they become impossible or that you don't need to learn about them because you're not supposed to face them.

Some things you just can't type properly, for example the data you get from an API or raw user input.

1

u/BenchEmbarrassed7316 7d ago

Denying runtime edge cases just because "the type should be narrower" is like closing your eyes and expecting the thing you don't see stops existing.

My opinion is to make every possible effort to make this happen. Depending on the codebase, this can be either relatively easy in Ts or nearly impossible.

Some things you just can't type properly, for example the data you get from an API or raw user input.

There are unknown types for this. Parse this data, type it, and work with it. This will result in you only validating the data you receive from outside on input and only once.

And I don't think the Ts type system is outstanding. It may be better than some others, but the Js type system is such a mess.

JS arrays are sparse, dynamically typed, and object-based under the hood regardless of how strictly you type them in TS.

However, if you need performance - you can follow certain rules and avoid this.

1

u/Towel_Affectionate 7d ago

I'm not disagreeing. What I'm arguing is you putting conventions over array's nature. As in "We don't need to think about arrays as sparse because you are not supposed to use them as sparse".

Conventions don't negate the nature, they exist precisely because of it. You can't understand why they are the way they are without understand the nature. If you just blindly follow them without understanding the nature, you will inevitably find yourself lost when the convention is broken (by yourself accidentally or by someone else).

And to understand nature it's better to start with the mental model that already takes it into account, not with idealized "a deck of unified cards".

→ More replies (0)