fullmoon wrote:
It's much cooler though. I've always wanted a sprite to be able to "say" another sprite! (And you can check collisions with a list of sprites)
It is very cool. Jens, could we add this, and a SELF block, and also add a NAME field to the [<var> OF <sprite>] block, and also add SPRITES that would report a list of all the sprites? I think that's really all we need for first-class sprites, isn't it?
Offline
nXIII wrote:
[perform [ ] with [ ] ]
Hmm, if we're going to do that, a more traditional form would be
[ASK <sprite> TO <script>]
But I didn't list that because I thought that
[LAUNCH [<script> OF <sprite>]]
covered it. Is the issue that you want to run scripts that aren't sprite-local?
Offline
bharvey wrote:
nXIII wrote:
[perform [ ] with [ ] ]
Hmm, if we're going to do that, a more traditional form would be
[ASK <sprite> TO <script>]
But I didn't list that because I thought that
[LAUNCH [<script> OF <sprite>]]
covered it. Is the issue that you want to run scripts that aren't sprite-local?
Yea, kind of...
PS: Squeak uses
<receiver> perform: something with: arg with: arg ...
Last edited by nXIII (2010-06-17 22:17:16)
Offline
bharvey wrote:
fullmoon wrote:
It's much cooler though. I've always wanted a sprite to be able to "say" another sprite! (And you can check collisions with a list of sprites)
It is very cool. Jens, could we add this, and a SELF block, and also add a NAME field to the [<var> OF <sprite>] block, and also add SPRITES that would report a list of all the sprites? I think that's really all we need for first-class sprites, isn't it?
Very nice, fullmoon!
Well, as fullmoon pointed out, everything we need for this is already in the code, i.e we can report sprites and use our customized speech/think/showValue bubbles to take care of the rest
Due to the Morphic tree structure we will, however, get in trouble once we try putting sprites into lists, because then the sprite will acutally move from the stage into the list (it can only have a single Morphic owner). So we'll have to come up with some special cases for displaying.
Last edited by Jens (2010-06-17 22:26:37)
Offline
nXIII wrote:
Squeak uses
<receiver> perform: something with: arg with: arg ...
But that doesn't execute a method in the calling sprite, not does it pass a method of the caller to the callee. It's just the same as calling another sprite's method by its name and passing some parameter.
What you want - I assume - is pass code from one sprite to another, right?
Offline
Jens wrote:
Due to the Morphic tree structure we will, however, get in trouble once we try putting sprites into lists, because then the sprite will acutally move from the stage into the list (it can only have a single Morphic owner). So we'll have to come up with some special cases for displaying.
Ah, yes, I see what you're saying It seems like it actually copies the SpriteMorph into the list, since I still have a copy in my sprites palette. They're no longer linked, though.
Last edited by fullmoon (2010-06-17 22:26:00)
Offline
fullmoon wrote:
Jens wrote:
Due to the Morphic tree structure we will, however, get in trouble once we try putting sprites into lists, because then the sprite will acutally move from the stage into the list (it can only have a single Morphic owner). So we'll have to come up with some special cases for displaying.
Ah, yes, I see what you're saying It seems like it actually copies the SpriteMorph into the list, since I still have a copy in my sprites palette. They're no longer linked, though.
Yeah, but we can change that. Actually, we don't have to put the Sprite into the list's morphic structure at all. I already made provisions in the code that a WatcherFrame will display any Morph that has been assigned to it's "complexObject" attribute. the only reason I'm putting sublists into their owner's morphic tree is to make them resizeable onstage. We wouldn't have to do this with sprites, so we could just special case the list setter method
Last edited by Jens (2010-06-17 22:31:51)
Offline
Jens wrote:
Yeah, but we can change that. Actually, we don't have to put the Sprite into the list's morphic structure at all. I already made provisions in the code that a WatcherFrame will display any Morph that has been assigned to it's "complexObject" attribute. the only reason I'm putting sublists into their owner's morphic tree is to make them resizeable onstage. We wouldn't have to do this with sprites, so we could just special case the list setter method
You lost me at "provisions"! Although I should point out that I've been enjoying your Elements browser; it lets me mess with Scratch without actually knowing any Smalltalk. Is there any way to copy a block in Elements?
Last edited by fullmoon (2010-06-17 22:35:26)
Offline
Jens wrote:
this release is a bit scary, because I've rewritten so much under the hood to make it faster, so let's thoroughly test it for newly introduced bugs!
Essentially this release brings BYOB 2.99 completely back to Scratch speed. You should now be able to run every and any native Scratch project in BYOB without noticing any difference in speed or behaviour, while still having all the power of "build your own blocks", else it's a bug. Also, while not quite as fast as in earlier, non lambda-versions of BYOB, projects made with those older versions should once again run at acceptable speeds in this release.
In order to accomplish this speedup I have identified and reworked numerous loopholes and bottlenecks in the code and disabled Scratch's "flashing blocks" (aka single stepping) feature, to gain timeshares for native BYOB features such as lambda, apply & eval.
"Turbo"
--------
In turn I made it easier to use Scratch's "turbo mode" setting in the EDIT menu. Using "Turbo" squeezes more computational steps into a display cycle (you could also say it just skips some display cycles :-) ) which greatly improves graphics-intensive projects, like drawing of fractals, and also musical projects relying on precise synchronization. The "turbo" setting is now a checkbox in the EDIT menu, but it's setting is non-persistent. Whenever you start BYOB it is "off" per default.
Speed-limit
------------
Note, however, that "turbo" will not speed up atomic procedures, as they are already running at full throttle. Speaking of "full throttle": There seems to be a hard minimum of 25 ms per computational step (non-atomic block) in Scratch by design, which can only be sped up so much with atomicity, because the underlying Scratch-interpreter is not really optimized. Therefore you will experience the biggest speed-up by far with regular Scratch projects (compare them to 018!) and not with already sped-up custom blocks as in recursive computational projects like Blackjack, Streams or Tic-Tac-Toe.
Debugger
----------
I've put some more effort into opening the Debugger window less often when debugging reporters.
Bugfixes
---------
There have been several bugfixes, among them:
- list blocks with special values ("last, any, all") now keep those and don't convert them to zero (as introduced in 019)
- empty COPY OF blocks now answer an empty list instead of a Squeak error message
- some more I've forgotten, because it's already morning again
Offline
Jens wrote:
the sprite will acutally move from the stage into the list
Wait I'm confused. I just made a variable FOO and a (named) list BAZ. I said
[SET <foo> TO [LIST <a> <b> <c>]]
[ADD <foo> TO <baz>]
[CHANGE ITEM <2> OF <foo> TO <thing>]
and both monitors saw the change. What am I not understanding?
Offline
PS: I made another named list GARPLY and then I did
[ADD <foo> TO <garply>]
[CHANGE ITEM <last> OF <foo> TO <bingo>]
The change happened in the monitors for FOO and GARPLY, but not BAZ. But if I shrink and then re-enlarge the BAZ watcher, I get the right answer.
Now if I resize the picture of FOO inside GARPLY, then FOO's own monitor resizes too, and vice versa. But I can't resize FOO inside BAZ at all.
What a kludge! (Morphic, I mean, not BYOB. ) I vote for copy-restore semantics for watched sublists (as least bad option without rewriting in Scheme).
Last edited by bharvey (2010-06-17 22:48:51)
Offline
Jens wrote:
But that doesn't execute a method in the calling sprite, not does it pass a method of the caller to the callee. It's just the same as calling another sprite's method by its name and passing some parameter.
Wait, Smalltalk has lambda... umm, "blocks."
<object> Perform: [ ... ]
Can you do that? Isn't that passing code from caller to callee? (But it doesn't directly transfer to BYOB because in Smalltalk you can just type a variable name whereas in BYOB you have to find an appropriate orange blob.
We should think about something like the Panther generic variable blob, with the name bound at the very last moment. Then cross-object code would work either way: the caller could include its own (specific) orange blob, which would give the callee access to the caller's variable, or the caller could use the generic blob, which would be resolved by the callee in its own environment.
Offline
bharvey wrote:
Jens wrote:
But that doesn't execute a method in the calling sprite, not does it pass a method of the caller to the callee. It's just the same as calling another sprite's method by its name and passing some parameter.
Wait, Smalltalk has lambda... umm, "blocks."
<object> Perform: [ ... ]
Can you do that? Isn't that passing code from caller to callee? (But it doesn't directly transfer to BYOB because in Smalltalk you can just type a variable name whereas in BYOB you have to find an appropriate orange blob.
Well, there are two answers to that:
1) No, you cannot say <object> perform: aBlock in Smalltalk
Smalltalk's #perform: message takes a selector of type Symbol as argument, not a Block. (In principle) you cannot make an object "perform" arbitrary code created outside of that object's context. Each BlockClosure (an evaluated Block) carries the context it has been created in. So if <object> sends you a BlockClosure you can call it by sending a message named #value to the BlockClosure:
<aBlockClosure> value
<aBlockClosure> value: arg1 value: arg2
But any code within the Closure referring to other attributes, messages, or to self will still point to the originating object's context.
2) Yeah, you can do pretty much anything in Smalltalk
Since Smalltalk is dynamically compiled at runtime, you can say something like:
<object> class compile: 'newMessage: arg
^ self doIllicitStuffWith: arg'
and then you can just call:
<object> perform: #newMessage with: arg
or directly:
<object> newMessage: arg
which, I take it, is exactly what nXIII wants :-)
Last edited by Jens (2010-06-18 07:44:19)
Offline
bharvey wrote:
What a kludge! (Morphic, I mean, not BYOB. ) I vote for copy-restore semantics for watched sublists (as least bad option without rewriting in Scheme).
Naw, the kludge is not Morphic. Morphic is just a hierarchical GUI, you can't blame a tree for having just one root.
The kludge is not separating the list data structure from its view(s). In Scratch it's a 1 to 1 relationship, which is very intuitive for beginners, but results in a ceiling so low you have to figuratively crawl underneath it.
Last edited by Jens (2010-06-18 08:03:47)
Offline
bharvey wrote:
We should think about something like the Panther generic variable blob, with the name bound at the very last moment. Then cross-object code would work either way: the caller could include its own (specific) orange blob, which would give the callee access to the caller's variable, or the caller could use the generic blob, which would be resolved by the callee in its own environment.
Good idea! Can't we do this already in BYOB with a custom reporter utilizing the OF block? (the OF block's left argument slot accepts certain reporters in BYOB, so we can also pass it a string - an identifier - for a variable).
Offline
Ideas for BYOB blocks:
Sprite groups, which are like lists that correspond to sprites.
Name script ( ), this would give the script a name.
Stop script ( ) of (sprite1) would stop that script.
Script ( ) of (sprite1) would report a certain script of a certain sprite.
Offline
Jens wrote:
In Scratch it's a 1 to 1 relationship, which is very intuitive for beginners, but results in a ceiling so low you have to figuratively crawl underneath it.
Hmpf. No matter how monitors were implemented, they'd still have to show the values correctly, and there's no reason they couldn't mutate the values. I don't think they can use intuitiveness as an excuse.
Offline
Jens wrote:
Can't we do this already in BYOB with a custom reporter utilizing the OF block? (the OF block's left argument slot accepts certain reporters in BYOB, so we can also pass it a string - an identifier - for a variable).
Wow! Yeah you can say
[[JOIN <> <foo>] OF <sprite2>]
but why only certain reporters? If you say
[[ID <foo>] OF <sprite2>]
(using ID from tools.ypr) it reports "foo" instead of the value of the variable.
And of course it doesn't work for global variables, which doesn't matter in a case like this where you want a specific variable, the same one every time, but it does matter if your program wants to compute a variable name.
PS A long time ago you talked about putting every method available to the sprite, including global ones, in the OF pulldown, and we rejected that because the list would be too long to be usable. But there's no UI reason we couldn't accept globals that are typed in.
Last edited by bharvey (2010-06-18 10:20:24)
Offline
Jens wrote:
Oh, the OF block doesn't accept custom reporters and string reporters? That's a bug I'll certainly fix!
So there are some bugs you won't fix?
Offline