Cool I'll check this out. Always looking for good VM tech to cover the different OSes I test over.
Thanks for the info
Cool I'll check this out. Always looking for good VM tech to cover the different OSes I test over.
Thanks for the info
do note that (given enough resources) a chrome os vm might run faster than an average chromebook (chrome os is built to be lightweight for low-power systems, such as systems with low ram, low-power cpus, etc.). try looking up the specs of different chromebooks and adjust your vm settings accordingly for a more accurate experience.
Hmm, is your complaint that we don't have those exact procedures as primitives? Because of course we do have higher order functions:
Even more importantly, we have lambda! So both our favorite HOFs and your favorite HOFs can be written in Snap! itself:
More generally, Snap! isn't a "tiny" language. If you separate the collection of libraries written for a language with the language itself, our language includes the Lisp ideas of first class functions and first class lists, the added Scheme feature of first class continuations, the Object Logo OOP capability with first class sprites with prototyping inheritance (real prototyping, not the class-instance-in-disguise abomination of JavaScript), and the APL extension of scalar functions to arbitrary-dimension arrays:
If there's an important language capability we're missing, please let me know!
A very small UI suggestion: Instead of turning the frame red when you pause, turn it yellow. Red means stop, yellow means pause.
LOL no not at all exactly the opposite of a complaint. I was illustrating that even someone who had mastered the use of all those different HOFs (The QOL ones that are just variations like for instance you have a Take [Keep] but no Skip etc.) could still learn something from a language like Snap. Even if it was rediscovering what had long ago slipped into just abstract levels of understanding what it does.
I'm not a teacher I work in IT, but I have taught so many people over the years mainly programming. Be it taking someone to the next level, or training a green HelpDesk user the BASICS of filtering to get to the information they might need, or training an entire department how to use advanced mapping to aggregate and organize complex data structures. I firmly believe in a language like that and I find it a little odd knowing that the personality of the language (And Snap ooooozes an amazing personality) DOES affect how easy it is to engage with your learners people would so vehemently fight against ideas of embracing that.
PowerShell for instance isn't visually different and real world familiar like Snap but it has an incredibly powerful system agnostic way of dealing with hierarchical data in a crazy elegant way. To a brand new programmer might not seem all that excited. But to someone well versed in the manual traversal of various systems learning they can apply the exact same commands in the same order to retrieve, filter, map, and display data from each of those systems its exciting, its engaging. Snap beautifully fits that bill for being engaging
Exactly my point I don't NEED to understand how a SkipWhile()
, or an Aggregate()
, or a ToDictionary()
work algorithmically to do my job very well. But given a language like Snap that deliberately leaves out all those QOL HOFs you can still find a path TO them while relearning core concepts you might find creative ways of using in your future work. Heck several times I've used the idea of as an exercise of IN CLASS recreating from the base language things like Where()
for my advanced students to demystify something they might have been using for years at that point and just views as this uber powerful black box that HAS to be SO FAR beyond their meager ability to understand how it works. Sure they understand WHAT it does and how to use it but the code MUST be long and complicated. When we puzzle out the logic together and we get to the end and they inevitably go "That's IT?!?!?!" its awesome seeing that light of understanding igniting other thoughts. They leave excited and invigorated to explore other areas they might have just assumed to be too complex for them to grasp on that level.
I was generally speaking in a relative frame of mind as well as a learners perspective when I say tiny. Compared to the amount of out of the box functions available TO the learner it IS a very small subset of options. The fact that in that subset are all the means to build ANYTHING including the QOL HOFs is a testament to how amazing this language is for teaching and learning.
Take your humble looking
This language managed to take the concepts of ALMOST TWENTY functions and presented them in a way where the user has to think about just ONE function. That is incredible, and dare I say an example of this language being TINY. Again as it pertains to the perception of how much a new learner has ahead of them to digest and understand. Some people might look at 20 separate functions and go "There's NO WAY I'm going to learn all of those and remember them!" But ONE function oh that FEELS a lot tinier, a LOT more manageable, a lot less scary. All those other 19 variations get learned in the end but the perception is more along the lines of "Oh this thing I've been using to get the length of things will also give me the log of something!. That's super easy" That feeling is all over this language and I'm genuinely impressed with how well this language works as both a whole heartedly legitimate language and as a gentle unintimidating means to get someone brand new into the joy of coding.
I was going more traffic light vibe where Yellow means caution not necessarily stop. Kind of a red, light green light kind of thing.
Ah, now I understand. Right, we're Scheme, not Common Lisp. :~)
I don't think there was any deliberate decision to leave out your hofs; I never heard of them until this discussion!
In our early days we tried to make it a rule that anything that could be written in Snap! wouldn't be included as a primitive, because writing all those procedures is such a good exercise. But alas many computations were just too slow.
I spent probably the largest part of my programming career working in C# so I'm a DIE hard LINQ user. In my mind it is one of the BEST examples of structured data manipulation logic embedded in a classically OOP language operating in a functional manner. They have an entire library of data manipulation methods that literally attach themselves via what are called extension methods (A way to attach a method on a sealed/closed whatever your language calls it class). They are verbally aligned with ISO-92 SQL so you can do things like
DataFromDB.Table.Where(item => item.Age >= 40).Where(item => item.LastName = "Smith").Skip(10).Take(10).Select(item => item.Age).Aggregate(0,(ages,age) => ages + age)
Because everything to the left of Aggregate is effectively SQL DML you can just generate an expression tree, walk it and generate the actual SQL query. Which is exactly what the .NET data providers do.
This means I can operate over data in my OOP language in the same thought process I use when working directly in SQL which i think is incredibly useful.
Pretty much all of them operate off of Lambda expressions you have things like
The chainability of all but the scalar methods leaves for VERY readable and at least conceptually SQL adjacent methodology.
The fact you can apply the exact same ideas to non DB sourced data is where you find the majority of its use. PowerShell for instance has its own sets of Cmdlets for these kinds of things Where-Object
, Group-Object
, Select-Object
, Sort-Object
, ForEach-Object
, etc. I can just as easily apply them to filter out particular files from a directory, as I can filtering out a type of Key from the registry, as I can RegEx matching lines from a text file, as I can filtering out actual table data from a database, as I can parsing through an XML or JSON doc.
I get that. Its a hard balance to have. I would argue though that the novelty of being able to actually build them in the language as a proof of concept is far more valuable than them running quickly. The point is to learn so building these kind of HOFs and visually seeing how they come together can help to cement those ideas so when your students move on to languages that DO have the speed and power to write those kinds of HOFs or actually HAVE those HOFs they won't just be treating them like little unknowable black boxes.
I'm of course a clear novice with this language but I would think that you get around the slower HOFs that are not practical to implement IN Snap! by offering them as compiled libraries. If I was teaching Snap! I would make it a multi semester course, possibly multi year. For my first semester/year class we would completely avoid ANY libraries. Base language nothing more. Over the semester/year we would build up the fundamentals all the way up to building some of the simpler HOFs IN Snap!. Year two we'd dive right into working out ALL the HOFs including the kind I listed above. As we complete a block of them, I'd introduce a Library that has all those HOFs but in a faster pre compiled format, and let them use that Library moving forward. Year 3 would continue that trend building their fundamental understanding of those HOFs until at the end they have access to multiple libraries of fast HOFs but they can use them to their maximum potential because we spent the time demystifying how they work.
Speed and compiling: Your idea would be plausible if in fact we had a compiler! We have a sorta-kinda experimental compiler for a simple subset of expressions.
Speed and pedagogy: We want to have our cake and eat it too about this. So right now in the dev version if you click on "blocks all the way" in the settings menu, all the primitives are editable, and you get internals like this one:
So, that's great for learners! But one pedagogic problem with respect to HOFs is that they have so many bells and whistles that instead of
So maybe we need a way for the scripts users see not to reflect the full featurefulness of the primitives? I dunno.
As for your multi-year curriculum, you are a bottom up person. The equivalent pedagogic stance in the traditional CS curriculum world is to start with a programmer's view of machine architecture (i.e., not gates or transistors), then teach C, then teach Java and data structures. By contrast, since SICP we've been a top-down school; start at the highest possible level of abstraction and work down to architecture in the third semester.
I definitely wasn't coming at Snap with any intention of changing anything. It's great the way it is. It's just fun from an educational perspective to consider ways something like this could enhance teaching a specific topic as scary and seemingly overwhelming as HOFs. That's also why my thought of limiting things to just libraries of "compiled" blocks would be ideal. You give developers the general schema of what a Command, Predicate, and Reporter looks like and they write their own in whatever web facing language they want as long as it outputs the necessary metadata to tell the scripts window what to render it as, and tells the Snap! script what its signature looks like, and finally its URI endpoint. All of that could be done with native JSON and you'd just have the microest of a microservice that just handles the heavy calculations and dumps the results back in JSON to be continued on with like it never left Snap! in the first place.
All that aside really not necessary. that's just me overthinking, and overengineering things. I've long ago grown out of the idea that if I had enough time I could write the perfect software to solve all my (and others) perceived (to me) problems. Though sometimes I feel the pull of how excited I got back in the day when I solved a particularly vexing problem with code even if the me now would be appalled at my code. I was definitely the walking, coding example of
"You clearly can, but SHOULD you?...."
I guess I should have clarified that in this hypothetical scenario my students would already have gone through things like Intro to Programming and learned things like scalars, simple data structures, advanced data structures, looping, branching etc. They'd be coming into the course/courses specifically to take their understanding from WHAT different DSs ARE, and WHAT methods are available to work with them to HOW do HOFs not just simplify complex DS concepts, but generalize them conceptually. You are absolutely correct you need the fundamental building blocks at the highest possible level of abstraction BEFORE you can even dream of tackling even something as simple as a recursive method. What's a condition? What's a branch?, What's an operation, What's scope? you NEED to understand those concepts abstractly or something like the Fibonacci algorithm, or an implementation of sigma notation summation is going to going to just be Greek to someone new. Understanding HOFs demands BOTH mastery of base level abstract ideas as well as intermediate level ideas like recursion.
I guess since I've mostly taught very small groups of people (max average 3 or 4) at a time I've gotten pretty fluid in adjusting how deep we get into things based on how I perceive their level of understanding to be. So some of my students I know I can dive literally into the deep end with things like HOFs, but others need their hand held through their first If-Else
I acknowledge you really can't do that with an actual classroom full of students
As you say, it depends on the audience. If you're teaching electrical engineering majors, it may well be easiest to start with what's actually on the wires in the chip and ease them into abstraction. :~)