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

3 suggestions for making p5js easier for newcomers #2305

Closed
makeyourownalgorithmicart opened this issue Oct 25, 2017 · 40 comments
Closed

3 suggestions for making p5js easier for newcomers #2305

makeyourownalgorithmicart opened this issue Oct 25, 2017 · 40 comments

Comments

@makeyourownalgorithmicart

Processing and p5js are designed to be accessible to newcomers to coding, especially artists who have never coded before.

For this reason I make 3 suggestions for language design changes.

They are arrived at as a result of writing (in progress) a book which aims to introduce algorithmic concepts and processing/p5js coding to complete beginners, and also first hand experience of teaching complete beginners.

They are:

  1. circle() and square() aliases for ellipse() and rect()
  2. easier loops eg repeat 5 {} as an alternative to the java/javascript structure
  3. random integer generator, perhaps making random() for integers and randomf() for floats, leading to the conventional randomn() for gaussian noise, etc

I have written a more detailed rationale here: http://makeyourownalgorithmicart.blogspot.co.uk/2017/10/ideas-for-making-processing-even-easier.html

@meiamsome
Copy link
Member

meiamsome commented Oct 25, 2017

Nice write up!

Most of these are issues with Processing that p5 inherited - but I certainly agree with a lot of them.

  1. Frankly, this amazes me that these aliases do not exist and rect instead of rectangle is such a pointless confusion. This has been discussed a lot previously, so I doubt it'd be possible to get conversion. What I find a bit bizarre is p5 has a three-argument version of ellipse, but Processing doesn't. (I'm not complaining, I like that p5 is ahead of the curve, so to speak!)
  2. Sadly, implementing such control structures in JS is not easy, however if you want to give a simpler one you can do
    for(var i of [0, 1, 2, 3, 4, 5]) {
    
    }
    as a 'simpler' loop. I would love to add a range function which behaves exactly like that of python (2) so that you can do for(var i of range(10)) but I don't know if it's a good idea or not. See Feature request/discussion: Simpler for loop syntax #1990
  3. I can see the logic behind this. I would perhaps prefer randomInt, randomFloat and leave random as is. Currently it works on arrays, so if range were to be implemented you could do random(range(10)); - that might be better for beginners.

@REAS
Copy link
Member

REAS commented Oct 26, 2017

I think I'm in favor of adding circle() and square() to Processing. I'll speak with @benfry about it. For context, the language was originally designed for university students. In that situation, ellipse() and rect() for circles and squares are not an issue and having extra functions to do the same thing as ellipse(x, y, d, d) and rect(x, y, w, w) was just more functions to clutter the language.

@tawez
Copy link
Contributor

tawez commented Oct 26, 2017

  1. I agree with everything that @sixhat wrote in Feature request/discussion: Simpler for loop syntax #1990.
    I think that we shouldn't obscure the nature of JavaScript using meta language and instead, promote constructions and statements built in the JavaScript.
    It’s just a matter of bunch of examples.

    I think that introduction of Python like range function would be a good idea.
    It may return generator to be compatible with many JavaScript loop statements.
    All necessary elements to do this are quite well supported in most of the browsers (except of the IE11, but I'm not convinced to support IE at all).
    I may make PR that introduce range function.

  2. I like randomInt and randomFloat names.
    If we are not convinced with rect name, will rangef be a good path to go?

@limzykenneth
Copy link
Member

limzykenneth commented Oct 26, 2017

Some of the points were brought up in the past and there's discussions around them while not necessarily conclusive, it would be helpful to add more opinions building on them.

  1. Make the fourth argument of ellipse() optional? #1368 which is also the reason why there is a 3 argument version of ellipse()
  2. As @meiamsome mentioned Feature request/discussion: Simpler for loop syntax #1990 contains similar suggestions and discussions
  3. Make it possible to pass an Array into random() #1331 while suggesting random([array]) also provided some discussions on naming the function

Below are some of my thoughts, although would be more or less rehashing my comments in those issues:

  1. I'm still in the camp of not making the fourth argument optional and a circle function to take 3 arguments still sounds good to me 😅. However, I don't think making circle and ellipse aliases and have the same function works, as mathematically they are different and I think it may confuse someone learning mathematical terms and p5.js at the same time (elementary school maybe?). The same goes for square.
  2. Same as @tawez and @sixhat in Feature request/discussion: Simpler for loop syntax #1990, I think we shouldn't go down the meta language route. p5.js should be a gateway into Javascript and coding in general so abstracting fundamentals such as loops feels like it can impede progress when moving forward. As @meiamsome mentioned, for...in loops may be a good solution to doing a simple repeat without resorting to the traditional for loops.
  3. I think I prefer randomInt and random (integer version and float version) to randomf and random() (the reverse). Only because it feel more inline with Javascript as a language: all numbers are floats and integers are really just floats with nothing after the decimal points.

@wjmoner
Copy link

wjmoner commented Oct 26, 2017

I'm using p5js this year to teach Javascript to beginners, so I am in strong agreement with @tawez @sixhat and @limzykenneth that the language should include the core programming processes common to programming languages.

@wjmoner
Copy link

wjmoner commented Oct 26, 2017

That noted, I'd love to have the ability to center any type of shape on an axis by introducing, perhaps, a shape mesh that could provide a nine-point registration grid ... because perfectly centering a triangle on a central translation point is tedious for the mathematically-challenged!

@meiamsome
Copy link
Member

meiamsome commented Oct 26, 2017

@limzykenneth Althought the same in this case for...in is a very different beast to for...of and this leads to this approach being less beginner friendly than it perhaps could be!

@tawez I was considering making a PR for an iterator range but I don't know if you can write iterators that don't break backward compatibility. It looks like you can, though. I'd be happy to try to whip up a range that had feature-parity with python's range whilst being backwards compatible

@limzykenneth
Copy link
Member

@meiamsome Ah yes, my mistake, I meant to say for...of. for...in have different implementation details than for...of.

@makeyourownalgorithmicart
Copy link
Author

I'm not an expert but I managed to create a circle() and square() primitive by adding them to src/core/2d_primitives.js by duplicating much of the existing code for ellipse() and rect().

A test sketch shows it works.

If that's the the correct way, I'd be happy to submit a PR.

In effect this is creating aliases but with different parameter handling.

@tawez
Copy link
Contributor

tawez commented Oct 26, 2017

@meiamsome According to https://github.com/processing/p5.js/wiki/Supported-browsers
IE11/10 is supported.
However, this page is dated 2 Aug, 2016 which means, it is... a bit outdated.
Do we really need to support IE at all?
This translates directly into code and performance.

IMHO supporting IE nowadays is like supporting IE6 a few years ago.
Edge is quite good (this is what I've heard).

@meiamsome
Copy link
Member

I did not know that page existed - I was assuming that there was just a general want to be pre-ES6. My main issue with generator using the function* syntax is that it breaks the entire library because it would be a syntax error rather than partially working.

@benfry
Copy link

benfry commented Oct 31, 2017

Responding to Casey's note above, some background on where these decisions came from originally…

  • circle() and square() seem fine. We didn't have them in the original version of Processing because we've always tried really, really hard to minimize the number of functions. The idea that a circle is a kind of ellipse isn't much of a leap for beginners in actual practice.
  • rect() instead of rectangle() is similar… The slight awkwardness of the function being called rect() is far outweighed by not having to type out the much-longer word. I've never taught a group of students who were tripped up by this.
  • We don't use randomInt() because in the majority of cases the float value is what people want from random, and randomInt() adds a new method that can be done with int(random(x)). You'd only be saving a single letter of typing, and have to add a new function to the reference, and maintain it in the code. Once you actually need an integer version (in the context of graphics coding), it's probably time to learn about int() anyway.
  • Throughout, we stayed away from things like randomf() or randomi() which are used in APIs like OpenGL. They're nice and descriptive for people who are familiar with programming, but it's just one more syntax headache for the people getting started.

@bmoren
Copy link
Contributor

bmoren commented Dec 5, 2017

I've got to agree with @benfry that int(random(x)) is the way to go. its much clearer and it is a great way to continue the discussion about functions returning things. Perhaps this strategy could be added into the random() documentation page? randomf() feels like it would become really opaque when a student has only in introduction to the distinction between floats and ints.

I've also got to agree that the ellipse() and rect() have never tripped up any of my students in the past, but I don't really see any issue with having square() and circle() as aliases as long as there is parity in the functionality.

Its likely pretty straightforward to wrap all of these ideas up into a little library which could extend or further abstract p5.js to your liking. It could be as simple as just passing variables on depending on how complex or how much feature parity you want:

function draw() { 	
     circle(200,200,50,50)
     square(20,20,100,100)
}

//~+~+~+~+~+~+~+~+~+
p5.prototype.circle = function(x,y,w,h){
     ellipse(x,y,w,h)
}

p5.prototype.square = function(x,y,w,h){
     rect(x,y,w,h)
}

@ChristerNilsson
Copy link

Or shorter

circle = ellipse
square = rect

I prefer

circle = (x,y,r) -> ellipse(x,y,2*r)
square = (x,y,s) -> rect(x,y,s,s)

I use
range = _.range

I like lodash random

@makeyourownalgorithmicart
Copy link
Author

I think there's an assumption that "students" means undergraduate students.

My experience includes younger learners of the age 6 to 12. In this case, the difference between ellipse and circle is huge, as is rectangle and square. Similarly int(random(x)) is just too much compared to the lower barriers that a potential randomNumber() would.

Today I helped teach a class at a UK university to first year under-graduates. C/Java/Javscript style loops are an enduring pain compared to something like Logo:

repeat 4 [
forward 50 right 90
]

Logo was created in 1967!

The option to have simple repeat as well as a more complex for(start; condition; stuff) would be good because it doesn't take away the capabilities this it provides. p5js provides for (x of list) is simple and I'm not sure the Java based Processing provides it ..

My final thought - Processing should be made accessible to non-technical artists as well as children learners of age 7-12 too. Design thinking means thinking about how the user experiences p5js, not just a core developer's perspective about overlapping functionality and redundancy of functions.

@sixhat
Copy link
Contributor

sixhat commented Feb 23, 2018 via email

@makeyourownalgorithmicart
Copy link
Author

most 7-12 year olds and non-technical artists coming to p5js don't really. understand this statement "feature of a language with a feature of a library".

It is a valid point for a core developer - but not for the user.

Similarly while(condition) needs further boilerplate like a variable to be tested. That really isn't easier than "repeat 4".

Anyway I've tried several times to get p5js developers to think about the Processing foundation's own objectives, but I guess I will move onto other tasks. Thanks everyone for your patience!

Our mission is to promote software literacy within the visual arts, and visual literacy within technology-related fields — and to make these fields accessible to diverse communities. Our goal is to empower people of all interests and backgrounds to learn how to program and make creative work with code, especially those who might not otherwise have access to these tools and resources.

@ChristerNilsson
Copy link

ChristerNilsson commented Feb 24, 2018 via email

@sixhat
Copy link
Contributor

sixhat commented Feb 24, 2018 via email

@bmoren
Copy link
Contributor

bmoren commented Feb 24, 2018

@makeyourownalgorithmicart I'm not a core developer but as a responder to this thread I can say that when I say my students, I do mean my undergraduate students. I think it's awesome that you are teaching p5js to 7-12 yo's and that perhaps whats been discussed previously in this thread has been geared toward an adult beginner rather that a young beginner. Of course those students are going to have a hard time getting a for loop down at first.

I can see both sides of this argument, particularly with the forloop discussion.
One one hand you have the simplicity of

repeat(5){ // block to execute}

Which allows instant understanding, but will make engaging with a native loop at a later time require a more in depth re-learning of loops. This is probably not an issue for 7-12yos who will take the idea and run as they progress.

This however is more problematic for the older beginner student who often has direct ambitions and desires for the language and often times want to immediately use the power of the i in the loop against an array, offsets, nested loops, or other more advanced topics withing JS (outside of straight repetitions of code blocks). In this case it's much better to just get to the for loop or a variable inside a while loop going immediately. I typically start with a while loop since it's such a nice transition from if/then conditionals.

let i = 0;
if(i < 5){
i++
//codeblock
}

is so similar to and a nice transition into

let i = 0;
while(i < 5){
i++
//codeblock
}

but, I can see how

let i = 0;
repeat(5){
  i++
    // codeblock
}

would be appealing for young beginners

I suppose that my ideal scenario for this situation would be to have a p5.kids library which would introduce things like:
randomNumber() which returns an Int
circle(x,y,size) which draws a circle
square(x,y,size) which draws a square
& some kind of loop like repeat(5){ //codeblock} or similar.

As I'm sure the kids are starting with a template or using the web editor it should be easy enough to put together a boilerplate project for them to start from.

I'm sure there are more things which could be abstracted for young beginners within this library too. I'd be happy to start work on something like this as it seems like it could be cool & fun, but is likely outside of what is possible to be supported directly in the p5js library without breaking too many things & plotting a course to changing p5.js into it's own fully abstracted language ontop of JS instead of being a library which rides ontop of the JS to facilitate canvas operations.

@lmccart @shiffman @benfry would have more ability to respond to the community statement than I. But, I do think simply stating that Processing Foundation is not adhering to the mission because of not including a few functions reads as misdirected frustration. There are a lot of scales to balance working on FLOSS projects and PF does an amazing job in having an open and honest conversation about the limitations of themselves and the projects they run. It's not always possible to meet every need, desire or proposed direction. With that, this is exactly why OSS projects are so amazing – because they let people build on top of them, add to them, and expand. So I propose we do just that – by making a library on top of this library just for kids learning. One that is specific to, and suited just for them! What do you think?

@makeyourownalgorithmicart
Copy link
Author

@bmoren - thanks for your thoughts, and also understanding.

I agree with your suggestion is great. An additional library wouldn't break the existing p5js and wouldn't upset those who want to keep such ideas out of the core.

I have on suggestion in response to yours - rather than a develop centric approach to developing a p5.kids library - we apply a filter for every suggestion to ensure that the proposals are based o actual user research. I'm sure this can be done proportionately - even a set of observations that "ellipse" scares people away but "circle" does not .. or the observation over several classes that kids are finding it tough to get over "int(random())". That way all features have a rationale and basis.

In the coming months I will get more experience with teaching younger people, and also non-technical artists, some who have never coded before .. and I hope to write down my learning.

Thanks everyone who commented.

@makeyourownalgorithmicart
Copy link
Author

@bmoren - I'm not an expert coder but I've made a start with a library to make entry to p5js even easier for new and young coders

so far I've implemented and tested:

  • circle(x, y, radius)
  • square(x, y, size)
  • randomNumber(n) for integers up to n .. result could include n, unlike random()
  • randomNumber(a,b) for integers in range [a,b] .. results could include a or b, unlike random()

I'm trying to think how I might implement a simpler loop like repeat 5 {}. Suggestions welcome.

I'm also working on test sketches to accompany this library to demonstrate (and test) the new functions.

Blog write up: http://makeyourownalgorithmicart.blogspot.co.uk/2018/03/p5-simplejs.html

@bmoren
Copy link
Contributor

bmoren commented Mar 29, 2018

I was trying to figure this out and was running into walls, does anyone here working on p5 have any ideas? Stack overflow was quick to make it even more complex than a while loop.

https://stackoverflow.com/questions/49041124/creating-a-custom-loop-for-children-to-use-eg-repeat5-code-to-be-executed

Good work getting it started, I will say that I think radius is much more difficult than diameter for circle.

@limzykenneth
Copy link
Member

As far as I can think, I can't come up with any solution in JS syntax that can make something like repeat 5 {} work, that is also the reason why this feels a lot like meta language programming in the discussion above and I suspect won't be implementable short of creating a new language that compiles to JS which defeat the whole purpose really. Unlike lower level stuff like C/C++, JS doesn't like its syntax messed with 😞 . You can try self executing functions (repeat(5))(fn) or something along those lines but the syntax is too funky for beginners in my opinion.

As mentioned in the stackoverflow question, the closest you can get may be a lodash style repeat(5, fn) but then maybe introducing loops may be easier at this point...

@makeyourownalgorithmicart
Copy link
Author

@bmoren - thanks for the feedback and encouragement.

I haven't solved the issue about a new kind of structure for loops - the more I read about javascript the more I realise it will be very hard, and even impossible to do elegantly.

I wanted the user to have some nice default when they first start coding - for new these are: noLoop() because loop() confuses beginners when creating random patterns, stroke weight that's actually visible, and a default fill colour

Sadly I can't make these happen upon invoking simple.js as I think they need a p5 context already set up? So for now we have to use a simple() in setup() to invoke these.

Is there a way of invoking these defaults without the need for a call from setup() .. that, only the inclusion of simple.js with <script> after p5.js being necessary?

also for the circle() command .. I did some quick research and yes, people do seem prefer diameter so I've changed that back

@limzykenneth I'll look at the lodash style .. it may be the best compromise for now.

@makeyourownalgorithmicart
Copy link
Author

I've started a wiki on GitHub to

  • explain rationale for each change
  • detail the instruction
  • point to an example or test

https://github.com/makeyourownalgorithmicart/simple.js/wiki

@makeyourownalgorithmicart
Copy link
Author

I won't bore anyone with too many more posts, but I've implemented a repeat(n, my_function) which I am happy with as a compromise given what is and isn't possible with Javascript.

wiki - https://github.com/makeyourownalgorithmicart/simple.js/wiki/repeat()

@kjhollen
Copy link
Member

Cool, @makeyourownalgorithmicart! Does this mean that you usually teach the students how to write functions before they learn to write loops?

I'm also curious how beginner students react to seeing a function as an argument to another function? I usually don't include this in a beginner class, because it seems difficult to me—but I've never been sure if that's because I learned languages like Java and C++ before JavaScript. I wonder if students learning JavaScript as their first programming language are more open to this, or don't find it strange.

@makeyourownalgorithmicart
Copy link
Author

@kjhollen - I didn't want to teach functions before loops - and in languages like Python this is fine.

But javascript's for loop is so problematic that - in my experience - students have understood the idea of functions far more quickly and comfortably. I still have 1st year undergraduate students (arts background) who 7 weeks into their creative coding course still can't construct a for loop, but they're very happy with functions as re-usable named code.

I know from a technical perspective the idea of functions and higher-order functions is seen as advanced .. but they don't see that .. because there's no need to talk theory of meta-programming or functional programming.

I also have a daughter who was coding since age 5 - beginning with scratch with avoids typing any code yet introduces the key ideas of loops and logic tests. She progressed onto Python easily. Logo is easy too (REPEAT 5 [FORWARD 10]) .. but C/Java/JS for loops are a pain.

Anyway - thanks for your question and thoughts. What I'm finding is that many of the challenges are coming from people who are already technically comfortable and their experience is not that of new / young / non-technical coders.

@makeyourownalgorithmicart
Copy link
Author

I've now implemented 2 forms of repeat():

  • repeat(n, fn) repeats n times the function fn
  • repeat(start, end, step, fn) calls fn(x) where x starts at start, increments by step, until it reaches end

documented on the GitHub wiki: https://github.com/makeyourownalgorithmicart/simple.js/wiki/repeat()

@makeyourownalgorithmicart
Copy link
Author

@bmoren - I've fleshed out the repo with examples, tests, documentation, wiki and even a tutorial:

https://github.com/makeyourownalgorithmicart/simple.js/wiki/Tutorial

I'd love feedback on improving this nascent simple.js.

@ChristerNilsson
Copy link

ChristerNilsson commented Apr 5, 2018

I'm using Coffeescript and p5.
Made my own versions of background, fill and circle.
range is taken from underscore.js.

@makeyourownalgorithmicart: I can't see how the loop variable is accessed in your code.
How would you handle a double for loop?

My site:
Tested on kids 7-17 and retired people.

Within p5Dojo:
repeat2

Outside p5Dojo:
repeat

@ChristerNilsson
Copy link

Using nameless functions instead makes it possible to have loops in loops without using global variables.

image

@makeyourownalgorithmicart
Copy link
Author

makeyourownalgorithmicart commented Apr 7, 2018

@ChristerNilsson - really interesting you've done, i'm going to explore it more :)

PS - i don't cover the case of loops within loops .. but it is possible by habing a repeat() inside the function called by repeat().

I've only wanted to cover the simple cases - not the more advanced cases because it is the new coders that find for loops difficult.

@gregja
Copy link

gregja commented Jun 1, 2018

Thank's a lot for this interesting discussion, sorry to arrive so late.
Primitives are useful for beginners, but I think it's important to teach them also how to create their own primitives. For example, learning to create their own circles, without depending on the ellipse () function, is very interesting to discover the basics of algorithmics. That's what I tried to teach in a tutorial that I wrote for a French-speaking audience (in pages 53 and 58).
https://github.com/gregja/p5Corner/

@kjhollen
Copy link
Member

kjhollen commented Jun 6, 2018

hey folks, I'm going to close this because it feels like the conversation has mostly wrapped up—but please feel free to open new issues for specific feature requests (like circle() etc). It's a little easier to track things if we have them broken into smaller items so people can sign up to work on them!

We've also got a brand new forum that can be great for future discussions like this: https://discourse.processing.org/ thank you all for a productive conversation.

@kjhollen kjhollen closed this as completed Jun 6, 2018
@makeyourownalgorithmicart
Copy link
Author

Thanks @kjhollen - as OP I agree the conversation has moved.

I implemented a simple.js to address most of the issues.

I still think changing core processing would make it more open to more diverse communities of people.

I respectfully disagree that it should be done in pieces - as that leads to the current state where circle() or sqaure() is rejected because it is seen as duplication - in the narrow view. But in a wider view conscious of a broad ambition and strategy (promote to more people, kids coding, first time artist coders) then a whole series of changes can be considered as a coherent change.

@kjhollen
Copy link
Member

kjhollen commented Jun 8, 2018

Thanks for the feedback. I still encourage you to file issues to track requested work items for the core library—for example, one for circle() and another one for square(). These were not rejected! I think no one picked them up to implement from this issue because when they browse through the github issues, the title of this issue doesn't make it obvious that is what is needed here.

Filing issues for smaller work items makes it more likely that someone will find and implement the features—and that they can take on concise, contained pieces of work even if they don't have time to implement a huge feature or overhaul. In the future, we're working toward having a project roadmap that will make it clearer how a collection of features are scheduled for release and why those features were chosen. The smaller issues are the detailed todo list for the bigger goal and helps us track progress. :)

@makeyourownalgorithmicart
Copy link
Author

just to say that open processing.org has now added simple.js as one of its optional libraries

dhn2rfow0aix6ve

@makeyourownalgorithmicart
Copy link
Author

support for nested loops now included

https://github.com/makeyourownalgorithmicart/simple.js/wiki/repeat()

three_forms_of_repeat_simplejs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests