Raku vs. Perl5, an unexpected result - raku

When I run this script in Raku I get the letter A with several newlines.
Why do I not get the concatenated strings as expected (and as Perl5 does) ?
EDIT BTW can I compile in commaIDE the file with the Perl5 compiler, where can I change this compiler to be that of Perl5 ?
say "A";
my $string1 = "00aabb";
my $string2 = "02babe";
say join ("A", $string1, $string2);
print "\n";
my #strings = ($string1, $string2);
say join ("A", #strings);
print "\n";

The solution I suggest is to drop the parens:
say "A";
my $string1 = "00aabb";
my $string2 = "02babe";
say join "A", $string1, $string2; # Pass THREE arguments to `join`, not ONE
print "\n";
my #strings = $string1, $string2;
say join "A", #strings;
print "\n";
(The elements in #strings in the second call to join are flattened, thus acting the same way as the first call to join.)
The above code displays:
A
00aabbA02babe
00aabbA02babe
When I run this script in Raku I get the letter A with several newlines.
Your code calls join with ONE argument, which is the joiner, and ZERO strings to concatenate. So the join call generates null strings. Hence you get blank lines.
Why do I not get the concatenated strings
The two say join... statements in your code print nothing but a newline because they're like the third and fourth say lines below:
say join( " \o/ ", "one?", "two?" ); # one? \o/ two?␤
say join " \o/ ", "one?", "two?" ; # one? \o/ two?␤
say join ( " \o/ ", "one?", "two?" ); # ␤
say join( " \o/ one? two?" ); # ␤
The first and second lines above pass three strings to join. The third passes a single List which then gets coerced to become a single string (a concatenation of the elements of the List joined using a single space character), i.e. the same result as the fourth line.
The my #strings = ($string1, $string2); incantation happens to work as you intended, because an assignment to a "plural" variable on the left hand side of the = will iterate the value, or list of values, on the right hand side.
But it's a good habit in Raku to err on the side of avoiding redundant code, in this instance only using parens if you really have to use them to express something different from code without them. This is a general principle in Raku that makes code high signal, low noise. For your code, all the parens are redundant.

The problem is the whitespace after the function name. If you leave a space there, raku will treat the expression in paranthesis as a List which is single thing. Here join will think you want to use the list as a joiner.
Observe:
>raku -e "sub foo( $arg ) { say $arg.WHAT }; foo( 'abc', )"
(Str)
>raku -e "sub foo( $arg ) { say $arg.WHAT }; foo ( 'abc', )"
(List)
So in short, if you want to use paranthesis to call a sub, don't put a whitespace between the sub name and the opening paren.

see Traps to avoid,
try:
my #s=("00aabb", "02babe");
say join "A", #s;
say join |("A",#s);
say join("A",#s);
say #s.join: "A";
#or some crazy
say join\ ("A",#s);
say "A".&join: #s;
say join #s: "A";
say "A" [&join] #s;
say #s R[&join] "A";
#…

A: "do not put whitespace between a function name and the opening paren '('" ♎️KISS

Related

Using WHERE with multiple columns with different data types to satisfy a single input in bash and postgressql

please assist with the following. i m trying to run a script that accepts one argument $1. The argument can either be a string or character or an integer. I want to use the argument in there where clause to search for the element in the database.
This is the table i want to search from:enter image description here
When i use the multiple conditions with OR , it works only when either the argument is a number or text.
This what my code looks like enter image description here
`
ELEMENT=$($PSQL "SELECT * FROM elements e FULL JOIN properties p USING(atomic_number) WHERE symbol = '$1' OR name = '$1' OR atomic_number = $1;")
`
and this is the results i get when i run with different aurgumentsenter image description here
Please help.
Thank you in advance
This will always fail on any non-numeric argument.
You are passing in H for hydrogen, but taking whatever was passed in and using it in the atomic_number comparison as an unquoted number, which the DB engine is trying to figure out what to do with. H isn't a number, and isn't a quoted string, so it must be the name of a column...but it isn't, so you are using invalid syntax.
I don't have a postgres available right now, but try something like this -
ELEMENT=$( $PSQL "
SELECT *
FROM elements e
FULL JOIN properties p USING(atomic_number)
WHERE symbol = '$1'
OR name = '$1'
OR atomic_number = CAST(`$1` as INTEGER); " )
Also, as an aside... avoid all-capital variable names.
As a convention, those are supposed to be system vars.
And please - please don't embed images except as helpful clarification.
Never rely on them to provide info if it can be avoided. Copy/paste actual formatted text people can copy/paste in their own testing.
An alternate way to construct the query: requires bash
looks_like_a_number() {
# only contains digits
[[ "$1" == +([[:digit:]]) ]]
}
sanitize() {
# at a minimum, handle embedded single quotes
printf '%s' "${1//\'/\'\'}"
}
if looks_like_a_number "$1"; then
field="atomic_number"
value=$1
elif [[ ${#1} -eq 1 ]]; then
field="symbol"
printf -v value "'%s'" "$(sanitize "$1")"
else
field="name"
printf -v value "'%s'" "$(sanitize "$1")"
fi
q="SELECT *
FROM elements e
FULL JOIN properties p USING(atomic_number)
WHERE $field = $value;"
printf '%s\n' "$q"
result=$("$PSQL" "$q")

Kotlin: 'if' must have both main and 'else' branches if used as an expression

I am trying to run this code:
fun main() {
print("This is a calculator")
print("enter your first number")
val no1 = readLine()!!
print("enter your operation")
val operation1 = readLine()!!
print("enter your second number")
val no2 = readLine()!!
val result = if(operation1 == '*')
print("$val no1 * $val no2")
}
But I get the following error:
'if' must have both main and 'else' branches if used as an expression
Operator '==' cannot be applied to 'String' and 'Char' Keyword cannot
be used as a reference Keyword cannot be used as a reference
It also keeps coming up with Kotlin: Keyword cannot be used as a reference within my IDE.
I am very new to Kotlin and I am just trying to create a basic calculator, can you please help?
That code has three different compilation errors, and many other things to fix:
In the line:
print("$val no1 * $val no2")
the $val is a string template which would fill in the value of the variable val — but val isn't a variable; it's a keyword. (That's what's causing the ‘Keyword cannot be used as a reference’ error.) I think you want $no1 and $no2.
The test if(operation1 == '*') is comparing a string with a character. (Single-quotes give a character constant. A string contains characters, but it is not a character, so it can never be equal to a character.) The compiler tells you this with the error ‘Operator '==' cannot be applied to 'String' and 'Char'’. The simplest way to fix it is to provide a string by using double-quotes instead: "*".
The pair of lines:
val result = if(operation1 == '*')
print("$val no1 * $val no2")
is incomplete and doesn't make sense as it is. What do you want to do if operation1 isn't "*"? And what do you want to set result to in each case?
(It looks like you're trying to use if as an expression, and assign its result to result — but to use if as an expression you need to add an else branch too, so it knows what value to use in all cases. That's causing the compilation error ‘'if' must have both main and 'else' branches if used as an expression’.)
If this is the start of some code which will check for *, +, and other operators, then maybe you want to set the result and then print it, e.g.:
val result = if (operation1 == "*") /* … */
else if (operation2 == "+") /* … */
else /* … */
print(result)
(Though that would be simpler with when instead of if.)
If you fix the first issue by changing it to "$no1 * $no2", that will print e.g. 1 * 2. I'm guessing you want instead to calculate the product of two numbers. But no1 and no2 aren't numbers; they're strings. So you first have to convert them into numbers, e.g. with no1.toInt(). You also have to tell the compiler that you want to evaluate the * rather than just printing it. If you just want to print out the number, you could skip the string template entirely:
print(no1.toInt() * no2.toInt())
However, if you want to use a string template (e.g. if you want to add some text), you'd have to use the ${…} format to mark out the bit you want to evaluate:
print("${no1.toInt() * no2.toInt()}")
Some or all of the print(…) calls should probably be println(…). (println() adds a line-break after the string, while print() doesn't, leaving the next input or output to follow immediately on the same line.)
Even if all that's fixed, the code could fail in several ways if the user doesn't enter the expected input. (Both !! and toInt() can throw exceptions, e.g. if you press Enter without typing a number.) That's fine for an exercise, of course; but if this code ever got to production, you'd want to handle those possibilities better.
When you use $val, it is trying to access the val variable, but as $val is undefined, it can't, and freaks out because it doesn't know what to do.
Instead of print("$val no1 * $val no2"), you can use:
print("$no1 * $no2")
The code above will use the $no1 and $no2 variables that you want it to use.
In line 4 and 8, the input should be converted to Int, like this:
val no1 = readLine()!!.toInt()
val no2 = readLine()!!.toInt()
In the last line, val should not be written and should be as follows:
print("$no1 * $no2")
You can also add other operators using else if in the continuation of the if command

How to choose all or a subset of a vector in SQL query when linking R to HANA

I am using R to link HANA, so that I can use SQL query in R for data retrieve. My data includes a lot of store names. sometimes, my query is based on all the stores, which can be done easily without setting up any limits in WHERE. Sometimes, I just focus on a couple of stores, like store 1,2,3. I can use the answer from Providing lookup list from R vector as SQL table for RODBC lookup to do this.
For example:
IDlist <- c(23, 232, 434, 35445)
paste("WHERE idname IN (", paste(IDlist, collapse = ", "), ")")
But how can I combine these two situations, i.e., all names or name subset, together in a WHERE? I am looking forward for something like:
IDlist <- all
IDlist <- c(23, 232, 434, 35445)
paste("WHERE idname IN (", paste(IDlist, collapse = ", "), ")")
So, when IDlist is all, then the query will be for all the store names. When IDlist have some specific numbers, then the query will just focus on those stores.
This is just my idea. I am not sure if there is a better way to do it. Anyway, combining all names and some names together so that I can use them in one WHERE, therefore, I do not need to change my code.
Here, my WHERE is :
myOffice <- c(416,247,602,428)
WHERE "a"."/BIC/ZARTICLE"<>\'GIFTCARDPU\' AND "a"."/BIC/ZRETURN"=\'X\'
AND "a"."CALDAY" BETWEEN',StartDate,'AND',EndDate,'
AND "a"."/BIC/ZSALE_OFF" IN (',paste(myOffice, collapse = ", "),')
Maybe something like this:
office_clause = ""
if (IDlist != all) {
office_clause = paste(
'AND "a"."/BIC/ZSALE_OFF" IN (',
paste(IDlist, collapse = ', '),
')'
)
}
Then you can construct your query, just pasting office_clause at the end of the where. If it IDlist is all, then you will paste on a blank string, otherwise you will paste on the ID clause. (Note that I assume all is a variable because that's how you used it in the question.)

Regex capturing inside a group

I working on a method to get all values based on a SQL query and then scape them in php.
The idea is to get the programmer who is careless about security when is doing a SQL query.
So when I try to execute this:
INSERT INTO tabla (a, b,c,d) VALUES ('a','b','c',a,b)
The regex needs to capture 'a' 'b' 'c' a and b
I was working on this a couple of days.
This was as far I can get with 2 regex querys, but I want to know if there is a better way to do:
VALUES ?\((([\w'"]+).+?)\)
Based on the previous SQL this will match:
VALUES ('a','b','c',a,b)
The second regex
['"]?(\w)['"]?
Will match
a b c a b
Previously removing VALUES, of course.
This way will match a lot of the values I gonna insert.
But doesn't work with JSON for example.
{a:b, "asd":"ads" ....}
Any help with this?
First, I think you should know that SQL support many types of single/double quoted string:
'Northwind\'s category name'
'Northwind''s category name'
"Northwind \"category\" name"
"Northwind ""category"" name"
"Northwind category's name"
'Northwind "category" name'
'Northwind \\ category name'
'Northwind \ncategory \nname'
to match them, try with these patterns:
"[^\\"]*(?:(?:\\.|"")[^\\"]*)*"
'[^\\']*(?:(?:\\.|'')[^\\']*)*'
combine patterns together:
VALUES\s*\(\s*(?:"[^\\"]*(?:(?:\\.|"")[^\\"]*)*"|'[^\\']*(?:(?:\\.|'')[^\\']*)*'|\w+)(?:\s*,\s*(?:"[^\\"]*(?:(?:\\.|"")[^\\"]*)*"|'[^\\']*(?:(?:\\.|'')[^\\']*)*'|\w+))*\)
PHP5.4.5 sample code:
<?php
$pat = '/\bVALUES\s*\((\s*(?:"[^\\"]*(?:(?:\\.|"")[^\\"]*)*"|\'[^\\\']*(?:(?:\\.|\'\')[^\\\']*)*\'|\w+)(?:\s*,\s*(?:"[^\\"]*(?:(?:\\.|"")[^\\"]*)*"|\'[^\\\']*(?:(?:\\.|\'\')[^\\\']*)*\'|\w+))*)\)/';
$sql_sample1 = "INSERT INTO tabla (a, b,c,d) VALUES ('a','b','c',a,b)";
if( preg_match($pat, $sql_sample1, $matches) > 0){
printf("%s\n", $matches[0]);
printf("%s\n\n", $matches[1]);
}
$sql_sample2 = 'INSERT INTO tabla (a, b,c,d) VALUES (\'a\',\'{a:b, "asd":"ads"}\',\'c\',a,b)';
if( preg_match($pat, $sql_sample2, $matches) > 0){
printf("%s\n", $matches[0]);
printf("%s\n", $matches[1]);
}
?>
output:
VALUES ('a','b','c',a,b)
'a','b','c',a,b
VALUES ('a','{a:b, "asd":"ads"}','c',a,b)
'a','{a:b, "asd":"ads"}','c',a,b
If you need to get each value from result, split by , (like parsing CSV)
I hope this will help you :)

How to pass a hash to a sub?

In my perl "script" I'm collecting data and building a hashmap. The hashmap keys represent field names, and the values represent the value I want to insert into the corresponding field.
The hashmap is built, and then passed to the saveRecord() method which is supposed to build a SQL query and eventually it will execute it.
The idea here is to update the database once, rather than once per field (there are a lot of fields).
The problem: I'm having trouble passing the hashmap over to the sub and then pulling the fields and values out of the hashmap. At this point my keys and values are blank. I suspect the data is getting lost during the passing to a sub.
The output of the script indicates no keys and no values.
Need help passing the data to the sub in a way that lets me pull it back apart as shown - with join().
Thanks!
Code snippet:
for my $key (keys %oids) {
$thisField = $key;
$thisOID = $oids{$thisField};
# print "loop: thisoid=$thisOID field=$thisField\n";
# perform the SNMP query.
$result = getOID ($thisOID);
# extract the information from the result.
$thisResult = $result->{$thisOID};
# remove quotation marks from the data value, replace them with question marks.
$thisResult =~ s/\"|\'|/\?/g;
# TODO: instead of printing this information, pass it to a subroutine which writes it to the database (use an update statement).
# printf "The $thisField for host '%s' is '%s'.\n", $session->hostname(), $result->{$thisOID};
# add this key/value pair to the mydata hashmap.
$mydata{$thisField} = $thisResult;
# print "$thisField=$thisResult\n";
}
# write one record update for hashmap %mydata.
saveRecord (%mydata);
# write all fields to database at once...
sub saveRecord ($) {
my $refToFields=shift;
my #fieldlist = keys %$refToFields;
my #valuelist = values %$refToFields;
my $sql = sprintf ("INSERT INTO mytable (%s) VALUES (%s)",join(",",#fieldlist), join(",",#valuelist) );
# Get ID of record with this MAC, if available, so we can perform SQL update
my $recid = getidbymac ($MAC);
print "sql=$sql\n";
# TODO: use an insert or an update based on whether recid was available...
# TODO: ID available, update the record
# TODO: ID not available, insert record let ID be auto assigned.
}
I cleaned up your code a little. Your main problem was not using a reference when calling your sub. Also note the commented regex which is cleaned up:
Code:
use strict;
use warnings;
# $thisResult =~ s/["']+/?/g;
my %mydata = ( 'field1' => 12, 'field2' => 34, );
saveRecord (\%mydata); # <-- Note the added backslash
sub saveRecord {
my $ref = shift;
my $sql = sprintf "INSERT INTO mytable (%s) VALUES (%s)",
join(',', keys %$ref),
join(',', values %$ref);
print "sql=$sql\n";
}
Output:
sql=INSERT INTO mytable (field1,field2) VALUES (12,34)