Re: Multi-d array transforms (was Re: Array rotate)
On Sat, Jun 13, 2009 at 1:08 AM, Larry Wallla...@wall.org wrote: Nevertheless, for any major methods borrowed from Perl 6, I'm not inclined to change them that drastically. Much more likely to define them as sugar for the more general list operators: .push means .=append .unshift means .=prepend .splice means .=impend :-) or some such. That makes sense to me. I'd very much like it if the fundamental methods on most data types were non-mutating - string manipulation, list munging etc. Along with having lazy lists, that gives us a good dose of tricks from the functional world we can do, and with .= and (hopefully) some clever bits in the compiler which can handle it effectively (as in performance-wise), it's no hassle to convert any non-mutator to a mutator. Syntactic sugar for really common mutating cases, as in other methods which do 'the same thing but mutated' is of course fine (particularly when they have sensible/familiar names, which implies to my mind that the operation makes sense). Although some things may be able to be implemented far more efficiently if they know that they're being called with infix:.= and not with infix:.. method munge($self is ro:) { } # infix:. case method mung($self is rw:) { } # infix:.= case ? Marginally inspired by C++ const methods. Of course, a potential problem here is that they might want different return types as well - but maybe our multis are fine with that, and maybe this is just some crazy dream caused by waking up too early on a Saturday morning and thinking about Perl before breakfast. Matthew
Re: Multi-d array transforms (was Re: Array rotate)
Larry Wall wrote: Nevertheless, for any major methods borrowed from Perl 6, I'm not inclined to change them that drastically. Much more likely to define them as sugar for the more general list operators: .push means .=append .unshiftmeans .=prepend .splice means .=impend:-) or some such. I like those. I feel similar to Matt W. I kind of like .push and .unshift the way they are (probably just habit) But I can appreciate that non-mutating alternatives might open a new class of algorithms from the functional world. Daniel.
Re: Multi-d array transforms (was Re: Array rotate)
On Fri, Jun 12, 2009 at 11:23 PM, Matthew Waltonmatt...@matthew-walton.co.uk wrote: Although some things may be able to be implemented far more efficiently if they know that they're being called with infix:.= and not with infix:.. Last I checked, Perl 6 had some types that are mutating and others that aren't (e.g., List and Array, I think). An additional benefit of setting up the primitive methods as non-mutating is that you increase the amount of functionality shared by the two: if all mutating methods are syntactic sugar for non-mutating counterparts, then non-mutating types will be able to do everything that their mutating brethren can do (except mutate, of course). E.g., a List can push, unshift, splice, etc; an Array can append, perpend, impend, etc. And if you want to do purely functional programming, you can do so by restricting yourself to the use of non-mutating types and staying away from those methods that have side effects (which should [i]also[/i] be easily identifiable). Indeed, this same notion of ensuring that pure functional versions of mutating methods exist should also apply to methods with side effects: as much as possible, if a method is designed to perform a calculation and to produce a side effect, there should also be an equivalent method that merely performs the calculation. Even better would be to segregate the methods that produce side effects from the methods that perform calculations. Am I making sense? -- Jonathan Dataweaver Lang
Re: Array rotate
Jon Lang dataweaver-at-gmail.com |Perl 6| wrote: On Fri, Jun 12, 2009 at 10:02 AM, yarynot@gmail.com wrote: I am tickled pink to see an Array rotate method in the settings spec S032, as I was thinking of writing up a little discussion on the very topic. Has there been discussion on using array rotate on multi-dimensional arrays? Being able to pass in a vector as the amount to rotate would be useful. With a multi-dimensional array, a number of transforms can be considered: * you can rearrange the elements along a given dimension (e.g., rotate and reverse). * you can rearrange the dimensions themselves (e.g., transpose). A short time ago, something similar came up. I think the built-in's should stay simple, and a module (or several different ones) can exist to do comprehensive features for multi-dimensional arrays. Designing that is really a separate project in itself, and it may shake out with use. So keep it out of the core spec. --John
Re: Multi-d array transforms (was Re: Array rotate)
Larry Wall larry-at-wall.org |Perl 6| wrote: We also need to consider the dimension of referentiality. I can see three levels here. Given @a.mung the .mung could return A) a modified @a (treat @a as mutable) B) a new array (treat @a as immutable) C) a remapped array whose elements refer back to @a's elements Currently .rotate is defined as A, but I could easily switch it to B, so you'd have to write @a.=rotate; Having some operation XX return a new object and using =.XX do it in place would be consistent with the way other things are shaping up. But people expect push to work like they are used to, and the exported push, called as a sub not as a method, would be copying. In void context it could give an error. push @a, $x;# what's the point? if we had a general way to decorate the sub definition to day must not use in void context. As expressed already in the synopses, the function called for @a.=push($x); can be written specially to handle the in-place case, rather than have to assign back after copying like the auto-generated case would. (What exactly define a self.push operator means needs to be clarified in S12. Is that not the normal sub syntax?) In other words, defining self.push would be the implementation that Perl 5 push is now. to rotate in place. If we did that, then we could conceivably set things up with more PDLish C semantics so that @a .= mung # A semantics @b = @a.mung # B semantics @b := @a.mung # C semantics That third one would be rather inefficient. The returned array would need to be set up as an array of binding proxies, if the original wasn't set up as an array of item containers, just in case it gets bound to something (or used as part of a larger expression) rather than assigned. I'm looking at this general issue right now (musing over it the last week actually) and although it's nowhere near done yet, you can see Figure 1 at http://www.dlugosz.com/Perl6/web/container-lvalues.html and the text that is taking shape around it. This implies, however, that the copy semantics of = are sufficiently clever to snapshot all the referenced values of @a before clobbering @a in the case of either: @a .= mung @a = @a.mung But list assignment really ought to be doing that in any case. Wow. The overarching logic for list assignment would have to compare the containers and the arguments in the capture before doing the list assignment to each container, in order to avoid cloning all the containers on the right first in the general case. It can't just copy values out because they may contain iterators or be lazy or be infinite. --John
Re: Array Dimensionality (Was: Re: Multi-d array transforms (was Re: Array rotate))
Larry Wall larry-at-wall.org |Perl 6| wrote: Alternately, we leave @@ (or @%) meaning ¢ and instead let some other syntax take over the pay attention to the capture's structure semantics from @@. Maybe it's another use for the zen slice: pay attention to the capture's structure is a can of worms. As things stand now in the Synopses, you get a lot of empty extra wrappers around things. You don't want to keep that exact! When you are not doing full-blown flattening, which levels in the morphology are extra due to passing though functions or grouping parens, and which are intended to be part of the final structure? Since the crazy stuff inside the capture is usually invisible, people will have a hard time using that correctly. (A literal reading of the synopses now gives us the morphology illustrated at http://www.dlugosz.com/Perl6/web/med-loop.html, and I hope to remove _some_ of those extra wrappings through refinement of the rules when I get around to studying that in detail.) My thoughts at this point is that slice context needs to *know* it is being rolled up into a final result that is a 2-dim array. The rules for that will strip out extra wrappers except where it really is significant, designed through use cases of seeing what common constructs actually produce. A shaped array knows what needs to be poured into it, so the RHS can be flattened. The single-dim array is just a special case of that; it generalizes to higher dimensions just fine, as seen in languages like APL. A smart shaped assignment, to handle containers with * in other than the highest position, can be supplied as part of a multi-dim array Module, designed separately along with a coherent set of features such as general vector-driven transposes etc. --John
Re: Array Dimensionality (Was: Re: Multi-d array transforms (was Re: Array rotate))
Daniel Ruoso daniel-at-ruoso.com |Perl 6| wrote: So, how do I deal with a multidim array? Well, TIMTOWTDI... my @a = 1,[2,[3,4]]; say @a[1][1][1]; say @a[1;1;1]; # I'm not sure this is correct I think that it should be. That is, multi-dim subscript is always the same as chained subscripts, regardless of whether the morphology is an array stored as an element, or a multi-dim container, or any mixture of that as you drill through them. I've not written out a full formalism yet, but I've thought about it. The multi-dim subscript would return a sub-array if there were fewer parameters than dimensions, an element if exact match, and recursively apply the remaining subscripts to the element if too many. Or.. (I'm using the proposed capture sigil here, which has '@%a' as its expanded form) my ¢a = 1,(2,(3,4); say ¢a[1][1][1]; say ¢a[1;1;1]; I think that makes the semantics of the API more clear... daniel The plain Array would work too, in the nested morphology: my @a = 1,[2,[3,4]]; @a has 2 elements, the second of which is type Array. say @a[1][1][1]; naturally. say @a[1;1;1]; means the same thing, intentionally. say @a[1][1;1]; say @a[1;1][1]; ditto. --John
Re: Multi-d array transforms (was Re: Array rotate)
Daniel Carrera daniel.carrera-at-theingots.org |Perl 6| wrote: In addition, the current @a.shift is useful because it returns the element that was removed from the array, so you can do something with it: The change to the library synopses was checked in before you posted that, if I recall the delta correctly. But you bring up a point: that is indeed the common idiom from Perl 5. That brings up the following radical idea: Have no method named shift at all. Shift etc. will be a non-member sub brought in through use legacy; and designed to work just like Perl 5, for that express purpose. The P6 way of doing it would be to not do that: use iterators rather than destructivly going through the array, or use decomposition to do things in a more functional way, or use the more general syntax to delete one element from the beginning, in-place or copy as indicated. --John
Re: Multi-d array transforms (was Re: Array rotate)
On Sat, Jun 13, 2009 at 02:49:10PM -0500, John M. Dlugosz wrote: Wow. The overarching logic for list assignment would have to compare the containers and the arguments in the capture before doing the list assignment to each container, in order to avoid cloning all the containers on the right first in the general case. It can't just copy values out because they may contain iterators or be lazy or be infinite. Well, that's not really a problem, as long as the same semantics are preserved. All you need to do is cut loose the contents of the container completely to the mercy of GC, build a new one with the appropriate structure, then copy values in from the assignment's RHS. The only reason Perl 5 couldn't do it this way is that the idiot who wrote it prematurely optimized values on the stack so that they didn't need to be reference counted. :) Larry
Re: Multi-d array transforms (was Re: Array rotate)
Larry Wall larry-at-wall.org |Perl 6| wrote: On Sat, Jun 13, 2009 at 02:49:10PM -0500, John M. Dlugosz wrote: Wow. The overarching logic for list assignment would have to compare the containers and the arguments in the capture before doing the list assignment to each container, in order to avoid cloning all the containers on the right first in the general case. It can't just copy values out because they may contain iterators or be lazy or be infinite. Well, that's not really a problem, as long as the same semantics are preserved. All you need to do is cut loose the contents of the container completely to the mercy of GC, build a new one with the appropriate structure, then copy values in from the assignment's RHS. The only reason Perl 5 couldn't do it this way is that the idiot who wrote it prematurely optimized values on the stack so that they didn't need to be reference counted. :) Larry I agree, if the contents include the iterators and code blocks and whatnot that make up the concrete types of the things on the right. But if it's not a built-in standard type, it might require a call to the general shallow-copy clone of the object. my @A is CustomContainer; my @B[7]; # fixed size ... @B,@A,@C = @A,@B; The compiler doesn't know how to juggle the internals of @A because it is not a standard type. This needs to become: my @temp1 = @A.clone; my @temp2 = @B.clone; @B,@A,@C = @temp1,@temp2; and assume that the compiler might optimize the case with @B through innate knowledge, and possibly inline and optimize over the calls for @A. Premature optimization is the root of all evil. But... design the semantics so there is some hope of optimization. That might entail designing in some features of Positional that will be used by this construct, as more efficient than just calling .clone(). OTOH, machines are a million times faster than what Perl 4 originally ran on.