Statements and expressions

856 views
Skip to first unread message

Chris Mountford

unread,
Apr 14, 2013, 8:25:28 AM4/14/13
to blo...@googlegroups.com
Hi All,

It seems like the blockly language has a strong distinction between statements, such as functions that return no value or assignment style statements and those that do have a value. 

Specifically, a Block will not permit init() to call this.setOutput(true, String) as well as this.setPreviousStatement(true);

This seems like a hard limitation and I'm not clear what the design intent behind this is.

Am I missing something?

cheers,

Chris.

Marc Wollenweber

unread,
Apr 16, 2013, 6:17:19 AM4/16/13
to blo...@googlegroups.com
Hey, 

I just answer what in my opinion could be a right answer (I'm not part of Blockly or google). 

My observation is, that a block can be used within a sequence and contains the notches at the top, etc. Another block can be added as an input.
If we look at the generated code (or the generator functions) we see, that the latter has a return value and the former not. 

The question is why do we need a block that returns a value and at the same time doesn't? you can argue that you want to use the return value in one place but not in another. Others might argue, why don't you just connect the block with the return value to a variable block and don't use it? Yet another might argue, if you never need a return value than just change the the block time from an output (value) block to a statement time.

Do you know what I mean?

If we look at beginners it might be more straight forward if we have a strict separation and not both possibilities at the same time. 

Still, I would like to hear your arguments and you might convince me that mine are wrong :)

best regards
Marc Wollenweber

Chris Mountford

unread,
Apr 16, 2013, 8:54:37 PM4/16/13
to blo...@googlegroups.com
Hi Marc,

Thanks for your thoughtful reply.

I think it would be better to enable a single block to return a value and also be executed without using that return value because it enables more block combinations to be made and fewer blocks used to achieve a goal.

We can implement our own blocks which work completely differently to the core blocks. For example, we can make a block that fetches a web page. Right now if I want to get the content of that web page sometimes and other times I just want to hit a URL and not look at the content, I would need to implement two blocks or use some kind of wrapper block (like Set Variable) that throws away the return value and provides the connection notch to the previous block. There are many uses for a Get Url block, some which need the response content and others which do not.

As for beginners, well if you're right and we shouldn't have both of them the block implementer can ensure this by designing the blocks accordingly. 

If there is *any* value in being able to make a block that can do both, then a block implementer cannot achieve it without modifying Blockly itself.

But real question is whether this is a deliberate design decision, and one that Blockly is sticking to. If it is, then it suggests Blockly is designed for an explicitly "imperative" programming style. This is a particular approach to programming which is contrasted with other styles.

Alternately, if this is just a current limitation that could be overcome while maintaining the Blockly philosophy then that's useful info for me and my project.

cheers,

Chris.



--
You received this message because you are subscribed to a topic in the Google Groups "Blockly" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/blockly/l22CIk5mrxo/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to blockly+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Chris Mountford


Neil Fraser

unread,
Apr 17, 2013, 12:35:50 AM4/17/13
to blo...@googlegroups.com
Take a look at the "in list x get x" block. This returns a value.
However, if you change the drop down menu from "get" to "remove", the
block changes shape so that it becomes a statement. So far this is
the only block to morph this way. It's an experiment.

App Inventor faced the same problem, and they created a dummy block.
See the last block on this page:
http://beta.appinventor.mit.edu/learn/reference/blocks/definition.html
So far Blockly has avoided adding this block, but we are open to it if
really needed.
> You received this message because you are subscribed to the Google Groups
> "Blockly" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to blockly+u...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>



--
Neil Fraser
http://neil.fraser.name

Chris Mountford

unread,
Apr 17, 2013, 9:01:49 AM4/17/13
to blo...@googlegroups.com, ro...@neil.fraser.name
Thanks for that Neil,

I'm still left wondering though, is the limitation an intentional part of the design of Blockly? What purpose does this limitation serve?

Consider the way the "in list x get x" block needs to also include a "get and remove" which would not be necessary if the block's "expression value" was optionally usable. I guess, reading between the lines, you see it as up to the block to mutate such that it is explicitly switched from return mode to non-return mode or vice versa. Is this correct?

The alternative is that blocks can always have a return value which is their expression value. A literal is itself. A variable dereference is the referent and a function call is the return value of the function. In this model there is no use for a distinction between a "procedure" and a "procedureWithResult" as found on the App Inventor page you linked, and no need for the "|" adapter block. The question of the value of blocks like "if (__) then ..." is something that can be decided by the block implementer.

If you're still experimenting you may choose to consider this option.

Let me know if this sounds like crazy talk.

Chris.

Ellen Spertus

unread,
Apr 17, 2013, 12:34:37 PM4/17/13
to blo...@googlegroups.com
I believe that Blockly has a similar design goal to App Inventor (which I worked on): Make things easy for the beginner.  For the longer version, see the appended section from the App Inventor documentation.

Given a choice between an API/UI that makes things easier for the beginner and makes the language easier for an expert to use, I will argue for the former.  Of course, it is best not to have to choose.  I'd be very interested in suggestions of how to allow statements to return values without (1) breaking the block/puzzle piece metaphor or (2) over-complicated the API.  See also the great Josh Bloch's API guidelines.

