Using a loop's positional parameters inside an inner loop in Raku - loops

Here is the code:
my #s=<a b c d>;
for #s.kv {
for ($^k ... #s.elems) {
printf("%s ", $^v);
}
printf("\n");
}
Expected output is:
# a b c d
# b c d
# c d
# d
But it gives this error (possibly among others)
key 0, val 1 Too few positionals passed; expected 2 arguments but got 1
It looks like the positional variables of the main loop $^k and $^v can't be used inside the inner loop. How to fix it? Thanks.
Update: Typo inside inner loop fixed

So for what you want to do I'd approach it like this :
my #s = <a b c d>;
for ^#s.elems -> $start-index {
for #s[$start-index..*] -> $value {
printf("%s ", $value );
}
print("\n");
}
Though really I'd do this.
my #s = <a b c d>;
(^#s.elems).map( { #s[$_..*].join(" ").say } )
Get the range from 0 to the number of elements in the array. Then the slice from there to the end for each, join on spaces and say.
A note on variables like $^k these are scoped to the current block only (hence why your above code is not working). Generally you only really want to use them in map, grep or other such things. Where possible I'd always advise naming your variables, this makes them scoped inside inner blocks as well.

Scimon Proctor's answer is essentially correct, but I'll try to explain why your example does not work. For starters, kv returns "an interleaved sequence of indexes and values", so this:
my #s=<a b c d>;
.say for #s.kv;
prints
0
a
1
b
2
c
3
d
Essentially, you're doing one turn of the loop for every key and value. Grouping them in pairs using rotor might be closer to what you're looking for:
.say for #s.kv.rotor(2)
which will return:
(0 a)
(1 b)
(2 c)
(3 d)
Since with this we got the value couple with the index, we can do...
my #s=<a b c d>;
for #s.kv.rotor(2) -> ($k, $) {
"{#s[$_]} ".print for ($k..^#s.elems);
printf("\n");
}
Please note that there was also an error in the inner loop, whose range went beyond the actual indices in #s. But, again, Scimon's answer that uses maps is much shorter, idiomatic and straightforward. This one is just kind of dwimming your original program. As a matter of fact, we are throwing away the values, so this would actually be:
my #s=<a b c d>;
for #s.keys -> $k {
"{#s[$_]} ".print for ($k..^#s.elems);
printf("\n");
}
No need to use kv at all, and just make do with the keys.

Related

Function Recursion within itself - haskell

I was trying to recursively pass a function to itself a given number of times. So given the input in form of Function | RepeatNumber(Count) | Argument. So as an example if given the input: f 3 2 it would return f(f(f 2) This should then also work if the Function value where "square" it would Square the argument.
In terms of the logic I approached it as follows:
def repeatnew func count arg
if count == 1 then (func arg)
else (func (repeatnew func (count -1) arg))
I've been trying to research a solution to this for a while and I came across using Iterate and some other functions. Finally I came across this: https://wiki.haskell.org/Higher_order_function However I was unable to implement a working solution.
Edit: The solutions I did try to implement I could get compiling correctly, I am still very inexperienced with haskell and would appreciate an explanation on how to create a higher order function using my parameters.
Spinning off from #Antisthenes' comment, One other way to do this is using the foldl1 with no base case.
pipeNTimes :: (a -> a) -> Int -> (a -> a)
pipeNTimes f n = foldl1 (.) $ replicate n f
pipeNTimes (*2) 3 2 -- returns 16
I am admittedly only a beginner at Haskell, so this may be a naive implementation, but I think this does what you are looking for:
applyRecursively f x y
| x == 1 = f y
| otherwise = f (applyRecursively f (x-1) y)
The applyRecursively function takes a function and two numbers as arguments.
If the middle argument (the count) is 1 then we apply the parameter function to the argument y. This is the edge case that stops the recursion.
The otherwise guard clause then calls recursively with the x parameter decremented, and applies function f to the result.
I have tested it using a lambda like this:
applyRecursively (\x -> x + 1) 3 3
It should add 1 to the values of 3 three times - it returns a value of 6 so it looks like it works.
As I say, I'm a beginner but I think this does what you're looking for.

Basic Python loop

How does Python know what "i" is when it is not defined, shouldn't there be an error? Probably a simple explanation, but I am new to learning Python.
def doubles (sum):
return sum * 2
myNum = 2
for i in range (0,3):
myNum = doubles(myNum)
print (myNum)
Haha :-) People are marking down your question, but I know that is one question must have came in every person's mind. Specially those who learned Python through Online courses and not through a teacher in person.
Well let me explain that in layman's term,
The method that you used is specially used for 1) lists and 2) lists within lists.
For eg,
example1= ['a','b','c'] # This is a simple list
example2 = [['a','b','c'],['a','b','c'],['a','b','c']] # This is list within lists.
Now, 'a','b' & 'c' are items in list.
So by saying,
for i in example1:
print i
we are actually saying,
for item in the list(example1):
print item
-------------------------
People use 'i', probably taken as abbreviation to item, or something else.
I don't know the history.
But, the fact is that, we can use anything instead or 'i' and Python will still consider it as an item in list.
Let me give you examples again.
example1= ['a','b','c'] # This is a simple list
example2 = [['a','b','c'],['a','b','c'],['a','b','c']] # This is list within lists.
for i in example1:
print i
[out]: a
b
c
now in example2, items are lists within lists. --- also, now i will use the word 'item' instead of 'i' --- the results regardless would be the same for both.
for item in example2:
print item
[out]: ['a','b','c']
['a','b','c']
['a','b','c']
people also use singulars and plurals to remember things,
so lets we have a list of alphabet.
letters=['a','b','c','d']
for letter in letters:
print letter
[out]: a
b
c
d
Hope that helps. There is much more to explain.
Keep researching and keep learning.
Regards,
Md. Mohsin
Using a variable as a loop control variable does assign to it each time through the loop.
As to "what it is"... Python is dynamically typed. The only thing it "is" is a name, just like any other variable.
i is assigned the value in the loop itself, it has no value (it is not defined) before the Python interpreter reaches the for line.
Its similar to how other for loops define variables. In C++ for example:
for(int i=0; i<5; i++){
cout << i << endl;
}
Here the variable i is only exists once the for loop is called.
i is assigned a value when the for loop runs, so the Python interpreter will not raise an error when the loop is run
long story short it creates a new variable without having to be defined and its value is whatever number your loop is on, for example if you had written:
num = 0
for i in range(3):
print(num)
num = num + 1
so for the first time this loop ran 'i' would equal 0 (because python lists/loops etc always start on 0 not 1), the second time it would equal 1, etc. and the 'num' you can ignore it's just an example of code you could have in a loop which would print out numbers in ascending order.
Levin

