Why does Perl 6's string concatenation not like .WHAT? - raku

I'm puzzled about this bit of code where I apparently can't call the WHAT method in a string concatenation?
my $object = 'Camelia';
say $object;
say $object.WHAT;
say "^name: The object is a " ~ $object.^name;
say "WHAT: The object is a " ~ $object.WHAT;
The output shows that calling ^name works (a metamethod from Metamodel::ClassHOW), but Perl 6 is confused by .WHAT as if there's a precedence issue.
Camelia
(Str)
^name: The object is a Str
Use of uninitialized value of type Str in string context
Any of .^name, .perl, .gist, or .say can stringify undefined things, if needed. in block <unit> at meta_methods.p6 line 7
WHAT: The object is a
My Perl 6:
This is Rakudo version 2015.12-219-gd67cb03 built on MoarVM version 2015.12-29-g8079ca5
implementing Perl 6.c.

.WHAT returns a type object, an undefined object
Like most routines/operators, concatenation assumes its arguments are defined. But the .WHAT in your last line returns a type object and a type object is not defined. So the result is a warning and stringification to the empty string.
If you want to concatenate an undefined object without generating a warning and instead stringify it into the object's type name you must explicitly .^name, .gist or .perl it eg:
say "The object is a " ~ $object.^name
say "The object is a " ~ $object.WHAT.gist
displays:
The object is a Str
The object is a (Str)

A quote from Perl 6's IRC channel, user FROGGS:
.WHAT gives you back a type, which is meant to warn if you interpolate or concat it or do math with it
In your example, $object is a Str, so $object.WHAT gives you the Str type.
In other words it's like writing:
say "WHAT: The object is a " ~ Str;
Edit: It seems your real question is "Why does Perl 6's string concatenation not like types?"
As others have mentioned, types are undefined and concatenation works on defined values. As Perl 6's warning message says, you need to use any of .^name, .perl, .gist to stringify undefined things.
These two will work because say uses .gist to stringify:
say Str;
say "The object is ", Str;

Related

String interpolation in Perl6

I have difficulty figuring out why the statement
say "\c500";
produces the character 'Ǵ' on my screen as expected, while the following statements give me an error message at compile time ("Unrecognized \c character"):
my $i = 500;
say "\c$i";
even though
say "$i"; # or 'say $i.Str;' for that matter
produces "500" (with "$i".WHAT indicating type Str).
You'll have to use $i.chr, which is documented here. \c is handled specially within strings, and does not seem to admit anything that is not a literal.
The string literal parser in Perl 6 is a type of domain specific language.
Basically what you write gets compiled similarly to the rest of the language.
"abc$_"
&infix:«~»('abc',$_.Str)
In the case of \c500, you could view it as a compile-time constant.
"\c500"
(BEGIN 500.chr)
Actually it is more like:
(BEGIN 500.HOW.find_method_qualified(Int,500,'chr').(500))
Except that the compiler for string literals actually tries to compile it to an abstract syntax tree, but is unable to because there hasn't been code added to handle this case of \c.
Even if there was, \c is effectively compiled to run at BEGIN time, which is before $_ has a value.
Also \c is used for more than .chr
"\c9" eq "\c[TAB]" eq "\cI" eq "\t"
(Note that \cI represents the character you would get by typing Cntrl+Alt+i on a posix platform)
So which of these should \c$_ compile to?
$_.chr
$_.parse-names
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.index($_).succ.chr
If you want .chr you can write it as one of the following. (spaces added where they are allowed)
"abc$_.chr( )def"
"abc{ $_.chr }def"
"abc{ .chr }def"
'abc' ~ $_.chr ~ 'def'

What does this %1$#%2$d format specifier means in objective c

