Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

To Binary Tree or Not to Tree #473

Closed
kingdavidmartins opened this issue Jan 3, 2018 · 32 comments
Closed

To Binary Tree or Not to Tree #473

kingdavidmartins opened this issue Jan 3, 2018 · 32 comments
Labels
help wanted Could do with some extra help from the community.

Comments

@kingdavidmartins
Copy link
Contributor

[SUGGESTION] Adding The Following Categories: Trees, Linked List, Double Linked List, Graph, Trie, Stack, & Queue

Description

I believe adding other categories representing different operations/manipulation of other data structures other than arrays / objects can also be beneficial to the project.

I think its important for the following reasons: exposure, growth, performance, and simplicity

An example of this would be Math.max() which is native and takes variadic inputs
But then we had arrayMax()
Then we made max() take both variadic & arrays. Which I regret & I partially take credit for see #295
Then #419 happened
Now there's #463

I honestly believe separating methods by their data structure would be best, and would prevent what was described above from repeating itself. Especially when looking at the following example

For example let's say we want create a function that can find the maximum number from a particular data structure

Example

Array

max

const max = (arr) => Math.max(...arr);
max(Array); // Number

Binary Tree

max

const max = (Binary Tree) => code;
max(Binary Tree); // Number

Linked List

max

const max = (Linked List) => code;
max(Linked List); // Number

As you can see moving the project in this direction will not only prevent what was described with the following issues #295 | #419 | #463 from repeating them selves. But also keep snippetNames simple when adding to their respective categories.

Thoughts? @atomiks @skatcat31 @fejes713 @Chalarangelo

@Chalarangelo
Copy link
Owner

First off, it's impossible to have multiple snippets with the same name, so we will have to still name them arrayMax, binaryTreeMax etc.

Secondly, data structure categories should be added but only as soon as we have enough snippets for each (5 sounds like a good starting amount). If someone can get started on coding snippets for each data structure and PRing them, I would be glad to get those categories up and running.

@Chalarangelo Chalarangelo added discussion help wanted Could do with some extra help from the community. labels Jan 3, 2018
@kingdavidmartins
Copy link
Contributor Author

@Chalarangelo I def agree

First off, it's impossible to have multiple snippets with the same name, so we will have to still name them arrayMax, binaryTreeMax etc.

Haha a lot of times I am lazy & omit my full explanation. I just used max() as an example snippetName for each Category because I was lazy and copied and pasted 😆

Didn't intend that we will actually have the same name, especially seeing that we have a package & would be conflicting AF when someone does tsoc.max() 🤣

@Chalarangelo
Copy link
Owner

We are not tsoc anymore, we now are _30s (30 seconds of lodash seems like). 🤣

@kingdavidmartins
Copy link
Contributor Author

kingdavidmartins commented Jan 3, 2018

Hahaha 😆 🤣 _30s Looks like lodash 3.0.
Yea sure I will quickly jump start a Linked List & Binary Tree, Before focusing on testing all the 190 + snippets Gosh 😦 lol

@Chalarangelo
Copy link
Owner

Chalarangelo commented Jan 3, 2018

@kingdavidmartins We will hit 200 before long, I have a backlog of 30 semi-implemented snippets on my computer, we might end up with 250 by next weekend.

@fejes713
Copy link
Contributor

fejes713 commented Jan 3, 2018

@kingdavidmartins and @Chalarangelo let's decide who is going to write which data structure so we don't come up with 2 same PRs. Should I make an Issue for this one?

@kingdavidmartins
Copy link
Contributor Author

kingdavidmartins commented Jan 3, 2018

@fejes713 I'll do linked List you can do BST
I'm actually eating taking a break. Should get started on it after

@fejes713
Copy link
Contributor

fejes713 commented Jan 3, 2018

@kingdavidmartins I am not starting now either, but will do in two hours or so... It's going to be fun.
I will reach you on gitter if I get stuck somewhere

@Chalarangelo
Copy link
Owner

I'm going to work on website features/maintenance and some other things, plus my own backlog of snippets. I'll pm either one of you if any of my code falls into one of your categories.

On a side note, find emojis for the categories, too.

@fejes713
Copy link
Contributor