awk, custom delarray function

Can someone explain, why I am not getting expected results?
awk '
# I know there is delete array, but this is more portable
# that is what docs are saying, anyway wanted to test it out.
function delarray(a, i)
{
for (i in a)
delete a[i]
}
BEGIN {
a[3]=""
a[4]=""
for (e in a)
print e
delarray(a)
for (e in a)
print ".."
print e
}
'
Executing the above script, I expected to see:
3
4
..(nothing here)
I used .. thinking I won't see anything else because of
deleted array values so just to see .. as placeholder)
,but the actual output I see is:
3
4
4 #(why this?, and where are two dots?)
,also exit code was 1, why is that?
Your delete function worked.
Since you're missing the braces around your for (e in a) loop, it only contains the print ".." statement, which is why you don't see any dots.
The print e command simply prints the last value that was assigned to e (from the previous for (e in a) loop), which is 4.
But your function is not very useful since virtually all versions of awk allow the delete a command without an index. It's in the POSIX standard.
You are missing curly braces around your second loop.
for (e in a) {
print ".."
print e
}
Output:
3
4

haskell repeat all chars in a string

i just started with Haskell and wanted to do a little function that takes an integer and a String to repeat each char in the String as often as the integer implies.
e.g.: multiply 3 "hello" would output "hhheeelllooo"
My problem now is that i am not sure how to iterate over all the chars.
multiply::Int->String->String
multiply 1 s = s
multiply i s = multiply (i-1) (take 1 s ++ s)
so what i would get is "hhhello". so basically i need to do something like:
mult::Int->String->String
mult 0 s = []
mult 1 s = s
mult i s = "iterate over s, take each char and call a modified version of the multiply method that only takes chars above"
Thank you for helping me out
This gets easier when you use the standard library. First off, repeating an item is done with replicate:
Prelude> replicate 3 'h'
"hhh"
You can then partially apply this function and map it over the string:
Prelude> map (replicate 3) "hello"
["hhh", "eee", "lll", "lll", "ooo"]
And finally concat that list of strings into one string:
Prelude> concat (map (replicate 3) "hello")
"hhheeellllllooo"
The composition of concat and map can be abbreviated as concatMap (this is a library function, not a language feature).
Prelude> concatMap (replicate 3) "hello"
"hhheeellllllooo"
So your function becomes
mult n s = concatMap (replicate n) s
For extra brevity, write this in point-free style as
mult = concatMap . replicate
There are many ways to achieve the same effect as you would with a loop in other languages, and larsmans has shown you one way, using map. Another common way is with recursion. You already know what to do with the first character, so you can recurse through the list like so:
multiply n [] = []
multiply n (x:xs) = replicate n x ++ multiply n xs
larsmans has explained how replicate works. For your homework, maybe you're not supposed to use library functions like replicate, so you can replace the call to replicate with your own version.
Another way based on monadic's nature of list.
You'd like to apply a function to each element of a list.
To do this just bind the list to the function, like this
# "hello" >>= replicate 3
Or,
# let f = flip (>>=) . replicate
To remove flip,
# let g = (=<<) . replicate
You can use applicative functors for this:
import Control.Applicative
multiply n = (<* [1..n])
--- multiply 3 "hello" --> "hhheeellllllooo"

Array Operations in perl

Why does the code below return 11 with this :- #myarray = ("Rohan");
Explaination i got was :- The expression $scalar x $num_times, on the other hand, returns a string containing $num_times copies of $scalar concatenated together string-wise.
So it should give 10 not 11 ...
code is as below :-
print "test:\n";
#myarray = ("Rohan"); # this returns 11
###myarray = ("Rohan","G"); this returns 22
#myarray2 = (#myarray x 2);
#myarray3 = ((#myarray) x 2); #returns Rohan,Rohan and is correct
print join(",",#myarray2,"\n\n");
print join(",",#myarray3,"\n\n");
What’s happening is that the x operator supplies scalar context not just to its right‐hand operand, but also to its left‐and operand as well — unless the LHO is surrounded by literal parens.
This rule is due to backwards compatibility with super‐ancient Perl code from back when Perl didn’t understand having a list as the LHO at all. This might be a v1 vs v2 thing, a v2 vs v3 thing, or maybe v3 vs v4. Can’t quite remember; it was a very long time ago, though. Ancient legacy.
Since an array of N elements in scalar context in N, so in your scenario that makes N == 1 and "1" x 2 eq "11".
Perl is doing exactly what you asked. In the first example, the array is in scalar context and returns its length. this is then concatenated with itself twice. In the second example, you have the array in list context and the x operator repeats the list.

Resources