I've been working with format specifiers but they were generic like %d or %# but today in a tutorial I saw these %1$#%2$d and didn't understand what they represent.It was a calculator example so they are using them in this statement: stack = [NSString stringWithFormat:#"%1$#%2$d",stack,number];
The numbers represent positional parameters. The parameters which follow the format string are slotted into the string based on their position in the parameters list. The first parameter goes into the %1 slot, the second into the %2 slot, and so on. The purpose is to deal with languages where the order of terms/words/etc might change from your default. You can't change the parameter order at runtime, but you can make sure the parameters end up in the correct place in the string.
Example
NSLog(#"%1$#, %2$#", #"Red", #"Blue");
NSLog(#"%2$#, %1$#", #"Red", #"Blue");
Output
Red, Blue
Blue, Red
Note that the format string changed, but the parameters are in the same order.
So your format specifier %1$# %2$d means:
%1$# for %#(Objective-C object) with first parameter and
%2$d for %d*(Signed 32-bit integer (int))* with second parameter.
This $0, $1, $2 are shorthand parameter names like in Closures
“Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0, $1, $2, and so on.”

How to pass functions as parameters in REBOL

I have attempted to pass a function as a parameter in the REBOL programming language, but I haven't figured out the correct syntax yet:
doSomething: func [a b] [
a b
a b
]
doSomething print "hello" {This should pass print as the first argument and "hello" as the second argument.}
This produces an error, since the print function is being called instead of being passed:
hello
*** ERROR
** Script error: doSomething does not allow unset! for its a argument
** Where: try do either either either -apply-
** Near: try load/all join %/users/try-REBOL/data/ system/script/args...
Is it possible to pass the print function as a parameter instead of calling the print function?
I've found the solution: I only need to add : before the name of the function that is being passed as a parameter.
Here, the :print function is being passed as a parameter instead of being invoked with "hello" as its argument:
doSomething: func [a b] [
a b
a b
]
doSomething :print "hello" {This should pass print as the first argument and "hello" as the second argument.}
You have discovered that by the nature of the system, when the interpreter comes across a WORD! symbol type which has been bound to a function, it will invoke the function by default. The default interpreter seeing a GET-WORD! symbol type, on the other hand, suppresses invocation and just returns the value the word is bound to.
The evaluator logic is actually rather straightforward for how it reacts when it sees a certain symbol type. Another way of suppressing invocation is the single quote, which will give you a LIT-WORD! symbol... but these become evaluated as the corresponding WORD! when it sees them:
>> some-word: 'print
>> type? some-word
== word!
In fact, the behavior of a GET-WORD! when the evaluator sees it is equivalent to using the GET function with a WORD!
doSomething: func [a b] [
a b
a b
]
doSomething get 'print "hello" {Message}
The interpreter sees the LIT-WORD! 'print and evaluates that into the WORD! for print, which is then passed to GET, which gives you a FUNCTION! back.
Simplicity of the interpreter logic is why you get things like:
>> a: b: c: 10 print [a b c]
10 10 10
Due to the nature of how it handles a SET-WORD! symbol followed by complete expressions. That yields also the following code printing out 20:
if 10 < a: 20 [
print a
]
Other languages achieve such features with specialized constructs (like multiple initialization, etc.) But Rebol's logic is simpler.
Just wanted to elaborate a bit to help explain what you were looking at. My answer to this other question might provide some more insight into the edge cases, historical and future: "When I use error? and try, err need a value"

Objective-C: What is the significance of the "#" (at) symbol for NSLog (#"abc");?

And also, why is it not necessary for, eg:
printf ("abc")
NSLog takes an NSString as argument. #"abc" denotes an NSString because of the # sign, so that is a valid argument for NSLog. printf is a normal C function that takes a C string, which is simply created using "".
UPDATE:
NSLog(#"%#",dictionary)
Tells the compiler that i got string to fulfill the requirement of string argument.
Update: Sorry I was supposed to write the "NSLog" instead of printf. my mistake!
Because it requires NSString. Adding #declares value as type of NSObject (simplification).

get in Object 'Func with Refinement in Rebol

Let's say I have
o: context [
f: func[message /refine message2][
print [message]
if refine [print message 2]
]
]
I can call it like this
do get in o 'f "hello"
But how can I do for the refinement ? something like this that would work
>> do get in o 'f/refine "hello" "world"
** Script Error: in expected word argument of type: any-word
** Near: do get in o 'f/refine
>>
I don't know if there's a way to directly tell the interpreter to use a refinement in invoking a function value. That would require some parameterization of do when its argument is a function! Nothing like that seems to exist...but maybe it's hidden somewhere else.
The only way I know to use a refinement is with a path. To make it clear, I'll first use a temporary word:
>> fword: get in o 'f
>> do compose [(to-path [fword refine]) "hello" "world"]
hello
world
What that second statement evaluates to after the compose is:
do [fword/refine "hello" "world"]
You can actually put function values into paths too. It gets rid of the need for the intermediary:
>> do compose [(to-path compose [(get in o 'f) refine]) "hello" "world"]
hello
world
P.S. you have an extra space between message and 2 above, where it should just be message2
Do this:
o/('f)/refine "hello" "world"
Parens in a path expression are evaluated if they correspond to object field or series pick/poke index references. That makes the above code equivalent to this:
apply get in o 'f ["hello" true "world"]
Note that apply arguments are positional, so you need to know the order the arguments were declared in. You can't do that trick with the function refinements themselves, so you have to use apply or create path expressions to evaluate if you want to parameterize the refinements of the function call.
Use the simple path o/f/refine