I’m afraid I don’t see a sync mechanism in Document.
Nor do I see why the IDE would flicker between documents. Tracing through the code for Document.open:
- If the path was already open, simply
.front
it.
- Otherwise,
initFromPath
:
- Get an ID.
- Initialize the sclang text mirror.
- Tell the IDE to open the file.
- Set instance variables.
- Add the document to the collection.
None of the initFromPath
steps explicitly front
s any document – so I suppose it’s assumed that the IDE will bring any newly-opened document to the front.
Also missing from that execution flow is an instruction to bring any other document to the front.
It would have to be some kind of race condition, but I don’t see where it could happen.
You might have to run that in a routine and insert a short wait
before front
?
That’s an interesting question… it’s something I had wanted to bring up for a while, but I couldn’t find a way to do it that was not over-prescriptive.
For an analogy, let’s say that I Google “dogs working” instead of “working dogs.” I could call that a style choice. And the former query does return results about working dogs – so I could say that either wording communicates the intent of the query to the search engine, so both are legitimate.
But to a human reader, “dogs working” connotes activity that happens to be carried out by dogs, while “working dogs” connotes a category of animals. If the context is the category of animals, then the former wording communicates less accurately, or more awkwardly, to human beings.
SC accepts the code style in the initial post – but I think it might not communicate optimally with human beings. I think both are important in programming.
Concretely, for instance, front(Document open: x)
: the best that I could say about it is that it perhaps emphasizes the final result – “1. something should be brought to the front; 2. that ‘something’ is…” – while the more typical formulation Document.open(x).front
emphasizes first who should perform the action – “Hey you! Document!” – and then a sequence of operations in the order of evaluation (“first open, then take that thing and ‘front’ it”).
I’m trying hard here not to argue simply what I’m accustomed to – but, I think there are concrete benefits to putting the receiver first, and to writing operations in evaluation order as much as possible. If there is a benefit to inverting the order, I’ll be honest that I don’t see it.
A possible drawback is, if you have a question about an especially complex block of code and the style is harder to understand, this might deter people from helping you. I don’t know about others, but I’m often quite busy. If it’s a difference between 5 or 15 minutes to understand a block of code, because of style choices, I might simply skip that question even if it’s interesting.
I know of one non-equivalence, because of a compiler optimization:
(
r = Routine {
(1 .. ).do { |i|
i.yield;
}
};
)
r.next; // 1, 2, 3, 4
(
r = Routine {
(1 .. ) do: { |i|
i.yield;
}
};
)
r.next;
ERROR: Primitive '_SimpleNumberSeries' failed.
Wrong type.
… because the first (1..).do
compiles to forSeries
, while the second compiles such that it would first try to construct an infinite series as an array – of course an infinite-size array can’t exist, so SC sensibly fails the attempt. (do((1 .. )) { |i| i.yield }
is also OK.) Apparently a keyword:
binary op must always operate on an object, and can’t fold series expressions into other methods.
One could say that’s a compiler bug (it surprised me when I found it mentioned in SC help), but it at least suggests that you can’t always assume the three method call syntaxes are equivalent.
hjh