Re: Aliasing an array slice
David Storrs wrote: > > Thinking about it, I'd rather see lvalue slices become a nicer version > of C. > > my @start = (0..5); > my @a = @start; > > @a[1..3] = qw/ a b c d e /; > print @a; # 0 a b c d e 4 5 What would happen if I used 1,2,3 instead of 1..3? Would it do the same thing? I wanna know what happens if I do: @a[0,2,4] = qw/ a b c d e /; -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: Aliasing an array slice
Luke Palmer wrote: > > > David Storrs wrote: > > > > > > Thinking about it, I'd rather see lvalue slices become a nicer version > > > of C. > > > > > > my @start = (0..5); > > > my @a = @start; > > > > > > @a[1..3] = qw/ a b c d e /; > > > print @a; # 0 a b c d e 4 5 > > > > What would happen if I used 1,2,3 instead of 1..3? Would it do the > > same thing? > > Of course. > > > I wanna know what happens if I do: > > > >@a[0,2,4] = qw/ a b c d e /; > > It would probably do the same as in Perl 5; the same thing as: > > @a[0,2,4] = << a b c >>; > > (those << >> brackets are new shorthand for qw, not that qw is going > anywhere) Hmm... so, if I were to do: @x = map int(rand(6)), 1..3; @[EMAIL PROTECTED] = "a" .. "e"; print @a.length; Then, if the three integers in @x are consecutive, @a grows, but otherwise it doesn't? -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: Aliasing an array slice
Dave Whipp wrote: > "Luke Palmer" wrote: > > Benjamin Goldberg wrote: > > > David Storrs wrote: > > > > @a[1..3] = qw/ a b c d e /; > > > > print @a; # 0 a b c d e 4 5 > > > > > > What would happen if I used 1,2,3 instead of 1..3? > > > Would it do the same thing? > > > > Of course. > > I tend to agree, I think. But see below > > > > I wanna know what happens if I do: > > > > > >@a[0,2,4] = qw/ a b c d e /; > > > > It would probably do the same as in Perl 5; the same thing as: > > > > @a[0,2,4] = << a b c >>; > > But that would be awful: > >@a[$x,$y] = <> > > would insert all 5 elements if ($y == $x+1); but only the first two > otherwise. Belch. > > If we wanted the array-splice thing to resize arrays for us, then either > we trigger the behavior only when rx/ \[ \.\. \]/, or AFAIK, in perl6, $a..$b doesn't create an expanded list... it creates a lazy list, which gets expanded as-needed. Most likely, this list object, and the list object representing the values being stored there, would be handed directly to the @a array object, just as if we'd done code like: @a[ new LazyIntRange(1,3) ] = new LazyStrRange("a","e"); So, @a can say, "hey, this is a Range, not merely a list of 1,2,3... I should instead splice() the values in" > we need to define the spilling algorithm in a way that makes sense (e.g. > all remaining items go into the element of the righmost index). > > But perhaps there's a better way to beet the desire. Perhaps ellipses > could be emplyed to indicate that the splice is allowed to resize the > array: > > @a[1...3] = qw(a b c d e); That might work, too. My way is more invisible, but then again, if someone *wants* to have @a[1,2,3,4,5,6,7,8,9] = @x, and writes it as @a[1..9] = @x, and is surprised by perl doing a splice, it would be bad; with "..." it would only splice when the user asks for a splice. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: The Perl 6 Summary -- preprocessors
Luke Palmer wrote: > > > grammar Grammars::Languages::C::Preprocessor { > > rule CompilationUnit { > > ( | )* > > } > > > > rule Directive { > > ( Include > >| Line > >| Conditional > >| Define > > ) * > > } > > > > rule Hash { /^\s*#\s*/ } > > rule Include {...} > > rule Line {...} > > rule Conditional {...} > > rule Define {...} > > rule Continuation {...} > > rule UnprocessedStuff {...} > > } > > We're not quite in the world of ACME::DWIM, so you can't just replace > the important stuff with ... . :-) > > You're not outputting a parse tree, you're just outputting more text > to be parsed with another, text-based, grammar. It seems to me like > it's a big s//ubstitution, of sorts. Hmm... well, think about yacc for a moment. You could either have the handlers for rules assign to $$, based on $1, etc., and thus build a huge structure, OR, you could have the handlers for rules print stuff to stdout (which might possibly be a pipe to another process). ISTM that we also want our grammers to be able to do things like that... We want to be able to produce a tree, *and*, we want to be able to act as a filter. And probably also some combination thereof -- some rules produce trees, and other rules within the same grammer (which contain the tree-producing ones) somehow process and output those trees. > Or maybe not, maybe we make an output stream which will be fed to > Grammars::Languages::C. Here's an implementation a #include > processor, using as little made-up syntax as possible. > > use Pattern::Common; > > grammar Preprocessor { > rule include { > :w(/\h*/) > \# include "" $$ > { $0 := (<<< open "< $filename") ~~ // } > } > > rule main { > $0 := ( [ | .]* ) > } > } Alas, this doesn't work right with a fairly common idiom: #ifdef HAVE_FOO_H #include #endif Nor the even more common: #ifndef SYS_SOMEFILE_H #define SYS_SOMEFILE_H lots of stuff, possibly including some #includes, and some typedefs. #endif /* SYS_SOMEFILE_H */ -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: Protocols
Chromatic wrote: [snip] > > I think you want to declare "I comply with ruleset X" at the callee > > object level. That enables the compiler to (1) check that you're not > > lying; and (2) optimize based on (1). > > At least one of us is using "caller/callee" in the X11 sense. What I > mean and what I think you mean is: > > method foo ( Thingie $t ) { ... } > > $object->foo( $behaves_like_thingie ); > > foo() says, "Give me something that I can treat like a Thingie. I > don't care HOW it does it, I just want it to do something sane." > > $behaves_like_thingie is an instance of a class that somehow says, > "Hey, I act like Thingie. I'm substitutable for Thingie if you don't > break my encapsulation." If this were Java, the way to do this would be to define a Thingie interface, and then an (archetypical) ThingieObject class... any time that we want to actually *create* Thingies, we would use "new ThingieObject", but everywhere else, we would use the typename "Thingie". This way, when we want a class which "acts like" a Thingie, but without inheriting any of it's innards, simply implement the Thingie interface, instead of inheriting the ThingyObject class. Here's a possible idea -- have a method of the Class class, which returns (creates) an anonymous Interface object, which provides all of the public methods of that class, and which is magically one of the parents of that class. This way, when one wants to define a new class X which "acts like" some other class Y, but which doesn't *really* inherit from Y (none of the internal data, etc.), we can define X as implementing the Y.interface() Interface. For our "isa" operator, and (perhaps more importantly) for multimethod dispatch and/or sub prototype checking, we only check if an object inherits from a class's magic parent interface, and *don't* check if it *really* inherits from that class itself. Of course, this by itself wouldn't let us delegate to the ThingyObject's versions of the methods... that would require another extra layer of nonsense^Windirection. > If we're just confused over a bit of terminology, we're in violent > agreement on the idea, which is much more important. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: Macro arguments themselves
Larry Wall wrote: [snip] > Nope. $x and $p are syntax trees. Macros are passed syntax trees as arguments, but return coderefs? That's... odd. I would expect that a macro would be expected to *return* a syntax tree... which could then undergo (more) macro-expansion. Sortof like how in lisp, a macro recieves lists as arguments (those lists being un-evaluated code) and then returns a list, which then has more macro expansion done on it, and then gets parsed and evaluated. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: "As soon as she walked through my door..."
Miko O Sullivan wrote: > > Congratulations to Damian on a great opening in Ex 6. Anybody can spoof > the classic detective novel setup, but it takes real talent to have it > actually make sense in the context of a technical document. How long till Ex 6 is online, for those of us who weren't there? :) -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: Perl 6's for() signature
Jonadab The Unsightly One wrote: > > John Siracusa <[EMAIL PROTECTED]> writes: > > > Did this ever get resolved to anyone's satisfaction? While reading > > EX6, I found myself wonder exactly what for() would look like in > > Perl 6 code... > > A for loop[1] is basically syntax sugar for a while loop. In general, > where foo, bar, baz, and quux are expressions, the following are equivalent: > > for (foo; bar; baz) { quux } > foo; while (bar) { quux; baz } Well, except that in the second, any variables declared in foo will leak into the scope after the end of the for loop. Also, in the second, "baz" is inside the same scope as quux, whereas in the normal C-style for loop, it's not. Thus, "for (foo; bar; baz) { quux }" is really more like: { foo; start_for_loop: if( !bar ) { goto end_for_loop } { quux } baz; goto start_for_loop; end_for_loop: }; > If Perl6 has enough syntax-sugar ability to let you turn the former > into the latter, then you don't need to worry about for's signature. Well, yes. But the point of this discussion is, precisely what *kind* of syntactic sugar will be used. > [1] Of course I mean a C-style for loop. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: PerlHash.get_pmc_keyed of non existing key
Gordon Henriksen wrote: > > Taking a thread from Perl 6 Internals. Will Perl 6 support this behavior? > > $ perl <<'EOT' > my @ary; > my $ref = \$ary[0]; > $$ref = "value"; > print '$ary[0] : ', $ary[0], "\n"; > EOT > $ary[0] : value > > Presumably the Perl 6 would be: > > my @ary; > my $ref = [EMAIL PROTECTED]; > $$ref = "value"; > print '@ary[0] : ', @ary[0], "\n"; # -> @ary[0] : value > > If that's supported, then how will this behave? > > my @cows of Cow; > my $slot = [EMAIL PROTECTED]; > $$slot = new Dog; Well, Perl6 can infer (at compile time) that $slot is a reference to a Cow, and from that, it can infer that $$slot may only contain a Cow. Thus, it should be catchable at compile time. OTOH, the following is not catchable at compile time: my @cows of Cow; my @dogs of Dog; my $ref = int(rand(2)) ? [EMAIL PROTECTED] : [EMAIL PROTECTED]; $$ref = new Dog; All that Perl6 can infer at compile time about $ref is that it is a reference to any(Cow, Dog). So, the assignment is legal at compile time. Thus, *some* sort of runtime check needs to be made. I suppose that instead of $ref being a PerlRef (or however we manage references), it would be a PerlTypeConstrainedRef, which throws an exception if you try to store a value the wrong type into it. > Do we wind up with Clarus or an exception? (Never mind whether you take > exception with Clarus.) Clarus would be if we had an object whose type was all(Cow, Dog), eh?:) > Hopefully an exception, from a user's POV. An exception at compile time the code you presented, an exception at run time for the code I presented. > And this? > > my @cows of Cow: > my @cats of Cat; > my $ref = [EMAIL PROTECTED]; Ok. > @cats[0] := $$ref; Ok, although this is mostly a no-op. > @cats[1] := @cows[0]; # Just to hammer the point home A compile time error. > $$ref = new Dog; A compile time error due to type inferencing. (If type inferencing were insufficient, it would be a run-time error). > But then there's a question for p6i as to how all the above happens. I suppose that a PerlRef would be a PMC which has another PMC stored in it's ->cache.struct_value component; storing and fetching it's contents would be done via VTABLE_set_pmc and VTABLE_get_pmc. I suppose that a PerlTypeConstrainedRef would, in addition, have a PerlClass PMC in it's PMC_data, and check for the appropriate isa relationship before allowing new data to be stored into it. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: Junctions & Set Theory
Luke Palmer wrote: > > Wow, what an old thread... > > Jonadab the Unsightly One writes: > > "Abhijit A. Mahabal" <[EMAIL PROTECTED]> writes: > > > > > On the other hand, if you wanted to say "true for all except exactly > > > one value, I can't think of a way. > > > > Easy. The following two statements are equivalent: > > > > F(x) is true for all but exactly one x > > (not F(x)) is true for exactly one x > > > > The only additional possibility that can't be phrased in terms of the > > four given is the complex generalised case: > > > > F(x) is true for at least n but not more than m values of x > > Oh, I wouldn't say that > > use HypotheticalModules::List::Combinations 'combinations'; > > sub between($low, $high, [EMAIL PROTECTED]) { > any( > $low..$high ==> map -> $num { > any( map { all(@$_) } combinations($num, @values) ) > } > ) > } > > Efficient? No. Blows out memory for (20, 30, 1..50)? Yes. > Works? Yes. > > We also have: > > class Betwunction is Junction { > submethod BUILD($.low, $.high, @.values) { } > > method evaluate() { > my Int $n = grep { ? $_ } @.values; > $.low <= $n <= $.high; > } > } > sub between($low, $high, @values) { > new Betwunction: $low, $high, @values; > } > > Or something. But I guess this one breaks the constraint of "in terms > of the four given". Also, it tests more values for truth than it has to. If there are fewer elements in the array than $.low, then obviously, we should fail immediately. Actually I should say, "elements remaining", instead of just "elements", and should say "$.low - the number of true elements so far" instead of "$.low". In otherwords, this bit of short- circuiting could be done on every iteration, so as to test fewer elements of the array for truth, if we can. If there are fewer elements in the array than $.high, then (assuming we already know that there are at least $.low elements) we can succeed immediately. Likewise, this short-circuiting can be done on every iteration. method evaluate() { my Iterator $i = Iterator.new($.values); my Int $need = $.low; while( $need > 0 ) { return false if $i < $need; --$need if ? $i.shift; } my Int $limit = $.high - $.low; while( $limit >= 0 ) { return true if $i < $limit; --$limit if ? $i.shift; } return false; } This *should* do no more boolean tests on the elements of $.values than absolutely necessary. > > So for example you could have a list of fifty values for x and test > > whether the condition is true for at least ten but not more than > > fourty of them. (Or, x could be the condition; you could have a list > > of fifty conditions and test whether between twenty and thirty of them > > were true.) My guess is, however, that the frequency with which > > anyone would use such a capability would not be overwhelming. > > > > It would be great for obfuscation, though, particularly if some of the > > conditions had side effects with an impact on the value of the other > > conditions to be tested... That would be sufficiently interesting > > that it's almost a shame I can't think of a real reason to request > > such a feature, since I rather doubt anyone's going to much fancy > > implementing it just for obfuscatory value ;-) > > Who needs reasons? It's at least as useful as the proposed "fortytwo" op for parrot. :) -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Timely object destruction
Piers Cawley wrote: > > The Perl 6 Summary for the week ending 20030601 > Another Monday, another Perl 6 Summary. Does this man never take a > holiday? (Yes, but only to go to Perl conferences this year, how did > that happen?) > > We start with the internals list as usual. > > More on timely destruction > The discussion of how to get timely destruction with Parrot's Garbage > Collection system continued. Last week Dan announced that, for languages > that make commitments to call destructors as soon as a thing goes out of > scope, there would be a set of helpful ops to allow languages to trigger > conditional DOD (Dead Object Detection) runs at appropriate times. > People weren't desperately keen on the performance hit that this entails > (though the performance hit involved with reference counting is pretty > substantial...) but we didn't manage to come up with a better solution > to the issue. > > http://xrl.us/iu5 I'd like to reiterate (and clarify) my idea, of a hybrid scheme combining refcounting and DoD. All values needing timely destruction would inherit from a class RefCounted. They should (in the normal scheme of things) be stored in variables with an "is refcounted" trait (or a trait which inherits or includes that trait, if that's possible). Hopefully, only a *small* number of objects in a system need timely destruction, and (for best performance) all variables which will hold those objects will have the "is refcounted" trait set on them. (If most or all objects needed timely destruction, then we wouldn't be moving away from perl5's pure-refcount GC, would we?) All operations on a variable or variables having the "is refcounted" trait result in opcodes to call the refcount(inc|dec) method(s) of the values in those variables. Under normal circumstances, when a refcounted value's refcount goes to zero, it self destructs^W^W cleans itself up. This is quite perl5-esque, and of course slower than simply letting the DoD-GC handle everything, BUT, in the absence of circular reference loops, it does produce timely cleanup of those objects which need it, which pure-DoD wouldn't, and DOESN'T result in numerous, and thus expensive, requests for full DoD runs. For all of the other schemes, full DoD runs would be run on every scope exit, even if there's only one single variable in scope which needs timely destruction. Here's where the non-normal circumstances are described, and how they're handled: It's legal for a refcounted value to end up referenced by a non- refcounted variable. This has to be so, since adding the "is refcounted" trait everywhere would get cumbersome; also we may sometimes *need*, for one reason or another, to store refcounted values in the same containers which also hold non-refcounted values. Thus, if a refcounted value gets stored in a non-refcounted variable, then that value could quite easily still be reachable when it's refcount goes to zero. Obviously, when this is the case, we need to avoid a premature cleanup. To avoid premature cleanup, any time that the contents of a refcounted variable is assigned to a non-refcounted variable, an opcode to set a "reachable by non-refcounted variable" flag on the value precedes the assignment. If a refcounted values's refcount goes to zero, and it has this flag set, it does NOT self-destruct[*]. A global counter keeps track of how many values have a refcount of zero and have this flag set. >From here, we are in a similar situation as other proposals -- for the timeliest possible destruction, then on every single scope exit, we check if this global counter is nonzero, and if so, do a DoD run. For potentially less timely destruction, we do this check whenever we leave a scope where a refcounted variable was declared, but not when we leave other scopes. Which of these two is done is a choice of the language designer, but might possibly be controlled by a pragma. Note that in the absence of marking any variables with the "is refcounted" trait, and with the use of the first option here (at every scope exit, check the counter and maybe do DoD), this scheme behaves *identically* with one of the other schemes proposed. It would be *no* slower at run time, since the refcount(inc|dec) methods are only called when doing operations dealing with variables with the "is refcounted" trait, and if noone uses that trait, there's no extra work. DoD would be a tiny bit slower with my scheme than the other, due to the extra flag checking, but (assuming that *most* code with objects needing timely destruction properly marks it's variables with the necessary "is refcounted" trait) that's a small price to pay for doing fewer DoD runs. [*] How does this flag get cleared, you might ask? Simplest would be to not clear it at all. This would be mostly harmless in terms of when objects get destructed, but would probably result in more DoD runs than we really need -- blech. [**] A mor
Re: Timely object destruction
Miko O'Sullivan wrote: > > On Mon, 2 Jun 2003, Benjamin Goldberg wrote: > > > All values needing timely destruction would inherit from a class > > RefCounted. > > I like this concept a lot, but maybe we can take it a little further > and make it transparent to the programmer. Suppose that the internals > only tracked objects that have a DESTROY method (or whatever it will > be called in Perl6)? You get the same benefit without the additional > brain-overhead of manually indicating that the class needs to be > tracked. That's a good idea, one which I left out because I was trying to simplyfy/clarify my description. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
Re: Timely object destruction
After reading Leopold Toetsch's post, I'm going to simplify part of my proposal slightly. Benjamin Goldberg wrote: [snip] > To avoid premature cleanup, any time that the contents of a > refcounted variable is assigned to a non-refcounted variable, an > opcode to set a "reachable by non-refcounted variable" flag on the > value precedes the assignment. Actually, as Leopold suggested, we could merely set a global interpreter->needs_lazy_dod flag to true. [snip] > [*] How does this flag get cleared, you might ask? > > Simplest would be to not clear it at all. This would be mostly > harmless in terms of when objects get destructed, but would probably > result in more DoD runs than we really need -- blech. [**] > > A more "proper" solution would be to clear it during/after each DoD > run. > > During the course of a DoD run, when we look for what PMCs are > reachable, we keep track of what each thing was reachable *from*. This needs a bit of clarification, I think. IIRC, DoD normally happens something vaguely like this: for my $p (@all_pmcs) { clear_is_live_flag($p); } our $traverse; sub set_is_live_flag($p) { if( !test_is_live_flag($p) and test_is_agregate($p) ) { $traverse = [$p, $traverse]; } really_set_is_live_flag($p); } set_is_live_flag($_) for @rootset; while( $traverse ) { ((my $p), $traverse) = splice @$traverse; $p->set_live_flag_on_contained_objects(); } for my $p (@all_pmcs) { next if test_is_live_flag($p); free_pmc($p); } My proposal would change the set_is_live_flag to something like: sub set_is_live_flag($p, $contained_in) { if( test_uses_refcounting($p) and not test_has_refcount_trait($contained_in) ) { $needs_lazy_dod = 1; } if( !test_is_live_flag($p) and test_is_agregate($p) ) { $traverse = [$p, $traverse]; } really_set_is_live_flag($p); } Where $contained_in would be the variable (or agregate object) which the object $p is contained in. -- $a=24;split//,240513;s/\B/ => /for@@=qw(ac ab bc ba cb ca );{push(@b,$a),($a-=6)^=1 for 2..$a/6x--$|;print "[EMAIL PROTECTED] ]\n";((6<=($a-=6))?$a+=$_[$a%6]-$a%6:($a=pop @b))&&redo;}
RE: Lessons to learn from ithreads (was: threads?)
> Date: Tue, 12 Oct 2010 23:46:48 +0100 > From: tim.bu...@pobox.com > To: faw...@gmail.com > CC: ben-goldb...@hotmail.com; perl6-language@perl.org > Subject: Lessons to learn from ithreads (was: threads?) > > On Tue, Oct 12, 2010 at 03:42:00PM +0200, Leon Timmermans wrote: > > On Mon, Oct 11, 2010 at 12:32 AM, Ben Goldberg > > wrote: > > > If thread-unsafe subroutines are called, then something like ithreads > > > might be used. > > > > For the love of $DEITY, let's please not repeat ithreads! > > It's worth remembering that ithreads are far superior to the older > 5005threads model, where multiple threads ran with an interpreter. > [Shudder] > > It's also worth remembering that real O/S level threads are needed to > work asynchronously with third-party libraries that would block. > Database client libraries that don't offer async support are an > obvious example. > > I definitely agree that threads should not be the dominant form of > concurrency, and I'm certainly no fan of working with O/S threads. > They do, however, have an important role and can't be ignored. > > So I'd like to use this sub-thread to try to identify when lessons we > can learn from ithreads. My initial thoughts are: > > - Don't clone a live interpreter. > Start a new thread with a fresh interpreter. > > - Don't try to share mutable data or data structures. > Use message passing and serialization. > > Tim. If the starting subroutine for a thread is reentrant, then no message passing is needed,and the only serialization that might be needed is for the initial arguments and for thereturn values (which will be gotten by the main thread via join). As for starting a new thread in a fresh interpreter, I think that it might be necessary topopulate that fresh interpreter with (copies of) data which is reachable from thesubroutine that the thread calls... reachability can probably be identified by usingthe same technique the garbage collector uses. This would provide an effect similar toithreads, but only copying what's really needed. To minimize copying, we would only treat things as reachable when we have to -- forexample, if there's no eval-string used a given sub, then the sub only "reaches" thosescopes (lexical and global) which it actually uses, not every scope that it could use.