fejes713 commented Jan 3, 2018

For example, the binary tree category could have:

  1. create
  2. insertNode
  3. containsNode
  4. BFS
  5. DFS

As for the insertNode I would need to reuse the create logic. What do I do? Write it again in the same snippet or rely on the user to copy that one also?

@Chalarangelo
Copy link
Owner

Rewriting is ok, as it shouldn't be terribly long. You should also add a checkBinaryTree to check if an object is a binary tree (for error handling if the user wants that).

@skatcat31
Copy link
Contributor

Do we want to do data-structures in this? That feels more like "30 seconds of CS" territory. Sure they're simple enough, but they are almost worthless in a website/server. If we need a binary tree we're literally recreating the Object in JS( which is doable, I'm just not certain we'd want to ) or getting into the land of odd stuff, which an advanced programmer might not understand. Remember great programmers can come from non-CS backgrounds.

@fejes713
Copy link
Contributor

fejes713 commented Jan 3, 2018

@skatcat31 You're right. I taught about writing that comment and then I was like "Huh I will just write snippets to see what others think about them". But yeah pretty much who would use a binary tree or a linked list on a website or a server... You got the point

@skatcat31
Copy link
Contributor

skatcat31 commented Jan 3, 2018

If we do these, we would need to create a type and reference every time in each of the BST snippets:


BST Sym Test

Test if a (Binary Search Tree)[URL to BST type in project] is symmetrical

const BSTSymTest = node =>
  (node.left === undefined && node.right === undefined)
  ? true
  : (node.left !== undefined && node.right !== undefined)
    ? BSTSymTest(node.left) && BSTSymTest(node.right)
    : false
const BST = {}
BSTSymTest(BST) // true
BST.left = {}
BSTSymTest(BST) // false
BST.right = {}
BSTSymTest(BST) // true

Which I'm pretty certain we said we wanted to avoid in our own contribution guidelines:

Try to keep your snippets' code short and to the point.

Which we kind of violate by saying "Go back and understand this first".

Since we'd always have to reference the type... well I'm not certain it's a snippet then as much as a contained library and/or an extension(s) of a snippet.