Ellen

The previously unwritten App Inventor design principles (which we have not always been successful at following) are:

Make it easy for the beginner

We chose to have the offset of the first element in a list be 1, rather than 0, because 1 is what a naive user would expect.  While this might make the transition to conventional programming languages a little harder, we’re more concerned with helping people discover the joy of computing rather than the details that don’t make sense until you’ve taken several classes.  Follow the Principle of Least Astonishment.  If you have to decide between astonishing a beginner or an experienced computer scientist, astonish the latter.


It is not always obvious what is easiest for the user.  Consider the numeric argument to the Sound component’s vibrate method.  We chose to make it milliseconds, which enables people to use whole numbers (500 milliseconds) rather than fractions (.5).  On the other hand, someone who doesn’t read the manual or doesn’t know what milliseconds are would probably start their experimenting with an argument of 1, which would cause an imperceptible vibration.  

Organize functionality in a way that makes sense to the user

Continuing our discussion of the vibrate method, a physicist might know to look for it in the Sound component, but most users would not.  Unfortunately, I don’t have a better suggestion of where the vibrate functionality should be, short of creating a new component whose name would make people snicker.


An example of good organization is having Camera, ImagePicker, and VideoPlayer all within the Media category.  Their implementations are totally different, but, to the user, it makes sense for them to be together.

Mobile ≮ Desktop

Mobile devices should not be considered to be desktop (or laptop) computers with small displays.  Focus less on functionality that works better on a large screen than a small screen, and focus more on functionality that takes advantage of mobile devices’ unique features, such as portability, connectivity (SMS, BlueTooth, NFC, etc.), sensors (acceleration and location), and recorders (audio, photographs, videos).  This principle suggests it would be better to develop components for data collection, taking advantage of all of these features of mobile devices, than to develop, for example, the capacity to display multiple videos on a single screen, which could only be done poorly on (existing) mobile technology.

Provide default values

Users should not have to understand all of a component’s properties in order to use it.  For example, new Labels have reasonable default values for all of their properties except for Text (which has the self-explanatory initial value “Text for Label1”).  This enables someone to begin using a component quickly and only look at other properties when dissatisfied with the default behavior (such as a label being hard to read on their chosen Screen background image).  By not requiring the user to understand properties until they are needed, this makes them a solution rather than a problem.


Similarly, reasonable default values should be provided for built-in blocks.  The parameter to the “make color” block is a list that must contain elements with the values of the red, green, and blue components and may optionally contain a fourth element with an alpha level, something that most users will never need.  (The downside of taking a single list parameter instead of one parameter for each numeric input is that the socket labels are less meaningful.)



Chris Mountford

unread,
Apr 17, 2013, 11:32:57 PM4/17/13
to blo...@googlegroups.com
Thanks Ellen,

I'm getting the impression it's a not a deliberate design choice but now the shapes are established and changing them would be too much work or it's not clear what alternative there is. 

For the record, I'm asking about something that enables more block types to be implemented, to enable implementing some blocks that will be easier for beginners to use! Surely the "|" block is obscure! It's an adapter. Is the block morphing as discoverable as static shape connections? 

As for a proposal, we're talking about a visual design of blocks such that it's clearly possible to connect a block that is capable of recieving the expression value of another block (right now that is achieved with a left side plug and right side socket) and simultaneously show that value block as connectable to the top and bottom (which implies execution ordering?).

It would presumably be unacceptable to allow a dangling plug on the left, I assume the user is supposed to know that a program is not "good" until all puzzle ends are docked. 

Is it possible to have an indent on the left such that it doesn't stick out and be OK with the idea that it need not be filled? This means the consumer of this block would have the convex shape on the right (assuming you maintain the left-right connection chain for value passing).

Does this break the puzzle piece metaphor? Perhaps this metaphor is the root cause of the modal thinking on expression values. If a connection has to be filled (like a puzzle) then you are forced to visually distinguish those blocks that can connect from those that cannot. By contrast, connecting top and bottom notches is optional. Perhaps this is why the shape is a smaller dimple. Top and bottom notches are not seen as confusing or difficult for beginners are they?

The API would not need any change in interfaces, only the removal of the implemented restriction. 

Another possibility is to use containment docking (which is nicely suited to the construction of composites). This is already done with the IF and REPEAT blocks and the blocks that go inside do so optionally. They can be used inside the IF, after it or on their own. So an expression value block would optionally dock into a consumer of that value.

A third possibility is to make blocks and Fields more similar and interchangeable. If a block returns a value and a field needs a value, why not just stick it in? Why force a beginner to learn how to create a temporary variable just so they can juggle the return value? Or, if you provide an inline input (rectangular hole with a left socket) then you prevent the use of a variable without the (otherwise meaningless) getter block to adapt the two distinct shapes. 

Perhaps the imposed distinction between value expressions and side-effect-only statements can sometimes result in more complexity for beginners. 
Reply all
Reply to author
Forward
0 new messages