Sniff is a "Scratch-like" programming language that's designed to help Scratchers move gently from Scratch to more conventional languages. They can start writing programs, without having to learn a new language because Sniff is based on Scratch. They learn a little more about variables, compiling, syntax errors (!), and they can have fun controlling real hardware while they're doing it.

Tuesday, 3 March 2015

Release 16: Now with extra Syntax

One of the "rules" when we designed Sniff was that it would be Scratch written down. We didn't want to change anything unless we had to. While we say that Sniff is a "language" its probably more accurate to say that Sniff and Scratch are different implementations of the same language.

We therefore think very carefully before changing anything, so this release is a bit unique. We've added a couple of features to the language! These are things we feel are really necessary due to the extended scale of Sniff projects - we've now got programs like the Sniff IDE written in Sniff which is over 1000 lines of code.

repeat times using numvar

Scratch doesn't have a "for" loop. If you want to count you need to use a repeat loop:

.set x to 1
.repeat 10
..say [x]
..change x by 1

The problem is that the "change" at the end of the loop is essential to the loops operation, but is physically separated from it, which means its easy to loose track of it (or forget it all together). We struggled to work out a suitable "block" that would meaningfully express the problem, but the problem is that while its simple enough to get over the idea of iteration, its harder to succinctly express the idea of iteration with in index. The traditional programming phrase is a for...next loop, but that means absolutely nothing to non-programmers.

However when working on the recently posted OCR exemplars, and having written the above code five or six times we realised who it could be done:

.repeat 10 using x
..say [x]

We're going to go around 10 times, using x as the counter! Simple, clear, and importantly: a lot like the loop we already have.

It's not as versatile as the C for loop which confuses every new programmer, but it handles the basic case very clearly. We've started using it, and have when updating a couple of the examples to use it have found it pretty handy. You can always fall back on repeat until if you need something more complex.

Local Variables

When writing larger programs the biggest worry is that you have to make sure that the variables used by one script aren't being used by another:

make counter number

when doIt
.repeat 2 using counter
..say [ counter ]

when start
.repeat to using counter
..broadcast doIt and wait
..say [counter]

Instead of printing out 
1,2,1,1,2,2,1,2,3,1,2,4...

This will print 
1,2,2,1,2,2,1,2,2,1,2,2...

When we run doIt it changes counter. That means when we're writing start we need to check that doIt doesn't use counter (or check that it does it thats what we want). In a large program this becomes a nightmare, as calling any other script could mess with any of your variables.

when doIt
.make counter number
.repeat 2 using counter
..say [ counter ]

when start
.make counter number
.repeat to using counter
..broadcast doIt and wait
..say [counter]

Here we've made counter a local variable. It only exists inside the functions and each function has its own version so they can't mess each other up. This isn't something you need to learn straight away - in fact its probably best to just get on, use regular global variables, until you get yourself in such a mess that you understand why local is such a good idea.

There are a couple of restrictions - variables need to be declared immediately after the "when", so that your whole script sees them. You can can't create input, outputs or devices - this would make no sense (or little sense, most of the time - yes there are cases where it might be slightly useful, but you can't do it, so get over it). Generally the "device" is something that actually exists - a piece of hardware, so it doesn't make sense for it to pop in and out of existence as your program runs. You also need to make sure that variables used by a device are global. The device can't see your local copy!

New Names for List data types

As we were working on the code that handles variable declarations anyway, we thought we'd finally fix something that's been niggling for a while. Now instead of creating a "list of number" you can make a "list of numbers". List data types are now plural!

For now we'll be supporting both the old singular version and the new plural version, and see how it goes, but we may phase out the old singular version in the future.


We don't take these changes lightly, but they come after over a year of experience programming in Sniff. In that time we've learnt what the language should feel like, and the size of our examples have grown by a factor of 100 (10 lines of Sniff can do quite a lot - we never expected to write 1000!). We think these are a step in the right direction.

Other Features of Release 16

Ethernet and Minecraft now work on Windows
Wedo supports raw access for homebrew hardware like the thermometer
OS X Windowing is MUCH faster
Support for 32bit OSX.
Additonal fixes and updates

Download

The new versions of Sniff, Release 16 are available on the downloads page. As usual there's a Windows, and Unix (Mac/Linux/Pi) version.




No comments:

Post a comment