Beyond those caveats, I vote against doing non-EC types and classes as categories since it would require the reader to learn more about 30SoC to be able to understand, and they would have to hunt through the type snippets to find the declaration( meaning they'd be reliant on previous knowledge to understand )

@skatcat31
Copy link
Contributor

I am however all for '30 Minutes of CS' lectures/articles 😸

@kingdavidmartins
Copy link
Contributor Author

kingdavidmartins commented Jan 3, 2018

Hey @skatcat31 👋 😄

Thanks for the feedback as always

However I have to disagree with @fejes713 & You on this one

Do we want to do data-structures in this? That feels more like "30 seconds of CS" territory. Sure they're simple enough, but they are almost worthless in a website/server.

First of we are already technically using data structures. i.e Arrays. Although linear in nature. It's technically still a data structure.

Which we kind of violate by saying "Go back and understand this first".

Second of, the same way one who has zero web dev experience might not be able to understand code under the browser category in less than "30 seconds" or one with zero ES6 experience might not be able to understand our code using spread operator ... or any other ES6 syntax/methods i.e .includes(), ${nameVariable} in under "30 seconds". The goal is to expose potential dev and curious learners to the different/modern JS practices in different categories.

There's always going to be snippets where users have to quickly read up on especially so if they are trying to learn web dev snippets in the browser category with zero web dev experience, or trying to learn server specific operations with zero experience as a Backend engineer, and so forth.

Just recently a friend of mine accepted an offer from Google. This is someone who is a "Non Traditional", who Picked up coding later on in high school, who also didn't attend college in the attempt to self study in pursuit to jump start their software dev career. During the interview process as you can imagine depending on the position/company the interview can entail solving/implementing things at scale.

Let's look at the following example which is typically asked during interviews.

How can one go about implementing a system similar to that of Twitter, Facebook, Google, etc that keeps track of what is currently trending as the top 10 in the midst of millions/billions of updates/post concurrently assuming your pull all the updates/post from a stream of sorts. Although one can use a Arrays to implement such a system. It is not feasible in production due to the insertion time / look up time for the greatest value or x amount of greatest values. Which if using a Binary tree would/can reach O (Log N) in regards to run time and can save the company valuable resources.

Imagine using an Array to insert all that data coming in from the stream and then sorting in place using Merge sort or Insertion sort. Then grabbing the last x values if sorted in ascending order. At scale this can incur hundreds of thousands $$$ if not millions $$$ of unnecessary expenses/resources daily/monthly 😦

I am not saying we can replace a CS course/degree. However I am saying that we can expose said users to new categories they never came across that could very much so help them in their endeavors with regards to their dev career.

I'm sure it will work out the same way in how we expect users who come across new information/topics in our project to be proactive and research what's not fully understandable as a way to subsidize their learning.

Personally after coming across a specifically new code block. I don't just don't copy blindly, but take time to research the subject on my own to a point where after re visiting said snippet it becomes more understandable.

I believe the people who are currently pursuing whatever they can about code or JS are doing so not just to learn & understand it, but also as a way to prep/break in the industry. And as such feel they only benefit to be exposed to more categories/data structures/operations/etc

Note

Please keep in mind that I also intend on keeping said snippets on par with the rules/standards set aside by the project in the sense that the time taken to grasp/understand said snippets will be on par with other their peers

@atomiks
Copy link
Contributor

atomiks commented Jan 3, 2018

I'm personally really interested in learning more about data structures, so I would like these snippets and categories 😀

@skatcat31
Copy link
Contributor

skatcat31 commented Jan 3, 2018

First off we are already technically using data structures. i.e Arrays. Although linear in nature. It's technically still a data structure.

This comment shows a massive misunderstanding of a Data Structure versus a Class in terms of ES/JS:

  • Class: in JS terms, instanceof will work on it, it will confirm to definition
  • Data Structure: An object with very specific keys, no way to consistently test or create them other than duck casing, library functions will work on it
var a = [1] // Array
var b = {0: 1, length: 1} // Array Data Structure
a instanceof Array // true
b instanceof Array // false
Array.prototype.map.call(b, x => x*2) // [2]
b // {0: 1, length: 1}
Array.prototype.map.call(a, x => x*2) // [2]
Array.prototype.forEach.call(b, (x,i,a) => a[i] = x*2)
b // {0: 2, length: 1}
Array.prototype.push.call(b, 3) // 2
b // {0: 2, 1: 3, length: 2}
b.push(4) // Uncaught TypeError: b.push is not a function

@skatcat31
Copy link
Contributor

@atomiks learning is always encouraged

@skatcat31
Copy link
Contributor

skatcat31 commented Jan 3, 2018

Now all this having been said, if we instead wanted to point to an external Class library for any of these CS ideas( BST, LL, Node list, etc. ) and then make snippets for them with a link to the library I have no complaints!

I do not want use however putting a class definition and then a bunch of separated methods that should ideally live on the class instance into the repository.


Afterthoughts: Also what implementation of BST/LL/TypeX would we do? Node Direct Construct or Node Reliant Class?

@skatcat31
Copy link
Contributor

skatcat31 commented Jan 4, 2018

My snippet earlier should have looked like


BST Sym Test

Test if a (Binary Search Tree)[URL to BST type in this project] is symmetrical

const BSTSymTest = node =>
  (node.left === undefined && node.right === undefined)
  ? true
  : (node.left !== undefined && node.right !== undefined)
    ? BSTSymTest(node.left) && BSTSymTest(node.right)
    : false
const BST = {}
BSTSymTest(BST) // true
BST.left = {}
BSTSymTest(BST) // false
BST.right = {}
BSTSymTest(BST) // true

@skatcat31
Copy link
Contributor

skatcat31 commented Jan 4, 2018

In case anyone is curious about BST:

class BST {
  constructor( value ){
    this.value = value;
  }
  insert(value){
    if ( value < this.value ) this.left = this.left ? this.left.insert( value ) : new BST( value )
    if ( value > this.value ) this.right = this.right? this.right.insert( value ) : new BST( value )
    return this;
  }
}

This is a basic insert capable BST. It does not have the find method, but it comes in at 10 lines

@kingdavidmartins
Copy link
Contributor Author

Hey @skatcat31

Ahh although I don't understand why you said the following

This comment shows a massive misunderstanding of a Data Structure versus a Class in terms of ES/JS:

  • Class: in JS terms, instanceof will work on it
  • Data Structure: An object with very specific keys, no way to consistently test or create them other than duck casing

I believe you made that statement with the assumption I was addressing JS in general.

During this discussion when describing data structure's please make the assumption I will be talking about data structures exclusive of any language. As I'm sure we can both agree that data structure's are not language specific in regards to implementation and/or time complexity when applied to Arrays, Lists, Vectors and/or other similar/different data structures

Example:

Go

package main

import "fmt"

func main() {
	var a [2]string
	a[0] = "Hello"
	a[1] = "World"
	fmt.Println(a[0], a[1])
	fmt.Println(a)

	primes := [6]int{2, 3, 5, 7, 11, 13}
	fmt.Println(primes)
}

Java

class Main {
    public static void main(String[] args) {
        // declares an array of integers
        int[] anArray;

        // allocates memory for 10 integers
        anArray = new int[10];
        // initialize first element
        anArray[0] = 100;
        // initialize second element
        anArray[1] = 200;
        // and so forth
        anArray[2] = 300;

        System.out.println("Element at index 0: "+ anArray[0]);
        System.out.println("Element at index 1: "+ anArray[1]);
        System.out.println("Element at index 2: "+ anArray[2]);

    }
} 

& etc

Pending on the language one uses one can prove or disprove the your assertion

Note

Feeling really lazy. So stopped there with the explanation/examples.

Also keep in mind the that the following statement introduces the definition of The Array Data Structure

In computer science, an array data structure, or simply an array, is a data structure consisting of a collection of elements (values or variables), each identified by at least one array index or key. An array is stored so that the position of each element can be computed from its index tuple by a mathematical formula. The simplest type of data structure is a linear array, also called one-dimensional array.

Although certain languages ergo JS can exhibit certain idiosyncrasies as you've shown. I still stands by the following statement

First off we are already technically using data structures. i.e Arrays. Although linear in nature. It's technically still a data structure.

@Chalarangelo
Copy link
Owner

Chalarangelo commented Jan 4, 2018

I'm a bit late to the discussion, but here's my take (an attempt at keeping the peace if you can call it that):

  1. Data structures are interesting and should be something that we try to expose developers to.
  2. Data structures definitely require more time to learn and expect prior knowledge/research.
  3. Defining a data structure like a BST and adding just the basic methods to insert/find/delete nodes could be done in one snippet.
  4. Defining algorithms like BFS/DFS cannot be done in a snippet without copying the data structure definition or expecting prior knowledge.
  5. Use-cases for data structures in a server/browser environment are not always apparent and will confuse developers who are here to learn. The assumption is we are targeting people who know ES6 syntax and have some experience in web development. Such a developer doesn't necessarily think with data structures like these on an everyday basis, so these snippets will probably confuse them and have them running back to find the data structure definition.

Based on my above points, my suggestion is the following:

  • Add one category named data structures where we only define data structures in a functional manner and have just the basic operations in the provided functions.
  • Provide links to articles in the snippet descriptions of said data structures and to useful algorithm implementations in JS about them (we can even write our own articles for this).
  • Refrain from adding snippets like BFS/DFS for data structures, as this requires a lot of back-and-forth and would only make the whole experience for beginner developers worse.

On a side note, the whole style of the project is a functional one and the guidelines have to be followed, so we should avoid using classes entirely and stick to our functional style, even if that makes things slightly more difficult.

@skatcat31
Copy link
Contributor

@kingdavidmartins

I believe you made that statement with the assumption I was addressing JS in general.

I think again we're not lining up correctly but I was not speaking about JS in general either. What I mean by Class I stand by what I said regardless of JS, but I feel like a further explanation of a Data Structure is needed to make it much more agnostic:

  • Data Structure: An idea of organizing memory space for referencing that has not been implemented in your language of choice but can be
  • Class: implementation of a Data Structure with typing that conforms to your language

Like I said in a comment before, if we link to an outside library or decide to make one ourselves and link to it then I have no problems.

What I have a problem with is us using a snippet to define a Data Structure and then relying on that snippet in the future. I don't think we should have Data Structure implementations in this repo since a Class would be more appropriate and is outside the scope of the repository.

While easy to implement a simple version, that version will have many downfalls in regards to the full Data Structure definition. That is why I want to avoid implementing the Data Structure as a snippet. Reading my previous comments I can see how this was a little obtuse.


Where I stand

Snippets relating to Class implementations of Data Structures and linking to them: All for
Snippets defining Data Structure as simple but lacking constructs: Completely Against

So if we can find a class we want to implement these snippets too I'm absolutely all for it, even if we code it ourselves. If we do code it ourselves we should probably make sure it fully conforms to a Previous Art Definition.

@skatcat31
Copy link
Contributor

skatcat31 commented Jan 4, 2018

@Chalarangelo

On a side note, the whole style of the project is a functional one and the guidelines have to be followed, so we should avoid using classes entirely and stick to our functional style, even if that makes things slightly more difficult.

Data Structures could be tens to hundreds of lines of codes for all the required implementation, and gets worse if we are not going to do it as a Class decleration due to possible prototype/state mutilation and exposing dangerous code that modifies this, which to this day after 10+ years of JS people still easily get confused about. If done wrong it will modify global and each "instance" will overwrite itself if a new keyword is not used, and we don't want to do the instanceof test every time. Worse yet there would be no instance scoped functions if we don't do it as a functional class and we would have an API and library completely contrary to JS( the language of the snippets ). Since Classes are in ES6, are Functions, have proper protection( CAN'T be called without new ), and can be done in a declarative scoped manner or a global manner I see no reason to not include classes since the examples should make it VERY easy to understand what a Class declaration does and what caveats it has.


Functions versus classes:

Arrow

const BST = value => ({value})
new BST(1) // FAILS, not a constructor, actually errors
BST(1) instanceof BST // false
BST(1) instanceof Object // true

Classical Constrtuctor

const BST = function (value) {
  // to fix problem to come you'd need to include the next line in all Functional Classes
  // if ( this instanceof BST === false ) throw new TypeError( `Class constructor BST cannot be invoked without 'new'` )
  this.value = value
  return this;
}
BST.prototype.insert = function (value) {}
BST.prototype.find = function (predicate) {}
BST.prototype.delete = function () {}
var a = BST(1) // !!! modifies inherited this context without required check !!!
a instanceof BST // false, it modified the inherited context
var b = BST(1)
b === a // true, and very bad
var c = new BST(1) // works, scoped properly
c instanceof BST // true
c === a // false

Class

class BST {
  constructor( value ){
    this.value = value;
  }
  insert(value){...}
  find(predicate){...}
  delete(predicate){...}
}
BST instanceof Function // true
var a = BST(1) // fails, throws error explaining why
var b = new BST(1)
b instanceof BST // true
var c = new BST(1)
c === b // false

Regardless of Classes we get into the territory of hosting a possibly hap hazard or dangerous implementation. We might want to instead link to an article we feel properly introduces the subject. Especially if we get into such types as Future, Functor, Collection, Iterable, Monad, Chain, CoMonad, IsoMorphic, Lens, etc.

@atomiks
Copy link
Contributor

atomiks commented Jan 4, 2018

@skatcat31 A downside of using a factory instead of a constructor is indeed that it has a memory performance impact because it creates new objects with the methods every time instead of re-using a single prototype...

const BST = value => ({
  value,
  insert(value) {
    if (value < this.value) this.left = this.left ? this.left.insert(value) : BST(value)
    if (value > this.value) this.right = this.right? this.right.insert(value) : BST(value)
    return this
  }
})

But you could use a closure so that only one prototype obj is created in memory

const BST = (() => {
  const BSTPrototype = {
    insert(value) {
      if (value < this.value) this.left = this.left ? this.left.insert(value) : BST(value)
      if (value > this.value) this.right = this.right? this.right.insert(value) : BST(value)
      return this
    }
  }
  return value => {
    const bst = Object.create(BSTPrototype)
    bst.value = value
    return bst
  }
})()  

@kingdavidmartins
Copy link
Contributor Author

Hey @skatcat31

  • Data Structure: An idea of organizing memory space for referencing that has not been implemented in your language of choice but can be
  • Class: implementation of a Data Structure with typing that conforms to your language

Yes I agree, I believe we are currently of the same mind.

@Chalarangelo I have to agree with @skatcat31 concerning the following statement

Since Classes are in ES6, are Functions, have proper protection( CAN'T be called without new ), and can be done in a declarative scoped manner or a global manner I see no reason to not include classes since the examples should make it VERY easy to understand what a Class declaration does and what caveats it has.

I am also for classes due to simplicity, consistency, & all the reasons @skatcat31 described above

For example implementing a LinkedList should be implemented like the following, and currently can't think of any other implementation that could out way the benefits of using classes

class LinkedList {
  constructor(head, ...tail) {
    this.head = head;
    this.tail = tail.length ? new LinkedList(...tail) : null;
  }
  add(item) {
    (this.tail) ? this.tail.add(item) : this.tail = new LinkedList(item);
  }
}

@Chalarangelo
Copy link
Owner

We are not doing classes, as this would lead to a huge host of issues with contribution guidelines and other things. Even with the tiny amount of rules we are enforcing on people, contributors have difficulty following them and PRs need some cleaning up 90% of the time. If we start doing classes, we will be causing a lot more harm than good to the project.

The original scope was to provide a learning resource for people to understand and learn modern JS and showcase cool features. While classes are cool and extremely useful, they are not instantly understandable and OOP takes a lot of time to wrap your head around. JS is mainly based on prototypes and classes are a relatively new addition, which confuses a lot of developers and that many people I know just entirely avoid. Apart from that, we are following a functional style. Adding OOP would be kind of against this.

Same thing applies to data structures. They take a lot of time to learn, their usefulness is not immediately apparent and it is something that most people in web development are not going to care for when starting out. Our user meta is in the beginner-intermediate range and these are quite advanced concepts that require some background in computer science. I have studied CS for almost 7 years now and I have never once used a BST or Linked List in a project (I have done like 50 of them, the majority were web-based). It's just something that doesn't come up as often and, even if it did, 30 seconds is not the place to teach people that kind of thing.

I'm all for adding a list linking to resources/libraries/articles for people to learn more advanced concepts and use them, but doing it ourselves would take up a lot of time, impact maintenance and change the very definition of the project. We have so many simpler things to focus on, so many cool micro-packages on npm we can try our hand on and functional libraries that we can get inspiration from. I do not think we shall put those on the backburner in favor of data structures now or ever.

TL;DR

  • We should stick to a simple snippet style, like we already do. Classes complicate things in that respect.
  • OOP is complicated, most JS developers are not used to it and will make those snippets either something most people skip or something that is hard to grasp by many.
  • Data structures have limited use-cases in the web and they require prior knowledge. They are a pretty bad fit for the project.
  • We have better things to focus on, but we should point developers to decent resources in order for them to learn these things, if they need them.

I'm voting to close this issue and all PRs related to it and move back to things like implementing methods under #100 and similar libraries. We spent far too much time discussing this and prototyping ideas for something we have no reason to implement. Having read through a lot of criticism for the repo, nobody has ever brought up the lack of data structure snippets, so apparently it's not something that comes up often in reference to the project.

@atomiks
Copy link
Contributor

atomiks commented Jan 5, 2018

Thoughts I wrote in the chat:

  • At first I was thinking they'd be cool to learn, but then I realized that they have almost no use in real world code for most devs, except in DB designs, right?

  • You need millions of data points for it to become a performance issue to use them

@fejes713
Copy link
Contributor

fejes713 commented Jan 5, 2018

We spent far too much time discussing this and prototyping ideas for something we have no reason to implement

@Chalarangelo Right, close it.

@lock
Copy link

lock bot commented Dec 18, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for any follow-up tasks.

@lock lock bot locked as resolved and limited conversation to collaborators Dec 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
help wanted Could do with some extra help from the community.
Projects
None yet
Development

No branches or pull requests

5 participants