William Michels wrote: >I actually wondered where the different programming paradigms >would be delineated
I think were the present topic has to do more with the strong/weak/gradual typing debates-- here Raku is doing an automatic type conversion that a "strong-typing" fanatic would sneer at. Though, the way this behavior is implemented is via the "(almost) everything is an object" philosophy that Tobias was describing. Willima Michels wrote: > split() performs an implied join of Array elements Yes, that's right, because split is a *string* method, it's as though you called .Str on the array first. What would you *want* to happen when someone treats an array as a string? my @monsters = < blob kong mothera fingfangfoom >; put @monsters; # blob kong mothera fingfangfoom say "{ @monsters }"; # blob kong mothera fingfangfoom What Raku does is a DWIM move: it joins the array on spaces when you use the array as a string. So these do the same things: my $s1 = @monsters.Str; my $s2 = @monsters.join(" "); dd( $s1 ); # Str $s1 = "blob kong mothera fingfangfoom" dd( $s2 ); # Str $s2 = "blob kong mothera fingfangfoom" You need to use .join explicitly if you want different behavior: my $s3 = @monsters.join(", "); dd( $s3 ); # Str $s3 = "blob, kong, mothera, fingfangfoom" All three of these do the same things: my @r1 = @monsters.split("a"); my @r2 = @monsters.Str.split("a"); my @r3 = @monsters.join(" ").split("a"); The each result in and array like: ["blob kong mother", " fingf", "ngfoom"] In this example of yours: my @a = "My Bloody Valentine", "Sonic Youth"; When you call split on @a, it joins on spaces first (and probably inadvertantly, throws away the division between 3 elements), then the actual split operation results in 5 elements: @a.split(" ").raku.say; # ("My", "Bloody", "Valentine", "Sonic", "Youth").Seq You might play with an explicit join to see what it does: my @r; @r = @a.join("|").split(" "); dd( @r ); # Array @r = ["My", "Bloody", "Valentine|Sonic", "Youth"] Myself, I think I'd be inclined to loop over the elements, e.g. with map: @r = @a.map({ [ .split(" ") ] }); dd(@r); # Array @r = [["My", "Bloody", "Valentine"], ["Sonic", "Youth"]] That's an array of arrays: two top-level elements, each split into 3 and 2 words respectively Note: split does stringification because it's intended to be run on strings, or things that can become strings-- map doesn't do this because it's intended to be run on things like Arrays. This probably is "specced" though not down on the level you're probably thinking of: it's not in the "split" documentation, for example, because it's not really specific to that method. You *could* argue that if you call a string method on an array, that's simply a mistake and it should error out. I think that's what "strong-typing" crowd would say-- they would point out you might have realized faster what was going on in that case. On 10/10/20, William Michels <w...@caa.columbia.edu> wrote: > So I guess the first question I have is whether the 'auto-joining' of array > elements is specc'ed or not. > > What you seem to be saying is that when calling a function on an array, the > first response is for Raku to call something similar to 'cat' on the array, > then proceed to process the function call. As it is my understanding that > Raku incorporates a lot of different programming paradigms (imperative, > object-oriented, functional, etc.), I'm not sure where this behavior falls > on the 'paradigm ladder'. > > I can point to the (functional) R-programming language to show what happens > there. When manipulating "array-like" (i.e. vector) objects in R, you can > do nested function calls, or sequential (piped) function calls, and still > get the same data structure out at the end. So a 10-element input gives a > 10-element output. In the R-GUI (i.e. REPL): > >> 0:9 > [1] 0 1 2 3 4 5 6 7 8 9 >> x <- 0:9 >> is.vector(x) > [1] TRUE >> length(x) > [1] 10 >> # using base-R: >> sqrt(tan(cos(sin(x)))) > [1] 1.2479614276 0.8867679488 0.8398446968 1.2344525173 0.9431819962 > 0.8044843661 1.1966884594 > [8] 1.0064589934 0.7823305851 1.1415611482 >> x ->.; sin(.) ->.; cos(.) ->.; tan(.) ->.; sqrt(.) > [1] 1.2479614276 0.8867679488 0.8398446968 1.2344525173 0.9431819962 > 0.8044843661 1.1966884594 > [8] 1.0064589934 0.7823305851 1.1415611482 >> library(magrittr) # add a "piping" library: >> x %>% sin %>% cos %>% tan %>% sqrt > [1] 1.2479614276 0.8867679488 0.8398446968 1.2344525173 0.9431819962 > 0.8044843661 1.1966884594 > [8] 1.0064589934 0.7823305851 1.1415611482 >> y <- x %>% sin %>% cos %>% tan %>% sqrt >> is.vector(y) > [1] TRUE >> length(y) > [1] 10 >> > > Now it's true that R has a greatly simplified memory/storage model compared > to Raku. But it's not hard to follow the R-code above, even if you don't > know the language. If at the end of all your function calls you want to > stringify and 'collapse' your 10 element vector into a single element > string, you call paste() on your object, which has a user-definable > 'collapse' argument that defaults to NULL. [For anyone worried about > formatting actual output, R has print() and sprintf() and cat() functions > as well]: > >> length(paste(0:9, y)) > [1] 10 >> paste(0:9, y) > [1] "0 1.24796142755091" "1 0.886767948777031" "2 0.839844696795443" "3 > 1.23445251727454" > [5] "4 0.943181996210625" "5 0.804484366108825" "6 1.19668845937773" "7 > 1.00645899343325" > [9] "8 0.782330585082487" "9 1.14156114815661" >> length(paste(0:9, "=", y, collapse= "; ")) > [1] 1 >> paste(0:9, "=", y, collapse= "; ") > [1] "0 = 1.24796142755091; 1 = 0.886767948777031; 2 = 0.839844696795443; > 3 = 1.23445251727454; 4 = 0.943181996210625; 5 = 0.804484366108825; 6 = > 1.19668845937773; 7 = 1.00645899343325; 8 = 0.782330585082487; 9 = > 1.14156114815661" >> > > When I started learning Perl6/Raku a few years ago I actually wondered > where the different programming paradigms would be delineated. Would > imperative/structural/procedural code be 'closer to the metal' while > functional code would be applied to higher-order data structures like > arrays, arrays-of-lists, arrays-of-hashes, and arrays-of-arrays? And those > higher-order data structures would then be utilized in object-oriented > code, i.e. the programmer would be manipulating classes and class-based > objects of varying complexity to produce a robust and secure program? Or > would Raku implement a different (i.e. better) paradigm hierarchy that I > hadn't anticipated? > > Best Regards, Bill. > > W. Michels, Ph.D. > > > > > > On Tue, Oct 6, 2020 at 1:59 PM Tobias Boege <t...@taboege.de> wrote: > >> On Tue, 06 Oct 2020, William Michels via perl6-users wrote: >> > [...] >> > >> > So my question regards "special-casing" of split/join in Raku. Is the >> first >> > result on comma-delimited data the default, i.e. joining disparate >> elements >> > of an array together head-to-tail? Or is the second result on >> > whitespace-delimited data the default (i.e. no joining of disparate >> > elements together head-to-tail)? Which one is special-cased? If the >> second >> > one is special-cased, is that why Raku returns 5 elements and not 4 >> > elements as in lines C/D (implied join)? >> > >> >> My answer is going to be that there is *no* special-casing. You have an >> array of strings @a and you call the `split` and `join` methods on it. >> These two methods are not alike. `join` is a proper method of List and >> it joins stringifications of the elements of that list. >> >> Crucially, the `split` method comes from somewhere else: Array inherits >> it from the Cool class. When you call Array.split, what happens is that >> your entire array gets stringified first (joining stringifications of >> its elements with spaces) and then Cool.split is called on that string >> representation of your array. This is even mentioned in the introductory >> paragraph about Cool [1]. >> >> This is the strangely consistent explanation of the effects you observed. >> You see, the only "special" thing is that Array.split being a Cool method >> causes the array to be joined with *spaces* before the splitting starts, >> but this always happens, independently of the join/split arguments. >> >> Array.split does in particular *not* "pass on" the split call to the >> elements of the array. For that you would use @a».split, although this >> would cause (itemized) Seqs for each element of @a to end up in the >> returned list, so what you actually thought you were doing may be >> written as >> >> @a».&{ .split(",").Slip } >> >> I am sure there are ways to write it more alphabetically. >> >> Best, >> Tobias >> >> [1] https://docs.raku.org/type/Cool >> >> -- >> "There's an old saying: Don't change anything... ever!" -- Mr. Monk >> >