processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.4k stars 3.28k forks source link

3 suggestions for making p5js easier for newcomers #2305

Closed makeyourownalgorithmicart closed 6 years ago

makeyourownalgorithmicart commented 6 years ago

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 commented 6 years ago

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 #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 commented 6 years ago

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 commented 6 years ago
  1. I agree with everything that @sixhat wrote in #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 commented 6 years ago

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. 1368 which is also the reason why there is a 3 argument version of ellipse()

  2. As @meiamsome mentioned #1990 contains similar suggestions and discussions
  3. 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 #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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

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

makeyourownalgorithmicart commented 6 years ago

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 commented 6 years ago

@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 commented 6 years ago

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 commented 6 years ago

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

bmoren commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

Let's not confuse a feature of a language with a feature of a library.

P5.js is a library whose language is Javascript. People tend to bash loops as difficult for newcomers because of the for loop, but if you look at the while loop in JS it is as simple as the repeat in Logo and probably the place to start if you want to teach loops. 

while (condition) {    code block to be executed }

https://www.w3schools.com/js/js_loop_while.asp

Cheers

makeyourownalgorithmicart commented 6 years ago

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 commented 6 years ago

What is your suggestion? Please state this in normal javascript code.

On Sat, 24 Feb 2018 at 21:14, Make Your Own Algorithmic Art < notifications@github.com> wrote:

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.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/processing/p5.js/issues/2305#issuecomment-368256463, or mute the thread https://github.com/notifications/unsubscribe-auth/ADRyi7nff6L2mHPrdSj9qi7pPUjpPFGAks5tYG2IgaJpZM4QGyJr .

-- /Christer Nilsson 070-749 6800

sixhat commented 6 years ago

This discussion has been very instructive. I've  learned that Logo has both for loops and repeat loops---JS has corresponding for loops and while loops. What I don't understand is this need to ask a Javascript library to be written as Logo( or any other language) and not even compare the corresponding equivalent constructs in the arguments used. 

bmoren commented 6 years ago

@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 commented 6 years ago

@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 commented 6 years ago

@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:

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 commented 6 years ago

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 commented 6 years ago

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 commented 6 years ago

@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 Githubissues.

  • Githubissues is a development platform for aggregating issues.